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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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