aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-06-03 11:33:53 +0200
committerMartin Odersky <odersky@gmail.com>2013-06-03 11:33:53 +0200
commit339809ed82e14699681a5a7765c87133cd681ec0 (patch)
tree283b653e9260d3feb01e19b955033de74bc53790 /src/dotty/tools
parent17d0e7008f62882c10193ea0db09c9b90736c320 (diff)
downloaddotty-339809ed82e14699681a5a7765c87133cd681ec0.tar.gz
dotty-339809ed82e14699681a5a7765c87133cd681ec0.tar.bz2
dotty-339809ed82e14699681a5a7765c87133cd681ec0.zip
More solid design of Namer with some Typer bits added.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala17
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala17
-rw-r--r--src/dotty/tools/dotc/ast/UntypedTrees.scala58
-rw-r--r--src/dotty/tools/dotc/core/Decorators.scala32
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala11
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala5
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala10
-rw-r--r--src/dotty/tools/dotc/core/Types.scala37
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala10
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala257
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala87
11 files changed, 454 insertions, 87 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
new file mode 100644
index 000000000..1fc62f7ce
--- /dev/null
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -0,0 +1,17 @@
+package dotty.tools
+package dotc
+package ast
+
+import core._
+import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
+import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
+import TreeInfo._
+import Decorators._
+import language.higherKinds
+import collection.mutable.ListBuffer
+
+trait Desugar { this: untpd.type =>
+
+
+
+} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index 6dfaa9c7b..7e1e70d57 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -313,6 +313,12 @@ object Trees {
override def envelope: Position = mods.pos union pos union initialPos
}
+ /** A ValDef or DefDef tree */
+ trait ValOrDefDef[T >: Untyped] extends ModDefTree[T] {
+ def tpt: Tree[T]
+ def rhs: Tree[T]
+ }
+
// ----------- Tree case classes ------------------------------------
/** name */
@@ -550,14 +556,14 @@ object Trees {
/** mods val name: tpt = rhs */
case class ValDef[T >: Untyped](mods: Modifiers[T], name: TermName, tpt: Tree[T], rhs: Tree[T])
- extends ModDefTree[T] {
+ extends ValOrDefDef[T] {
type ThisTree[T >: Untyped] = ValDef[T]
def withName(name: Name) = this.derivedValDef(mods, name.toTermName, tpt, rhs)
}
/** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */
case class DefDef[T >: Untyped](mods: Modifiers[T], name: TermName, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])
- extends ModDefTree[T] {
+ extends ValOrDefDef[T] {
type ThisTree[T >: Untyped] = DefDef[T]
def withName(name: Name) = this.derivedDefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs)
}
@@ -650,9 +656,13 @@ object Trees {
}
object Thicket {
- def apply[T >: Untyped](): Tree[T] = emptyTree()
+ def apply[T >: Untyped](): Thicket[T] = emptyTree()
def apply[T >: Untyped](x1: Tree[T], x2: Tree[T]): Thicket[T] = Thicket(List(x1, x2))
def apply[T >: Untyped](x1: Tree[T], x2: Tree[T], x3: Tree[T]): Thicket[T] = Thicket(List(x1, x2, x3))
+ def make[T >: Untyped](xs: List[Tree[T]]): Tree[T] = flatten(xs) match {
+ case x :: Nil => x
+ case _ => apply(xs)
+ }
}
// ----- Auxiliary creation methods ------------------
@@ -678,6 +688,7 @@ object Trees {
type RefTree = Trees.RefTree[T]
type DefTree = Trees.DefTree[T]
type ModDefTree = Trees.ModDefTree[T]
+ type ValOrDefDef = Trees.ValOrDefDef[T]
type Ident = Trees.Ident[T]
type Select = Trees.Select[T]
diff --git a/src/dotty/tools/dotc/ast/UntypedTrees.scala b/src/dotty/tools/dotc/ast/UntypedTrees.scala
index 7e3c906b2..befb5e85c 100644
--- a/src/dotty/tools/dotc/ast/UntypedTrees.scala
+++ b/src/dotty/tools/dotc/ast/UntypedTrees.scala
@@ -323,8 +323,19 @@ object untpd extends Trees.Instance[Untyped] {
If(cond, thenp, unitLiteral)
case Match(EmptyTree, cases) =>
makeCaseClosure(cases)
- case _: DefDef | _: ClassDef =>
- desugarContextBounds(tree)
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ val (tparams1, vparamss1) =
+ desugarContextBounds(tparams, vparamss, ofClass = false)
+ tree.derivedDefDef(mods, name, tparams1, vparamss1, tpt, rhs)
+ case ClassDef(
+ mods, name, tparams, impl @ Template(constr, parents, self, body)) =>
+ val (tparams1, vparamss1) =
+ desugarContextBounds(tparams, constr.vparamss, ofClass = true)
+ val constr1 = constr.derivedDefDef(
+ constr.mods, constr.name, constr.tparams, vparamss1, constr.tpt, constr.rhs)
+
+ val templ1 = impl.derivedTemplate(constr1, parents, self, body)
+ tree.derivedClassDef(mods, name, tparams1, templ1)
case ModuleDef(mods, name, tmpl @ Template(constr, parents, self, body)) =>
// <module> val name: name$ = New(name$)
// <module> final class name$ extends parents { self: name.type => body }
@@ -431,20 +442,35 @@ object untpd extends Trees.Instance[Untyped] {
}
}
- def desugarContextBounds(tree: Tree): Tree = tree match {
- case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- val (tparams1, vparamss1) =
- desugarContextBounds(tparams, vparamss, ofClass = false)
- tree.derivedDefDef(mods, name, tparams1, vparamss1, tpt, rhs)
- case ClassDef(
- mods, name, tparams, templ @ Template(constr, parents, self, body)) =>
- val (tparams1, vparamss1) =
- desugarContextBounds(tparams, constr.vparamss, ofClass = true)
- val constr1 = constr.derivedDefDef(
- constr.mods, constr.name, constr.tparams, vparamss1, constr.tpt, constr.rhs)
- val templ1 = templ.derivedTemplate(constr1, parents, self, body)
- tree.derivedClassDef(mods, name, tparams1, templ1)
- case _ => tree
+ val NotInTypeAccessorFlags = Param | Private | Local
+
+ def desugarClassDef(cdef: ClassDef)(implicit ctx: Context): ClassDef = {
+ val ClassDef(
+ mods, name, tparams, impl @ Template(constr, parents, self, body)) = cdef
+
+ // desugar context bounds
+ val (tparamAccs, vparamAccss) =
+ desugarContextBounds(tparams, constr.vparamss, ofClass = true)
+
+ val tparams1 = tparams.map(tparam => tparam.derivedTypeDef(
+ Modifiers(Param), tparam.name, tparam.tparams, tparam.rhs))
+
+ // ensure parameter list is non-empty
+ val vparamss1 =
+ if (vparamAccss.isEmpty) {
+ if (mods is Case)
+ ctx.error("case class needs to have at least one parameter list", cdef.pos)
+ ListOfNil
+ }
+ else
+ vparamAccss.nestedMap(vparam => vparam.derivedValDef(
+ Modifiers(Param), vparam.name, vparam.tpt, vparam.rhs))
+
+ val constr1 = constr.derivedDefDef(
+ constr.mods, constr.name, constr.tparams, vparamss1, constr.tpt, constr.rhs)
+
+ cdef.derivedClassDef(mods, name, tparams1,
+ impl.derivedTemplate(constr1, parents, self, tparamAccs ::: vparamAccss.flatten ::: body))
}
/** Expand to:
diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala
index 094aa7b4a..476b97ec2 100644
--- a/src/dotty/tools/dotc/core/Decorators.scala
+++ b/src/dotty/tools/dotc/core/Decorators.scala
@@ -4,6 +4,8 @@ package core
import annotation.tailrec
import Symbols._
import Contexts._, Names._, Phases._, printing.Texts._, printing.Printer
+import util.Positions.Position, util.SourcePosition
+import collection.mutable.ListBuffer
/** This object provides useful implicit decorators for types defined elsewhere */
object Decorators {
@@ -35,6 +37,33 @@ object Decorators {
*/
implicit class ListDecorator[T](val xs: List[T]) extends AnyVal {
+ @inline final def mapconserve[U](f: T => U): List[U] = {
+ @tailrec
+ def loop(mapped: ListBuffer[U], unchanged: List[U], pending: List[T]): List[U] =
+ if (pending.isEmpty) {
+ if (mapped eq null) unchanged
+ else mapped.prependToList(unchanged)
+ } else {
+ val head0 = pending.head
+ val head1 = f(head0)
+
+ if (head1.asInstanceOf[AnyRef] eq head0.asInstanceOf[AnyRef])
+ loop(mapped, unchanged, pending.tail)
+ else {
+ val b = if (mapped eq null) new ListBuffer[U] else mapped
+ var xc = unchanged
+ while (xc ne pending) {
+ b += xc.head
+ xc = xc.tail
+ }
+ b += head1
+ val tail0 = pending.tail
+ loop(b, tail0.asInstanceOf[List[U]], tail0)
+ }
+ }
+ loop(null, xs.asInstanceOf[List[U]], xs)
+ }
+
/** Like `xs filter p` but returns list `xs` itself - instead of a copy -
* if `p` is true for all elements and `xs` is not longer
* than `MaxFilterRecursions`.
@@ -86,5 +115,8 @@ object Decorators {
def containsPhase(phase: Phase) =
names exists (phase.name.startsWith)
}
+
+ implicit def sourcePos(pos: Position)(implicit ctx: Context): SourcePosition =
+ ctx.source.atPos(pos)
}
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 97b25be00..9c89a28cf 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -197,6 +197,17 @@ object Denotations {
def requiredMethod(name: PreName)(implicit ctx: Context): TermSymbol =
info.member(name.toTermName).requiredSymbol(_ is Method).asTerm
+ /** The denotation that has a type matching `targetType` when seen
+ * as a member of type `site`, `NoDenotation` if none exists.
+ */
+ def matchingDenotation(site: Type, targetType: Type)(implicit ctx: Context): SingleDenotation =
+ if (isOverloaded)
+ atSignature(targetType.signature).matchingDenotation(site, targetType)
+ else if (exists && !(site.memberInfo(symbol) matches targetType))
+ NoDenotation
+ else
+ this.asInstanceOf[SingleDenotation]
+
/** Form a denotation by conjoining with denotation `that` */
def & (that: Denotation)(implicit ctx: Context): Denotation =
if (this eq that) this
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index f22c2a0f2..1b918cfcd 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -63,6 +63,8 @@ object Flags {
*/
def is(flags: FlagConjunction, butNot: FlagSet): Boolean = is(flags) && !is(butNot)
+ def isEmpty = (bits & ~KINDFLAGS) == 0
+
/** Is this flag set a subset of that one? */
def <= (that: FlagSet) = (bits & that.bits) == bits
@@ -434,6 +436,9 @@ object Flags {
/** Labeled private[this] */
final val PrivateLocal = allOf(Private, Local)
+ /** A private parameter accessor */
+ final val PrivateLocalParamAccessor = allOf(Private, Local, ParamAccessor)
+
/** A local parameter */
final val ParamAndLocal = allOf(Param, Local)
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 56b168102..e1550d529 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -533,17 +533,11 @@ object SymDenotations {
* inClass <-- find denot.symbol class C { <-- symbol is here
*
* site: Subtype of both inClass and C
- *
*/
final def matchingSymbol(inClass: Symbol, site: Type)(implicit ctx: Context): Symbol = {
var denot = inClass.info.nonPrivateDecl(name)
- if (denot.isTerm) { // types of the same name always match
- val targetType = site.memberInfo(symbol)
- if (denot.isOverloaded)
- denot = denot.atSignature(targetType.signature) // seems we need two kinds of signatures here
- if (!(site.memberInfo(denot.symbol) matches targetType))
- denot = NoDenotation
- }
+ if (denot.isTerm) // types of the same name always match
+ denot = denot.matchingDenotation(site, site.memberInfo(symbol))
denot.symbol
}
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index c0e338ef1..c78b876b4 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -411,6 +411,22 @@ object Types {
ctx.typeComparer.matchesType(
this, that, alwaysMatchSimple = !ctx.phase.erasedTypes)
+ /** The non-private symbol with given name in the given class that matches this type.
+ * @param inClass The class containing the symbol's definition
+ * @param name The name of the symbol we are looking for
+ * @param site The base type from which member types are computed
+ */
+ def matchingTermSymbol(inClass: Symbol, name: Name, site: Type)(implicit ctx: Context): Symbol = {
+ var denot = inClass.info.nonPrivateDecl(name)
+ if (denot.isTerm) { // types of the same name always match
+ if (denot.isOverloaded)
+ denot = denot.atSignature(this.signature) // seems we need two kinds of signatures here
+ if (!(site.memberInfo(denot.symbol) matches this))
+ denot = NoDenotation
+ }
+ denot.symbol
+ }
+
/** The basetype of this type with given class symbol */
final def baseType(base: Symbol)(implicit ctx: Context): Type = base.denot match {
case classd: ClassDenotation => classd.baseTypeOf(this)
@@ -505,6 +521,15 @@ object Types {
/** The resultType of a PolyType, MethodType, or ExprType, the type itself for others */
def resultType: Type = this
+ /** The final result type of a PolyType, MethodType, or ExprType, after skipping
+ * all parameter sections, the type itself for all others.
+ */
+ def finalResultType: Type = resultType match {
+ case mt: MethodType => mt.resultType.finalResultType
+ case pt: PolyType => pt.resultType.finalResultType
+ case _ => resultType
+ }
+
/** This type seen as a TypeBounds */
final def bounds(implicit ctx: Context): TypeBounds = this match {
case tp: TypeBounds => tp
@@ -1369,13 +1394,15 @@ object Types {
}
object PolyType {
- def fromSymbols(tparams: List[Symbol], resultType: Type)(implicit ctx: Context) = {
- def transform(pt: PolyType, tp: Type) =
- tp.subst(tparams, (0 until tparams.length).toList map (PolyParam(pt, _)))
- apply(tparams map (_.name.asTypeName))(
+ def fromSymbols(tparams: List[Symbol], resultType: Type)(implicit ctx: Context) =
+ if (tparams.isEmpty) resultType
+ else {
+ def transform(pt: PolyType, tp: Type) =
+ tp.subst(tparams, (0 until tparams.length).toList map (PolyParam(pt, _)))
+ apply(tparams map (_.name.asTypeName))(
pt => tparams map (tparam => transform(pt, tparam.info).bounds),
pt => transform(pt, resultType))
- }
+ }
}
abstract class BoundType extends UncachedProxyType with ValueType {
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 20f0f1df1..5c585cacb 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -1455,18 +1455,18 @@ object Parsers {
val modStart = in.offset
var mods = annotsAsMods()
if (owner.isTypeName) {
- mods = modifiers(start = mods)
+ mods = modifiers(start = mods) | ParamAccessor
mods =
atPos(modStart, in.offset) {
if (in.token == VAL) {
in.nextToken()
- mods | Param
+ mods
} else if (in.token == VAR) {
in.nextToken()
- addFlag(mods | Param, Mutable)
+ addFlag(mods, Mutable)
} else {
- if (mods.hasFlags) syntaxError("`val' or `var' expected")
- if (firstClauseOfCaseClass) mods | Param else mods | Param | PrivateLocal
+ if ((mods.flags &~ ParamAccessor).isEmpty) syntaxError("`val' or `var' expected")
+ if (firstClauseOfCaseClass) mods else mods | PrivateLocal
}
}
}
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 84a82044b..e0a65bb52 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -19,15 +19,68 @@ trait NamerContextOps { ctx: Context =>
}
}
-class Namer(val typer: Typer) {
+abstract class Namer { typer: Typer =>
import untpd._
- val expandedTrees = new mutable.WeakHashMap[Tree, Tree]()
- val symOfTree = mutable.Map[Tree, Symbol]()
+ /** 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.
+ */
- implicit def sourcePos(pos: Position)(implicit ctx: Context): SourcePosition =
- ctx.source.atPos(pos)
+ val expandedTree = new mutable.WeakHashMap[Tree, Tree]
+
+ val untypedTreeOfSym = mutable.Map[Symbol, Tree]()
+
+ val typedTreeOfSym = new mutable.HashMap[Symbol, tpd.Tree]
implicit def posToCoord(pos: Position): Coord = positionCoord(pos)
@@ -50,10 +103,20 @@ class Namer(val typer: Typer) {
}
}
+ def symOfTree(tree: Trees.NameTree[_], treeMap: collection.Map[Symbol, Trees.Tree[_]])(implicit ctx: Context): Symbol = {
+ var e = ctx.scope.lookupEntry(tree.name)
+ while (e != null && treeMap(e.sym) != tree)
+ e = ctx.scope.lookupNextEntry(e)
+ if (e == null) NoSymbol else e.sym
+ }
+
+ def symOfTypedTree(tree: tpd.NameTree)(implicit ctx: Context) = symOfTree(tree, typedTreeOfSym)(ctx)
+ def symOfUntypedTree (tree: NameTree)(implicit ctx: Context) = symOfTree(tree, untypedTreeOfSym)(ctx)
+
def createSymbol(tree: Tree, original: Tree)(implicit ctx: Context): Symbol = {
def createSym(name: Name, flags: FlagSet, privateWithin: Symbol) = {
- val sym = ctx.newSymbol(ctx.owner, name, flags, new Completer(original), privateWithin, original.pos)
- symOfTree(original) = sym
+ val sym = ctx.newSymbol(ctx.owner, name, flags, new Completer, privateWithin, original.pos)
+ untypedTreeOfSym(sym) = tree
sym
}
tree match {
@@ -81,14 +144,14 @@ class Namer(val typer: Typer) {
New(classTypeRef(cdef), cdef.impl.constr.vparamss.nestedMap(refOfDef))
def methTypeParams(cdef: ClassDef) =
- for (tparam <- cdef.tparams) yield
- tparam.derivedTypeDef(Modifiers(TypeParam), tparam.name, tparam.tparams, tparam.rhs)
+ for (tparam <- cdef.tparams) yield // don't use derivedTypeDef; parameters have to be unique
+ TypeDef(Modifiers(TypeParam), tparam.name, tparam.tparams, tparam.rhs).withPos(tparam.pos)
def methParamss(cdef: ClassDef) =
- cdef.impl.constr.vparamss.nestedMap(vparam =>
- vparam.derivedValDef(Modifiers(TermParam), vparam.name, vparam.tpt, vparam.rhs))
+ cdef.impl.constr.vparamss.nestedMap(vparam => // don't use derivedValDef; parameters have to be unique
+ ValDef(Modifiers(TermParam), vparam.name, vparam.tpt, vparam.rhs).withPos(vparam.pos))
- def expandCaseClass(cdef: ClassDef): ClassDef = {
+ def expandCaseClass(cdef: ClassDef): Tree = {
val ClassDef(mods, cname, tparams, impl @ Template(constr, parents, self, stats)) = cdef
val constr1 =
if (constr.vparamss.nonEmpty) constr
@@ -107,23 +170,52 @@ class Namer(val typer: Typer) {
if (mods is Abstract) (Nil, Nil)
else {
val copyFirstParams = caseParams.map(vparam =>
- vparam.derivedValDef(Modifiers(TermParam), vparam.name, vparam.tpt, refOfDef(vparam)))
+ ValDef(Modifiers(TermParam), vparam.name, vparam.tpt, refOfDef(vparam)).withPos(vparam.pos))
val copyRestParamss = constr1.vparamss.tail.nestedMap(vparam =>
- vparam.derivedValDef(Modifiers(TermParam), vparam.name, vparam.tpt, EmptyTree))
+ ValDef(Modifiers(TermParam), vparam.name, vparam.tpt, EmptyTree).withPos(vparam.pos))
val applyParamss = constr1.vparamss.nestedMap(vparam =>
- vparam.derivedValDef(Modifiers(TermParam), vparam.name, vparam.tpt, vparam.rhs))
+ ValDef(Modifiers(TermParam), vparam.name, vparam.tpt, vparam.rhs).withPos(vparam.pos))
val copyMeth =
DefDef(synthetic, nme.copy, methTypeParams(cdef), copyFirstParams :: copyRestParamss, EmptyTree, creator(cdef))
val applyMeth =
DefDef(synthetic, nme.apply, methTypeParams(cdef), methParamss(cdef), EmptyTree, creator(cdef))
(copyMeth :: Nil, applyMeth :: Nil)
- }
+ }
val unapplyMeth = {
val unapplyParam = makeSyntheticParameter(tpt = classTypeRef(cdef))
DefDef(synthetic, nme.unapply, methTypeParams(cdef), (unapplyParam :: Nil) :: Nil, EmptyTree, This(EmptyTypeName))
}
- updateCompanion(cname.toTermName, applyMeths ::: unapplyMeth :: Nil)
- addToClass(cdef, copyMeths ::: isDefinedMeth :: productArityMeth :: productElemMeths.toList)
+ val classMeths = copyMeths ::: isDefinedMeth :: productArityMeth :: productElemMeths.toList
+ val cls1 = addToClass(cdef, classMeths)
+
+ // update or create companion object:
+ val companionMeths = applyMeths ::: unapplyMeth :: Nil
+ val companionName = cname.toTermName
+ var companionFound = false
+ for (companion @ ModuleDef(_, `companionName`, _) <- enclosingStats) {
+ // Add `companionDefs` to either the expanded or unexpanded version of
+ // the companion object with given `companionName`, and update its expandedTree map
+ // with the result.
+ expandedTree(companion) = expandedTree get companion match {
+ case Some(Thicket(vdef :: (cdef: ClassDef) :: Nil)) =>
+ Thicket(vdef, addToClass(cdef, companionMeths))
+ case none =>
+ addToModule(companion, companionMeths)
+ }
+ companionFound = true
+ }
+ val syntheticCompanions =
+ if (companionFound) Nil
+ else {
+ val parent =
+ if (tparams.nonEmpty) ref(defn.AnyRefAlias.typeConstructor)
+ else (constr1.vparamss :\ classTypeRef(cdef)) ((vparams, restpe) =>
+ Function(vparams map (_.tpt), restpe))
+ ModuleDef(
+ Modifiers(Synthetic), companionName,
+ Template(emptyConstructor, parent :: Nil, EmptyValDef(), companionMeths)) :: Nil
+ }
+ Thicket.make(cls1 :: syntheticCompanions)
}
def addToTemplate(templ: Template, stats: List[Tree]): Template =
@@ -135,16 +227,6 @@ class Namer(val typer: Typer) {
def addToModule(mdef: ModuleDef, stats: List[Tree]): ModuleDef =
mdef.derivedModuleDef(mdef.mods, mdef.name, addToTemplate(mdef.impl, stats))
- def updateCompanion(name: TermName, newDefs: List[Tree]) =
- for (companion @ ModuleDef(_, `name`, _) <- enclosingStats) {
- expandedTrees(companion) = expandedTrees get companion match {
- case Some(Thicket(vdef :: (cdef: ClassDef) :: Nil)) =>
- Thicket(vdef, addToClass(cdef, newDefs))
- case none =>
- addToModule(companion, newDefs)
- }
- }
-
def implicitWrapper(cdef: ClassDef) =
DefDef(Modifiers(Synthetic | Implicit), cdef.name.toTermName,
methTypeParams(cdef), methParamss(cdef), EmptyTree, creator(cdef))
@@ -164,29 +246,36 @@ class Namer(val typer: Typer) {
Thicket(field, getter, setter)
}
}
+ case tdef: TypeDef if tdef.mods is PrivateLocalParamAccessor =>
+ val tparam = tdef.derivedTypeDef(
+ tdef.mods &~ PrivateLocal | ExpandedName, tdef.name.expandedName(ctx.owner), tdef.tparams, tdef.rhs)
+ val alias = tdef.derivedTypeDef(
+ Modifiers(PrivateLocal | Synthetic), tdef.name, Nil, refOfDef(tparam))
+ Thicket(tparam :: alias :: Nil)
case mdef: ModuleDef =>
desugarModuleDef {
- expandedTrees get mdef match {
+ expandedTree get mdef match {
case Some(mdef1: ModuleDef) => mdef
case _ => mdef
}
}
case cdef: ClassDef =>
- val result = if (cdef.mods is Case) expandCaseClass(cdef) else cdef
+ val cdef1: ClassDef = desugarClassDef(cdef)
+ val cdef2 = if (cdef1.mods is Case) expandCaseClass(cdef1) else cdef1
if (cdef.mods is Implicit) {
if (ctx.owner is Package)
ctx.error("implicit classes may not be toplevel", cdef.pos)
- Thicket(result :: implicitWrapper(cdef) :: Nil)
+ Thicket(cdef2 :: implicitWrapper(cdef) :: Nil)
}
- else result
+ else cdef2
case _ =>
tree
}
- if (tree1 ne tree) expandedTrees(tree) = tree1
+ if (tree1 ne tree) expandedTree(tree) = tree1
tree1
}
- def enterSyms(stats: List[Tree])(implicit ctx: Context): Unit = stats match {
+ def enterSyms(stats: List[Tree])(implicit ctx: Context): Context = stats match {
case (imp @ Import(expr, selectors)) :: rest =>
val sym = createSymbol(imp, imp)
enterSyms(rest)(ctx.fresh.withImport(ImportInfo(sym, selectors, ctx.scopeNestingLevel)))
@@ -194,27 +283,103 @@ class Namer(val typer: Typer) {
for (expanded <- expansion(stat).toList) createSymbol(expanded, stat)
enterSyms(rest)
case Nil =>
+ ctx
}
+ def localContext(owner: Symbol)(implicit ctx: Context) =
+ ctx.fresh.withOwner(owner).withScope(newScope)
+ def enterParams(ddef: DefDef)(ctx: Context): Context =
+ (enterSyms(ddef.tparams)(ctx) /: ddef.vparamss) ((ctx, params) => enterSyms(params)(ctx))
- class Completer(tree: Tree)(implicit ctx: Context) extends LazyType {
- def complete(sym: SymDenotation): Unit = {
- for (defn <- expandedTrees.getOrElse(tree, tree).toList if symOfTree(defn) == sym)
- defn match {
- case ValDef(mods, name, tpt, rhs) =>
- val (tpt1, rhs1) =
- if (tpt.isEmpty) {
- val rhs1 = typer.typedExpr(rhs)
- (TypeTree().withType(rhs1.tpe), TypedSplice(rhs1))
- }
- else (typer.typedType(tpt), rhs)
- defn.derivedValDef(mods, name, TypedSplice(tpt1), rhs1)
+ class Completer(implicit ctx: Context) extends LazyType {
+
+ def registerTyped(originals: List[NameTree], trees: List[tpd.Tree]): Unit =
+ for ((original, tree) <- (originals, trees).zipped)
+ typedTreeOfSym(symOfTree(original, untypedTreeOfSym)) = tree
+
+ def complete(denot: SymDenotation): Unit = {
+ val sym = denot.symbol
+ val original = untypedTreeOfSym(sym)
+
+ def inheritedResultType(paramFn: Type => Type): Type = {
+ lazy val schema = paramFn(WildcardType)
+ val site = sym.owner.symTypeRef
+ ((NoType: Type) /: sym.owner.info.baseClasses.tail) { (tp, cls) =>
+ val itpe = cls.info
+ .nonPrivateDecl(sym.name)
+ .matchingDenotation(site, schema)
+ .asSeenFrom(site)
+ .info.finalResultType
+ tp & itpe
+ }
+ }
+
+ def typedDefn(tree: Tree, sym: Symbol)(implicit ctx: Context): tpd.Tree = {
+ val tree1 = typer.typed(tree, sym.symRef)
+ typedTreeOfSym(sym) = tree1
+ tree1
+ }
+
+ def valOrDefDefTypeSig[UT <: untpd.ValOrDefDef, T <: tpd.ValOrDefDef]
+ (defn: UT, op: DefTyper[UT, T], paramFn: Type => Type)(implicit ctx: Context): Type =
+ paramFn {
+ if (!defn.tpt.isEmpty) typer.typed(defn.tpt).tpe
+ else {
+ val inherited = inheritedResultType(paramFn)
+ if (inherited.exists) typer.typed(defn.tpt, inherited).tpe
+ else aheadDef(defn, op).tpt.tpe
+ }
+ }
+ def completeParams[UT <: untpd.NameTree, T <: tpd.Tree]
+ (params: List[UT], completer: DefTyper[UT, T])(implicit ctx: Context): Unit = {
+ enterSyms(params)
+ for (param <- params) aheadDef(param, completer)
+ }
+ def defDefTypeSig(defn: DefDef)(implicit ctx: Context) = {
+ val DefDef(_, _, tparams, vparamss, _, _) = defn
+ completeParams(tparams, completeTypeDef)
+ for (vparams <- vparamss) completeParams(vparams, completeValDef)
+ 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 symOfUntypedTree, restpe)
+ }
+ if (tparams.nonEmpty) PolyType.fromSymbols(tparams map symOfUntypedTree, monotpe)
+ else if (vparamss.isEmpty) ExprType(monotpe)
+ else monotpe
}
+ valOrDefDefTypeSig(defn, completeDefDef, wrapMethType)
+ }
+
+ def classDefTypeSig(defn: ClassDef)(implicit ctx: Context): Type = {
+ val ClassDef(_, _, tparams, impl @ Template(constr, parents, self, body)) = defn
+ val localCtx = ctx.fresh.withOwner(sym)
+ ???
+ }
+ def typeSig(defn: Tree): Type = defn match {
+ case defn: ValDef =>
+ valOrDefDefTypeSig(defn, completeValDef, identity)(ctx.fresh.withOwner(sym))
+ case defn: DefDef =>
+ defDefTypeSig(defn)(localContext(sym))
+ case defn: TypeDef =>
+ val localCtx = localContext(sym)
+ completeParams(defn.tparams, completeTypeDef)(localCtx)
+ val TypeDef(_, _, _, rhs) = aheadDef(defn, completeTypeDef)(localCtx)
+ rhs.tpe // !!! do something about parameters!
+ case defn: ClassDef =>
+ classDefTypeSig(defn)(ctx.fresh.withOwner(sym))
+ case imp: Import =>
+ val expr1 = typedDefn(imp.expr, sym)
+ ImportType(SharedTree(expr1))
}
+
+ sym.info = typeSig(original)
}
}
} \ 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 c9405af86..44cefe5e6 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -14,8 +14,87 @@ import language.implicitConversions
trait TyperContextOps { ctx: Context => }
-class Typer {
- def typed(tree: untpd.Tree, pt: Type)(implicit ctx: Context): tpd.Tree = ???
- def typedExpr(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree = ???
- def typedType(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree = ???
+class Typer extends Namer {
+
+ import tpd._
+
+ def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = ???
+ def typedExpr(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = ???
+ def typedType(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = ???
+
+ type DefTyper[UT <: untpd.NameTree, T <: tpd.Tree] = (UT, NamedType) => Context => T
+
+ def lateDef[UT <: untpd.NameTree, T <: tpd.Tree](defn: UT, op: DefTyper[UT, T])(implicit ctx: Context): T = {
+ val sym = symOfUntypedTree(defn)
+ sym.ensureCompleted()
+ untypedTreeOfSym -= sym
+ typedTreeOfSym remove sym match {
+ case Some(tree) => tree.asInstanceOf[T]
+ case None => op(defn, sym.symRef)(ctx)
+ }
+ }
+
+ def aheadDef[UT <: untpd.NameTree, T <: tpd.Tree](defn: UT, op: DefTyper[UT, T])(implicit ctx: Context): T = {
+ val sym = symOfUntypedTree(defn)
+ val tree1 = op(defn, sym.symRef)(ctx)
+ typedTreeOfSym(sym) = tree1
+ tree1
+ }
+
+ def noDefTyper: DefTyper[untpd.NameTree, Nothing] = { (tdef, pt) => implicit ctx => ??? }
+
+ val completeTypeDef: DefTyper[untpd.TypeDef, TypeDef] = { (tdef, pt) => implicit ctx =>
+ val Trees.TypeDef(mods, name, tparams, rhs) = tdef
+ val mods1 = typedModifiers(mods)
+ val tparams1 = reEnterParams(tparams)
+ val rhs1 = typedType(rhs)
+ tdef.withType(pt).derivedTypeDef(mods1, name, tparams1, rhs1)
+ }
+
+ def typedTypedDef(tdef: untpd.TypeDef)(implicit ctx: Context): TypeDef =
+ lateDef(tdef, completeTypeDef)
+
+ def typedTptRhs(tpt: untpd.Tree, rhs: untpd.Tree)(implicit ctx: Context): (Tree, Tree) = {
+ var tpt1: Tree = EmptyTree
+ var rhs1: Tree = EmptyTree
+ if (tpt.isEmpty) {
+ rhs1 = typedExpr(rhs)
+ tpt1 = tpt.withType(rhs1.tpe)
+ } else {
+ tpt1 = typedType(tpt)
+ rhs1 = typedExpr(rhs, tpt1.tpe)
+ }
+ (tpt1, rhs1)
+ }
+
+ val completeValDef: DefTyper[untpd.ValDef, ValDef] = { (vdef, pt) => implicit ctx: Context =>
+ val Trees.ValDef(mods, name, tpt, rhs) = vdef
+ val mods1 = typedModifiers(mods)
+ val (tpt1, rhs1) = typedTptRhs(tpt, rhs)
+ vdef.withType(tpt1.tpe).derivedValDef(mods1, name, tpt1, rhs1)
+ }
+
+ def reEnterParams[UT <: untpd.NameTree, T <: tpd.Tree](params: List[UT])(implicit ctx: Context): List[T] = {
+ for (param <- params) yield {
+ val sym = symOfUntypedTree(param)
+ ctx.enterSym(sym)
+ lateDef(param, noDefTyper)
+ }
+ }
+
+ val completeDefDef: DefTyper[untpd.DefDef, DefDef] = { (ddef, pt) => implicit ctx: Context =>
+ val Trees.DefDef(mods, name, tparams, vparamss, tpt, rhs) = ddef
+ val mods1 = typedModifiers(mods)
+ val tparams1: List[TypeDef] = reEnterParams(tparams)
+ val vparamss1: List[List[ValDef]] = vparamss.mapconserve(reEnterParams)
+ val (tpt1, rhs1) = typedTptRhs(tpt, rhs)
+ ddef.withType(tpt1.tpe).derivedDefDef(mods1, name, tparams1, vparamss1, tpt1, rhs1)
+ }
+
+ 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 = ???
} \ No newline at end of file