diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala new file mode 100644 index 0000000000..b494e1c33f --- /dev/null +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -0,0 +1,139 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author Martin Odersky + */ +// $Id$ +package scala.tools.nsc.typechecker; + +import scala.tools.nsc.util.Position; +import scala.tools.nsc.reporters.AbstractReporter; +import symtab.Flags._; + +abstract class TreeCheckers extends Analyzer { + + import global._; + + val tpeOfTree = new scala.collection.mutable.HashMap[Tree, Type]; + + def checkTrees: unit = { + System.out.println("[consistency check at start of phase " + phase + "]"); + for (val unit <- currentRun.units) check(unit); + } + + def check(unit: CompilationUnit): unit = { + val areporter = if (reporter.isInstanceOf[AbstractReporter]) reporter.asInstanceOf[AbstractReporter] else null; + + val curPrompt = if (areporter != null) { + val ret = areporter.prompt; + areporter.prompt = true; + ret; + } else false; + + val context = startContext.make(unit); + context.checking = true; + tpeOfTree.clear; + val checker = new TreeChecker(context); + checker.precheck.traverse(unit.body); + checker.typed(unit.body); + checker.postcheck.traverse(unit.body); + if (areporter != null) + areporter.prompt = curPrompt; + } + + override def newTyper(context: Context): Typer = new TreeChecker(context); + + class TreeChecker(context0: Context) extends Typer(context0) { + + import infer._; + + override def typed(tree: Tree, mode: int, pt: Type): Tree = { + //System.out.println("**** checking " + tree);//debug + tree match { + case EmptyTree | TypeTree() => + ; + case _ => + if (!tpeOfTree.contains(tree)) { + tpeOfTree.update(tree, tree.tpe); + tree.tpe = null + } + val newtree = super.typed(tree, mode, pt); + if ((newtree ne tree) && !newtree.isInstanceOf[Literal]) + error(tree.pos, "trees differ\n old: " + tree + " [" + tree.getClass() + "]\n new: " + + newtree + " [" + newtree.getClass() + "]"); + } + tree + } + override def typed(tree: Tree) = super.typed(tree); // doto remove for new compiler + + object precheck extends Traverser { + override def traverse(tree: Tree): unit = + try { + tree match { + case DefDef(_, _, _, _, _, _) => + if (tree.symbol.hasFlag(ACCESSOR) && + !tree.symbol.hasFlag(DEFERRED) && + !tree.symbol.tpe.resultType.isInstanceOf[ConstantType]) { + assert(tree.symbol.accessed != NoSymbol); + assert(tree.symbol.accessed.getter(tree.symbol.owner) == tree.symbol || + tree.symbol.accessed.setter(tree.symbol.owner) == tree.symbol); + } + case ValDef(_, _, _, _) => + if (tree.symbol.hasGetter) { + assert(tree.symbol.getter(tree.symbol.owner) != NoSymbol) + } + case Apply(_, args) => + assert(args forall (EmptyTree !=)) + case Select(_, _) => + assert(tree.symbol != NoSymbol, tree); + case This(_) => + if (!(tree.symbol.isStatic && (tree.symbol hasFlag MODULE))) { + var o = currentOwner; + while (o != tree.symbol) { + o = o.owner; + assert(o != NoSymbol, tree) + } + } + case _ => + } + if (tree.pos == Position.NOPOS && tree != EmptyTree) { + error(tree.pos, "tree without position: " + tree) + } else if (tree.tpe == null && phase.id >= currentRun.typerPhase.id) { + error(tree.pos, "tree without type: " + tree); + } else if (tree.isDef && tree.symbol.owner != currentOwner) { + var owner = currentOwner; + while (owner.isTerm && !owner.isMethod && tree.symbol.owner != owner) + owner = owner.owner; + if (tree.symbol.owner != owner) { + error(tree.pos, "" + tree.symbol + " has wrong owner: " + tree.symbol.owner + + tree.symbol.owner.locationString + ", should be: " + + currentOwner + currentOwner.locationString) + } + } else { + super.traverse(tree) + } + } catch { + case ex: Throwable => + if (settings.debug.value) + System.out.println("exception when traversing " + tree); + throw(ex) + } + } + + object postcheck extends Traverser { + override def traverse(tree: Tree): unit = tree match { + case EmptyTree | TypeTree() => + ; + case _ => + tpeOfTree.get(tree) match { + case Some(oldtpe) => + if (!(oldtpe =:= tree.tpe)) + error(tree.pos, "types differ\n old: " + oldtpe + "\n new: " + tree.tpe + + "\n tree: " + tree); + tree.tpe = oldtpe; + super.traverse(tree) + case None => + } + } + } + } +} |