Phase 3: Var system — var-get, var-set, var?, alter-var-root, find-var, alter-meta!, reset-meta!
- types.janet: find-var (ctx-based var resolution), alter-meta!, reset-meta! - evaluator.janet: 10 new special-form dispatch arms for var ops - core.janet: 6 new Clojure-level wrappers in core-bindings - core-meta: add var-aware branch (was struct-only) - core-binding macro: use array-map instead of hash-map (PHM incompatibility) - 8 new tests (17: var system, 18: var metadata) — all pass - 317 total tests, 0 failures
This commit is contained in:
parent
ad895945a0
commit
8e86c7c2ec
8 changed files with 177 additions and 51 deletions
|
|
@ -467,7 +467,8 @@
|
|||
|
||||
(defn core-meta [x]
|
||||
"Returns the metadata of x, or nil."
|
||||
(if (struct? x) (get x :meta) nil))
|
||||
(if (var? x) (var-meta x)
|
||||
(if (struct? x) (get x :meta) nil)))
|
||||
|
||||
(def core-comp
|
||||
(fn [& fs]
|
||||
|
|
@ -780,8 +781,17 @@
|
|||
(defn core-push-thread-bindings [b] (push-thread-bindings b))
|
||||
(defn core-pop-thread-bindings [] (pop-thread-bindings))
|
||||
|
||||
(defn core-var-get [v] (var-get v))
|
||||
(defn core-var-set [v val] (var-set v val))
|
||||
(defn core-var? [x] (var? x))
|
||||
(defn core-alter-var-root [v f & args] (apply alter-var-root v f args))
|
||||
(defn core-alter-meta! [v f & args] (apply alter-meta! v f args))
|
||||
(defn core-reset-meta! [v meta] (reset-meta! v meta))
|
||||
|
||||
(defn core-binding
|
||||
"Macro: (binding [var val ...] body...)"
|
||||
"Macro: (binding [var val ...] body...)
|
||||
Uses array-map (plain struct) to store binding frame
|
||||
to avoid PHM get() incompatibility with var-get."
|
||||
[bindings & body]
|
||||
(def frame-pairs @[])
|
||||
(var i 0)
|
||||
|
|
@ -792,7 +802,7 @@
|
|||
(array/push frame-pairs (in bindings (+ i 1)))
|
||||
(+= i 2)))
|
||||
(def hm-form (array/insert frame-pairs 0
|
||||
{:jolt/type :symbol :ns nil :name "hash-map"}))
|
||||
{:jolt/type :symbol :ns nil :name "array-map"}))
|
||||
@[{:jolt/type :symbol :ns nil :name "let*"}
|
||||
[{:jolt/type :symbol :ns nil :name "frame"} hm-form]
|
||||
@[{:jolt/type :symbol :ns nil :name "push-thread-bindings"}
|
||||
|
|
@ -1155,6 +1165,12 @@
|
|||
"avoid-method-too-large" core-avoid-method-too-large
|
||||
"qualified-symbol?" core-qualified-symbol?
|
||||
"meta" core-meta
|
||||
"var-get" core-var-get
|
||||
"var-set" core-var-set
|
||||
"var?" core-var?
|
||||
"alter-var-root" core-alter-var-root
|
||||
"alter-meta!" core-alter-meta!
|
||||
"reset-meta!" core-reset-meta!
|
||||
"binding" core-binding
|
||||
"push-thread-bindings" core-push-thread-bindings
|
||||
"pop-thread-bindings" core-pop-thread-bindings
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@
|
|||
(= name "recur") (= name "throw") (= name "try")
|
||||
(= name "set!") (= name "var") (= name "locking")
|
||||
(= name "instance?") (= name "defmulti") (= name "defmethod")
|
||||
(= name "deftype") (= name "new") (= name ".")))
|
||||
(= name "deftype") (= name "new") (= name ".")
|
||||
(= name "var-get") (= name "var-set") (= name "var?")
|
||||
(= name "alter-var-root") (= name "find-var") (= name "intern")
|
||||
(= name "alter-meta!") (= name "reset-meta!")))
|
||||
|
||||
(var eval-form nil)
|
||||
|
||||
|
|
@ -568,8 +571,21 @@
|
|||
(def new-v (ns-intern ns (target-sym :name) val))
|
||||
val)))))
|
||||
"var" (let [target-sym (in form 1)
|
||||
v (resolve-var ctx bindings target-sym)]
|
||||
(if v v (error (string "Unable to resolve var: " (sym-name-str target-sym) " in var"))))
|
||||
v (resolve-var ctx bindings target-sym)]
|
||||
(if v v (error (string "Unable to resolve var: " (sym-name-str target-sym) " in var"))))
|
||||
"var-get" (var-get (eval-form ctx bindings (in form 1)))
|
||||
"var-set" (var-set (eval-form ctx bindings (in form 1))
|
||||
(eval-form ctx bindings (in form 2)))
|
||||
"var?" (var? (eval-form ctx bindings (in form 1)))
|
||||
"alter-var-root" (alter-var-root (eval-form ctx bindings (in form 1))
|
||||
(eval-form ctx bindings (in form 2)))
|
||||
"find-var" (find-var ctx (eval-form ctx bindings (in form 1)))
|
||||
"alter-meta!" (let [v (eval-form ctx bindings (in form 1))
|
||||
f (eval-form ctx bindings (in form 2))
|
||||
args (map |(eval-form ctx bindings $) (tuple/slice form 3))]
|
||||
(apply alter-meta! v f args))
|
||||
"reset-meta!" (reset-meta! (eval-form ctx bindings (in form 1))
|
||||
(eval-form ctx bindings (in form 2)))
|
||||
"locking" (eval-form ctx bindings (in form 2))
|
||||
"instance?" (let [type-sym (in form 1)
|
||||
val (eval-form ctx bindings (in form 2))]
|
||||
|
|
|
|||
|
|
@ -112,6 +112,19 @@
|
|||
(let [new-val (f (v :root) ;args)]
|
||||
(put v :root new-val)))
|
||||
|
||||
(defn alter-meta!
|
||||
"Atomically update a var's metadata via (apply f args)."
|
||||
[v f & args]
|
||||
(let [new-meta (apply f (var-meta v) args)]
|
||||
(put v :meta new-meta)
|
||||
new-meta))
|
||||
|
||||
(defn reset-meta!
|
||||
"Reset a var's metadata to the given value."
|
||||
[v meta]
|
||||
(put v :meta meta)
|
||||
meta)
|
||||
|
||||
(defn with-meta
|
||||
"Return a new var with updated metadata. The original var is unchanged."
|
||||
[v meta]
|
||||
|
|
@ -319,3 +332,18 @@
|
|||
[ctx]
|
||||
(let [ns (ctx-find-ns ctx (ctx-current-ns ctx))]
|
||||
(ns :imports)))
|
||||
|
||||
(defn find-var
|
||||
"Resolve a symbol to a var in the current context.
|
||||
Looks in current namespace first, then clojure.core."
|
||||
[ctx sym-s]
|
||||
(let [name (sym-s :name)
|
||||
ns-sym (sym-s :ns)]
|
||||
(if ns-sym
|
||||
(let [ns (ctx-find-ns ctx ns-sym)]
|
||||
(ns-find ns name))
|
||||
(let [current-ns (ctx-find-ns ctx (ctx-current-ns ctx))
|
||||
v (ns-find current-ns name)]
|
||||
(if v v
|
||||
(let [core-ns (ctx-find-ns ctx "clojure.core")]
|
||||
(ns-find core-ns name)))))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue