aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-06-06 19:20:41 +0200
committerMartin Odersky <odersky@gmail.com>2013-06-06 19:20:41 +0200
commit1571ec5f39cacac6433cce0a140ebfb18e2ac314 (patch)
treebb27d85d7ef2e07a06805bc443795c56e9e1f1f6 /src/dotty/tools
parent5651846489834ed69cbb2dab88bc628cf6234dc9 (diff)
downloaddotty-1571ec5f39cacac6433cce0a140ebfb18e2ac314.tar.gz
dotty-1571ec5f39cacac6433cce0a140ebfb18e2ac314.tar.bz2
dotty-1571ec5f39cacac6433cce0a140ebfb18e2ac314.zip
Namer redesign.
A new design that relies on DefDef local maps, instead of global maps before.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala2
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala3
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala250
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala120
-rw-r--r--src/dotty/tools/dotc/util/Positions.scala5
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)