Commit a050c65
## Summary
Closes #458 — \`String < String\` (and \`>\` / \`<=\` / \`>=\`) now
type-check, lowering to JS's native lexicographic string comparison.
Pre-fix: \`TypeMismatch (String, Int)\`.
## Implementation
Single addition to the existing comparison dispatch in
\`Typecheck.synth_expr\` for \`ExprBinary\`:
\`\`\`ocaml
match repr lhs_ty with
| TCon "Float" -> ...
| TCon "String" ->
let* () = check ctx rhs ty_string in
Ok ty_bool
| _ -> ... (* legacy Int monomorphism *)
\`\`\`
Pattern mirrors the existing Float dispatch a few lines up. No codegen
changes needed — JavaScript's \`<\` / \`>\` / \`<=\` / \`>=\` on strings
is lex compare natively, and the JS-family backends already emit those
operators verbatim.
## Test plan
New regression fixture \`tests/codegen-deno/string_lex_cmp.affine\` +
harness with **22 assertions**:
- All four ops via functional form (\`lt(a, b)\`, etc.) — covers each
operator's positive/negative direction
- All four ops via literal form (\`first_lt()\`, etc.)
- Equal-string corner cases — \`x <= x\` true, \`x >= x\` true, \`x <
x\` false
- Empty strings — \`\"\" < \"a\"\`, \`\"\" <= \"\"\`
- Prefix relations — \`\"abc\" < \"abcd\"\`
- [x] Local \`./tools/run_codegen_deno_tests.sh\`: **14/14** harnesses
green
- [x] Local \`dune test\`: **352/352** green
- [x] Smoke compile: \`return a < b;\` emits as \`return (a < b);\` (JS
native)
## Out of scope
- **Non-ASCII string comparison** in the fixture: this branch forked
from \`main\` before #463 (the companion Unicode-escape codegen fix for
#460) lands, so non-ASCII source literals would still emit OCaml-style
\`\\NNN\` octal escapes that strict-mode ESM rejects. The relational
typecheck change is orthogonal to literal encoding — non-ASCII lex
compare works naturally once both PRs merge. A non-ASCII assertion can
be added in a follow-up commit after #463 merges, or auto-rebased here
if they land in either order.
- **Other backends** (rescript, wasm, lua, c, rust): out of scope; #458
specifically called out the JS-family ergonomic gap. If \`String <\`
lowering for other backends becomes load-bearing, file separately.
## Refs
- Closes #458
- Refs hyperpolymath/standards#284 (the seam-analyst PR with the
\`str_lt\` workaround)
- Companion: #463 (#460 Unicode-escape codegen, lands together to
unblock non-ASCII relational comparisons)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d5437f8 commit a050c65
3 files changed
Lines changed: 61 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1024 | 1024 | | |
1025 | 1025 | | |
1026 | 1026 | | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
1027 | 1033 | | |
1028 | 1034 | | |
1029 | 1035 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
0 commit comments