aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Namer.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/typer/Namer.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala301
1 files changed, 111 insertions, 190 deletions
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 45f788e15..d5b63a703 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -6,16 +6,20 @@ import core._
import ast._
import Trees._, Constants._, StdNames._, Scopes._
import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._
+import ast.desugar, ast.desugar._
import util.Positions._
import util.SourcePosition
import collection.mutable
import language.implicitConversions
-trait NamerContextOps { ctx: Context =>
+trait NamerContextOps { this: Context =>
- def enterSym(sym: Symbol) = ctx.owner match {
- case cls: ClassSymbol => cls.enter(sym)
- case _ => this.scope.asInstanceOf[MutableScope].enter(sym)
+ def enter(sym: Symbol): Symbol = {
+ ctx.owner match {
+ case cls: ClassSymbol => cls.enter(sym)
+ case _ => this.scope.asInstanceOf[MutableScope].enter(sym)
+ }
+ sym
}
}
@@ -76,7 +80,7 @@ abstract class Namer { typer: Typer =>
* during phase typer.
*/
- val expandedTree = new mutable.WeakHashMap[Tree, Tree]
+ val expandedTree = new mutable.WeakHashMap[MemberDef, Tree]
val untypedTreeOfSym = mutable.Map[Symbol, Tree]()
@@ -113,201 +117,90 @@ abstract class Namer { typer: Typer =>
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, privateWithin, original.pos)
- untypedTreeOfSym(sym) = tree
- sym
- }
- tree match {
+ def createSymbol(tree: Tree)(implicit ctx: Context): Symbol = {
+ val sym = tree match {
+ case tree: ClassDef =>
+ ctx.enter(ctx.newClassSymbol(
+ ctx.owner, tree.name, tree.mods.flags, new Completer,
+ privateWithinClass(tree.mods), tree.pos, ctx.source.file))
case tree: MemberDef =>
- val sym = createSym(tree.name, tree.mods.flags, privateWithinClass(tree.mods))
- ctx.enterSym(sym)
- sym
+ ctx.enter(ctx.newSymbol(
+ ctx.owner, tree.name, tree.mods.flags, new Completer,
+ privateWithinClass(tree.mods), tree.pos))
case imp: Import =>
- createSym(nme.IMPORT, Synthetic, NoSymbol)
+ ctx.newSymbol(
+ ctx.owner, nme.IMPORT, Synthetic, new Completer, NoSymbol, tree.pos)
case _ =>
NoSymbol
}
+ if (sym.exists) untypedTreeOfSym(sym) = tree
+ sym
}
- val synthetic = Modifiers(Synthetic)
-
- def expansion(tree: Tree)(implicit ctx: Context): Tree = {
-
- def classTypeRef(cdef: ClassDef) = {
- val tycon = Ident(cdef.name)
- if (cdef.tparams.isEmpty) tycon else AppliedTypeTree(tycon, cdef.tparams map refOfDef)
- }
+ def expansion(defn: MemberDef)(implicit ctx: Context): Tree = {
+ val expanded = desugar.memberDef(defn)
+ if (expanded ne defn) expandedTree(defn) = expanded
+ expanded
+ }
- def creator(cdef: ClassDef) =
- New(classTypeRef(cdef), cdef.impl.constr.vparamss.nestedMap(refOfDef))
+ 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
+ ctx
+ case _ =>
+ ctx
+ }
- def methTypeParams(cdef: ClassDef) =
- 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 enterSyms(stats: List[Tree])(implicit ctx: Context): Context = {
- def methParamss(cdef: ClassDef) =
- 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 traverse(stats: List[Tree])(implicit ctx: Context): Context = stats match {
+ case stat :: stats1 =>
+ traverse(stats)(enterSym(stat))
+ case nil =>
+ ctx
+ }
- def expandCaseClass(cdef: ClassDef): Tree = {
- val ClassDef(mods, cname, tparams, impl @ Template(constr, parents, self, stats)) = cdef
- val constr1 =
- if (constr.vparamss.nonEmpty) constr
- else {
- ctx.error("case class needs to have at least one parameter list", cdef.pos)
- constr.derivedDefDef(constr.mods, constr.name, constr.tparams, ListOfNil, constr.tpt, constr.rhs)
- }
- val caseParams = constr1.vparamss.head
- val caseParamsArray = caseParams.toArray
- def syntheticProperty(name: TermName, rhs: Tree) = DefDef(synthetic, name, Nil, Nil, EmptyTree, rhs)
- val isDefinedMeth = syntheticProperty(nme.isDefined, Literal(Constant(true)))
- val productArityMeth = syntheticProperty(nme.productArity, Literal(Constant(caseParamsArray.length)))
- val productElemMeths = for (i <- 0 until caseParamsArray.length) yield
- syntheticProperty(("_" + (i + 1)).toTermName, Select(This(EmptyTypeName), caseParamsArray(i).name))
- val (copyMeths, applyMeths) =
- if (mods is Abstract) (Nil, Nil)
- else {
- val copyFirstParams = caseParams.map(vparam =>
- ValDef(Modifiers(TermParam), vparam.name, vparam.tpt, refOfDef(vparam)).withPos(vparam.pos))
- val copyRestParamss = constr1.vparamss.tail.nestedMap(vparam =>
- ValDef(Modifiers(TermParam), vparam.name, vparam.tpt, EmptyTree).withPos(vparam.pos))
- val applyParamss = constr1.vparamss.nestedMap(vparam =>
- 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))
- }
- 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))
+ def mergeCompanionDefs() = {
+ val caseClassDef = mutable.Map[TypeName, ClassDef]()
+ for (cdef @ ClassDef(mods, name, _) <- stats)
+ if (mods is Case) caseClassDef(name) = cdef
+ for (mdef @ ModuleDef(_, name, _) <- stats)
+ caseClassDef get name.toTypeName match {
+ case Some(cdef) =>
+ val Thicket((mcls @ ClassDef(_, _, impl)) :: mrest) = expandedTree(mdef)
+ val Thicket(cls :: (companion: ClassDef) :: crest) = expandedTree(cdef)
+ val mcls1 = mcls.derivedClassDef(mcls.mods, mcls.name,
+ impl.derivedTemplate(impl.constr, impl.parents, impl.self,
+ companion.impl.body ++ impl.body))
+ expandedTree(mdef) = Thicket(mcls1 :: mrest)
+ expandedTree(cdef) = Thicket(cls :: crest)
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 =
- templ.derivedTemplate(templ.constr, templ.parents, templ.self, templ.body ++ stats)
-
- def addToClass(cdef: ClassDef, stats: List[Tree]): ClassDef =
- cdef.derivedClassDef(cdef.mods, cdef.name, cdef.tparams, addToTemplate(cdef.impl, stats))
-
- def addToModule(mdef: ModuleDef, stats: List[Tree]): ModuleDef =
- mdef.derivedModuleDef(mdef.mods, mdef.name, addToTemplate(mdef.impl, stats))
-
- def implicitWrapper(cdef: ClassDef) =
- DefDef(Modifiers(Synthetic | Implicit), cdef.name.toTermName,
- methTypeParams(cdef), methParamss(cdef), EmptyTree, creator(cdef))
-
- val tree1 = tree match {
- case ValDef(mods, name, tpt, rhs) =>
- if (!ctx.owner.isClass || (mods is Private)) tree
- else {
- val lname = name.toLocalName
- val field = tree.derivedValDef(mods, lname, tpt, rhs)
- val getter = tree.derivedDefDef(mods, name, Nil, Nil, tpt, Ident(lname))
- if (!(mods is Mutable)) Thicket(field, getter)
- else {
- val setterParam = makeSyntheticParameter(tpt = TypeTree(field))
- val setter = tree.derivedDefDef(
- mods, name.getterToSetter, Nil, (setterParam :: Nil) :: Nil, EmptyTree, refOfDef(setterParam))
- 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 {
- expandedTree get mdef match {
- case Some(mdef1: ModuleDef) => mdef
- case _ => mdef
- }
- }
- case cdef: ClassDef =>
- 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(cdef2 :: implicitWrapper(cdef) :: Nil)
- }
- else cdef2
- case _ =>
- tree
- }
- if (tree1 ne tree) expandedTree(tree) = tree1
- tree1
- }
- 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)))
- case stat :: rest =>
- for (expanded <- expansion(stat).toList) createSymbol(expanded, stat)
- enterSyms(rest)
- case Nil =>
- ctx
+ val result = traverse(stats)
+ mergeCompanionDefs()
+ result
}
- 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(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)
+ val symToComplete = denot.symbol
+ val original = untypedTreeOfSym(symToComplete)
- def inheritedResultType(paramFn: Type => Type): Type = {
+ def inheritedResultType(paramFn: Type => Type)(implicit ctx: Context): Type = {
lazy val schema = paramFn(WildcardType)
- val site = sym.owner.symTypeRef
- ((NoType: Type) /: sym.owner.info.baseClasses.tail) { (tp, cls) =>
+ val site = symToComplete.owner.symTypeRef
+ ((NoType: Type) /: symToComplete.owner.info.baseClasses.tail) { (tp, cls) =>
val itpe = cls.info
- .nonPrivateDecl(sym.name)
+ .nonPrivateDecl(symToComplete.name)
.matchingDenotation(site, schema)
.asSeenFrom(site)
.info.finalResultType
@@ -321,7 +214,7 @@ abstract class Namer { typer: Typer =>
tree1
}
- def valOrDefDefTypeSig[UT <: untpd.ValOrDefDef, T <: tpd.ValOrDefDef]
+ def valOrDefDefSig[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
@@ -338,7 +231,7 @@ abstract class Namer { typer: Typer =>
for (param <- params) aheadDef(param, completer)
}
- def defDefTypeSig(defn: DefDef)(implicit ctx: Context) = {
+ def defDefSig(defn: DefDef)(implicit ctx: Context) = {
val DefDef(_, _, tparams, vparamss, _, _) = defn
completeParams(tparams, completeTypeDef)
for (vparams <- vparamss) completeParams(vparams, completeValDef)
@@ -353,33 +246,61 @@ abstract class Namer { typer: Typer =>
else if (vparamss.isEmpty) ExprType(monotpe)
else monotpe
}
- valOrDefDefTypeSig(defn, completeDefDef, wrapMethType)
+ valOrDefDefSig(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 typeDefSig(defn: TypeDef)(implicit ctx: Context): Type = {
+ val lctx = localContext
+ completeParams(defn.tparams, completeTypeDef)(lctx)
+ val TypeDef(_, _, _, rhs) = aheadDef(defn, completeTypeDef)(lctx)
+ rhs.tpe // !!! do something about parameters!
}
+ def classDefSig(defn: ClassDef)(implicit ctx: Context): Type = {
+
+ def parentType(constr: untpd.Tree): Type = {
+ val Trees.Select(Trees.New(tpt), _) = TreeInfo.methPart(constr)
+ val ptype = typedType(tpt).tpe
+ if (ptype.uninstantiatedTypeParams.isEmpty) ptype else typedExpr(constr).tpe
+ }
+
+ def enterSelfSym(name: TermName, tpe: Type): Unit =
+ ctx.enter(ctx.newSymbol(ctx.owner, name, Synthetic, tpe, coord = symToComplete.coord))
+
+ val ClassDef(_, _, impl @ Template(constr, parents, self, body)) = defn
+
+ val decls = newScope
+ val (params, rest) = body span {
+ case td: TypeDef => td.mods is ParamOrAccessor
+ case _ => false
+ }
+ enterSyms(params)
+ val parentTypes = parents map parentType
+ val parentRefs = ctx.normalizeToRefs(parentTypes, symToComplete.asClass, decls)
+ val selfTypeOpt = if (self.tpt.isEmpty) NoType else typedType(self.tpt).tpe
+ if (self.name != nme.WILDCARD)
+ enterSelfSym(self.name, selfTypeOpt orElse symToComplete.typeConstructor)
+ enterSyms(rest)
+ ClassInfo(denot.owner.thisType, symToComplete.asClass, parentRefs, decls, selfTypeOpt)
+ }
+
+ def localContext = ctx.fresh.withOwner(symToComplete)
+
def typeSig(defn: Tree): Type = defn match {
case defn: ValDef =>
- valOrDefDefTypeSig(defn, completeValDef, identity)(ctx.fresh.withOwner(sym))
+ valOrDefDefSig(defn, completeValDef, identity)(localContext)
case defn: DefDef =>
- defDefTypeSig(defn)(localContext(sym))
+ defDefSig(defn)(localContext.withNewScope)
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!
+ typeDefSig(defn)(localContext.withNewScope)
case defn: ClassDef =>
- classDefTypeSig(defn)(ctx.fresh.withOwner(sym))
+ classDefSig(defn)(localContext)
case imp: Import =>
- val expr1 = typedDefn(imp.expr, sym)
+ val expr1 = typedDefn(imp.expr, symToComplete)
ImportType(SharedTree(expr1))
}
- sym.info = typeSig(original)
+ symToComplete.info = typeSig(original)
}
}
} \ No newline at end of file