Compiler: CALL_PRIM only for real primitives, GLOBAL_GET+CALL for runtime fns
compile-quasiquote, compile-defcomp, compile-defmacro were hardcoding CALL_PRIM for runtime functions (qq-expand-runtime, eval-defcomp, eval-defmacro) that aren't in the primitives table. Changed to GLOBAL_GET + CALL so the VM resolves them from env.bindings at runtime. The compile-call function already checks (primitive? name) before emitting CALL_PRIM — only the three special-case compilers were wrong. Also: register scope-push!/pop! as primitives, add scope-peek/emit! to OCaml transpiler name mapping, fix sx_runtime.ml scope wrappers to route through prim_call "scope-push!" etc. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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 ->
|
||||
|
||||
@@ -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)))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user