Step 10d: fix scope form compilation for non-keyword args

compile-expr args instead of keyword-name — handles (context "name"),
(context var), and (context :name) uniformly. Fixes freeze.sx .sxbc
compilation (was failing with "keyword-name: expected keyword").

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 13:28:17 +00:00
parent 2cf4c73ab3
commit a74c983615
6 changed files with 1882 additions and 1314 deletions

View File

@@ -315,19 +315,27 @@
(compile-provide em args scope tail?)
(= name "context")
(do
(emit-const em (keyword-name (first args)))
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "context"))
(emit-byte em 1))
(compile-expr em (first args) scope false)
(if
(> (len args) 1)
(do
(compile-expr em (nth args 1) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "context"))
(emit-byte em 2))
(do
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "context"))
(emit-byte em 1))))
(= name "peek")
(do
(emit-const em (keyword-name (first args)))
(compile-expr em (first args) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-peek"))
(emit-byte em 1))
(= name "provide!")
(do
(emit-const em (keyword-name (first args)))
(compile-expr em (first args) scope false)
(compile-expr em (nth args 1) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "provide-set!"))
@@ -340,14 +348,14 @@
(emit-byte em 1))
(= name "emit!")
(do
(emit-const em (keyword-name (first args)))
(compile-expr em (first args) scope false)
(compile-expr em (nth args 1) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-emit!"))
(emit-byte em 2))
(= name "emitted")
(do
(emit-const em (keyword-name (first args)))
(compile-expr em (first args) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-emitted"))
(emit-byte em 1))
@@ -986,7 +994,14 @@
(fn
(em args scope tail?)
(let
((name (keyword-name (first args)))
((first-arg (first args))
(name
(cond
(= (type-of first-arg) "keyword")
(keyword-name first-arg)
(= (type-of first-arg) "string")
first-arg
:else (symbol-name first-arg)))
(val-expr (nth args 1))
(body (slice args 2))
(name-idx (pool-add (get em "pool") name)))

View File

@@ -303,6 +303,62 @@
(compile-letrec em args scope tail?)
(= name "match")
(compile-match em args scope tail?)
(= name "guard")
(compile-guard em args scope tail?)
(= name "raise")
(do
(compile-expr em (first args) scope false)
(emit-op em 37))
(= name "scope")
(compile-scope em args scope tail?)
(= name "provide")
(compile-provide em args scope tail?)
(= name "context")
(do
(compile-expr em (first args) scope false)
(if
(> (len args) 1)
(do
(compile-expr em (nth args 1) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "context"))
(emit-byte em 2))
(do
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "context"))
(emit-byte em 1))))
(= name "peek")
(do
(compile-expr em (first args) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-peek"))
(emit-byte em 1))
(= name "provide!")
(do
(compile-expr em (first args) scope false)
(compile-expr em (nth args 1) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "provide-set!"))
(emit-byte em 2))
(= name "bind")
(do
(compile-expr em (first args) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "bind"))
(emit-byte em 1))
(= name "emit!")
(do
(compile-expr em (first args) scope false)
(compile-expr em (nth args 1) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-emit!"))
(emit-byte em 2))
(= name "emitted")
(do
(compile-expr em (first args) scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-emitted"))
(emit-byte em 1))
(= name "perform")
(let
()
@@ -455,8 +511,8 @@
(args)
(let
((first-arg (first args)))
(if (dict? first-arg)
;; Variant 2: (let-match {:k v} expr body...)
(if
(dict? first-arg)
(let
((pattern first-arg)
(expr (nth args 1))
@@ -465,28 +521,36 @@
(bindings (list)))
(append! bindings (list src-sym expr))
(for-each
(fn (k)
(append! bindings
(list (get pattern k)
(fn
(k)
(append!
bindings
(list
(get pattern k)
(list (make-symbol "get") src-sym (str k)))))
(keys pattern))
(cons bindings body))
;; Variant 1: (let-match name expr {:k v} body...)
(let
((name-sym first-arg)
(expr (nth args 1))
(pattern (nth args 2))
(body (slice args 3))
(src-sym (if (= (str name-sym) "_")
(make-symbol "__lm_tmp")
name-sym))
(src-sym
(if
(= (str name-sym) "_")
(make-symbol "__lm_tmp")
name-sym))
(bindings (list)))
(append! bindings (list src-sym expr))
(when (dict? pattern)
(when
(dict? pattern)
(for-each
(fn (k)
(append! bindings
(list (get pattern k)
(fn
(k)
(append!
bindings
(list
(get pattern k)
(list (make-symbol "get") src-sym (str k)))))
(keys pattern)))
(cons bindings body))))))
@@ -925,4 +989,129 @@
{:constants (get (get em "pool") "entries") :bytecode (get em "bytecode")}))))) ;; end define-library
;; Re-export to global namespace for backward compatibility
(define
compile-provide
(fn
(em args scope tail?)
(let
((first-arg (first args))
(name
(cond
(= (type-of first-arg) "keyword")
(keyword-name first-arg)
(= (type-of first-arg) "string")
first-arg
:else (symbol-name first-arg)))
(val-expr (nth args 1))
(body (slice args 2))
(name-idx (pool-add (get em "pool") name)))
(emit-op em 1)
(emit-u16 em name-idx)
(compile-expr em val-expr scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-push!"))
(emit-byte em 2)
(emit-op em 5)
(if (empty? body) (emit-op em 2) (compile-begin em body scope false))
(emit-op em 1)
(emit-u16 em name-idx)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-pop!"))
(emit-byte em 1)
(emit-op em 5))))
(define
compile-scope
(fn
(em args scope tail?)
(let
((first-arg (first args))
(name
(if
(= (type-of first-arg) "keyword")
(keyword-name first-arg)
(symbol-name first-arg)))
(rest-args (rest args))
(name-idx (pool-add (get em "pool") name)))
(if
(and
(>= (len rest-args) 2)
(= (type-of (first rest-args)) "keyword")
(= (keyword-name (first rest-args)) "value"))
(let
((val-expr (nth rest-args 1)) (body (slice rest-args 2)))
(emit-op em 1)
(emit-u16 em name-idx)
(compile-expr em val-expr scope false)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-push!"))
(emit-byte em 2)
(emit-op em 5)
(if
(empty? body)
(emit-op em 2)
(compile-begin em body scope false))
(emit-op em 1)
(emit-u16 em name-idx)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-pop!"))
(emit-byte em 1)
(emit-op em 5))
(let
((body rest-args))
(emit-op em 1)
(emit-u16 em name-idx)
(emit-op em 2)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-push!"))
(emit-byte em 2)
(emit-op em 5)
(if
(empty? body)
(emit-op em 2)
(compile-begin em body scope false))
(emit-op em 1)
(emit-u16 em name-idx)
(emit-op em 52)
(emit-u16 em (pool-add (get em "pool") "scope-pop!"))
(emit-byte em 1)
(emit-op em 5))))))
(define
compile-guard-clauses
(fn
(em clauses scope var-slot tail?)
(if
(empty? clauses)
(do (emit-op em 16) (emit-byte em var-slot) (emit-op em 37))
(let
((clause (first clauses))
(rest-clauses (rest clauses))
(test (first clause))
(body (rest clause)))
(if
(or
(and
(= (type-of test) "keyword")
(= (keyword-name test) "else"))
(= test true))
(compile-begin em body scope tail?)
(do
(compile-expr em test scope false)
(emit-op em 33)
(let
((skip (current-offset em)))
(emit-i16 em 0)
(compile-begin em body scope tail?)
(emit-op em 32)
(let
((end-jump (current-offset em)))
(emit-i16 em 0)
(patch-i16 em skip (- (current-offset em) (+ skip 2)))
(compile-guard-clauses em rest-clauses scope var-slot tail?)
(patch-i16
em
end-jump
(- (current-offset em) (+ end-jump 2)))))))))))
(import (sx compiler))

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,3 @@
(sxbc 1 "050ab6181dc93341"
(code
:constants ("freeze-registry" "dict" "freeze-signal" {:upvalue-count 0 :arity 2 :constants ("context" "sx-freeze-scope" "get" "freeze-registry" "list" "append!" "dict" "name" "signal" "dict-set!") :bytecode (1 1 0 2 52 0 0 2 17 2 16 2 33 55 0 20 3 0 16 2 52 2 0 2 6 34 5 0 5 52 4 0 0 17 3 16 3 1 7 0 16 0 1 8 0 16 1 52 6 0 4 52 5 0 2 5 20 3 0 16 2 16 3 52 9 0 3 32 1 0 2 50)} "freeze-scope" {:upvalue-count 0 :arity 2 :constants ("scope-push!" "sx-freeze-scope" "dict-set!" "freeze-registry" "list" "cek-call" "scope-pop!") :bytecode (1 1 0 16 0 52 0 0 2 5 20 3 0 16 0 52 4 0 0 52 2 0 3 5 16 1 2 52 5 0 2 5 1 1 0 52 6 0 1 5 2 50)} "cek-freeze-scope" {:upvalue-count 0 :arity 1 :constants ("get" "freeze-registry" "list" "dict" "for-each" {:upvalue-count 1 :arity 1 :constants ("dict-set!" "get" "name" "signal-value" "signal") :bytecode (18 0 16 0 1 2 0 52 1 0 2 20 3 0 16 0 1 4 0 52 1 0 2 48 1 52 0 0 3 50)} "name" "signals") :bytecode (20 1 0 16 0 52 0 0 2 6 34 5 0 5 52 2 0 0 17 1 52 3 0 0 17 2 51 5 0 1 2 16 1 52 4 0 2 5 1 6 0 16 0 1 7 0 16 2 52 3 0 4 50)} "cek-freeze-all" {:upvalue-count 0 :arity 0 :constants ("map" {:upvalue-count 0 :arity 1 :constants ("cek-freeze-scope") :bytecode (20 0 0 16 0 49 1 50)} "keys" "freeze-registry") :bytecode (51 1 0 20 3 0 52 2 0 1 52 0 0 2 50)} "cek-thaw-scope" {:upvalue-count 0 :arity 2 :constants ("get" "freeze-registry" "list" "signals" "for-each" {:upvalue-count 1 :arity 1 :constants ("get" "name" "signal" "not" "nil?" "reset!") :bytecode (16 0 1 1 0 52 0 0 2 17 1 16 0 1 2 0 52 0 0 2 17 2 18 0 16 1 52 0 0 2 17 3 16 3 52 4 0 1 52 3 0 1 33 12 0 20 5 0 16 2 16 3 49 2 32 1 0 2 50)}) :bytecode (20 1 0 16 0 52 0 0 2 6 34 5 0 5 52 2 0 0 17 2 16 1 1 3 0 52 0 0 2 17 3 16 3 33 14 0 51 5 0 1 3 16 2 52 4 0 2 32 1 0 2 50)} "cek-thaw-all" {:upvalue-count 0 :arity 1 :constants ("for-each" {:upvalue-count 0 :arity 1 :constants ("cek-thaw-scope" "get" "name") :bytecode (20 0 0 16 0 1 2 0 52 1 0 2 16 0 49 2 50)}) :bytecode (51 1 0 16 0 52 0 0 2 50)} "freeze-to-sx" {:upvalue-count 0 :arity 1 :constants ("sx-serialize" "cek-freeze-scope") :bytecode (20 1 0 16 0 48 1 52 0 0 1 50)} "thaw-from-sx" {:upvalue-count 0 :arity 1 :constants ("sx-parse" "not" "empty?" "first" "cek-thaw-scope" "get" "name") :bytecode (20 0 0 16 0 48 1 17 1 16 1 52 2 0 1 52 1 0 1 33 27 0 16 1 52 3 0 1 17 2 20 4 0 16 2 1 6 0 52 5 0 2 16 2 49 2 32 1 0 2 50)} {:library (sx freeze) :op "import"}) :bytecode (52 1 0 0 128 0 0 5 51 3 0 128 2 0 5 51 5 0 128 4 0 5 51 7 0 128 6 0 5 51 9 0 128 8 0 5 51 11 0 128 10 0 5 51 13 0 128 12 0 5 51 15 0 128 14 0 5 51 17 0 128 16 0 5 1 18 0 112 50)))
:constants ("freeze-registry" "dict" "freeze-signal" {:upvalue-count 0 :arity 2 :constants ("sx-freeze-scope" "context" "get" "freeze-registry" "list" "append!" "dict" "name" "signal" "dict-set!") :bytecode (1 0 0 2 52 1 0 2 17 2 16 2 33 55 0 20 3 0 16 2 52 2 0 2 6 34 5 0 5 52 4 0 0 17 3 16 3 1 7 0 16 0 1 8 0 16 1 52 6 0 4 52 5 0 2 5 20 3 0 16 2 16 3 52 9 0 3 32 1 0 2 50)} "freeze-scope" {:upvalue-count 0 :arity 2 :constants ("scope-push!" "sx-freeze-scope" "dict-set!" "freeze-registry" "list" "cek-call" "scope-pop!") :bytecode (1 1 0 16 0 52 0 0 2 5 20 3 0 16 0 52 4 0 0 52 2 0 3 5 16 1 2 52 5 0 2 5 1 1 0 52 6 0 1 5 2 50)} "cek-freeze-scope" {:upvalue-count 0 :arity 1 :constants ("get" "freeze-registry" "list" "dict" "for-each" {:upvalue-count 1 :arity 1 :constants ("dict-set!" "get" "name" "signal-value" "signal") :bytecode (18 0 16 0 1 2 0 52 1 0 2 20 3 0 16 0 1 4 0 52 1 0 2 48 1 52 0 0 3 50)} "name" "signals") :bytecode (20 1 0 16 0 52 0 0 2 6 34 5 0 5 52 2 0 0 17 1 52 3 0 0 17 2 51 5 0 1 2 16 1 52 4 0 2 5 1 6 0 16 0 1 7 0 16 2 52 3 0 4 50)} "cek-freeze-all" {:upvalue-count 0 :arity 0 :constants ("map" {:upvalue-count 0 :arity 1 :constants ("cek-freeze-scope") :bytecode (20 0 0 16 0 49 1 50)} "keys" "freeze-registry") :bytecode (51 1 0 20 3 0 52 2 0 1 52 0 0 2 50)} "cek-thaw-scope" {:upvalue-count 0 :arity 2 :constants ("get" "freeze-registry" "list" "signals" "for-each" {:upvalue-count 1 :arity 1 :constants ("get" "name" "signal" "not" "nil?" "reset!") :bytecode (16 0 1 1 0 52 0 0 2 17 1 16 0 1 2 0 52 0 0 2 17 2 18 0 16 1 52 0 0 2 17 3 16 3 52 4 0 1 52 3 0 1 33 12 0 20 5 0 16 2 16 3 49 2 32 1 0 2 50)}) :bytecode (20 1 0 16 0 52 0 0 2 6 34 5 0 5 52 2 0 0 17 2 16 1 1 3 0 52 0 0 2 17 3 16 3 33 14 0 51 5 0 1 3 16 2 52 4 0 2 32 1 0 2 50)} "cek-thaw-all" {:upvalue-count 0 :arity 1 :constants ("for-each" {:upvalue-count 0 :arity 1 :constants ("cek-thaw-scope" "get" "name") :bytecode (20 0 0 16 0 1 2 0 52 1 0 2 16 0 49 2 50)}) :bytecode (51 1 0 16 0 52 0 0 2 50)} "freeze-to-sx" {:upvalue-count 0 :arity 1 :constants ("sx-serialize" "cek-freeze-scope") :bytecode (20 1 0 16 0 48 1 52 0 0 1 50)} "thaw-from-sx" {:upvalue-count 0 :arity 1 :constants ("sx-parse" "not" "empty?" "first" "cek-thaw-scope" "get" "name") :bytecode (20 0 0 16 0 48 1 17 1 16 1 52 2 0 1 52 1 0 1 33 27 0 16 1 52 3 0 1 17 2 20 4 0 16 2 1 6 0 52 5 0 2 16 2 49 2 32 1 0 2 50)} {:library (sx freeze) :op "import"}) :bytecode (52 1 0 0 128 0 0 5 51 3 0 128 2 0 5 51 5 0 128 4 0 5 51 7 0 128 6 0 5 51 9 0 128 8 0 5 51 11 0 128 10 0 5 51 13 0 128 12 0 5 51 15 0 128 14 0 5 51 17 0 128 16 0 5 1 18 0 112 50)))

File diff suppressed because one or more lines are too long

View File

@@ -1792,7 +1792,7 @@
blake2_js_for_wasm_create: blake2_js_for_wasm_create};
}
(globalThis))
({"link":[["runtime-0db9b496",0],["prelude-d7e4b000",0],["stdlib-23ce0836",[]],["sx-7ca4d3ad",[2]],["jsoo_runtime-f96b44a8",[2]],["js_of_ocaml-651f6707",[2,4]],["dune__exe__Sx_browser-bec4a5c4",[2,3,5]],["std_exit-10fb8830",[2]],["start-f5d3f095",0]],"generated":(b=>{var
({"link":[["runtime-0db9b496",0],["prelude-d7e4b000",0],["stdlib-23ce0836",[]],["sx-3af91abd",[2]],["jsoo_runtime-f96b44a8",[2]],["js_of_ocaml-651f6707",[2,4]],["dune__exe__Sx_browser-19f4e198",[2,3,5]],["std_exit-10fb8830",[2]],["start-f5d3f095",0]],"generated":(b=>{var
c=b,a=b?.module?.export||b;return{"env":{"caml_ba_kind_of_typed_array":()=>{throw new
Error("caml_ba_kind_of_typed_array not implemented")},"caml_exn_with_js_backtrace":()=>{throw new
Error("caml_exn_with_js_backtrace not implemented")},"caml_int64_create_lo_mi_hi":()=>{throw new