addinterfaces.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 376 行

SCALA
376
字号
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author Martin Odersky */// $Id: AddInterfaces.scala 12285 2007-07-12 14:56:50Z odersky $package scala.tools.nsc.transformimport symtab._import Flags._import collection.mutable.{HashMap, ListBuffer}abstract class AddInterfaces extends InfoTransform {  import global._                  // the global environment  import definitions._             // standard classes and methods  import posAssigner.atPos         // for filling in tree positions   /** <p>   *    The phase sets <code>lateINTERFACE</code> for non-interface traits   *    that now become interfaces.   *  </p>   *  <p>   *    It sets <code>lateDEFERRED</code> for formerly concrete methods in   *    such traits.   *  </p>   */  override def phaseNewFlags: Long = lateDEFERRED | lateINTERFACE  /** Type reference after erasure; to be defined in subclass   *  <code>Erasure</code>.   */  def erasedTypeRef(sym: Symbol): Type  /** Erasure type-map; to be defined in subclass   *  <code>Erasure</code>.   */  def erasure: TypeMap  /** A lazily constructed map that associates every non-interface trait with   *  its implementation class.   */  private val implClassMap = new HashMap[Symbol, Symbol]  /** A lazily constructed map that associates every concrete method in a non-interface   *  trait that's currently compiled with its corresponding method in the trait's   *  implementation class.   */  private val implMethodMap = new HashMap[Symbol, Symbol]  override def newPhase(prev: scala.tools.nsc.Phase): StdPhase = {    implClassMap.clear    implMethodMap.clear    super.newPhase(prev)  }  /** Is given trait member symbol a member of the trait's interface    *  after this transform is performed? */  private def isInterfaceMember(sym: Symbol): Boolean = {    sym.isType ||    { sym.info; // to set lateMETHOD flag if necessary      sym.isMethod && !(sym hasFlag (PRIVATE | BRIDGE | LABEL)) &&       !sym.isConstructor && !sym.isImplOnly    }  }  /** Does symbol need an implementation method? */  private def needsImplMethod(sym: Symbol): Boolean =    sym.isMethod && isInterfaceMember(sym) &&     (!(sym hasFlag (DEFERRED | SUPERACCESSOR)) || (sym hasFlag lateDEFERRED))  def implClassPhase = currentRun.erasurePhase.next  /** Return the implementation class of a trait; create a new one of one does not yet exist */    def implClass(iface: Symbol): Symbol = implClassMap.get(iface) match {    case Some(c) => c    case None =>      atPhase(implClassPhase) {        val implName = nme.implClassName(iface.name)        var impl = if (iface.owner.isClass) iface.owner.info.decl(implName) else NoSymbol        if (impl == NoSymbol) {          impl = iface.cloneSymbolImpl(iface.owner)          impl.name = implName          if (iface.owner.isClass)            iface.owner.info.decls enter impl         }        if (currentRun.compiles(iface)) currentRun.symSource(impl) = iface.sourceFile        impl setPos iface.pos        impl.flags = iface.flags & ~(INTERFACE | lateINTERFACE) | IMPLCLASS        impl setInfo new LazyImplClassType(iface)        implClassMap(iface) = impl        if (settings.debug.value) log("generating impl class " + impl + " in " + iface.owner)//debug        impl      }  }  /** <p>   *    A lazy type to set the info of an implementation class    *    The parents of an implementation class for trait <code>iface</code> are:   *  </p>   *  <ul>   *    <li>superclass: <code>Object</code></li>   *    <li>   *      mixin classes: mixin classes of <code>iface</code> where every   *      non-interface trait is mapped to its implementation class, followed   *      by <code>iface</code> itself.   *    </li>   *  </ul>   *  <p>   *    The declarations of a mixin class are:   *  </p>   *  <ul>   *    <li>   *      for every interface member of <code>iface</code> its implemention   *      method, if one is needed.   *    </li>   *    <li>   *      every former member of <code>iface</code> that is implementation only   *    </li>   *  </ul>   */  private class LazyImplClassType(iface: Symbol) extends LazyType {    /** Compute the decls of implementation class <code>implClass</code>,      *  given the decls <code>ifaceDecls</code> of its interface.     *     *  @param implClass  ...     *  @param ifaceDecls ...     *  @return           ...     */    private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = {      val decls = newScope      if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol)        decls enter (implClass.newMethod(implClass.pos, nme.MIXIN_CONSTRUCTOR)                      setInfo MethodType(List(), UnitClass.tpe))      for (val sym <- ifaceDecls.elements) {        if (isInterfaceMember(sym)) {          if (needsImplMethod(sym)) {            val impl = sym.cloneSymbol(implClass).setInfo(sym.info).resetFlag(lateDEFERRED)            if (currentRun.compiles(implClass)) implMethodMap(sym) = impl            decls enter impl            sym setFlag lateDEFERRED          }        } else {          sym.owner = implClass           // note: OK to destructively modify the owner here,           // because symbol will not be accessible from outside the sourcefile.          // mixin constructors are corrected separately; see TermSymbol.owner          decls enter sym        }      }      decls    }    override def complete(sym: Symbol) {      def implType(tp: Type): Type = tp match {        case ClassInfoType(parents, decls, _) =>          assert(phase == implClassPhase, sym)          ClassInfoType(            ObjectClass.tpe :: (parents.tail map mixinToImplClass) ::: List(iface.tpe),            implDecls(sym, decls),            sym)        case PolyType(tparams, restpe) =>          implType(restpe)      }      sym.setInfo(implType(atPhase(currentRun.erasurePhase)(iface.info)))    }    override def load(clazz: Symbol) { complete(clazz) }  }  /** If type <code>tp</code> refers to a non-interface trait, return a   *  reference to its implementation class. Otherwise return <code>tp</code>   *  itself.   *   *  @param tp ...   *  @return   ...   */  private def mixinToImplClass(tp: Type): Type =     erasure(      tp match { //@MATN: no normalize needed (comes after erasure)        case TypeRef(pre, sym, args) if (sym.needsImplClass) =>          typeRef(pre, implClass(sym), args)        case _ =>          tp      })  def transformMixinInfo(tp: Type): Type = tp match {    case ClassInfoType(parents, decls, clazz) =>      if (clazz.needsImplClass) {        clazz setFlag lateINTERFACE        implClass(clazz) // generate an impl class      }      val parents1 =        if (parents.isEmpty) List()        else {          assert(!parents.head.typeSymbol.isTrait, clazz)          if (clazz.isTrait) erasedTypeRef(ObjectClass) :: parents.tail          else parents        }      val decls1 = decls filter (sym =>        if (clazz hasFlag INTERFACE) isInterfaceMember(sym)        else (!sym.isType || sym.isClass))      //if (!clazz.isPackageClass) System.out.println("Decls of "+clazz+" after explicitOuter = " + decls1);//DEBUG      //if ((parents1 eq parents) && (decls1 eq decls)) tp      //else       ClassInfoType(parents1, decls1, clazz)    case _ =>      tp  }// Tree transformation --------------------------------------------------------------  private class ChangeOwnerAndReturnTraverser(oldowner: Symbol, newowner: Symbol)          extends ChangeOwnerTraverser(oldowner, newowner) {    override def traverse(tree: Tree) {      tree match {        case Return(expr) =>          if (tree.symbol == oldowner) tree.symbol = newowner        case _ =>      }      super.traverse(tree)    }  }  private def ifaceMemberDef(tree: Tree): Tree =    if (!tree.isDef || !isInterfaceMember(tree.symbol)) EmptyTree    else if (needsImplMethod(tree.symbol)) DefDef(tree.symbol, vparamss => EmptyTree)    else tree  private def ifaceTemplate(templ: Template): Template =    copy.Template(templ, templ.parents, emptyValDef, templ.body map ifaceMemberDef)  private def implMethodDef(tree: Tree, ifaceMethod: Symbol): Tree =    implMethodMap.get(ifaceMethod) match {      case Some(implMethod) =>        tree.symbol = implMethod        new ChangeOwnerAndReturnTraverser(ifaceMethod, implMethod)(tree)      case None =>        throw new Error("implMethod missing for " + ifaceMethod)    }  private def implMemberDef(tree: Tree): Tree =    if (!tree.isDef || !isInterfaceMember(tree.symbol)) tree    else if (needsImplMethod(tree.symbol)) implMethodDef(tree, tree.symbol)    else EmptyTree  /** Add mixin constructor definition    *    def $init$(): Unit = ()   *  to `stats' unless there is already one.   */  private def addMixinConstructorDef(clazz: Symbol, stats: List[Tree]): List[Tree] =     if (treeInfo.firstConstructor(stats) != EmptyTree) stats    else DefDef(clazz.primaryConstructor, vparamss => Block(List(), Literal(()))) :: stats      private def implTemplate(clazz: Symbol, templ: Template): Template = atPos(templ.pos) {    val templ1 = atPos(templ.pos) {      Template(templ.parents, emptyValDef,                addMixinConstructorDef(clazz, templ.body map implMemberDef))        .setSymbol(clazz.newLocalDummy(templ.pos))    }    new ChangeOwnerTraverser(templ.symbol.owner, clazz)(      new ChangeOwnerTraverser(templ.symbol, templ1.symbol)(templ1))  }  def implClassDefs(trees: List[Tree]): List[Tree] = {    val buf = new ListBuffer[Tree]    for (val tree <- trees)      tree match {        case ClassDef(_, _, _, impl) =>          if (tree.symbol.needsImplClass)            buf += {              val clazz = implClass(tree.symbol).initialize              ClassDef(clazz, implTemplate(clazz, impl))            }        case _ =>      }    buf.toList  }  /** Add calls to supermixin constructors   *  <blockquote><pre>super[mix].$init$()</pre></blockquote>   *  to <code>tree</code>. <code>tree</code> which is assumed to be the body   *  of a constructor of class <code>clazz</code>.   */  private def addMixinConstructorCalls(tree: Tree, clazz: Symbol): Tree = {    def mixinConstructorCall(impl: Symbol): Tree = atPos(tree.pos) {      Apply(Select(This(clazz), impl.primaryConstructor), List())    }    val mixinConstructorCalls: List[Tree] = {      for (val mc <- clazz.mixinClasses.reverse;           mc.hasFlag(lateINTERFACE) && mc != ScalaObjectClass)      yield mixinConstructorCall(implClass(mc))    }    (tree: @unchecked) match {      case Block(stats, expr) =>        val (presuper, supercall :: rest) = stats span (_.symbol.hasFlag(PRESUPER))        //assert(supercall.symbol.isClassConstructor, supercall)        copy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr)    }  }  protected val mixinTransformer = new Transformer {    override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =      (super.transformStats(stats, exprOwner) :::       super.transformStats(implClassDefs(stats), exprOwner))    override def transform(tree: Tree): Tree = {      val sym = tree.symbol      val tree1 = tree match {        case ClassDef(mods, name, tparams, impl) if (sym.needsImplClass) =>          implClass(sym).initialize // to force lateDEFERRED flags          copy.ClassDef(tree, mods | INTERFACE, name, tparams, ifaceTemplate(impl))        case DefDef(mods, name, tparams, vparamss, tpt, rhs)         if (sym.isClassConstructor && sym.isPrimaryConstructor && sym.owner != ArrayClass) =>          copy.DefDef(tree, mods, name, tparams, vparamss, tpt,                       addMixinConstructorCalls(rhs, sym.owner)) // (3)        case Template(parents, self, body) =>          val parents1 = sym.owner.info.parents map (t => TypeTree(t) setPos tree.pos)          copy.Template(tree, parents1, emptyValDef, body)        case This(_) =>          if (sym.needsImplClass) {            val impl = implClass(sym)            var owner = currentOwner            while (owner != sym && owner != impl) owner = owner.owner;            if (owner == impl) This(impl) setPos tree.pos            else tree          } else tree/* !!!        case Super(qual, mix) =>          val mix1 = mix            if (mix == nme.EMPTY.toTypeName) mix            else {              val ps = atPhase(currentRun.erasurePhase) {                sym.info.parents dropWhile (p => p.symbol.name != mix)              }              assert(!ps.isEmpty, tree);              if (ps.head.symbol.needsImplClass) implClass(ps.head.symbol).name               else mix            }          if (sym.needsImplClass) Super(implClass(sym), mix1) setPos tree.pos          else copy.Super(tree, qual, mix1)*/        case _ =>          tree      }      super.transform(tree1)    }  }}/*    val ensureNoEscapes = new TypeTraverser {      def ensureNoEscape(sym: Symbol) {        if (sym.hasFlag(PRIVATE)) {          var o = currentOwner;          while (o != NoSymbol && o != sym.owner && !o.isLocal && !o.hasFlag(PRIVATE))          o = o.owner          if (o == sym.owner) sym.makeNotPrivate(base);        }      }      def traverse(t: Type): TypeTraverser = {        t match {          case TypeRef(qual, sym, args) =>            ensureNoEscape(sym)            mapOver(t)          case ClassInfoType(parents, decls, clazz) =>            parents foreach { p => traverse; () }            traverse(t.typeOfThis)          case _ =>             mapOver(t)        }        this      }    }*/

⌨️ 快捷键说明

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