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:
2026-03-23 10:02:17 +00:00
parent 09feb51762
commit e12b2eab6b
2 changed files with 25 additions and 12 deletions

View File

@@ -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)))
;; --------------------------------------------------------------------------