compiler phase 1: var-indirection for redefinable compiled globals
Compiled global references now deref through the Jolt var cell instead of an early-bound Janet symbol, so redefining a def/defn is visible to already-compiled callers (Janet early-binds plain symbols). A global ref analyzes to :op :var (resolving/creating the cell); a def sets that same cell's root. Because Janet copies table constants but references functions, we embed memoized getter/setter closures over the cell rather than the cell itself. This also subsumes the old named-fn recursion rewrite and the separate ns-intern. ns-intern now stores the namespace *name* (string) in a var, not the ns table, so var cells aren't cyclic (required for embedding). fib(30) compiled ~0.5s (the late-binding cost vs phase 2's direct-linked 0.08s; direct-linking for hot calls is a later optimization). Suite green; cross-form, recursion, and context isolation preserved; redefinition now works.
This commit is contained in:
parent
614962d535
commit
70711b4489
3 changed files with 53 additions and 35 deletions
|
|
@ -100,10 +100,19 @@
|
|||
(assert (= 2 (ct-eval ctx "(#{1 2 3} 2)")) "set as fn")
|
||||
(assert (= true (ct-eval ctx "(= [1 2] [1 2])")) "= is value equality, not core-= bypass"))
|
||||
|
||||
# Context isolation: a def in one compiled context is invisible in another.
|
||||
# Context isolation: a def in one compiled context is invisible in another. With
|
||||
# var-indirection each context has its own var cells, so b's `secret` is a
|
||||
# distinct, unbound var (nil) rather than a's 7.
|
||||
(let [a (init {:compile? true}) b (init {:compile? true})]
|
||||
(eval-string a "(def secret 7)")
|
||||
(assert (= 7 (ct-eval a "secret")) "def visible in its own ctx")
|
||||
(assert (not ((protect (ct-eval b "secret")) 0)) "def isolated to its ctx"))
|
||||
(assert (nil? (ct-eval b "secret")) "def isolated to its ctx"))
|
||||
|
||||
# Redefinition is visible to already-compiled callers (var-indirection).
|
||||
(let [c (init {:compile? true})]
|
||||
(eval-string c "(defn g [] 1)")
|
||||
(eval-string c "(defn calls-g [] (g))")
|
||||
(eval-string c "(defn g [] 2)")
|
||||
(assert (= 2 (ct-eval c "(calls-g)")) "compiled caller sees redefined global"))
|
||||
|
||||
(print "\nAll Phase 6 tests passed!")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue