mixin.scala

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

SCALA
818
字号
       *  where bitmap$n is an int value acting as a bitmap of initialized values. It is       *  the 'n' is (offset / 32), the MASK is (1 << (offset % 32)).       */      def mkLazyDef(clazz: Symbol, init: Tree, retVal: Tree, offset: Int): Tree = {        /** Return the bitmap field for 'offset', create one if not inheriting it already. */         def bitmapFor(offset: Int): Symbol = {          var sym = clazz.info.member(nme.bitmapName(offset / FLAGS_PER_WORD))          assert(!sym.hasFlag(OVERLOADED))          if (sym == NoSymbol) {            sym = clazz.newVariable(clazz.pos, nme.bitmapName(offset / FLAGS_PER_WORD))                         .setInfo(definitions.IntClass.tpe)                         .setFlag(PROTECTED)            atPhase(currentRun.typerPhase) {              sym.attributes = AnnotationInfo(definitions.VolatileAttr.tpe, List(), List()) :: sym.attributes            }            clazz.info.decls.enter(sym)            addDef(clazz.pos, ValDef(sym, Literal(Constant(0))))          }          sym        }        val bitmapSym = bitmapFor(offset)                  def mkSetFlag(bmp: Symbol, mask: Tree): Tree =           Assign(Select(This(clazz), bmp),            Apply(Select(Select(This(clazz), bmp), Int_Or), List(mask)))                      def mkTest(mask: Tree): Tree =           Apply(Select(Apply(Select(Select(This(clazz), bitmapSym), Int_And), List(mask)),                Int_==), List(Literal(Constant(0))))                val mask = Literal(Constant(1 << (offset % FLAGS_PER_WORD)))        val result =           If(mkTest(mask),             gen.mkSynchronized(gen.mkAttributedThis(clazz),               If(mkTest(mask),                  Block(List(init,                         mkSetFlag(bitmapSym, mask)),                         Literal(Constant(()))),                  EmptyTree)),              EmptyTree)        localTyper.typed(atPos(init.pos)(Block(List(result), retVal)))      }             /** Complete lazy field accessors. Applies only to classes, for it's own (non inherited) lazy fields. */      def lazifyOwnFields(clazz: Symbol, stats: List[Tree]): List[Tree] = {        var offset = clazz.info.findMember(nme.ANYNAME, 0, METHOD | LAZY, false).alternatives.filter(_.owner != clazz).length        val stats1 = for (stat <- stats; sym = stat.symbol) yield stat match {          case DefDef(mods, name, tp, vp, tpt, rhs)             if sym.hasFlag(LAZY) && rhs != EmptyTree && !clazz.isImplClass =>              val rhs1 = if (sym.tpe.resultType.typeSymbol == definitions.UnitClass)                 mkLazyDef(clazz, rhs, Literal(()), offset)              else {                val Block(List(assignment), res) = rhs                mkLazyDef(clazz, assignment, Select(This(clazz), res.symbol), offset)              }              offset += 1              copy.DefDef(stat, mods, name, tp, vp, tpt, rhs1)          case _ => stat        }	stats1      }                   // the number of inherited lazy fields that are not mixed in      offset = (clazz.info.findMember(nme.ANYNAME, 0, METHOD | LAZY, false)                .alternatives filter { f => f.owner != clazz || !f.hasFlag(MIXEDIN)}).length      // begin addNewDefs      var stats1 = lazifyOwnFields(clazz, stats)      // for all symbols `sym' in the class definition, which are mixed in:      for (val sym <- clazz.info.decls.toList) {        if (sym hasFlag MIXEDIN) {          if (clazz hasFlag lateINTERFACE) {            // if current class is a trait interface, add an abstract method for accessor `sym'            addDefDef(sym, vparamss => EmptyTree)          } else if (!clazz.isTrait) {             // if class is not a trait add accessor definitions            if ((sym hasFlag ACCESSOR) &&                 (!(sym hasFlag DEFERRED) || (sym hasFlag lateDEFERRED))) {               // add accessor definitions              addDefDef(sym, vparams => {                val accessedRef = sym.tpe match {                  case MethodType(List(), ConstantType(c)) => Literal(c)                  case _ =>                     // if it is a mixed-in lazy value, complete the accessor                    if (sym.hasFlag(LAZY) && sym.isGetter) {                      val rhs1 = if (sym.tpe.resultType.typeSymbol == definitions.UnitClass)                        mkLazyDef(clazz, Apply(staticRef(initializer(sym)), List(gen.mkAttributedThis(clazz))), Literal(()), offset)                      else {                        val assign = atPos(sym.pos) {                          Assign(Select(This(sym.accessed.owner), sym.accessed) /*gen.mkAttributedRef(sym.accessed)*/,                               Apply(staticRef(initializer(sym)), gen.mkAttributedThis(clazz) :: Nil))                        }                        mkLazyDef(clazz, assign, Select(This(clazz), sym.accessed), offset)                      }                      offset += 1                       rhs1                    } else                      Select(This(clazz), sym.accessed)                }                if (sym.isSetter) Assign(accessedRef, Ident(vparams.head))                else gen.mkCheckInit(accessedRef)              })            } else if (sym.isModule && !(sym hasFlag LIFTED | BRIDGE)) {              // add modules               val vdef = gen.mkModuleVarDef(sym)              addDef(position(sym), vdef)              addDef(position(sym), gen.mkCachedModuleAccessDef(sym, vdef.symbol))            } else if (!sym.isMethod) {              // add fields              addDef(position(sym), ValDef(sym))            } else if (sym hasFlag SUPERACCESSOR) {              // add superaccessors              addDefDef(sym, vparams => EmptyTree)            } else {              // add forwarders              assert(sym.alias != NoSymbol, sym)              addDefDef(sym, vparams =>                Apply(staticRef(sym.alias), gen.mkAttributedThis(clazz) :: (vparams map Ident)))            }          }        }      }      stats1 = add(stats1, newDefs.toList)      if (!clazz.isTrait) stats1 = stats1 map completeSuperAccessor      stats1    }    /** The transform that gets applied to a tree after it has been completely     *  traversed and possible modified by a preTransform.     *  This step will     *    - change every node type that refers to an implementation class to its      *      corresponding interface, unless the node's symbol is an implementation class.     *    - change parents of templates to conform to parents in the symbol info     *    - add all new definitions to a class or interface     *    - remove widening casts     *    - change calls to methods which are defined only in implementation classes     *      to static calls of methods in implementation modules (@see staticCall)     *    - change super calls to methods in implementation classes to static calls     *      (@see staticCall)     *    - change `this' in implementation modules to references to the self parameter     *    - refer to fields in some implementation class vie an abstract method in the interface.     */    private def postTransform(tree: Tree): Tree = {      val sym = tree.symbol      // change every node type that refers to an implementation class to its      // corresponding interface, unless the node's symbol is an implementation class.      if (tree.tpe.typeSymbol.isImplClass &&          ((tree.symbol eq null) || !tree.symbol.isImplClass))        tree.tpe = toInterface(tree.tpe);      tree match {        case Template(parents, self, body) =>          // change parents of templates to conform to parents in the symbol info          val parents1 = currentOwner.info.parents map (t => TypeTree(t) setPos tree.pos)          // add all new definitions to current class or interface          val body1 = addNewDefs(currentOwner, body)          copy.Template(tree, parents1, self, body1)        case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List())        if (tree.symbol == Object_asInstanceOf && (qual.tpe <:< targ.tpe)) =>          // remove widening casts          qual        case Apply(Select(qual, _), args) =>          /** Changes <code>qual.m(args)</code> where m refers to an implementation           *  class method to Q.m(S, args) where Q is the implementation module of           *  <code>m</code> and S is the self parameter for the call, which           *  is determined as follows:           *     - if qual != super, qual itself           *     - if qual == super, and we are in an implementation class,           *       the current self parameter.           *     - if qual == super, and we are not in an implementation class, `this'           */          def staticCall(target: Symbol) = {            if (target == NoSymbol)              assert(false, "" + sym + ":" + sym.tpe + " " + sym.owner + " " + implClass(sym.owner) + " " + implClass(sym.owner).info.member(sym.name) + " " + atPhase(phase.prev)(implClass(sym.owner).info.member(sym.name).tpe) + " " + phase);//debug            localTyper.typed {              atPos(tree.pos) {                Apply(staticRef(target), transformSuper(qual) :: args)              }            }          }          if (isStaticOnly(sym)) {            // change calls to methods which are defined only in implementation            // classes to static calls of methods in implementation modules            staticCall(sym)          } else qual match {            case Super(_, mix) =>              // change super calls to methods in implementation classes to static calls.              // Transform references super.m(args) as follows:              //  - if `m' refers to a trait, insert a static call to the correspondign static              //    implementation              //  - otherwise return tree unchanged              if (mix == nme.EMPTY.toTypeName && currentOwner.enclClass.isImplClass)                assert(false, "illegal super in trait: " + currentOwner.enclClass + " " + tree);              if (sym.owner hasFlag lateINTERFACE) {                if (sym.hasFlag(ACCESSOR)) {                  assert(args.isEmpty)                  val sym1 = sym.overridingSymbol(currentOwner.enclClass)                  localTyper.typed {                    atPos(tree.pos) {                      Apply(Select(transformSuper(qual), sym1), List())                    }                  }                } else {                  staticCall(atPhase(phase.prev)(sym.overridingSymbol(implClass(sym.owner))))                }              } else {                assert(!currentOwner.enclClass.isImplClass)                tree              }            case _ =>              tree          }        case This(_) if tree.symbol.isImplClass =>          // change `this' in implementation modules to references to the self parameter          assert(tree.symbol == currentOwner.enclClass)          selfRef(tree.pos)        case Select(Super(_, _), name) =>          tree        case Select(qual, name) if sym.owner.isImplClass && !isStaticOnly(sym) =>          // refer to fields in some implementation class via an abstract          // getter in the interface.          if (sym.isMethod)            assert(false, "no method allowed here: " + sym + sym.isImplOnly +                          " " + flagsToString(sym.flags))          val getter = sym.getter(enclInterface)          assert(getter != NoSymbol)          localTyper.typed {            atPos(tree.pos) {              Apply(Select(qual, getter), List())            }          }        case Assign(Apply(lhs @ Select(qual, _), List()), rhs) =>          // assign to fields in some implementation class via an abstract          // setter in the interface.          localTyper.typed {            atPos(tree.pos) {              Apply(Select(qual, lhs.symbol.setter(enclInterface)) setPos lhs.pos, List(rhs))            }          }        case _ =>          tree      }    }    /** The main transform method.     *  This performs pre-order traversal preTransform at mixin phase;     *  when coming back, it performs a postTransform at phase after.     */    override def transform(tree: Tree): Tree = {      try { //debug        val tree1 = super.transform(preTransform(tree))        atPhase(phase.next)(postTransform(tree1))      } catch {        case ex: Throwable =>          if (settings.debug.value) Console.println("exception when traversing " + tree)          throw ex      }    }  }}

⌨️ 快捷键说明

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