diff --git a/hosts/ocaml/bin/sx_server.ml b/hosts/ocaml/bin/sx_server.ml index 85c16d5..f758702 100644 --- a/hosts/ocaml/bin/sx_server.ml +++ b/hosts/ocaml/bin/sx_server.ml @@ -435,6 +435,17 @@ let make_server_env () = | [], _ -> Nil) | _ -> Nil); + (* qq-expand-runtime — quasiquote expansion at runtime. + The bytecode compiler emits CALL_PRIM "qq-expand-runtime" for + backtick expressions. Expands the template with the calling env. *) + bind "qq-expand-runtime" (fun args -> + match args with + | [template] -> + (* qq_expand needs an env — use the kernel env *) + Sx_ref.qq_expand template (Env env) + | [template; Env e] -> Sx_ref.qq_expand template (Env e) + | _ -> Nil); + (* Evaluator bridge — aser calls these spec functions. Route to the OCaml CEK machine. *) bind "eval-expr" (fun args -> diff --git a/spec/compiler.sx b/spec/compiler.sx index fb13be9..cbc7533 100644 --- a/spec/compiler.sx +++ b/spec/compiler.sx @@ -584,28 +584,30 @@ (define compile-defcomp (fn (em args scope) - "Compile defcomp/defisland — delegates to runtime primitive." - ;; For now, quote the entire defcomp form and call the primitive - (emit-const em (concat (list (make-symbol "defcomp")) args)) + "Compile defcomp/defisland — delegates to runtime via GLOBAL_GET + CALL." (let ((name-idx (pool-add (get em "pool") "eval-defcomp"))) - (emit-op em 52) (emit-u16 em name-idx) (emit-byte em 1)) ;; CALL_PRIM - )) + (emit-op em 20) (emit-u16 em name-idx)) ;; GLOBAL_GET fn + (emit-const em (concat (list (make-symbol "defcomp")) args)) + (emit-op em 48) (emit-byte em 1))) ;; CALL 1 (define compile-defmacro (fn (em args scope) - "Compile defmacro — delegates to runtime." - (emit-const em (concat (list (make-symbol "defmacro")) args)) + "Compile defmacro — delegates to runtime via GLOBAL_GET + CALL." (let ((name-idx (pool-add (get em "pool") "eval-defmacro"))) - (emit-op em 52) (emit-u16 em name-idx) (emit-byte em 1)))) + (emit-op em 20) (emit-u16 em name-idx)) ;; GLOBAL_GET fn + (emit-const em (concat (list (make-symbol "defmacro")) args)) + (emit-op em 48) (emit-byte em 1))) (define compile-quasiquote (fn (em expr scope) - "Compile quasiquote — for now, quote the template and call qq-expand at runtime." - (emit-const em expr) ;; push template - ;; qq-expand is a runtime function — call it + "Compile quasiquote — look up qq-expand-runtime in globals and call it. + Uses GLOBAL_GET + CALL (not CALL_PRIM) since it's a runtime function." + ;; Stack: push fn first, then arg, then CALL 1 (let ((name-idx (pool-add (get em "pool") "qq-expand-runtime"))) - (emit-op em 52) (emit-u16 em name-idx) (emit-byte em 1)))) + (emit-op em 20) (emit-u16 em name-idx)) ;; GLOBAL_GET fn + (emit-const em expr) ;; push template + (emit-op em 48) (emit-byte em 1))) ;; --------------------------------------------------------------------------