mixin.scala

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

SCALA
818
字号
              .resetFlag(DEFERRED | lateDEFERRED)          }        }      }      for (val mc <- clazz.mixinClasses)        if (mc hasFlag lateINTERFACE) {          addLateInterfaceMembers(mc)          mixinTraitMembers(mc)          mixinImplClassMembers(implClass(mc), mc)        }    }  }  /** The info transform for this phase does the following:   *   - The parents of every class are mapped from implementation class to interface   *   - Implementation classes become modules that inherit nothing   *     and that define all.   *   *  @param sym ...   *  @param tp  ...   *  @return    ...   */  override def transformInfo(sym: Symbol, tp: Type): Type = tp match {    case ClassInfoType(parents, decls, clazz) =>      var parents1 = parents      var decls1 = decls      if (!clazz.isPackageClass) {        atPhase(phase.next)(clazz.owner.info)        if (clazz.isImplClass) {          clazz setFlag lateMODULE          var sourceModule = clazz.owner.info.decls.lookup(sym.name.toTermName)          if (sourceModule != NoSymbol) {            sourceModule setPos sym.pos            sourceModule.flags = MODULE | FINAL          } else {            sourceModule = clazz.owner.newModule(              sym.pos, sym.name.toTermName, sym.asInstanceOf[ClassSymbol])            clazz.owner.info.decls enter sourceModule          }          sourceModule setInfo sym.tpe          assert(clazz.sourceModule != NoSymbol)//debug          parents1 = List()          decls1 = newScope(decls.toList filter isImplementedStatically)        } else if (!parents.isEmpty) {          parents1 = parents.head :: (parents.tail map toInterface)        }      }      //decls1 = atPhase(phase.next)(newScope(decls1.toList))//debug      if ((parents1 eq parents) && (decls1 eq decls)) tp      else ClassInfoType(parents1, decls1, clazz)    case MethodType(formals, restp) =>      toInterfaceMap(        if (isImplementedStatically(sym))          MethodType(toInterface(sym.owner.typeOfThis) :: formals, restp)        else          tp)    case _ =>      tp  }// --------- term transformation -----------------------------------------------  protected def newTransformer(unit: CompilationUnit): Transformer =    new MixinTransformer  class MixinTransformer extends Transformer {    /** Within a static implementation method: the parameter referring to the     *  current object undefined evrywhere else.     */    private var self: Symbol = _    /** The rootContext used for typing */    private val rootContext =      erasure.NoContext.make(EmptyTree, RootClass, newScope)    /** The typer */    private var localTyper: erasure.Typer = _    /** Within a static implementation method: the interface type corresponding     *  to the implementation module; undefined evrywhere else.     */    private var enclInterface: Symbol = _    /** The first transform; called in a pre-order traversal at phase mixin     *  (that is, every node is processed before its children.     *  What transform does:     *   - For every non-trait class, add all mixed in members to the class info.     *   - For every trait, add all late interface members to the class info     *   - For every static implementation method:     *       - remove override flag     *       - create a new method definition that also has a `self' parameter     *         (which comes first) Iuli: this position is assumed by tail call elimination      *         on a different receiver. Storing a new 'this' assumes it is located at     *         index 0 in the local variable table. See 'STORE_THIS' and GenJVM/GenMSIL.     *   - Map implementation class types in type-apply's to their interfaces     *   - Remove all fields in implementation classes     */    private def preTransform(tree: Tree): Tree = {      val sym = tree.symbol      tree match {        case Template(parents, self, body) =>          localTyper = erasure.newTyper(rootContext.make(tree, currentOwner))          atPhase(phase.next)(currentOwner.owner.info)//todo: needed?          if (!currentOwner.isTrait) addMixedinMembers(currentOwner)          else if (currentOwner hasFlag lateINTERFACE) addLateInterfaceMembers(currentOwner)          tree        case DefDef(mods, name, tparams, List(vparams), tpt, rhs) if currentOwner.isImplClass =>          if (isImplementedStatically(sym)) {            sym setFlag notOVERRIDE            self = sym.newValue(sym.pos, nme.SELF)               .setFlag(PARAM)              .setInfo(toInterface(currentOwner.typeOfThis));            enclInterface = currentOwner.toInterface            val selfdef = ValDef(self) setType NoType            copy.DefDef(tree, mods, name, tparams, List(selfdef :: vparams), tpt, rhs)          } else {            EmptyTree          }        case Apply(tapp @ TypeApply(fn, List(arg)), List()) =>          if (arg.tpe.typeSymbol.isImplClass) {            val ifacetpe = toInterface(arg.tpe)            arg.tpe = ifacetpe            tapp.tpe = MethodType(List(), ifacetpe)            tree.tpe = ifacetpe          }          tree        case ValDef(_, _, _, _) if currentOwner.isImplClass =>          EmptyTree        case _ =>          tree      }    }             /** Create an identifier which references self parameter.     *     *  @param pos ...     */    private def selfRef(pos: Position) =      gen.mkAttributedIdent(self) setPos pos    /** Replace a super reference by this or the self parameter, depending     *  on whether we are in an implementation class or not.     *  Leave all other trees unchanged */    private def transformSuper(qual: Tree) =       if (!qual.isInstanceOf[Super]) qual      else if (currentOwner.enclClass.isImplClass) selfRef(qual.pos)      else gen.mkAttributedThis(currentOwner.enclClass)    /** Create a static reference to given symbol <code>sym</code> of the     *  form <code>M.sym</code> where M is the symbol's implementation module.     */    private def staticRef(sym: Symbol) = {      sym.owner.info  //todo: needed?      sym.owner.owner.info //todo: needed?      if (sym.owner.sourceModule == NoSymbol) {        assert(false, "" + sym + " in " + sym.owner + " in " + sym.owner.owner +                      " " + sym.owner.owner.info.decls.toList)//debug      }      Select(gen.mkAttributedRef(sym.owner.sourceModule), sym)    }    /** Add all new definitions to a non-trait class      *  These fall into the following categories:     *    - for a trait interface:      *       - abstract accessors for all fields in the implementation class     *    - for a non-trait class:     *       - A field for every in a mixin class      *       - Setters and getters for such fields     *           - getters for mixed in lazy fields are completed      *       - module variables and module creators for every module in a mixin class     *         (except if module is lifted -- in this case the module variable     *          is local to some function, and the creator method is static.)     *       - A super accessor for every super accessor in a mixin class     *       - Forwarders for all methods that are implemented statically     *  All superaccessors are completed with right-hand sides (@see completeSuperAccessor)     *  @param clazz  The class to which definitions are added     */    private def addNewDefs(clazz: Symbol, stats: List[Tree]): List[Tree] = {      val newDefs = new ListBuffer[Tree]      var offset: Int = 0      /** Attribute given tree and anchor at given position */      def attributedDef(pos: Position, tree: Tree): Tree = {        if (settings.debug.value) log("add new def to " + clazz + ": " + tree)        localTyper.typed { atPos(pos) { tree } }      }      /** The position of given symbol, or, if this is undefined,        *  the position of the current class. */      def position(sym: Symbol) =        if (sym.pos == NoPosition) clazz.pos else sym.pos      /** Add tree at given position as new definition */      def addDef(pos: Position, tree: Tree) {        newDefs += attributedDef(pos, tree)      }      /** Add new method definition.       *       *  @param sym   The method       *  @param rhs   A function that maps formal parameters to the method's       *               right-hand side       */      def addDefDef(sym: Symbol, rhs: List[Symbol] => Tree) {        addDef(position(sym), DefDef(sym, vparamss => rhs(vparamss.head)))      }      /** Add `newdefs' to `stats', removing any abstract method definitions       *  in <code>stats</code> that are matched by some symbol defined in       *  <code>newDefs</code>.       */      def add(stats: List[Tree], newDefs: List[Tree]) = {        val newSyms = newDefs map (_.symbol)        def isNotDuplicate(tree: Tree) = tree match {          case DefDef(_, _, _, _, _, _) =>            val sym = tree.symbol;            !(sym.isDeferred &&              (newSyms exists (nsym => nsym.name == sym.name && (nsym.tpe matches sym.tpe))))          case _ =>            true        }        if (newDefs.isEmpty) stats        else newDefs ::: stats.filter(isNotDuplicate)      }      /** If `stat' is a superaccessor, complete it by adding a right-hand side.       *  (Note: superaccessors are always abstract until this point.        *   The method to call in a superaccessor is stored in the accessor symbol's alias field.       *  The rhs is:        *    super.A(xs)  where A is the super accessor's alias and xs are its formal parameters.       *  This rhs is typed and then mixin transformed.       */      def completeSuperAccessor(stat: Tree) = stat match {        case DefDef(mods, name, tparams, List(vparams), tpt, EmptyTree)        if (stat.symbol hasFlag SUPERACCESSOR) =>          val rhs0 =            Apply(Select(Super(clazz, nme.EMPTY.toTypeName), stat.symbol.alias),                  vparams map (vparam => Ident(vparam.symbol)))          val rhs1 = localTyper.typed(atPos(stat.pos)(rhs0), stat.symbol.tpe.resultType)          val rhs2 = atPhase(currentRun.mixinPhase)(transform(rhs1))          if (settings.debug.value)            log("complete super acc " + stat.symbol + stat.symbol.locationString +                " " + rhs1 + " " + stat.symbol.alias + stat.symbol.alias.locationString +                "/" + stat.symbol.alias.owner.hasFlag(lateINTERFACE))//debug          copy.DefDef(stat, mods, name, tparams, List(vparams), tpt, rhs2)        case _ =>          stat      }      import lazyVals._            /** return a 'lazified' version of rhs.        *  @param clazz The class symbol       *  @param init The tree which initializes the field ( f = <rhs> )       *  @param fieldSym The symbol of this lazy field       *  @param offset The offset of this field in the flags bitmap       *       *  The result will be a tree of the form       *  {       *    if ((bitmap$n & MASK) == 0) {       *       synhronized(this) {       *         if ((bitmap$n & MASK) == 0) {       *           synhronized(this) {       *             init // l$ = <rhs>       *           }       *           bitmap$n = bimap$n | MASK       *         }}}       *    l$       *  }

⌨️ 快捷键说明

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