|
36 | 36 | (into-array (map totype cs))
|
37 | 37 | (make-array Type 0)))
|
38 | 38 | super-type (totype super)
|
39 |
| - map-type (totype PersistentHashMap) |
| 39 | + imap-type (totype IPersistentMap) |
40 | 40 | ifn-type (totype clojure.lang.IFn)
|
41 | 41 | obj-type (totype Object)
|
42 | 42 | sym-type (totype clojure.lang.Symbol)
|
|
54 | 54 | decl-type (. Type (getType (. meth (getDeclaringClass))))]
|
55 | 55 | (. gen (visitCode))
|
56 | 56 | (. gen (loadThis))
|
57 |
| - (. gen (getField ctype fmap map-type)) |
58 |
| - ;get symbol corresponding to name |
| 57 | + (. gen (getField ctype fmap imap-type)) |
| 58 | + |
59 | 59 | (. gen (push (. meth (getName))))
|
60 |
| - (. gen (invokeStatic sym-type (. Method (getMethod "clojure.lang.Symbol create(String)")))) |
61 | 60 | ;lookup fn in map
|
62 | 61 | (. gen (invokeStatic rt-type (. Method (getMethod "Object get(Object, Object)"))))
|
63 | 62 | (. gen (dup))
|
|
94 | 93 | (into-array (map iname (cons IProxy interfaces)))))
|
95 | 94 | ;add field for fn mappings
|
96 | 95 | (. cv (visitField (+ (. Opcodes ACC_PRIVATE) (. Opcodes ACC_VOLATILE))
|
97 |
| - fmap (. map-type (getDescriptor)) nil nil)) |
| 96 | + fmap (. imap-type (getDescriptor)) nil nil)) |
98 | 97 | ;add ctors matching/calling super's
|
99 | 98 | (doseq [#^Constructor ctor (. super (getDeclaredConstructors))]
|
100 | 99 | (when-not (. Modifier (isPrivate (. ctor (getModifiers))))
|
|
107 | 106 | (. gen (dup))
|
108 | 107 | (. gen (loadArgs))
|
109 | 108 | (. gen (invokeConstructor super-type m))
|
110 |
| - ;init fmap |
111 |
| - (. gen (getStatic map-type "EMPTY" map-type)) |
112 |
| - (. gen (putField ctype fmap map-type)) |
113 | 109 |
|
114 | 110 | (. gen (returnValue))
|
115 | 111 | (. gen (endMethod)))))
|
116 | 112 | ;add IProxy methods
|
| 113 | + (let [m (. Method (getMethod "void __initClojureFnMappings(clojure.lang.IPersistentMap)")) |
| 114 | + gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv)] |
| 115 | + (. gen (visitCode)) |
| 116 | + (. gen (loadThis)) |
| 117 | + (. gen (loadArgs)) |
| 118 | + (. gen (putField ctype fmap imap-type)) |
| 119 | + |
| 120 | + (. gen (returnValue)) |
| 121 | + (. gen (endMethod))) |
117 | 122 | (let [m (. Method (getMethod "void __updateClojureFnMappings(clojure.lang.IPersistentMap)"))
|
118 | 123 | gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv)]
|
119 | 124 | (. gen (visitCode))
|
120 | 125 | (. gen (loadThis))
|
121 | 126 | (. gen (dup))
|
122 |
| - (. gen (getField ctype fmap map-type)) |
| 127 | + (. gen (getField ctype fmap imap-type)) |
123 | 128 | (. gen (loadArgs))
|
124 | 129 | (. gen (invokeInterface (totype clojure.lang.IPersistentCollection)
|
125 | 130 | (. Method (getMethod "clojure.lang.IPersistentCollection cons(Object)"))))
|
126 |
| - (. gen (checkCast map-type)) |
127 |
| - (. gen (putField ctype fmap map-type)) |
| 131 | + (. gen (checkCast imap-type)) |
| 132 | + (. gen (putField ctype fmap imap-type)) |
128 | 133 |
|
129 | 134 | (. gen (returnValue))
|
130 | 135 | (. gen (endMethod)))
|
131 | 136 | (let [m (. Method (getMethod "clojure.lang.IPersistentMap __getClojureFnMappings()"))
|
132 | 137 | gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv)]
|
133 | 138 | (. gen (visitCode))
|
134 | 139 | (. gen (loadThis))
|
135 |
| - (. gen (getField ctype fmap map-type)) |
| 140 | + (. gen (getField ctype fmap imap-type)) |
136 | 141 | (. gen (returnValue))
|
137 | 142 | (. gen (endMethod)))
|
138 | 143 |
|
|
210 | 215 | [c & ctor-args]
|
211 | 216 | (. Reflector (invokeConstructor c (to-array ctor-args))))
|
212 | 217 |
|
| 218 | +(defn init-proxy |
| 219 | + "Takes a proxy instance and a map of strings (which must |
| 220 | + correspond to methods of the proxy superclass/superinterfaces) to |
| 221 | + fns (which must take arguments matching the corresponding method, |
| 222 | + plus an additional (explicit) first arg corresponding to this, and |
| 223 | + sets the proxy's fn map." |
| 224 | + [#^IProxy proxy mappings] |
| 225 | + (. proxy (__initClojureFnMappings mappings))) |
| 226 | + |
213 | 227 | (defn update-proxy
|
214 |
| - "Takes a proxy instance and a map of symbols (whose names must |
| 228 | + "Takes a proxy instance and a map of strings (which must |
215 | 229 | correspond to methods of the proxy superclass/superinterfaces) to
|
216 | 230 | fns (which must take arguments matching the corresponding method,
|
217 | 231 | plus an additional (explicit) first arg corresponding to this, and
|
|
259 | 273 | (clojure.lang.Compiler/writeClassFile cname bytecode)))
|
260 | 274 | pc-effect (apply get-proxy-class bases)
|
261 | 275 | pname (proxy-name super interfaces)]
|
262 |
| - `(let [pc# (get-proxy-class ~@class-and-interfaces) |
| 276 | + `(let [;pc# (get-proxy-class ~@class-and-interfaces) |
263 | 277 | p# (new ~(symbol pname) ~@args)] ;(construct-proxy pc# ~@args)]
|
264 |
| - (update-proxy p# |
| 278 | + (init-proxy p# |
265 | 279 | ~(loop [fmap {} fs fs]
|
266 | 280 | (if fs
|
267 | 281 | (let [[sym & meths] (first fs)
|
|
271 | 285 | meths (map (fn [[params & body]]
|
272 | 286 | (cons (apply vector 'this params) body))
|
273 | 287 | meths)]
|
274 |
| - (recur (assoc fmap (list `quote (symbol (name sym))) (cons `fn meths)) (rest fs))) |
| 288 | + (recur (assoc fmap (name sym) (cons `fn meths)) (rest fs))) |
275 | 289 | fmap)))
|
276 | 290 | p#)))
|
277 | 291 |
|
|
286 | 300 | "Use to call a superclass method in the body of a proxy method.
|
287 | 301 | Note, expansion captures 'this"
|
288 | 302 | [meth & args]
|
289 |
| - `(proxy-call-with-super (fn [] (. ~'this ~meth ~@args)) ~'this '~(symbol (name meth)))) |
| 303 | + `(proxy-call-with-super (fn [] (. ~'this ~meth ~@args)) ~'this ~(name meth))) |
290 | 304 |
|
291 | 305 | (defn bean
|
292 | 306 | "Takes a Java object and returns a read-only implementation of the
|
|
0 commit comments