- Function calls are f(a, b) via a postfix argument list; juxtaposition
application removed; nullary calls f() supported
- Wire DEFINITION (x ≜ e), ALLOC/RELEASE postfix (r ⊕ / r ⊖), channel
operations (⇀_ch e / ↽_ch e), and qualified module access (M‧f)
- Delete tokens with no rule and no example: QUERY (?), EXISTS, IMPORT,
ARROW, DOT; delete the unary ? prefix operator
- Canonical handler clause: ↯pattern ⟹ expr (pattern is an identifier or
a string); clauses separated by semicolons
- SEMICOLON has one role: sequence separator with optional trailing use
- Disambiguate braces structurally: record ({a: e}), set ({a, b}), block
- IDENTIFIER no longer allows a leading underscore, so subscripts such as
⌉_db_lock and ↽_socket lex as UNDERSCORE + IDENTIFIER
- Add '/' as ASCII alias of ÷; add unary minus; pathLiteral accepts
🖫identifier as well as 🖫"…"
- Exactly one ASCII escape per glyph (drop \lam, \gets, \ne, \le, \ge,
\vee, \wedge, \cup alias forms, \N, \Z, \Q, \R, \C, \B)
- Replace deprecated ANTLRInputStream with CharStreams in the test
harness: it fed UTF-16 units and could never tokenize the
supplementary-plane glyphs 𝔹, 𝓜 and 🖫
- Update LexerTest/ParserTest to canonical syntax; add coverage for
subscript lexing, channels, resources, module access, unary minus,
nullary calls, and negative tests for juxtaposition and the ternary
4.7 KiB
4.7 KiB
Design decisions
One line per decision, with the rejected alternatives named. Governing principles, in order: One Right Answer, the Fatima test, minimal churn against the existing examples.
- Conditionals are guarded alternatives
(condition ⟹ result) | fallback, wired in as acondExprprecedence level; rejected: C-style ternarycond ? a : b(programmer convention, fails the Fatima test), standalone left-recursiveconditionalrule (ANTLR error 119). - Exception handling is a postfix operator
expr ↴ { … }; rejected: standaloneexceptionHandlerrule reachable fromatomExpr(mutual left recursion, ANTLR error 119). - λ has one token,
LAMBDA_VAR, used both as a variable and to open a lambda; rejected: separateLAMBDAtoken (identical alternatives, fully shadowed, ANTLR warning 184). \impliesmaps to ⟹ and\Rightarrowmaps to ⇒ — one escape, one glyph; rejected:\Rightarrowas an alias of ⟹ (shadowed EXPORT's escape, ANTLR warning 184).- The Java package for generated code comes from
-packagein build.gradle only; rejected:@headerpackage declaration in the grammar (combined with-packageit generates a duplicatepackagestatement that does not compile). - ANTLR warnings fail the build (
-Werrorin build.gradle); rejected: warnings as advisory output (they hid the shadowed-token bugs). - The choice-type rule is
⟨ expr ⟩with the interior|consumed bycondExpr; rejected: explicit⟨ expr | expr ⟩(the interior expr already consumes the bar, making the explicit BAR unreachable). - Function calls are
f(a, b)— a postfix argument list, nullaryf()included; rejected: Haskell juxtapositionf x(programmer convention, fails the Fatima test — children learnf(x)in school). - SEMICOLON has one role: sequence separator (trailing
;permitted); the program, blocks,(...),⌈...⌉,〔...〕,⌜...⌝,⌞...⌟and⟳(...)all contain oneseqExpr; rejected: a separate statement-terminator rule duplicating the same token (two roles for one symbol). - Braces disambiguate structurally:
IDENTIFIER :→ record, two-plus comma-separated exprs → set, everything else (incl.{}and{x}) → block; a singleton set literal cannot be written (deferred to M1); rejected: parser-order coin flips left undocumented. ≜defines,←assigns; both wired into the chain with≜binding looser than←, both right-associative; rejected:≜tokenized but unreachable.⊕/⊖are postfix resource operators (database ⊕,conn ⊖), matching every example; rejected: prefix form⊕open(path)that appeared only in the whitepaper.- Channel operations are subscripted prefix operators
⇀_ch expr/↽_ch expr; rejected: leaving SEND/RECEIVE orphaned. ‧is qualified module access (Mathematics‧sin(angle)), a postfix‧IDENTIFIER; rejected: leaving MIDDOT orphaned, or.(removed — one access syntax).- Handler clauses are
↯pattern ⟹ expr, semicolon-separated, where pattern is an identifier (binds the exception) or a string (matches a message); rejected:↯e ⇒ expr(⇒ is EXPORT; the clause arrow should mirror the guarded-alternative arrow ⟹). - IDENTIFIER may not start with
_, so subscripts (⌉_db_lock,↽_socket) lex as UNDERSCORE + IDENTIFIER; rejected: identifiers with a leading underscore (made every subscript lex as one identifier token). /is an ASCII alias of ÷ (DIV) soπ/4parses; rejected: ÷-only division (unreachable on most keyboards).- Unary minus exists (
-x), sharing the MINUS token at prefix level; rejected: binary-only minus (cannot write negative numbers); unary plus was NOT added (x ++ ystays invalid). pathLiteralaccepts🖫"…"and🖫identifier, as required byreadFile(🖫path)in example 03.- Deleted tokens:
?(QUERY),∃(EXISTS),⇐(IMPORT),→(ARROW),.(DOT) — defined but used by no parser rule and no example; dead operators are debt; each returns in M1 only with a documented semantic. Rejected: keeping them tokenized-but-unreachable. - Exactly one ASCII escape per glyph (
\lambdanot\lam,\leftarrownot\gets,\neqnot\ne,\natnot\N, …); rejected: alias sets (two ways to write the same token). %(modulo),∑,√,²,|x|, ranges[a..b], indexing/slicing,where, and record field access are NOT in M0 — every document says so instead of using them; deferred to M1 with semantics, not smuggled in via prose.- Lambda parameters are a bare comma-separated pattern list (
λa, b: body); rejected: parenthesized parameter listsλ(a, b):(two ways to write parameters).