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

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 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.