Tracks issue #488 (partial-port mode), the successor to the now-closed #57 (parser + metaparser; the declaration-translation phase, delivered). Companion to RESCRIPT-ELIMINATION.adoc, which is the authoritative ledger for the broader estate ReScript-surface retirement.
Estate language policy retires ReScript in favour of AffineScript →
typed-wasm. Per the inventories captured in
RESCRIPT-ELIMINATION.adoc and the
upstream tracker hyperpolymath/gitbot-fleet#148, ~5k LOC of ReScript
remains in gitbot-fleet/bots/sustainabot/bot-integration/src/ alone;
the idaptik tail is ~542 .res files plus ~80 .ts. By-hand
translation is impractical, and a literal transliterator misses the
point — the AffineScript answer to ReScript’s anti-patterns is
re-decomposition, not a token-level rewrite.
Issue #57 proposes a migration assistant: a tool that reads .res,
recognises the anti-patterns surfaced by the idaptik Wave 3 pilot, and
emits a .affine skeleton that surfaces the work the human migrator
still owes.
-
The migration assistant lives at
tools/res-to-affine/as an OCaml CLI built by the repo’s existingdunetoolchain. -
The canonical source-of-truth grammar for
.resparsing isrescript-lang/tree-sitter-rescript, vendored manifest-only ateditors/tree-sitter-rescript/(pinned to commit990214a83f25801dfe0226bd7e92bb71bba1970f, version 6.0.0, MIT-licensed and compatible with this repo’s MPL-2.0). -
The tool ships in three phases:
Phase What it does Status 1
Text-scan emitter detecting 4 of the 6 anti-patterns, emitting a
.affineskeleton with migration markers and the quoted original for reference.this PR
2
Replaces the text scanner with a tree-sitter AST walker reading the vendored grammar. Adds the two deferred patterns. Same emitter interface.
follow-up
3
Partial translation of pure-structural forms (type aliases, sum decls, simple
letbindings,switch→match). Effect-laden / exception-bearing / globally-mutating regions remain TODO islands.follow-up
-
The Phase-1 deliverable is deliberately small and useful in isolation. It gates the architectural commitment to tree-sitter behind something that already pays its way against real estate
.resfiles.
The richest signal is in the ReScript compiler’s typed AST. Rejected because:
-
Adding
rescriptas a build-time dependency contradicts the estate language policy (which bans new ReScript code and treats ReScript as the artefact to be retired). -
The ReScript compiler’s AST changes across versions in non-backwards-compatible ways; pinning would create an ongoing compatibility burden in the wrong direction.
We already have lib/rescript_codegen.ml going affinescript → .res,
so the grammar is partly understood. Rejected because:
-
ReScript’s surface syntax is large; recreating it for a one-way migration tool is days-to-weeks of work that the canonical tree-sitter grammar has already done and maintains.
-
The community grammar is MIT-licensed and version-pinned; the cost of consuming it is a one-line manifest plus an install script.
Phase 1 is this — but committing to it permanently would leave the two structural anti-patterns (callback records, oversized functions) undetected forever, and would block Phase 3 (partial translation), which is what makes the tool earn its keep on idaptik’s 542 files.
-
editors/tree-sitter-rescript/exists for the migration pipeline, not as an editor binding. The editor binding for AffineScript itself remainseditors/tree-sitter-affinescript/. -
tools/res-to-affine/is the first OCaml tool undertools/(existing tools are shell scripts or Rust). Theduneintegration is local to the tool’s owndunefile; no workspace changes. -
Phase 2 introduces
tree-sitterCLI as a runtime dependency for the migration assistant. It is not a build-time dependency for the AffineScript compiler itself. CI for the migration tool’s Phase-2 tests will need to installtree-sitter-cli. -
The Phase plan is recorded in
tools/res-to-affine/README.md; this document is the architectural decision, the README is the user/contributor surface.
-
tools/res-to-affine/README.md— tool usage, Phase plan, design rationale. -
editors/tree-sitter-rescript/README.md— vendoring manifest details. -
affinescript#57— parser + metaparser proposal (closed; declaration translation delivered). -
affinescript#488— successor: partial-port mode + module-qualified-reference resolution. -
gitbot-fleet#148— downstream tracker for the consumed ReScript subtree. -
RESCRIPT-ELIMINATION.adoc— estate-wide ledger. -
idaptik LESSONS.md — six anti-patterns the assistant targets.
-
idaptik PILOT.md — original Wave-3 pilot that surfaced the six patterns.