added nav constructors + tests, fixed bug with clj platform eval'd params fn to bind to the namesapace where the path was defined

This commit is contained in:
Nathan Marz 2016-05-24 16:00:22 -04:00
parent cd7b759c3a
commit e70cfb3623
3 changed files with 53 additions and 20 deletions

View file

@ -857,8 +857,10 @@
)))
#+clj
(defn mk-params-maker [params-code possible-params-code used-locals]
(let [array-sym (gensym "array")]
(defn mk-params-maker [ns-str params-code possible-params-code used-locals]
(let [ns (find-ns (symbol ns-str))
array-sym (gensym "array")]
(binding [*ns* ns]
(eval
`(fn [~@used-locals]
(let [~array-sym (fast-object-array ~(count params-code))]
@ -868,10 +870,10 @@
params-code
)
~array-sym
)))))
))))))
#+cljs
(defn mk-params-maker [params-code possible-params-code used-locals]
(defn mk-params-maker [ns-str params-code possible-params-code used-locals]
(let [indexed (->> possible-params-code
(map-indexed (comp vec reverse vector))
(into {}))]
@ -879,7 +881,7 @@
(mapv (fn [c] (get indexed c)) params-code)))
;; possible-params-code is for cljs impl that can't use eval
(defn magic-precompilation [prepared-path used-locals possible-params-code]
(defn magic-precompilation [prepared-path ns-str used-locals possible-params-code]
(let [params-atom (atom [])
failed-atom (atom false)
path (magic-precompilation* prepared-path params-atom failed-atom)
@ -891,7 +893,7 @@
(let [precompiled (comp-paths* path)
params-code (mapv extract-original-code @params-atom)
params-maker (if-not (empty? params-code)
(mk-params-maker params-code possible-params-code used-locals))
(mk-params-maker ns-str params-code possible-params-code used-locals))
]
;; TODO: error if precompiled is compiledpath and there are params or
;; precompiled is paramsneededpath and there are no params...

View file

@ -319,7 +319,7 @@
`(def ~name (vary-meta (fn ~@args) assoc :pathedfn true))))
(defmacro defnavconstructor [name & args]
(let [[name [anav & body-or-bodies]] (m/name-with-attributes name args)
(let [[name [[csym anav] & body-or-bodies]] (m/name-with-attributes name args)
bodies (if (-> body-or-bodies first vector?) [body-or-bodies] body-or-bodies)
checked-code
@ -330,11 +330,13 @@
(if (i/layered-nav? ret#)
(i/layered-nav-underlying ret#)
(i/throw-illegal "Expected result navigator '" (quote ~anav)
"' from nav constructor '" (quote ~name) "'"))
"' from nav constructor '" (quote ~name) "'"
" constructed with the provided constructor '" (quote ~csym)
"'"))
))))]
`(def ~name
(vary-meta
(let [~anav (i/layered-wrapper ~anav)]
(let [~csym (i/layered-wrapper ~anav)]
(fn ~@checked-code))
assoc :layerednav true))
))
@ -428,6 +430,7 @@
(if (nil? info#)
(let [info# (i/magic-precompilation
~prepared-path
~(str *ns*)
(quote ~used-locals)
;;possible-params is wrong atm
;;as is used-locals in cljs...

View file

@ -7,7 +7,7 @@
[com.rpl.specter.macros
:refer [paramsfn defprotocolpath defnav extend-protocolpath
nav declarepath providepath select select-one select-one!
select-first transform setval replace-in]])
select-first transform setval replace-in defnavconstructor]])
(:use
#+clj [clojure.test :only [deftest is]]
#+clj [clojure.test.check.clojure-test :only [defspec]]
@ -15,7 +15,7 @@
#+clj [com.rpl.specter.macros
:only [paramsfn defprotocolpath defnav extend-protocolpath
nav declarepath providepath select select-one select-one!
select-first transform setval replace-in]]
select-first transform setval replace-in defnavconstructor]]
)
@ -859,6 +859,27 @@
(= q1 q2)
(= (type q1) (type q2))))))
(defnavconstructor double-str-keypath
[p s/keypath]
[s1 s2]
(p (str s1 s2)))
(defnavconstructor some-keypath
[p s/keypath]
([] (p "a"))
([k1] (p (str k1 "!")))
([k & args] (p "bbb")))
(deftest nav-constructor-test
;; this also tests that the eval done by clj platform during inline
;; caching rebinds to the correct namespace since this is run
;; by clojure.test in a different namespace
(is (= 1 (select-one! (double-str-keypath "a" "b") {"ab" 1 "c" 2})))
(is (= 1 (select-one! (some-keypath) {"a" 1 "a!" 2 "bbb" 3 "d" 4})))
(is (= 2 (select-one! (some-keypath "a") {"a" 1 "a!" 2 "bbb" 3 "d" 4})))
(is (= 3 (select-one! (some-keypath 1 2 3 4 5) {"a" 1 "a!" 2 "bbb" 3 "d" 4})))
)
(def ^:dynamic *APATH* s/keypath)
(deftest inline-caching-test
@ -883,6 +904,13 @@
inc
{:a 1 :b 2}
[[true] [false]])
(ic-test
true
[v]
[s/ALL (double-str-keypath v (inc v))]
str
[{"12" :a "1011" :b} {"1011" :c}]
[[1] [10]])
(ic-test
false
[k]