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