contexts.scala

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

SCALA
643
字号
/* NSC -- new Scala compiler * Copyright 2005-2008 LAMP/EPFL * @author  Martin Odersky */// $Id: Contexts.scala 14543 2008-04-07 15:57:07Z odersky $package scala.tools.nsc.typecheckerimport symtab.Flags._import scala.tools.nsc.util.{Position,NoPosition}import scala.collection.mutable.ListBuffer/** This trait ... * *  @author  Martin Odersky *  @version 1.0 */trait Contexts { self: Analyzer =>  import global._  val NoContext = new Context {    override def implicitss: List[List[ImplicitInfo]] = List()    outer = this  }  NoContext.enclClass = NoContext  NoContext.enclMethod = NoContext  private val startContext = {    NoContext.make(    global.Template(List(), emptyValDef, List()) setSymbol global.NoSymbol setType global.NoType,    global.definitions.RootClass,    global.definitions.RootClass.info.decls)  }  /** List of objects and packages to import from in   *  a root context.  This list is sensitive to the   *  compiler settings.   */  protected def rootImports(unit: CompilationUnit, tree: Tree): List[Symbol] = {    import definitions._    val imps = new ListBuffer[Symbol]    if (!settings.noimports.value) {      assert(isDefinitionsInitialized)      imps += JavaLangPackage      assert(ScalaPackage ne null, "Scala package is null")      imps += ScalaPackage      if (!(treeInfo.isPredefUnit(unit.body) || treeInfo.containsLeadingPredefImport(List(unit.body))))        imps += PredefModule    }    imps.toList  }  def rootContext(unit: CompilationUnit): Context =    rootContext(unit, EmptyTree, false)  def rootContext(unit: CompilationUnit, tree: Tree, erasedTypes: Boolean): Context = {    import definitions._    var sc = startContext    def addImport(pkg: Symbol) {      assert(pkg ne null)      val qual = gen.mkAttributedStableRef(pkg)      sc = sc.makeNewImport(        Import(qual, List((nme.WILDCARD, null)))        .setSymbol(NoSymbol.newImport(NoPosition).setFlag(SYNTHETIC).setInfo(ImportType(qual)))        .setType(NoType))      sc.depth += 1    }    for (imp <- rootImports(unit, tree))      addImport(imp)    val c = sc.make(unit, tree, sc.owner, sc.scope, sc.imports)    c.reportAmbiguousErrors = !erasedTypes    c.reportGeneralErrors = !erasedTypes    c.implicitsEnabled = !erasedTypes    c  }  def resetContexts() {    var sc = startContext    while (sc != NoContext) {      sc.tree match {        case Import(qual, _) => qual.tpe = singleType(qual.symbol.owner.thisType, qual.symbol)        case _ =>      }      sc = sc.outer    }  }  class Context private[typechecker] {    var unit: CompilationUnit = _    var tree: Tree = _ // Tree associated with this context    var owner: Symbol = NoSymbol// The current owner    var scope: Scope = _                    // The current scope    var outer: Context = _                  // The next outer context    var enclClass: Context = _              // The next outer context whose tree is a                                            // template or package definition    var enclMethod: Context = _             // The next outer context whose tree is a method    var variance: Int = _                   // Variance relative to enclosing class    private var _undetparams: List[Symbol] = List() // Undetermined type parameters,                                                    // not inherited to child contexts    var depth: Int = 0    var imports: List[ImportInfo] = List()   // currently visible imports    var openImplicits: List[Type] = List()   // types for which implicit arguments                                             // are currently searched    var prefix: Type = NoPrefix    var inConstructorSuffix = false         // are we in a secondary constructor                                            // after the this constructor call?    var returnsSeen = false                 // for method context: were returns encountered?    var reportAmbiguousErrors = false    var reportGeneralErrors = false    var implicitsEnabled = false    var checking = false    var retyping = false    var savedTypeBounds: List[(Symbol, Type)] = List() // saved type bounds       // for type parameters which are narrowed in a GADT    def intern0 : Context = {      if (this eq NoContext) return this      val txt = new Context      txt.unit = unit      txt.tree = tree      txt.owner = owner      txt.scope = scope      assert(outer ne this) // stupid      txt.outer = outer // already interned      def f(what : Context) =         if (what eq this) txt        else what      txt.enclClass = f(enclClass)      txt.enclMethod = f(enclMethod)      txt.implicitsEnabled = implicitsEnabled      txt.variance = variance      txt._undetparams = _undetparams      txt.depth = depth      txt.imports = imports      txt.openImplicits = openImplicits      txt.prefix = prefix      txt.inConstructorSuffix = inConstructorSuffix      txt.returnsSeen = returnsSeen      txt.reportGeneralErrors = reportGeneralErrors      txt.checking = checking      txt.retyping = retyping      txt.savedTypeBounds = savedTypeBounds      txt    }    override def equals(that: Any): Boolean = that match {      case that: AnyRef if (this eq that) =>        true      case that if !inIDE =>        super.equals(that)      //case NoContext => false      case that: Context =>        if (that eq NoContext) return this eq NoContext        assert(that ne NoContext)        if (this eq NoContext) return false        assert(inIDE)        def eq[T](x : T, y : T) = x == y        val a0 = {          if (tree ne null) tree.setType(null)          if ((tree eq null) || (that.tree eq null)) tree == that.tree else             tree equalsStructure that.tree;        }         val a1 = eq(owner, that.owner)        val a2 = eq(scope, that.scope)        def f(txt0 : Context, txt1 : Context) =           ((this eq txt0) && (that eq txt1)) || (txt0 eq txt1)                val a3 = f(outer, that.outer)        val a4 = f(enclClass, that.enclClass)        val a5 = f(enclMethod, that.enclMethod)        val a6 = eq(variance, that.variance)        val a7 = eq(_undetparams, that._undetparams)        val a8 = eq(depth, that.depth)        val a9 = eq(imports, that.imports)        val a10 = eq(openImplicits, that.openImplicits)        val a11 = eq(prefix, that.prefix)        val a12 = eq(inConstructorSuffix, that.inConstructorSuffix)        val a13 = eq(implicitsEnabled, that.implicitsEnabled)        val a14 = eq(checking, that.checking)        val a15 = eq(retyping, that.retyping)        val a16 = eq(savedTypeBounds, that.savedTypeBounds)        val a17 = eq(unit, that.unit)        val ret = a0 && a1 && a2 && a3 && a4 && a5 && a6 && a7 && a8 && a9 && a10 && a11 && a12 && a13 && a14 && a15 && a16 && a17        val a18 = {          if (implicitsRunId > that.implicitsRunId) {            that.implicitsRunId = NoRunId            that.implicitsCache = null          }          else if (that.implicitsRunId > implicitsRunId) {            implicitsRunId = NoRunId            implicitsCache = null          }          implicitsCache == that.implicitsCache        }        if (ret) {          if (!a18) {            //assert(this.implicitsCache == null || that.implicitsCache == null)          }        }        ret      case _ => false    }        def undetparams = _undetparams    def undetparams_=(ps: List[Symbol]) = {      //System.out.println("undetparams = " + ps);//debug      _undetparams = ps    }    /**     *  @param unit    ...     *  @param tree    ...     *  @param owner   ...     *  @param scope   ...     *  @param imports ...     *  @return        ...     */    def make(unit: CompilationUnit, tree: Tree, owner: Symbol,             scope: Scope, imports: List[ImportInfo]): Context = {      val c = new Context      c.unit = unit      c.tree = sanitize(tree)      c.owner = owner      c.scope = scope            c.outer = intern(this)      def internIf(txt : Context) = {        if (txt eq this) c.outer // already interned!        else txt      }            tree match {        case Template(_, _, _) | PackageDef(_, _) =>          c.enclClass = c          c.prefix = c.owner.thisType          c.inConstructorSuffix = false        case _ =>          c.enclClass = internIf(this.enclClass)          c.prefix =            if (c.owner != this.owner && c.owner.isTerm) NoPrefix            else this.prefix          c.inConstructorSuffix = this.inConstructorSuffix      }      tree match {        case DefDef(_, _, _, _, _, _) =>          c.enclMethod = c        case _ =>          c.enclMethod = internIf(this.enclMethod)      }      c.variance = this.variance      c.depth = if (scope == this.scope) this.depth else this.depth + 1      c.imports = imports      c.reportAmbiguousErrors = this.reportAmbiguousErrors      c.reportGeneralErrors = this.reportGeneralErrors      c.implicitsEnabled = this.implicitsEnabled      c.checking = this.checking      c.retyping = this.retyping      c.openImplicits = this.openImplicits      c    }    def make(unit: CompilationUnit): Context = {      val c = make(unit, EmptyTree, owner, scope, imports)      c.reportAmbiguousErrors = true      c.reportGeneralErrors = true      c.implicitsEnabled = true      c    }    def makeNewImport(imp: Import): Context =      make(unit, imp, owner, scope, new ImportInfo(imp, depth) :: imports)                def make(tree: Tree, owner: Symbol, scope: Scope): Context = {      if (tree == this.tree && owner == this.owner && scope == this.scope) this      else make0(tree, owner, scope)    }    private def make0(tree : Tree, owner : Symbol, scope : Scope) : Context = {      make(unit, tree, owner, scope, imports)    }    def makeNewScope(tree: Tree, owner: Symbol)(implicit kind : ScopeKind): Context =      make(tree, owner, scopeFor(scope, tree, kind))    // IDE stuff: distinguish between scopes created for typing and scopes created for naming.     def make(tree: Tree, owner: Symbol): Context =      make0(tree, owner, scope)    def make(tree: Tree): Context =      make(tree, owner)    def makeSilent(reportAmbiguousErrors: Boolean): Context = {      val c = make(tree)      c.reportGeneralErrors = false      c.reportAmbiguousErrors = reportAmbiguousErrors      c    }    def makeImplicit(reportAmbiguousErrors: Boolean) = {      val c = makeSilent(reportAmbiguousErrors)      c.implicitsEnabled = false      c    }    def makeConstructorContext = {      var baseContext = enclClass.outer      //todo: find out why we need next line      while (baseContext.tree.isInstanceOf[Template])        baseContext = baseContext.outer      val argContext = baseContext.makeNewScope(tree, owner)(Constructor0ScopeKind)      argContext.reportGeneralErrors = this.reportGeneralErrors      argContext.reportAmbiguousErrors = this.reportAmbiguousErrors      def enterElems(c: Context) {        def enterLocalElems(e: ScopeEntry) {          if (e != null && e.owner == c.scope) {            enterLocalElems(e.next)            argContext.scope enter e.sym          }        }        if (c.owner.isTerm && !c.owner.isLocalDummy) {

⌨️ 快捷键说明

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