scala.tools.partest.ASMConverters.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-partest Show documentation
Show all versions of scala-partest Show documentation
testing framework for the Scala compiler.
package scala.tools.partest
import scala.collection.JavaConverters._
import scala.tools.asm
import asm.tree.{ClassNode, MethodNode, InsnList}
/** Makes using ASM from ByteCodeTests more convenient.
*
* Wraps ASM instructions in case classes so that equals and toString work
* for the purpose of bytecode diffing and pretty printing.
*/
trait ASMConverters {
// wrap ASM's instructions so we get case class-style `equals` and `toString`
object instructions {
def fromMethod(meth: MethodNode): List[Instruction] = {
val insns = meth.instructions
val asmToScala = new AsmToScala{ def labelIndex(l: asm.tree.AbstractInsnNode) = insns.indexOf(l) }
asmToScala.mapOver(insns.iterator.asScala.toList).asInstanceOf[List[Instruction]]
}
sealed abstract class Instruction { def opcode: String }
case class Field (opcode: String, desc: String, name: String, owner: String) extends Instruction
case class Incr (opcode: String, incr: Int, `var`: Int) extends Instruction
case class Op (opcode: String) extends Instruction
case class IntOp (opcode: String, operand: Int) extends Instruction
case class Jump (opcode: String, label: Label) extends Instruction
case class Ldc (opcode: String, cst: Any) extends Instruction
case class LookupSwitch (opcode: String, dflt: Label, keys: List[Integer], labels: List[Label]) extends Instruction
case class TableSwitch (opcode: String, dflt: Label, max: Int, min: Int, labels: List[Label]) extends Instruction
case class Method (opcode: String, desc: String, name: String, owner: String) extends Instruction
case class NewArray (opcode: String, desc: String, dims: Int) extends Instruction
case class TypeOp (opcode: String, desc: String) extends Instruction
case class VarOp (opcode: String, `var`: Int) extends Instruction
case class Label (offset: Int) extends Instruction { def opcode: String = "" }
case class FrameEntry (local: List[Any], stack: List[Any]) extends Instruction { def opcode: String = "" }
case class LineNumber (line: Int, start: Label) extends Instruction { def opcode: String = "" }
}
abstract class AsmToScala {
import instructions._
def labelIndex(l: asm.tree.AbstractInsnNode): Int
def mapOver(is: List[Any]): List[Any] = is map {
case i: asm.tree.AbstractInsnNode => apply(i)
case x => x
}
def op(i: asm.tree.AbstractInsnNode) = if (asm.util.Printer.OPCODES.isDefinedAt(i.getOpcode)) asm.util.Printer.OPCODES(i.getOpcode) else "?"
def lst[T](xs: java.util.List[T]): List[T] = if (xs == null) Nil else xs.asScala.toList
def apply(l: asm.tree.LabelNode): Label = this(l: asm.tree.AbstractInsnNode).asInstanceOf[Label]
def apply(x: asm.tree.AbstractInsnNode): Instruction = x match {
case i: asm.tree.FieldInsnNode => Field (op(i), i.desc: String, i.name: String, i.owner: String)
case i: asm.tree.IincInsnNode => Incr (op(i), i.incr: Int, i.`var`: Int)
case i: asm.tree.InsnNode => Op (op(i))
case i: asm.tree.IntInsnNode => IntOp (op(i), i.operand: Int)
case i: asm.tree.JumpInsnNode => Jump (op(i), this(i.label))
case i: asm.tree.LdcInsnNode => Ldc (op(i), i.cst: Any)
case i: asm.tree.LookupSwitchInsnNode => LookupSwitch (op(i), this(i.dflt), lst(i.keys), mapOver(lst(i.labels)).asInstanceOf[List[Label]])
case i: asm.tree.TableSwitchInsnNode => TableSwitch (op(i), this(i.dflt), i.max: Int, i.min: Int, mapOver(lst(i.labels)).asInstanceOf[List[Label]])
case i: asm.tree.MethodInsnNode => Method (op(i), i.desc: String, i.name: String, i.owner: String)
case i: asm.tree.MultiANewArrayInsnNode => NewArray (op(i), i.desc: String, i.dims: Int)
case i: asm.tree.TypeInsnNode => TypeOp (op(i), i.desc: String)
case i: asm.tree.VarInsnNode => VarOp (op(i), i.`var`: Int)
case i: asm.tree.LabelNode => Label (labelIndex(x))
case i: asm.tree.FrameNode => FrameEntry (mapOver(lst(i.local)), mapOver(lst(i.stack)))
case i: asm.tree.LineNumberNode => LineNumber (i.line: Int, this(i.start): Label)
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy