Language guide

This is a tour of the whole WCHNT language, from the file format down to the Target layer. The Tutorial shows these pieces working together; this page is the reference. This first draft is written by AI. But will shortly be rewritten by a human

The file format

A WCHNT program is markdown. Code lives in fenced blocks under reserved ## headings, in this order:

Section Purpose
## Schema declare classes, types, and relationships
## Construction build the initial object graph
## Methods pure-ish behaviour as expressions
## Target Methods methods that take platform types (@Type/name)
## Target name the host and its entry points

## Import may appear first to merge sibling pages. Prose and unrelated fences are ignored.


Schema

The schema is a list of lines of the form ClassName = components. It's the single place where the shape of the whole assemblage is declared.

Composition


Game = PlayArea Ball Paddle/paddle1 Paddle/paddle2
Rect = Int/x Int/y Int/width Int/height

Relationship sigils

A sigil on a component changes the kind of relationship, not the field's type.

Sigil Name Meaning
(none) ordinary owned by the parent; built alongside it
: context-specific child belongs to this parent; it gets a back-reference
@ external borrowed from outside the assemblage
$ reactive an observable/subscriber relationship (see update)

Car = :Engine String/model
Engine = Int/cylinders
Game = PlayArea Ball $Time

Car = :Engine gives the Engine a field pointing back to its Car (called theCar), so engine methods can read sibling data. Game = … $Time means Time is observable and Game subscribes to it.

Collections


Team = String/name [Player]/players
School = {String:Discipline}/disciplines

[Player] is an array of players; {String:Discipline} is a map keyed by string.

Sum types and enums


Shape = Circle | Triangle
Circle = Int/radius
Triangle = Int/base Int/height

A line that is all | defines an interface (Shape) implemented by the classes on the right.


BuildType = "Dev" | "Local" | "Deploy"

A line of string literals defines a Haxe-style enum.


Construction

Construction is the initial data, written as a nested literal:


[:Game
  [:PlayArea [0 0 800 600]]
  [:Ball 200 150 6 5 16]]

A construction block may bind intermediate values with = before a final expression:


players = [:Array/Player [:Player "Ada"] [:Player "Bob"]].
[:Team "Aces" players]

Methods

A method is ClassName::methodName = { body }. The body is an expression; its value is the return value.


Rect::area = { width * height }

Ball::move = { Rect/bounds |
  [:Ball (x + dx) (y + dy) dx dy rad]
}

Statements and lets

A block is a sequence of statements separated by . (a full stop). Only the last statement is the result; earlier ones are let-style bindings and may not be reassigned.


Rect::doubleWidth = {
  w = width * 2.
  [:Rect x y w height]
}

Expressions

Collections in methods

Arrays have length(), cons, head, tail, plus the combinators map, filter, fold:


players.map({ p | p.name })
players.filter({ p | p.score > 0 })
players.fold(0, { acc, p | acc + p.score })

Maps have put, get, remove (writes copy the map). Strings have length(), concat, and substring(start, end). Ints have times: 3.times({ i | i * 2 }).

update and reactive dependencies

Ordinary methods are pure and return new objects. update is the one piece of mutation: it rewrites this in place and — if the object is observable — notifies its subscribers.


Time::update = { [:Time (t + 1)] }

Game::update = {
  [:Game playArea [:Ball (ball.x + ball.dx) (ball.y + ball.dy) ball.dx ball.dy ball.rad] time]
}

$Time on Game means: when Time.update() finishes, Game.update() runs automatically. Identity objects ($ observables and > mailboxes) are mutated in place, never replaced.


Target

Target names the outer environment — the layer that changes when you move platform.

Host Entry points Notes
%terminal %main Haxe, compiled and run by go.sh
%openfl %init + %step Haxe, windowed (Lime/OpenFL)
%canvas %init + %step JavaScript, runs in the browser (Play)

%name(...) helpers bind a Haxe function callable from Methods; %main (terminal) or %init/%step (openfl/canvas) are the program entry. The browser harness exposes gameFactory(), wchntGraphics, and input — see the Play page. Drawing is done through the portable wchntGraphics object.


Further reading