summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-04-12 13:54:50 +0000
committerRich Hickey <richhickey@gmail.com>2009-04-12 13:54:50 +0000
commit31b821a98adafbdc090ad33db69ed46f9e9bb31d (patch)
tree90821f5868613524cf266d30eeef27284d009818 /src
parentac2374f91a047f119127163a96158d2eb9a204b7 (diff)
:post-init option for gen-class [issue 45], patch from Chouser
Diffstat (limited to 'src')
-rw-r--r--src/clj/clojure/genclass.clj34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/clj/clojure/genclass.clj b/src/clj/clojure/genclass.clj
index 57c7140c..4947b3b3 100644
--- a/src/clj/clojure/genclass.clj
+++ b/src/clj/clojure/genclass.clj
@@ -93,7 +93,7 @@
(defn- generate-class [options-map]
(let [default-options {:prefix "-" :load-impl-ns true :impl-ns (ns-name *ns*)}
{:keys [name extends implements constructors methods main factory state init exposes
- exposes-methods prefix load-impl-ns impl-ns]}
+ exposes-methods prefix load-impl-ns impl-ns post-init]}
(merge default-options options-map)
name (str name)
super (if extends (the-class extends) Object)
@@ -117,6 +117,7 @@
(make-array Type 0)))
super-type #^Type (totype super)
init-name (str init)
+ post-init-name (str post-init)
factory-name (str factory)
state-name (str state)
main-name "main"
@@ -132,6 +133,7 @@
sigs-by-name (apply merge-with concat {} all-sigs)
overloads (into {} (filter (fn [[m s]] (next s)) sigs-by-name))
var-fields (concat (when init [init-name])
+ (when post-init [post-init-name])
(when main [main-name])
;(when exposes-methods (map str (vals exposes-methods)))
(distinct (concat (keys sigs-by-name)
@@ -267,6 +269,8 @@
gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv)
no-init-label (. gen newLabel)
end-label (. gen newLabel)
+ no-post-init-label (. gen newLabel)
+ end-post-init-label (. gen newLabel)
nth-method (. Method (getMethod "Object nth(Object,int)"))
local (. gen newLocal obj-type)]
(. gen (visitCode))
@@ -318,6 +322,26 @@
(. gen (invokeConstructor super-type super-m)))
(throw (new Exception ":init not specified, but ctor and super ctor args differ"))))
+ (when post-init
+ (emit-get-var gen post-init-name)
+ (. gen dup)
+ (. gen ifNull no-post-init-label)
+ (.checkCast gen ifn-type)
+ (. gen (loadThis))
+ ;box init args
+ (dotimes [i (count pclasses)]
+ (. gen (loadArg i))
+ (. clojure.lang.Compiler$HostExpr (emitBoxReturn nil gen (nth pclasses i))))
+ ;call init fn
+ (. gen (invokeInterface ifn-type (new Method "invoke" obj-type
+ (arg-types (inc (count ptypes))))))
+ (. gen pop)
+ (. gen goTo end-post-init-label)
+ ;no init found
+ (. gen mark no-post-init-label)
+ (. gen (throwException ex-type (str impl-pkg-name "/" prefix post-init-name " not defined")))
+ (. gen mark end-post-init-label))
+
(. gen (returnValue))
(. gen (endMethod))
;factory
@@ -495,6 +519,14 @@
constructor signature. When you supply this, you must supply an :init
specifier.
+ :post-init name
+
+ If supplied, names a function that will be called with the object as
+ the first argument, followed by the arguments to the constructor.
+ It will be called every time an object of this class is created,
+ immediately after all the inherited constructors have completed.
+ It's return value is ignored.
+
:methods [ [name [param-types] return-type], ...]
The generated class automatically defines all of the non-private