diff options
author | Martin Odersky <odersky@gmail.com> | 2013-06-05 17:27:02 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-06-05 17:27:02 +0200 |
commit | 898fe8a499c97fa62840e2c79755fc729015a442 (patch) | |
tree | 95d0795c01764326bf51f2a0d4c8212b484e5da5 | |
parent | b28c9ef75e274bdc54e9502e56c95b505495de5b (diff) | |
download | dotty-898fe8a499c97fa62840e2c79755fc729015a442.tar.gz dotty-898fe8a499c97fa62840e2c79755fc729015a442.tar.bz2 dotty-898fe8a499c97fa62840e2c79755fc729015a442.zip |
wip - partial redesign of namer/typer
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 239 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 126 |
3 files changed, 187 insertions, 186 deletions
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 6d566cdbd..346cf72f5 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -133,6 +133,11 @@ object Contexts { protected def scope_=(scope: Scope) = _scope = scope def scope: Scope = _scope + /** The current typer */ + private[this] var _typer: Typer = _ + protected def typer_=(typer: Typer) = _typer = typer + def typer: Typer = _typer + /** The currently visible imports */ private[this] var _imports: List[ImportInfo] = _ protected def imports_=(imports: List[ImportInfo]) = _imports = imports @@ -253,10 +258,11 @@ object Contexts { def withPlainPrinter(printer: Context => Printer): this.type = { this.plainPrinter = printer; this } def withRefinedPrinter(printer: Context => Printer): this.type = { this.refinedPrinter = printer; this } def withOwner(owner: Symbol): this.type = { this.owner = owner; this } - def withNewScope: this.type = { this.scope = newScope; this } def withSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this } 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 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/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index d5b63a703..fc8b85f11 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -23,7 +23,15 @@ trait NamerContextOps { this: Context => } } -abstract class Namer { typer: Typer => +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]() +} + +class Namer { typer: Typer => import untpd._ @@ -80,23 +88,15 @@ abstract class Namer { typer: Typer => * during phase typer. */ - val expandedTree = new mutable.WeakHashMap[MemberDef, Tree] - - val untypedTreeOfSym = mutable.Map[Symbol, Tree]() + 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] + lazy val nestedTyper = new mutable.HashMap[Symbol, Typer] - val typedTreeOfSym = new mutable.HashMap[Symbol, tpd.Tree] + val scope = newScope implicit def posToCoord(pos: Position): Coord = positionCoord(pos) - def enclosingStats(implicit ctx: Context): List[Trees.Tree[_ >: Untyped]] = - if (ctx == NoContext) Nil - else ctx.tree match { - case Template(_, _, _, stats) => stats - case Block(stats, _) => stats - case PackageDef(_, stats) => stats - case _ => enclosingStats(ctx.outer) - } - def privateWithinClass(mods: Modifiers)(implicit ctx: Context): Symbol = { val pw = mods.privateWithin if (pw.isEmpty) NoSymbol @@ -107,33 +107,23 @@ abstract class Namer { 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)(implicit ctx: Context): Symbol = { val sym = tree match { case tree: ClassDef => ctx.enter(ctx.newClassSymbol( - ctx.owner, tree.name, tree.mods.flags, new Completer, + ctx.owner, tree.name, tree.mods.flags, new Completer(tree), privateWithinClass(tree.mods), tree.pos, ctx.source.file)) case tree: MemberDef => ctx.enter(ctx.newSymbol( - ctx.owner, tree.name, tree.mods.flags, new Completer, + ctx.owner, tree.name, tree.mods.flags, new Completer(tree), privateWithinClass(tree.mods), tree.pos)) case imp: Import => ctx.newSymbol( - ctx.owner, nme.IMPORT, Synthetic, new Completer, NoSymbol, tree.pos) + ctx.owner, nme.IMPORT, Synthetic, new Completer(tree), NoSymbol, tree.pos) case _ => NoSymbol } - if (sym.exists) untypedTreeOfSym(sym) = tree + if (sym.exists) symOfTree(tree) = sym sym } @@ -186,121 +176,120 @@ abstract class Namer { typer: Typer => result } - 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 { + class Completer(original: Tree)(implicit ctx: Context) extends LazyType { def complete(denot: SymDenotation): Unit = { - val symToComplete = denot.symbol - val original = untypedTreeOfSym(symToComplete) + val sym = denot.symbol + def localContext = ctx.fresh.withOwner(sym) - def inheritedResultType(paramFn: Type => Type)(implicit ctx: Context): Type = { - lazy val schema = paramFn(WildcardType) - val site = symToComplete.owner.symTypeRef - ((NoType: Type) /: symToComplete.owner.info.baseClasses.tail) { (tp, cls) => - val itpe = cls.info - .nonPrivateDecl(symToComplete.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 typeSig(defn: Tree): Type = defn match { + case defn: ValDef => + valOrDefDefSig(defn, sym, identity)(localContext) + case defn: 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) + case imp: Import => + val expr1 = typedAhead(imp.expr) + ImportType(SharedTree(expr1)) } - 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 - else { - val inherited = inheritedResultType(paramFn) - if (inherited.exists) typer.typed(defn.tpt, inherited).tpe - else aheadDef(defn, op).tpt.tpe - } - } + sym.info = typeSig(original) + } + } - 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 typedAhead(tree: Tree, mode: Mode.Value = Mode.Expr, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree = + typedTree.getOrElseUpdate(tree, typer.typed(tree)) - def defDefSig(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 + def valOrDefDefSig(defn: ValOrDefDef, sym: Symbol, paramFn: Type => Type)(implicit ctx: Context): Type = { + val pt = + if (!defn.tpt.isEmpty) WildcardType + else { + lazy val schema = paramFn(WildcardType) + val site = sym.owner.symTypeRef + val inherited = { + ((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 } - valOrDefDefSig(defn, completeDefDef, wrapMethType) - } - - 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! + } + inherited orElse typedAhead(defn.rhs).tpe } + paramFn(typedAhead(defn.tpt, Mode.Type, pt).tpe) + } - def classDefSig(defn: ClassDef)(implicit ctx: Context): Type = { + def completeParams(params: List[MemberDef])(implicit ctx: Context) = { + enterSyms(params) + for (param <- params) typedAhead(param) + } - 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 defDefSig(ddef: DefDef, sym: Symbol)(implicit ctx: Context) = { + val DefDef(_, name, tparams, vparamss, _, _) = ddef + completeParams(tparams) + vparamss foreach completeParams + val isConstructor = name == nme.CONSTRUCTOR + val isSecondaryConstructor = isConstructor && sym != sym.owner.primaryConstructor + def typeParams = + if (isSecondaryConstructor) sym.owner.primaryConstructor.typeParams + else tparams map symOfTree + 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) } + if (tparams.nonEmpty) PolyType.fromSymbols(typeParams, monotpe) + else if (vparamss.isEmpty) ExprType(monotpe) + else monotpe + } + if (isConstructor) { + // set result type tree to unit, but set the current class as result type of the symbol + typedAhead(ddef.tpt, Mode.Type, defn.UnitType) + wrapMethType(sym.owner.typeConstructor.appliedTo(typeParams map (_.symRef))) + } + else valOrDefDefSig(ddef, sym, wrapMethType) + } - def enterSelfSym(name: TermName, tpe: Type): Unit = - ctx.enter(ctx.newSymbol(ctx.owner, name, Synthetic, tpe, coord = symToComplete.coord)) + def typeDefSig(defn: TypeDef, sym: Symbol)(implicit ctx: Context): Type = { + completeParams(defn.tparams) + ??? + } - val ClassDef(_, _, impl @ Template(constr, parents, self, body)) = defn + def classDefSig(defn: ClassDef, cls: ClassSymbol)(implicit ctx: Context): Type = { - 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 parentType(constr: untpd.Tree): Type = { + val Trees.Select(Trees.New(tpt), _) = TreeInfo.methPart(constr) + val ptype = typedAhead(tpt, Mode.Type).tpe + if (ptype.uninstantiatedTypeParams.isEmpty) ptype + else typedAhead(constr, Mode.Expr).tpe + } - def localContext = ctx.fresh.withOwner(symToComplete) + def enterSelfSym(name: TermName, tpe: Type): Unit = + ctx.enter(ctx.newSymbol(ctx.owner, name, Synthetic, tpe, coord = cls.coord)) - def typeSig(defn: Tree): Type = defn match { - case defn: ValDef => - valOrDefDefSig(defn, completeValDef, identity)(localContext) - case defn: DefDef => - defDefSig(defn)(localContext.withNewScope) - case defn: TypeDef => - typeDefSig(defn)(localContext.withNewScope) - case defn: ClassDef => - classDefSig(defn)(localContext) - case imp: Import => - val expr1 = typedDefn(imp.expr, symToComplete) - ImportType(SharedTree(expr1)) - } + val ClassDef(_, _, impl @ Template(_, parents, self, body)) = defn - symToComplete.info = typeSig(original) + 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, 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) } }
\ 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 ee221f9f2..dd46a678e 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -10,6 +10,7 @@ import util.Positions._ import util.SourcePosition import collection.mutable import language.implicitConversions +import desugar.Mode trait TyperContextOps { ctx: Context => } @@ -18,83 +19,88 @@ 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 = ??? + def typedImport(imp: untpd.Import, pt: Type)(implicit ctx: Context): Import = { + val expr1 = typed(imp.expr) + imp.withType(pt).derivedImport(expr1, imp.selectors) + } - type DefTyper[UT <: untpd.NameTree, T <: tpd.Tree] = (UT, NamedType) => Context => T + def typedModifiers(mods: untpd.Modifiers): Modifiers = ??? - 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 typedValDef(defn: untpd.ValDef, sym: Symbol)(implicit ctx: Context) = { + val Trees.ValDef(mods, name, tpt, rhs) = defn + 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) } - 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 typedDefDef(defn: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = { + val Trees.DefDef(mods, name, tparams, vparamss, tpt, rhs) = defn + 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) } - 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 + def typedTypeDef(defn: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): TypeDef = { + val Trees.TypeDef(mods, name, tparams, rhs) = defn val mods1 = typedModifiers(mods) - val tparams1 = reEnterParams(tparams) + val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef]) 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) + defn.withType(sym.symRef).derivedTypeDef(mods1, name, tparams1, rhs1) } - val completeValDef: DefTyper[untpd.ValDef, ValDef] = { (vdef, pt) => implicit ctx: Context => - val Trees.ValDef(mods, name, tpt, rhs) = vdef + def typedClassDef(defn: untpd.ClassDef, cls: ClassSymbol)(implicit ctx: Context) = { + val Trees.ClassDef(mods, name, impl @ Trees.Template(constr, parents, self, body)) = defn val mods1 = typedModifiers(mods) - val (tpt1, rhs1) = typedTptRhs(tpt, rhs) - vdef.withType(tpt1.tpe).derivedValDef(mods1, name, tpt1, rhs1) + val constr1 = typed(constr) + val parents1 = parents mapconserve (typed(_)) + val self1 = typed(self) + ??? } - 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.enter(sym) - lateDef(param, noDefTyper) + 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) } } - 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 typed(tree: untpd.Tree, mode: Mode.Value = Mode.Expr, pt: Type = WildcardType)(implicit ctx: Context): Tree = { + typedTree get 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.TypeTree => + if (!tree.isEmpty) typed(tree.original, Mode.Type, pt) + else { + assert(pt != WildcardType) + tree.withType(pt) + } + case untpd.EmptyTree => + tpd.EmptyTree + } + } } - def typedImport(imp: untpd.Import, pt: Type)(implicit ctx: Context): Import = { - val expr1 = typed(imp.expr) - imp.withType(pt).derivedImport(expr1, imp.selectors) - } + 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 = + typed(tree, Mode.Type, pt) - def typedModifiers(mods: untpd.Modifiers): Modifiers = ??? }
\ No newline at end of file |