Skip to content

feat(res-to-affine): Phase 3 slice 3 — literal let→const translation (Refs #57) - #484

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/pensive-fermi-JVCzu
May 31, 2026
Merged

feat(res-to-affine): Phase 3 slice 3 — literal let→const translation (Refs #57)#484
hyperpolymath merged 1 commit into
mainfrom
claude/pensive-fermi-JVCzu

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

What

Third slice of Phase 3 for the .res.affine migration assistant (#57). Extends --translate to module-level literal let bindings, lowering them to typed AffineScript const declarations (AffineScript has no module-level let — a top-level value binding is const name: Type = value;).

ReScript AffineScript
let answer = 42 const answer: Int = 42;
let pi = 3.14 const pi: Float = 3.14;
let greeting = "hi" const greeting: String = "hi";
let enabled = true const enabled: Bool = true;

How / conservatism

Only int/float/string/bool literals translate — their type is inferred and the resulting const type-checks standalone (a literal is a compile-time constant). Skipped (left as marker + quoted original, never a wrong const):

  • non-literal body — a call (Date.now()), a ref(...) (the mutable-global anti-pattern), etc.
  • destructuring pattern (let (a, b) = …) — not a plain identifier
  • exotic numbers — hex / octal / binary / signed / scientific / underscored (number forms limited to plain decimal int and D+.D+ float, to avoid a literal the AffineScript lexer might reject)

Walker-internal only (classify_number / translate_literal / translate_let_const + a let_declaration branch in collect_translations); Walker.translate / Emitter.emit_translation signatures unchanged.

Scope boundary (the remaining #57 items)

The guarantee is "every emitted form type-checks standalone", which bounds translation to self-contained top-level declarations. Two forms are out of that scope by construction, now documented in the README:

Verification (local, apt-bootstrapped toolchain)

Check Result
full dune build ✅ exit 0
dune runtest tools/res-to-affine/ ✅ 22/22 (4 new slice-3 cases) against pinned grammar 990214a
compiler oracle main.exe check on the generated consts Type checking passed
doc-truthing + no-extension-ts guards ✅ pass

No OCaml outside tools/res-to-affine/walker.ml; config/compiler jobs unaffected.

Refs #57

https://claude.ai/code/session_017T8SzHr2yXav8hm4Ho76Uw


Generated by Claude Code

…tion (Refs #57)

Extends --translate to module-level value bindings: `let <id> = <literal>`
becomes a typed AffineScript `const`, since AffineScript has no module-level
`let` (a top-level value binding is `const name: Type = value;`).

  let answer = 42      ->  const answer: Int = 42;
  let pi = 3.14        ->  const pi: Float = 3.14;
  let greeting = "hi"  ->  const greeting: String = "hi";
  let enabled = true   ->  const enabled: Bool = true;

Conservative: only int/float/string/bool literals (type inferred, const
type-checks standalone). A call body, a `ref(...)` mutable-global, a
destructuring pattern, or an exotic number (hex/signed/scientific/underscored)
is skipped — left as marker + quoted original, never a wrong const. Number
forms limited to plain decimal int and D+.D+ float.

Walker-internal (translate_literal / classify_number / translate_let_const +
a let_declaration branch in collect_translations); Walker.translate /
Emitter.emit_translation signatures unchanged.

Scope boundary documented: switch->match (an expression needing whole-function
translation of un-annotated ReScript fns) and qualified-path resolution stay
out of the "every emitted form type-checks" scope.

Verified locally with the apt-bootstrapped toolchain: full `dune build` exit 0;
22 res-to-affine walker tests green (4 new) against pinned grammar 990214a;
`main.exe check` on the generated consts returns Type checking passed.

Refs #57

https://claude.ai/code/session_017T8SzHr2yXav8hm4Ho76Uw
@hyperpolymath
hyperpolymath marked this pull request as ready for review May 31, 2026 05:48
@hyperpolymath
hyperpolymath merged commit ea8bef5 into main May 31, 2026
15 of 24 checks passed
@hyperpolymath
hyperpolymath deleted the claude/pensive-fermi-JVCzu branch May 31, 2026 05:48
hyperpolymath added a commit that referenced this pull request May 31, 2026
…rms (Refs #488) (#490)

STATE.a2ml: dated note for Phase 3 slice 3 (#484), the #57 closure, and successor #488; last-updated 2026-05-31. .claude/settings.json: add git-workflow commands to the permission allowlist. Docs/config only, no code. Refs #57 #488.
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 83 issues detected

Severity Count
🔴 Critical 2
🟠 High 13
🟡 Medium 68

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action perpolymath/standards/.github/workflows/governance-reusable.yml@main\n needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action ons/checkout@v6\n    needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action land/setup-deno@v2\n    needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in affine-vscode-publish.yml",
    "type": "missing_timeout_minutes",
    "file": "affine-vscode-publish.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

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

Labels

None yet

2 participants