-
-
Notifications
You must be signed in to change notification settings - Fork 5
Interface Implementation
Justin Conklin edited this page Oct 27, 2017
·
3 revisions
The namespace insn.op
defines a corresponding helper fn for every bytecode instruction, all of which take an ASM MethodVisitor
as their first argument. Below, instead of a sequence of ops, :emit
is a fn that is passed the visitor object when the class bytecode is being written.
(require '[insn.core :as insn]
'[insn.op :as op])
(insn/define
{:flags #{:public :interface}
:name 'my.math.Inc
:methods [{:flags #{:public :abstract}, :name :inc, :desc [:long :long]}
{:flags #{:public :abstract}, :name :inc, :desc [:double :double]}]})
(defn make-inc
"Return an emit fn that will increment the given primitive type."
[type]
(let [[load const add ret]
(if (= type :long)
[op/lload op/lconst-1 op/ladd op/lreturn]
[op/dload op/dconst-1 op/dadd op/dreturn])]
(fn [v]
(doto v (load 1) const add ret))))
(def ops
(insn/new-instance
{:flags #{:public}, :name 'my.math.IncImpl, :interfaces ['my.math.Inc]
:methods [{:flags #{:public}, :name :inc, :desc [:long :long]
:emit (make-inc :long)}
{:flags #{:public}, :name :inc, :desc [:double :double]
:emit (make-inc :double)}]}))
(.inc ops 42) ;; => 43
(.inc ops 43.0) ;; => 44.0
We use the new-instance
helper to quickly define and instantiate an instance of our class.
Using an :emit
fn can be useful when performance is of utmost importance.