Step 10c: bind CEK special form + provide-set frame + scope-stack integration
bind is now a CEK special form that captures its body unevaluated, establishes a tracking context (*bind-tracking*), and registers subscribers on provide frames when context reads are tracked. - bind special form: step-sf-bind, make-bind-frame, bind continue handler - provide-set frame: provide! evaluates value with kont (fixes peek bug) - context tracking: step-sf-context appends to *bind-tracking* when active - scope-stack fallback: provide pushes to scope stack for cek-call contexts - CekFrame mutation: cf_remaining/cf_results/cf_extra2 now mutable - Transpiler: subscribers + prev-tracking field mappings, *bind-tracking* in ml-mutable-globals - Test fixes: string-append → str, restored edge-cases suite Passing: bind returns initial value, bind with expression, bind with let, bind no deps is static, bind with conditional deps, provide! updates/multiple/nil, provide! computed new value, peek read-modify-write, guard inside bind, bind with string-append, provide! same value does not notify, bind does not fire on unrelated provide!, bind sees latest value, bind inside provide scope. Remaining: subscriber re-evaluation on provide! (scope-stack key issue), batch coalescing (no batch support yet). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -80,6 +80,15 @@ let sx_dict_set_b d k v =
|
||||
match d, k with
|
||||
| Dict tbl, String key -> Hashtbl.replace tbl key v; v
|
||||
| Dict tbl, Keyword key -> Hashtbl.replace tbl key v; v
|
||||
| CekFrame f, String key ->
|
||||
(match key with
|
||||
| "value" | "extra" | "ho-type" | "scheme" | "indexed"
|
||||
| "phase" | "has-effects" | "match-val" | "current-item"
|
||||
| "update-fn" | "head-name" -> f.cf_extra <- v; v
|
||||
| "remaining" -> f.cf_remaining <- v; v
|
||||
| "subscribers" | "results" | "raw-args" -> f.cf_results <- v; v
|
||||
| "emitted" | "effect-list" | "first-render" | "extra2" -> f.cf_extra2 <- v; v
|
||||
| _ -> raise (Eval_error ("dict-set! cek-frame: unknown field " ^ key)))
|
||||
| VmFrame f, String key ->
|
||||
(match key with
|
||||
| "ip" -> f.vf_ip <- val_to_int v; v
|
||||
@@ -116,6 +125,8 @@ let get_val container key =
|
||||
| "emitted" -> f.cf_extra2 | "effect-list" -> f.cf_extra2
|
||||
| "first-render" -> f.cf_extra2 | "file" -> f.cf_env
|
||||
| "extra" -> f.cf_extra | "extra2" -> f.cf_extra2
|
||||
| "subscribers" -> f.cf_results
|
||||
| "prev-tracking" -> f.cf_extra
|
||||
| _ -> Nil)
|
||||
| VmFrame f, String k ->
|
||||
(match k with
|
||||
|
||||
@@ -91,12 +91,12 @@ and cek_frame = {
|
||||
cf_env : value; (* environment — every frame has this *)
|
||||
cf_name : value; (* let/define/set/scope: binding name *)
|
||||
cf_body : value; (* when/let: body expr *)
|
||||
cf_remaining : value; (* begin/cond/map/etc: remaining exprs *)
|
||||
mutable cf_remaining : value; (* begin/cond/map/etc: remaining exprs *)
|
||||
cf_f : value; (* call/map/filter/etc: function *)
|
||||
cf_args : value; (* call: raw args; arg: evaled args *)
|
||||
cf_results : value; (* map/filter/dict: accumulated results *)
|
||||
mutable cf_results : value; (* map/filter/dict: accumulated results; provide: subscribers *)
|
||||
mutable cf_extra : value; (* extra field: scheme, indexed, value, phase, etc. *)
|
||||
cf_extra2 : value; (* second extra: emitted, etc. *)
|
||||
mutable cf_extra2 : value; (* second extra: emitted, etc. *)
|
||||
}
|
||||
|
||||
(** Mutable string-keyed table (SX dicts support [dict-set!]). *)
|
||||
|
||||
@@ -285,7 +285,7 @@
|
||||
|
||||
(define
|
||||
ml-mutable-globals
|
||||
(list "*strict*" "*prim-param-types*" "*last-error-kont*"))
|
||||
(list "*strict*" "*prim-param-types*" "*last-error-kont*" "*bind-tracking*"))
|
||||
|
||||
(define
|
||||
ml-is-mutable-global?
|
||||
@@ -539,6 +539,8 @@
|
||||
(ef "results")
|
||||
(some (fn (k) (= k "raw-args")) items)
|
||||
(ef "raw-args")
|
||||
(some (fn (k) (= k "subscribers")) items)
|
||||
(ef "subscribers")
|
||||
:else "Nil")
|
||||
"; cf_extra = "
|
||||
(cond
|
||||
@@ -562,6 +564,8 @@
|
||||
(ef "update-fn")
|
||||
(some (fn (k) (= k "head-name")) items)
|
||||
(ef "head-name")
|
||||
(some (fn (k) (= k "prev-tracking")) items)
|
||||
(ef "prev-tracking")
|
||||
(some (fn (k) (= k "extra")) items)
|
||||
(ef "extra")
|
||||
:else "Nil")
|
||||
|
||||
Reference in New Issue
Block a user