diff options
author | Martin Odersky <odersky@gmail.com> | 2013-08-14 16:07:59 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-08-14 16:07:59 +0200 |
commit | f19250b1a123aa63cf8f14096bfd8e29e7e548b2 (patch) | |
tree | a676a2d5c8e3dc494c4736c9d1454294b9b10341 /src/dotty | |
parent | c6f0c00790c996bea57ea905a830dedcb4f2bb44 (diff) | |
download | dotty-f19250b1a123aa63cf8f14096bfd8e29e7e548b2.tar.gz dotty-f19250b1a123aa63cf8f14096bfd8e29e7e548b2.tar.bz2 dotty-f19250b1a123aa63cf8f14096bfd8e29e7e548b2.zip |
Integrated parser/typer into compiler
Some initial bug fixes.
Added -explaintypes diagnostics.
Diffstat (limited to 'src/dotty')
-rw-r--r-- | src/dotty/tools/dotc/CompilationUnit.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/Run.scala | 26 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 14 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Phases.scala | 33 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 12 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/RefinedPrinter.scala | 13 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 20 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 14 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/TyperPhase.scala | 43 |
10 files changed, 170 insertions, 35 deletions
diff --git a/src/dotty/tools/dotc/CompilationUnit.scala b/src/dotty/tools/dotc/CompilationUnit.scala new file mode 100644 index 000000000..0c662116e --- /dev/null +++ b/src/dotty/tools/dotc/CompilationUnit.scala @@ -0,0 +1,15 @@ +package dotty.tools +package dotc + +import util.SourceFile +import ast.{tpd, untpd} + +class CompilationUnit(val source: SourceFile) { + + override def toString = source.toString + + var untpdTree: untpd.Tree = untpd.EmptyTree + + var tpdTree: tpd.Tree = tpd.EmptyTree + +}
\ No newline at end of file diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index f5bf1fb9b..e094cc06c 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -3,9 +3,22 @@ package dotc import core._ import Contexts._ +import Periods._ +import Symbols._ +import typer.{FrontEnd, Typer} class Compiler { - def newRun(implicit ctx: Context): Run = new Run(this) + def phases = List(new FrontEnd) + def rootContext(implicit ctx: Context): Context = { + ctx.usePhases(phases) + ctx.fresh + .withPeriod(Period(ctx.runId + 1, FirstPhaseId)) + .withOwner(defn.RootClass) + .withTyper(new Typer) + } + + def newRun(implicit ctx: Context): Run = + new Run(this)(rootContext) }
\ No newline at end of file diff --git a/src/dotty/tools/dotc/Run.scala b/src/dotty/tools/dotc/Run.scala index 8358cdbca..923e5f8b2 100644 --- a/src/dotty/tools/dotc/Run.scala +++ b/src/dotty/tools/dotc/Run.scala @@ -2,11 +2,31 @@ package dotty.tools package dotc import core._ -import Contexts._ +import Contexts._, Periods._, Symbols._ +import io.PlainFile +import util.{SourceFile, NoSource} class Run(comp: Compiler)(implicit ctx: Context) { - def compile(fileNames: List[String]): Unit = - for (name <- fileNames) println(s"<compiling $name>") + defn.init() + var units: List[CompilationUnit] = _ + + def getSource(fileName: String): SourceFile = { + val f = new PlainFile(fileName) + if (f.exists) new SourceFile(f) + else { + ctx.error(s"not found: $fileName") + NoSource + } + } + + def compile(fileNames: List[String]): Unit = { + val sources = fileNames map getSource + if (sources forall (_.exists)) { + units = sources map (new CompilationUnit(_)) + for (phase <- ctx.allPhases) + phase.runOn(units) + } + } }
\ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index a193da372..6c2670d5d 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -14,7 +14,7 @@ import SymDenotations._ import util.Positions._ import ast.Trees._ import ast.untpd -import util.{FreshNameCreator, SimpleMap} +import util.{FreshNameCreator, SimpleMap, SourceFile, NoSource} import typer._ import Implicits.ContextualImplicits import config.Settings._ @@ -114,6 +114,11 @@ object Contexts { def sstate: SettingsState = _sstate /** The current tree */ + private[this] var _compilationUnit: CompilationUnit = _ + protected def compilationUnit_=(compilationUnit: CompilationUnit) = _compilationUnit = compilationUnit + def compilationUnit: CompilationUnit = _compilationUnit + + /** The current tree */ private[this] var _tree: Tree[_ >: Untyped] = _ protected def tree_=(tree: Tree[_ >: Untyped]) = _tree = tree def tree: Tree[_ >: Untyped] = _tree @@ -227,7 +232,8 @@ object Contexts { /** The current source file; will be derived from current * compilation unit. */ - def source = util.NoSource // for now + def source: SourceFile = + if (compilationUnit == null) NoSource else compilationUnit.source /** Does current phase use an erased types interpretation? */ def erasedTypes: Boolean = phase.erasedTypes @@ -300,6 +306,7 @@ object Contexts { def withRefinedPrinter(printer: Context => Printer): this.type = { this.refinedPrinter = printer; this } def withOwner(owner: Symbol): this.type = { this.owner = owner; this } def withSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this } + def withCompilationUnit(compilationUnit: CompilationUnit): this.type = { this.compilationUnit = compilationUnit; 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 } @@ -444,6 +451,9 @@ object Contexts { private[dotc] var indent = 0 protected[dotc] val indentTab = " " + + /** Should warnings and errors containing non-sensical strings be suppressed? */ + private[dotc] var suppressNonSensicalErrors = true } object Context { diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala index 40a9f64d3..7979d3c58 100644 --- a/src/dotty/tools/dotc/core/Phases.scala +++ b/src/dotty/tools/dotc/core/Phases.scala @@ -27,15 +27,17 @@ object Phases { trait PhasesBase { this: ContextBase => + def allPhases = phases.tail + object NoPhase extends Phase { override def exists = false def name = "<no phase>" - def run() { throw new Error("NoPhase.run") } + def run(implicit ctx: Context): Unit = unsupported("run") } object SomePhase extends Phase { def name = "<some phase>" - def run() { throw new Error("SomePhase.run") } + def run(implicit ctx: Context): Unit = unsupported("run") } def phaseNamed(name: String) = @@ -58,7 +60,20 @@ object Phases { lazy val flattenPhase = phaseNamed(flattenName) } - abstract class Phase { + abstract class Phase extends DotClass { + + def name: String + + def run(implicit ctx: Context): Unit + + def runOn(units: List[CompilationUnit])(implicit ctx: Context): Unit = + for (unit <- units) run(ctx.fresh.withCompilationUnit(unit)) + + def description: String = name + + def checkable: Boolean = true + + def exists: Boolean = true private[this] var idCache = -1 @@ -77,17 +92,7 @@ object Phases { } } - def name: String - - def run(): Unit - - def description: String = name - - def checkable: Boolean = true - - def exists: Boolean = true - - final def <= (that: Phase)(implicit ctx: Context) = + final def <= (that: Phase)(implicit ctx: Context) = exists && id <= that.id final def prev(implicit ctx: Context): Phase = diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index a4cbdfe25..2940f949a 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -3,6 +3,7 @@ package dotc package core import Types._, Contexts._, Symbols._, Flags._ +import StdNames.nme import collection.mutable import util.SimpleMap @@ -181,8 +182,9 @@ class TypeComparer(implicit val ctx: Context) extends DotClass { case tp2: NamedType => thirdTryNamed(tp1, tp2) case tp2: RefinedType => - isSubType(tp1, tp2.parent) && - isSubType(tp1.member(tp2.refinedName).info, tp2.refinedInfo) + isSubType(tp1, tp2.parent) && ( + tp2.refinedName == nme.WILDCARD || + isSubType(tp1.member(tp2.refinedName).info, tp2.refinedInfo)) case AndType(tp21, tp22) => isSubType(tp1, tp21) && isSubType(tp1, tp22) case OrType(tp21, tp22) => @@ -357,4 +359,10 @@ class TypeComparer(implicit val ctx: Context) extends DotClass { if (tp1 == NoType || tp2 == NoType) false else if (tp1 eq tp2) true else isSubType(tp1, tp2) && isSubType(tp2, tp1) +} + +class ExplainingTypeComparer(implicit ctx: Context) extends TypeComparer { + override def isSubType(tp1: Type, tp2: Type) = { + ctx.traceIndented(s"${tp1.show} <:< ${tp2.show}")(super.isSubType(tp1, tp2)) + } }
\ No newline at end of file diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 75b3db186..87441f7b7 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -54,11 +54,14 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { super.toTextPrefix(tp) } - override protected def refinementNameString(tp: RefinedType): String = { - val tsym = tp.member(tp.refinedName).symbol - val name = tsym.originalName - nameString(if (tsym is ExpandedTypeParam) name.asTypeName.unexpandedName() else name) - } + override protected def refinementNameString(tp: RefinedType): String = + if (tp.parent.isInstanceOf[WildcardType] || tp.refinedName == nme.WILDCARD) + super.refinementNameString(tp) + else { + val tsym = tp.member(tp.refinedName).symbol + val name = tsym.originalName + nameString(if (tsym is ExpandedTypeParam) name.asTypeName.unexpandedName() else name) + } override def toText(tp: Type): Text = controlled { def toTextTuple(args: List[Type]): Text = diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 716de5f3c..1d679c070 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -7,6 +7,7 @@ import ast._ import Trees._, Constants._, StdNames._, Scopes._, Denotations._ import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._ import ast.desugar, ast.desugar._ +import Typer.AnySelectionProto import util.Positions._ import util.SourcePosition import collection.mutable @@ -126,6 +127,17 @@ class Namer { typer: Typer => sym } + /** All PackageClassInfoTypes come from here. */ + private def createPackageSymbol(pid: RefTree)(implicit ctx: Context): Symbol = { + val pkgOwner = pid match { + case Ident(_) => if (ctx.owner eq defn.EmptyPackageClass) defn.RootClass else ctx.owner + case Select(qual: RefTree, _) => createPackageSymbol(qual).moduleClass + } + val existing = pkgOwner.info.decls.lookup(pid.name) + if ((existing is Package) && (pkgOwner eq existing.owner)) existing + else println(s"entering new ${pid.name} in ${pkgOwner.show}") + } + /** The expansion of a member def */ def expansion(mdef: MemberDef)(implicit ctx: Context): Tree = { val expanded = desugar.memberDef(mdef) @@ -147,6 +159,10 @@ class Namer { typer: Typer => /** Enter statement */ def enterSym(stat: Tree)(implicit ctx: Context): Context = stat match { + case pcl: PackageDef => + val pkg = createPackageSymbol(pcl.pid) + enterSyms(pcl.stats)(ctx.fresh.withOwner(pkg.moduleClass)) + ctx case imp: Import => importContext(createSymbol(imp), imp.selectors) case mdef: MemberDef => @@ -161,7 +177,7 @@ class Namer { typer: Typer => def enterSyms(stats: List[Tree])(implicit ctx: Context): Context = { @tailrec def traverse(stats: List[Tree])(implicit ctx: Context): Context = stats match { case stat :: stats1 => - traverse(stats)(enterSym(stat)) + traverse(stats1)(enterSym(stat)) case nil => ctx } @@ -210,7 +226,7 @@ class Namer { typer: Typer => if (tree.isClassDef) classDefSig(tree, sym.asClass)(localContext) else typeDefSig(tree, sym)(localContext.withNewScope) case imp: Import => - val expr1 = typedAheadExpr(imp.expr) + val expr1 = typedAheadExpr(imp.expr, AnySelectionProto) ImportType(tpd.SharedTree(expr1)) } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 219f8045b..45750de87 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -59,6 +59,8 @@ object Typer { } class SelectionProto(name: Name, tp: Type) extends RefinedType(WildcardType, name)(_ => tp) + + object AnySelectionProto extends SelectionProto(nme.WILDCARD, WildcardType) } class Typer extends Namer with Applications with Implicits { @@ -96,7 +98,7 @@ class Typer extends Namer with Applications with Implicits { } def checkValue(tpe: Type, proto: Type, pos: Position)(implicit ctx: Context): Unit = - if (!(proto.isInstanceOf[SelectionProto])) { + if (!proto.isInstanceOf[SelectionProto]) { val sym = tpe.termSymbol if ((sym is Package) || (sym is JavaModule)) ctx.error(s"${sym.show} is not a value", pos) } @@ -737,7 +739,7 @@ class Typer extends Namer with Applications with Implicits { } def typedImport(imp: untpd.Import, sym: Symbol)(implicit ctx: Context): Import = { - val expr1 = typedExpr(imp.expr) + val expr1 = typedExpr(imp.expr, AnySelectionProto) cpy.Import(imp, expr1, imp.selectors).withType(sym.symRef) } @@ -751,16 +753,16 @@ class Typer extends Namer with Applications with Implicits { cpy.Typed(tree, arg1, TypeTree(ownType)) withType ownType } - def typedPackageDef(tree: untpd.PackageDef)(implicit ctx: Context): Tree = { - val pid1 = typed(tree.pid) + def typedPackageDef(tree: untpd.PackageDef)(implicit ctx: Context): Tree = { + val pid1 = typedExpr(tree.pid, AnySelectionProto) val pkg = pid1.symbol - val nestedCtx = + val packageContext = if (pkg is Package) ctx.fresh withOwner pkg.moduleClass else { ctx.error(s"${pkg.show} is not a packge") ctx } - val stats1 = typedStats(tree.stats, NoSymbol)(nestedCtx) + val stats1 = typedStats(tree.stats, NoSymbol)(packageContext) cpy.PackageDef(tree, pid1.asInstanceOf[RefTree], stats1) withType pkg.symRef } diff --git a/src/dotty/tools/dotc/typer/TyperPhase.scala b/src/dotty/tools/dotc/typer/TyperPhase.scala new file mode 100644 index 000000000..c43aae47f --- /dev/null +++ b/src/dotty/tools/dotc/typer/TyperPhase.scala @@ -0,0 +1,43 @@ +package dotty.tools.dotc +package typer + +import core._ +import Phases._ +import Contexts._ +import parsing.Parsers.Parser + +class FrontEnd extends Phase { + + def name = "frontend" + + def parse(implicit ctx: Context) = { + val unit = ctx.compilationUnit + unit.untpdTree = new Parser(unit.source).parse() + println("parsed:\n"+unit.untpdTree.show) + } + + def enterSyms(implicit ctx: Context) = { + val unit = ctx.compilationUnit + ctx.typer.enterSym(unit.untpdTree) + println("entered:\n"+unit.source) + } + + def typeCheck(implicit ctx: Context) = { + val unit = ctx.compilationUnit + unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree) + println("typed:\n"+unit.source) + } + + override def runOn(units: List[CompilationUnit])(implicit ctx: Context): Unit = { + val unitContexts = units map ctx.fresh.withCompilationUnit + unitContexts foreach (parse(_)) + unitContexts foreach (enterSyms(_)) + unitContexts foreach (typeCheck(_)) + } + + override def run(implicit ctx: Context): Unit = { + parse + enterSyms + typeCheck + } +}
\ No newline at end of file |