From c0e512e3046e3ec3c9daa839ff5ad319025f31a6 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 13 Mar 2021 17:04:35 +0100 Subject: [PATCH] proxy --- sci | 2 +- src/babashka/impl/proxy.clj | 76 +++++++++++++++++++----------------- test/babashka/proxy_test.clj | 15 ++++--- 3 files changed, 51 insertions(+), 42 deletions(-) diff --git a/sci b/sci index 02409735..139df5af 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 02409735ac3e085a407352ea3d0fbd29a3777816 +Subproject commit 139df5af5ab8e80a4988db45f1c7110ff40f3e8f diff --git a/src/babashka/impl/proxy.clj b/src/babashka/impl/proxy.clj index 9a68eaad..4dd06fe4 100644 --- a/src/babashka/impl/proxy.clj +++ b/src/babashka/impl/proxy.clj @@ -10,43 +10,47 @@ (defn method-or [methods k default] (or (get methods k) - default)) + (constantly default))) -(defn proxy-fn [{:keys [class methods]}] - (case (.getName ^Class class) - "clojure.lang.APersistentMap" - (proxy [clojure.lang.APersistentMap clojure.lang.IMeta clojure.lang.IObj] [] - (iterator [] ((method-or-bust methods 'iterator) this)) - (containsKey [k] ((method-or-bust methods 'containsKey) this k)) - (entryAt [k] ((method-or-bust methods 'entryAt) this k)) - (valAt - ([k] ((method-or-bust methods 'valAt) this k)) - ([k default] ((method-or-bust methods 'valAt) this k default))) - (cons [v] - (if-let [m (get methods 'cons)] - (m this v) - (proxy-super cons v))) - (count [] ((method-or-bust methods 'count) this)) - (assoc [k v] ((method-or-bust methods 'assoc) this k v)) - (without [k] ((method-or-bust methods 'without) this k)) - (seq [] ((method-or-bust methods 'seq) this)) +(defn class-name [^Class clazz] + (.getName clazz)) - (equiv [other] - (if-let [m (get methods 'equiv)] - (m this other) - (proxy-super equiv other))) - (empty [] ((method-or-bust methods 'empty) this)) +(defn proxy-fn [{:keys [class interfaces methods]}] + (let [interfaces (set (map class-name interfaces))] + (case [(class-name class) interfaces ] + ["clojure.lang.APersistentMap" #{"clojure.lang.IMeta" "clojure.lang.IObj"}] + (proxy [clojure.lang.APersistentMap clojure.lang.IMeta clojure.lang.IObj] [] + (iterator [] ((method-or-bust methods 'iterator) this)) + (containsKey [k] ((method-or-bust methods 'containsKey) this k)) + (entryAt [k] ((method-or-bust methods 'entryAt) this k)) + (valAt + ([k] ((method-or-bust methods 'valAt) this k)) + ([k default] ((method-or-bust methods 'valAt) this k default))) + (cons [v] + (if-let [m (get methods 'cons)] + (m this v) + (proxy-super cons v))) + (count [] ((method-or-bust methods 'count) this)) + (assoc [k v] ((method-or-bust methods 'assoc) this k v)) + (without [k] ((method-or-bust methods 'without) this k)) + (seq [] ((method-or-bust methods 'seq) this)) - (meta [] ((method-or methods 'meta nil) this)) - (withMeta [meta] ((method-or methods 'withMeta this) this meta)) + (equiv [other] + (if-let [m (get methods 'equiv)] + (m this other) + (proxy-super equiv other))) + (empty [] ((method-or-bust methods 'empty) this)) - (toString [] - (if-let [m (get methods 'toString)] - (m this) - (proxy-super toString)))) - "clojure.lang.AMapEntry" - (proxy [clojure.lang.AMapEntry] [] - (key [] ((method-or-bust methods 'key) this)) - (val [] ((method-or-bust methods 'val) this)) - (getKey [] ((method-or-bust methods 'getKey) this)) - (getValue [] ((method-or-bust methods 'getValue) this))))) + (meta [] ((method-or-bust methods 'meta) this)) + (withMeta [meta] ((method-or-bust methods 'withMeta) this meta)) + + (toString [] + (if-let [m (get methods 'toString)] + (m this) + (proxy-super toString)))) + ["clojure.lang.AMapEntry" #{}] + (proxy [clojure.lang.AMapEntry] [] + (key [] ((method-or-bust methods 'key) this)) + (val [] ((method-or-bust methods 'val) this)) + (getKey [] ((method-or-bust methods 'getKey) this)) + (getValue [] ((method-or-bust methods 'getValue) this)))))) diff --git a/test/babashka/proxy_test.clj b/test/babashka/proxy_test.clj index c59e0e71..e4213f10 100644 --- a/test/babashka/proxy_test.clj +++ b/test/babashka/proxy_test.clj @@ -21,14 +21,14 @@ (defn proxy-deref-map {:added "1.0"} [m] - (proxy [clojure.lang.APersistentMap] + (proxy [clojure.lang.APersistentMap clojure.lang.IMeta clojure.lang.IObj] [] (iterator [] ::TODO) (containsKey [k] (contains? m k)) (entryAt [k] (when (contains? m k) (proxy [clojure.lang.AMapEntry] [] (key [] k) - (val [] (auto-deref(get m k)))))) + (val [] (auto-deref (get m k)))))) (valAt ([k] (auto-deref (get m k))) ([k default] (auto-deref (get m k default)))) (cons [v] (proxy-deref-map (conj m v))) @@ -37,7 +37,9 @@ (without [k] (proxy-deref-map (dissoc m k))) (seq [] (map (fn [[k v]](proxy [clojure.lang.AMapEntry] [] (key [] k) - (val [] (auto-deref (get m k))))) m)))) + (val [] (auto-deref (get m k))))) m)) + (withMeta [md] (proxy-deref-map (with-meta m md))) + (meta [] (meta m)))) (let [m (proxy-deref-map {:a (delay 1) :b (delay 2) @@ -54,10 +56,13 @@ :d) (-> (dissoc m :a) (contains? :a)) - (seq m)]))) + (seq m) + (meta (with-meta m {:a 1})) + ]))) (deftest APersistentMap-proxy-test (is (= [1 2 3 true [:c 3] 5 3 5 false - '([:a 1] [:b 2] [:c 3])] + '([:a 1] [:b 2] [:c 3]) + {:a 1}] (bb code))))