Skip to content

Instantly share code, notes, and snippets.

@warmuuh
Created September 26, 2012 12:55
Show Gist options
  • Save warmuuh/3787856 to your computer and use it in GitHub Desktop.
Save warmuuh/3787856 to your computer and use it in GitHub Desktop.
scala asm dsl
package wrm
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Label
import org.objectweb.asm.Opcodes
import org.objectweb.asm.FieldVisitor
import org.objectweb.asm.AnnotationVisitor
import org.objectweb.asm.ClassWriter
object invokeHelper1 {
def apply(method: String) {}
}
trait Container {
def start(cw:ClassWriter)
def end(cw:ClassWriter)
}
case class ClazzDefinition(f: String) extends Container{
val name = f
var superType: String = null
def extend[A](c:Class[A]) = { superType = c.getName().replace(".", "/"); this }
override def start(cw:ClassWriter) = cw.visit(49, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, name, null, superType, null)
override def end(cw:ClassWriter) = cw.visitEnd()
object ClazzContent{
}
}
case class MethodDefinition(m: String) extends Container{
val name = m
var signature: String = "()"
var typeId: String = null
var mv:MethodVisitor = _
def of[A](c:Class[A]) = { typeId = c.getName().replace(".", "/"); this }
def accepts[A] (cs:Class[A]*) = {
signature = "(" + cs.map(toInternal).reduceLeft(_+","+_) + ")"
this
}
def returns[A] (cs:Class[A]) = this
def returns (cs:ASM#SpecialType) = {cs match {
case nothing => signature += "V"
}
this
}
def toInternal[A](c:Class[A]) = {
"L" + c.getName().replace(".","/") + ";"
}
override def start(cw:ClassWriter) = mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, signature, null, null)
override def end(cw:ClassWriter) = mv.visitEnd()
object MethodContent {
var stack = 0;
var local = 1;
def exec(f: => Unit) = { f }
// def STACK(s: Int): stackHelper = stackHelper(s)
// case class stackHelper(s: Int) {
// def LOCAL(l: Int) = {; ASM}
// }
def ALOAD(idx: Int) = {exec { stack+=1;mv.visitVarInsn(Opcodes.ALOAD, idx)} ; this}
def NEW(typeId: String) = {exec { mv.visitTypeInsn(Opcodes.NEW, typeId)} ; this}
def DUP = {exec { stack+=1;mv.visitInsn(Opcodes.DUP)} ; this}
def INVOKESPECIAL[T](m: MethodDefinition) = {exec { mv.visitMethodInsn(Opcodes.INVOKESPECIAL, m.typeId, m.name, m.signature)}; this }
def PUTFIELD(f: FieldDefinition) = {exec { mv.visitFieldInsn(Opcodes.PUTFIELD, f.typeId, f.name, f.signature);}; this }
def GETSTATIC(f: FieldDefinition) = {exec { stack+=1;mv.visitFieldInsn(Opcodes.GETSTATIC, f.typeId, f.name, f.signature);}; this } //todo: dirty: f.signature is actually a internal type!
def INVOKEVIRTUAL(m: MethodDefinition) = {exec { mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, m.typeId, m.name, m.signature); }; this}
def LDC(str: String) = {exec { stack+=1;mv.visitLdcInsn(str) }; this}
def PUSH = {stack+=1; this}
def POP = {; this}
def RETURN() = { mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(stack, local); ASM}
}
}
case class FieldDefinition(f: String) {
val name = f
var signature: String = null
var typeId: String = null
def of[A](c:Class[A]) = { typeId = c.getName().replace(".", "/"); this }
def withType[A] (cs:Class[A]) = {signature = toInternal(cs); this}
def withType (cs:ASM#SpecialType) = this
def toInternal[A](c:Class[A]) = {
"L" + c.getName().replace(".","/") + ";"
}
}
object ASM extends ASM
class ASM {
case class SpecialType
case object nothing extends SpecialType
var curResult = null
implicit val cw = new ClassWriter(0);
var fv: FieldVisitor = null
var av0: AnnotationVisitor = null
def apply(source: String)(fn: => Unit): ClassWriter = {
cw.visitSource("Hello.java", null);
fn
return cw
}
var containerStack:List[Container] = Nil
def _new(c: ClazzDefinition) = { containerStack = c :: containerStack; c.start(cw); this}
def _new(c: MethodDefinition) = { containerStack = c :: containerStack; c.start(cw); c.MethodContent}
def method(s:String) = MethodDefinition(s)
def field(s:String) = FieldDefinition(s)
def clazz(s:String) = ClazzDefinition(s)
def _end() = {containerStack.head.end(cw); containerStack = containerStack.tail ; this}
}
ASM("Hello.java")(
_new (clazz ("Hello") extend classOf[Object])
_new (method ("<init>") returns nothing)
ALOAD 0
INVOKESPECIAL (method ("<init>") of classOf[Object] returns nothing)
RETURN()
_end()
_new ( method ("main") accepts classOf[String] returns nothing)
GETSTATIC (field ("out") of classOf[java.lang.System] withType classOf[PrintStream])
LDC "hello"
INVOKEVIRTUAL (method ("println") of classOf[PrintStream] accepts classOf[String] returns nothing)
RETURN ()
_end()
_end
).toByteArray()
@gre
Copy link

gre commented Jan 8, 2015

useful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment