Appendix A · Programming in a Glass House

Appendix A: The Chalk Language

A technical reference for Chalk v1.1, supplementing Programming in a Glass House.

Contents

This appendix states the language precisely: its lexical structure, grammar, static rules, dynamic semantics, and canonical output, followed by the standard vocabulary and the properties the implementation verifies. The normative definition of Chalk is the reference implementation and its test suite (274 tests, including byte-exact golden outputs); this document is descriptive, written for readers who want the language in formal terms rather than by example.

A.1  Overview #

Chalk is a small, deterministic, statement-oriented language for constructing pictures and frame-based animations. Its design inverts the usual priorities: it is optimized to be observed and inverted rather than written and composed. Three commitments shape everything below: every call argument is labeled; all mutable state is declared and enumerable; and a program’s output is a serializable display list, not pixels. The grammar comprises roughly twenty-five productions.

Back to contents

A.2  Lexical structure #

Layout. Statements end at newlines. Blocks are introduced by a trailing : and delimited by indentation, which must be spaces in multiples of two; a tab character is a lexical error with a plain-language diagnostic. Comments run from // to end of line.

Keywords. state to end every frame when pointer key pressed released moved repeat as for from to step if else return and or not true false group (the last added in v1.1). Keywords are reserved and may not be bound.

Identifiers. Letters then letters/digits; case-sensitive. Argument labels are identifiers in label position (before : in an argument or parameter list) and occupy a separate syntactic role from names.

Literals.

FormTypeNotes
40, 0.85numberDecimal; the printed form is canonical (no trailing zeros). A literal’s textual form is significant to the environment (drag step 1 vs 0.1) but not to evaluation.
45°, 45degangleDegrees. The suffix style is preserved by machine edits.
#2A76C6colorExactly six hex digits; machine edits write uppercase. A color literal means the same color in every program — there is no color mode.
true, falseboolean
(x, y)pointSyntax, not a token: two expressions in parentheses separated by a comma. Disambiguated from a parenthesized expression by the comma.

Back to contents

A.3  Grammar #

EBNF, with NL, INDENT, DEDENT supplied by the layout lexer. This is the v1.1 surface.

program    ::= { top }
top        ::= stateDecl | definition | frameBlock | eventBlock | stmt
stateDecl  ::= "state" name "=" expr NL
definition ::= "to" name "(" param { "," param } ")" ":" NL block "end" NL
param      ::= label ":" name
frameBlock ::= "every" "frame" ":" NL block
eventBlock ::= "when" ("pointer" | "key") ("pressed" | "released" | "moved") ":" NL block
block      ::= INDENT { stmt } DEDENT
stmt       ::= call NL | assign NL | "return" expr NL
             | repeat | forLoop | ifStmt | groupBlock
assign     ::= name "=" expr
repeat     ::= "repeat" expr "as" name ":" NL block
forLoop    ::= "for" name "from" expr "to" expr [ "step" expr ] ":" NL block
ifStmt     ::= "if" expr ":" NL block [ "else" ":" NL block ]
groupBlock ::= "group" "(" arg { "," arg } ")" ":" NL block
call       ::= name "(" [ arg { "," arg } ] ")"
arg        ::= label ":" expr
expr       ::= orE
orE        ::= andE { "or" andE }
andE       ::= notE { "and" notE }
notE       ::= "not" notE | cmp
cmp        ::= add [ ("<"|"<="|">"|">="|"=="|"!=") add ]
add        ::= mul { ("+"|"-") mul }
mul        ::= unary { ("*"|"/") unary }
unary      ::= "-" unary | member
member     ::= primary { "." ("x"|"y") }
primary    ::= NUMBER | ANGLE | COLOR | "true" | "false"
             | name | call | point | "(" expr ")"
point      ::= "(" expr "," expr ")"

There is no positional argument form: arg requires a label. That absence is the single most consequential production in the grammar.

Back to contents

A.4  Static semantics #

Back to contents

A.5  Dynamic semantics #

The frame relation. A program P denotes a step function. Setup runs once over the declarations and top-level statements, producing the initial store σ₀ and the static display list. Thereafter, for each frame k:

(Dₖ, σₖ₊₁)  =  Fₚ(σₖ, ιₖ)

where ιₖ is that frame’s recorded input (pointer position, button and key events) and Dₖ the frame’s display list. The store σ contains exactly the state variables plus the random generator’s internal state — randomness is part of the store, which is why replay from a seed is exact. There is no other clock: “now” is the frame index.

Evaluation order. Expressions evaluate left-to-right, post-order; arguments evaluate in written order before the call applies. Every expression completion, statement completion, and state write is a numbered step; container statements (repeat, if, group, for) complete as one statement step after their bodies. This step numbering is frozen by golden outputs — it is observable semantics, not an implementation detail, because the scrubber and every pane are keyed to it.

Determinism, strengthened. Beyond seeded randomness and virtual time, trigonometric results inside rotation are rounded to a 10⁻⁹ grid before use, making rotated coordinates bit-identical across processors. Two runs of a program with the same seed and inputs produce byte-identical serialized display lists on every platform; the instrumented (traced) and fast execution modes are one code path and are tested to agree byte-for-byte.

Group transforms. A group’s matrix is T(move)·T(around)·R(rotate)·S(scale)·T(−around); nested groups compose parent·child; positive rotation is clockwise on screen (the stage is y-down, 320×240). Transforms apply eagerly at emission: display operations carry world coordinates, so the output format is transform-free. Radii and stroke widths scale with scale. Under nonzero rotation a rect lowers to two exact triangles sharing one step index, and an ellipse is a diagnostic rather than a silently wrong shape.

Back to contents

A.6  Output: the display list #

A program’s output for a frame is an ordered display list: a background color and a sequence of operations of kinds circle, ellipse, rect, triangle, line, each carrying its full world-coordinate geometry and color, plus two provenance fields — the source node that emitted it and the step index at which it was emitted. The list serializes to a canonical byte string, and equality of programs’ outputs is defined as equality of those bytes. A second, visual serialization omits the two provenance fields; it is the oracle for source-to-source transformations, since inserting a statement necessarily shifts provenance while leaving every pixel-determining byte unchanged. The two serializations, and a test that the visual one still distinguishes a one-unit geometry change and a reordered draw, are part of the language’s contract.

Back to contents

A.7  The trace #

Instrumented execution records one row per step in columnar storage: sequence number, source node, step kind, a type tag, two numeric payload slots (value, or point x/y, or color, or degrees), a string-table index, and the half-open range of display operations emitted during the step. The recording is two-tier: frame keyframes are kept cheaply for the whole run, and full step traces are produced on demand by re-executing a focused frame — determinism makes the re-execution exact. Everything the environment shows, including the affine provenance chains behind direct manipulation, is a pure function of this trace; provenance is reconstructed post-hoc and adds nothing to execution cost.

Back to contents

A.8  Standard vocabulary #

WordParameters (label: type)Defaults offered by the environment
papercolor: color#888888 fallback
circlecenter: point, radius: number, fill: color(160, 120), 40, #888888
ellipsecenter: point, width: number, height: number, fill: colorcentered, stage-proportioned
rectleft: number, top: number, width: number, height: number, fill: colorstage-proportioned
trianglea: point, b: point, c: point, fill: colorstage-proportioned
linefrom: point, to: point, stroke: color, width: numberwidth 2
randomfrom: number, to: numbernone — bounds are the meaning

Defaults are stored in the vocabulary registry and rendered through the single value formatter, so a completion’s inserted text is itself valid Chalk. random draws from the store’s seeded generator. pointer.x, pointer.y read the frame’s input.

Back to contents

A.9  Verified properties #

These are stated as the propositions the test suite enforces, since they are the language’s reason to exist. Determinism: equal source, seed, and inputs imply byte-equal serialized output, across platforms. Mode agreement: traced and untraced execution produce byte-equal output. Splice identity: every machine edit of a literal re-parses to a program whose node identities match the original with zero fresh and zero dropped statements. Gesture law: every abstraction gesture preserves the visual serialization byte-for-byte and preserves the identities of untouched statements. Provenance discipline: reconstructed chains are affine over source literals with a canonical term order; values the algebra cannot express (products of two variable terms, state carried across frames, random draws, pointer reads) are opaque constants, never guesses; every drag candidate satisfies prediction consistency — applying it and re-running places the dragged attribute at the target.

Back to contents

A.10  Exclusions #

Chalk v1.1 has no collections, no recursion, no functions as values, no strings in the value surface, no modules, no exceptions, and no null. These are commitments rather than omissions: each absent construct is one the environment would otherwise have to explain, trace, invert, and preserve, and the main report’s closing sections discuss what admitting any of them would cost.

Back to contents


Appendix B #

The eight-lesson curriculum — the shipped learning sequence, its validation contract, and a live, playable demonstration of each lesson's capability — is a separate document: Appendix B: The Eight-Lesson Curriculum.

Back to contents

Companion to Programming in a Glass House and Appendix B: The Eight-Lesson Curriculum. Part of Grasphouse. Chalk and Glasshouse are open source; the reference implementation and its 274-test suite are the normative definition of everything stated here.