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 + -
显示快捷键?