diff options
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Flags.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Symbols.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 250 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 120 | ||||
-rw-r--r-- | src/dotty/tools/dotc/util/Positions.scala | 5 |
7 files changed, 225 insertions, 161 deletions
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 346cf72f5..588c18c4c 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -262,7 +262,7 @@ object Contexts { def withTree(tree: Tree[_ >: Untyped]): this.type = { this.tree = tree; this } def withScope(scope: Scope): this.type = { this.scope = scope; this } def withNewScope: this.type = { this.scope = newScope; this } - def withTyper(typer: Typer): this.type = { this.typer = typer; this } + def withTyper(typer: Typer): this.type = { this.typer = typer; this.scope = typer.scope; this } def withImport(importInfo: ImportInfo): this.type = { this.imports = importInfo :: imports; this } def withReporter(reporter: Reporter): this.type = { this.reporter = reporter; this } def withDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this } diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index e15ca04d3..6e4777749 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -394,6 +394,9 @@ object Flags { /** Module classes always have these flags set */ final val ModuleClassCreationFlags = ModuleClass | Final + /** The flags of the self symbol */ + final val SelfSymFlags = Private | Local | Deferred + /** The flags of a type parameter */ final val TypeParamCreationFlags = TypeParam | Protected | Local diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index e1550d529..64119944c 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -638,8 +638,6 @@ object SymDenotations { } /** The contents of a class definition during a period - * Note: important to leave initctx non-implicit, and to check that it is not - * retained after object construction. */ class ClassDenotation private[SymDenotations] ( symbol: Symbol, diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 23984c7a4..34b3eae73 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -213,8 +213,8 @@ trait Symbols { this: Context => newConstructor(cls, EmptyFlags, Nil, Nil) /** Create a symbol representing a selftype declaration for class `cls`. */ - def newSelfSym(cls: ClassSymbol): TermSymbol = - ctx.newSymbol(cls, nme.THIS, SyntheticArtifact, cls.classInfo.selfType) + def newSelfSym(cls: ClassSymbol, name: TermName = nme.WILDCARD, optSelfType: Type = NoType): TermSymbol = + ctx.newSymbol(cls, name, SelfSymFlags, optSelfType orElse cls.classInfo.selfType, coord = cls.coord) /** Create new type parameters with given owner, names, and flags. * @param boundsFn A function that, given type refs to the newly created diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index fc8b85f11..7308d3aa6 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -10,6 +10,7 @@ import ast.desugar, ast.desugar._ import util.Positions._ import util.SourcePosition import collection.mutable +import annotation.tailrec import language.implicitConversions trait NamerContextOps { this: Context => @@ -23,91 +24,85 @@ trait NamerContextOps { this: Context => } } -class Environment { - import untpd._ - val scope = newScope - val expandedTree = new mutable.WeakHashMap[MemberDef, Tree] - val treeOfSym = mutable.Map[Symbol, Tree]() - val typedTree = mutable.Map[Tree, tpd.Tree]() -} - +/** This class attaches creates symbols from definitions and imports and gives them + * lazy types. + * + * Timeline: + * + * During enter, trees are expanded as necessary, populating the expandedTree map. + * Symbols are created, and the symOfTree map is set up. + * + * Symbol completion causes some trees to be already typechecked and typedTree + * entries are created to associate the typed trees with the untyped expanded originals. + * + * During typer, original trees are first expanded using expandedTree. For each + * expanded member definition or import we extract and remove the corresponding symbol + * from the symOfTree map and complete it. We then consult the typedTree map to see + * whether a typed tree exists already. If yes, the typed tree is returned as result. + * Otherwise, we proceed with regular type checking. + * + * The scheme is designed to allow sharing of nodes, as long as each duplicate appears + * in a different method. + */ class Namer { typer: Typer => import untpd._ - /** There are three maps at play here: - * - * - * Original tree ------------> Expanded tree(s) - * expandedTree : ^ - * (weak) : | - * : | - * symOfUntypedTree : | untypedTreeOfSym - * : | - * v | typedTreeOfSym - * Symbol --------------> Typed tree - * <:::::::::::::: - * symOfTypedTree - * - * The expandedTree map is weak, the others are strong. - * - * The untypedTreeOfSym map can be inverted to a map from untyped trees - * to the symbols they define. The function `symOfUntypedTree` looks up a - * symbol in the current context with the name of the tree and which points - * back (via untypedTreeOfSym) to the tree. Similarly, `typedTreeOfSym` can be - * inverted to `symofTypedTree`. - * - * Timeline: - * - * During enter, trees are expanded as necessary, populating the expandedTree map. - * Symbols are created, and the untypedTreeOfSym link is set up. - * - * Symbol completion causes some trees to be already typechecked and typedTreeOfSym - * entries are created to associate the typed trees with the untyped expanded originals. - * - * During typer, original trees are first expanded using expandedTree. For each - * expanded definition tree, we make sure the corresponding symbol is completed - * and remove its untypedTreeOfSym link. We then consult the typedTreeOfSym map. - * If a typed tree exists, it replaces the original untyped tree, and the corresponding - * entry in the typedTree map is removed. Otherwise the untyped tree is typechecked, - * yielding the typed tree. - * - * Dealing with shared tree nodes: - * - * The scheme is designed to allow arbitrary sharing of nodes: (1) The expansion of - * a tree is context free, so expanding trees several times yields the same result - * as expanding once. No need to lock or duplicate expandedTree items. (2) - * Each `enterSyms` pass over a shared node creates new symbols and the two remaining - * maps are indexed with these symbols, so no sharing occurs for them. - * - * Memory reclamation: - * - * expandedTrees is a weak map, so entries will be reclaimed once the original - * untyped tree is no longer referenced. typedTreeOfSym and untypedTreeOfSym - * entries are both removed by the time a definition is integrated in the typed tree - * during phase typer. + + /** A partial map from unexpanded member defs to their expansions. + * Populated during enterSyms, emptied during typer. + */ + lazy val expandedTree = new mutable.HashMap[MemberDef, Tree] + + /** A map from expanded MemberDef or Import trees to their symbols. + * Populated during enterSyms, emptied at the point a typed tree + * with the same symbol is created (this can be when the symbol is completed + * or at the latest when the tree is typechecked. */ + lazy val symOfTree = new mutable.HashMap[Tree, Symbol] - lazy val expandedTree = new mutable.WeakHashMap[Tree, Tree] - lazy val symOfTree = new mutable.WeakHashMap[Tree, Symbol] - lazy val typedTree = new mutable.WeakHashMap[Tree, tpd.Tree] + /** A map from expanded trees their typed versions. + * Populated when trees are typechecked during completion (using method typedAhead). + * Emptied during typer. + */ + lazy val typedTree = new mutable.HashMap[Tree, tpd.Tree] + + /** A map from method symbols to nested typers. + * Populated when methods are completed. Emptied when they are typechecked. + * The nested typer contains new versions of the four maps above including this + * one, so that trees that are shared between different DefDefs can be independently + * used as indices. It also contains a scope that contains nested parameters. + */ lazy val nestedTyper = new mutable.HashMap[Symbol, Typer] + /** The scope of the typer. + * For nested typers this is a place parameters are entered during completion + * and where they survive until typechecking. + */ val scope = newScope - implicit def posToCoord(pos: Position): Coord = positionCoord(pos) + /** The symbol of the given expanded tree. */ + def symbolOfTree(tree: Tree)(implicit ctx: Context): Symbol = typedTree get tree match { + case Some(tree1) => tree1.denot.symbol + case _ => symOfTree(tree) + } - def privateWithinClass(mods: Modifiers)(implicit ctx: Context): Symbol = { - val pw = mods.privateWithin - if (pw.isEmpty) NoSymbol + /** The enclosing class with given name; error if none exists */ + def enclosingClassNamed(name: TypeName, pos: Position)(implicit ctx: Context): Symbol = { + if (name.isEmpty) NoSymbol else { - val cls = ctx.owner.enclosingClassNamed(pw) - if (!cls.exists) ctx.error(s"no enclosing class or object is named $pw", mods.pos) + val cls = ctx.owner.enclosingClassNamed(name) + if (!cls.exists) ctx.error(s"no enclosing class or object is named name", pos) cls } } + /** If this tree is a member def or an import, create a symbol of it + * and store in symOfTree map. + */ def createSymbol(tree: Tree)(implicit ctx: Context): Symbol = { + def privateWithinClass(mods: Modifiers) = + enclosingClassNamed(mods.privateWithin, mods.pos) val sym = tree match { case tree: ClassDef => ctx.enter(ctx.newClassSymbol( @@ -127,32 +122,49 @@ class Namer { typer: Typer => sym } - def expansion(defn: MemberDef)(implicit ctx: Context): Tree = { - val expanded = desugar.memberDef(defn) - if (expanded ne defn) expandedTree(defn) = expanded + /** The expansion of a member def */ + def expansion(mdef: MemberDef)(implicit ctx: Context): Tree = { + val expanded = desugar.memberDef(mdef) + if (expanded ne mdef) expandedTree(mdef) = expanded expanded } + /** A new context that summarizes an import statement */ + def importContext(sym: Symbol, selectors: List[Tree])(implicit ctx: Context) = + ctx.fresh.withImport(ImportInfo(sym, selectors, ctx.scopeNestingLevel)) + + /** A new context for the interior of a class */ + def inClassContext(cls: ClassSymbol, selfName: TermName)(implicit ctx: Context): Context = { + val localCtx: Context = ctx.fresh.withNewScope + if (selfName != nme.WILDCARD) + localCtx.enter(localCtx.newSelfSym(cls, selfName, cls.thisType)) + localCtx + } + + /** Enter statement */ def enterSym(stat: Tree)(implicit ctx: Context): Context = stat match { case imp: Import => - val sym = createSymbol(imp) - ctx.fresh.withImport(ImportInfo(sym, imp.selectors, ctx.scopeNestingLevel)) - case defn: MemberDef => - expansion(defn).toList foreach createSymbol + importContext(createSymbol(imp), imp.selectors) + case mdef: MemberDef => + expansion(mdef).toList foreach createSymbol ctx case _ => ctx } + /** Enter all statements in stats. + */ def enterSyms(stats: List[Tree])(implicit ctx: Context): Context = { - - def traverse(stats: List[Tree])(implicit ctx: Context): Context = stats match { + @tailrec def traverse(stats: List[Tree])(implicit ctx: Context): Context = stats match { case stat :: stats1 => traverse(stats)(enterSym(stat)) case nil => ctx } + /** Merge the definitions of a synthetic companion generated by a case class + * and the real companion, if both exist. + */ def mergeCompanionDefs() = { val caseClassDef = mutable.Map[TypeName, ClassDef]() for (cdef @ ClassDef(mods, name, _) <- stats) @@ -176,23 +188,24 @@ class Namer { typer: Typer => result } + /** The completer of a symbol defined by a member def or import */ class Completer(original: Tree)(implicit ctx: Context) extends LazyType { def complete(denot: SymDenotation): Unit = { val sym = denot.symbol def localContext = ctx.fresh.withOwner(sym) - def typeSig(defn: Tree): Type = defn match { - case defn: ValDef => - valOrDefDefSig(defn, sym, identity)(localContext) - case defn: DefDef => + def typeSig(tree: Tree): Type = tree match { + case tree: ValDef => + valOrDefDefSig(tree, sym, identity)(localContext) + case tree: DefDef => val typer1 = new Typer nestedTyper(sym) = typer1 - typer1.defDefSig(defn, sym)(localContext.withScope(typer1.scope)) - case defn: TypeDef => - typeDefSig(defn, sym)(localContext.withNewScope) - case defn: ClassDef => - classDefSig(defn, sym.asClass)(localContext) + typer1.defDefSig(tree, sym)(localContext.withTyper(typer1)) + case tree: TypeDef => + typeDefSig(tree, sym)(localContext.withNewScope) + case tree: ClassDef => + classDefSig(tree, sym.asClass)(localContext) case imp: Import => val expr1 = typedAhead(imp.expr) ImportType(SharedTree(expr1)) @@ -202,15 +215,28 @@ class Namer { typer: Typer => } } + /** Typecheck tree during completion, and remember result in yypedtree map */ def typedAhead(tree: Tree, mode: Mode.Value = Mode.Expr, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree = - typedTree.getOrElseUpdate(tree, typer.typed(tree)) + typedTree.getOrElseUpdate(tree, typer.typedExpanded(tree, mode, pt)) + + /** Enter and typecheck parameter list */ + def completeParams(params: List[MemberDef])(implicit ctx: Context) = { + enterSyms(params) + for (param <- params) typedAhead(param) + } - def valOrDefDefSig(defn: ValOrDefDef, sym: Symbol, paramFn: Type => Type)(implicit ctx: Context): Type = { + /** The type signature of a ValDef or DefDef + * @param mdef The definition + * @param sym Its symbol + * @param paramFn A wrapping function that produces the type of the + * defined symbol, given its final return type + */ + def valOrDefDefSig(mdef: ValOrDefDef, sym: Symbol, paramFn: Type => Type)(implicit ctx: Context): Type = { val pt = - if (!defn.tpt.isEmpty) WildcardType + if (!mdef.tpt.isEmpty) WildcardType else { lazy val schema = paramFn(WildcardType) - val site = sym.owner.symTypeRef + val site = sym.owner.thisType val inherited = { ((NoType: Type) /: sym.owner.info.baseClasses.tail) { (tp, cls) => val itpe = cls.info @@ -221,16 +247,12 @@ class Namer { typer: Typer => tp & itpe } } - inherited orElse typedAhead(defn.rhs).tpe + inherited orElse typedAhead(mdef.rhs).tpe } - paramFn(typedAhead(defn.tpt, Mode.Type, pt).tpe) - } - - def completeParams(params: List[MemberDef])(implicit ctx: Context) = { - enterSyms(params) - for (param <- params) typedAhead(param) + paramFn(typedAhead(mdef.tpt, Mode.Type, pt).tpe) } + /** The type signature of a DefDef with given symbol */ def defDefSig(ddef: DefDef, sym: Symbol)(implicit ctx: Context) = { val DefDef(_, name, tparams, vparamss, _, _) = ddef completeParams(tparams) @@ -239,15 +261,16 @@ class Namer { typer: Typer => val isSecondaryConstructor = isConstructor && sym != sym.owner.primaryConstructor def typeParams = if (isSecondaryConstructor) sym.owner.primaryConstructor.typeParams - else tparams map symOfTree + else tparams map symbolOfTree def wrapMethType(restpe: Type): Type = { val monotpe = (restpe /: vparamss) { (restpe, params) => - val creator = - if (params.nonEmpty && (params.head.mods is Implicit)) ImplicitMethodType else MethodType - creator.fromSymbols(params map symOfTree, restpe) + val make = + if (params.nonEmpty && (params.head.mods is Implicit)) ImplicitMethodType + else MethodType + make.fromSymbols(params map symbolOfTree, restpe) } - if (tparams.nonEmpty) PolyType.fromSymbols(typeParams, monotpe) + if (typeParams.nonEmpty) PolyType.fromSymbols(typeParams, monotpe) else if (vparamss.isEmpty) ExprType(monotpe) else monotpe } @@ -259,12 +282,13 @@ class Namer { typer: Typer => else valOrDefDefSig(ddef, sym, wrapMethType) } - def typeDefSig(defn: TypeDef, sym: Symbol)(implicit ctx: Context): Type = { - completeParams(defn.tparams) + def typeDefSig(tdef: TypeDef, sym: Symbol)(implicit ctx: Context): Type = { + completeParams(tdef.tparams) ??? } - def classDefSig(defn: ClassDef, cls: ClassSymbol)(implicit ctx: Context): Type = { + /** The type signature of a ClassDef with given symbol */ + def classDefSig(cdef: ClassDef, cls: ClassSymbol)(implicit ctx: Context): Type = { def parentType(constr: untpd.Tree): Type = { val Trees.Select(Trees.New(tpt), _) = TreeInfo.methPart(constr) @@ -273,23 +297,19 @@ class Namer { typer: Typer => else typedAhead(constr, Mode.Expr).tpe } - def enterSelfSym(name: TermName, tpe: Type): Unit = - ctx.enter(ctx.newSymbol(ctx.owner, name, Synthetic, tpe, coord = cls.coord)) - - val ClassDef(_, _, impl @ Template(_, parents, self, body)) = defn + val ClassDef(_, _, impl @ Template(_, parents, self, body)) = cdef val decls = newScope val (params, rest) = body span { - case td: TypeDef => td.mods is ParamOrAccessor + case td: TypeDef => td.mods is Param + case td: ValDef => td.mods is ParamAccessor case _ => false } enterSyms(params) val parentTypes = parents map parentType val parentRefs = ctx.normalizeToRefs(parentTypes, cls, decls) - val selfTypeOpt = if (self.tpt.isEmpty) NoType else typedAhead(self.tpt, Mode.Type).tpe - if (self.name != nme.WILDCARD) - enterSelfSym(self.name, selfTypeOpt orElse cls.typeConstructor) - enterSyms(rest) - ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfTypeOpt) + val optSelfType = if (self.tpt.isEmpty) NoType else typedAhead(self.tpt, Mode.Type).tpe + enterSyms(rest)(inClassContext(cls, self.name)) + ClassInfo(cls.owner.thisType, cls, parentRefs, decls, optSelfType) } }
\ No newline at end of file diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index dd46a678e..295d0a1b2 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -9,6 +9,7 @@ import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Fla import util.Positions._ import util.SourcePosition import collection.mutable +import annotation.tailrec import language.implicitConversions import desugar.Mode @@ -19,73 +20,82 @@ class Typer extends Namer { import tpd._ - def typedImport(imp: untpd.Import, pt: Type)(implicit ctx: Context): Import = { - val expr1 = typed(imp.expr) - imp.withType(pt).derivedImport(expr1, imp.selectors) - } - def typedModifiers(mods: untpd.Modifiers): Modifiers = ??? - def typedValDef(defn: untpd.ValDef, sym: Symbol)(implicit ctx: Context) = { - val Trees.ValDef(mods, name, tpt, rhs) = defn + def typedValDef(vdef: untpd.ValDef, sym: Symbol)(implicit ctx: Context) = { + val Trees.ValDef(mods, name, tpt, rhs) = vdef val mods1 = typedModifiers(mods) val tpt1 = typedType(tpt) val rhs1 = typedExpr(rhs, tpt1.tpe) val pt = if (sym.exists) sym.symRef else NoType - defn.withType(pt).derivedValDef(mods1, name, tpt1, rhs1) + vdef.withType(pt).derivedValDef(mods1, name, tpt1, rhs1) } - def typedDefDef(defn: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = { - val Trees.DefDef(mods, name, tparams, vparamss, tpt, rhs) = defn + def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = { + val Trees.DefDef(mods, name, tparams, vparamss, tpt, rhs) = ddef val mods1 = typedModifiers(mods) val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef]) val vparamss1 = vparamss.mapconserve(_ mapconserve (typed(_).asInstanceOf[ValDef])) val tpt1 = typedType(tpt) val rhs1 = typedExpr(rhs, tpt1.tpe) - defn.withType(sym.symRef).derivedDefDef(mods1, name, tparams1, vparamss1, tpt1, rhs1) + ddef.withType(sym.symRef).derivedDefDef(mods1, name, tparams1, vparamss1, tpt1, rhs1) } - def typedTypeDef(defn: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): TypeDef = { - val Trees.TypeDef(mods, name, tparams, rhs) = defn + def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): TypeDef = { + val Trees.TypeDef(mods, name, tparams, rhs) = tdef val mods1 = typedModifiers(mods) val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef]) val rhs1 = typedType(rhs) - defn.withType(sym.symRef).derivedTypeDef(mods1, name, tparams1, rhs1) + tdef.withType(sym.symRef).derivedTypeDef(mods1, name, tparams1, rhs1) } - def typedClassDef(defn: untpd.ClassDef, cls: ClassSymbol)(implicit ctx: Context) = { - val Trees.ClassDef(mods, name, impl @ Trees.Template(constr, parents, self, body)) = defn + def typedClassDef(cdef: untpd.ClassDef, cls: ClassSymbol)(implicit ctx: Context) = { + val Trees.ClassDef(mods, name, impl @ Template(constr, parents, self, body)) = cdef val mods1 = typedModifiers(mods) - val constr1 = typed(constr) + val constr1 = typed(constr).asInstanceOf[DefDef] val parents1 = parents mapconserve (typed(_)) - val self1 = typed(self) - ??? + val self1 = self.withType(NoType).derivedValDef( + typedModifiers(self.mods), self.name, typed(self.tpt), EmptyTree) + + val localDummy = ctx.newLocalDummy(cls, impl.pos) + val body1 = typedStats(body, localDummy)(inClassContext(cls, self.name)) + val impl1 = impl.withType(localDummy.symRef).derivedTemplate( + constr1, parents1, self1, body1) + + cdef.withType(cls.symRef).derivedClassDef(mods1, name, impl1) + + // todo later: check that + // 1. If class is non-abstract, it is instantiatable: + // - self type is s supertype of own type + // - all type members have consistent bounds + // 2. all private type members have consistent bounds + // 3. Types do not override classes. + // 4. Polymorphic type defs override nothing. } - def typedMemberDef(defn: untpd.MemberDef, sym: Symbol)(implicit ctx: Context) = { - sym.ensureCompleted() - def localContext = ctx.fresh.withOwner(sym) - defn match { - case defn: untpd.ValDef => - typedValDef(defn, sym)(localContext) - case defn: untpd.DefDef => - val typer1 = nestedTyper.remove(sym).get - typer1.typedDefDef(defn, sym)(localContext.withScope(typer1.scope)) - case defn: untpd.TypeDef => - typedTypeDef(defn, sym)(localContext.withNewScope) - case defn: untpd.ClassDef => - typedClassDef(defn, sym.asClass)(localContext) - } + def typedImport(imp: untpd.Import, sym: Symbol)(implicit ctx: Context): Import = { + val expr1 = typed(imp.expr) + imp.withType(sym.symRef).derivedImport(expr1, imp.selectors) } - def typed(tree: untpd.Tree, mode: Mode.Value = Mode.Expr, pt: Type = WildcardType)(implicit ctx: Context): Tree = { - typedTree get tree match { + def typedExpanded(tree: untpd.Tree, mode: Mode.Value = Mode.Expr, pt: Type = WildcardType)(implicit ctx: Context): Tree = { + val sym = symOfTree.remove(tree).getOrElse(NoSymbol) + sym.ensureCompleted() + def localContext = ctx.fresh.withOwner(sym) + typedTree remove tree match { case Some(tree1) => tree1 case none => tree match { - case defn: untpd.MemberDef => - typedMemberDef(defn, symOfTree(defn)) - case imp: untpd.Import => - typedImport(imp, symOfTree(imp).symRef) + case tree: untpd.ValDef => + typedValDef(tree, sym)(localContext) + case tree: untpd.DefDef => + val typer1 = nestedTyper.remove(sym).get + typer1.typedDefDef(tree, sym)(localContext.withTyper(typer1)) + case tree: untpd.TypeDef => + typedTypeDef(tree, sym)(localContext.withNewScope) + case tree: untpd.ClassDef => + typedClassDef(tree, sym.asClass)(localContext) + case tree: untpd.Import => + typedImport(tree, sym) case tree: untpd.TypeTree => if (!tree.isEmpty) typed(tree.original, Mode.Type, pt) else { @@ -98,6 +108,38 @@ class Typer extends Namer { } } + def typed(tree: untpd.Tree, mode: Mode.Value = Mode.Expr, pt: Type = WildcardType)(implicit ctx: Context): Tree = { + val xtree = + tree match { + case tree: untpd.MemberDef => + expandedTree remove tree match { + case Some(xtree) => xtree + case none => tree + } + case _ => tree + } + typedExpanded(xtree, mode, pt) + } + + def typedStats(stats: List[untpd.Tree], exprOwner: Symbol)(implicit ctx: Context): List[tpd.Tree] = { + val buf = new mutable.ListBuffer[Tree] + @tailrec def traverse(stats: List[untpd.Tree])(implicit ctx: Context): List[Tree] = stats match { + case (imp: untpd.Import) :: rest => + val imp1 = typed(imp) + buf += imp1 + traverse(rest)(importContext(imp1.symbol, imp.selectors)) + case (mdef: untpd.MemberDef) :: rest => + buf += typed(mdef) + traverse(rest) + case stat :: rest => + buf += typed(stat)(ctx.fresh.withOwner(exprOwner)) + traverse(rest) + case _ => + buf.toList + } + traverse(stats) + } + def typedExpr(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = typed(tree, Mode.Expr, pt) def typedType(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = diff --git a/src/dotty/tools/dotc/util/Positions.scala b/src/dotty/tools/dotc/util/Positions.scala index 0a0a52e51..281540321 100644 --- a/src/dotty/tools/dotc/util/Positions.scala +++ b/src/dotty/tools/dotc/util/Positions.scala @@ -1,5 +1,6 @@ package dotty.tools.dotc package util +import language.implicitConversions /** Position format in little endian: * Start: unsigned 26 Bits (works for source files up to 64M) @@ -149,8 +150,8 @@ object Positions { } /** An index coordinate */ - def indexCoord(n: Int) = new Coord(n + 1) - def positionCoord(pos: Position) = new Coord(-(pos.point + 1)) + implicit def indexCoord(n: Int): Coord = new Coord(n + 1) + implicit def positionCoord(pos: Position): Coord = new Coord(-(pos.point + 1)) /** A sentinel for a missing coordinate */ val NoCoord = new Coord(0) |