Skip to content

[Repo] res-to-affine partial-port mode: switch→match / function translation + module-qualified references #488

Description

@hyperpolymath

Proposal

Successor to #57 (now closed — its goal, the .res.affine declaration translator, is delivered). This issue tracks the next translation model for tools/res-to-affine/: a partial-port mode that translates expression- and function-level constructs, plus module-qualified references.

Why a separate issue / model

--translate today guarantees that every emitted form type-checks standalone (main.exe checkType checking passed), which is exactly why it's bounded to self-contained top-level declarations: type aliases, sums, structs, generics, and literal letconst (slices delivered in #477 / #481 / #484). Two remaining forms cannot meet that guarantee by construction and need a different model:

1. switchmatch (+ function translation) — partial-port mode

A match is an expression, only meaningful inside a function body. Producing a type-checkable result means translating the whole enclosing function — but ReScript bindings are usually un-annotated (let f = x => …), while AffineScript fn requires parameter and return types, so the output won't compile.

The model this needs is translate-with-TODO-holes: render the structural skeleton of a function (signature stub + match arms with translated patterns) and leave un-inferable bodies / types as explicit // TODO islands. This drops the standalone-type-check guarantee — output is a partial port a human finishes, matching the README's original "~60–80% translation" vision. Scope to design:

  • function signature stubs from un-annotated params (TODO-typed params, inferred-where-possible)
  • switch e { | P => body, … }match e { P => body, … } (pattern translation; => kept; leading | dropped; commas added)
  • a small expression translator for the common, safe cases (literals, identifiers, constructor application, simple calls/operators), TODO for the rest

2. Module-qualified references

Belt.Map.t now parses (the #228 grammar gap closed — parser.mly:515 wires qualified_type_name into type_expr_primary) but Belt::Map::T won't resolve against a target module that doesn't exist yet. Needs a module-mapping story (ReScript stdlib module → AffineScript stdlib module, or an explicit "unresolved import" marker) before it can be emitted without breaking a build.

Acceptance / starting points

  • Decide the partial-port output contract (it is explicitly not required to type-check; document that distinction from the declaration translator).
  • Reuse the existing walker AST (tools/res-to-affine/walker.ml) and the conservative skip-don't-guess discipline.
  • Gate tests like the existing walker-phase3* suites (skip without the tree-sitter grammar).

Context


Filed as the successor to #57 at the owner's request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew capability or improvement to existing behaviourmigrationPorting between languages or toolchains (e.g. -> AffineScript)scope:repoConfined to this repository

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions