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