Surfaced by: IDApTIK Mode A pilot of shared/src/PortNames.res → migration/shared/PortNames.affine (after PR #67's parser fix lands).
Affected version: v0.1.0 (affinescript HEAD with PR #67 [T] parser fix applied).
Severity: Blocks compile (codegen) on any module with top-level const bindings used by other top-level fns or consts. check (typechecker) handles them correctly.
Reproducer
const inputSuffix: String = ":in";
fn withInput(port: String) -> String { port ++ inputSuffix }
$ affinescript check pn.affine
Type checking passed
$ affinescript compile pn.affine
Code generation error: (Codegen.UnboundVariable "inputSuffix")
affinescript: Code generation error
Diagnosis
The typechecker resolves inputSuffix correctly (check passes), so the AST has the right cross-reference. The codegen phase has its own name resolution and fails to look up inputSuffix when generating code for withInput's body — top-level consts aren't being threaded into the codegen environment alongside fn bindings.
bin/main.ml and lib/codegen.ml (or wherever the codegen lives) likely walk fn_decl declarations only, skipping const_decl. Adding consts to the codegen environment is the likely fix.
Why this matters now
Real idaptik translation hits this immediately. Modules like PortNames (well-known string constants used across the codebase), AssetPaths (resource locations), PortBindings (configuration), and many more, are precisely the shape of "a few module-level constants + a few helper fns that reference them". They typecheck cleanly but cannot be compiled to wasm.
Cross-reference
Surfaced by: IDApTIK Mode A pilot of
shared/src/PortNames.res → migration/shared/PortNames.affine(after PR #67's parser fix lands).Affected version: v0.1.0 (
affinescriptHEAD with PR #67[T]parser fix applied).Severity: Blocks
compile(codegen) on any module with top-levelconstbindings used by other top-level fns or consts.check(typechecker) handles them correctly.Reproducer
$ affinescript check pn.affine Type checking passed $ affinescript compile pn.affine Code generation error: (Codegen.UnboundVariable "inputSuffix") affinescript: Code generation errorDiagnosis
The typechecker resolves
inputSuffixcorrectly (checkpasses), so the AST has the right cross-reference. The codegen phase has its own name resolution and fails to look upinputSuffixwhen generating code forwithInput's body — top-levelconsts aren't being threaded into the codegen environment alongsidefnbindings.bin/main.mlandlib/codegen.ml(or wherever the codegen lives) likely walkfn_decldeclarations only, skippingconst_decl. Adding consts to the codegen environment is the likely fix.Why this matters now
Real idaptik translation hits this immediately. Modules like
PortNames(well-known string constants used across the codebase),AssetPaths(resource locations),PortBindings(configuration), and many more, are precisely the shape of "a few module-level constants + a few helper fns that reference them". They typecheck cleanly but cannot be compiled to wasm.Cross-reference
[T]array/list shorthand in user source (closes #40) #67 (parser[T]) is independent of this issue; both are needed for end-to-end Mode A migration of idaptik.migration/shared/PortNames.affineis the test case (typechecks clean, compile fails with the message above).