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:
@@ -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 ->
|
||||
|
||||
Reference in New Issue
Block a user