Skip to content

Instantly share code, notes, and snippets.

@paulp
Created May 7, 2014 17:52
Show Gist options
  • Save paulp/c8d50c508d1ecf51ae86 to your computer and use it in GitHub Desktop.
Save paulp/c8d50c508d1ecf51ae86 to your computer and use it in GitHub Desktop.
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
}
}
}
@samskivert
Copy link

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.

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