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
|
|
@ -1,7 +1,37 @@
|
|||
Janet's `eval` runs in Janet's default environment and does NOT have access to symbols imported via `(use ...)` in the calling file. `(eval '(core-inc 1))` fails with "unknown symbol core-inc" even when the file does `(use ./core)`. FIX: emit Janet data structures where function VALUES are embedded directly (e.g. `[core-inc 1]`) rather than source strings `"(core-inc 1)"`. The `core-fn-values` table resolves Janet symbol names to actual function values at compile time.
|
||||
§
|
||||
Jolt Compiler Architecture (Phases 1-6, dfa9874→c366963): Two-phase — analyze-form (Clojure form → annotated AST) → emit-ast (→ Janet source string) or emit-expr (→ Janet data structures for eval). analyze-form takes [form bindings &opt ctx]; ctx needed for macro expansion. Symbol classification: bindings first (:local), then core-renames (:core-symbol), then plain (:symbol). Two emitter paths: string (compile-form) and data structures (compile-ast). Core fn values resolved via core-fn-values table. compile-and-eval takes [form ctx]; pass nil for no macro ctx. Naming: Clojure - → core-sub. Key bugs found: emit-vector-expr must wrap with (tuple ...) — bare tuples eval as fn calls. make-symbol must treat / at pos 0 as unqualified. raw-form->janet converter for quote (don't re-analyze). core-renames entry for fn? was missing.
|
||||
Jolt Compiler Architecture (Phases 1-6, dfa9874→1de109f): Two-phase — analyze-form (Clojure form → annotated AST) → emit-ast (→ Janet source string) or emit-expr (→ Janet data structures for eval). analyze-form takes [form bindings &opt ctx]; ctx needed for macro expansion. Symbol classification: bindings first (:local), then core-renames (:core-symbol), then plain (:symbol). Two emitter paths: string (compile-form) and data structures (compile-ast). Core fn values resolved via core-fn-values table. compile-and-eval takes [form ctx]; pass nil for no macro ctx.
|
||||
|
||||
Key naming/facts:
|
||||
- Clojure - → core-sub (NOT core--)
|
||||
- core-nth did not exist — had to add both the function and core-bindings entry
|
||||
- Missing from core-renames early: fn?, list, name, subs
|
||||
- Bare tuples in Janet eval → treated as function calls. Always emit (tuple ...) or ['tuple ...]
|
||||
- make-symbol: / at position 0 means unqualified symbol (was parsing empty ns)
|
||||
- raw-form->janet converter for quote: don't re-analyze quoted forms, pass through verbatim
|
||||
- emit-try-expr: Janet format is (try body ([err] handler)) not (try body (catch sym handler))
|
||||
- Loop compilation: (do (var _loop_N nil) (set _loop_N (fn [params] body)) (_loop_N init-vals...))
|
||||
- Recur compilation: rewrites to (loop-name arg1 arg2...) via :loop-name in AST
|
||||
|
||||
eval-string dispatch: When :compile? true, stateful forms (defmacro, ns, deftype, defmulti, defmethod, require, in-ns) use interpreter. All others (def, macros like defn) go through compile-and-eval. Macros expanded at analyze time via resolve-macro.
|
||||
|
||||
Remaining: syntax-quote, set! compiler support. deftype/defmulti/defmethod routed to interpreter.
|
||||
§
|
||||
eval-string dispatch (api.janet): When :compile? is true, stateful forms (defmacro, ns, deftype, defmulti, defmethod, require, in-ns) always use interpreter. All others (def, defn via macros, pure expressions) go through compile-and-eval. defn bug was caused by macros not being expanded — fixed in Phase 4 by routing macros through compiler's analyze-form which expands them at analyze time.
|
||||
Jolt Compiler Architecture (Phases 1-6, dfa9874→1de109f): Two-phase — analyze-form (Clojure form → annotated AST) → emit-ast (→ Janet source string) or emit-expr (→ Janet data structures for eval). analyze-form takes [form bindings &opt ctx]; ctx needed for macro expansion. Symbol classification: bindings first (:local), then core-renames (:core-symbol), then plain (:symbol). Two emitter paths: string (compile-form) and data structures (compile-ast). Core fn values resolved via core-fn-values table. compile-and-eval takes [form ctx]; pass nil for no macro ctx.
|
||||
|
||||
Key naming/facts:
|
||||
- Clojure - → core-sub (NOT core--)
|
||||
- core-nth did not exist — had to add both the function and core-bindings entry
|
||||
- Missing from core-renames early: fn?, list, name, subs
|
||||
- Bare tuples in Janet eval → treated as function calls. Always emit (tuple ...) or ['tuple ...]
|
||||
- make-symbol: / at position 0 means unqualified symbol (was parsing empty ns)
|
||||
- raw-form->janet converter for quote: don't re-analyze quoted forms, pass through verbatim
|
||||
- emit-try-expr: Janet format is (try body ([err] handler)) not (try body (catch sym handler))
|
||||
- Loop compilation: (do (var _loop_N nil) (set _loop_N (fn [params] body)) (_loop_N init-vals...))
|
||||
- Recur compilation: rewrites to (loop-name arg1 arg2...) via :loop-name in AST
|
||||
|
||||
eval-string dispatch: When :compile? true, stateful forms (defmacro, ns, deftype, defmulti, defmethod, require, in-ns) use interpreter. All others (def, macros like defn) go through compile-and-eval. Macros expanded at analyze time via resolve-macro.
|
||||
|
||||
Remaining: syntax-quote, set! compiler support. deftype/defmulti/defmethod routed to interpreter. Git push needs manual approval.
|
||||
§
|
||||
Phase 6: 47 comprehensive compile-mode tests in test/phase6-final.janet. Collections, math, predicates, comparison, seq ops (map/filter/reduce/take/drop), special forms (let/if/loop/try/quote), macros (defn/when/and/or/fn/if-let), complex nesting. All 317 tests pass. Remaining: syntax-quote, set! compiler support. deftype, defmulti/defmethod routed to interpreter (stateful).
|
||||
Phase 6: 47 comprehensive compile-mode tests in test/phase6-final.janet. Collections, math, predicates, comparison, seq ops (map/filter/reduce/take/drop), special forms (let/if/loop/try/quote), macros (defn/when/and/or/fn/if-let), complex nesting. 58 assertions. All 317 tests pass, 0 failures. Remaining: syntax-quote, set! compiler support. deftype, defmulti/defmethod routed to interpreter (stateful).
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
Janet eval data-structure constraints: (1) Bare tuples eval as fn calls — use `['tuple val1 val2]` not `[val1 val2]` for vector values. (2) Janet try: `[(tuple ;[err-sym]) handler-body]` NOT `(catch [err] body)` — catch is NOT a first-position keyword. (3) quote in compile-ast: use raw-form→janet converter (map Jolt reader structs → Janet symbols) — don't re-analyze. (4) eval runs in default env, doesn't see `use`-imported symbols. FIX: embed fn values directly via core-fn-values table.
|
||||
§
|
||||
When you need to mutate a local with `set`, use `(var x nil)` not `(def x nil)`. `def` creates constants — `(set ns-name ...)` on a `def` fails with "cannot set constant". This hit us in loader.janet ns-name extraction loop.
|
||||
§
|
||||
core-renames MUST match actual function names in core.janet. `"-"`→`core-sub` NOT `core--`. `"fn?"` was missing entirely (caused silent nil). Missing entries → symbol treated as unknown global, returns nil. When adding: grep core.janet for actual `(defn core-XXX)` name, add to BOTH core-renames (string table) and core-fn-values (fn value table).
|
||||
§
|
||||
Bare tuples in Janet's `eval` are function calls: `(eval [1 2 3])` tries to call `1` as function. Always emit `['tuple 1 2 3]` or `(tuple 1 2 3)` in data-structure emitter. Similarly, `(eval (try body (sym handler)))` fails because `catch` is not a Janet special form — must be `(try body ([sym] handler))`. Discovered during Phase 5/6 compiler work.
|
||||
§
|
||||
core-renames MUST match actual function names in core.janet. `"-"`→`core-sub` NOT `core--`. `"fn?"` was missing entirely (caused silent nil). Missing entries → symbol treated as unknown global, returns nil. When adding: grep core.janet for actual `(defn core-XXX)` name, add to BOTH core-renames (string table) and core-fn-values (fn value table).
|
||||
§
|
||||
Bare tuples in Janet's `eval` are function calls: `(eval [1 2 3])` tries to call `1` as function. Always emit `['tuple 1 2 3]` or `(tuple 1 2 3)` in data-structure emitter. Similarly, `(eval (try body (sym handler)))` fails because `catch` is not a Janet special form — must be `(try body ([sym] handler))`. Discovered during Phase 5/6 compiler work.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue