Skip to content

Commit 3a31737

Browse files
hyperpolymathclaude
andcommitted
feat: Add WasmGC (typed WASM) codegen target
Implement the WebAssembly GC proposal as a second compilation target alongside the existing WASM 1.0 linear memory backend. The --wasm-gc flag on the compile subcommand activates the new pipeline. Three new modules: - wasm_gc.ml: GC IR types (heap types, ref types, struct/array defs, GC instructions with 0xFB prefix opcodes) - wasm_gc_encode.ml: binary encoder for GC modules (type section with struct 0x5F / array 0x5E markers, ref types 0x63/0x64) - codegen_gc.ml: GC codegen mapping AffineScript types to GC types (records→struct.new, arrays→array.new_fixed, field access→struct.get, affine values→non-null GcRef, shared→GcAnyref) Key design: AffineScript affine types map to non-null WasmGC refs (GcRef), giving compile-time null safety enforced by the WASM type validator. No bump allocator or linear memory needed — the runtime GC handles collection. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent fb2bc07 commit 3a31737

6 files changed

Lines changed: 1822 additions & 7 deletions

File tree

.machine_readable/6a2/STATE.a2ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[metadata]
55
project = "affinescript"
66
version = "0.1.0"
7-
last-updated = "2026-04-03"
7+
last-updated = "2026-04-04"
88
status = "active"
99

1010
[project-context]
@@ -20,6 +20,7 @@ type-checker = "99% (Never/bottom type handling fixed; block divergence propagat
2020
borrow-checker = "95%"
2121
interpreter = "95%"
2222
wasm-codegen = "92% (real-world game compiles: airborne-submarine-squadron/src/main.as → 8KB WASM)"
23+
wasm-gc-codegen = "70% (WasmGC proposal target: struct.new/struct.get/array.new_fixed/array.get; --wasm-gc CLI flag)"
2324
julia-codegen = "exists"
2425
lsp-phase-a = "complete"
2526
lsp-phase-b = "in-progress"
@@ -29,6 +30,6 @@ stdlib = "95% (5 stubs remain as extern builtins)"
2930

3031
[stats]
3132
compiler-loc = 12424
32-
compiler-modules = 35
33+
compiler-modules = 38
3334
lsp-files = 5
3435
test-files = 54

bin/main.ml

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,9 @@ let repl_cmd_fn () =
229229
`Error (false, "REPL not yet implemented")
230230

231231
(** Compile a file. With [--json], emits diagnostics for any
232-
compilation errors. *)
233-
let compile_file json path output =
232+
compilation errors. With [--wasm-gc], targets the WebAssembly GC
233+
proposal instead of WASM 1.0 linear memory. *)
234+
let compile_file json wasm_gc path output =
234235
if json then begin
235236
let diags = ref [] in
236237
let add d = diags := d :: !diags in
@@ -257,6 +258,15 @@ let compile_file json path output =
257258
let oc = open_out output in
258259
output_string oc julia_code;
259260
close_out oc
261+
end else if wasm_gc then begin
262+
match Affinescript.Codegen_gc.generate_gc_module prog with
263+
| Error e ->
264+
add { severity = Error; code = "E0802";
265+
message = Printf.sprintf "WASM GC codegen error: %s"
266+
(Affinescript.Codegen_gc.format_codegen_error e);
267+
span = Affinescript.Span.dummy; help = None; labels = [] }
268+
| Ok gc_module ->
269+
Affinescript.Wasm_gc_encode.write_gc_module_to_file output gc_module
260270
end else begin
261271
let optimized_prog = Affinescript.Opt.fold_constants_program prog in
262272
match Affinescript.Codegen.generate_module optimized_prog with
@@ -304,6 +314,16 @@ let compile_file json path output =
304314
close_out oc;
305315
Format.printf "Compiled %s -> %s (Julia)@." path output;
306316
`Ok ())
317+
else if wasm_gc then
318+
(match Affinescript.Codegen_gc.generate_gc_module prog with
319+
| Error e ->
320+
Format.eprintf "@[<v>%s@]@."
321+
(Affinescript.Codegen_gc.format_codegen_error e);
322+
`Error (false, "WASM GC codegen error")
323+
| Ok gc_module ->
324+
Affinescript.Wasm_gc_encode.write_gc_module_to_file output gc_module;
325+
Format.printf "Compiled %s -> %s (WASM GC)@." path output;
326+
`Ok ())
307327
else
308328
let optimized_prog = Affinescript.Opt.fold_constants_program prog in
309329
(match Affinescript.Codegen.generate_module optimized_prog with
@@ -407,6 +427,12 @@ let path_arg =
407427
let output_arg =
408428
Arg.(value & opt string "out.wasm" & info ["o"; "output"] ~docv:"FILE" ~doc:"Output file")
409429

430+
let wasm_gc_arg =
431+
Arg.(value & flag & info ["wasm-gc"]
432+
~doc:"Target the WebAssembly GC proposal (struct/array types, no linear memory). \
433+
Requires a runtime that supports the GC proposal: V8/Chrome ≥ 119, \
434+
SpiderMonkey/Firefox ≥ 120, or Wasmtime with --wasm-features gc.")
435+
410436
let lex_cmd =
411437
let doc = "Lex a file and print tokens" in
412438
let info = Cmd.info "lex" ~doc in
@@ -433,9 +459,9 @@ let repl_cmd =
433459
Cmd.v info Term.(ret (const repl_cmd_fn $ const ()))
434460

435461
let compile_cmd =
436-
let doc = "Compile a file to WebAssembly or Julia" in
462+
let doc = "Compile a file to WebAssembly (1.0 or GC proposal) or Julia" in
437463
let info = Cmd.info "compile" ~doc in
438-
Cmd.v info Term.(ret (const compile_file $ json_arg $ path_arg $ output_arg))
464+
Cmd.v info Term.(ret (const compile_file $ json_arg $ wasm_gc_arg $ path_arg $ output_arg))
439465

440466
let fmt_cmd =
441467
let doc = "Format a file" in

0 commit comments

Comments
 (0)