Phase 0: Fix defn bug + bare symbol resolution

Root cause: compile-and-eval for def created Janet global but never
interned the var in Jolt's namespace. Bare symbols fell through to
interpreter which couldn't find them.

Fixes:
- eval-string: bare symbols and tuples now go through compile path
- compile-and-eval: def/defn/defn- forms intern result in Jolt namespace
- New tests: defn/def integration (4 assertions)

All 317 tests pass.
This commit is contained in:
Yogthos 2026-06-02 16:58:10 -04:00
parent 4ca7c31e50
commit 3ac293c7a5
4 changed files with 268 additions and 15 deletions

View file

@ -49,19 +49,27 @@
[ctx s]
(let [compile? (get (ctx :env) :compile?)
form (parse-string s)]
(if (and compile? (array? form))
(let [first-form (first form)
head-name (if (and (struct? first-form) (= :symbol (first-form :jolt/type)))
(first-form :name)
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 "syntax-quote") (= head-name "set!")
(= head-name "var") (= head-name ".") (= head-name "new"))]
(if stateful?
(eval-form ctx @{} form)
(compile-and-eval form ctx)))
(if compile?
(if (array? form)
# Lists: check for stateful forms
(let [first-form (first form)
head-name (if (and (struct? first-form) (= :symbol (first-form :jolt/type)))
(first-form :name)
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 "syntax-quote") (= head-name "set!")
(= head-name "var") (= head-name ".") (= head-name "new"))]
(if stateful?
(eval-form ctx @{} form)
(compile-and-eval form ctx)))
# Bare symbols and other non-literal forms: also compile
(if (or (and (struct? form) (= :symbol (form :jolt/type)))
(tuple? form))
(compile-and-eval form ctx)
(eval-form ctx @{} form)))
# No compile flag: always interpret
(eval-form ctx @{} form))))
(defn eval-string*

View file

@ -831,6 +831,18 @@
(emit-expr (analyze-form form @{} ctx)))
(defn compile-and-eval
"Compile a Clojure form and evaluate it as Janet."
"Compile a Clojure form and evaluate it as Janet.
For def/defn forms, interns the result in the Jolt namespace
so the interpreter can resolve it later."
[form ctx]
(eval (compile-ast form ctx)))
(def result (eval (compile-ast form ctx)))
# Intern def/defn results in Jolt namespace for interpreter resolution
(when (and ctx (array? form) (> (length form) 0)
(struct? (first form)) (= :symbol ((first form) :jolt/type)))
(def head-name ((first form) :name))
(when (or (= head-name "def") (= head-name "defn") (= head-name "defn-"))
(def name-sym (in form 1))
(def name (if (struct? name-sym) (name-sym :name) name-sym))
(def ns (ctx-find-ns ctx (ctx-current-ns ctx)))
(ns-intern ns name result)))
result)