cleanup.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 569 行 · 第 1/2 页

SCALA
569
字号
/* NSC -- new Scala compiler * Copyright 2005-2006 LAMP/EPFL * @author Martin Odersky */// $Id: CleanUp.scala 14428 2008-03-20 14:56:41Z dubochet $package scala.tools.nsc.transformimport symtab._import Flags._import scala.tools.nsc.util.Positionimport scala.collection.mutable.{ListBuffer, HashMap}abstract class CleanUp extends Transform {  import global._  import definitions._  import posAssigner.atPos  /** the following two members override abstract members in Transform */  val phaseName: String = "cleanup"  protected def newTransformer(unit: CompilationUnit): Transformer =    new CleanUpTransformer(unit)  class CleanUpTransformer(unit: CompilationUnit) extends Transformer {    private val MethodClass = if (forCLDC || forMSIL) null                              else definitions.getClass("java.lang.reflect.Method")    private val newDefs = new ListBuffer[Tree]    private val classConstantMeth = new HashMap[String, Symbol]    // a map from the symbols of the Scala primitive types to the symbols    // of the modules of the Java box classes    private val javaBoxClassModule = new HashMap[Symbol, Symbol]    if (!forMSIL) {      javaBoxClassModule(BooleanClass) = getModule("java.lang.Boolean")      javaBoxClassModule(ByteClass)    = getModule("java.lang.Byte")      javaBoxClassModule(ShortClass)   = getModule("java.lang.Short")      javaBoxClassModule(IntClass)     = getModule("java.lang.Integer")      javaBoxClassModule(CharClass)    = getModule("java.lang.Character")      javaBoxClassModule(LongClass)    = getModule("java.lang.Long")      if (!forCLDC) {        javaBoxClassModule(FloatClass)   = getModule("java.lang.Float")        javaBoxClassModule(DoubleClass)  = getModule("java.lang.Double")        javaBoxClassModule(UnitClass)    = getModule("java.lang.Void")      }    }    private var localTyper: analyzer.Typer = null    private def classConstantMethod(pos: Position, sig: String): Symbol = classConstantMeth.get(sig) match {      case Some(meth) =>        meth      case None =>        val forName = getMember(ClassClass.linkedModuleOfClass, nme.forName)        val owner = currentOwner.enclClass        val cvar = owner.newVariable(pos, unit.fresh.newName("class$Cache"))          .setFlag(PRIVATE | STATIC | MUTABLE | SYNTHETIC).setInfo(ClassClass.tpe)        owner.info.decls.enter(cvar)        val cdef =          localTyper.typed {            atPos(pos) {              ValDef(cvar, Literal(Constant(null)))            }          }        val meth = owner.newMethod(pos, unit.fresh.newName("class$Method"))          .setFlag(PRIVATE | STATIC | SYNTHETIC).setInfo(MethodType(List(), ClassClass.tpe))        owner.info.decls.enter(meth)        val mdef =           localTyper.typed {            atPos(pos) {              DefDef(meth, vparamss =>                gen.mkCached(                  cvar,                  Apply(                    gen.mkAttributedRef(forName), List(Literal(sig)))))            }          }        newDefs.append(cdef, mdef);        classConstantMeth.update(sig, meth)        meth    }        private val existingReflectiveMethodCache = new HashMap[(String, List[Type]), Symbol]            /* Transforms a list of types into a list of trees representing these types     * as java.lang.Class instances. */    private def paramTypeClasses(paramTypes: List[Type]): List[Tree] =      paramTypes map { pt => Literal(Constant(pt)) }        private def reflectiveMethodCache(pos: Position, method: String, paramTypes: List[Type]): Symbol =      existingReflectiveMethodCache.get((method, paramTypes)) match {        case Some(cache) => cache        case None =>          val owner = currentOwner.enclClass                    val rmvar = owner.newVariable(pos, unit.fresh.newName("reflMethod$Cache"))            .setFlag(PRIVATE | STATIC | MUTABLE | SYNTHETIC)            .setInfo(MethodClass.tpe)          owner.info.decls.enter(rmvar)          val rmdef =            localTyper.typed {              atPos(pos) {                ValDef(rmvar, Literal(Constant(null)))              }            }                    val rmcvar = owner.newVariable(pos, unit.fresh.newName("reflClass$Cache"))            .setFlag(PRIVATE | STATIC | MUTABLE | SYNTHETIC)            .setInfo(ClassClass.tpe)          owner.info.decls.enter(rmcvar)          val rmcdef =            localTyper.typed {              atPos(pos) {                ValDef(rmcvar, Literal(Constant(null)))              }            }                    val rmmeth = owner.newMethod(pos, unit.fresh.newName("reflMethod$Method"))            .setFlag(STATIC | SYNTHETIC)            .setInfo(MethodType(List(ClassClass.tpe), MethodClass.tpe))          owner.info.decls.enter(rmmeth)          val rmmdef =             localTyper.typed {              atPos(pos) {                DefDef(rmmeth, { vparamss =>                  val callClass = vparamss(0)(0)                  Block(                    List(                      If(                        gen.mkOr(                          Apply(Select(Select(This(owner), rmvar), nme.eq), List(Literal(Constant(null)))),                          Apply(Select(Select(This(owner), rmcvar), nme.ne), List(gen.mkAttributedRef(callClass)))                        ),                        Block(                          List(                            Assign(                              Select(This(owner), rmvar),                              Apply(                                Select(                                  gen.mkAttributedRef(callClass),                                  ClassClass.tpe.member(nme.getMethod_)                                ),                                List(                                  Literal(Constant(method)),                                  ArrayValue(TypeTree(ClassClass.tpe), paramTypeClasses(paramTypes))                                )                              )                            ),                            Assign(Select(This(owner), rmcvar), gen.mkAttributedRef(callClass))                          ),                          Literal(Constant(()))                        ),                        EmptyTree                      )                    ),                    Select(This(owner), rmvar)                  )                })              }            }                    newDefs.append(transform(rmdef), transform(rmcdef), transform(rmmdef));          existingReflectiveMethodCache.update((method, paramTypes), rmmeth)          rmmeth      }        override def transformUnit(unit: CompilationUnit) =      unit.body = transform(unit.body)            /** A value class is defined to be only Java-compatible values: unit is      * not part of it, as opposed to isValueClass in definitions. scala.Int is      * a value class, java.lang.Integer is not. */    def isValueClass(sym: Symbol) = boxedClass contains sym    override def transform(tree: Tree): Tree = tree match {              /* Transforms dynamic calls (i.e. calls to methods that are undefined       * in the erased type space) to -- dynamically -- unsafe calls using       * reflection. This is used for structural sub-typing of refinement       * types.       * For 'a.f(b)' it will generate something like:       * 'a.getClass().       * '  getMethod("f", Array(classOf[b.type])).       * '  invoke(a, Array(b))        * plus all the necessary casting/boxing/etc. machinery required       * for type-compatibility (see fixResult and fixParams).       *        * USAGE CONTRACT:       * There are a number of assumptions made on the way a dynamic apply       * is used. Assumptions relative to type are handled by the erasure       * phase.       * - The applied arguments are compatible with AnyRef, which means       *   that an argument tree typed as AnyVal has already been extended       *   with the necessary boxing calls. This implies that passed       *   arguments might not be strictly compatible with the method's       *   parameter types (a boxed integeer while int is expected).       * - The expected return type is an AnyRef, even when the method's       *   return type is an AnyVal. This means that the tree containing the       *   call has already been extended with the necessary unboxing calls       *   (or keeps the boxed type).       * - The type-checker has prevented dynamic applies on methods which       *   parameter's erased types are not statically known at the call site.       *   This is necessary to allow dispatching the call to the correct       *   method (dispatching on paramters is static in Scala). In practice,       *   this limitation only arises when the called method is defined as a       *   refinement, where the refinement defines a parameter based on a       *   type variable. */      case ad@ApplyDynamic(qual, params) =>        assert(ad.symbol.isPublic)                val testForNumber: Tree =          gen.mkOr(            Apply(              TypeApply(                gen.mkAttributedSelect(qual, definitions.Object_isInstanceOf),                List(TypeTree(BoxedNumberClass.tpe.normalize))              ),              List()            ),            Apply(              TypeApply(                gen.mkAttributedSelect(qual, definitions.Object_isInstanceOf),                List(TypeTree(BoxedCharacterClass.tpe.normalize))              ),              List()            )          )                val testForBoolean: Tree =          Apply(            TypeApply(              gen.mkAttributedSelect(qual, definitions.Object_isInstanceOf),              List(TypeTree(BoxedBooleanClass.tpe.normalize))            ),            List()          )                val testForNumberOrBoolean: Tree = gen.mkOr(testForNumber, testForBoolean)                def getPrimitiveReplacementForStructuralCall: PartialFunction[Name, (Symbol, Tree)] = {        /* Unary arithmetic */          case nme.UNARY_+ =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("positive")), testForNumber)          case nme.UNARY_- =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("negate")), testForNumber)        /* Unary logic */          case nme.UNARY_~ =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("complement")), testForNumber)          case nme.UNARY_! =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeNot")), testForBoolean)        /* Binary arithmetic */          case nme.ADD =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("add")), testForNumber)          case nme.SUB =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("subtract")), testForNumber)          case nme.MUL =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("multiply")), testForNumber)          case nme.DIV =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("divide")), testForNumber)          case nme.MOD =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeModulo")), testForNumber)        /* Binary logic */          case nme.OR =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeOr")), testForNumberOrBoolean)          case nme.XOR =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeXor")), testForNumberOrBoolean)          case nme.AND =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeAnd")), testForNumberOrBoolean)          case nme.ZOR =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeConditionalOr")), testForBoolean)          case nme.ZAND =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeConditionalAnd")), testForBoolean)        /* Shifting */          case nme.LSL =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("shiftSignedLeft")), testForNumber)          case nme.LSR =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("shiftSignedRight")), testForNumber)          case nme.ASR =>            (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("shiftLogicalRight")), testForNumber)          case nme.EQ => 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?