Created
May 7, 2014 17:52
-
-
Save paulp/c8d50c508d1ecf51ae86 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package improving | |
package jvm | |
package pool | |
import JvmConstants._ | |
/* | |
4.2.2 Unqualified Names | |
Names of methods, fields and local variables are stored as unqualified | |
names. Unqualified names must not contain the characters '.', ';', '[' | |
or '/'. Method names are further constrained so that, with the exception | |
of the special method names <init> and <clinit> (§3.9), they must not | |
contain the characters '<' or '>'. | |
4.3 Descriptors and Signatures | |
A descriptor is a string representing the type of a field or method. | |
Descriptors are represented in the class file format using modified | |
UTF-8 strings (§4.4.7) and thus may be drawn, where not further | |
constrained, from the entire Unicode character set. A signature is a | |
string representing the generic type of a field or method, or generic | |
type information for a class declaration. | |
*/ | |
sealed trait PoolEntry { override def toString = this.entryString } | |
sealed trait Name_Info extends PoolEntry { def name_index: UShort } | |
sealed trait Ref_Info extends PoolEntry { def class_index: UShort ; def name_and_type_index: UShort } | |
final case class Fieldref_info(class_index: UShort, name_and_type_index: UShort) extends Ref_Info | |
final case class InterfaceMethodref_info(class_index: UShort, name_and_type_index: UShort) extends Ref_Info | |
final case class Methodref_info(class_index: UShort, name_and_type_index: UShort) extends Ref_Info | |
final case class Class_info(name_index: UShort) extends Name_Info | |
final case class NameAndType_info(name_index: UShort, descriptor_index: UShort) extends Name_Info | |
final case class String_info(string_index: UShort) extends PoolEntry | |
final case class Double_info(value: Double) extends PoolEntry | |
final case class Float_info(value: Float) extends PoolEntry | |
final case class Integer_info(value: Int) extends PoolEntry | |
final case class Long_info(value: Long) extends PoolEntry | |
final case class Utf8_info(value: String) extends PoolEntry | |
final case object NoEntry extends PoolEntry { } | |
object PoolEntry { | |
implicit class PoolEntryOps(val entry: PoolEntry) extends AnyVal { | |
def width: Int = (tag: @switch) match { | |
case CONSTANT_Double | CONSTANT_Long => 2 | |
case _ => 1 | |
} | |
def stringValue: String = entry match { | |
case Utf8_info(value) => s"Asciz $value".trim | |
case _ => sys.error(s"Not a String-valued constant pool entry: $this") | |
} | |
def tag: Byte = entry match { | |
case _: Fieldref_info => CONSTANT_Fieldref | |
case _: InterfaceMethodref_info => CONSTANT_InterfaceMethodref | |
case _: Methodref_info => CONSTANT_Methodref | |
case _: Class_info => CONSTANT_Class | |
case _: NameAndType_info => CONSTANT_NameAndType | |
case _: String_info => CONSTANT_String | |
case _: Double_info => CONSTANT_Double | |
case _: Float_info => CONSTANT_Float | |
case _: Integer_info => CONSTANT_Integer | |
case _: Long_info => CONSTANT_Long | |
case _: Utf8_info => CONSTANT_Utf8 | |
case NoEntry => -1 | |
} | |
def entryString: String = entry match { | |
case Methodref_info(cindex, nindex) => "Methodref_info #%d:#%d;".format(cindex.toInt, nindex.toInt) | |
case InterfaceMethodref_info(cindex, nindex) => "InterfaceMethodref_info #%d:#%d;".format(cindex.toInt, nindex.toInt) | |
case NameAndType_info(nindex, dindex) => "NameAndType #%d:#%d;".format(nindex.toInt, dindex.toInt) | |
case Fieldref_info(cindex, nindex) => "Fieldref_info #%d:#%d;".format(cindex.toInt, nindex.toInt) | |
case _ => entry.getClass.getName.split("[.$]").last | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm probably being short sighted, but I see a whole lot of hidden cost and no especial value over using implementation inheritance. As long as there are no private fields in your case classes, anyone can extend your code with SpecialPoolEntryOps themselves or just use functions that take a PoolEntry as an argument, like God and Phil Wadler intended.
When I see a giant cascading series of type tests like you have in "def tag" I can't help but think ur doin it wrong.