explicitouter.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 511 行 · 第 1/2 页
SCALA
511 行
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author Martin Odersky */// $Id: ExplicitOuter.scala 13819 2008-01-28 18:43:24Z odersky $package scala.tools.nsc.transformimport symtab._import Flags._import scala.collection.mutable.{HashMap, ListBuffer}import matching.{TransMatcher, PatternNodes, CodeFactory, ParallelMatching}/** This class ... * * @author Martin Odersky * @version 1.0 */abstract class ExplicitOuter extends InfoTransform with TransMatcher with PatternNodes with CodeFactory with ParallelMatching with TypingTransformers { import global._ import definitions._ import posAssigner.atPos /** The following flags may be set by this phase: */ override def phaseNewFlags: Long = notPRIVATE | notPROTECTED | lateFINAL /** the name of the phase: */ val phaseName: String = "explicitouter" /** This class does not change linearization */ override def changesBaseClasses = false protected def newTransformer(unit: CompilationUnit): Transformer = new ExplicitOuterTransformer(unit) /** Is given <code>clazz</code> an inner class? */ private def isInner(clazz: Symbol) = !clazz.isPackageClass && !clazz.outerClass.isStaticOwner /** Does given <code>clazz</code> define an outer field? */ def hasOuterField(clazz: Symbol) = { def hasSameOuter(parent: Type) = parent.typeSymbol.isClass && clazz.owner.isClass && clazz.owner == parent.typeSymbol.owner && parent.prefix =:= clazz.owner.thisType isInner(clazz) && !clazz.isTrait && (clazz.info.parents.isEmpty || !hasSameOuter(clazz.info.parents.head)) } private def outerField(clazz: Symbol): Symbol = { val result = clazz.info.member(nme.getterToLocal(nme.OUTER)) if (result == NoSymbol) assert(false, "no outer field in "+clazz+clazz.info.decls+" at "+phase) result } def outerAccessor(clazz: Symbol): Symbol = { val firstTry = clazz.info.decl(clazz.expandedName(nme.OUTER)) if (firstTry != NoSymbol && firstTry.outerSource == clazz) firstTry else { var e = clazz.info.decls.elems while ((e ne null) && e.sym.outerSource != clazz) e = e.next if (e ne null) e.sym else NoSymbol } } /** <p> * The type transformation method: * </p> * <ol> * <li> * Add an outer parameter to the formal parameters of a constructor * in a inner non-trait class; * </li> * <li> * Add a protected <code>$outer</code> field to an inner class which is * not a trait. * </li> * <li> * <p> * Add an outer accessor <code>$outer$$C</code> to every inner class * with fully qualified name <code>C</code> that is not an interface. * The outer accesssor is abstract for traits, concrete for other * classes. * </p> * <p> * 3a. Also add overriding accessor defs to every class that inherits * mixin classes with outer accessor defs (unless the superclass * already inherits the same mixin). * </p> * </li> * <li> * Make all super accessors and modules in traits non-private, mangling * their names. * </li> * <li> * Remove protected flag from all members of traits. * </li> * </ol> */ def transformInfo(sym: Symbol, tp: Type): Type = tp match { case MethodType(formals, restpe1) => val restpe = transformInfo(sym, restpe1) if (sym.owner.isTrait && ((sym hasFlag SUPERACCESSOR) || sym.isModule)) { // 5 sym.makeNotPrivate(sym.owner) } // moved form the term transformer if (sym.owner.isTrait && (sym hasFlag (ACCESSOR | SUPERACCESSOR))) sym.makeNotPrivate(sym.owner); //(2) if (sym.owner.isTrait && (sym hasFlag PROTECTED)) sym setFlag notPROTECTED // 6 if (sym.isClassConstructor && isInner(sym.owner)) // 1 MethodType(sym.owner.outerClass.thisType :: formals, restpe) else if (restpe ne restpe1) MethodType(formals, restpe) else tp case ClassInfoType(parents, decls, clazz) => var decls1 = decls if (isInner(clazz) && !(clazz hasFlag INTERFACE)) { decls1 = newScope(decls.toList) val outerAcc = clazz.newMethod(clazz.pos, nme.OUTER) // 3 outerAcc.expandName(clazz) val restpe = if (clazz.isTrait) clazz.outerClass.tpe else clazz.outerClass.thisType decls1 enter clazz.newOuterAccessor(clazz.pos).setInfo(MethodType(List(), restpe)) if (hasOuterField(clazz)) { //2 decls1 enter ( clazz.newValue(clazz.pos, nme.getterToLocal(nme.OUTER)) setFlag (SYNTHETIC | PROTECTED | PARAMACCESSOR) setInfo clazz.outerClass.thisType) } } if (!clazz.isTrait && !parents.isEmpty) { for (val mc <- clazz.mixinClasses) { val mixinOuterAcc: Symbol = atPhase(phase.next)(outerAccessor(mc)) if (mixinOuterAcc != NoSymbol) { if (decls1 eq decls) decls1 = newScope(decls.toList) val newAcc = mixinOuterAcc.cloneSymbol(clazz) newAcc.resetFlag(DEFERRED) newAcc.setInfo(clazz.thisType.memberType(mixinOuterAcc)) decls1 enter newAcc } } } if (decls1 eq decls) tp else ClassInfoType(parents, decls1, clazz) case PolyType(tparams, restp) => val restp1 = transformInfo(sym, restp) if (restp eq restp1) tp else PolyType(tparams, restp1) case _ => tp } /** A base class for transformers that maintain <code>outerParam</code> * values for outer parameters of constructors. * The class provides methods for referencing via outer. */ abstract class OuterPathTransformer(unit: CompilationUnit) extends TypingTransformer(unit) { /** The directly enclosing outer parameter, if we are in a constructor */ protected var outerParam: Symbol = NoSymbol /** The first outer selection from currently transformed tree. * The result is typed but not positioned. */ protected def outerValue: Tree = if (outerParam != NoSymbol) gen.mkAttributedIdent(outerParam) else outerSelect(gen.mkAttributedThis(currentClass)) /** Select and apply outer accessor from 'base' * The result is typed but not positioned. */ private def outerSelect(base: Tree): Tree = { val path = Apply(Select(base, outerAccessor(base.tpe.typeSymbol.toInterface)), List()) localTyper.typed(path) } /** The path * <blockquote><pre>`base'.$outer$$C1 ... .$outer$$Cn</pre></blockquote> * which refers to the outer instance of class <code>to</code> of * value <code>base</code>. The result is typed but not positioned. * * @param base ... * @param from ... * @param to ... * @return ... */ protected def outerPath(base: Tree, from: Symbol, to: Symbol): Tree = { //Console.println("outerPath from "+from+" to "+to+" at "+base+":"+base.tpe) //assert(base.tpe.widen.baseType(from.toInterface) != NoType, ""+base.tpe.widen+" "+from.toInterface)//DEBUG if (from == to || from.isImplClass && from.toInterface == to) base else outerPath(outerSelect(base), from.outerClass, to) } override def transform(tree: Tree): Tree = { val savedOuterParam = outerParam try { tree match { case Template(_, _, _) => outerParam = NoSymbol case DefDef(_, _, _, vparamss, _, _) => if (tree.symbol.isClassConstructor && isInner(tree.symbol.owner)) { outerParam = vparamss.head.head.symbol assert(outerParam.name startsWith nme.OUTER, outerParam.name) } case _ => } super.transform(tree) } catch {//debug case ex: Throwable => Console.println("exception when transforming " + tree) //Console.println(ex.getMessage) //Console.println(ex.printStackTrace()) //System.exit(-1); throw ex } finally { outerParam = savedOuterParam } } } /** <p> * The phase performs the following transformations on terms: * </p> * <ol> * <li> <!-- 1 --> * <p> * An class which is not an interface and is not static gets an outer * accessor (@see outerDefs). * </p> * <p> * 1a. A class which is not a trait gets an outer field. * </p> * </li> * <li> <!-- 4 --> * A constructor of a non-trait inner class gets an outer parameter. * </li> * <li> <!-- 5 --> * A reference <code>C.this</code> where <code>C</code> refers to an * outer class is replaced by a selection * <code>this.$outer$$C1</code> ... <code>.$outer$$Cn</code> (@see outerPath) * </li> * <li> * </li> * <li> <!-- 7 --> * A call to a constructor Q.<init>(args) or Q.$init$(args) where Q != this and * the constructor belongs to a non-static class is augmented by an outer argument. * E.g. <code>Q.<init>(OUTER, args)</code> where <code>OUTER</code> * is the qualifier corresponding to the singleton type <code>Q</code>. * </li> * <li> * A call to a constructor <code>this.<init>(args)</code> in a * secondary constructor is augmented to <code>this.<init>(OUTER, args)</code> * where <code>OUTER</code> is the last parameter of the secondary constructor. * </li> * <li> <!-- 9 --> * Remove <code>private</code> modifier from class members <code>M</code>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?