Fix env-merge for Dict/Nil args + add adapter-html.sx primitives
sx_runtime.ml: unwrap_env now accepts Dict and Nil (converts to Env), fixing env-merge when adapter-html.sx passes dict-as-env. sx_server.ml + run_tests.ml: env-merge bindings use Sx_runtime.env_merge (which handles Dict/Nil) instead of requiring strict Env pattern match. sx_primitives.ml: Added scope stack (scope-push!/pop!/peek/emit!, emitted), type predicates (lambda?/island?/component?/macro?), component accessors (closure/name/params/body/has-children?), lambda accessors, for-each-indexed, empty-dict?, make-raw-html, raw-html-content, is-else-clause?. 8 OCaml render tests still fail (env propagation in render-lambda-html) — same adapter code works in JS and in production via Python bridge. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -208,7 +208,7 @@ let make_test_env () =
|
||||
|
||||
bind "env-merge" (fun args ->
|
||||
match args with
|
||||
| [Env a; Env b] -> Env (Sx_types.env_merge a b)
|
||||
| [a; b] -> Sx_runtime.env_merge a b
|
||||
| _ -> raise (Eval_error "env-merge: expected 2 envs"));
|
||||
|
||||
(* --- Equality --- *)
|
||||
@@ -280,6 +280,11 @@ let make_test_env () =
|
||||
bind "eval-expr" (fun args ->
|
||||
match args with
|
||||
| [expr; Env e] -> eval_expr expr (Env e)
|
||||
| [expr; Dict d] ->
|
||||
(* Dict used as env — wrap it *)
|
||||
let e = Sx_types.make_env () in
|
||||
Hashtbl.iter (fun k v -> ignore (Sx_types.env_bind e k v)) d;
|
||||
eval_expr expr (Env e)
|
||||
| [expr] -> eval_expr expr (Env env)
|
||||
| _ -> raise (Eval_error "eval-expr: expected (expr env)"));
|
||||
bind "scope-push!" (fun args ->
|
||||
|
||||
@@ -824,7 +824,7 @@ let make_server_env () =
|
||||
|
||||
bind "env-merge" (fun args ->
|
||||
match args with
|
||||
| [Env a; Env b] -> Env (env_merge a b)
|
||||
| [a; b] -> Sx_runtime.env_merge a b
|
||||
| _ -> raise (Eval_error "env-merge: expected 2 envs"));
|
||||
|
||||
(* Strict mode state *)
|
||||
|
||||
@@ -242,6 +242,14 @@ let type_of v = String (Sx_types.type_of v)
|
||||
The transpiled CEK machine stores envs in dicts as Env values. *)
|
||||
let unwrap_env = function
|
||||
| Env e -> e
|
||||
| Dict d ->
|
||||
(* Dict used as env — wrap it. Needed by adapter-html.sx which
|
||||
passes dicts as env args (e.g. empty {} as caller env). *)
|
||||
let e = Sx_types.make_env () in
|
||||
Hashtbl.iter (fun k v -> ignore (Sx_types.env_bind e k v)) d;
|
||||
e
|
||||
| Nil ->
|
||||
Sx_types.make_env ()
|
||||
| v -> raise (Eval_error ("Expected env, got " ^ Sx_types.type_of v))
|
||||
|
||||
let env_has e name = Bool (Sx_types.env_has (unwrap_env e) (value_to_str name))
|
||||
|
||||
Reference in New Issue
Block a user