Skip to content

feat: t27_check -- parse and typecheck .t27 source, with a fix hint for foreign syntax - #8

Merged
gHashTag merged 2 commits into
masterfrom
t27-check
Oct 18, 2026
Merged

gHashTag merged 2 commits into
masterfrom
t27-check

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes gHashTag/t27#10073

Part of the epic gHashTag/t27#10066 (learnability: parser hints for foreign syntax). The rule table is gHashTag/t27#10080. (Replaces #5, which GitHub closed when its base branch was deleted after #4 merged; same commit, rebased onto master.)

What

A new tool, t27_check: give it .t27 source, get back whether it parses and typechecks and, for each
diagnostic, the line, the source line and a short "write this instead" hint for foreign syntax. It runs offline.

t27_check({source: "module M;\npub fn f(a: u8) -> u8 {\n    return (a as u3);\n}\n"})
{ ok: false, errors: 1, warnings: 0, diagnostics: [{ severity: "error", line: 3,
  message: "parse error in fn 'f' near line 3: unknown cast target type `u3`; ...",
  hint: "Casts reach only bool u8 ... usize f32 f64: there is no `as u3`. Keep a wider type and mask the value, e.g. `x & 7`.",
  source: "    return (a as u3);" }] }
  • wasm/explorer.wasm: the bootstrap parser and typechecker (gHashTag/t27 bindings/wasm-explorer), copied
    unchanged, 774 KB. It decides ok or not; the server adds no verdict.
  • wasm/check_hints.wasm + wasm/check_hints.mjs: generated from specs/t27mcp/check_hints.t27 by
    t27c gen-c + zig cc and t27c gen-js (the string parameters of the spec arrive as const char*, so no
    hand export glue is needed). Built on the Railway lab; commands and sha256 in wasm/BUILD.
  • check.mjs (26 lines) is glue: it moves bytes between the two wasm modules. A message the spec does not know
    gets no hint, and the compiler's words stand alone.

Hand-written JavaScript added: check.mjs 26, server.mjs 11, smoke.mjs 11 = 48 lines (cap: 40 per file, 80
per PR).

Evidence

  • npm run smoke: the four new t27_check checks pass (clean source, as u3 with its line and source, in as a
    name, and a negative control: an arity error gets no hint). The run's one failure,
    backendFailures tally matches the specs blaming a backend (737 counted vs 113 blaming), is in the live atlas
    data and in code this PR does not touch; it is the kind of tally logic the epic's last item moves into .t27.
  • 200 checks of a failing source take 58 ms in total.
  • Spec side: 13 of 13 tests, 0 vacuous, negative control fails as it should (spec(t27mcp): check_hints -- compiler message to a short fix hint for foreign syntax t27#10080).

🤖 Generated with Claude Code

@tri-claw

tri-claw Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Summary by t27-bees

This PR adds a new t27_check tool that parses and typechecks .t27 source offline using the real compiler front-end (wasm/explorer.wasm), then enriches each diagnostic with a line number, the offending source line, and a fix hint for known foreign-syntax patterns (generated from specs/t27mcp/check_hints.t27 via wasm/check_hints.wasm).

Worth a look

  • check.mjs:14–15 — The check_hints wasm instance uses a single fixed memory region (base + one grown page) for all ask calls. Concurrent requests will overwrite each other's input strings, producing wrong hints or crashes.
  • check.mjs:15 — Messages are silently truncated to 4000 characters before being passed to the hint module. Long compiler diagnostics could lose information needed for hint matching.
  • check.mjs:23 — When j.astError exists, only that parse error is reported; any j.typecheck.errors are dropped. If the parser recovers and produces multiple errors, only the first is surfaced.
  • check.mjs:25 — Severity is inferred solely by message.startsWith('warning:'). Any non-warning message (including potential future "info" or "note" categories) becomes "error".
  • check.mjs:26 — line || undefined treats line 0 as falsy, yielding source: undefined. If the hint module ever returns 0 for "unknown line," the source line disappears instead of showing the first line.

Read: 9 files, +131 -1, the whole diff. Head 0079a1b. Model: openai-compatible/nvidia/nemotron-3-ultra-550b-a55b. Commands: @t27-bees review | summary | help | pause | resume. Free for every repository.

…or foreign syntax

The compiler front end runs as wasm (explorer.wasm, gHashTag/t27
bindings/wasm-explorer, unchanged); each message gets a hint code and a line
number from wasm/check_hints.wasm, generated from
gHashTag/t27 specs/t27mcp/check_hints.t27 (PR gHashTag/t27#10080). check.mjs is
26 lines of glue and holds no rule.

Closes gHashTag/t27#10073
Refs gHashTag/t27#10066

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…t27#8087)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag merged commit ce1c980 into master Oct 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec(t27mcp): t27_check -- compiler message to a short fix hint for foreign syntax

1 participant