aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-08-14 16:07:59 +0200
committerMartin Odersky <odersky@gmail.com>2013-08-14 16:07:59 +0200
commitf19250b1a123aa63cf8f14096bfd8e29e7e548b2 (patch)
treea676a2d5c8e3dc494c4736c9d1454294b9b10341
parentc6f0c00790c996bea57ea905a830dedcb4f2bb44 (diff)
downloaddotty-f19250b1a123aa63cf8f14096bfd8e29e7e548b2.tar.gz
dotty-f19250b1a123aa63cf8f14096bfd8e29e7e548b2.tar.bz2
dotty-f19250b1a123aa63cf8f14096bfd8e29e7e548b2.zip
Integrated parser/typer into compiler
Some initial bug fixes. Added -explaintypes diagnostics.
-rw-r--r--src/dotty/tools/dotc/CompilationUnit.scala15
-rw-r--r--src/dotty/tools/dotc/Compiler.scala15
-rw-r--r--src/dotty/tools/dotc/Run.scala26
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala14
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala33
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala12
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala13
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala20
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala14
-rw-r--r--src/dotty/tools/dotc/typer/TyperPhase.scala43
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