Commit 478857f
Implements the #92 ruling across both engines — plus two bugs found
while verifying it.
## The rule
`T-Eq-Word` required both operands at the same width. Four ways that was
inconsistent with the language itself (evidence in #92):
- **`tComposeWord` already widens** to `max n m` — you could compose two
braids you were then forbidden to compare.
- **`~` accepted differing widths** and, since TG-7, evaluates through
the *same* `Braid_equiv.equiv`. Identical operands, identical answer,
one rejected by the typechecker.
- **`eqIdBraid`/`eqBraidId`** decide "is this braid trivial?" against
`identity : word 0`, so under the old rule they could only fire when the
braid was empty. The step relation had rules for a question the typing
rule forbade asking.
- **`braid_equiv.equiv` has no width parameter at all.**
Lean's `tEqWord` now takes `(n m)`; `infer`'s `.eq` case drops the `if n
= m`; OCaml `Eq` mirrors it. Match arms join on width for words and
still require exact agreement otherwise.
## The metatheory needed no patching
**Progress, Preservation, Determinism, TypeSafety, `infer_sound`,
`infer_complete` all still hold** — `lean Tangle.lean` reports **0
errors**, sorry/axiom gate passes.
`infer_sound`'s proof got *simpler*: with no `if n = m` there's no inner
`split` to case on. A restriction whose removal shortens the proof was
carrying no weight.
**TG-3 regenerated and kernel-checked: 496 obligations, 0 errors.** 46
flipped from `= none` to `= some .bool` — exactly the `identity ==
braid` shape that was unreachable before.
## Two bugs found while verifying
**1. Statement order.** `parse_file_recovering` did `stmts := prog @
!stmts` then `List.rev` on the flattened result. That reversal is
correct for an accumulator built by prepending *single items* (as
`diagnostics` is) — but whole **segments** were prepended, so every
program came out backwards:
```
def x = 5 parses to def z = 7
def y = 6 -------> def y = 6
def z = 7 def x = 5
```
Any program whose statements depend on order died with *"Unbound
variable"*. **The test suites never caught it because they call
`Tangle.Parser.program` directly — only the CLI goes through the
recovering path.**
**2. A false assertion in `examples/trefoil.tangle`:**
```tangle
assert reversed == braid[s1, s1, s1] # reversed = reverse(trefoil)
```
`reverse` reverses the word *and negates exponents*, yielding the
inverse braid. Verified by invariant: `writhe(trefoil) = 3`,
`writhe(reversed) = -3`, and writhe is invariant under the braid
relations — so they cannot be equal. The assertion had been wrong since
it was written; nothing ran the examples until #89. Corrected to
`braid[s1^-1, s1^-1, s1^-1]`, which passes.
## Result
| | before | after |
|---|---|---|
| examples evaluating | 2/7 | **7/7** |
| `lib/stdlib.tangle` | did not typecheck | **typechecks** |
| conformance | 18/19 | 18/19 (`v11` is the Harvard sub-language, #94) |
All seven examples are now in the corpus gate's must-run set, so none
can regress.
## ⚠ Trusted base — registered as A-TG-92.1
The embedding **Bₙ ↪ Bₙ₊₁** that justifies cross-width comparison is
standard mathematics, but it is **asserted in prose, not mechanised** —
no Lean lemma states it.
What *is* machine-checked: that the metatheory holds under the widened
rule, and that OCaml `infer_expr` still agrees with Lean `infer` on the
corpus. That distinction is recorded in `ASSUMPTIONS.md` rather than
left implicit.
## Tests
6 new typecheck cases, including **two negatives** — mismatched *kinds*
still rejected, match arms of different kinds still rejected — so
widening cannot quietly become "anything compares to anything". Three
`test_check` cases repointed at an error that is still an error (and an
assertion helper left unused by the change was put back to work rather
than deleted).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 1223ea6 commit 478857f
11 files changed
Lines changed: 212 additions & 97 deletions
File tree
- compiler
- bin
- lib
- test
- tg3
- examples
- proofs
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
36 | 37 | | |
37 | 38 | | |
38 | 39 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
52 | | - | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
53 | 64 | | |
54 | 65 | | |
55 | 66 | | |
56 | 67 | | |
57 | | - | |
| 68 | + | |
58 | 69 | | |
59 | 70 | | |
60 | 71 | | |
| |||
76 | 87 | | |
77 | 88 | | |
78 | 89 | | |
79 | | - | |
| 90 | + | |
| 91 | + | |
80 | 92 | | |
81 | 93 | | |
82 | 94 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
90 | 90 | | |
91 | 91 | | |
92 | 92 | | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
93 | 105 | | |
94 | 106 | | |
95 | 107 | | |
| |||
321 | 333 | | |
322 | 334 | | |
323 | 335 | | |
324 | | - | |
325 | | - | |
326 | 336 | | |
327 | 337 | | |
328 | 338 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
399 | 399 | | |
400 | 400 | | |
401 | 401 | | |
402 | | - | |
403 | | - | |
404 | | - | |
405 | | - | |
406 | | - | |
407 | | - | |
408 | | - | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
409 | 434 | | |
410 | 435 | | |
411 | 436 | | |
| |||
571 | 596 | | |
572 | 597 | | |
573 | 598 | | |
574 | | - | |
575 | | - | |
576 | | - | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
577 | 606 | | |
578 | 607 | | |
579 | 608 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | | - | |
47 | | - | |
48 | | - | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
49 | 50 | | |
50 | | - | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
51 | 56 | | |
52 | 57 | | |
53 | 58 | | |
| |||
61 | 66 | | |
62 | 67 | | |
63 | 68 | | |
64 | | - | |
| 69 | + | |
65 | 70 | | |
66 | 71 | | |
67 | 72 | | |
68 | | - | |
| 73 | + | |
69 | 74 | | |
70 | 75 | | |
71 | 76 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1062 | 1062 | | |
1063 | 1063 | | |
1064 | 1064 | | |
1065 | | - | |
1066 | | - | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
| 1090 | + | |
| 1091 | + | |
| 1092 | + | |
| 1093 | + | |
| 1094 | + | |
| 1095 | + | |
| 1096 | + | |
| 1097 | + | |
1067 | 1098 | | |
1068 | 1099 | | |
1069 | 1100 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
357 | 357 | | |
358 | 358 | | |
359 | 359 | | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
360 | 364 | | |
361 | 365 | | |
362 | 366 | | |
363 | 367 | | |
364 | | - | |
| 368 | + | |
365 | 369 | | |
366 | 370 | | |
367 | 371 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
66 | 66 | | |
67 | 67 | | |
68 | 68 | | |
69 | | - | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
70 | 78 | | |
71 | 79 | | |
72 | 80 | | |
| |||
0 commit comments