feat(jtv): the add{} injection island — Harvard data expressions (#94) - #102
Conversation
`conformance/valid/v11_add_block.tangle` was the last program in the corpus
the parser rejected, and the only one that was not a parse-rule gap: `add{}`
is a SUB-LANGUAGE, specified across 288 lines of FORMAL-SEMANTICS.md.
Not stale, unlike TangleIR — README-jtv.adoc documents it as a deliberate
design: "Computation is braiding... But sometimes, you need arithmetic."
Two syntactically isolated islands give TANGLE data manipulation without
polluting the topological core.
## Semantic separation is the point
`+` in TANGLE is connect-sum on tangles; `+` inside add{} is arithmetic. So
the island gets its OWN grammar (`hv_expr`), its OWN type language (`hv_ty`),
its OWN judgement (|-_hd), and its OWN value space (`hv_value`) — sharing
TANGLE's `expr` would have lost exactly the distinction the design exists to
make. Verified: `braid[s1] + braid[s2]` is connect-sum, `add{ 2 + 3 }` is 5,
and a braid inside add{} does not parse. The island is closed.
Results cross back through Embed (D2.4): Int/Float -> Num, Bool -> Bool,
String -> Str.
## `add` is NOT reserved
First attempt made `add` a keyword, which broke `def add(a, b) = a . b` — a
valid TANGLE program, and one the e2e suite contains. The spec's own first
design principle points at the fix: "Delimited Syntax: add{...} cannot
conflict with TANGLE operators". The DELIMITER is what prevents conflict, so
`add{` is lexed as a single ADDBRACE token. `add` alone remains an ordinary
identifier — the token dump shows IDENT(add) and ADDBRACE side by side in one
file.
## Scope, stated rather than implied
Implemented: the full operator hierarchy (+ - * / %, == != < <= > >=,
&& || !), the TOTAL conditional (both branches required, D2.1), and Int /
Float / Bool / String literals. Guaranteed terminating: structural recursion
on a finite term, no loops, no assignment, no side effects.
NOT implemented and NOT pretended — recorded in the source, not just here:
rationals, complex numbers, lists and tuples (section 7.1); Hex, Binary and
Symbolic types; variables resolving in the Pi environment and function calls
(sections 8.2, 9.5); and the `harvard{...}` CONTROL block (section 6.3)
entirely.
The island is outside the mechanised core — |-_hd has no Lean image — so
AddBlock joins the non-core constructors that tg3_emit rejects outright, and
the JEG lists T-Add-Block among its deferred rules rather than pretending to
re-derive a judgement it does not implement.
## Result
conformance 18/19 -> 19/19. Both corpus manifest gap-lists are now EMPTY: for
the first time every valid program parses, typechecks and evaluates, and every
invalid one is still rejected.
Tests: 13 covering precedence, the conditional, logic, modulo, integer vs
float division, mixed promotion, division by zero, Embed, and two negatives —
arithmetic on a Bool, and if-branches that disagree (totality).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Note Automatic reviews are paused because your trial's included automatic processing has been used for this period. Upgrade now, or comment "Gitar review" to run a review anytime. Code Review ✅ Approved 2 resolved / 2 findingsAdds the ✅ 2 resolved✅ Bug: Float modulo type-checks but crashes at runtime
✅ Bug: add{} == on mixed Int/Float always returns false
OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
conformance/valid/v11_add_block.tanglewas the last program the parser rejected — and the only one that wasn't a parse-rule gap.add{}is a sub-language, specified across 288 lines ofFORMAL-SEMANTICS.md.Not stale, unlike
TangleIR.README-jtv.adocdocuments it as deliberate design: "Computation is braiding… But sometimes, you need arithmetic." Two syntactically isolated islands give TANGLE data manipulation without polluting the topological core.Semantic separation is the whole point
+in TANGLE is connect-sum;+insideadd{}is arithmetic. So the island gets its own grammar (hv_expr), its own type language (hv_ty), its own judgement (⊢_hd) and its own value space (hv_value) — sharing TANGLE'sexprwould have lost exactly the distinction the design exists to make.Verified:
braid[s1] + braid[s2]add{ 2 + 3 }5add{ braid[s1] }Results cross back through Embed (D2.4):
Int/Float→Num,Bool→Bool,String→Str.addis NOT reservedMy first attempt made
adda keyword — which brokedef add(a, b) = a . b, a valid TANGLE program that the e2e suite contains.The spec's own first design principle points at the fix: "Delimited Syntax:
add{...}cannot conflict with TANGLE operators." The delimiter is what prevents conflict, soadd{is lexed as a singleADDBRACEtoken.addalone stays an ordinary identifier — the token dump shows both in one file:Scope — stated, not implied
Implemented: the full operator hierarchy (
+ - * / %,== != < <= > >=,&& || !), the total conditional (both branches required, D2.1), and Int/Float/Bool/String literals. Guaranteed terminating: structural recursion on a finite term, no loops, no assignment, no side effects.Not implemented, and not pretended — recorded in the source, not just here: rationals, complex, lists, tuples (§7.1); Hex/Binary/Symbolic types; variables in the
Πenvironment and function calls (§8.2, §9.5); and theharvard{...}control block (§6.3) entirely.The island is outside the mechanised core —
⊢_hdhas no Lean image — soAddBlockjoins the non-core constructorstg3_emitrejects outright, and the JEG listsT-Add-Blockamong its deferred rules rather than pretending to re-derive a judgement it doesn't implement.Result
conformance 18/19 → 19/19. Both corpus manifest gap-lists are now empty: for the first time every valid program parses, typechecks and evaluates, and every invalid one is still rejected.
13 tests: precedence, conditional, logic, modulo, int-vs-float division, mixed promotion, division by zero, Embed — plus two negatives (arithmetic on a
Bool; if-branches that disagree).🤖 Generated with Claude Code