alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (ScalaSig.scala)

This example Scala source code file (ScalaSig.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Scala tags/keywords

annotinfo, bytecode, bytecode, children, entry, entryparser, entryparser, int, int, option, scalasig, scalasig, seq, symbol

The Scala ScalaSig.scala source code

/*     ___ ____ ___   __   ___   ___
**    / _// __// _ | / /  / _ | / _ \    Scala classfile decoder
**  __\ \/ /__/ __ |/ /__/ __ |/ ___/    (c) 2003-2011, LAMP/EPFL
** /____/\___/_/ |_/____/_/ |_/_/        http://scala-lang.org/
**
*/


package scala.tools.scalap
package scalax
package rules
package scalasig

import ClassFileParser.{ ConstValueIndex, Annotation }
import scala.reflect.generic.ByteCodecs

object ScalaSigParser {
  import Main.{ SCALA_SIG, SCALA_SIG_ANNOTATION, BYTES_VALUE }
  
  def scalaSigFromAnnotation(classFile: ClassFile): Option[ScalaSig] = {
    import classFile._

    classFile.annotation(SCALA_SIG_ANNOTATION) map {
      case Annotation(_, elements) =>
        val bytesElem = elements.find(elem => constant(elem.elementNameIndex) == BYTES_VALUE).get
        val bytes = ((bytesElem.elementValue match {case ConstValueIndex(index) => constantWrapped(index)})
                .asInstanceOf[StringBytesPair].bytes)
        val length = ByteCodecs.decode(bytes)
        
        ScalaSigAttributeParsers.parse(ByteCode(bytes.take(length)))
    }
  }

  def scalaSigFromAttribute(classFile: ClassFile) : Option[ScalaSig] =
    classFile.attribute(SCALA_SIG).map(_.byteCode).map(ScalaSigAttributeParsers.parse)
  
  def parse(classFile: ClassFile): Option[ScalaSig] = {
    val scalaSig  = scalaSigFromAttribute(classFile)
    
    scalaSig match {
      // No entries in ScalaSig attribute implies that the signature is stored in the annotation
      case Some(ScalaSig(_, _, entries)) if entries.length == 0 =>
        scalaSigFromAnnotation(classFile)
      case x => x
    }
  }
    
  def parse(clazz : Class[_]): Option[ScalaSig] = {
    val byteCode  = ByteCode.forClass(clazz)
    val classFile = ClassFileParser.parse(byteCode)

    parse(classFile)
  }
}

object ScalaSigAttributeParsers extends ByteCodeReader  {
  def parse(byteCode : ByteCode) = expect(scalaSig)(byteCode)

  val nat = apply {
    def natN(in : ByteCode, x : Int) : Result[ByteCode, Int, Nothing] = in.nextByte match {
      case Success(out, b) => {
        val y = (x << 7) + (b & 0x7f)
        if ((b & 0x80) == 0) Success(out, y) else natN(out, y)
      }
      case _ => Failure
    }
    in => natN(in, 0)
  }

  val rawBytes = nat >> bytes
  val entry = nat ~ rawBytes
  val symtab = nat >> entry.times
  val scalaSig = nat ~ nat ~ symtab ^~~^ ScalaSig

  val utf8 = read(x => x.fromUTF8StringAndBytes.string)
  val longValue = read(_ toLong)
}

case class ScalaSig(majorVersion : Int, minorVersion : Int, table : Seq[Int ~ ByteCode]) extends DefaultMemoisable {

  case class Entry(index : Int, entryType : Int, byteCode : ByteCode) extends DefaultMemoisable {
    def scalaSig = ScalaSig.this

    def setByteCode(byteCode : ByteCode) = Entry(index, entryType, byteCode)
  }

  def hasEntry(index : Int) = table isDefinedAt index

  def getEntry(index : Int) = {
    val entryType ~ byteCode = table(index)
    Entry(index, entryType, byteCode)
  }

  def parseEntry(index : Int) = applyRule(ScalaSigParsers.parseEntry(ScalaSigEntryParsers.entry)(index))

  implicit def applyRule[A](parser : ScalaSigParsers.Parser[A]) = ScalaSigParsers.expect(parser)(this)

  override def toString = "ScalaSig version " + majorVersion + "." + minorVersion + {
    for (i <- 0 until table.size) yield i + ":\t" + parseEntry(i) // + "\n\t" + getEntry(i)
  }.mkString("\n", "\n", "")

  lazy val symbols : Seq[Symbol] = ScalaSigParsers.symbols

  lazy val topLevelClasses : List[ClassSymbol] = ScalaSigParsers.topLevelClasses
  lazy val topLevelObjects : List[ObjectSymbol] = ScalaSigParsers.topLevelObjects
}

object ScalaSigParsers extends RulesWithState with MemoisableRules {
  type S = ScalaSig
  type Parser[A] = Rule[A, String]

  val symTab = read(_.table)
  val size = symTab ^^ (_.size)

  def entry(index : Int) = memo(("entry", index)) {
    cond(_ hasEntry index) -~ read(_ getEntry index) >-> { entry => Success(entry, entry.entryType) }
  }

  def parseEntry[A](parser : ScalaSigEntryParsers.EntryParser[A])(index : Int) : Parser[A] =
    entry(index) -~ parser >> { a => entry => Success(entry.scalaSig, a) }

  def allEntries[A](f : ScalaSigEntryParsers.EntryParser[A]) = size >> { n => anyOf((0 until n) map parseEntry(f)) }

  lazy val entries = allEntries(ScalaSigEntryParsers.entry) as "entries"
  lazy val symbols = allEntries(ScalaSigEntryParsers.symbol) as "symbols"
  lazy val methods = allEntries(ScalaSigEntryParsers.methodSymbol) as "methods"
  lazy val attributes = allEntries(ScalaSigEntryParsers.attributeInfo) as "attributes"

  lazy val topLevelClasses = allEntries(ScalaSigEntryParsers.topLevelClass)
  lazy val topLevelObjects = allEntries(ScalaSigEntryParsers.topLevelObject)
}

object ScalaSigEntryParsers extends RulesWithState with MemoisableRules {
  import ScalaSigAttributeParsers.{nat, utf8, longValue}

  type S = ScalaSig#Entry
  type EntryParser[A] = Rule[A, String]

  implicit def byteCodeEntryParser[A](rule : ScalaSigAttributeParsers.Parser[A]) : EntryParser[A] = apply { entry =>
    rule(entry.byteCode) mapOut (entry setByteCode _)
  }

  def toEntry[A](index : Int) = apply { sigEntry => ScalaSigParsers.entry(index)(sigEntry.scalaSig) }

  def parseEntry[A](parser : EntryParser[A])(index : Int) = (toEntry(index) -~ parser)

  implicit def entryType(code : Int) = key filter (_ == code)

  val index = read(_.index)
  val key = read(_.entryType)

  lazy val entry : EntryParser[Any] = symbol | typeEntry | literal | name | attributeInfo | annotInfo | children | get

  val ref = byteCodeEntryParser(nat)

  val termName = 1 -~ utf8
  val typeName = 2 -~ utf8

  val name = termName | typeName as "name"

  def refTo[A](rule : EntryParser[A]) : EntryParser[A] = ref >>& parseEntry(rule)

  lazy val nameRef = refTo(name)
  lazy val symbolRef = refTo(symbol)
  lazy val typeRef = refTo(typeEntry)
  lazy val constantRef = refTo(literal)

  val symbolInfo = nameRef ~ symbolRef ~ nat ~ (symbolRef?) ~ ref ~ get ^~~~~~^ SymbolInfo

  def symHeader(key: Int) = (key -~ none | (key + 64) -~ nat)

  def symbolEntry(key : Int) = symHeader(key) -~ symbolInfo

  /***************************************************
   * Symbol table attribute format:
   *   Symtab         = nentries_Nat {Entry}
   *   Entry          = 1 TERMNAME len_Nat NameInfo
   *                  | 2 TYPENAME len_Nat NameInfo
   *                  | 3 NONEsym len_Nat
   *                  | 4 TYPEsym len_Nat SymbolInfo
   *                  | 5 ALIASsym len_Nat SymbolInfo
   *                  | 6 CLASSsym len_Nat SymbolInfo [thistype_Ref]
   *                  | 7 MODULEsym len_Nat SymbolInfo
   *                  | 8 VALsym len_Nat [defaultGetter_Ref /* no longer needed*/] SymbolInfo [alias_Ref]
   *                  | 9 EXTref len_Nat name_Ref [owner_Ref]
   *                  | 10 EXTMODCLASSref len_Nat name_Ref [owner_Ref]
   *                  | 11 NOtpe len_Nat
   *                  | 12 NOPREFIXtpe len_Nat
   *                  | 13 THIStpe len_Nat sym_Ref
   *                  | 14 SINGLEtpe len_Nat type_Ref sym_Ref
   *                  | 15 CONSTANTtpe len_Nat constant_Ref
   *                  | 16 TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref}
   *                  | 17 TYPEBOUNDStpe len_Nat tpe_Ref tpe_Ref
   *                  | 18 REFINEDtpe len_Nat classsym_Ref {tpe_Ref}
   *                  | 19 CLASSINFOtpe len_Nat classsym_Ref {tpe_Ref}
   *                  | 20 METHODtpe len_Nat tpe_Ref {sym_Ref}
   *                  | 21 POLYTtpe len_Nat tpe_Ref {sym_Ref}
   *                  | 22 IMPLICITMETHODtpe len_Nat tpe_Ref {sym_Ref} /* no longer needed */
   *                  | 52 SUPERtpe len_Nat tpe_Ref tpe_Ref
   *                  | 24 LITERALunit len_Nat
   *                  | 25 LITERALboolean len_Nat value_Long
   *                  | 26 LITERALbyte len_Nat value_Long
   *                  | 27 LITERALshort len_Nat value_Long
   *                  | 28 LITERALchar len_Nat value_Long
   *                  | 29 LITERALint len_Nat value_Long
   *                  | 30 LITERALlong len_Nat value_Long
   *                  | 31 LITERALfloat len_Nat value_Long
   *                  | 32 LITERALdouble len_Nat value_Long
   *                  | 33 LITERALstring len_Nat name_Ref
   *                  | 34 LITERALnull len_Nat
   *                  | 35 LITERALclass len_Nat tpe_Ref
   *                  | 36 LITERALenum len_Nat sym_Ref
   *                  | 40 SYMANNOT len_Nat sym_Ref AnnotInfoBody
   *                  | 41 CHILDREN len_Nat sym_Ref {sym_Ref}
   *                  | 42 ANNOTATEDtpe len_Nat [sym_Ref /* no longer needed */] tpe_Ref {annotinfo_Ref}
   *                  | 43 ANNOTINFO len_Nat AnnotInfoBody
   *                  | 44 ANNOTARGARRAY len_Nat {constAnnotArg_Ref}
   *                  | 47 DEBRUIJNINDEXtpe len_Nat level_Nat index_Nat
   *                  | 48 EXISTENTIALtpe len_Nat type_Ref {symbol_Ref}
   */
  val noSymbol = 3 -^ NoSymbol
  val typeSymbol = symbolEntry(4) ^^ TypeSymbol as "typeSymbol"
  val aliasSymbol = symbolEntry(5) ^^ AliasSymbol as "alias"
  val classSymbol = symbolEntry(6) ~ (ref?) ^~^ ClassSymbol as "class"
  val objectSymbol = symbolEntry(7) ^^ ObjectSymbol as "object"
  val methodSymbol = symHeader(8) -~ /*(ref?) -~*/ symbolInfo ~ (ref?) ^~^ MethodSymbol as "method"
  val extRef = 9 -~ nameRef ~ (symbolRef?) ~ get ^~~^ ExternalSymbol as "extRef"
  val extModClassRef = 10 -~ nameRef ~ (symbolRef?) ~ get ^~~^ ExternalSymbol as "extModClassRef"

  lazy val symbol : EntryParser[Symbol] = oneOf(
      noSymbol,
      typeSymbol,
      aliasSymbol,
      classSymbol,
      objectSymbol,
      methodSymbol,
      extRef,
      extModClassRef) as "symbol"

  val classSymRef = refTo(classSymbol)
  val attribTreeRef = ref
  val typeLevel = nat
  val typeIndex = nat

  lazy val typeEntry : EntryParser[Type] = oneOf(
      11 -^ NoType,
      12 -^ NoPrefixType,
      13 -~ symbolRef ^^ ThisType,
      14 -~ typeRef ~ symbolRef ^~^ SingleType,
      15 -~ constantRef ^^ ConstantType,
      16 -~ typeRef ~ symbolRef ~ (typeRef*) ^~~^ TypeRefType,
      17 -~ typeRef ~ typeRef ^~^ TypeBoundsType,
      18 -~ classSymRef ~ (typeRef*) ^~^ RefinedType,
      19 -~ symbolRef ~ (typeRef*) ^~^ ClassInfoType,
      20 -~ typeRef ~ (symbolRef*) ^~^ MethodType,
      21 -~ typeRef ~ (refTo(typeSymbol)+) ^~^ PolyType,
      // TODO: make future safe for past by doing the same transformation as in the
      // full unpickler in case we're reading pre-2.9 classfiles
      21 -~ typeRef ^^ NullaryMethodType,
      22 -~ typeRef ~ (symbolRef*) ^~^ MethodType,
      42 -~ typeRef ~ (attribTreeRef*) ^~^ AnnotatedType,
      51 -~ typeRef ~ symbolRef ~ (attribTreeRef*) ^~~^ AnnotatedWithSelfType,
      47 -~ typeLevel ~ typeIndex ^~^ DeBruijnIndexType,
      48 -~ typeRef ~ (symbolRef*) ^~^ ExistentialType) as "type"

  lazy val literal = oneOf(
      24 -^ (),
      25 -~ longValue ^^ (_ != 0L),
      26 -~ longValue ^^ (_.toByte),
      27 -~ longValue ^^ (_.toShort),
      28 -~ longValue ^^ (_.toChar),
      29 -~ longValue ^^ (_.toInt),
      30 -~ longValue ^^ (_.toLong),
      31 -~ longValue ^^ (l => java.lang.Float.intBitsToFloat(l.toInt)),
      32 -~ longValue ^^ (java.lang.Double.longBitsToDouble),
      33 -~ nameRef,
      34 -^ null,
      35 -~ typeRef)

  lazy val attributeInfo = 40 -~ symbolRef ~ typeRef ~ (constantRef?) ~ (nameRef ~ constantRef *) ^~~~^ AttributeInfo // sym_Ref info_Ref {constant_Ref} {nameRef constantRef}
  lazy val children = 41 -~ (nat*) ^^ Children //sym_Ref {sym_Ref}
  lazy val annotInfo = 43 -~ (nat*) ^^ AnnotInfo // attarg_Ref {constant_Ref attarg_Ref}

  lazy val topLevelClass = classSymbol filter isTopLevelClass
  lazy val topLevelObject = objectSymbol filter isTopLevel

  def isTopLevel(symbol : Symbol) = symbol.parent match {
    case Some(ext : ExternalSymbol) => true
    case _ => false
  }
  def isTopLevelClass (symbol : Symbol) = !symbol.isModule && isTopLevel(symbol)
}

  case class AttributeInfo(symbol : Symbol, typeRef : Type, value : Option[Any], values : Seq[String ~ Any]) // sym_Ref info_Ref {constant_Ref} {nameRef constantRef}
  case class Children(symbolRefs : Seq[Int]) //sym_Ref {sym_Ref}

  case class AnnotInfo(refs : Seq[Int]) // attarg_Ref {constant_Ref attarg_Ref}

  /***************************************************
   *                  | 49 TREE len_Nat 1 EMPTYtree
   *                  | 49 TREE len_Nat 2 PACKAGEtree type_Ref sym_Ref mods_Ref name_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 3 CLASStree type_Ref sym_Ref mods_Ref name_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 4 MODULEtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref
   *                  | 49 TREE len_Nat 5 VALDEFtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref tree_Ref
   *                  | 49 TREE len_Nat 6 DEFDEFtree type_Ref sym_Ref mods_Ref name_Ref numtparams_Nat {tree_Ref} numparamss_Nat {numparams_Nat {tree_Ref}} tree_Ref tree_Ref
   *                  | 49 TREE len_Nat 7 TYPEDEFtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 8 LABELtree type_Ref sym_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 9 IMPORTtree type_Ref sym_Ref tree_Ref {name_Ref name_Ref}
   *                  | 49 TREE len_Nat 11 DOCDEFtree type_Ref sym_Ref string_Ref tree_Ref
   *                  | 49 TREE len_Nat 12 TEMPLATEtree type_Ref sym_Ref numparents_Nat {tree_Ref} tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 13 BLOCKtree type_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 14 CASEtree type_Ref tree_Ref tree_Ref tree_Ref
   *                  | 49 TREE len_Nat 15 SEQUENCEtree type_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 16 ALTERNATIVEtree type_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 17 STARtree type_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 18 BINDtree type_Ref sym_Ref name_Ref tree_Ref
   *                  | 49 TREE len_Nat 19 UNAPPLYtree type_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 20 ARRAYVALUEtree type_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 21 FUNCTIONtree type_Ref sym_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 22 ASSIGNtree type_Ref tree_Ref tree_Ref
   *                  | 49 TREE len_Nat 23 IFtree type_Ref tree_Ref tree_Ref tree_Ref
   *                  | 49 TREE len_Nat 24 MATCHtree type_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 25 RETURNtree type_Ref sym_Ref tree_Ref
   *                  | 49 TREE len_Nat 26 TREtree type_Ref tree_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 27 THROWtree type_Ref tree_Ref
   *                  | 49 TREE len_Nat 28 NEWtree type_Ref tree_Ref
   *                  | 49 TREE len_Nat 29 TYPEDtree type_Ref tree_Ref tree_Ref
   *                  | 49 TREE len_Nat 30 TYPEAPPLYtree type_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 31 APPLYtree type_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 32 APPLYDYNAMICtree type_Ref sym_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 33 SUPERtree type_Ref sym_Ref tree_Ref name_Ref
   *                  | 49 TREE len_Nat 34 THIStree type_Ref sym_Ref  name_Ref
   *                  | 49 TREE len_Nat 35 SELECTtree type_Ref sym_Ref tree_Ref name_Ref
   *                  | 49 TREE len_Nat 36 IDENTtree type_Ref sym_Ref name_Ref
   *                  | 49 TREE len_Nat 37 LITERALtree type_Ref constant_Ref
   *                  | 49 TREE len_Nat 38 TYPEtree type_Ref
   *                  | 49 TREE len_Nat 39 ANNOTATEDtree type_Ref tree_Ref tree_Ref
   *                  | 49 TREE len_Nat 40 SINGLETONTYPEtree type_Ref tree_Ref
   *                  | 49 TREE len_Nat 41 SELECTFROMTYPEtree type_Ref tree_Ref name_Ref
   *                  | 49 TREE len_Nat 42 COMPOUNDTYPEtree type_Ref tree_Ref
   *                  | 49 TREE len_Nat 43 APPLIEDTYPEtree type_Ref tree_Ref {tree_Ref}
   *                  | 49 TREE len_Nat 44 TYPEBOUNDStree type_Ref tree_Ref tree_Ref
   *                  | 49 TREE len_Nat 45 EXISTENTIALTYPEtree type_Ref tree_Ref {tree_Ref}
   *                  | 50 MODIFIERS len_Nat flags_Long privateWithin_Ref
   *   SymbolInfo     = name_Ref owner_Ref flags_LongNat [privateWithin_Ref] info_Ref
   *   NameInfo       = <character sequence of length len_Nat in Utf8 format>
   *   NumInfo        = <len_Nat-byte signed number in big endian format>
   *   Ref            = Nat
   *   AnnotInfoBody  = info_Ref {annotArg_Ref} {name_Ref constAnnotArg_Ref}
   *   AnnotArg       = Tree | Constant
   *   ConstAnnotArg  = Constant | AnnotInfo | AnnotArgArray
   *
   *   len is remaining length after `len'.
   */

Other Scala examples (source code examples)

Here is a short list of links related to this Scala ScalaSig.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.