-
Notifications
You must be signed in to change notification settings - Fork 0
Reason tags
Both non-transition responses — Ignore and Can't Happen — take an explanation. Most reasons are used once and are simply written where they apply:
can't happen
Door closed
Door is opening, so it should not detect ‘closed’.
The explanation is free text indented one level below the event name. It may run to as many lines as it needs; the parser joins them into a single paragraph, so the line breaks are yours to place wherever the source reads best.
Some reasons apply in several states, and repeating the prose invites the copies to drift apart. Label the reason once with a tag in angle brackets, at the start of its explanation:
state OPENING
...
can't happen
Unlock
<Cabin not moving> Cabin is not able to progress to a state where it can send this event while we are
opening the door.
Every other state then names the tag alone:
state CLOSING
...
can't happen
Unlock
<Cabin not moving>
Since a reference carries no text of its own, it may also ride on the event line:
state COMPLETED
...
can't happen
Cabin arrived <Transfer synch>
Cancel <Transfer synch>
Both forms mean the same thing. The compact one earns its keep in a state whose responses are all references, where the indented lines would otherwise be a column of lone tags.
The grammar:
response = INDENT event_name (SP tag)? EOL* explanation?
explanation = expl_line+
expl_line = INDENT INDENT tag? expl_text EOL
expl_text = r'[^\n]*'
tag = '<' r'[^>\n]+' '>' SP*
Note that only the indented form can define a tag, because a definition needs somewhere to put its text.
A tag is any text between angle brackets, so spaces are fine and reasons can be named in plain English.
Tags are scoped to the file. The occurrence carrying explanatory text defines the tag; an occurrence
with a tag and nothing after it is a reference. Definition and reference may appear in either order and
in any state, and a tag may cross between the ignore and can't happen sections when the same reason
justifies both.
- Tag only what you reuse. A reason used once reads better as plain prose with no tag at all. In the Door lifecycle, eleven reasons are tagged and nine are one-offs left untagged.
-
Avoid apostrophes in tag names. Tags match as literal text, so a straight
'typed against a curly’silently fails to resolve.<Closed door cannot be blocked>sidesteps the problem that<Can't block a closed door>invites. - One reason, one tag. If two states need subtly different justifications, write two reasons. Sharing a tag across situations that are only roughly similar is how a reason ends up too vague to be worth reading.
The state transition tables these files replaced used numbered comments — CH-14, IGN-4 — collected in a
separate table. That works on paper but inserting a comment renumbers everything after it, and the numbers
mean nothing at the point of use. A tag reads as its own explanation at every reference, and a generated
table can still number the reasons however it likes at render time.
Each Response_a carries tag and explanation. A definition has both; a reference has a tag and an
empty explanation; an untagged one-off has an explanation and tag set to None. Resolving a reference
means looking up the tag among the definitions:
reason = r.explanation if r.explanation else tags[r.tag]Copyright 2023-2026 © Leon Starr under MIT Open Source License