aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Namer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-06-04 18:00:37 +0200
committerMartin Odersky <odersky@gmail.com>2013-06-04 18:00:37 +0200
commitb28c9ef75e274bdc54e9502e56c95b505495de5b (patch)
tree84b350bffb77d521d7c8393096b43deca78f5e5f /src/dotty/tools/dotc/typer/Namer.scala
parent4fc1d8501a3937547e05f14aa4f4423a2c0d6a1d (diff)
downloaddotty-b28c9ef75e274bdc54e9502e56c95b505495de5b.tar.gz
dotty-b28c9ef75e274bdc54e9502e56c95b505495de5b.tar.bz2
dotty-b28c9ef75e274bdc54e9502e56c95b505495de5b.zip
Refactoring: breaking out desugaring into its own object.
Also, changing the maps in Namer. More commenting needs to be done. Pushing now to get off this machine and back to the new one, which just came back form repair.
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