Route syntax-quote, set!, var, ., new to interpreter
Compile-time implementation of syntax-quote proved too complex for the current emission pipeline (qualified symbol handling across both string and data-structure paths). These ops require runtime context (var lookup, field mutation, deftype construction) and are now correctly routed to the interpreter via the stateful? check in eval-string. Also fixed: - raw-form->janet handles namespace-qualified symbols correctly - emit-quote-str and emit-quote-expr use raw-form->janet consistently - Duplicate function definitions removed All 317 tests pass, 0 failures.
This commit is contained in:
parent
1de109f261
commit
4ca7c31e50
7 changed files with 254 additions and 44 deletions
|
|
@ -56,7 +56,9 @@
|
|||
nil)
|
||||
stateful? (or (= head-name "defmacro") (= head-name "ns")
|
||||
(= head-name "deftype") (= head-name "defmulti") (= head-name "defmethod")
|
||||
(= head-name "require") (= head-name "in-ns"))]
|
||||
(= head-name "require") (= head-name "in-ns")
|
||||
(= head-name "syntax-quote") (= head-name "set!")
|
||||
(= head-name "var") (= head-name ".") (= head-name "new"))]
|
||||
(if stateful?
|
||||
(eval-form ctx @{} form)
|
||||
(compile-and-eval form ctx)))
|
||||
|
|
|
|||
|
|
@ -234,6 +234,90 @@
|
|||
(++ loop-counter)
|
||||
name))
|
||||
|
||||
# ============================================================
|
||||
# Syntax-quote expansion
|
||||
# ============================================================
|
||||
|
||||
(defn- sq-list?
|
||||
"Check if form is a (unquote ...) or (unquote-splicing ...) call."
|
||||
[form]
|
||||
(and (array? form) (> (length form) 0)
|
||||
(struct? (first form)) (= :symbol ((first form) :jolt/type))
|
||||
(or (= "unquote" ((first form) :name))
|
||||
(= "unquote-splicing" ((first form) :name)))))
|
||||
|
||||
(defn- sq-has-unquote?
|
||||
"Check if any item in a collection is an unquote/unquote-splicing form."
|
||||
[items]
|
||||
(var found false) (var i 0)
|
||||
(while (and (< i (length items)) (not found))
|
||||
(if (sq-list? (in items i)) (set found true)) (++ i))
|
||||
found)
|
||||
|
||||
(defn- sq-resolve-sym
|
||||
"Qualify an unqualified symbol with the current namespace."
|
||||
[sym-s ctx]
|
||||
(if (and ctx (nil? (sym-s :ns)))
|
||||
{:jolt/type :symbol :ns (ctx-current-ns ctx) :name (sym-s :name)}
|
||||
sym-s))
|
||||
|
||||
(defn- syntax-quote-expand
|
||||
"Expand a syntax-quoted form into a plain Clojure form.
|
||||
Simple forms are wrapped in (quote ...). Forms with unquote produce
|
||||
(concat (list ...) ...) calls."
|
||||
[form ctx]
|
||||
(cond
|
||||
# unquote → just the inner expression
|
||||
(and (array? form) (> (length form) 0)
|
||||
(struct? (first form)) (= :symbol ((first form) :jolt/type))
|
||||
(= "unquote" ((first form) :name)))
|
||||
(in form 1)
|
||||
|
||||
# unquote-splicing → just the inner expression
|
||||
(and (array? form) (> (length form) 0)
|
||||
(struct? (first form)) (= :symbol ((first form) :jolt/type))
|
||||
(= "unquote-splicing" ((first form) :name)))
|
||||
(in form 1)
|
||||
|
||||
# Literals → (quote literal)
|
||||
(or (nil? form) (= true form) (= false form)
|
||||
(number? form) (string? form) (keyword? form))
|
||||
[{:jolt/type :symbol :ns nil :name "quote"} form]
|
||||
|
||||
# Symbols → (quote resolved-symbol)
|
||||
(and (struct? form) (= :symbol (form :jolt/type)))
|
||||
[{:jolt/type :symbol :ns nil :name "quote"} (sq-resolve-sym form ctx)]
|
||||
|
||||
# Lists/arrays with unquote → (concat (list ...) (list ...) ...)
|
||||
(array? form)
|
||||
(if (sq-has-unquote? form)
|
||||
(let [items (map |(syntax-quote-expand $ ctx) form)
|
||||
concat-args @[]]
|
||||
(each item items
|
||||
(array/push concat-args
|
||||
[{:jolt/type :symbol :ns nil :name "list"} item]))
|
||||
(if (> (length concat-args) 1)
|
||||
(tuple ;(array/insert concat-args 0
|
||||
{:jolt/type :symbol :ns nil :name "concat"}))
|
||||
(in concat-args 0)))
|
||||
[{:jolt/type :symbol :ns nil :name "quote"} form])
|
||||
|
||||
# Vectors → (vec (concat (list ...) ...))
|
||||
(tuple? form)
|
||||
(if (sq-has-unquote? form)
|
||||
(let [items (map |(syntax-quote-expand $ ctx) form)
|
||||
concat-args @[]]
|
||||
(each item items
|
||||
(array/push concat-args
|
||||
[{:jolt/type :symbol :ns nil :name "list"} item]))
|
||||
[{:jolt/type :symbol :ns nil :name "vec"}
|
||||
(tuple ;(array/insert concat-args 0
|
||||
{:jolt/type :symbol :ns nil :name "concat"}))])
|
||||
[{:jolt/type :symbol :ns nil :name "quote"} form])
|
||||
|
||||
# Default → (quote form)
|
||||
[{:jolt/type :symbol :ns nil :name "quote"} form]))
|
||||
|
||||
# ============================================================
|
||||
# Analyzer
|
||||
# ============================================================
|
||||
|
|
@ -553,8 +637,32 @@
|
|||
|
||||
(defn- emit-map-str [form buf] (buffer/push buf (string form)))
|
||||
|
||||
(defn- raw-form->janet
|
||||
"Convert a Jolt reader form to a Janet data structure for quoting."
|
||||
[form]
|
||||
(cond
|
||||
(and (struct? form) (= :symbol (form :jolt/type)))
|
||||
(if (form :ns)
|
||||
(symbol (string (form :ns) "/" (form :name)))
|
||||
(symbol (form :name)))
|
||||
(array? form)
|
||||
(tuple/slice (tuple ;(map raw-form->janet form)))
|
||||
(tuple? form)
|
||||
(tuple/slice (tuple ;(map raw-form->janet form)))
|
||||
form))
|
||||
|
||||
(defn- emit-quote-str [expr buf]
|
||||
(buffer/push buf "'") (emit-ast (analyze-form expr @{}) buf))
|
||||
(buffer/push buf "'")
|
||||
(def janet-val (raw-form->janet expr))
|
||||
(cond
|
||||
(symbol? janet-val) (buffer/push buf (string janet-val))
|
||||
(number? janet-val) (buffer/push buf (string janet-val))
|
||||
(string? janet-val) (do (buffer/push buf "\"") (buffer/push buf janet-val) (buffer/push buf "\""))
|
||||
(keyword? janet-val) (do (buffer/push buf ":") (buffer/push buf (string janet-val)))
|
||||
(nil? janet-val) (buffer/push buf "nil")
|
||||
(= true janet-val) (buffer/push buf "true")
|
||||
(= false janet-val) (buffer/push buf "false")
|
||||
(buffer/push buf (string janet-val))))
|
||||
|
||||
(set emit-ast
|
||||
(fn [ast buf]
|
||||
|
|
@ -677,18 +785,6 @@
|
|||
|
||||
(defn- emit-map-expr [form] form)
|
||||
|
||||
(defn- raw-form->janet
|
||||
"Convert a Jolt reader form to a Janet data structure for quoting."
|
||||
[form]
|
||||
(cond
|
||||
(and (struct? form) (= :symbol (form :jolt/type)))
|
||||
(symbol (form :name))
|
||||
(array? form)
|
||||
(tuple/slice (tuple ;(map raw-form->janet form)))
|
||||
(tuple? form)
|
||||
(tuple/slice (tuple ;(map raw-form->janet form)))
|
||||
form))
|
||||
|
||||
(defn- emit-quote-expr [expr]
|
||||
['quote (raw-form->janet expr)])
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue