Skip to content

Commit ce324fa

Browse files
hyperpolymathclaude
andcommitted
feat(codegen): export pub fn to WASM (both codegen.ml + codegen_gc.ml)
The AST has carried `fd_vis : visibility` since forever; the parser has accepted `pub fn` since forever; the `PUB` token has been wired through lexer + parser_driver. Only the two WASM backends (codegen.ml:1724 and codegen_gc.ml:1110) were ignoring `fd_vis` and instead consulting a hardcoded name allowlist: ["main"; "init_state"; "step_state"; "get_state"; "mission_active"] This commit makes both backends honour `fd_vis = Public` as well. The game-hook allowlist is retained verbatim for backward compat with pre-`pub` programs (IDApTIK CharacterSelect bridge et al.), so: - `pub fn foo() -> Bool` — exported (new) - `fn main() -> ()` — exported (backward compat) - `fn helper() -> Int` — not exported (unchanged) Verified via `/tmp/multi_pub_test.affine`: three `pub fn test_*` all appear in the WASM export list; a non-`pub` helper does not. Unblocks the `affinescript-deno-test` MVP's one-test-per-file constraint — the harness can now discover multiple `test_*` exports per file via `module.functionExports.filter(n => n.startsWith('test_'))`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1f7006e commit ce324fa

2 files changed

Lines changed: 14 additions & 5 deletions

File tree

lib/codegen.ml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,9 +1721,13 @@ let gen_decl (ctx : context) (decl : top_level) : context result =
17211721
let* (ctx_after_gen, func) = gen_function ctx_with_func_idx fd in
17221722
let func_with_type = { func with f_type = type_idx } in
17231723

1724-
(* Add export for main and control helpers *)
1725-
let export_names = ["main"; "init_state"; "step_state"; "get_state"; "mission_active"] in
1726-
let export = if List.mem fd.fd_name.name export_names then
1724+
(* Export function if marked `pub` OR if its name matches a reserved
1725+
game-loop hook (preserved for backward compatibility with the
1726+
IDApTIK CharacterSelect bridge and the pre-`pub` compiler behaviour). *)
1727+
let game_hook_names = ["main"; "init_state"; "step_state"; "get_state"; "mission_active"] in
1728+
let is_pub = (fd.fd_vis = Ast.Public) in
1729+
let is_game_hook = List.mem fd.fd_name.name game_hook_names in
1730+
let export = if is_pub || is_game_hook then
17271731
[{ e_name = fd.fd_name.name; e_desc = ExportFunc func_idx }]
17281732
else
17291733
[]

lib/codegen_gc.ml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,11 +1111,16 @@ let gen_gc_decl (ctx : gc_ctx) (decl : top_level) : gc_ctx cg_result =
11111111
} in
11121112
let* (ctx', func) = gen_gc_function ctx_with_idx fd in
11131113

1114-
let export_names =
1114+
(* Export function if marked `pub` OR if its name matches a reserved
1115+
game-loop hook (preserved for backward compatibility, mirroring
1116+
codegen.ml). *)
1117+
let game_hook_names =
11151118
["main"; "init_state"; "step_state"; "get_state"; "mission_active"]
11161119
in
1120+
let is_pub = (fd.fd_vis = Ast.Public) in
1121+
let is_game_hook = List.mem fd.fd_name.name game_hook_names in
11171122
let new_exports =
1118-
if List.mem fd.fd_name.name export_names then
1123+
if is_pub || is_game_hook then
11191124
[{ ge_name = fd.fd_name.name; ge_desc = GcExportFunc func_idx }]
11201125
else []
11211126
in

0 commit comments

Comments
 (0)