Skip to content

Commit

Permalink
Partial support for multiple reified classes
Browse files Browse the repository at this point in the history
  • Loading branch information
borkdude committed Oct 18, 2020
1 parent ea5a87b commit 323a257
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 20 deletions.
10 changes: 5 additions & 5 deletions src/sci/impl/opts.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@
:class->opts (persistent! class->opts)})))

(def default-reify
#?(:clj {'java.lang.Object
(fn [{:keys [:methods]}]
{:obj (reify Object
(toString [this]
((get methods 'toString) this)))})}
#?(:clj {'#{java.lang.Object}
(fn [methods]
(reify Object
(toString [this]
((get-in methods '[java.lang.Object toString]) this))))}
:cljs {}))

(defn init
Expand Down
42 changes: 27 additions & 15 deletions src/sci/impl/reify.cljc
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
(ns sci.impl.reify
(:refer-clojure :exclude [reify])
(:require [sci.impl.types :as t]))
(:require [sci.impl.types :as t]
[sci.impl.utils :refer [split-when]]))

(defn reify [_ _ _ctx interface & meths]
(let [meths (into {} (map (fn [meth]
`['~(first meth) (fn ~(second meth) ~@(nnext meth))])
meths))]
`(clojure.core/reify* ~interface ~meths)))
(defn reify [_ _ _ctx & args]
(let [classes->methods (split-when symbol? args)
classes->methods (into {} (map (fn [[class & methods]]
[class (into {}
(map (fn [meth]
`['~(first meth) (fn ~(second meth) ~@(nnext meth))])
methods))])
classes->methods))]
`(clojure.core/reify* ~classes->methods)))

(defn reify* [#?(:clj ctx
:cljs _ctx) interface meths]
#?(:clj (if (class? interface)
(let [class-name (symbol (.getName ^Class interface))]
(if-let [factory (get-in ctx [:reify class-name])]
(:obj (factory {:class interface :methods meths}))
(throw (ex-info (str "No reify factory for: " class-name)
{:class class}))))
(t/->Reified interface meths))
:cljs (t/->Reified interface meths)))
:cljs _ctx) classes->methods]
#?(:clj (let [ks (keys classes->methods)]
;; NOTE: if the first thing in reify is a class, we assume all
;; classes and no protocols. This should be addressed in a future version.
(if (class? (first ks))
(let [class-names (set (map #(symbol (.getName ^Class %)) ks))]
(if-let [factory (get-in ctx [:reify class-names])]
(factory (zipmap class-names (vals classes->methods)))
(throw (ex-info (str "No reify factory for: " class-names)
{:class class}))))
;; So far we only supported reify-ing one protocol at a time. This
;; should be addressed in a future version
(let [[interface methods] (first classes->methods)]
(t/->Reified interface methods))))
:cljs (let [[interface methods] (first classes->methods)]
(t/->Reified interface methods))))

0 comments on commit 323a257

Please sign in to comment.