Skip to content

Commit

Permalink
some cljc
Browse files Browse the repository at this point in the history
  • Loading branch information
darkleaf committed Sep 21, 2019
1 parent 2f86cdd commit 7ebbd0b
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 67 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
/tags
/target
\#*\#
/.cljs_node_repl
3 changes: 2 additions & 1 deletion project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@

:dependencies
[[pretty "1.0.0"]
[potemkin "0.4.5"]]
[potemkin "0.4.5"]
[org.clojure/clojurescript "1.10.520" :scope "provided"]]

:aot [methodical.interface methodical.impl.standard]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
(ns methodical.impl.dispatcher.common
"Utility functions for implementing Dispatchers.")
"Utility functions for implementing Dispatchers."
#?(:cljs
(:require
[goog.string :refer [format]])))

#?(:cljs (def ^:private IllegalStateException js/Error))

(defn add-preference
"Add a method preference to `prefs` for dispatch value `x` over `y`. Used to implement `prefer-method`."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
(:refer-clojure :exclude [prefers prefer-method])
(:require [methodical.impl.dispatcher.common :as dispatcher.common]
[methodical.interface :as i]
[pretty.core :refer [PrettyPrintable]])
(:import methodical.interface.Dispatcher))
#?(:clj [pretty.core :refer [PrettyPrintable]])
#?(:cljs [methodical.interface :refer [Dispatcher]])
#?(:cljs [goog.string :refer [format]]))
#?(:clj (:import methodical.interface.Dispatcher)))

#?(:cljs (def ^:private IllegalArgumentException js/Error))

(defn- matching-primary-pairs-excluding-default
"Return a sequence of pairs of `[dispatch-value method]` for all applicable dispatch values, excluding the default
Expand Down Expand Up @@ -86,20 +90,23 @@
:when (seq pairs)]
[qualifier (map second pairs)])))


(deftype StandardDispatcher [dispatch-fn hierarchy-var default-value prefs]
PrettyPrintable
(pretty [_]
(concat ['standard-dispatcher dispatch-fn]
(when (not= hierarchy-var #'clojure.core/global-hierarchy)
[:hierarchy hierarchy-var])
(when (not= default-value :default)
[:default-value default-value])
(when (seq prefs)
[:prefers prefs])))

Object
(equals [_ another]
#?@(:clj
[PrettyPrintable
(pretty [_]
(concat ['standard-dispatcher dispatch-fn]
(when (not= hierarchy-var #'clojure.core/global-hierarchy)
[:hierarchy hierarchy-var])
(when (not= default-value :default)
[:default-value default-value])
(when (seq prefs)
[:prefers prefs])))])

#?(:clj Object
:cljs IEquiv)
;; todo: hashcode

(#?(:clj equals, :cljs -equiv) [_ another]
(and
(instance? StandardDispatcher another)
(let [^StandardDispatcher another another]
Expand All @@ -109,7 +116,7 @@
(= default-value (.default-value another))
(= prefs (.prefs another))))))

Dispatcher
#?(:clj Dispatcher :cljs Object)
(dispatchValue [_] (dispatch-fn))
(dispatchValue [_ a] (dispatch-fn a))
(dispatchValue [_ a b] (dispatch-fn a b))
Expand All @@ -130,6 +137,8 @@
prefs)

(preferMethod [this x y]
;; var-get is not implemented in cljs
;; https://github.com/camsaul/methodical/issues/29
(let [new-prefs (dispatcher.common/add-preference (partial isa? (var-get hierarchy-var)) prefs x y)]

This comment has been minimized.

Copy link
@darkleaf

darkleaf Sep 21, 2019

Author Contributor

var-get is not implemented in cljs
#29

(if (= prefs new-prefs)
this
Expand Down
114 changes: 65 additions & 49 deletions src/methodical/interface.clj → src/methodical/interface.cljc
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
(ns methodical.interface
(:refer-clojure :exclude [isa? prefers prefer-method]))

(defmacro ^:private defonceinterface [interface-name & body]
(let [class-name (clojure.string/replace (str *ns* "." interface-name) #"\-" "_")
exists (try
(Class/forName class-name)
true
(catch Exception _
false))]
(if exists
`(do
(import ~(symbol class-name))
nil)
`(definterface ~interface-name ~@body))))

(defonceinterface MethodCombination
(allowedQualifiers [])
(combineMethods [primary-methods aux-methods])
(transformFnTail [qualifier fn-tail]))
#?(:clj
(defmacro ^:private defonceinterface [interface-name & body]
(let [class-name (clojure.string/replace (str *ns* "." interface-name) #"\-" "_")
exists (try
(Class/forName class-name)
true
(catch Exception _
false))]
(if exists
`(do
(import ~(symbol class-name))
nil)
`(definterface ~interface-name ~@body)))))

#?(:clj
(defonceinterface MethodCombination
(allowedQualifiers [])
(combineMethods [primary-methods aux-methods])
(transformFnTail [qualifier fn-tail]))
:cljs
(def MethodCombination))

(defn allowed-qualifiers
"The set containg all qualifiers supported by this method combination. `nil` in the set means the method
Expand All @@ -44,13 +48,16 @@
[^MethodCombination method-combination qualifier fn-tail]
(.transformFnTail method-combination qualifier fn-tail))

(defonceinterface MethodTable
(primaryMethods [])
(auxMethods [])
(addPrimaryMethod [dispatch-value f])
(removePrimaryMethod [dispatch-value])
(addAuxMethod [qualifier dispatch-value f])
(removeAuxMethod [qualifier dispatch-val method]))
#?(:clj
(defonceinterface MethodTable
(primaryMethods [])
(auxMethods [])
(addPrimaryMethod [dispatch-value f])
(removePrimaryMethod [dispatch-value])
(addAuxMethod [qualifier dispatch-value f])
(removeAuxMethod [qualifier dispatch-val method]))
:cljs
(def MethodTable))

(defn primary-methods
"Get a `dispatch-value -> fn` map of all primary methods assoicated with this method table."
Expand Down Expand Up @@ -88,19 +95,22 @@
[^MethodTable method-table qualifier dispatch-val method]
(.removeAuxMethod method-table qualifier dispatch-val method))

(defonceinterface Dispatcher
(dispatchValue [])
(dispatchValue [a])
(dispatchValue [a b])
(dispatchValue [a b c])
(dispatchValue [a b c d])
(dispatchValue [a b c d more])

(matchingPrimaryMethods [method-table dispatch-value])
(matchingAuxMethods [method-table dispatch-value])
(defaultDispatchValue [])
(prefers [])
(preferMethod [dispatch-val-x dispatch-val-y]))
#?(:clj
(defonceinterface Dispatcher
(dispatchValue [])
(dispatchValue [a])
(dispatchValue [a b])
(dispatchValue [a b c])
(dispatchValue [a b c d])
(dispatchValue [a b c d more])

(matchingPrimaryMethods [method-table dispatch-value])
(matchingAuxMethods [method-table dispatch-value])
(defaultDispatchValue [])
(prefers [])
(preferMethod [dispatch-val-x dispatch-val-y]))
:cljs
(def Dispatcher))

(defn dispatch-value
"Return an appropriate dispatch value for args passed to a multimethod. (This method is equivalent in purpose to
Expand Down Expand Up @@ -140,13 +150,16 @@
[^Dispatcher dispatcher dispatch-val-x dispatch-val-y]
(.preferMethod dispatcher dispatch-val-x dispatch-val-y))

(defonceinterface MultiFnImpl
(^methodical.interface.MethodCombination methodCombination [])
(^methodical.interface.Dispatcher dispatcher [])
(^methodical.interface.MultiFnImpl withDispatcher [new-dispatcher])
(^methodical.interface.MethodTable methodTable [])
(^methodical.interface.MultiFnImpl withMethodTable [new-method-table])
(effectiveMethod [dispatch-value]))
#?(:clj
(defonceinterface MultiFnImpl
(^methodical.interface.MethodCombination methodCombination [])
(^methodical.interface.Dispatcher dispatcher [])
(^methodical.interface.MultiFnImpl withDispatcher [new-dispatcher])
(^methodical.interface.MethodTable methodTable [])
(^methodical.interface.MultiFnImpl withMethodTable [new-method-table])
(effectiveMethod [dispatch-value]))
:cljs
(def MultiFnImpl))

(defn ^methodical.interface.MethodCombination method-combination
"Get the method combination associated with this multifn."
Expand Down Expand Up @@ -181,11 +194,14 @@
[^MultiFnImpl multifn dispatch-value]
(.effectiveMethod multifn dispatch-value))

(defonceinterface Cache
(cachedMethod [dispatch-value])
(cacheMethodBang [dispatch-value method])
(clearCacheBang [])
(^methodical.interface.Cache emptyCopy []))
#?(:clj
(defonceinterface Cache
(cachedMethod [dispatch-value])
(cacheMethodBang [dispatch-value method])
(clearCacheBang [])
(^methodical.interface.Cache emptyCopy []))
:cljs
(def Cache))

(defn cached-method
"Return cached effective method for `dispatch-value`, if it exists in the cache."
Expand Down

0 comments on commit 7ebbd0b

Please sign in to comment.