Skip to content

Commit 1ecb162

Browse files
committed
More stuff
1 parent 80f5c15 commit 1ecb162

File tree

2 files changed

+74
-3
lines changed

2 files changed

+74
-3
lines changed

src/basilisp/core.lpy

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7091,17 +7091,43 @@
70917091
(. proxy (_update-proxy-mappings mappings))
70927092
proxy)))
70937093

7094-
;; TODO: how to handle multi-arity fns
70957094
;; TODO: kwargs on supertypes
7095+
;; TODO: check interface/superclass method membership
7096+
;; TODO: check if duplicate methods
70967097
(defmacro proxy
7098+
"Create a new proxy class instance.
7099+
7100+
The proxy class may implement 0 or more interface (or subclass 0 or more classes),
7101+
which are given as the vector ``class-and-interfaces``. If 0 such supertypes are
7102+
provided, Python's ``object`` type will be used.
7103+
7104+
If the supertype constructors take arguments, those arguments are given in the
7105+
potentially empty vector ``args``.
7106+
7107+
The remaining forms (if any) should be method overrides for any methods of the
7108+
declared classes and interfaces. Not every method needs to be overridden. Override
7109+
declarations may be multi-arity to simulate multi-arity methods. Overrides need
7110+
not include ``this``, as it will be automatically added and is available within
7111+
all proxy methods. Proxy methods may access the proxy superclass using the
7112+
:lpy:fn:`proxy-super` macro.
7113+
7114+
Overrides take the following form::
7115+
7116+
(single-arity []
7117+
...)
7118+
7119+
(multi-arity
7120+
([] ...)
7121+
([arg1] ...)
7122+
([arg1 & others] ...))"
70977123
[class-and-interfaces args & fs]
70987124
(let [formatted-arity (fn [method-name [arg-vec & body]]
7099-
[(name method-name)
7125+
[(munge method-name)
71007126
(apply list 'fn method-name (vec (concat ['this] arg-vec)) body)])
71017127
methods (mapcat (fn [[method-name & body]]
71027128
(if (vector? (first body))
71037129
(formatted-arity method-name body)
7104-
(map (partial formatted-arity method-name) body)))
7130+
(mapcat (partial formatted-arity method-name) body)))
71057131
fs)]
71067132
#_(println methods)
71077133
`((get-proxy-class ~@class-and-interfaces) ~(apply hash-map methods) ~@args)))

tests/basilisp/test_proxies.lpy

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
(ns tests.basilisp.test-proxies
2+
(:require
3+
[basilisp.test :as test :refer [deftest is are testing]]))
4+
5+
(def no-op-proxy
6+
(proxy [] []))
7+
8+
(deftest get-proxy-class-test
9+
(is (identical? (get-proxy-class) (get-proxy-class)))
10+
(is (python/issubclass (get-proxy-class) basilisp.lang.interfaces/IProxy)))
11+
12+
(deftest proxy-mappings-test
13+
(is (= {} (proxy-mappings no-op-proxy)))
14+
(is (thrown? basilisp.lang.exception/ExceptionInfo
15+
(proxy-mappings (python/object)))))
16+
17+
(deftest construct-proxy-test
18+
(let [obj-proxy-cls (get-proxy-class)]
19+
(is (instance? obj-proxy-cls (construct-proxy obj-proxy-cls)))
20+
(is (thrown? basilisp.lang.exception/ExceptionInfo
21+
(construct-proxy python/object)))))
22+
23+
(definterface ToString
24+
(to-string [])
25+
(to-string [arg1])
26+
(to-string [arg1 & rest]))
27+
28+
;; TODO: (?) needs to be mutable or setting _proxy_mappings on the instance fails
29+
(deftype ConcreteToString [^:mutable arg]
30+
ToString
31+
(to-string [this] "0")
32+
(to-string [this arg1] (str "1" arg1))
33+
(to-string [this arg1 & rest] (str "rest" arg1 rest)))
34+
35+
(deftest proxy-test
36+
(testing "multi-arity interface methods"
37+
(let [p (proxy [ConcreteToString] [1]
38+
(to-string
39+
([] "hi i am 0")
40+
([arg1] (str "i am 1 " arg1))
41+
([arg1 & args] (str "i am rest " arg1 " " args))))]
42+
(is (= "hi i am 0" (.to-string p)))
43+
(is (= "i am 1 yes" (.to-string p "yes")))
44+
(is (= "i am rest first " (.to-string p "first")))
45+
(is (= "i am rest first (:yes)" (.to-string p "first" :yes))))))

0 commit comments

Comments
 (0)