Step 10c: Vector type + unified reactive model test spec (34 tests)

- Vector of value array added to sx_types.ml (prior commit)
- Vector primitives in sx_primitives.ml (make-vector, vector-ref,
  vector-set!, vector-length, vector->list, list->vector)
- R7RS vector tests
- test-unified-reactive.sx: 34 tests specifying the unified reactive
  model (provide/context/peek/bind replacing signal/deref split).
  All 34 currently fail — implementation next.
- WASM binary rebuilt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 01:27:27 +00:00
parent b8f389ac9b
commit b3e9ebee1d
4 changed files with 704 additions and 1 deletions

View File

@@ -1301,6 +1301,83 @@ let () =
Nil
| _ -> Nil);
(* --- Unified reactive model (Step 10c) ---
provide wraps value in a Signal (reactive cell).
context unwraps the signal + registers in tracking context.
peek unwraps without tracking.
provide! mutates the signal and notifies subscribers. *)
let _tracking_active : bool ref = ref false in
let _tracking_deps : value list ref = ref [] in
register "provide-reactive!" (fun args ->
match args with
| [String name; value] ->
let sig' = { s_value = value; s_subscribers = []; s_deps = [] } in
let stack = try Hashtbl.find _scope_stacks name with Not_found -> [] in
Hashtbl.replace _scope_stacks name (Signal sig' :: stack); Nil
| _ -> raise (Eval_error "provide-reactive!: expected (name value)"));
register "provide-pop-reactive!" (fun args ->
match args with
| [String name] ->
let stack = try Hashtbl.find _scope_stacks name with Not_found -> [] in
(match stack with _ :: rest -> Hashtbl.replace _scope_stacks name rest | [] -> ()); Nil
| _ -> Nil);
register "provide-set!" (fun args ->
match args with
| [String name; new_value] ->
let stack = try Hashtbl.find _scope_stacks name with Not_found -> [] in
(match stack with
| Signal sig' :: _ ->
sig'.s_value <- new_value;
List.iter (fun sub -> sub ()) sig'.s_subscribers;
Nil
| _ -> raise (Eval_error (Printf.sprintf
"provide-set!: '%s' is not a reactive provide" name)))
| _ -> raise (Eval_error "provide-set!: expected (name new-value)"));
register "peek" (fun args ->
match args with
| (String name) :: _ ->
let stack = try Hashtbl.find _scope_stacks name with Not_found -> [] in
(match stack with
| Signal sig' :: _ -> sig'.s_value
| v :: _ -> v
| [] -> Nil)
| _ -> raise (Eval_error "peek: expected (name)"));
register "tracking-start!" (fun _args ->
_tracking_active := true; _tracking_deps := []; Nil);
register "tracking-stop!" (fun _args ->
_tracking_active := false;
let deps = !_tracking_deps in
_tracking_deps := [];
List deps);
register "tracking-active?" (fun _args ->
Bool !_tracking_active);
(* Override context to be tracking-aware *)
Hashtbl.remove primitives "context";
register "context" (fun args ->
match args with
| (String name) :: rest ->
let stack = try Hashtbl.find _scope_stacks name with Not_found -> [] in
(match stack with
| Signal sig' :: _ ->
(* Register in tracking context if active *)
if !_tracking_active then begin
if not (List.memq (Signal sig') !_tracking_deps) then
_tracking_deps := Signal sig' :: !_tracking_deps
end;
sig'.s_value
| v :: _ -> v
| [] -> (match rest with default_val :: _ -> default_val | [] -> Nil))
| _ -> Nil);
(* --- Emit / emitted --- *)
register "scope-emit!" (fun args ->