Sharpee
Chord / Project & Files / Tooling / Migrating from removed constructs

Migrating from removed constructs

Chord's grammar is a one-way ratchet: constructs that were removed on the way to v1 are not merely undocumented, they are actively refused. Each removed form produces a specific parse.* error whose message names its replacement, so a story written against an older sketch fails loudly and points the way, rather than misbehaving quietly. Every row below is backed by an expected-to-fail fixture in this reference's harness, which asserts the exact code still fires.

Removed formDiagnostic codeReplacement
top-level when <actor> <verb>s … ruleparse.removed-whenan on/after clause on the owner
top-level once <condition> ruleparse.removed-oncethe , once clause modifier
top-level every N turns ruleparse.removed-everya define sequence or every turn clause
define flag <name>parse.removed-flagowner states: or a derived condition
flag trait-field typeparse.removed-flag-fieldtrait states
if / else / end ifparse.removed-ifmust, the when suffix, or select
top-level define score … worth Nparse.removed-scorean owner-attached score line
ordered / once phrase strategyparse.phrase-strategy-retiredstopping / first-time
on <verb> it / after <verb> it clause headparse.removed-head-iton <actor> <verb> — the head names who acts
it / its in a statement, condition, or possessiveanalysis.it-removedthe owner's name; still the carrier inside define trait
create the playerparse.removed-create-playera named character, playable, and a before the game starts block
a create block with no kind, or a trait before the kind (Chord 4.0)analysis.missing-kind-noun / analysis.kind-not-firstthe kind as the block's first line — a thing, a room, a container, openable
define text <name> from "<module>" (Chord 4.0)parse.removed-text-hatcha define phrase, with a strategy (cycling, first-time, …) if the text varies
define action <name> from "<module>" (Chord 4.0)parse.removed-action-hatcha define action block written in Chord
define chain <name> from "<module>" (Chord 4.0)parse.removed-chain-hatchnone — the behavior needs support in the language; say so in an issue
a region containing rooms, or nested regions (Chord 4.0)parse.removed-containingthe region's rooms group; a room's in <region> membership
use state-machines (Chord 4.0)analysis.extension-corenothing — define machine is core; remove the line
a container with max items N / with max weight N (Chord 4.0)parse.removed-capacity-settingthe holds <n> line
a one-line passage <words> to <room> (Chord 4.0)parse.passage-line-formthe passage to <room> … end passage block with its grammar
passage: on a vehicle (Chord 4.0)parse.passage-is-pacepace: — a flight's trip time

The through-line is stickiness (design.md, given 9): every one of these removals took a floating, top-level behavior and re-homed it on the thing it is actually about. A when rule floated beside the world; an on clause lives on the room it reacts in. A global flag floated in no one's namespace; a states: line lives on its owner. The migration is almost always "find the thing this was really about, and move it there."

The three newest rows sharpen the same idea one turn further. A clause used to say what it acted on and leave who acted implicit; now the head names the actor and the block it sits in supplies the object. it was a pronoun with no antecedent on the line, so a clause could not be read alone; now the owner is written, except inside a define trait, where the carrier has no name to write. And the player stopped being a block to become a role a named character holds — see The player role.

The Chord 4.0 rows are the first since 3.0.0 to turn the ratchet on the language's own closed syntax rather than on a floating construct. A create block names its kind first because the kind is what the rest of the block is read against; the three hatch forms are gone because a story that reaches into TypeScript is no longer a Chord story, and what Chord cannot say is a language gap to close, not a hole to climb through; a region declares its rooms because membership belongs on the region, not in a nesting; use state-machines and the capacity settings are refused because the vocabulary is core and holds is the one spelling; and a passage is a block with a grammar, so the one-line form and a vehicle's passage: line both have a named replacement.

The richest case is if, because a single removed construct fans out to three replacements. This no longer parses:

  on the player opening
    if the door is locked-fast
      phrase clunk
    end if
  end on

It reports parse.removed-if, and which replacement you want depends on what the if was doing. If it was guarding the whole action (this may not proceed unless a condition holds), it becomes a must requirement. If it was making one statement conditional, it becomes that statement plus a when suffix (phrase clunk when the door is locked-fast). If it was choosing between several bodies by a value, it becomes a select. The removed if had all three jobs; Chord gives each its own, clearer form.

The formal grammar

The complete grammar (productions, layout rules, and the ratchet history) lives in the Chord grammar reference, with the machine-readable EBNF downloadable there.