diff options
Diffstat (limited to 'src/dotty/tools/dotc/typer/Namer.scala')
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 301 |
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 |