Skip to content

Instantly share code, notes, and snippets.

@athos
Created June 18, 2011 12:34
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save athos/1033052 to your computer and use it in GitHub Desktop.
Save athos/1033052 to your computer and use it in GitHub Desktop.
An example code to generate a class with ASM in Clojure.
(import '[clojure.asm Opcodes Type ClassWriter]
'[clojure.asm.commons Method GeneratorAdapter])
(defn make-class [name]
(let [cw (ClassWriter. ClassWriter/COMPUTE_FRAMES)
init (Method/getMethod "void <init>()")
meth (Method/getMethod "int fact(int)")]
(.visit cw Opcodes/V1_6 Opcodes/ACC_PUBLIC (.replace name \. \/) nil "java/lang/Object" nil)
(doto (GeneratorAdapter. Opcodes/ACC_PUBLIC init nil nil cw)
(.visitCode)
(.loadThis)
(.invokeConstructor (Type/getType Object) init)
(.returnValue)
(.endMethod))
(let [mv (GeneratorAdapter. Opcodes/ACC_PUBLIC meth nil nil cw)
INT (Type/getType Integer/TYPE)
acc (.newLocal mv INT)
beginning (.newLabel mv)
then (.newLabel mv)]
(doto mv
(.visitCode)
(.push 1)
(.storeLocal acc)
(.mark beginning)
(.visitCode)
(.loadArg 0)
(.ifZCmp GeneratorAdapter/NE then)
(.loadLocal acc)
(.returnValue)
(.mark then)
(.loadArg 0)
(.dup)
(.loadLocal acc)
(.math GeneratorAdapter/MUL INT)
(.storeLocal acc)
(.push 1)
(.math GeneratorAdapter/SUB INT)
(.storeArg 0)
(.goTo beginning)
(.endMethod)))
(.visitEnd cw)
(let [b (.toByteArray cw)
cl (clojure.lang.DynamicClassLoader.)]
(.defineClass cl name b nil))))
(comment
user=> (make-class "foo.Foo")
foo.Foo
user=> (def o (construct-proxy *1))
#'user/o
user=> (.fact o 6)
720
user=>
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment