OCaml runtime: R7RS parameters, VM closure introspection, import suspension

- R7RS parameter primitives (make-parameter, parameter?, parameterize support)
- VM closure get_val introspection (vm-code, vm-upvalues, vm-name, vm-globals)
- Lazy list caching on vm_code for transpiled VM performance
- VM import suspension: check_io_suspension + resume_module for browser lazy loading
- 23 new R7RS tests (parameter-basic, parameterize-basic, syntax-rules-basic)
- Playwright bytecode-loading spec + WASM rebuild

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 18:48:51 +00:00
parent 2727577702
commit 4baed1853c
16 changed files with 692 additions and 178 deletions

View File

@@ -208,6 +208,8 @@ let () =
for i = 0 to Array.length a.r_fields - 1 do
if not (safe_eq a.r_fields.(i) b.r_fields.(i)) then eq := false
done; !eq)
(* Parameters: same UID = same parameter *)
| Parameter a, Parameter b -> a.pm_uid = b.pm_uid
(* Lambda/Component/Island/Signal/NativeFn: physical only *)
| _ -> false
in
@@ -732,6 +734,7 @@ let () =
String (Printf.sprintf "~%s" i.i_name)
| [Lambda _] -> String "<lambda>"
| [Record r] -> String (Printf.sprintf "#<%s>" r.r_type.rt_name)
| [Parameter p] -> String (Printf.sprintf "#<parameter %s>" p.pm_uid)
| [a] -> String (inspect a) (* used for dedup keys in compiler *)
| _ -> raise (Eval_error "serialize: 1 arg"));
register "make-symbol" (fun args ->
@@ -951,6 +954,39 @@ let () =
register "make-record-mutator" (fun args ->
match args with [idx] -> make_record_mutator idx
| _ -> raise (Eval_error "make-record-mutator: expected (index)"));
(* R7RS parameters — converter stored, applied by parameterize frame *)
register "make-parameter" (fun args ->
match args with
| [init] ->
let uid = !param_counter in
incr param_counter;
Parameter { pm_uid = "__param_" ^ string_of_int uid;
pm_default = init; pm_converter = None }
| [init; converter] ->
let uid = !param_counter in
incr param_counter;
(* Apply converter to init for NativeFn, store raw for Lambda *)
let converted = match converter with
| NativeFn (_, f) -> f [init]
| _ -> init (* Lambda converters applied via CEK at parameterize time *)
in
Parameter { pm_uid = "__param_" ^ string_of_int uid;
pm_default = converted; pm_converter = Some converter }
| _ -> raise (Eval_error "make-parameter: expected 1-2 args"));
register "parameter?" (fun args ->
match args with [Parameter _] -> Bool true | [_] -> Bool false
| _ -> Bool false);
register "parameter-uid" (fun args ->
match args with [Parameter p] -> String p.pm_uid
| _ -> raise (Eval_error "parameter-uid: expected parameter"));
register "parameter-default" (fun args ->
match args with [Parameter p] -> p.pm_default
| _ -> raise (Eval_error "parameter-default: expected parameter"));
register "parameter-converter" (fun args ->
match args with
| [Parameter p] -> (match p.pm_converter with Some c -> c | None -> Nil)
| _ -> raise (Eval_error "parameter-converter: expected parameter"));
register "is-else-clause?" (fun args ->
match args with
| [Keyword "else"] -> Bool true