summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-04-28 17:37:27 +0000
committerMartin Odersky <odersky@gmail.com>2005-04-28 17:37:27 +0000
commit0baff379fd40abb757551c7a02676b051b1c8e17 (patch)
tree7352cfd392c87bd78781a66a74df0e00346c829e /sources/scala/tools/nsc
parent6d81466523463b6a7795e841a7cfdf7ad3e06356 (diff)
downloadscala-0baff379fd40abb757551c7a02676b051b1c8e17.tar.gz
scala-0baff379fd40abb757551c7a02676b051b1c8e17.tar.bz2
scala-0baff379fd40abb757551c7a02676b051b1c8e17.zip
*** empty log message ***
Diffstat (limited to 'sources/scala/tools/nsc')
-rwxr-xr-xsources/scala/tools/nsc/Global.scala27
-rw-r--r--sources/scala/tools/nsc/StdPhase.scala6
-rwxr-xr-xsources/scala/tools/nsc/ast/TreeBuilder.scala320
-rwxr-xr-xsources/scala/tools/nsc/ast/TreeCheckers.scala21
-rwxr-xr-xsources/scala/tools/nsc/ast/TreeGen.scala8
-rw-r--r--sources/scala/tools/nsc/ast/TreePrinters.scala25
-rw-r--r--sources/scala/tools/nsc/ast/Trees.scala2
-rw-r--r--sources/scala/tools/nsc/ast/parser/ParserPhase.scala4
-rwxr-xr-xsources/scala/tools/nsc/ast/parser/Parsers.scala (renamed from sources/scala/tools/nsc/ast/parser/Syntactic.scala)178
-rwxr-xr-x[-rw-r--r--]sources/scala/tools/nsc/ast/parser/Scanners.scala (renamed from sources/scala/tools/nsc/ast/parser/Lexical.scala)6
-rw-r--r--sources/scala/tools/nsc/ast/parser/Tokens.scala26
-rwxr-xr-xsources/scala/tools/nsc/buildnsc1
-rwxr-xr-xsources/scala/tools/nsc/symtab/Definitions.scala95
-rw-r--r--sources/scala/tools/nsc/symtab/Flags.scala59
-rwxr-xr-xsources/scala/tools/nsc/symtab/Scopes.scala8
-rwxr-xr-xsources/scala/tools/nsc/symtab/StdNames.scala3
-rwxr-xr-xsources/scala/tools/nsc/symtab/SymbolLoaders.scala88
-rwxr-xr-xsources/scala/tools/nsc/symtab/Symbols.scala42
-rwxr-xr-xsources/scala/tools/nsc/symtab/Types.scala135
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala12
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/MetaParser.scala14
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/PickleFormat.scala2
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/Pickler.scala15
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/UnPickle.scala480
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/UnPickler.scala9
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Contexts.scala165
-rw-r--r--sources/scala/tools/nsc/typechecker/EtaExpansion.scala5
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Infer.scala104
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Namers.scala37
-rwxr-xr-xsources/scala/tools/nsc/typechecker/TypeCheckers.scala300
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala47
-rw-r--r--sources/scala/tools/nsc/util/LinkedList.scala11
-rw-r--r--sources/scala/tools/nsc/util/ListBuffer.scala58
33 files changed, 1281 insertions, 1032 deletions
diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala
index 605e162b1d..651725f7cf 100755
--- a/sources/scala/tools/nsc/Global.scala
+++ b/sources/scala/tools/nsc/Global.scala
@@ -8,7 +8,7 @@ package scala.tools.nsc;
import java.io._;
import java.nio.charset._;
import scala.tools.util._;
-import scala.collection.mutable.{HashSet,HashMap,ListBuffer}
+import scala.collection.mutable.{HashSet,HashMap}
import symtab._;
import symtab.classfile.{PickleBuffer, Pickler};
@@ -116,7 +116,7 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
val global: Global.this.type = Global.this
}
- def rootLoader: LazyType = loaders.packageLoader(classPath.getRoot());
+ def rootLoader: LazyType = new loaders.PackageLoader(classPath.getRoot());
// Phases ------------------------------------------------------------
@@ -130,8 +130,11 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
object analyzer extends Analyzer {
val global: Global.this.type = Global.this;
}
+ val infer = new analyzer.Inferencer(analyzer.NoContext);
+
val namerPhase = new analyzer.NamerPhase(parserPhase);
val typeCheckPhase = new analyzer.TypeCheckPhase(namerPhase);
+
val picklePhase = new pickler.PicklePhase(typeCheckPhase);
/*
@@ -162,7 +165,7 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
fileset += unit.source.getFile();
}
- def units: Seq[CompilationUnit] = unitbuf;
+ def units: Iterator[CompilationUnit] = unitbuf.elements;
/** A map from compiled top-level symbols to their source files */
val symSource = new HashMap[Symbol, AbstractFile];
@@ -203,7 +206,7 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
}
} else {
for (val Pair(sym, file) <- symSource.elements)
- sym.reset(loaders.sourcefileLoader(file));
+ sym.reset(new loaders.SourcefileLoader(file));
}
informTime("total", startTime);
}
@@ -254,10 +257,18 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
/** Returns the file with the given suffix for the given class. */
private def getFile(clazz: Symbol, suffix: String) = {
- val outdir = settings.outdir.value;
- new File(
- if (outdir == "") clazz.simpleName.toString() + suffix
- else outdir + File.separatorChar + clazz.fullNameString(File.separatorChar) + suffix);
+ val outdirname = settings.outdir.value;
+ var outdir = new File(if (outdirname == "") "." else outdirname);
+ val filename = clazz.fullNameString('.');
+ var start = 0;
+ var end = filename.indexOf('.', start);
+ while (end >= start) {
+ outdir = new File(outdir, filename.substring(start, end));
+ if (!outdir.exists()) outdir.mkdir();
+ start = end + 1;
+ end = filename.indexOf('.', start);
+ }
+ new File(outdir, filename.substring(start) + suffix)
}
private def writeSymblFile(clazz: Symbol, pickled: PickleBuffer) = {
diff --git a/sources/scala/tools/nsc/StdPhase.scala b/sources/scala/tools/nsc/StdPhase.scala
index 7db984f563..1a663a6a45 100644
--- a/sources/scala/tools/nsc/StdPhase.scala
+++ b/sources/scala/tools/nsc/StdPhase.scala
@@ -7,7 +7,11 @@ package scala.tools.nsc;
abstract class StdPhase(prev: Phase) extends Phase(prev) {
val global: Global;
- def run: unit = for (val unit <- global.units) apply(unit);
+ def run: unit =
+ for (val unit <- global.units) {
+ if (global.settings.debug.value) System.out.println("[running phase " + name + " on " + unit + "]");//debug
+ apply(unit);
+ }
def apply(unit: global.CompilationUnit): unit;
}
diff --git a/sources/scala/tools/nsc/ast/TreeBuilder.scala b/sources/scala/tools/nsc/ast/TreeBuilder.scala
new file mode 100755
index 0000000000..e183cb7804
--- /dev/null
+++ b/sources/scala/tools/nsc/ast/TreeBuilder.scala
@@ -0,0 +1,320 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id$
+package scala.tools.nsc.ast;
+
+import symtab.Flags._;
+import util.ListBuffer;
+
+abstract class TreeBuilder {
+
+ val global: Global;
+ import global._;
+ import posAssigner.atPos;
+
+ def freshName(prefix: String): Name;
+
+ def freshName(): Name = freshName("x$");
+
+ private object patvarTransformer extends Transformer {
+ override def transform(tree: Tree): Tree = tree match {
+ case Ident(name) if (treeInfo.isVariableName(name) && name != nme.WILDCARD) =>
+ atPos(tree.pos)(Bind(name, Ident(nme.WILDCARD)))
+ case Typed(id @ Ident(name), tpt) =>
+ Bind(name, atPos(tree.pos)(Typed(Ident(nme.WILDCARD), tpt))) setPos id.pos
+ case Apply(fn @ Apply(_, _), args) =>
+ copy.Apply(tree, transform(fn), transformTrees(args))
+ case Apply(fn, args) =>
+ copy.Apply(tree, fn, transformTrees(args))
+ case Typed(expr, tpt) =>
+ copy.Typed(tree, transform(expr), tpt)
+ case Sequence(_) | Alternative(_) | Bind(_, _) =>
+ super.transform(tree)
+ case _ =>
+ tree
+ }
+ }
+
+ /** Traverse pattern and collect all variable names in buffer */
+ private object getvarTraverser extends Traverser {
+ val buf = new ListBuffer[Name];
+ def init: Traverser = { buf.clear; this }
+ override def traverse(tree: Tree): unit = tree match {
+ case Bind(name, tpe) =>
+ if (buf.elements forall (name !=)) buf += name;
+ traverse(tpe)
+ case _ => super.traverse(tree)
+ }
+ }
+
+ /** Returns list of all pattern variables without duplicates */
+ private def getVariables(tree: Tree): List[Name] = {
+ getvarTraverser.init.traverse(tree);
+ getvarTraverser.buf.toList
+ }
+
+ private def mkTuple(trees: List[Tree]): Tree = trees match {
+ case List() => Literal(())
+ case List(tree) => tree
+ case _ => Apply(Select(Ident(nme.scala), newTermName("Tuple" + trees.length)), trees)
+ }
+
+ /** If tree is a variable pattern, return Some("its name and type").
+ * Otherwise return none */
+ private def matchVarPattern(tree: Tree): Option[Pair[Name, Tree]] = tree match {
+ case Ident(name) => Some(Pair(name, TypeTree()))
+ case Bind(name, Ident(nme.WILDCARD)) => Some(Pair(name, TypeTree()))
+ case Typed(Ident(name), tpt) => Some(Pair(name, tpt))
+ case Bind(name, Typed(Ident(nme.WILDCARD), tpt)) => Some(Pair(name, tpt))
+ case _ => None
+ }
+
+ /** Create tree representing (unencoded) binary operation expression or pattern. */
+ def makeBinop(isExpr: boolean, left: Tree, op: Name, right: Tree): Tree = {
+ if (isExpr) {
+ if (treeInfo.isLeftAssoc(op)) {
+ Apply(Select(left, op.encode), List(right))
+ } else {
+ val x = freshName();
+ Block(
+ List(ValDef(SYNTHETIC, x, TypeTree(), left)),
+ Apply(Select(right, op.encode), List(Ident(x))))
+ }
+ } else {
+ Apply(Ident(op.encode.toTypeName), List(left, right))
+ }
+ }
+
+ /** Create tree representing an object creation <new parents { stats }> */
+ def makeNew(parents: List[Tree], stats: List[Tree], args: List[Tree]): Tree =
+ if (parents.tail.isEmpty && stats.isEmpty)
+ Apply(Select(New(parents.head), nme.CONSTRUCTOR), args)
+ else {
+ val x = freshName(nme.ANON_CLASS_NAME.toString());
+ Block(
+ List(ClassDef(
+ FINAL | SYNTHETIC, x, List(), TypeTree(),
+ Template(parents, makeConstructorPart(0, List(List()), args) ::: stats))),
+ Typed(
+ New(Apply(Select(Ident(x), nme.CONSTRUCTOR), List())),
+ makeIntersectionTypeTree(parents map (.duplicate))))
+ }
+
+ /** Create a tree represeting an assignment <lhs = rhs> */
+ def makeAssign(lhs: Tree, rhs: Tree): Tree = lhs match {
+ case Apply(fn, args) => Apply(Select(fn, nme.update), args ::: List(rhs))
+ case _ => Assign(lhs, rhs)
+ }
+
+ /** A type tree corresponding to (possibly unary) intersection type */
+ def makeIntersectionTypeTree(tps: List[Tree]): Tree = {
+ if (tps.tail.isEmpty) tps.head else CompoundTypeTree(Template(tps, List()))
+ }
+
+ /** Create tree representing a while loop */
+ def makeWhile(lname: Name, cond: Tree, body: Tree): Tree = {
+ val continu = Apply(Ident(lname), List());
+ val rhs = If(cond, Block(List(body), continu), Literal(()));
+ LabelDef(lname, Nil, rhs)
+ }
+
+ /** Create tree representing a do-while loop */
+ def makeDoWhile(lname: Name, body: Tree, cond: Tree): Tree = {
+ val continu = Apply(Ident(lname), List());
+ val rhs = Block(List(body), If(cond, continu, Literal(())));
+ LabelDef(lname, Nil, rhs)
+ }
+
+ /** Create block of statements `stats' */
+ def makeBlock(stats: List[Tree]): Tree = {
+ if (stats.isEmpty) Literal(())
+ else if (!stats.last.isTerm) Block(stats, Literal(()));
+ else if (stats.length == 1) stats(0)
+ else Block(stats.init, stats.last)
+ }
+
+ /** Create tree for for-comprehension generator <val pat0 <- rhs0> */
+ def makeGenerator(pat: Tree, rhs: Tree): Tree = {
+ val pat1 = patvarTransformer.transform(pat);
+ val rhs1 = matchVarPattern(pat1) match {
+ case Some(_) =>
+ rhs
+ case None =>
+ Apply(
+ Select(rhs, nme.filter),
+ List(makeVisitor(List(
+ CaseDef(pat1.duplicate, EmptyTree, Literal(true)),
+ CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))))))
+ }
+ CaseDef(pat1, EmptyTree, rhs1)
+ }
+
+ /** Create tree for for-comprehension <for (enums) do body> or
+ * <for (enums) yield body> where mapName and flatMapName are chosen
+ * corresponding to whether this is a for-do or a for-yield.
+ */
+ private def makeFor(mapName: Name, flatMapName: Name, enums: List[Tree], body: Tree): Tree = {
+
+ def makeCont(pat: Tree, body: Tree): Tree = matchVarPattern(pat) match {
+ case Some(Pair(name, tpt)) =>
+ Function(List(ValDef(PARAM, name, tpt, EmptyTree)), body)
+ case None =>
+ makeVisitor(List(CaseDef(pat, EmptyTree, body)))
+ }
+
+ def makeBind(meth: Name, qual: Tree, pat: Tree, body: Tree): Tree =
+ Apply(Select(qual, meth), List(makeCont(pat, body)));
+
+ atPos(enums.head.pos) {
+ enums match {
+ case CaseDef(pat, g, rhs) :: Nil =>
+ makeBind(mapName, rhs, pat, body)
+ case CaseDef(pat, g, rhs) :: (rest @ (CaseDef(_, _, _) :: _)) =>
+ makeBind(flatMapName, rhs, pat, makeFor(mapName, flatMapName, rest, body))
+ case CaseDef(pat, g, rhs) :: test :: rest =>
+ makeFor(mapName, flatMapName,
+ CaseDef(pat, g, makeBind(nme.filter, rhs, pat.duplicate, test)) :: rest,
+ body)
+ }
+ }
+ }
+
+ /** Create tree for for-do comprehension <for (enums) body> */
+ def makeFor(enums: List[Tree], body: Tree): Tree =
+ makeFor(nme.foreach, nme.foreach, enums, body);
+
+ /** Create tree for for-yield comprehension <for (enums) yield body> */
+ def makeForYield(enums: List[Tree], body: Tree): Tree =
+ makeFor(nme.map, nme.flatMap, enums, body);
+
+ /** Create tree for a pattern alternative */
+ def makeAlternative(ts: List[Tree]): Tree = {
+ def alternatives(t: Tree): List[Tree] = t match {
+ case Alternative(ts) => ts
+ case _ => List(t)
+ }
+ Alternative(for (val t <- ts; val a <- alternatives(t)) yield a)
+ }
+
+ /** Create tree for a pattern sequence */
+ def makeSequence(ts: List[Tree]): Tree = {
+ def elements(t: Tree): List[Tree] = t match {
+ case Sequence(ts) => ts
+ case _ => List(t)
+ }
+ Sequence(for (val t <- ts; val e <- elements(t)) yield e)
+ }
+
+ /** Create tree for the p* regex pattern, becomes z@( |(p,z)) */
+ def makeStar(p: Tree): Tree = {
+ val zname = freshName();
+ Bind(zname,
+ makeAlternative(List(
+ Sequence(List()),
+ makeSequence(List(p, Ident(zname))))))
+ }
+
+ /** Create tree for the p+ regex pattern, becomes z@(p,(z| )) */
+ def makePlus(p: Tree): Tree = {
+ val zname = freshName();
+ Bind(zname,
+ makeSequence(List(
+ p, makeAlternative(List(Ident(zname), Sequence(List()))))))
+ }
+
+ /** Create tree for the p? regex pattern, becomes (p| ) */
+ def makeOpt(p: Tree): Tree =
+ makeAlternative(List(p, Sequence(List())));
+
+ /** Create visitor <x => x match cases> */
+ def makeVisitor(cases: List[CaseDef]): Tree = {
+ val x = freshName();
+ Function(List(ValDef(PARAM | SYNTHETIC, x, TypeTree(), EmptyTree)), Match(Ident(x), cases))
+ }
+
+ /** Create tree for case definition <case pat if guard => rhs> */
+ def makeCaseDef(pat: Tree, guard: Tree, rhs: Tree): CaseDef = {
+ CaseDef(patvarTransformer.transform(pat), guard, rhs);
+ }
+
+ /** Create tree for pattern definition <mods val pat0 = rhs> */
+ def makePatDef(mods: int, pat: Tree, rhs: Tree): List[Tree] = matchVarPattern(pat) match {
+ case Some(Pair(name, tpt)) =>
+ List(ValDef(mods, name, tpt, rhs))
+
+ case None =>
+ // in case there are no variables in pattern
+ // val p = e ==> e.match (case p => ())
+ //
+ // in case there is exactly one variable in pattern
+ // val x_1 = e.match (case p => (x_1))
+ //
+ // in case there are more variables in pattern
+ // val p = e ==> private synthetic val t$ = e.match (case p => (x_1, ..., x_N))
+ // val x_1 = t$._1
+ // ...
+ // val x_N = t$._N
+ val pat1 = patvarTransformer.transform(pat);
+ val vars = getVariables(pat1);
+ val matchExpr = atPos(pat1.pos){
+ Match(rhs, List(CaseDef(pat1, EmptyTree, mkTuple(vars map Ident))))
+ }
+ vars match {
+ case List() =>
+ List(matchExpr)
+ case List(vname) =>
+ List(ValDef(mods, vname, TypeTree(), matchExpr))
+ case _ =>
+ val tmp = freshName();
+ val firstDef = ValDef(PRIVATE | LOCAL | SYNTHETIC, tmp, TypeTree(), matchExpr);
+ var cnt = 0;
+ val restDefs = for (val v <- vars) yield {
+ cnt = cnt + 1;
+ ValDef(mods, v, TypeTree(), Select(Ident(tmp), newTermName("_" + cnt)))
+ }
+ firstDef :: restDefs
+ }
+ }
+
+ /** Add constructor to template */
+ def makeConstructorPart(mods: int, vparamss: List[List[ValDef]], args: List[Tree]): List[Tree] = {
+ val vparamss1 = vparamss map (.map (vd =>
+ ValDef(PARAM | (vd.mods & IMPLICIT), vd.name, vd.tpt.duplicate, EmptyTree)));
+ val constr: Tree = DefDef(
+ mods & ConstrFlags | SYNTHETIC, nme.CONSTRUCTOR, List(),
+ if (vparamss1.isEmpty) List(List()) else vparamss1,
+ TypeTree(), makeSuperCall(args));
+ val vparams: List[Tree] =
+ for (val vparams <- vparamss; val vparam <- vparams) yield vparam;
+ vparams ::: List(constr)
+ }
+
+ /** Create supercall */
+ def makeSuperCall(args: List[Tree]): Tree =
+ Apply(
+ Select(Super(nme.EMPTY.toTypeName, nme.EMPTY.toTypeName), nme.CONSTRUCTOR),
+ args);
+
+ /** Create a tree representing a function type */
+ def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree =
+ AppliedTypeTree(
+ Select(Ident(nme.scala), newTypeName("Function" + argtpes.length)),
+ argtpes ::: List(restpe));
+
+ /** Append implicit view section if for `implicitViews' if nonempty */
+ def addImplicitViews(vparamss: List[List[ValDef]], implicitViews: List[Tree]): List[List[ValDef]] = {
+ def makeViewParam(tpt: Tree) = ValDef(PARAM | IMPLICIT, freshName("view$"), tpt, EmptyTree);
+ if (implicitViews.isEmpty) vparamss
+ else vparamss ::: List(implicitViews map makeViewParam)
+ }
+
+ /** Create a tree representing a packaging */
+ def makePackaging(pkg: Tree, stats: List[Tree]): PackageDef = pkg match {
+ case Ident(name) =>
+ PackageDef(name, stats)
+ case Select(qual, name) =>
+ makePackaging(qual, List(PackageDef(name, stats)))
+ }
+}
diff --git a/sources/scala/tools/nsc/ast/TreeCheckers.scala b/sources/scala/tools/nsc/ast/TreeCheckers.scala
new file mode 100755
index 0000000000..8c3cf80334
--- /dev/null
+++ b/sources/scala/tools/nsc/ast/TreeCheckers.scala
@@ -0,0 +1,21 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id$
+package scala.tools.nsc.ast;
+
+import scala.tools.util.Position;
+
+class TreeCheckers: Global {
+
+ object treeChecker extends Traverser {
+ override def traverse(tree: Tree): unit = {
+ if (tree.pos == Position.NOPOS)
+ throw new FatalError("tree without position: " + tree)
+ else if (tree.tpe == null && phase.id >= typeCheckPhase.id)
+ throw new FatalError("tree without type: " + tree)
+ }
+ }
+}
+
diff --git a/sources/scala/tools/nsc/ast/TreeGen.scala b/sources/scala/tools/nsc/ast/TreeGen.scala
index f152bb2f2e..82190a13ce 100755
--- a/sources/scala/tools/nsc/ast/TreeGen.scala
+++ b/sources/scala/tools/nsc/ast/TreeGen.scala
@@ -86,12 +86,15 @@ abstract class TreeGen {
def ValDef(sym: Symbol, rhs: Tree): ValDef = atPos(sym.pos) {
global.ValDef(flags2mods(sym.flags), sym.name, TypeTree(sym.tpe), rhs)
+ setSymbol sym setType UnitClass.tpe
}
def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree);
- def AbsTypeDef(sym: Symbol) =
+ def AbsTypeDef(sym: Symbol) = atPos(sym.pos) {
global.AbsTypeDef(flags2mods(sym.flags), sym.name,
- TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi));
+ TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi))
+ setSymbol sym setType UnitClass.tpe
+ }
def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree) = atPos(sym.pos) {
var cnt = 0;
@@ -110,6 +113,7 @@ abstract class TreeGen {
vparamss.map(.map(ValDef)),
TypeTree(tpe),
rhs(vparamss))
+ setSymbol sym setType UnitClass.tpe
}
mk(List(), List(), sym.tpe)
}
diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala
index acc96bedfc..8d5d061fcf 100644
--- a/sources/scala/tools/nsc/ast/TreePrinters.scala
+++ b/sources/scala/tools/nsc/ast/TreePrinters.scala
@@ -53,18 +53,16 @@ abstract class TreePrinters {
print("["); printSeq(ts){printParam}{print(", ")}; print("]")
}
- def printValueParams(ts: List[ValDef]): unit =
- if (!ts.isEmpty) {
- print("("); printSeq(ts){printParam}{print(", ")}; print(")")
- }
+ def printValueParams(ts: List[ValDef]): unit = {
+ print("(");
+ if (!ts.isEmpty) printModifiers(ts.head.mods & IMPLICIT);
+ printSeq(ts){printParam}{print(", ")};
+ print(")")
+ }
def printParam(tree: Tree): unit = tree match {
case ValDef(mods, name, tp, rhs) =>
- if ((mods & PARAMACCESSOR) != 0) {
- print(tree)
- } else {
- print(symName(tree, name)); printOpt(": ", tp);
- }
+ print(symName(tree, name)); printOpt(": ", tp);
case AbsTypeDef(mods, name, lo, hi) =>
print(symName(tree, name));
printOpt(" >: ", lo); printOpt(" <: ", hi);
@@ -83,7 +81,8 @@ abstract class TreePrinters {
if (!tree.isEmpty) { print(prefix); print(tree) }
def printModifiers(flags: int): unit = {
- val s = flagsToString(flags);
+ val mask = if (settings.debug.value) -1 else PrintableFlags;
+ val s = flagsToString(flags & mask);
if (s.length() != 0) print(s + " ")
}
@@ -117,10 +116,10 @@ abstract class TreePrinters {
if (rhs.isEmpty) print("_") else print(rhs)
}
- case DefDef(mods, name, tparams, vparams, tp, rhs) =>
+ case DefDef(mods, name, tparams, vparamss, tp, rhs) =>
printModifiers(mods);
print("def " + symName(tree, name));
- printTypeParams(tparams); vparams foreach printValueParams;
+ printTypeParams(tparams); vparamss foreach printValueParams;
printOpt(": ", tp); printOpt(" = ", rhs);
case AbsTypeDef(mods, name, lo, hi) =>
@@ -167,7 +166,7 @@ abstract class TreePrinters {
printRow(trees, "(", "| ", ")")
case Bind(name, t) =>
- print(symName(tree, name)); print(" @ "); print(t)
+ print("("); print(symName(tree, name)); print(" @ "); print(t); print(")");
case Function(vparams, body) =>
print("("); printValueParams(vparams); print(" => "); print(body); print(")")
diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala
index 1a1f64a872..e5d040a31f 100644
--- a/sources/scala/tools/nsc/ast/Trees.scala
+++ b/sources/scala/tools/nsc/ast/Trees.scala
@@ -146,7 +146,7 @@ class Trees: Global {
/** Bind of a variable to a rhs pattern, eliminated by TransMatch */
case class Bind(name: Name, body: Tree)
- extends TermTree;
+ extends DefTree;
/** Anonymous function, eliminated by analyzer */
case class Function(vparams: List[ValDef], body: Tree)
diff --git a/sources/scala/tools/nsc/ast/parser/ParserPhase.scala b/sources/scala/tools/nsc/ast/parser/ParserPhase.scala
index 0e4e9643a1..008ba70c00 100644
--- a/sources/scala/tools/nsc/ast/parser/ParserPhase.scala
+++ b/sources/scala/tools/nsc/ast/parser/ParserPhase.scala
@@ -7,8 +7,8 @@ package scala.tools.nsc.ast.parser;
abstract class ParserPhase(prev: Phase)
extends StdPhase(prev)
- with Lexical
- with Syntactic {
+ with Scanners
+ with Parsers {
def name = "parser";
def apply(unit: global.CompilationUnit): unit = {
global.informProgress("parsing " + unit);
diff --git a/sources/scala/tools/nsc/ast/parser/Syntactic.scala b/sources/scala/tools/nsc/ast/parser/Parsers.scala
index 479e0a65d6..4e8b098707 100755
--- a/sources/scala/tools/nsc/ast/parser/Syntactic.scala
+++ b/sources/scala/tools/nsc/ast/parser/Parsers.scala
@@ -6,7 +6,7 @@
package scala.tools.nsc.ast.parser;
import scala.tools.util.Position;
-import scala.collection.mutable.ListBuffer;
+import util.ListBuffer;
import symtab.Flags;
import Tokens._;
@@ -38,7 +38,7 @@ import Tokens._;
* (4) Wraps naked case definitions in a match as follows:
* { cases } ==> (x => x.match {cases}), except when already argument to match
*/
-abstract class Syntactic: ParserPhase {
+abstract class Parsers: ParserPhase {
import global._;
import posAssigner.atPos;
@@ -56,7 +56,7 @@ abstract class Syntactic: ParserPhase {
var loopNestingDepth = 0;
object treeBuilder extends TreeBuilder {
- val global: Syntactic.this.global.type = Syntactic.this.global;
+ val global: Parsers.this.global.type = Parsers.this.global;
def freshName(prefix: String): Name = unit.fresh.newName(prefix);
}
import treeBuilder._;
@@ -126,7 +126,7 @@ abstract class Syntactic: ParserPhase {
/////// TOKEN CLASSES //////////////////////////////////////////////////////
def isModifier: boolean = in.token match {
- case ABSTRACT | FINAL | SEALED | PRIVATE | PROTECTED | OVERRIDE => true
+ case ABSTRACT | FINAL | SEALED | PRIVATE | PROTECTED | OVERRIDE | IMPLICIT => true
case _ => false
}
@@ -741,12 +741,13 @@ abstract class Syntactic: ParserPhase {
simpleExpr()
}
- /* SimpleExpr ::= literal
+ /* SimpleExpr ::= new SimpleType [`(' [Exprs] `)'] {`with' SimpleType} [TemplateBody]
+ * | SimpleExpr1
+ * SimpleExpr1 ::= literal
* | xLiteral
* | StableRef
* | `(' [Expr] `)'
* | BlockExpr
- * | new SimpleType [`(' [Exprs] `)'] {`with' SimpleType} [TemplateBody]
* | SimpleExpr `.' Id
* | SimpleExpr TypeArgs
* | SimpleExpr ArgumentExprs
@@ -784,7 +785,7 @@ abstract class Syntactic: ParserPhase {
case LBRACE =>
t = blockExpr()
case NEW =>
- t = atPos(in.skipToken()) {
+ return atPos(in.skipToken()) {
val parents = new ListBuffer[Tree] + simpleType();
var args: List[Tree] = List();
if (in.token == LPAREN) args = argumentExprs();
@@ -1058,6 +1059,8 @@ abstract class Syntactic: ParserPhase {
loop(addMod(mods, Flags.PROTECTED))
case OVERRIDE =>
loop(addMod(mods, Flags.OVERRIDE))
+ case IMPLICIT =>
+ loop(addMod(mods, Flags.IMPLICIT))
case _ =>
mods
}
@@ -1091,48 +1094,60 @@ abstract class Syntactic: ParserPhase {
//////// PARAMETERS //////////////////////////////////////////////////////////
- /** ParamClauses ::= {ParamClause}
- */
- def paramClauses(ofClass: boolean): List[List[ValDef]] = {
- val vds = new ListBuffer[List[ValDef]];
- while (in.token == LPAREN) vds += paramClause(ofClass);
- vds.toList
- }
-
- /** ParamClause ::= `(' [Param {`,' Param}] `)'
- * ClassParamClause ::= `(' [ClassParam {`,' ClassParam}] `)'
- */
- def paramClause(ofClass: boolean): List[ValDef] = {
- accept(LPAREN);
- val params = new ListBuffer[ValDef];
- if (in.token != RPAREN) {
- params += param(ofClass);
- while (in.token == COMMA) {
- in.nextToken(); params += param(ofClass)
- }
- }
- accept(RPAREN);
- params.toList
- }
-
- /** Param ::= Id `:' ParamType
+ /** ParamClauses ::= {`(' [Param {`,' Param}] ')'}
+ * [`(' implicit Param {`,' Param} `)']
+ * Param ::= Id `:' ParamType
+ * ClassParamClauses ::= {`(' [ClassParam {`' ClassParam}] ')'}
+ * [`(' implicit ClassParam {`,' ClassParam} `)']
* ClassParam ::= [[modifiers] val] Param
*/
- def param(ofClass: boolean): ValDef = {
- atPos(in.pos) {
- var mods = Flags.PARAM;
- if (ofClass) {
- mods = modifiers() | Flags.PARAMACCESSOR;
- if (in.token == VAL) in.nextToken()
- else {
- if (mods != Flags.PARAMACCESSOR) accept(VAL);
- mods = mods | Flags.PRIVATE | Flags.LOCAL;
+ def paramClauses(owner: Name, implicitViews: List[Tree], ofCaseClass: boolean): List[List[ValDef]] = {
+ var implicitmod = 0;
+ def param(): ValDef = {
+ atPos(in.pos) {
+ var mods = Flags.PARAM;
+ if (owner.isTypeName) {
+ mods = modifiers() | Flags.PARAMACCESSOR;
+ if (in.token == VAL) in.nextToken()
+ else {
+ if (mods != Flags.PARAMACCESSOR) accept(VAL);
+ if (!ofCaseClass) mods = mods | Flags.PRIVATE | Flags.LOCAL;
+ }
}
+ val name = ident();
+ accept(COLON);
+ ValDef(mods | implicitmod, name, paramType(), EmptyTree)
}
- val name = ident();
- accept(COLON);
- ValDef(mods, name, paramType(), EmptyTree)
}
+ def paramClause(): List[ValDef] = {
+ val params = new ListBuffer[ValDef];
+ if (in.token != RPAREN) {
+ if (in.token == IMPLICIT) {
+ if (!implicitViews.isEmpty)
+ syntaxError("cannot have both view bounds `<%' and implicit parameters", false);
+ in.nextToken();
+ implicitmod = Flags.IMPLICIT
+ }
+ params += param();
+ while (in.token == COMMA) {
+ in.nextToken(); params += param()
+ }
+ }
+ params.toList
+ }
+ val vds = new ListBuffer[List[ValDef]];
+ val pos = in.pos;
+ while (implicitmod == 0 && in.token == LPAREN) {
+ in.nextToken();
+ vds += paramClause();
+ accept(RPAREN);
+ }
+ val result = vds.toList;
+ if (owner == nme.CONSTRUCTOR &&
+ (result.isEmpty || (!result.head.isEmpty &&
+ (result.head.head.mods & Flags.IMPLICIT) != 0)))
+ syntaxError(pos, "auxiliary constructor needs non-implicit parameter list", false);
+ addImplicitViews(result, implicitViews)
}
/** ParamType ::= Type | `=>' Type | Type `*'
@@ -1152,39 +1167,43 @@ abstract class Syntactic: ParserPhase {
}
/** TypeParamClauseOpt ::= [`[' TypeParam {`,' TypeParam} `]']
+ * TypeParam ::= [`+' | `-'] FunTypeParam
* FunTypeParamClauseOpt ::= [`[' FunTypeParam {`,' FunTypeParam} `]']
+ * FunTypeParam ::= Id TypeBounds
*/
- def typeParamClauseOpt(ofClass: boolean): List[AbsTypeDef] = {
+ def typeParamClauseOpt(owner: Name, implicitViews: ListBuffer[Tree]): List[AbsTypeDef] = {
+ def typeParam(): AbsTypeDef = {
+ var mods = Flags.PARAM;
+ if (owner.isTypeName && in.token == IDENTIFIER) {
+ if (in.name == PLUS) {
+ in.nextToken();
+ mods = mods | Flags.COVARIANT;
+ } else if (in.name == MINUS) {
+ in.nextToken();
+ mods = mods | Flags.CONTRAVARIANT;
+ }
+ }
+ val pname = ident();
+ val param = atPos(in.pos) { typeBounds(mods, pname) }
+ if (in.token == VIEWBOUND && (implicitViews != null))
+ implicitViews += atPos(in.skipToken()) {
+ makeFunctionTypeTree(List(Ident(pname.toTypeName)), typ())
+ }
+ param
+ }
val params = new ListBuffer[AbsTypeDef];
if (in.token == LBRACKET) {
in.nextToken();
- params += typeParam(ofClass);
+ params += typeParam();
while (in.token == COMMA) {
in.nextToken();
- params += typeParam(ofClass);
+ params += typeParam();
}
accept(RBRACKET);
}
params.toList
}
- /** TypeParam ::= [`+' | `-'] FunTypeParam
- * FunTypeParam ::= Id TypeBounds
- */
- def typeParam(ofClass: boolean): AbsTypeDef = {
- var mods = Flags.PARAM;
- if (ofClass && in.token == IDENTIFIER) {
- if (in.name == PLUS) {
- in.nextToken();
- mods = mods | Flags.COVARIANT;
- } else if (in.name == MINUS) {
- in.nextToken();
- mods = mods | Flags.CONTRAVARIANT;
- }
- }
- atPos(in.pos) { typeBounds(mods, ident()) }
- }
-
/** TypeBounds ::= [`>:' Type] [`<:' Type]
*/
def typeBounds(mods: int, name: Name): AbsTypeDef = {
@@ -1321,14 +1340,14 @@ abstract class Syntactic: ParserPhase {
} while (in.token == COMMA);
val tp = typedOpt();
val rhs =
- if (tp == EmptyTree || in.token == EQUALS) equalsExpr()
+ if (tp.isEmpty || in.token == EQUALS) equalsExpr()
else {
newmods = newmods | Flags.DEFERRED;
EmptyTree
}
def mkDefs(p: Tree): List[Tree] = {
val trees =
- makePatDef(newmods, if (tp == EmptyTree) p else Typed(p, tp), rhs.duplicate)
+ makePatDef(newmods, if (tp.isEmpty) p else Typed(p, tp), rhs.duplicate)
map atPos(p.pos);
if (rhs == EmptyTree) {
trees match {
@@ -1352,7 +1371,7 @@ abstract class Syntactic: ParserPhase {
lhs += Pair(in.skipToken(), ident())
} while (in.token == COMMA);
val tp = typedOpt();
- val rhs = if (tp == EmptyTree || in.token == EQUALS) {
+ val rhs = if (tp.isEmpty || in.token == EQUALS) {
accept(EQUALS);
if (tp != EmptyTree && in.token == USCORE) {
in.nextToken();
@@ -1368,7 +1387,7 @@ abstract class Syntactic: ParserPhase {
}
/** FunDef ::= FunSig `:' Type `=' Expr
- * | this ParamClause `=' ConstrExpr
+ * | this ParamClause ParamClauses `=' ConstrExpr
* FunDcl ::= FunSig `:' Type
* FunSig ::= id [FunTypeParamClause] ParamClauses
*/
@@ -1376,17 +1395,18 @@ abstract class Syntactic: ParserPhase {
atPos(in.skipToken()) {
if (in.token == THIS) {
in.nextToken();
- val vparams = List(paramClause(false));
+ val vparamss = paramClauses(nme.CONSTRUCTOR, List(), false);
accept(EQUALS);
- DefDef(mods, nme.CONSTRUCTOR, List(), vparams, TypeTree(), constrExpr())
+ DefDef(mods, nme.CONSTRUCTOR, List(), vparamss, TypeTree(), constrExpr())
} else {
var newmods = mods;
val name = ident();
- val tparams = typeParamClauseOpt(false);
- val vparamss = paramClauses(false);
+ val implicitViews = new ListBuffer[Tree];
+ val tparams = typeParamClauseOpt(name, implicitViews);
+ val vparamss = paramClauses(name, implicitViews.toList, false);
val restype = typedOpt();
val rhs =
- if (restype == EmptyTree || in.token == EQUALS) equalsExpr();
+ if (restype.isEmpty || in.token == EQUALS) equalsExpr();
else {
newmods = newmods | Flags.DEFERRED;
EmptyTree
@@ -1425,7 +1445,7 @@ abstract class Syntactic: ParserPhase {
val name = ident().toTypeName;
in.token match {
case LBRACKET =>
- val tparams = typeParamClauseOpt(true);
+ val tparams = typeParamClauseOpt(name, null);
accept(EQUALS);
AliasTypeDef(mods, name, tparams, typ())
case EQUALS =>
@@ -1464,11 +1484,15 @@ abstract class Syntactic: ParserPhase {
def classDef(mods: int): Tree =
atPos(in.skipToken()) {
val name = ident().toTypeName;
- val tparams = typeParamClauseOpt(true);
+ val implicitViews = new ListBuffer[Tree];
+ val tparams = typeParamClauseOpt(name, implicitViews);
if ((mods & Flags.CASE) != 0 && in.token != LPAREN) accept(LPAREN);
- val vparamss = paramClauses(true);
+ val vparamss = paramClauses(name, implicitViews.toList, (mods & Flags.CASE) != 0);
val thistpe = simpleTypedOpt();
- val mods1 = if (vparamss.isEmpty && (mods & ABSTRACT) != 0) mods | Flags.TRAIT else mods;
+ val mods1 = if (vparamss.isEmpty && (mods & Flags.ABSTRACT) != 0) {
+ if (settings.debug.value) System.out.println("is trait: " + name);//debug
+ mods | Flags.TRAIT
+ } else mods;
val template = classTemplate(mods1, vparamss);
ClassDef(mods1, name, tparams, thistpe, template)
}
diff --git a/sources/scala/tools/nsc/ast/parser/Lexical.scala b/sources/scala/tools/nsc/ast/parser/Scanners.scala
index 318ae77395..91da9b67f0 100644..100755
--- a/sources/scala/tools/nsc/ast/parser/Lexical.scala
+++ b/sources/scala/tools/nsc/ast/parser/Scanners.scala
@@ -10,7 +10,7 @@ import scala.tools.util.{Position, SourceFile}
import SourceFile.{LF, FF, CR, SU}
import scala.tools.nsc.util.CharArrayReader;
-abstract class Lexical: ParserPhase {
+abstract class Scanners: ParserPhase {
import global._;
@@ -102,7 +102,7 @@ abstract class Lexical: ParserPhase {
token match {
case ELSE | EXTENDS | WITH | YIELD | CATCH | FINALLY |
COMMA | SEMI | DOT | COLON | EQUALS | ARROW |
- LARROW | SUBTYPE | SUPERTYPE | HASH | AT |
+ LARROW | SUBTYPE | VIEWBOUND | SUPERTYPE | HASH | AT |
RPAREN | RBRACKET | RBRACE =>
case _ =>
if (token == EOF || Position.line(pos) > Position.line(prevpos)) {
@@ -728,6 +728,7 @@ abstract class Lexical: ParserPhase {
enterKeyword("finally", FINALLY);
enterKeyword("for", FOR);
enterKeyword("if", IF);
+ enterKeyword("implicit", IMPLICIT);
enterKeyword("import", IMPORT);
enterKeyword("match", MATCH);
enterKeyword("new", NEW);
@@ -758,6 +759,7 @@ abstract class Lexical: ParserPhase {
enterKeyword("=>", ARROW);
enterKeyword("<-", LARROW);
enterKeyword("<:", SUBTYPE);
+ enterKeyword("<%", VIEWBOUND);
enterKeyword(">:", SUPERTYPE);
enterKeyword("#", HASH);
enterKeyword("@", AT);
diff --git a/sources/scala/tools/nsc/ast/parser/Tokens.scala b/sources/scala/tools/nsc/ast/parser/Tokens.scala
index 1908ee70f1..90d1b7ad7b 100644
--- a/sources/scala/tools/nsc/ast/parser/Tokens.scala
+++ b/sources/scala/tools/nsc/ast/parser/Tokens.scala
@@ -43,14 +43,15 @@ object Tokens {
val PRIVATE = 34;
val PROTECTED = 35;
val OVERRIDE = 36;
- val VAR = 37;
- val DEF = 38;
- val TYPE = 39;
- val EXTENDS = 40;
- val TRUE = 41;
- val FALSE = 42;
- val OBJECT = 43;
- val CLASS = 44;
+ val IMPLICIT = 37;
+ val VAR = 38;
+ val DEF = 39;
+ val TYPE = 40;
+ val EXTENDS = 41;
+ val TRUE = 42;
+ val FALSE = 43;
+ val OBJECT = 44;
+ val CLASS = 45;
val IMPORT = 46;
val PACKAGE = 47;
@@ -75,10 +76,11 @@ object Tokens {
val EQUALS = 66;
val LARROW = 67;
val ARROW = 68;
- val SUBTYPE = 69;
- val SUPERTYPE = 70;
- val HASH = 71;
- val AT = 72;
+ val SUBTYPE = 70;
+ val SUPERTYPE = 71;
+ val HASH = 72;
+ val AT = 73;
+ val VIEWBOUND = 74; //todo: elim
/** parenthesis */
val LPAREN = 90;
diff --git a/sources/scala/tools/nsc/buildnsc b/sources/scala/tools/nsc/buildnsc
new file mode 100755
index 0000000000..65a77944e0
--- /dev/null
+++ b/sources/scala/tools/nsc/buildnsc
@@ -0,0 +1 @@
+scalac -d /tmp/classes *.scala ast/*.scala ast/parser/*.scala symtab/*.scala symtab/classfile/*.scala util/*.scala typechecker/*.scala $*
diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala
index c9561c5e30..bc78fb2ad8 100755
--- a/sources/scala/tools/nsc/symtab/Definitions.scala
+++ b/sources/scala/tools/nsc/symtab/Definitions.scala
@@ -68,16 +68,16 @@ abstract class Definitions: SymbolTable {
def tupleType(elems: List[Type]) = {
val sym = TupleClass(elems.length);
- typeRef(sym.info.prefix, sym, elems)
+ typeRef(sym.typeConstructor.prefix, sym, elems)
}
def functionType(formals: List[Type], restpe: Type) = {
val sym = FunctionClass(formals.length);
- typeRef(sym.info.prefix, sym, formals ::: List(restpe))
+ typeRef(sym.typeConstructor.prefix, sym, formals ::: List(restpe))
}
def seqType(arg: Type) =
- typeRef(SeqClass.info.prefix, SeqClass, List(arg));
+ typeRef(SeqClass.typeConstructor.prefix, SeqClass, List(arg));
// members of class scala.Any
var Any_== : Symbol = _;
@@ -87,9 +87,12 @@ abstract class Definitions: SymbolTable {
var Any_toString : Symbol = _;
var Any_isInstanceOf: Symbol = _;
var Any_asInstanceOf: Symbol = _;
+ var Any_isInstanceOfErased: Symbol = _;
+ var Any_asInstanceOfErased: Symbol = _;
// members of class java.lang.{Object, String}
var Object_eq : Symbol = _;
+ var Object_ne : Symbol = _;
var Object_synchronized: Symbol = _;
var String_+ : Symbol = _;
@@ -138,9 +141,18 @@ abstract class Definitions: SymbolTable {
msym
}
+ private def newMethod(owner: Symbol, name: Name, formals: List[Type], restpe: Type): Symbol =
+ newMethod(owner, name).setInfo(MethodType(formals, restpe));
+
+ private def newPolyMethod(owner: Symbol, name: Name, tcon: Symbol => Type): Symbol = {
+ val msym = newMethod(owner, name);
+ val tparam = newTypeParam(msym, 0);
+ msym.setInfo(PolyType(List(tparam), tcon(tparam)))
+ }
+
private def newTypeParam(owner: Symbol, index: int): Symbol =
owner.newTypeParameter(Position.NOPOS, "T" + index)
- .setInfo(TypeBounds(AllClass.tpe, AnyClass.tpe));
+ .setInfo(TypeBounds(AllClass.typeConstructor, AnyClass.typeConstructor));
def init = {
RootClass =
@@ -165,10 +177,10 @@ abstract class Definitions: SymbolTable {
AnyValClass = getClass("scala.AnyVal");
ObjectClass = getClass("java.lang.Object");
- AnyRefClass = newAlias(ScalaPackageClass, "AnyRef", ObjectClass.tpe);
+ AnyRefClass = newAlias(ScalaPackageClass, "AnyRef", ObjectClass.typeConstructor);
- AllRefClass = newClass(ScalaPackageClass, "AllRef", List(AnyRefClass.tpe));
- AllClass = newClass(ScalaPackageClass, "All", List(AnyClass.tpe));
+ AllRefClass = newClass(ScalaPackageClass, "AllRef", List(AnyRefClass.typeConstructor));
+ AllClass = newClass(ScalaPackageClass, "All", List(AnyClass.typeConstructor));
StringClass = getClass("java.lang.String");
ThrowableClass = getClass("java.lang.Throwable");
@@ -194,7 +206,6 @@ abstract class Definitions: SymbolTable {
SeqClass = getClass("scala.Seq");
ListClass = getClass("scala.List");
ArrayClass = getClass("scala.Array");
- System.out.println("array class: " + ArrayClass.tpe);//debug
TypeClass = getClass("scala.Type");
PredefModule = getModule("scala.Predef");
ConsoleModule = getModule("scala.Console");
@@ -207,53 +218,45 @@ abstract class Definitions: SymbolTable {
PolyType(
List(tparam),
ClassInfoType(
- List(typeRef(SeqClass.tpe.prefix, SeqClass, List(tparam.typeConstructor))),
+ List(typeRef(SeqClass.typeConstructor.prefix, SeqClass, List(tparam.typeConstructor))),
new Scope(),
RepeatedParamClass)))
}
// members of class scala.Any
- Any_== = newMethod(AnyClass, "==")
- .setInfo(MethodType(List(AnyClass.tpe), BooleanClass.tpe))
- .setFlag(FINAL);
- Any_!= = newMethod(AnyClass, "!=")
- .setInfo(MethodType(List(AnyClass.tpe), BooleanClass.tpe))
- .setFlag(FINAL);
- Any_equals = newMethod(AnyClass, "equals")
- .setInfo(MethodType(List(AnyClass.tpe), BooleanClass.tpe));
- Any_hashCode = newMethod(AnyClass, "hashCode")
- .setInfo(MethodType(List(), IntClass.tpe));
- Any_toString = newMethod(AnyClass, "toString")
- .setInfo(MethodType(List(), StringClass.tpe));
- Any_isInstanceOf = newMethod(AnyClass, "isInstanceOf")
- .setFlag(FINAL);
- { val tparam = newTypeParam(Any_isInstanceOf, 0);
- Any_isInstanceOf.setInfo(PolyType(List(tparam), BooleanClass.tpe));
- }
- Any_asInstanceOf = newMethod(AnyClass, "asInstanceOf")
- .setFlag(FINAL);
- { val tparam = newTypeParam(Any_asInstanceOf, 0);
- Any_asInstanceOf.setInfo(PolyType(List(tparam), tparam.typeConstructor));
- }
+ Any_== = newMethod(
+ AnyClass, "==", List(AnyClass.typeConstructor), BooleanClass.typeConstructor) setFlag FINAL;
+ Any_!= = newMethod(
+ AnyClass, "!=", List(AnyClass.typeConstructor), BooleanClass.typeConstructor) setFlag FINAL;
+ Any_equals = newMethod(
+ AnyClass, "equals", List(AnyClass.typeConstructor), BooleanClass.typeConstructor);
+ Any_hashCode = newMethod(
+ AnyClass, "hashCode", List(), IntClass.typeConstructor);
+ Any_toString = newMethod(
+ AnyClass, "toString", List(), StringClass.typeConstructor);
+
+ Any_isInstanceOf = newPolyMethod(
+ AnyClass, "isInstanceOf", tparam => BooleanClass.typeConstructor) setFlag FINAL;
+ Any_asInstanceOf = newPolyMethod(
+ AnyClass, "asInstanceOf", tparam => tparam.typeConstructor) setFlag FINAL;
+ Any_isInstanceOfErased = newPolyMethod(
+ AnyClass, "isInstanceOf$erased", tparam => BooleanClass.typeConstructor) setFlag FINAL;
+ Any_asInstanceOfErased = newPolyMethod(
+ AnyClass, "asInstanceOf$erased", tparam => tparam.typeConstructor) setFlag FINAL;
// members of class java.lang.{Object, String}
- Object_eq = newMethod(ObjectClass, "eq")
- .setInfo(MethodType(List(AnyRefClass.tpe), BooleanClass.tpe))
- .setFlag(FINAL);
- Object_synchronized = newMethod(ObjectClass, "synchronized")
- .setFlag(FINAL);
- { val tparam = newTypeParam(Object_synchronized, 0);
- Object_synchronized.setInfo(
- PolyType(
- List(tparam),
- MethodType(List(tparam.typeConstructor), tparam.typeConstructor)));
- }
- String_+ = newMethod(StringClass, "+")
- .setInfo(MethodType(List(AnyClass.tpe), StringClass.tpe))
- .setFlag(FINAL);
+ Object_eq = newMethod(
+ ObjectClass, "eq", List(AnyRefClass.typeConstructor), BooleanClass.typeConstructor) setFlag FINAL;
+ Object_ne = newMethod(
+ ObjectClass, "ne", List(AnyRefClass.typeConstructor), BooleanClass.typeConstructor) setFlag FINAL;
+ Object_synchronized = newPolyMethod(
+ ObjectClass, "synchronized", tparam => MethodType(List(tparam.typeConstructor), tparam.typeConstructor)) setFlag FINAL;
+
+ String_+ = newMethod(
+ StringClass, "+", List(AnyClass.typeConstructor), StringClass.typeConstructor) setFlag FINAL;
// pattern wildcard
- PatternWildcard = NoSymbol.newValue(Position.NOPOS, "_").setInfo(AllClass.tpe)
+ PatternWildcard = NoSymbol.newValue(Position.NOPOS, "_").setInfo(AllClass.typeConstructor)
}
}
}
diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala
index 776adab42e..83c8a5c269 100644
--- a/sources/scala/tools/nsc/symtab/Flags.scala
+++ b/sources/scala/tools/nsc/symtab/Flags.scala
@@ -8,7 +8,7 @@ package scala.tools.nsc.symtab;
object Flags {
// modifiers
- val DEFERRED = 0x00000001; // was `abstract' for members
+ val IMPLICIT = 0x00000001;
val FINAL = 0x00000002;
val PRIVATE = 0x00000004;
val PROTECTED = 0x00000008;
@@ -20,9 +20,9 @@ object Flags {
// with abstract override.
// Note difference to DEFERRED!
- val METHOD = 0x00000100; // a def parameter
- val TRAIT = 0x00000200; // a trait
- val JAVA = 0x00000400; // symbol was defined by a Java class
+ val DEFERRED = 0x00000100; // was `abstract' for members
+ val METHOD = 0x00000200; // a def parameter
+ val TRAIT = 0x00000400; // a trait
val MODULE = 0x00000800; // symbol is module or class implementing a module
val MUTABLE = 0x00001000; // symbol is a mutable variable.
@@ -36,11 +36,10 @@ object Flags {
val LOCAL = 0x00080000; // symbol is local to current class.
// pre: PRIVATE is also set
- val SYNTHETIC = 0x00100000; // symbol is compiler-generated
- val STABLE = 0x00200000; // functions that are assumed to be stable
+ val JAVA = 0x00100000; // symbol was defined by a Java class
+ val SYNTHETIC = 0x00200000; // symbol is compiler-generated
+ val STABLE = 0x00400000; // functions that are assumed to be stable
// (typically, access methods for valdefs)
- val INITIALIZED = 0x00400000; // symbol's definition is complete
- val LOCKED = 0x00800000; // temporary flag to catch cyclic dependencies
val ACCESSED = 0x01000000; // symbol was accessed at least once
val SELECTOR = 0x02000000; // symbol was used as selector in Select
@@ -61,25 +60,31 @@ object Flags {
val OVERLOADED = 0x400000000l; // symbol is overloaded
val TRANS_FLAG = 0x800000000l; // transient flag guaranteed to be reset after each phase.
- val LIFTED = TRANS_FLAG; // transient flag for lambdalift
- val INCONSTRUCTOR = TRANS_FLAG; // transient flag for analyzer
+ val LIFTED = TRANS_FLAG; // transient flag for lambdalift
+ val INCONSTRUCTOR = TRANS_FLAG; // transient flag for analyzer
- // masks
- val SOURCEFLAGS = 0x00077777; // these modifiers can be set in source programs.
- val GENFLAGS = // these modifiers can be in generated trees
- SOURCEFLAGS | SYNTHETIC | STABLE | ACCESSOR | ACCESS_METHOD | PARAMACCESSOR | LABEL | BRIDGE;
- val EXPLICITFLAGS = // these modifiers can be set explicitly in source programs.
- PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED | OVERRIDE | CASE;
+ val INITIALIZED = 0x1000000000l; // symbol's definition is complete
+ val LOCKED = 0x2000000000l; // temporary flag to catch cyclic dependencies
- val ACCESSFLAGS = PRIVATE | PROTECTED;
- val VARIANCES = COVARIANT | CONTRAVARIANT;
- val CONSTRFLAGS = JAVA;
- val PICKLEDFLAGS = 0x77777777 & ~LOCKED & ~INITIALIZED;
+ // masks
+ val SourceFlags = 0x001FFFFF; // these modifiers can be set in source programs.
+ val ExplicitFlags = // these modifiers can be set explicitly in source programs.
+ PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED | OVERRIDE | CASE | IMPLICIT;
+ val PrintableFlags = // these modifiers appear in TreePrinter output.
+ ExplicitFlags | LOCAL | SYNTHETIC | STABLE | ACCESSOR |
+ ACCESS_METHOD | PARAMACCESSOR | LABEL | BRIDGE;
+ val GenFlags = // these modifiers can be in generated trees
+ SourceFlags | PrintableFlags;
+
+ val AccessFlags = PRIVATE | PROTECTED;
+ val Variances = COVARIANT | CONTRAVARIANT;
+ val ConstrFlags = JAVA;
+ val PickledFlags = 0xFFFFFFFF & ~LOCKED & ~INITIALIZED;
/** Module flags inherited by their module-class */
- val MODULE2CLASSFLAGS = ACCESSFLAGS | PACKAGE;
+ val ModuleToClassFlags = AccessFlags | PACKAGE;
- def flags2mods(flags: long): int = flags.asInstanceOf[int] & GENFLAGS;
+ def flags2mods(flags: long): int = flags.asInstanceOf[int] & GenFlags;
def flagsToString(flags: long): String =
List.range(0, 63)
@@ -91,8 +96,10 @@ object Flags {
else if (flag == IS_ERROR) "<is_error>"
else if (flag == OVERLOADED) "<overloaded>"
else if (flag == TRANS_FLAG) "<transient>"
+ else if (flag == INITIALIZED) "<initialized>"
+ else if (flag == LOCKED) "<locked>"
else flag.asInstanceOf[int] match {
- case DEFERRED => "<deferred>"
+ case IMPLICIT => "implicit"
case FINAL => "final"
case PRIVATE => "private"
case PROTECTED => "protected"
@@ -102,9 +109,9 @@ object Flags {
case CASE => "case"
case ABSTRACT => "abstract"
+ case DEFERRED => "<deferred>"
case METHOD => "<method>"
case TRAIT => "<trait>"
- case JAVA => "<java>"
case MODULE => "<module>"
case MUTABLE => "<mutable>"
@@ -117,14 +124,12 @@ object Flags {
case ABSOVERRIDE => "<absoverride>"
case LOCAL => "<local>"
+ case JAVA => "<java>"
case SYNTHETIC => "<synthetic>"
case STABLE => "<stable>"
- case INITIALIZED => "<initialized>"
- case LOCKED => "<locked>"
case ACCESSED => "<accessed>"
case SELECTOR => "<selector>"
-
case CAPTURED => "<captured>"
case ACCESSOR => "<accessor>"
diff --git a/sources/scala/tools/nsc/symtab/Scopes.scala b/sources/scala/tools/nsc/symtab/Scopes.scala
index d1628d7814..c9432222df 100755
--- a/sources/scala/tools/nsc/symtab/Scopes.scala
+++ b/sources/scala/tools/nsc/symtab/Scopes.scala
@@ -195,7 +195,7 @@ abstract class Scopes: SymbolTable {
if (elemsCache == null) {
elemsCache = Nil;
var e = elems;
- while (e != null) {
+ while (e != null && e.owner == this) {
elemsCache = e.sym :: elemsCache;
e = e.next
}
@@ -207,8 +207,10 @@ abstract class Scopes: SymbolTable {
*/
def elements: Iterator[Symbol] = toList.elements;
- override def toString(): String =
- toList.map(.defString).mkString("{\n ", ";\n ", "\n}");
+ def mkString(start: String, sep: String, end: String) =
+ toList.map(.defString).mkString(start, sep, end);
+
+ override def toString(): String = mkString("{\n ", ";\n ", "\n}");
/** Return the nesting level of this scope, i.e. the number of times this scope
* was nested in another */
diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala
index 2c3603dbaa..8e8ebdb0fe 100755
--- a/sources/scala/tools/nsc/symtab/StdNames.scala
+++ b/sources/scala/tools/nsc/symtab/StdNames.scala
@@ -106,10 +106,12 @@ abstract class StdNames: SymbolTable {
val apply = newTermName("apply");
val array = newTermName("array");
val asInstanceOf = newTermName("asInstanceOf");
+ val asInstanceOfErased = newTermName("asInstanceOf$erased");
val box = newTermName("box");
val checkCastability = newTermName("checkCastability");
val coerce = newTermName("coerce");
val defaultValue = newTermName("defaultValue");
+ val dummy = newTermName("$dummy");
val elem = newTermName("elem");
val elements = newTermName("elements");
val fail = newTermName("fail");
@@ -124,6 +126,7 @@ abstract class StdNames: SymbolTable {
val hasNext = newTermName("hasNext");
val head = newTermName("head");
val isInstanceOf = newTermName("isInstanceOf");
+ val isInstanceOfErased = newTermName("isInstanceOf$erased");
val isDefinedAt = newTermName("isDefinedAt");
val isEmpty = newTermName("isEmpty");
val java = newTermName("java");
diff --git a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
index 7e69107d45..af05d2fcf1 100755
--- a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -24,18 +24,30 @@ abstract class SymbolLoaders {
* name of file loaded for completion as a result.
* Can throw an IOException on error.
*/
- class SymbolLoader(doComplete: Symbol => String) extends LazyType {
+ abstract class SymbolLoader(file: AbstractFile) extends LazyType {
+ /** Load source or class file for `root', return */
+ protected def doComplete(root: Symbol): unit;
+ /** The kind of file that's processed by this loader */
+ protected def kindString: String;
private var ok = false;
+ private def setSource(sym: Symbol): unit = sym match {
+ case clazz: ClassSymbol => clazz.sourceFile = file;
+ case _ =>
+ }
override def complete(root: Symbol): unit = {
try {
val start = System.currentTimeMillis();
val currentphase = phase;
phase = firstPhase;
- val source = doComplete(root);
+ doComplete(root);
phase = currentphase;
+ def source = kindString + " " + file;
informTime("loaded " + source, start);
- if (root.rawInfo != this) ok = true
- else error(source + " does not define " + root)
+ if (root.rawInfo != this) {
+ ok = true;
+ setSource(root.linkedModule);
+ setSource(root.linkedClass);
+ } else error(source + " does not define " + root)
} catch {
case ex: IOException =>
if (settings.debug.value) ex.printStackTrace();
@@ -57,9 +69,8 @@ abstract class SymbolLoaders {
/** Load contents of a package
*/
- def packageLoader(directory: AbstractFile): SymbolLoader =
- new SymbolLoader(root => {
- if (settings.debug.value) System.out.println("loading " + root);
+ class PackageLoader(directory: AbstractFile) extends SymbolLoader(directory) {
+ protected def doComplete(root: Symbol): unit = {
assert(root.isPackageClass, root);
root.setInfo(new PackageClassInfoType(new Scope(), root));
@@ -80,8 +91,8 @@ abstract class SymbolLoaders {
module.moduleClass.setInfo(errorLoader);
owner.info.decls.enter(clazz);
owner.info.decls.enter(module);
- assert(clazz.linkedModule == module, "" + module + module.hasFlag(MODULE));
- assert(module.linkedClass == clazz);
+ assert(clazz.linkedModule == module, module);
+ assert(module.linkedClass == clazz, clazz);
}
val sources = new HashMap[String, AbstractFile];
@@ -108,25 +119,26 @@ abstract class SymbolLoaders {
for (val Pair(name, sfile) <- sources.elements) {
classes.get(name) match {
case Some(cfile) if (cfile.lastModified() >= sfile.lastModified()) => {}
- case _ => enterClassAndModule(name, sourcefileLoader(sfile));
+ case _ => enterClassAndModule(name, new SourcefileLoader(sfile));
}
}
for (val Pair(name, cfile) <- classes.elements) {
sources.get(name) match {
case Some(sfile) if (sfile.lastModified() > cfile.lastModified()) => {}
case _ =>
- val loader = if (cfile.getName().endsWith(".symbl")) symblfileLoader(cfile)
- else classfileLoader(cfile);
+ val loader =
+ if (cfile.getName().endsWith(".symbl")) new SymblfileLoader(cfile)
+ else new ClassfileLoader(cfile);
enterClassAndModule(name, loader)
}
}
for (val Pair(name, file) <- packages.elements) {
if (!sources.contains(name) && !classes.contains(name))
- enterPackage(name, packageLoader(file));
+ enterPackage(name, new PackageLoader(file));
}
-
- "directory path '" + directory + "'"
- });
+ }
+ protected def kindString: String = "directory path"
+ }
private object classfileParser extends ClassfileParser {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global;
@@ -136,26 +148,28 @@ abstract class SymbolLoaders {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global;
}
- def classfileLoader(file: AbstractFile) =
- new SymbolLoader(root => {
- classfileParser.parse(file, root);
- "class file '" + file + "'";
- });
-
- def symblfileLoader(file: AbstractFile) =
- new SymbolLoader(root => {
- symblfileParser.parse(file, root);
- "symbl file '" + file + "'";
- });
-
- def sourcefileLoader(file: AbstractFile) =
- new SymbolLoader(root => {
- global.compileLate(file);
- "source file '" + file + "'";
- });
-
- val errorLoader =
- new SymbolLoader(root => {
+ abstract class ClassSymbolLoader(file: AbstractFile) extends SymbolLoader(file) {
+ override def completeLoad(root: Symbol): unit = complete(root);
+ }
+
+ class ClassfileLoader(file: AbstractFile) extends ClassSymbolLoader(file) {
+ protected def doComplete(root: Symbol): unit = classfileParser.parse(file, root);
+ protected def kindString: String = "class file";
+ }
+
+ class SymblfileLoader(file: AbstractFile) extends ClassSymbolLoader(file) {
+ protected def doComplete(root: Symbol): unit = symblfileParser.parse(file, root);
+ protected def kindString: String = "symbl file";
+ }
+
+ class SourcefileLoader(file: AbstractFile) extends ClassSymbolLoader(file) {
+ protected def doComplete(root: Symbol): unit = global.compileLate(file);
+ protected def kindString: String = "source file";
+ }
+
+ object errorLoader extends SymbolLoader(null) {
+ protected def doComplete(root: Symbol): unit =
throw new Error(" loading " + root + " without loading module first");
- });
+ protected def kindString: String = "";
+ }
}
diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala
index 7d87f7e552..36e03cf808 100755
--- a/sources/scala/tools/nsc/symtab/Symbols.scala
+++ b/sources/scala/tools/nsc/symtab/Symbols.scala
@@ -5,7 +5,7 @@
// $Id$
package scala.tools.nsc.symtab;
-import scala.tools.util.Position;
+import scala.tools.util.{AbstractFile, Position}
import Flags._;
abstract class Symbols: SymbolTable {
@@ -111,6 +111,7 @@ abstract class Symbols: SymbolTable {
final def isModuleClass = isClass && hasFlag(MODULE);
final def isPackageClass = isClass && hasFlag(PACKAGE);
final def isRoot = isPackageClass && name == nme.ROOT.toTypeName;
+ final def isEmptyPackage = isPackage && name == nme.EMPTY_PACKAGE_NAME;
final def isEmptyPackageClass = isPackageClass && name == nme.EMPTY_PACKAGE_NAME.toTypeName;
/** Does this symbol denote a stable value? */
@@ -168,7 +169,7 @@ abstract class Symbols: SymbolTable {
final def resetFlag(mask: long): this.type = { rawflags = rawflags & ~mask; this }
final def getFlag(mask: long): long = rawflags & mask;
final def hasFlag(mask: long): boolean = (rawflags & mask) != 0;
- final def resetFlags: unit = { rawflags = rawflags & SOURCEFLAGS }
+ final def resetFlags: unit = { rawflags = rawflags & SourceFlags }
// Info and Type -------------------------------------------------------------------
@@ -187,7 +188,7 @@ abstract class Symbols: SymbolTable {
final def info: Type = {
var cnt = 0;
while ((rawflags & INITIALIZED) == 0) {
- assert(infos != null, "infos null for " + this.name + " " + (this == definitions.EmptyPackageClass));//debug
+ assert(infos != null, this.name);
val tp = infos.info;
if ((rawflags & LOCKED) != 0) {
setInfo(ErrorType);
@@ -203,7 +204,7 @@ abstract class Symbols: SymbolTable {
cnt = cnt + 1;
// allow for two completions:
// one: sourceCompleter to LazyType, two: LazyType to completed type
- if (cnt == 2) throw new Error("no progress in completing " + this + ":" + tp);
+ if (cnt == 3) throw new Error("no progress in completing " + this + ":" + tp);
}
rawInfo
}
@@ -212,11 +213,9 @@ abstract class Symbols: SymbolTable {
def setInfo(info: Type): this.type = {
infos = new TypeHistory(phase, info, null);
limit = phase;
- assert(info != null, "setInfo(null) for " + name + " at phase " + phase);//debug
+ assert(info != null);
rawflags = if (info.isComplete) rawflags | INITIALIZED & ~LOCKED;
else rawflags & ~INITIALIZED & ~LOCKED;
- if (info.isInstanceOf[MethodType] || info.isInstanceOf[PolyType])
- assert(isClass || hasFlag(METHOD));
this
}
@@ -248,7 +247,7 @@ abstract class Symbols: SymbolTable {
phase = current;
limit = current;
}
- assert(infos != null, name.toString() + " " + limit + " " + phase);//debug
+ assert(infos != null/*, name.toString() + " " + limit + " " + phase*/);
infos.info
} else {
var infos = this.infos;
@@ -278,7 +277,15 @@ abstract class Symbols: SymbolTable {
def typeConstructor: Type = throw new Error("typeConstructor inapplicable for " + this);
/** The type parameters of this symbol */
- def typeParams: List[Symbol] = rawInfo.typeParams;
+ def typeParams: List[Symbol] = {
+/*
+ if (!hasFlag(MODULE)) {
+ System.out.println("complete load " + this);
+ rawInfo.completeLoad(this);
+ }
+*/
+ rawInfo.typeParams
+ }
/** Reset symbol to initial state
*/
@@ -337,7 +344,7 @@ abstract class Symbols: SymbolTable {
def suchThat(cond: Symbol => boolean): Symbol = {
val result = filter(cond);
- assert(!result.hasFlag(OVERLOADED));
+ assert(!result.hasFlag(OVERLOADED)/*, result.alternatives*/);
result
}
@@ -412,10 +419,11 @@ abstract class Symbols: SymbolTable {
sym => (sym hasFlag MODULE) && (sym.rawInfo != NoType));
else NoSymbol;
- /** For a module its linked class, for a class its linked module, NoSymbol otherwise */
+ /** For a module its linked class, for a class its linked module or case factory otherwise */
final def linkedSym: Symbol =
- if (isModule) linkedClass
- else if (isClass) linkedModule
+ if (isTerm) linkedClass
+ else if (isClass && owner.isPackageClass)
+ owner.info.decl(name.toTermName).suchThat(sym => sym.rawInfo != NoType)
else NoSymbol;
/** The module corresponding to this module class (note that this
@@ -554,7 +562,7 @@ abstract class Symbols: SymbolTable {
/** String representation of symbol's definition */
final def defString: String =
- compose(List(flagsToString(flags & EXPLICITFLAGS),
+ compose(List(flagsToString(flags & ExplicitFlags),
keyString,
varianceString + nameString,
infoString(rawInfo)));
@@ -597,7 +605,7 @@ abstract class Symbols: SymbolTable {
tpeCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType,
this, typeParams map (.tpe));
}
- assert(tpeCache != null, "" + this + " " + phase);
+ assert(tpeCache != null/*, "" + this + " " + phase*/);
tpeCache
}
override def typeConstructor: Type = {
@@ -623,7 +631,7 @@ abstract class Symbols: SymbolTable {
/** A class for class symbols */
class ClassSymbol(initOwner: Symbol, initPos: int, initName: Name)
extends TypeSymbol(initOwner, initPos, initName) {
- var sourceFile: String = null;
+ var sourceFile: AbstractFile = null;
private var thissym: Symbol = this;
override def isClass: boolean = true;
override def reset(completer: Type): unit = {
@@ -666,7 +674,7 @@ abstract class Symbols: SymbolTable {
* Note: Not all module classes are of this type; when unpickled, we get plain class symbols!
*/
class ModuleClassSymbol(module: ModuleSymbol) extends ClassSymbol(module.owner, module.pos, module.name.toTypeName) {
- setFlag(module.getFlag(MODULE2CLASSFLAGS) | MODULE | FINAL);
+ setFlag(module.getFlag(ModuleToClassFlags) | MODULE | FINAL);
override def sourceModule = module;
}
diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala
index a693da77a5..250a85f639 100755
--- a/sources/scala/tools/nsc/symtab/Types.scala
+++ b/sources/scala/tools/nsc/symtab/Types.scala
@@ -129,18 +129,21 @@ abstract class Types: SymbolTable {
* Members appear in linearization order of their owners.
* Members with the same owner appear in reverse order of their declarations.
*/
- def members: List[Symbol] = findMember(nme.ANYNAME, 0).alternatives;
+ def members: List[Symbol] = findMember(nme.ANYNAME, 0, 0).alternatives;
/** A list of all non-private members of this type (defined or inherited) */
- def nonPrivateMembers: List[Symbol] = findMember(nme.ANYNAME, PRIVATE).alternatives;
+ def nonPrivateMembers: List[Symbol] = findMember(nme.ANYNAME, PRIVATE, 0).alternatives;
+
+ /** A list of all implicit symbols of this type (defined or inherited) */
+ def implicitMembers: List[Symbol] = findMember(nme.ANYNAME, 0, IMPLICIT).alternatives;
/** The member with given name,
* an OverloadedSymbol if several exist, NoSymbol if none exist */
- def member(name: Name): Symbol = findMember(name, 0);
+ def member(name: Name): Symbol = findMember(name, 0, 0);
/** The non-private member with given name,
* an OverloadedSymbol if several exist, NoSymbol if none exist */
- def nonPrivateMember(name: Name): Symbol = findMember(name, PRIVATE);
+ def nonPrivateMember(name: Name): Symbol = findMember(name, PRIVATE, 0);
/** The least type instance of given class which is a supertype
* of this type */
@@ -159,10 +162,8 @@ abstract class Types: SymbolTable {
sym.info.asSeenFrom(this, sym.owner);
/** The type of `sym', seen as a member of this type. */
- def memberType(sym: Symbol): Type = {
- assert(sym.tpe != null, sym);//debug
+ def memberType(sym: Symbol): Type =
sym.tpe.asSeenFrom(this, sym.owner);
- }
/** Substitute types `to' for occurrences of references to symbols `from'
* in this type. */
@@ -288,6 +289,9 @@ abstract class Types: SymbolTable {
/** If this is a lazy type, assign a new type to `sym'. */
def complete(sym: Symbol): unit = {}
+ /** If this is a symbol loader type, assign the loaded type to `sym'. */
+ def completeLoad(sym: Symbol): unit = {}
+
private def findDecl(name: Name, excludedFlags: int): Symbol = {
var alts: List[Symbol] = List();
var sym: Symbol = NoSymbol;
@@ -306,7 +310,7 @@ abstract class Types: SymbolTable {
else baseClasses.head.newOverloaded(this, alts)
}
- protected def findMember(name: Name, excludedFlags: int): Symbol = {
+ protected def findMember(name: Name, excludedFlags: int, requiredFlags: int): Symbol = {
//System.out.println("find member " + name.decode + " in " + this.baseClasses);//DEBUG
var members: Scope = null;
var member: Symbol = NoSymbol;
@@ -321,26 +325,30 @@ abstract class Types: SymbolTable {
var entry = if (name == nme.ANYNAME) decls.elems else decls lookupEntry name;
while (entry != null) {
val sym = entry.sym;
- val excl = sym.getFlag(excluded);
- if (excl == 0) {
- if (name.isTypeName) {
- return sym
- } else if (member == NoSymbol) {
- member = sym
- } else if (members == null) {
- if (member.name != sym.name || !memberType(member).matches(memberType(sym)))
- members = new Scope(List(member, sym))
- } else {
- var prevEntry = members lookupEntry sym.name;
- while (prevEntry != null &&
- !(memberType(prevEntry.sym) matches memberType(sym)))
- prevEntry = members lookupNextEntry prevEntry;
- if (prevEntry == null)
- members enter sym
- }
- } else if (excl == DEFERRED) {
- continue = true;
- }
+ if (sym.getFlag(requiredFlags) == requiredFlags) {
+ val excl = sym.getFlag(excluded);
+ if (excl == 0) {
+ if (name.isTypeName) {
+ return sym
+ } else if (member == NoSymbol) {
+ member = sym
+ } else if (members == null) {
+ if (member.name != sym.name ||
+ member != sym && !memberType(member).matches(memberType(sym)))
+ members = new Scope(List(member, sym))
+ } else {
+ var prevEntry = members lookupEntry sym.name;
+ while (prevEntry != null && prevEntry.sym != sym &&
+ !(memberType(prevEntry.sym) matches memberType(sym)))
+ prevEntry = members lookupNextEntry prevEntry;
+ if (prevEntry == null) {
+ members enter sym;
+ }
+ }
+ } else if (excl == DEFERRED) {
+ continue = true;
+ }
+ }
entry = if (name == nme.ANYNAME) entry.next else decls lookupNextEntry entry
} // while (entry != null)
excluded = excluded | PRIVATE
@@ -384,7 +392,7 @@ abstract class Types: SymbolTable {
// todo see whether we can do without
override def isError: boolean = true;
override def decls: Scope = new ErrorScope(NoSymbol);
- override def findMember(name: Name, excludedFlags: int): Symbol = decls lookup name;
+ override def findMember(name: Name, excludedFlags: int, requiredFlags: int): Symbol = decls lookup name;
override def baseType(clazz: Symbol): Type = this;
override def toString(): String = "<error>";
override def narrow: Type = this;
@@ -437,7 +445,9 @@ abstract class Types: SymbolTable {
}
override def symbol = sym;
override def prefix: Type = pre;
- override def prefixString: String = pre.prefixString + sym.nameString + ".";
+ override def prefixString: String =
+ if (sym.isEmptyPackage && !settings.debug.value) ""
+ else pre.prefixString + sym.nameString + ".";
}
/** A class for the bounds of abstract types and type parameters
@@ -473,7 +483,7 @@ abstract class Types: SymbolTable {
validClosure = phase;
closureCache = null;
closureCache = computeClosure;
- System.out.println("closure(" + symbol + ") = " + List.fromArray(closureCache));//debug
+ //System.out.println("closure(" + symbol + ") = " + List.fromArray(closureCache));//DEBUG
}
if (closureCache == null)
throw new TypeError("illegal cyclic reference involving " + symbol);
@@ -519,7 +529,7 @@ abstract class Types: SymbolTable {
if (parents.isEmpty) this else parents.head.erasure;
override def toString(): String =
- parents.mkString("", " with ", "") + decls.toString()
+ parents.mkString("", " with ", "") + decls.mkString("{", "; ", "}")
}
/** A class representing intersection types with refinements of the form
@@ -590,8 +600,7 @@ abstract class Types: SymbolTable {
if (sym.isAbstractType) addClosure(this, transform(bounds.hi).closure)
else {
val result = transform(sym.info.closure);
- System.out.println("closure[" + this + "] = " +
- List.fromArray(sym.info.closure) + " => " + result);
+ //System.out.println("closure[" + this + "] = " + List.fromArray(sym.info.closure) + " => " + result);//DEBUG
result
}
@@ -630,7 +639,9 @@ abstract class Types: SymbolTable {
override def toString(): String = paramTypes.mkString("(", ",", ")") + resultType;
}
- class ImplicitMethodType(pts: List[Type], rt: Type) extends MethodType(pts, rt);
+ class ImplicitMethodType(pts: List[Type], rt: Type) extends MethodType(pts, rt) {
+ override def toString(): String = paramTypes.mkString("(implicit ", ",", ")") + resultType;
+ }
/** A class representing a polymorphic type or, if tparams.length == 0,
* a parameterless method type.
@@ -653,7 +664,6 @@ abstract class Types: SymbolTable {
override def toString(): String =
(if (typeParams.isEmpty) "=> " else typeParams.mkString("[", ",", "]")) + resultType;
-
override def cloneInfo(owner: Symbol) = {
val tparams = typeParams map (.cloneSymbol(owner));
for (val tparam <- tparams)
@@ -721,7 +731,7 @@ abstract class Types: SymbolTable {
if (sym1.hasFlag(LOCKED))
throw new TypeError("illegal cyclic reference involving " + sym1);
sym1.setFlag(LOCKED);
- val result = sym1.info.asSeenFrom(pre, sym1.owner).subst(sym1.typeParams, args);
+ val result = sym1.info.resultType.asSeenFrom(pre, sym1.owner).subst(sym1.typeParams, args);
sym1.resetFlag(LOCKED);
result
} else {
@@ -821,6 +831,7 @@ abstract class Types: SymbolTable {
val paramtypes1 = paramtypes mapConserve this;
val result1 = this(result);
if ((paramtypes1 eq paramtypes) && (result1 eq result)) tp
+ else if (tp.isInstanceOf[ImplicitMethodType]) new ImplicitMethodType(paramtypes1, result1)
else MethodType(paramtypes1, result1)
case PolyType(tparams, result) =>
val tparams1 = mapOver(tparams);
@@ -891,7 +902,7 @@ abstract class Types: SymbolTable {
if (symclazz == clazz && (pre.widen.symbol isSubClass symclazz))
pre.baseType(symclazz) match {
case TypeRef(_, basesym, baseargs) =>
- instParam(basesym.typeParams, baseargs);
+ instParam(basesym.info.typeParams, baseargs);
case _ =>
throwError
}
@@ -1050,7 +1061,8 @@ abstract class Types: SymbolTable {
case Pair(MethodType(pts1, res1), MethodType(pts2, res2)) =>
pts1.length == pts2.length &&
isSameTypes(pts1, pts2) &&
- res1 =:= res2
+ res1 =:= res2 &&
+ tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType]
case Pair(PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
tparams1.length == tparams2.length &&
List.forall2(tparams1, tparams2)
@@ -1100,6 +1112,7 @@ abstract class Types: SymbolTable {
case Pair(ConstantType(_, _), ConstantType(_, _)) => tp1 =:= tp2
case Pair(TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
+ //System.out.println("isSubType " + tp1 + " " + tp2);//DEBUG
def isSubArgs(tps1: List[Type], tps2: List[Type],
tparams: List[Symbol]): boolean = {
tps1.isEmpty && tps2.isEmpty
@@ -1111,21 +1124,23 @@ abstract class Types: SymbolTable {
isSubArgs(tps1.tail, tps2.tail, tparams.tail)
}
sym1 == sym2 && (pre1 <:< pre2) &&
- isSubArgs(args1, args2, sym1.typeParams)
+ isSubArgs(args1, args2, sym1.info.typeParams)
||
- sym1.isAbstractType && (tp1.bounds.hi <:< tp2)
+ sym1.isAbstractType && !(tp1 =:= tp1.bounds.hi) && (tp1.bounds.hi <:< tp2)
||
- sym2.isAbstractType && (tp1 <:< tp2.bounds.lo)
+ sym2.isAbstractType && !(tp2 =:= tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo)
||
sym2.isClass &&
- ({ val base = tp1 baseType sym2; !(base eq tp1) && (base <:< tp2) })//debug
+ ({ val base = tp1 baseType sym2; !(base eq tp1) && (base <:< tp2) })
||
sym1 == AllClass
||
sym1 == AllRefClass && sym2 != AllClass && tp2 <:< AnyRefClass.tpe
case Pair(MethodType(pts1, res1), MethodType(pts2, res2)) =>
pts1.length == pts2.length &&
- isSameTypes(pts1, pts2) && (res1 <:< res2)
+ isSameTypes(pts1, pts2) &&
+ (res1 <:< res2) &&
+ tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType]
case Pair(PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
tparams1.length == tparams2.length &&
List.forall2(tparams1, tparams2)
@@ -1191,12 +1206,15 @@ abstract class Types: SymbolTable {
/** A function implementing tp1 matches tp2 */
private def matchesType(tp1: Type, tp2: Type): boolean = Pair(tp1, tp2) match {
case Pair(MethodType(pts1, res1), MethodType(pts2, res2)) =>
- isSameTypes(pts1, pts2) && (res1 matches res2)
+ isSameTypes(pts1, pts2) && (res1 matches res2) &&
+ tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType]
case Pair(PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
tparams1.length == tparams2.length &&
(res1 matches res2.substSym(tparams2, tparams1))
- case Pair(MethodType(_, _), _) | Pair(PolyType(_, _), _) =>
- false
+ case Pair(MethodType(_, _), _) => false
+ case Pair(PolyType(_, _), _) => false
+ case Pair(_, MethodType(_, _)) => false
+ case Pair(_, PolyType(_, _)) => false
case _ =>
!phase.exactMatch || tp1 =:= tp2
}
@@ -1296,8 +1314,18 @@ abstract class Types: SymbolTable {
/** The least sorted upwards closed upper bound of a non-empty list
* of closures.
* @See lubList for more explanations. */
- private def lubArray(tss: List[Array[Type]]): Array[Type] =
- Predef.Array(lubList(tss map (ts: Array[Type] => List.fromArray(ts))): _* );
+ private def lubArray(tss: List[Array[Type]]): Array[Type] = {
+ var lubs = lubList(tss map (ts: Array[Type] => List.fromArray(ts)));
+ var arr = new Array[Type](lubs.length);
+ var i = 0;
+ while (i < arr.length) {
+ arr(i) = lubs.head;
+ i = i + 1;
+ lubs = lubs.tail
+ }
+ arr
+ // todo: replace by Predef.Array(lubs: _* )
+ }
/** The minimal symbol (wrt Symbol.isLess) of a list of types */
private def minSym(tps: List[Type]): Symbol =
@@ -1382,7 +1410,10 @@ abstract class Types: SymbolTable {
addMember(lubThisType, lubType, lubsym(sym));
if (lubType.decls.isEmpty) lubBase else lubType;
}
- limitRecursion(ts, "least upper", lub0);
+ if (settings.debug.value) System.out.println("lub of " + ts);//debug
+ val res = limitRecursion(ts, "least upper", lub0);
+ if (settings.debug.value) System.out.println("lub of " + ts + " is " + res);//debug
+ res
}
/** The greatest lower bound wrt <:< of a list of types */
@@ -1458,7 +1489,7 @@ abstract class Types: SymbolTable {
/** The most deeply nested owner that contains all the symbols
* of thistype or prefixless typerefs/singletype occurrences in given list of types */
private def commonOwner(tps: List[Type]): Symbol = {
- System.out.println("computing common owner of types " + tps);//debug
+ if (settings.debug.value) System.out.println("computing common owner of types " + tps);//debug
commonOwnerMap.init;
tps mapConserve commonOwnerMap;
commonOwnerMap.result
@@ -1477,7 +1508,7 @@ abstract class Types: SymbolTable {
val pre = if (variance == 1) lub(pres) else glb(pres);
val argss = tps map (.typeArgs);
val args =
- List.map2(sym.typeParams, List.transpose(argss))
+ List.map2(sym.info.typeParams, List.transpose(argss))
((tparam, as) =>
if (tparam.variance == variance) lub(as)
else if (tparam.variance == -variance) glb(as)
diff --git a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 569e9f6273..d63f186146 100755
--- a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -253,10 +253,10 @@ abstract class ClassfileParser {
val methodCount = in.nextChar();
for (val i <- Iterator.range(0, methodCount)) parseMethod();
if (instanceDefs.lookup(nme.CONSTRUCTOR) == NoSymbol && (sflags & INTERFACE) == 0) {
- System.out.println("adding constructor to " + clazz);//debug
+ //System.out.println("adding constructor to " + clazz);//DEBUG
instanceDefs enter
clazz.newConstructor(Position.NOPOS)
- .setFlag(clazz.flags & CONSTRFLAGS).setInfo(MethodType(List(), clazz.tpe));
+ .setFlag(clazz.flags & ConstrFlags).setInfo(MethodType(List(), clazz.tpe));
}
}
}
@@ -285,7 +285,13 @@ abstract class ClassfileParser {
in.skip(4); skipAttributes();
} else {
val name = pool.getName(in.nextChar());
- val info = pool.getType(in.nextChar());
+ var info = pool.getType(in.nextChar());
+ if (name == nme.CONSTRUCTOR)
+ info match {
+ case MethodType(formals, restpe) =>
+ assert(restpe == definitions.UnitClass.tpe);
+ info = MethodType(formals, clazz.tpe)
+ }
val sym = getOwner(jflags)
.newMethod(Position.NOPOS, name).setFlag(sflags).setInfo(info);
parseAttributes(sym, info);
diff --git a/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala b/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala
index 8bfd9709ad..07ccc96748 100755
--- a/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala
@@ -6,7 +6,7 @@
package scala.tools.nsc.symtab.classfile;
import java.util.{StringTokenizer, NoSuchElementException}
-import scala.collection.mutable.ListBuffer;
+import util.ListBuffer;
import scala.tools.util.Position;
abstract class MetaParser{
@@ -51,7 +51,7 @@ abstract class MetaParser{
else {
val args = new ListBuffer[Type];
do {
- nextToken(); args append parseType();
+ nextToken(); args += parseType();
} while (token == ",");
nextToken();
appliedType(tp, args.toList)
@@ -79,9 +79,9 @@ abstract class MetaParser{
nextToken();
val syms = new ListBuffer[Symbol];
if (token != "]") {
- syms append parseTypeParam();
+ syms += parseTypeParam();
while (token == ",") {
- nextToken(); syms append parseTypeParam();
+ nextToken(); syms += parseTypeParam();
}
}
assert(token == "]");
@@ -92,9 +92,9 @@ abstract class MetaParser{
nextToken();
val tps = new ListBuffer[Type];
if (token != ")") {
- tps append parseType();
+ tps += parseType();
while (token == ",") {
- nextToken(); tps append parseType();
+ nextToken(); tps += parseType();
}
}
assert(token == ")");
@@ -110,7 +110,7 @@ abstract class MetaParser{
} else if (token == "extends") {
val tps = new ListBuffer[Type];
do {
- nextToken(); tps append parseType()
+ nextToken(); tps += parseType()
} while (token == "with");
ownertype match {
case ClassInfoType(parents, decls, clazz) =>
diff --git a/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala b/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala
index 8f1ec5b6ad..1f05cf1234 100755
--- a/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala
@@ -31,6 +31,7 @@ object PickleFormat {
* | 19 CLASSINFOtpe len_Nat classsym_Ref {tpe_Ref}
* | 20 METHODtpe len_Nat tpe_Ref {tpe_Ref}
* | 21 POLYTtpe len_Nat tpe_Ref {sym_Ref}
+ * | 22 IMPLICITMETHODtpe len_Nat tpe_Ref {tpe_Ref}
* | 24 LITERALunit len_Nat
* | 25 LITERALboolean len_Nat value_Long
* | 26 LITERALbyte len_Nat value_Long
@@ -71,6 +72,7 @@ object PickleFormat {
val CLASSINFOtpe = 19;
val METHODtpe = 20;
val POLYtpe = 21;
+ val IMPLICITMETHODtpe = 22;
val LITERALunit = 24;
val LITERALboolean = 25;
val LITERALbyte = 26;
diff --git a/sources/scala/tools/nsc/symtab/classfile/Pickler.scala b/sources/scala/tools/nsc/symtab/classfile/Pickler.scala
index c1f2b0d2d4..b21f033354 100755
--- a/sources/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -28,8 +28,7 @@ abstract class Pickler {
case PackageDef(_, stats) => stats foreach pickle;
case ClassDef(_, _, _, _, _) | ModuleDef(_, _, _) =>
val sym = tree.symbol;
- System.out.println("add " + sym);//debug
- System.out.println("pickling " + tree + " " + sym);//debug
+ if (settings.debug.value) System.out.println("pickling " + tree + " " + sym);//debug
val pickle = new Pickle(sym.name.toTermName, sym.owner);
def add(sym: Symbol) = {
if (!sym.isExternal && !symData.contains(sym)) {
@@ -75,7 +74,6 @@ abstract class Pickler {
/** Store symbol in index. If symbol is local, also store everything it refers to. */
def putSymbol(sym: Symbol): unit = if (putEntry(sym)) {
- System.out.println("put symbol " + sym);
if (isLocal(sym)) {
putEntry(sym.name);
putSymbol(sym.owner);
@@ -136,7 +134,6 @@ abstract class Pickler {
private def writeSymInfo(sym: Symbol): unit = {
writeRef(sym.name);
writeRef(sym.owner);
- System.out.println("" + sym + " has flags " + sym.flags + " " + (sym.flags & PickledFlags));
writeNat((sym.flags & PickledFlags).asInstanceOf[int]);
writeRef(sym.info)
}
@@ -171,10 +168,8 @@ abstract class Pickler {
case sym: TypeSymbol =>
writeSymInfo(sym);
if (sym.isAbstractType) TYPEsym else ALIASsym
- case sym: ModuleSymbol =>
- writeSymInfo(sym); MODULEsym
case sym: TermSymbol =>
- writeSymInfo(sym); VALsym
+ writeSymInfo(sym); if (sym.isModule) MODULEsym else VALsym
case NoType =>
NOtpe
case NoPrefix =>
@@ -194,7 +189,9 @@ abstract class Pickler {
case ClassInfoType(parents, decls, clazz) =>
writeRef(clazz); writeRefs(parents); CLASSINFOtpe
case MethodType(formals, restpe) =>
- writeRef(restpe); writeRefs(formals); METHODtpe
+ writeRef(restpe); writeRefs(formals);
+ if (entry.isInstanceOf[ImplicitMethodType]) IMPLICITMETHODtpe
+ else METHODtpe
case PolyType(tparams, restpe) =>
writeRef(restpe); writeRefs(tparams); POLYtpe
case Constant(null) =>
@@ -232,7 +229,7 @@ abstract class Pickler {
def finish = {
assert(writeIndex == 0);
writeNat(ep);
- System.out.println("" + ep + " entries");//debug
+ if (settings.debug.value) System.out.println("" + ep + " entries");//debug
for (val i <- Iterator.range(0, ep)) writeEntry(entries(i))
}
}
diff --git a/sources/scala/tools/nsc/symtab/classfile/UnPickle.scala b/sources/scala/tools/nsc/symtab/classfile/UnPickle.scala
deleted file mode 100755
index e46b876b2f..0000000000
--- a/sources/scala/tools/nsc/symtab/classfile/UnPickle.scala
+++ /dev/null
@@ -1,480 +0,0 @@
-/* NSC -- new scala compiler
- * Copyright 2005 LAMP/EPFL
- * @author Martin Odersky
- */
-// $Id$
-package scala.tools.nsc.symtab.classfile {
-
-//import scalac_symtab.Modifiers;
-//import scalac_symtab.EntryTags._;
-import java.io.PrintStream;
-import scala.tools.util.{Position, UTF8Codec};
-import java.lang.{Float, Double};
-
-/***************************************************
- * Symbol table attribute format: see EntryTags.java
- */
-abstract class UnPickle {
-
- val global: Global;
- import global._;
-
- private var classRoot: Symbol = _;
- private var moduleRoot: Symbol = _;
- private var bytes: Array[byte] = _;
- private var bp: int = _;
- private var index: Array[int] = _;
- private var entries: Array[AnyRef] = _;
-
- def parse(bytes: Array[byte], clazz: Symbol, module: Symbol): unit = {
- warning("cannot yet unpickle: " + clazz.fullNameString('.'));
- }
-}}
-/*
- this.classRoot = clazz;
- this.moduleRoot = module;
- this.bytes = bytes;
- this.bp = 0;
- if (settings.debug.value) global.log("unpickle " + classRoot + " and " + moduleRoot);
- createIndex();
- if (settings.debug.value) printAll(System.out);
- entries = new Array[Any](index.length);
- for (val i <- Iterator.range(0, index.length)) {
- if (isSymbolEntry(i)) getSymbol(i)
- }
- if (settings.debug.value) global.log("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug
- }
-
- def readByte(): int = {
- val x = bytes(bp); bp = bp + 1; x
- }
-
- def readNat(): int = {
- var b = 0;
- var x = 0;
- do {
- b = readByte();
- x = (x << 7) + (b & 0x7f);
- } while ((b & 0x80) != 0);
- x
- }
-
- def readLong(len: int): long = {
- var x = 0L;
- var i = 0;
- while (i < len) {
- x = (x << 8) + (readByte() & 0xff);
- i = i + 1
- }
- val leading = 64 - (len << 3);
- x << leading >> leading
- }
-
- private def at[T](start: int)(op: => T): T = {
- val savedBp = bp;
- bp = start;
- val result = op;
- bp = savedBp;
- result
- }
-
- private def createIndex(): unit = {
- index = new Array[int](readNat());
- for (val i <- Iterator.range(0, index.length)) {
- index(i) = readByte();
- bp = readNat() + bp
- }
- }
-
- def isTypeEntry(i: int): boolean = {
- val tag = bytes(index(i));
- (firstTypeTag <= tag && tag <= lastTypeTag) || tag == NOpre;
- }
-
- def isSymbolEntry(i: int): boolean = {
- val tag = bytes(index(i));
- firstSymTag <= tag && tag <= lastSymTag
- }
-
- def getName(i: int): Name = {
- var name: Name = entries(i).asInstanceOf[Name];
- if (name == null) {
- at(index(i)) {
- val tag = readByte();
- val len = readNat();
- val cs = new Array[char](len);
- val defined = UTF8Codec.decode(bytes, bp, cs, 0, len);
- name = tag match {
- case TERMname => newTermName(cs, 0, defined)
- case TYPEname => newTypeName(cs, 0, defined)
- case _ => errorBadSignature("");
- }
- entries(i) = name
- }
- }
- name
- }
-
- def readNameRef(): Name = getName(readNat());
-
- def getSymbol(i: int): Symbol = {
- var sym: Symbol = entries(i).asInstanceOf[Symbol];
- if (sym == null) {
- at(index(i)) {
- val tag = readByte();
- val end = readNat() + bp;
- tag match {
- case NONEsym =>
- sym = NoSymbol;
- entries(i) = sym
- case EXTref | EXTMODCLASSref =>
- val name = readNameRef();
- val owner =
- if (bp == end) definitions.RootClass
- else { assert(bp < end); readSymbolRef() }
- sym =
- if (name.toTermName == nme.ROOT && owner == NoSymbol) {
- assert(tag != EXTref);
- global.definitions.RootClass
- } else if (tag == EXTMODCLASSref) {
- owner.info.decl(name).moduleClass
- } else {
- owner.info.decl(name)
- }
- entries(i) = sym;
- if (sym == NoSymbol)
- errorBadSignature(
- "reference " + (if (name.isTypeName) "type " else "value ") +
- name.decode + " of " + owner + " refers to nonexisting symbol.");
- case _ =>
- assert(isSymbolEntry(i));
- val name = readNameRef();
- if (settings.debug.value) global.log("reading " + name + " at " + i);
- val owner = readSymbolRef();
- if (entries(i) != null)
- sym = entries(i).asInstanceOf[Symbol]
- else {
- val pflags = readNat();
- val inforef = readNat();
- var syminfo: Type = null;
- tag match {
- case TYPEsym =>
- sym = owner.newAbstractType(Position.NOPOS, name);
- entries(i) = sym;
- syminfo = new LazyBoundsTypeRef(
- inforef, readNat(), (pflags & Modifiers.VIEWBOUND) != 0)
- case ALIASsym =>
- sym = owner.newAliasType(Position.NOPOS, name);
- entries(i) = sym;
- syminfo = new LazyTypeRef(inforef, sym);
- val constr = readSymbolRef();
- if (!constr.typeParams.isEmpty)
- syminfo = new LazyPolyType(
- constr.typeParams map (.cloneSymbol(sym)),
- syminfo);
- case CLASSsym =>
- sym =
- if ((pflags & Modifiers.MODUL) != 0) {
- val modulesym = readSymbolRef();
- modulesym.moduleClass
- } else if (name == classRoot.name && owner == classRoot.owner) {
- if (settings.debug.value) global.log("overwriting " + classRoot);
- classRoot
- } else {
- owner.newClass(Position.NOPOS, name)
- }
- entries(i) = sym;
- syminfo = new LazyTypeRef(inforef, sym);
- sym.setTypeOfThis(new LazyTypeRef(readNat(), sym));
- val constr = readSymbolRef();
- if (!constr.typeParams.isEmpty)
- syminfo = new LazyPolyType(
- constr.typeParams map (.cloneSymbol(sym)),
- syminfo);
- case VALsym =>
- sym =
- if (name == moduleRoot.name && owner == moduleRoot.owner) {
- if (settings.debug.value) global.log("overwriting " + moduleRoot);
- moduleRoot
- } else if ((pflags & Modifiers.MODUL) != 0) {
- owner.newModule(Position.NOPOS, name)
- } else {
- if (name == nme.CONSTRUCTOR && bp < end) readSymbolRef();
- owner.newValue(Position.NOPOS, name);
- }
- if (sym.isModule) {
- val clazz = readSymbolRef();
- assert(clazz == sym.moduleClass, sym)
- }
- syminfo = new LazyTypeRef(inforef, sym);
- case _ =>
- errorBadSignature("");
- }
- sym.setFlag(transFlags(pflags));
- sym.setInfo(syminfo);
- enterSymbol(sym);
- }
- }
- }
- }
- sym
- }
-
- def readSymbolRef(): Symbol = getSymbol(readNat());
-
- def readSymbolRefs(end: int): List[Symbol] =
- if (bp == end) List()
- else {
- val symref = readNat();
- if (!isSymbolEntry(symref)) List()
- else getSymbol(symref) :: readSymbolRefs(end)
- }
-
- def enterSymbol(sym: Symbol): unit =
- if (sym.owner.isClass && !sym.isModuleClass) {
- if (settings.debug.value) global.log("entering " + sym + ":" + sym.tpe + " in " + sym.owner);//debug
- val scope = sym.owner.info.decls;
- val other = scope.lookup(sym.name);
- if (other != sym) {
- sym.info match {
- case OverloadedType(alts) => alts foreach scope.enter
- case _ => scope.enter(sym)
- }
- }
- }
-
- def getType(i: int, owner: Symbol): Type = {
- var tpe = entries(i).asInstanceOf[Type];
- if (tpe == null) {
- at(index(i)) {
- val tag = readByte();
- val end = readNat() + bp;
- tpe = tag match {
- case NOtpe =>
- NoType
- case NOpre =>
- NoPrefix
- case THIStpe =>
- ThisType(readSymbolRef())
- case SINGLEtpe =>
- singleType(readTypeRef(owner), readSymbolRef());
- case CONSTANTtpe =>
- ConstantType(readTypeRef(owner), readConstantRef())
- case TYPEREFtpe =>
- // create a type-ref as found, without checks or rebinds
- new ExtTypeRef(readTypeRef(owner), readSymbolRef(), readTypeRefs(end, owner))
- case COMPOUNDtpe =>
- val isCompoundSym = readByte() != 0;
- val ctOwner = if (isCompoundSym) readSymbolRef() else null;
- val ctClassRef = readNat();
- val ctClass: Symbol =
- if (isCompoundSym) entries(ctClassRef).asInstanceOf[Symbol]
- else getSymbol(ctClassRef);
- val parents = readTypeRefs(end, owner);
- if (ctClass == null)
- refinedType(intersectionType(parents), ctOwner)
- else if (isCompoundSym)
- new ExtRefinedType(intersectionType(parents), new Scope, ctClass)
- else
- ClassInfoType(parents, new Scope, ctClass);
- case METHODtpe =>
- val restype = readTypeRef(owner);
- val argtps = at(bp)(readTypeRefs(end, owner)) map { argtp =>
- val flags = getFlags(readNat());
- if ((flags & DEFflag) != 0)
- PolyType(List(), argtp)
- else if ((flags & REPEATEDflag) != 0)
- appliedType(definitions.RepeatedParamClass.tpe, List(argtp))
- else
- argtp
- }
- MethodType(argtps, restype)
- case POLYtpe =>
- val restype = readTypeRef(owner);
- PolyType(readSymbolRefs(end), restype)
- case OVERLOADEDtpe =>
- val alts = readSymbolRefs(end);
- readTypeRefs(end, NoSymbol);
- OverloadedType(alts)
- case FLAGGEDtpe =>
- readNat(); // skip flags
- readTypeRef(owner)
- case _ =>
- errorBadSignature("");
- }
- if (tag != METHODtpe) entries(i) = tpe;
- }
- }
- tpe
- }
-
- def readTypeRef(owner: Symbol): Type = getType(readNat(), owner);
-
- def readTypeRefs(end: int, owner: Symbol): List[Type] =
- if (bp == end) List()
- else {
- val typeref = readNat();
- if (!isTypeEntry(typeref)) List()
- else getType(typeref, owner) :: readTypeRefs(end, owner)
- }
-
- def getFlags(i: int): int =
- at(index(i)) {
- val tag = readByte();
- val end = readNat() + bp;
- if (tag == FLAGGEDtpe) readNat() else 0
- }
-
- def getConstant(i: int): Any = {
- var value = entries(i);
- if (value == null) {
- at(index(i)) {
- val tag = readByte();
- val len = readNat();
- value = tag match {
- case LITERALunit => ()
- case LITERALboolean => if (readByte() == 0) false else true
- case LITERALbyte => readLong(len).asInstanceOf[byte]
- case LITERALshort => readLong(len).asInstanceOf[short]
- case LITERALchar => readLong(len).asInstanceOf[char]
- case LITERALint => readLong(len).asInstanceOf[int]
- case LITERALlong => readLong(len)
- case LITERALfloat => Float.intBitsToFloat(readLong(len).asInstanceOf[int])
- case LITERALdouble => Double.longBitsToDouble(readLong(len))
- case LITERALstring => readNameRef().toString()
- case LITERALnull => null
- case _ => errorBadSignature("bad constant tag: " + tag)
- }
- entries(i)= value
- }
- }
- value
- }
-
- def readConstantRef(): Any = getConstant(readNat());
-
- def errorBadSignature(msg: String) =
- throw new RuntimeException("malformed Scala signature at " + bp + "; " + msg);
-
- private case class OverloadedType(alts: List[Symbol]) extends Type;
-
- private class LazyTypeRef(tpref: int, owner: Symbol) extends LazyType {
- override def complete(sym: Symbol): unit =
- sym.setInfo(getType(tpref, owner));
- }
-
- private class LazyBoundsTypeRef(hiref: int, loref: int, vubound: boolean) extends LazyType {
- override def complete(sym: Symbol): unit = {
- val hi = if (vubound) definitions.AnyClass.tpe else getType(hiref, sym);
- val vu = if (vubound) getType(hiref, sym) else definitions.AnyClass.tpe;
- val lo = getType(loref, sym);
- sym.setInfo(TypeBounds(lo, hi, vu))
- }
- }
-
-// --- print symbl files -------------------------------------------------
-
- private def tag2string(tag: int): String = tag match {
- case TERMname => "TERMname";
- case TYPEname => "TYPEname";
- case NONEsym => "NONEsym";
- case TYPEsym => "TYPEsym";
- case ALIASsym => "ALIASsym";
- case CLASSsym => "CLASSsym";
- case VALsym => "VALsym";
- case EXTref => "EXTref";
- case EXTMODCLASSref => "EXTMODCLASSref";
- case NOtpe => "NOtpe";
- case THIStpe => "THIStpe";
- case SINGLEtpe => "SINGLEtpe";
- case TYPEREFtpe => "TYPEREFtpe";
- case CONSTANTtpe => "CONSTANTtpe";
- case COMPOUNDtpe => "COMPOUNDtpe";
- case METHODtpe => "METHODtpe";
- case POLYtpe => "POLYtpe";
- case OVERLOADEDtpe => "OVERLOADEDtpe";
- case UNBOXEDtpe => "UNBOXEDtpe";
- case UNBOXEDARRAYtpe => "UNBOXEDARRAYtpe";
- case FLAGGEDtpe => "FLAGGEDtpe";
- case ERRORtpe => "ERRORtpe";
- case LITERALunit => "LITERALunit";
- case LITERALboolean => "LITERALboolean";
- case LITERALbyte => "LITERALbyte";
- case LITERALshort => "LITERALshort";
- case LITERALchar => "LITERALchar";
- case LITERALint => "LITERALint";
- case LITERALlong => "LITERALlong";
- case LITERALfloat => "LITERALfloat";
- case LITERALdouble => "LITERALdouble";
- case LITERALstring => "LITERALstring";
- case LITERALnull => "LITERALnull";
- case LITERALzero => "LITERALzero";
- case _ => "***BAD TAG***(" + tag + ")";
- }
-
- def printAll(out: PrintStream): unit = {
- out.println("symbl attribute for " + classRoot + ":");
- for (val i <- Iterator.range(0, index.length)) {
- out.print(i + "," + index(i) + ": ");
- bp = index(i);
- val tag = readByte();
- out.print(tag2string(tag));
- val len = readNat();
- val end = len + bp;
- out.print(" " + len);
- tag match {
- case TERMname | TYPEname =>
- out.print(" " + UTF8Codec.decode(bytes, bp, len));
- bp = end;
- case NONEsym =>
- case TYPEsym | ALIASsym | CLASSsym | VALsym =>
- out.print(" " + readNat()); //name
- out.print(" " + readNat()); //owner
- out.print(" " + Integer.toHexString(readNat())); //flags
- out.print(" " + readNat()); //type
- case FLAGGEDtpe =>
- out.print(" " + Integer.toHexString(readNat())); //flags
- }
- while (bp < end) out.print(" " + readNat());
- out.println();
- }
- }
-
- def transFlags(pflags: int): long = {
- var res = 0L;
- if ((pflags & Modifiers.DEFERRED ) != 0) res = res | Flags.DEFERRED ;
- if ((pflags & Modifiers.FINAL ) != 0) res = res | Flags.FINAL ;
- if ((pflags & Modifiers.PRIVATE ) != 0) res = res | Flags.PRIVATE ;
- if ((pflags & Modifiers.PROTECTED ) != 0) res = res | Flags.PROTECTED ;
- if ((pflags & Modifiers.SEALED ) != 0) res = res | Flags.SEALED ;
- if ((pflags & Modifiers.OVERRIDE ) != 0) res = res | Flags.OVERRIDE ;
- if ((pflags & Modifiers.CASE ) != 0) res = res | Flags.CASE ;
- if ((pflags & Modifiers.ABSTRACT ) != 0) res = res | Flags.ABSTRACT ;
- if ((pflags & Modifiers.SYNTHETIC ) != 0) res = res | Flags.SYNTHETIC ;
- if ((pflags & Modifiers.DEPRECATED ) != 0) res = res | Flags.DEPRECATED ;
- if ((pflags & Modifiers.JAVA ) != 0) res = res | Flags.JAVA ;
- if ((pflags & Modifiers.MODUL ) != 0) res = res | Flags.MODULE ;
- if ((pflags & Modifiers.MUTABLE ) != 0) res = res | Flags.MUTABLE ;
- if ((pflags & Modifiers.PARAM ) != 0) res = res | Flags.PARAM ;
- if ((pflags & Modifiers.INITIALIZED ) != 0) res = res | Flags.INITIALIZED;
- if ((pflags & Modifiers.LOCKED ) != 0) res = res | Flags.LOCKED ;
- if ((pflags & Modifiers.ACCESSED ) != 0) res = res | Flags.ACCESSED ;
- if ((pflags & Modifiers.SELECTOR ) != 0) res = res | Flags.SELECTOR ;
- if ((pflags & Modifiers.PACKAGE ) != 0) res = res | Flags.PACKAGE ;
- if ((pflags & Modifiers.STABLE ) != 0) res = res | Flags.STABLE ;
- if ((pflags & Modifiers.CAPTURED ) != 0) res = res | Flags.CAPTURED ;
- if ((pflags & Modifiers.INCONSTRUCTOR) != 0) res = res | Flags.INCONSTRUCTOR;
- if ((pflags & Modifiers.PARAMACCESSOR) != 0) res = res | Flags.PARAMACCESSOR;
- if ((pflags & Modifiers.ACCESSOR ) != 0) res = res | Flags.ACCESSOR ;
- if ((pflags & Modifiers.BRIDGE ) != 0) res = res | Flags.BRIDGE ;
- if ((pflags & Modifiers.LIFTED ) != 0) res = res | Flags.LIFTED ;
- if ((pflags & Modifiers.ALTERNATIVE ) != 0) res = res | Flags.ALTERNATIVE;
- if ((pflags & Modifiers.INTERFACE ) != 0) res = res | Flags.TRAIT ;
- if ((pflags & Modifiers.TRAIT ) != 0) res = res | Flags.TRAIT ;
- if ((pflags & Modifiers.COVARIANT ) != 0) res = res | Flags.COVARIANT ;
- if ((pflags & Modifiers.CONTRAVARIANT) != 0) res = res | Flags.CONTRAVARIANT;
- res
- }
-}
-}
-*/
diff --git a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala
index 6012d428c4..2356e61f8c 100755
--- a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -103,13 +103,15 @@ abstract class UnPickler {
sym = if (name == moduleRoot.name && owner == moduleRoot.owner) moduleRoot
else owner.newModule(Position.NOPOS, name, mclazz)
case VALsym =>
- sym = owner.newValue(Position.NOPOS, name)
+ sym = if (name == moduleRoot.name && owner == moduleRoot.owner) moduleRoot.resetFlag(MODULE)
+ else owner.newValue(Position.NOPOS, name)
case _ =>
errorBadSignature("bad symbol tag: " + tag);
}
sym.setFlag(flags);
sym.setInfo(new LazyTypeRef(inforef));
- if (sym.owner.isClass && !sym.isModuleClass && !sym.hasFlag(PARAM))
+ if (sym.owner.isClass && sym != classRoot && sym != moduleRoot &&
+ !sym.isModuleClass && !sym.hasFlag(PARAM))
sym.owner.info.decls enter sym
}
sym
@@ -144,6 +146,9 @@ abstract class UnPickler {
case METHODtpe =>
val restpe = readTypeRef();
MethodType(until(end, readTypeRef), restpe)
+ case IMPLICITMETHODtpe =>
+ val restpe = readTypeRef();
+ new ImplicitMethodType(until(end, readTypeRef), restpe)
case POLYtpe =>
val restpe = readTypeRef();
PolyType(until(end, readSymbolRef), restpe)
diff --git a/sources/scala/tools/nsc/typechecker/Contexts.scala b/sources/scala/tools/nsc/typechecker/Contexts.scala
index afaa1542b3..19d02e6856 100755
--- a/sources/scala/tools/nsc/typechecker/Contexts.scala
+++ b/sources/scala/tools/nsc/typechecker/Contexts.scala
@@ -5,14 +5,16 @@
// $Id$
package scala.tools.nsc.typechecker;
+import symtab.Flags._;
import scala.tools.util.Position;
class Contexts: Analyzer {
import global._;
val NoContext = new Context {
- override def imports: List[ImportInfo] = List();
+ override def implicitss: List[List[ImplicitInfo]] = List();
}
+ NoContext.enclClass = NoContext;
val startContext = {
import definitions._;
@@ -22,11 +24,11 @@ class Contexts: Analyzer {
definitions.RootClass.info.decls);
def addImport(pkg: Symbol): unit = {
val qual = gen.mkStableRef(pkg);
- val impTree = Import(qual, List(Pair(nme.WILDCARD, null)))
- setSymbol NoSymbol.newImport(Position.NOPOS).setInfo(ImportType(qual))
- setType NoType;
- sc = sc.make(
- Template(List(), List(impTree)) setSymbol NoSymbol setType NoType, sc.owner, sc.scope)
+ sc = sc.makeNewImport(
+ Import(qual, List(Pair(nme.WILDCARD, null)))
+ setSymbol NoSymbol.newImport(Position.NOPOS).setInfo(ImportType(qual))
+ setType NoType);
+ sc.depth = sc.depth + 1
}
if (!settings.noimports.value) {
addImport(JavaLangPackage);
@@ -40,7 +42,7 @@ class Contexts: Analyzer {
class Context {
var unit: CompilationUnit = _;
var tree: Tree = _; // Tree associated with this context
- var owner: Symbol = _; // The current owner
+ var owner: Symbol = NoSymbol; // The current owner
var scope: Scope = _; // The current scope
var outer: Context = _; // The next outer context
var enclClass: Context = _; // The next outer context whose tree is a
@@ -48,15 +50,19 @@ class Contexts: Analyzer {
var variance: int = _; // Variance relative to enclosing class.
private var _undetparams: List[Symbol] = List(); // Undetermined type parameters
var depth: int = 0;
+ var imports: List[ImportInfo] = List();
+
+ var reportAmbiguousErrors = false;
+ var reportGeneralErrors = false;
def undetparams = _undetparams;
def undetparams_=(ps: List[Symbol]) = {
- System.out.println("undetparams = " + ps);
+ //System.out.println("undetparams = " + ps);//debug
_undetparams = ps
}
- def make(unit: CompilationUnit, tree: Tree, owner: Symbol, scope: Scope): Context = {
- val c = new Context();
+ def make(unit: CompilationUnit, tree: Tree, owner: Symbol, scope: Scope, imports: List[ImportInfo]): Context = {
+ val c = new Context;
c.unit = unit;
c.tree = tree;
c.owner = owner;
@@ -66,25 +72,55 @@ class Contexts: Analyzer {
case _ => this.enclClass
}
c.variance = this.variance;
- c.depth = this.depth + 1;
+ c.depth = if (scope == this.scope) this.depth else this.depth + 1;
+ c.imports = imports;
+ c.reportAmbiguousErrors = this.reportAmbiguousErrors;
+ c.reportGeneralErrors = this.reportGeneralErrors;
c.outer = this;
c
}
- def make(unit: CompilationUnit): Context =
- make(unit, EmptyTree, this.owner, this.scope);
+ def make(unit: CompilationUnit): Context = {
+ val c = make(unit, EmptyTree, owner, scope, imports);
+ c.reportAmbiguousErrors = true;
+ c.reportGeneralErrors = true;
+ c
+ }
+
+ def makeNewImport(imp: Import): Context =
+ make(unit, imp, owner, scope, new ImportInfo(imp, depth) :: imports);
def make(tree: Tree, owner: Symbol, scope: Scope): Context =
- make(this.unit, tree, owner, scope);
+ make(unit, tree, owner, scope, imports);
def makeNewScope(tree: Tree, owner: Symbol): Context =
- make(tree, owner, new Scope(this.scope));
+ make(tree, owner, new Scope(scope));
def make(tree: Tree, owner: Symbol): Context =
- make(tree, owner, this.scope);
+ make(tree, owner, scope);
def make(tree: Tree): Context =
- make(tree, this.owner);
+ make(tree, owner);
+
+ def makeImplicit(reportAmbiguousErrors: boolean) = {
+ val c = make(tree);
+ c.reportAmbiguousErrors = reportAmbiguousErrors;
+ c.reportGeneralErrors = false;
+ c
+ }
+
+ def error(pos: int, msg: String): unit =
+ if (reportGeneralErrors) unit.error(pos, msg)
+ else throw new TypeError(msg);
+
+ def ambiguousError(pos: int, pre: Type, sym1: Symbol, sym2: Symbol, rest: String): unit = {
+ val msg =
+ "ambiguous reference to overloaded definition,\n" +
+ "both " + sym1 + ": " + pre.memberType(sym1) + "\n" +
+ "and " + sym2 + ": " + pre.memberType(sym2) + "\nmatch " + rest;
+ if (reportAmbiguousErrors) unit.error(pos, msg)
+ else throw new TypeError(msg);
+ }
def outerContext(clazz: Symbol): Context = {
var c = this;
@@ -101,30 +137,85 @@ class Contexts: Analyzer {
override def toString(): String = {
if (this == NoContext) "NoContext";
- else tree.toString() + "\n:: " + outer.toString()
+ else owner.toString() + " @ " + tree.toString() + "\n:: " + outer.toString()
}
- private var importsCache: List[ImportInfo] = null;
+ /** Is `sym' accessible as a member of tree `site' with type `pre' in current context?
+ */
+ def isAccessible(sym: Symbol, pre: Type, site: Tree): boolean = {
+
+ /** Are we inside definition of `owner'? */
+ def accessWithin(owner: Symbol): boolean = {
+ var c = this;
+ while (c != NoContext && c.owner != owner) {
+ if (c.outer == null) assert(false, "accessWithin(" + owner + ") " + c);//debug
+ if (c.outer.enclClass == null) assert(false, "accessWithin(" + owner + ") " + c);//debug
+ c = c.outer.enclClass;
+ }
+ c != NoContext;
+ }
+
+ /** Is `clazz' a subclass of an enclosing class? */
+ def isSubClassOfEnclosing(clazz: Symbol): boolean = {
+ var c = this;
+ while (c != NoContext && !clazz.isSubClass(c.owner)) c = c.outer.enclClass;
+ c != NoContext;
+ }
+
+ pre == NoPrefix
+ ||
+ (!sym.hasFlag(PRIVATE | PROTECTED))
+ ||
+ accessWithin(sym.owner) && (!sym.hasFlag(LOCAL) || pre.isInstanceOf[ThisType])
+ ||
+ (!sym.hasFlag(PRIVATE) &&
+ (site.isInstanceOf[Super] ||
+ (pre.widen.symbol.isSubClass(sym.owner) && isSubClassOfEnclosing(pre.widen.symbol))))
+ }
- def imports: List[ImportInfo] = {
- def collectImports(stats: List[Tree]): List[ImportInfo] = stats match {
- case Nil => outer.imports
- case (imp @ Import(_, _)) :: rest => new ImportInfo(imp, depth) :: collectImports(rest)
- case _ :: rest => collectImports(rest)
+ private var implicitsCache: List[List[ImplicitInfo]] = null;
+
+ private def collectImplicits(syms: List[Symbol], pre: Type): List[ImplicitInfo] =
+ for (val sym <- syms; sym.hasFlag(IMPLICIT) && isAccessible(sym, pre, EmptyTree))
+ yield ImplicitInfo(sym.name, pre.memberType(sym), sym);
+
+ private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = {
+ val pre = imp.qual.tpe;
+ def collect(sels: List[Pair[Name, Name]]): List[ImplicitInfo] = sels match {
+ case List() => List()
+ case List(Pair(nme.WILDCARD, _)) => collectImplicits(pre.implicitMembers, pre)
+ case Pair(from, to) :: sels1 =>
+ var impls = collect(sels1) filter (info => info.name != from);
+ if (to != nme.WILDCARD) {
+ val sym = imp.importedSymbol(to);
+ if (sym.hasFlag(IMPLICIT)) impls = ImplicitInfo(to, pre.memberType(sym), sym) :: impls;
+ }
+ impls
}
- if (importsCache == null) {
- importsCache = tree match {
- case PackageDef(_, stats) => collectImports(stats)
- case Template(_, stats) => collectImports(stats)
- case Block(stats, _) => collectImports(stats)
- case _ => outer.imports
- }
+ if (settings.debug.value) System.out.println("collect implicit imports " + imp + "=" + collect(imp.tree.selectors));//debug
+ collect(imp.tree.selectors)
+ }
+
+ def implicitss: List[List[ImplicitInfo]] = {
+ if (implicitsCache == null) {
+ val newImplicits: List[ImplicitInfo] =
+ if (owner != outer.owner && owner.isClass && !owner.isPackageClass) {
+ collectImplicits(owner.info.implicitMembers, owner.thisType)
+ } else if (scope != outer.scope && !owner.isPackageClass) {
+ if (settings.debug.value) System.out.println("collect local implicits " + scope.toList);//debug
+ collectImplicits(scope.toList, NoPrefix)
+ } else if (imports != outer.imports) {
+ assert(imports.tail == outer.imports);
+ collectImplicitImports(imports.head)
+ } else List();
+ implicitsCache = if (newImplicits.isEmpty) outer.implicitss
+ else newImplicits :: outer.implicitss;
}
- importsCache
+ implicitsCache
}
}
- class ImportInfo(tree: Import, val depth: int) {
+ class ImportInfo(val tree: Import, val depth: int) {
/** The prefix expression */
def qual: Tree = tree.symbol.info match {
@@ -144,12 +235,12 @@ class Contexts: Analyzer {
var selectors = tree.selectors;
while (selectors != Nil && result == NoSymbol) {
if (selectors.head._2 == name.toTermName)
- result = tree.expr.symbol.info.member(
+ result = qual.tpe.member(
if (name.isTypeName) selectors.head._1.toTypeName else selectors.head._1);
else if (selectors.head._1 == name.toTermName)
renamed = true
else if (selectors.head._1 == nme.WILDCARD && !renamed)
- result = tree.expr.symbol.info.member(name);
+ result = qual.tpe.member(name);
selectors = selectors.tail
}
result
@@ -159,6 +250,6 @@ class Contexts: Analyzer {
}
case class ImportType(expr: Tree) extends Type;
-}
-
+ case class ImplicitInfo(val name: Name, val tpe: Type, val sym: Symbol);
+}
diff --git a/sources/scala/tools/nsc/typechecker/EtaExpansion.scala b/sources/scala/tools/nsc/typechecker/EtaExpansion.scala
index 4c8052563c..0d38a1b687 100644
--- a/sources/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/sources/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -5,7 +5,7 @@
// $Id$
package scala.tools.nsc.typechecker;
-import collection.mutable.ListBuffer;
+import util.ListBuffer;
import symtab.Flags._;
class EtaExpansion: Analyzer {
@@ -26,7 +26,8 @@ class EtaExpansion: Analyzer {
* }
* tree is already attributed
*/
- def etaExpand(tree: Tree, tpe: Type): Tree = {
+ def etaExpand(tree: Tree): Tree = {
+ val tpe = tree.tpe;
var cnt = 0;
def freshName() = { cnt = cnt + 1; newTermName("eta$" + cnt) }
val defs = new ListBuffer[Tree];
diff --git a/sources/scala/tools/nsc/typechecker/Infer.scala b/sources/scala/tools/nsc/typechecker/Infer.scala
index 513cb9cc31..5980f46881 100755
--- a/sources/scala/tools/nsc/typechecker/Infer.scala
+++ b/sources/scala/tools/nsc/typechecker/Infer.scala
@@ -10,7 +10,7 @@ class Infer: Analyzer {
import global._;
import definitions._;
import posAssigner.atPos;
- import scala.collection.mutable.ListBuffer;
+ import util.ListBuffer;
/* -- Type parameter inference utility functions -------------------------------------- */
@@ -76,16 +76,17 @@ class Infer: Analyzer {
upper: boolean): List[Type] = {
val config = tvars zip (tparams zip variances);
- def solveOne(tvar: TypeVar, tparam: Symbol, variance: int): unit =
+ def solveOne(tvar: TypeVar, tparam: Symbol, variance: int): unit = {
if (tvar.constr.inst == NoType) {
val up = if (variance != CONTRAVARIANT) upper else !upper;
tvar.constr.inst = null;
val bound: Type = if (up) tparam.info.bounds.hi else tparam.info.bounds.lo;
var cyclic = false;
for (val Pair(tvar2, Pair(tparam2, variance2)) <- config) {
- if ((bound contains tparam2) ||
- up && (tparam2.info.bounds.lo =:= tparam.tpe) ||
- !up && (tparam2.info.bounds.hi =:= tparam.tpe)) {
+ if (tparam2 != tparam &&
+ ((bound contains tparam2) ||
+ up && (tparam2.info.bounds.lo =:= tparam.tpe) ||
+ !up && (tparam2.info.bounds.hi =:= tparam.tpe))) {
if (tvar2.constr.inst == null) cyclic = true;
solveOne(tvar2, tparam2, variance2);
}
@@ -101,7 +102,7 @@ class Infer: Analyzer {
tparam2.tpe.subst(tparams, tvars) :: tvar.constr.hibounds;
}
} else {
- if (bound.symbol != AllClass) {
+ if (bound.symbol != AllClass && bound.symbol != tparam) {
tvar.constr.lobounds =
bound.subst(tparams, tvars) :: tvar.constr.lobounds;
for (val tparam2 <- tparams)
@@ -113,7 +114,7 @@ class Infer: Analyzer {
tvar.constr.inst = if (up) glb(tvar.constr.hibounds) else lub(tvar.constr.lobounds)
}
}
-
+ }
for (val Pair(tvar, Pair(tparam, variance)) <- config) solveOne(tvar, tparam, variance);
tvars map instantiate;
}
@@ -128,7 +129,7 @@ class Infer: Analyzer {
private def normalize(tp: Type): Type = skipImplicit(tp) match {
case MethodType(formals, restpe) => functionType(formals, normalize(restpe))
case PolyType(List(), restpe) => normalize(restpe);
- case _ => tp
+ case tp1 => tp1
}
class TreeSubstituter(tparams: List[Symbol], targs: List[Type]) extends Traverser {
@@ -166,11 +167,6 @@ class Infer: Analyzer {
(if (tree.tpe.paramSectionCount > 0) "" else " of type ") +
tree.tpe;
- def overloadErrorMsg(pre: Type, sym1: Symbol, sym2: Symbol): String =
- "ambiguous reference to overloaded definition,\n" +
- "both " + sym1 + ": " + pre.memberType(sym1) + "\n" +
- "and " + sym2 + ": " + pre.memberType(sym2) + "\nmatch";
-
def applyErrorMsg(tree: Tree, msg: String, argtpes: List[Type], pt: Type) =
treeSymTypeMsg(tree) + msg + argtpes.mkString("(", ",", ")") +
(if (pt == WildcardType) "" else " with expected result type " + pt);
@@ -179,7 +175,7 @@ class Infer: Analyzer {
";\n found : " + found.toLongString + "\n required: " + req;
def error(pos: int, msg: String): unit =
- context.unit.error(pos, msg);
+ context.error(pos, msg);
def errorTree(tree: Tree, msg: String): Tree = {
error(tree.pos, msg);
@@ -202,47 +198,8 @@ class Infer: Analyzer {
setError(tree)
}
- /* -- Views --------------------------------------------------------------- */
-
- def availableViews(argtp: Type): List[Type] = List(); // for now
- def bestView(argtp: Type, pt: Type): Symbol = NoSymbol; // for now
- def bestView(argtp: Type, name: Name): Symbol = NoSymbol; // for now
-
- object inferView extends Inferencer(context) {
- override def availableViews(argtp: Type): List[Type] = List()
- }
-
/* -- Tests & Checks-------------------------------------------------------- */
- /** Is `sym' accessible as a member of tree `site' with type `pre' in current context?
- */
- private def isAccessible(sym: Symbol, pre: Type, site: Tree): boolean = {
-
- /** Are we inside definition of `owner'? */
- def accessWithin(owner: Symbol): boolean = {
- var c = context;
- while (c != NoContext && c.owner != owner) c = c.outer.enclClass;
- c != NoContext;
- }
-
- /** Is `clazz' a subclass of an enclosing class? */
- def isSubClassOfEnclosing(clazz: Symbol): boolean = {
- var c = context;
- while (c != NoContext && !clazz.isSubClass(c.owner)) c = c.outer.enclClass;
- c != NoContext;
- }
-
- pre == NoPrefix
- ||
- (!sym.hasFlag(PRIVATE | PROTECTED))
- ||
- accessWithin(sym.owner)
- ||
- (!sym.hasFlag(PRIVATE) &&
- (site.isInstanceOf[Super] ||
- (pre.widen.symbol.isSubClass(sym.owner) && isSubClassOfEnclosing(pre.widen.symbol))))
- }
-
/** Check that `sym' is defined and accessible as a member of tree `site' with type `pre'
* in current context. */
def checkAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): Tree =
@@ -251,7 +208,7 @@ class Infer: Analyzer {
} else if (sym.owner.hasFlag(INCONSTRUCTOR) && !sym.isTypeParameter && site.isInstanceOf[This]) {
errorTree(tree, "" + sym + " cannot be accessed from constructor");
} else {
- val sym1 = sym filter (alt => isAccessible(alt, pre, site));
+ val sym1 = sym filter (alt => context.isAccessible(alt, pre, site));
if (sym1 == NoSymbol) {
errorTree(tree, sym.toString() + " cannot be accessed in " + pre.widen)
} else {
@@ -262,11 +219,11 @@ class Infer: Analyzer {
def isCompatible(tp: Type, pt: Type): boolean = {
val tp1 = normalize(tp);
- (tp1 <:< pt)/* ||
- (availableViews(tp1) exists (view =>
- inferView.isApplicable(List(), view.methtpe, List(tp1), pt)))*/
+ (tp1 <:< pt) || isCoercible(tp, pt)
}
+ def isCoercible(tp: Type, pt: Type): boolean = false;
+
def isCompatible(tps: List[Type], pts: List[Type]): boolean =
List.map2(tps, pts)((tp, pt) => isCompatible(tp, pt)) forall (x => x);
@@ -478,6 +435,7 @@ class Infer: Analyzer {
uninstantiated.toList;
} catch {
case ex: NoInstance =>
+ System.out.println("error " + fn.pos + " " + fn);//debug
errorTree(fn,
"no type parameters for " +
applyErrorMsg(
@@ -504,9 +462,11 @@ class Infer: Analyzer {
" can be instantiated in more than one way to expected type " + pt +
"\n --- because ---\n" + ex.getMessage());
}
- else
+ else {
+ System.out.println("ici " + tree + " " + undetparams + " " + pt);//debug
errorTree(tree, "constructor cannot be instantiated to expected type" +
foundReqMsg(restpe, pt))
+ }
}
/* -- Overload Resolution ----------------------------------------------------------- */
@@ -526,16 +486,23 @@ class Infer: Analyzer {
{val tp1 = pre.memberType(sym1);
val tp2 = pre.memberType(sym2);
tp2 == ErrorType ||
- !inferView.isCompatible(tp2, pt) && inferView.isCompatible(tp1, pt) ||
+ !global.infer.isCompatible(tp2, pt) && global.infer.isCompatible(tp1, pt) ||
(tp2.paramSectionCount > 0) && (tp1.paramSectionCount == 0 || specializes(tp1, tp2))
});
val best = ((NoSymbol: Symbol) /: alts) ((best, alt) =>
if (improves(alt, best)) alt else best);
val competing = alts dropWhile (alt => best == alt || improves(best, alt));
if (best == NoSymbol) {
+ tree match {//debug
+ case Select(qual, _) =>
+ System.out.println("qual: " + qual + ":" + qual.tpe + " with decls " + qual.tpe.decls + " with members " + qual.tpe.members + " with members " + qual.tpe.member(newTermName("$minus")));
+ case _ =>
+ }
typeErrorTree(tree, tree.symbol.tpe, pt)
} else if (!competing.isEmpty) {
- errorTree(tree, overloadErrorMsg(pre, best, competing.head) + "expected type " + pt)
+ context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt);
+ setError(tree);
+ ()
} else {
tree.setSymbol(best).setType(pre.memberType(best))
}
@@ -551,6 +518,7 @@ class Infer: Analyzer {
*/
def inferMethodAlternative(tree: Tree, undetparams: List[Symbol], argtpes: List[Type], pt: Type): unit = {
val pre = tree.symbol.info.prefix;
+ if (settings.debug.value) System.out.println("infer method alt " + tree.symbol + " with alternatives " + (tree.symbol.alternatives map pre.memberType) + ", argtpes = " + argtpes + ", pt = " + pt);//debug
val alts = tree.symbol.alternatives filter (alt =>
isApplicable(undetparams, pre.memberType(alt), argtpes, pt));
def improves(sym1: Symbol, sym2: Symbol) = {
@@ -568,10 +536,11 @@ class Infer: Analyzer {
inferMethodAlternative(tree, undetparams, argtpes, WildcardType)
}
} else if (!competing.isEmpty) {
- errorTree(tree,
- overloadErrorMsg(pre, best, competing.head) +
- "argument types " + argtpes.mkString("(", ",", ")") +
- (if (pt == WildcardType) "" else " and expected result type " + pt))
+ context.ambiguousError(tree.pos, pre, best, competing.head,
+ "argument types " + argtpes.mkString("(", ",", ")") +
+ (if (pt == WildcardType) "" else " and expected result type " + pt));
+ setError(tree);
+ ()
} else {
tree.setSymbol(best).setType(pre.memberType(best))
}
@@ -591,9 +560,10 @@ class Infer: Analyzer {
"wrong number of type parameters for " + treeSymTypeMsg(tree)
else treeSymTypeMsg(tree) + " does not take type parameters")
} else if (!alts.tail.isEmpty) {
- errorTree(tree,
- overloadErrorMsg(pre, alts.head, alts.tail.head) +
- " polymorphic function with " + nparams + " parameters")
+ context.ambiguousError(tree.pos, pre, alts.head, alts.tail.head,
+ "polymorphic function with " + nparams + " parameters");
+ setError(tree);
+ ()
} else {
tree.setSymbol(alts.head).setType(pre.memberType(alts.head))
}
diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala
index 7b1ac4f6cc..12341ee961 100755
--- a/sources/scala/tools/nsc/typechecker/Namers.scala
+++ b/sources/scala/tools/nsc/typechecker/Namers.scala
@@ -24,7 +24,7 @@ trait Namers: Analyzer {
val typer = new Typer(context);
private def doubleDefError(pos: int, sym: Symbol): unit =
- context.unit.error(pos,
+ context.error(pos,
sym.name.toString() + " is already defined as " +
(if (sym.hasFlag(CASE)) "case class " + sym.name else sym.toString()));
@@ -35,7 +35,7 @@ trait Namers: Analyzer {
val newflags = mods & ~(INITIALIZED | LOCKED);
sym.flags = oldflags | newflags;
if (sym.isModule)
- updatePosFlags(sym.moduleClass, pos, (mods & MODULE2CLASSFLAGS) | MODULE | FINAL);
+ updatePosFlags(sym.moduleClass, pos, (mods & ModuleToClassFlags) | MODULE | FINAL);
sym
}
@@ -85,45 +85,45 @@ trait Namers: Analyzer {
private def enterCaseFactorySymbol(pos: int, mods: int, name: Name): Symbol = {
val m: Symbol = context.scope.lookup(name);
if (m.isModule && !m.isPackage && m.isExternal && context.scope == m.owner.info.decls) {
+ m.resetFlag(MODULE);
updatePosFlags(m, pos, mods)
} else {
enterInScope(context.owner.newMethod(pos, name).setFlag(mods))
}
}
- def enterSyms(trees: List[Tree]): unit =
- for (val tree <- trees) enterSym(tree);
+ def enterSyms(trees: List[Tree]): Namer =
+ (this /: trees) ((namer, tree) => namer.enterSym(tree));
- def enterSym(tree: Tree): Symbol = {
+ def enterSym(tree: Tree): Namer = {
- def finishWith(tparams: List[AbsTypeDef]) = {
+ def finishWith(tparams: List[AbsTypeDef]): unit = {
if (settings.debug.value) log("entered " + tree.symbol);
var ltype: LazyType = typer.typeCompleter(tree);
if (!tparams.isEmpty) {
new Namer(context.makeNewScope(tree, tree.symbol)).enterSyms(tparams);
ltype = new LazyPolyType(tparams map (.symbol), ltype);
}
- tree.symbol.setInfo(ltype)
+ tree.symbol.setInfo(ltype);
}
def finish = finishWith(List());
- if (tree.symbol != null && tree.symbol != NoSymbol) tree.symbol
- else {
+ if (tree.symbol == null || tree.symbol == NoSymbol) {
val owner = context.owner;
tree match {
case PackageDef(name, stats) =>
tree.symbol = enterPackageSymbol(tree.pos, name);
val namer = new Namer(
context.make(tree, tree.symbol.moduleClass, tree.symbol.info.decls));
- stats map namer.enterSym;
- tree.symbol
+ namer.enterSyms(stats);
case ClassDef(mods, name, tparams, _, _) =>
if ((mods & (CASE | ABSTRACT)) == CASE) { // enter case factory method.
tree.symbol = enterCaseFactorySymbol(
- tree.pos, mods & ACCESSFLAGS | CASE, name.toTermName);
- finishWith(tparams map (.duplicate.asInstanceOf[AbsTypeDef]));
+ tree.pos, mods & AccessFlags | CASE, name.toTermName)
+ setInfo typer.caseFactoryCompleter(tree)
}
tree.symbol = enterClassSymbol(tree.pos, mods, name);
+ if (settings.debug.value) System.out.println("entered: " + tree.symbol + flagsToString(tree.symbol.flags));//debug
finishWith(tparams)
case ModuleDef(mods, name, _) =>
tree.symbol = enterModuleSymbol(tree.pos, mods | MODULE | FINAL, name);
@@ -146,7 +146,6 @@ trait Namers: Analyzer {
owner.newValue(tree.pos, name)
.setFlag(mods | PRIVATE | LOCAL).setInfo(typer.typeCompleter(tree))
else getter;
- tree.symbol
} else {
tree.symbol =
enterInScope(owner.newValue(tree.pos, name).setFlag(mods));
@@ -154,7 +153,7 @@ trait Namers: Analyzer {
}
case DefDef(mods, nme.CONSTRUCTOR, tparams, vparams, tp, rhs) =>
tree.symbol = enterInScope(owner.newConstructor(tree.pos))
- .setFlag(mods | owner.getFlag(CONSTRFLAGS));
+ .setFlag(mods | owner.getFlag(ConstrFlags));
finishWith(tparams)
case DefDef(mods, name, tparams, _, _, _) =>
tree.symbol = enterInScope(owner.newMethod(tree.pos, name)).setFlag(mods);
@@ -169,13 +168,13 @@ trait Namers: Analyzer {
enterSym(defn)
case DocDef(_, defn) =>
enterSym(defn)
- case Import(_, _) =>
- tree.symbol = NoSymbol.newImport(tree.pos);
- finish
+ case imp @ Import(_, _) =>
+ tree.symbol = NoSymbol.newImport(tree.pos).setInfo(typer.typeCompleter(tree));
+ return new Namer(context.makeNewImport(imp));
case _ =>
- tree.symbol
}
}
+ this
}
}
}
diff --git a/sources/scala/tools/nsc/typechecker/TypeCheckers.scala b/sources/scala/tools/nsc/typechecker/TypeCheckers.scala
index 3f9b4b41fa..ccc1156b3d 100755
--- a/sources/scala/tools/nsc/typechecker/TypeCheckers.scala
+++ b/sources/scala/tools/nsc/typechecker/TypeCheckers.scala
@@ -5,7 +5,7 @@
// $Id$
package scala.tools.nsc.typechecker;
-import collection.mutable.ListBuffer;
+import nsc.util.ListBuffer;
import symtab.Flags._;
import scala.tools.util.Position;
@@ -22,14 +22,34 @@ trait TypeCheckers: Analyzer {
unit.body = new TypeChecker(startContext.make(unit)).transformExpr(unit.body)
}
- class TypeChecker(context: Context) {
+ class TypeChecker(context0: Context) {
+ import context0.unit;
- import context.unit;
+ val infer = new Inferencer(context0) {
+ override def isCoercible(tp: Type, pt: Type): boolean =
+ context0.reportGeneralErrors && // this condition prevents chains of views
+ inferView(Position.NOPOS, tp, pt, false) != EmptyTree
+ }
+
+ private def inferView(pos: int, from: Type, to: Type, reportAmbiguous: boolean): Tree = {
+ if (settings.debug.value) System.out.println("infer view from " + from + " to " + to);//debug
+ val res = inferImplicit(pos, functionType(List(from), to), true, reportAmbiguous);
+ res
+ }
+
+ private def inferView(pos: int, from: Type, name: Name, reportAmbiguous: boolean): Tree = {
+ val to = refinedType(List(WildcardType), NoSymbol);
+ val psym = (if (name.isTypeName) to.symbol.newAbstractType(pos, name)
+ else to.symbol.newValue(pos, name)) setInfo WildcardType;
+ to.decls.enter(psym);
+ inferView(pos, from, to, reportAmbiguous)
+ }
- val infer = new Inferencer(context);
import infer._;
- object namer extends Namer(context);
+ object namer extends Namer(context0);
+
+ var context = context0;
/** Mode constants
*/
@@ -92,7 +112,9 @@ trait TypeCheckers: Analyzer {
/** Check that type `tree' does not refer to private components unless itself is wrapped
* in something private (`owner' tells where the type occurs). */
- def privates[T <: Tree](owner: Symbol, tree: T): T = check(owner, EmptyScope, tree);
+ def privates[T <: Tree](owner: Symbol, tree: T): T = {
+ check(owner, EmptyScope, tree);
+ }
/** Check that type `tree' does not refer to entities defined in scope `scope'. */
def locals[T <: Tree](scope: Scope, tree: T): T = check(NoSymbol, scope, tree);
@@ -167,8 +189,10 @@ trait TypeCheckers: Analyzer {
* (3) Apply polymorphic types to fresh instances of their type parameters and
* store these instances in context.undetparams,
* unless followed by explicit type application.
- * (4) When in mode EXPRmode but not FUNmode, convert unapplied methods to functions
- * However, if function is `match' or a constructor, issue an error.
+ * (4) In mode EXPRmode but not FUNmode, do the following to unapplied methods:
+ * (4.1) if the method has only implicit parameters, pass implicit arguments
+ * (4.2) otherwise, convert to function by eta-expansion, unless function is
+ * a constructor, in which case we issue an error.
* (5) Convert a class type that serves as a constructor in a pattern as follows:
* (5.1) If this type refers to a case class, set tree's type to the unique
* instance of its primary constructor that is a subtype of the expected type.
@@ -193,29 +217,34 @@ trait TypeCheckers: Analyzer {
case PolyType(List(), restpe) => // (2)
transform(constfold(tree.setType(restpe)), mode, pt);
case PolyType(tparams, restpe) if ((mode & TAPPmode) == 0) => // (3)
+ if (tree.symbol != null) {
+ if (settings.debug.value) System.out.println("adapting " + tree + " " + tree.symbol.tpe + " " + tree.symbol.getClass() + " " + tree.symbol.hasFlag(CASE));//debug
+ }
val tparams1 = tparams map (.cloneSymbol);
+ for (val tparam1 <- tparams1)
+ tparam1.setInfo(tparam1.info.substSym(tparams, tparams1));
val tree1 = if (tree.isType) tree
else TypeApply(tree, tparams1 map (tparam =>
- TypeTree() setPos tparam.pos setType tparam.tpe));
+ TypeTree() setPos tparam.pos setType tparam.tpe)) setPos tree.pos;
context.undetparams = context.undetparams ::: tparams1;
adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt)
- case MethodType(_, _) if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
- isCompatible(tree.tpe, pt)) => // (4)
+ case mt: ImplicitMethodType if ((mode & (EXPRmode | FUNmode)) == EXPRmode) => // (4.1)
+ transform(applyImplicitArgs(tree), mode, pt)
+ case mt: MethodType if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
+ isCompatible(tree.tpe, pt)) => // (4.2)
val meth = treeInfo.methSymbol(tree);
if (meth.isConstructor) errorTree(tree, "missing arguments for " + meth)
- else transform(etaExpand(tree, tree.tpe), mode, pt)
+ else transform(etaExpand(tree), mode, pt)
case _ =>
if (tree.isType) {
val clazz = tree.tpe.symbol;
if ((mode & PATTERNmode) != 0) { // (5)
+ clazz.initialize;
if (clazz.hasFlag(CASE)) { // (5.1)
- val tparams = context.undetparams;
- context.undetparams = List();
- inferConstructorInstance(
- TypeTree() setPos tree.pos
- setType tree.tpe.prefix.memberType(clazz.primaryConstructor),
- tparams, pt);
- tree
+ val tree1 = TypeTree() setPos tree.pos
+ setType tree.tpe.prefix.memberType(clazz.primaryConstructor);
+ inferConstructorInstance(tree1, clazz.typeParams, pt);
+ tree1
} else if (clazz.isSubClass(SeqClass)) { // (5.2)
pt.baseType(clazz).baseType(SeqClass) match {
case TypeRef(pre, seqClass, args) =>
@@ -224,8 +253,10 @@ trait TypeCheckers: Analyzer {
errorTree(tree, "expected pattern type " + pt +
" does not conform to sequence " + clazz)
}
- } else errorTree(tree,
- clazz.toString() + " is neither a case class nor a sequence class")
+ } else {
+ System.out.println("bad: " + clazz + flagsToString(clazz.flags) + clazz.hasFlag(CASE));//debug
+ errorTree(tree, clazz.toString() + " is neither a case class nor a sequence class")
+ }
} else if ((mode & FUNmode) != 0) {
tree
} else if (tree.symbol != null && !tree.symbol.typeParams.isEmpty) { // (7)
@@ -248,16 +279,20 @@ trait TypeCheckers: Analyzer {
} else {
val tree1 = constfold(tree, pt); // (10) (11)
if (tree1 != tree) transform(tree1, mode, pt);
- else if ((mode & EXPRmode) != 0)
- if (pt.symbol == UnitClass && tree1.tpe <:< AnyClass.tpe) // (12)
- transform(Block(List(tree), Literal(())), mode, pt)
- else { // (13)
- val vmeth = bestView(tree.tpe, pt);
- if (vmeth != NoSymbol)
- transform(Apply(Ident(vmeth.name), List(tree)), mode, pt)
- else typeErrorTree(tree, tree.tpe, pt)
- }
- else typeErrorTree(tree, tree.tpe, pt)
+ else {
+ if ((mode & (EXPRmode | FUNmode)) == EXPRmode) {
+ assert(pt != null);
+ assert(tree1.tpe != null, tree1);
+ if (pt.symbol == UnitClass && tree1.tpe <:< AnyClass.tpe) // (12)
+ return transform(Block(List(tree), Literal(())), mode, pt)
+ else if (context.reportGeneralErrors) { // (13); the condition prevents chains of views
+ val coercion = inferView(tree.pos, tree.tpe, pt, true);
+ if (coercion != EmptyTree)
+ return transform(Apply(coercion, List(tree)) setPos tree.pos, mode, pt);
+ }
+ }
+ typeErrorTree(tree, tree.tpe, pt)
+ }
}
}
@@ -271,6 +306,11 @@ trait TypeCheckers: Analyzer {
def parentTypes(templ: Template): List[Tree] = {
var supertpt = transform(templ.parents.head, TYPEmode | FUNmode, WildcardType);
var mixins = templ.parents.tail map transformType;
+ // If first parent is trait, make it first mixin and add its superclass as first parent
+ if (supertpt.tpe.symbol != null && supertpt.tpe.symbol.isTrait) {
+ supertpt = gen.TypeTree(supertpt.tpe.parents(0)) setPos supertpt.pos;
+ mixins = templ.parents
+ }
if (supertpt.symbol != null) {
val tparams = supertpt.symbol.typeParams;
if (!tparams.isEmpty) {
@@ -283,9 +323,6 @@ trait TypeCheckers: Analyzer {
tparams,
vparamss map (.map(.duplicate.asInstanceOf[ValDef])),
superargs map (.duplicate))) setPos supertpt.pos;
- } else if (supertpt.symbol.isTrait) {
- supertpt = gen.TypeTree(supertpt.tpe.parents(0)) setPos supertpt.pos;
- mixins = templ.parents
}
}
(supertpt :: mixins) mapConserve (tpt => checkNoEscaping.privates(context.owner, tpt))
@@ -348,14 +385,14 @@ trait TypeCheckers: Analyzer {
reenterTypeParams(cdef.tparams);
val tparams1 = cdef.tparams mapConserve transformAbsTypeDef;
val tpt1 = checkNoEscaping.privates(clazz.thisSym, transformType(cdef.tpt));
- val impl1 = new TypeChecker(context.make(cdef.impl, clazz, clazz.info.decls))
+ val impl1 = new TypeChecker(context.make(cdef.impl, clazz, new Scope()))
.transformTemplate(cdef.impl);
copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, tpt1, impl1) setType NoType
}
def transformModuleDef(mdef: ModuleDef): Tree = {
val clazz = mdef.symbol.moduleClass;
- val impl1 = new TypeChecker(context.make(mdef.impl, clazz, clazz.info.decls))
+ val impl1 = new TypeChecker(context.make(mdef.impl, clazz, new Scope()))
.transformTemplate(mdef.impl);
copy.ModuleDef(mdef, mdef.mods, mdef.name, impl1) setType NoType
}
@@ -365,16 +402,15 @@ trait TypeCheckers: Analyzer {
def setter: DefDef = {
val sym = vd.symbol;
val setter = sym.owner.info.decls.lookup(nme.SETTER_NAME(sym.name)).suchThat(.hasFlag(ACCESSOR));
- atPos(vd.pos)(
- gen.DefDef(setter, vparamss => gen.Assign(gen.mkRef(vparamss.head.head), gen.mkRef(sym)))
- ).setType(null) // to force type check
+ atPos(vd.pos)(gen.DefDef(
+ setter, vparamss => gen.Assign(gen.mkRef(vparamss.head.head), gen.mkRef(sym))));
}
- def getter: ValDef = {
+ def getter: DefDef = {
val sym = vd.symbol;
val getter = sym.owner.info.decls.lookup(sym.name).suchThat(.hasFlag(ACCESSOR));
- atPos(vd.pos)(
- gen.ValDef(getter, gen.mkRef(sym))
- ).setType(null) // to force type check
+ val result = atPos(vd.pos)(gen.DefDef(getter, vparamss => gen.mkRef(sym)));
+ checkNoEscaping.privates(result.symbol, result.tpt);
+ result
}
if ((mods & MUTABLE) != 0) List(stat, getter, setter) else List(stat, getter)
case _ =>
@@ -386,7 +422,7 @@ trait TypeCheckers: Analyzer {
val parents1 = parentTypes(templ);
validateParentClasses(parents1, context.owner.typeOfThis);
val body1 = templ.body flatMap addGetterSetter;
- val body2 = transformStats(templ.body, templ.symbol);
+ val body2 = transformStats(body1, templ.symbol);
copy.Template(templ, parents1, body2) setType context.owner.tpe
}
@@ -450,13 +486,13 @@ trait TypeCheckers: Analyzer {
if ((mode & INCONSTRmode) != 0) {
val constrCall = transform(block.stats.head, mode, WildcardType);
context.enclClass.owner.resetFlag(INCONSTRUCTOR);
- constrCall :: block.stats.tail mapConserve transformExpr
+ constrCall :: transformStats(block.stats.tail, context.owner);
} else {
- block.stats mapConserve transformExpr
+ transformStats(block.stats, context.owner)
}
val expr1 = transform(block.expr, mode & ~(FUNmode | QUALmode), pt);
- checkNoEscaping.locals(
- context.scope, copy.Block(block, stats1, expr1) setType expr1.tpe.deconst)
+ val block1 = copy.Block(block, stats1, expr1) setType expr1.tpe.deconst;
+ if (isFullyDefined(pt)) block1 else checkNoEscaping.locals(context.scope, block1)
}
def transformCase(cdef: CaseDef, pattpe: Type, pt: Type): CaseDef = {
@@ -484,7 +520,8 @@ trait TypeCheckers: Analyzer {
if (argpt == NoType) { error(vparam.pos, "missing parameter type"); ErrorType }
else argpt
}
- namer.enterSym(vparam)
+ namer.enterSym(vparam);
+ vparam.symbol
}
val vparams1 = fun.vparams mapConserve transformValDef;
val body1 = transform(fun.body, EXPRmode, respt);
@@ -493,7 +530,8 @@ trait TypeCheckers: Analyzer {
}
def transformRefinement(stats: List[Tree]): List[Tree] = {
- for (val stat <- stats) namer.enterSym(stat) setFlag OVERRIDE;
+ namer.enterSyms(stats);
+ for (val stat <- stats) stat.symbol setFlag OVERRIDE;
transformStats(stats, NoSymbol);
}
@@ -501,8 +539,14 @@ trait TypeCheckers: Analyzer {
stats mapConserve { stat =>
if (context.owner.isRefinementClass && !treeInfo.isDeclaration(stat))
errorTree(stat, "only declarations allowed here");
- (if (stat.isDef) TypeChecker.this
- else new TypeChecker(context.make(stat, exprOwner))).transformExpr(stat)
+ stat match {
+ case imp @ Import(_, _) =>
+ context = context.makeNewImport(imp);
+ EmptyTree
+ case _ =>
+ (if (stat.isDef && exprOwner != context.owner)
+ new TypeChecker(context.make(stat, exprOwner)) else this).transformExpr(stat)
+ }
}
private def transform1(tree: Tree, mode: int, pt: Type): Tree = {
@@ -510,8 +554,8 @@ trait TypeCheckers: Analyzer {
def funmode = mode & stickyModes | FUNmode | POLYmode;
def transformCases(cases: List[CaseDef], pattp: Type): List[CaseDef] = {
- val tc1 = new TypeChecker(context.makeNewScope(tree, context.owner));
- cases mapConserve (cdef => tc1.transformCase(cdef, pattp, pt))
+ cases mapConserve (cdef => new TypeChecker(context.makeNewScope(tree, context.owner))
+ .transformCase(cdef, pattp, pt))
}
def transformTypeApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match {
@@ -522,7 +566,7 @@ trait TypeCheckers: Analyzer {
if (tparams.length == args.length) {
val targs = args map (.tpe);
checkBounds(tree.pos, tparams, targs, "");
- System.out.println("type app " + tparams + " => " + targs + " = " + restpe.subst(tparams, targs));//debug
+ if (settings.debug.value) System.out.println("type app " + tparams + " => " + targs + " = " + restpe.subst(tparams, targs));//debug
copy.TypeApply(tree, fun, args) setType restpe.subst(tparams, targs);
} else {
errorTree(tree, "wrong number of type parameters for " + treeSymTypeMsg(fun))
@@ -571,6 +615,7 @@ trait TypeCheckers: Analyzer {
val args1 = List.map2(args, formals)(transformArg);
if (args1 exists (.tpe.isError)) setError(tree)
else {
+ if (settings.debug.value) System.out.println("infer method inst " + fun + ", tparams = " + tparams + ", args = " + args1.map(.tpe) + ", pt = " + pt + ", lobounds = " + tparams.map(.tpe.bounds.lo));//debug
val undetparams = inferMethodInstance(fun, tparams, args1, pt);
val result = transformApply(fun, args1);
context.undetparams = undetparams;
@@ -607,15 +652,21 @@ trait TypeCheckers: Analyzer {
*/
def transformSelect(qual: Tree, name: Name): Tree = {
val sym = qual.tpe.member(name);
- if (sym == NoSymbol && qual.isTerm) {
- val vmeth = bestView(qual.tpe, name);
- if (vmeth != NoSymbol)
- return transform(Select(Apply(Ident(vmeth.name), List(qual)), name), mode, pt)
+ if (sym == NoSymbol && qual.isTerm && (qual.symbol == null || qual.symbol.isValue)) {
+ val coercion = inferView(qual.pos, qual.tpe, name, true);
+ if (coercion != EmptyTree)
+ return transform(
+ copy.Select(tree, Apply(coercion, List(qual)) setPos qual.pos, name), mode, pt)
}
if (sym.info == NoType)
errorTree(tree, decode(name) + " is not a member of " + qual.tpe.widen)
- else
- stabilize(checkAccessible(tree, sym, qual.tpe, qual), qual.tpe)
+ else {
+ val tree1 = tree match {
+ case Select(_, _) => copy.Select(tree, qual, name)
+ case SelectFromTypeTree(_, _) => copy.SelectFromTypeTree(tree, qual, name);
+ }
+ stabilize(checkAccessible(tree1, sym, qual.tpe, qual), qual.tpe)
+ }
}
/** Attribute an identifier consisting of a simple name or an outer reference.
@@ -634,8 +685,8 @@ trait TypeCheckers: Analyzer {
var cx = context;
while (defSym == NoSymbol && cx != NoContext) {
- defEntry = cx.scope.lookupEntry(name);
- pre = cx.enclClass.owner.thisType;
+ pre = cx.enclClass.owner.thisType;
+ defEntry = cx.scope.lookupEntry(name);
if (defEntry != null) defSym = defEntry.sym
else {
cx = cx.enclClass;
@@ -671,7 +722,7 @@ trait TypeCheckers: Analyzer {
var impSym1 = NoSymbol;
var imports1 = imports.tail;
def ambiguousImportError = ambiguousError(
- "it is imported twice in the same scope by\n" + impSym + "\nand " + impSym1);
+ "it is imported twice in the same scope by\n" + imports.head + "\nand " + imports1.head);
while (!imports1.isEmpty && imports1.head.depth == imports.head.depth) {
var impSym1 = imports1.head.importedSymbol(name);
if (impSym1 != NoSymbol) {
@@ -679,15 +730,16 @@ trait TypeCheckers: Analyzer {
if (imports.head.isExplicitImport(name)) ambiguousImportError;
impSym = impSym1;
imports = imports1;
- }
- if (imports.head.isExplicitImport(name)) impSym1 = NoSymbol;
+ } else if (!imports.head.isExplicitImport(name)) ambiguousImportError
}
+ imports1 = imports1.tail;
}
- if (impSym1 != NoSymbol) ambiguousImportError;
defSym = impSym;
qual = imports.head.qual;
pre = qual.tpe;
} else {
+ System.out.println(context);//debug
+ System.out.println(context.imports);//debug
error(tree.pos, "not found: " + decode(name));
defSym = context.owner.newErrorSymbol(name);
}
@@ -707,8 +759,9 @@ trait TypeCheckers: Analyzer {
case PolyType(List(), restp @ ConstantType(base, value)) => // (1)
Literal(value) setPos tree.pos setType restp
case _ =>
- if (tree.symbol.hasFlag(OVERLOADED) && (mode & FUNmode) == 0)
- inferExprAlternative(tree, pt);
+ if (tree.symbol.hasFlag(OVERLOADED) && (mode & FUNmode) == 0) {
+ inferExprAlternative(tree, pt)
+ }
if ((mode & (PATTERNmode | FUNmode)) == PATTERNmode && tree.isTerm) // (2)
checkStable(tree)
else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && !tree.symbol.isValue) // (3)
@@ -721,10 +774,9 @@ trait TypeCheckers: Analyzer {
}
// begin transform1
- System.out.println("transforming " + tree);//debug
val sym: Symbol = tree.symbol;
if (sym != null) sym.initialize;
- if (settings.debug.value && tree.isDef) global.log("transforming definition of " + sym);
+ //if (settings.debug.value && tree.isDef) global.log("transforming definition of " + sym);//DEBUG
tree match {
case PackageDef(name, stats) =>
val stats1 = new TypeChecker(context.make(tree, sym.moduleClass, sym.info.decls))
@@ -732,10 +784,7 @@ trait TypeCheckers: Analyzer {
copy.PackageDef(tree, name, stats1) setType NoType
case cdef @ ClassDef(_, _, _, _, _) =>
- val result = new TypeChecker(context.makeNewScope(tree, sym)).transformClassDef(cdef);
- System.out.println("entered: " + result.symbol);//debug
- result
-
+ new TypeChecker(context.makeNewScope(tree, sym)).transformClassDef(cdef)
case mdef @ ModuleDef(_, _, _) =>
transformModuleDef(mdef)
@@ -755,9 +804,6 @@ trait TypeCheckers: Analyzer {
case ldef @ LabelDef(_, List(), _) =>
new TypeChecker(context.makeNewScope(tree, context.owner)).transformLabelDef(ldef)
- case Import(_, _) =>
- EmptyTree
-
case Attributed(attr, defn) =>
val attr1 = transform(attr, EXPRmode, AttributeClass.tpe);
val defn1 = transform(defn, mode, pt);
@@ -786,7 +832,8 @@ trait TypeCheckers: Analyzer {
case Bind(name, body) =>
val body1 = transform(body, mode, pt);
val vble = context.owner.newValue(tree.pos, name).setInfo(
- if (treeInfo.isSequenceValued(body)) seqType(pt) else pt);
+ if (treeInfo.isSequenceValued(body)) seqType(pt) else body1.tpe);
+ //todo: check whether we can always use body1.tpe
namer.enterInScope(vble);
copy.Bind(tree, name, body1) setSymbol vble setType pt
@@ -801,18 +848,17 @@ trait TypeCheckers: Analyzer {
}
val lhs1 = transformExpr(lhs);
val varsym = lhs1.symbol;
- System.out.println("" + lhs1 + " " + " " + lhs1.getClass() + varsym);//debug
if (varsym != null && isGetter(varsym)) {
lhs1 match {
case Select(qual, name) =>
transform(Apply(Select(qual, nme.SETTER_NAME(name)), List(rhs)), mode, pt)
}
} else if (varsym != null && varsym.isVariable) {
- val rhs1 = transform(rhs, EXPRmode, lhs.tpe);
+ val rhs1 = transform(rhs, EXPRmode, lhs1.tpe);
copy.Assign(tree, lhs1, rhs1) setType UnitClass.tpe;
} else {
System.out.println("" + lhs1 + " " + " " + lhs1.getClass() + varsym);//debug
- if (!lhs.tpe.isError) error(tree.pos, "assignment to non-variable ");
+ if (!lhs1.tpe.isError) error(tree.pos, "assignment to non-variable ");
setError(tree)
}
@@ -931,15 +977,19 @@ trait TypeCheckers: Analyzer {
case RefinedType(parents, _) => qual1.tpe = parents.head;
case _ =>
}
- transformSelect(qual1, nme.CONSTRUCTOR);
+ transformSelect(qual1, nme.CONSTRUCTOR);
case Select(qual, name) =>
var qual1 = transform(qual, EXPRmode | QUALmode | POLYmode, WildcardType);
if (name.isTypeName) qual1 = checkStable(qual1);
- transformSelect(qual1, name);
+ val res = transformSelect(qual1, name);
+ res
case Ident(name) =>
- transformIdent(name)
+ if (name == nme.WILDCARD && (mode & (PATTERNmode | FUNmode)) == PATTERNmode)
+ tree setType pt
+ else
+ transformIdent(name);
case Literal(value) =>
tree setType literalType(value)
@@ -958,14 +1008,14 @@ trait TypeCheckers: Analyzer {
else {
val decls = new Scope();
val self = refinedType(parents1 map (.tpe), context.enclClass.owner, decls);
- new TypeChecker(context.make(tree, self.symbol, decls)).transformRefinement(templ.body);
+ new TypeChecker(context.make(tree, self.symbol, new Scope())).transformRefinement(templ.body);
self
}
}
case AppliedTypeTree(tpt, args) =>
val tpt1 = transform(tpt, mode | FUNmode | TAPPmode, WildcardType);
- val tparams = tpt1.tpe.symbol.typeParams;
+ val tparams = tpt1.tpe.symbol.info.typeParams;
val args1 = args mapConserve transformType;
if (tpt1.tpe.isError)
setError(tree)
@@ -980,21 +1030,85 @@ trait TypeCheckers: Analyzer {
def transform(tree: Tree, mode: int, pt: Type): Tree =
try {
- if (tree.tpe != null) tree
- else {
- val tree1 = transform1(tree, mode, pt);
- System.out.println("transformed " + tree1 + ":" + tree1.tpe);//debug
- adapt(tree1, mode, pt)
- }
+ if (settings.debug.value) assert(pt != null, tree);//debug
+ val tree1 = if (tree.tpe != null) tree else transform1(tree, mode, pt);
+ if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt)
} catch {
case ex: TypeError =>
reportTypeError(tree.pos, ex);
setError(tree)
+ case ex: Throwable =>
+ if (settings.debug.value)
+ System.out.println("exception when tranforming " + tree + ", pt = " + pt);
+ throw(ex)
}
def transformExpr(tree: Tree): Tree = transform(tree, EXPRmode, WildcardType);
def transformQualExpr(tree: Tree): Tree = transform(tree, EXPRmode | QUALmode, WildcardType);
def transformType(tree: Tree) = transform(tree, TYPEmode, WildcardType);
+
+ /* -- Views --------------------------------------------------------------- */
+
+ private def transformImplicit(pos: int, info: ImplicitInfo, pt: Type): Tree =
+ if (isCompatible(info.tpe, pt)) {
+ var tree: Tree = EmptyTree;
+ try {
+ tree = transform1(Ident(info.name) setPos pos, EXPRmode, pt);
+ if (settings.debug.value) System.out.println("transformed implicit " + tree + ":" + tree.tpe + ", pt = " + pt);//debug
+ if (settings.debug.value) assert(isCompatible(tree.tpe, pt), "bad impl " + info.tpe + " " + tree.tpe + " " + pt);//debug
+ val tree1 = adapt(tree, EXPRmode, pt);
+ if (settings.debug.value) System.out.println("adapted implicit " + tree.symbol + ":" + info.sym);//debug
+ if (info.sym == tree.symbol) tree1 else EmptyTree
+ } catch {
+ case ex: TypeError =>
+ if (settings.debug.value)
+ System.out.println(tree.toString() + " is not a valid implicit value because:\n" + ex.getMessage());
+ EmptyTree
+ }
+ } else EmptyTree;
+
+ private def inferImplicit(pos: int, pt: Type, isView: boolean, reportAmbiguous: boolean): Tree = {
+ val tc = new TypeChecker(context.makeImplicit(reportAmbiguous));
+ var iss = context.implicitss;
+ var tree: Tree = EmptyTree;
+ while (tree == EmptyTree && !iss.isEmpty) {
+ var is = iss.head;
+ if (settings.debug.value) System.out.println("testing " + is.head.sym + ":" + is.head.tpe);//debug
+ iss = iss.tail;
+ while (!is.isEmpty) {
+ tree = tc.transformImplicit(pos, is.head, pt);
+ val is0 = is;
+ is = is.tail;
+ if (tree != EmptyTree) {
+ while (!is.isEmpty) {
+ val tree1 = tc.transformImplicit(pos, is.head, pt);
+ if (tree1 != EmptyTree)
+ error(pos,
+ "ambiguous implicit value:\n" +
+ " both " + is0.head.sym + is0.head.sym.locationString +
+ "\n and" + is.head.sym + is.head.sym.locationString +
+ (if (isView)
+ "\n are possible conversion functions from " +
+ pt.typeArgs(0) + " to " + pt.typeArgs(1)
+ else
+ "\n match expected type " + pt));
+ is = is.tail
+ }
+ }
+ }
+ }
+ tree
+ }
+
+ def applyImplicitArgs(tree: Tree): Tree = tree.tpe match {
+ case MethodType(formals, _) =>
+ def implicitArg(pt: Type) = {
+ val arg = inferImplicit(tree.pos, pt, false, true);
+ if (arg != EmptyTree) arg
+ else errorTree(tree, "no implicit argument matching parameter type " + pt + " was found.")
+ }
+ Apply(tree, formals map implicitArg) setPos tree.pos
+ }
}
}
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index 441d6ab1e5..eb3df2491d 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -16,7 +16,6 @@ trait Typers: Analyzer {
abstract class TypeCompleter(val tree: Tree) extends LazyType;
class Typer(context: Context) {
- import context.unit;
val typechecker = new TypeChecker(context);
@@ -53,13 +52,23 @@ trait Typers: Analyzer {
}
}
+ def caseFactoryCompleter(tree: Tree) = new TypeCompleter(tree) {
+ override def complete(sym: Symbol): unit = {
+ val clazz = tree.symbol;
+ var tpe = clazz.primaryConstructor.tpe;
+ val tparams = clazz.typeParams;
+ if (!tparams.isEmpty) tpe = PolyType(tparams, tpe).cloneInfo(sym);
+ sym.setInfo(tpe);
+ }
+ }
+
private def deconstIfNotFinal(sym: Symbol, tpe: Type): Type =
if (sym.isVariable || sym.hasFlag(FINAL)) tpe.deconst else tpe;
def enterValueParams(owner: Symbol, vparamss: List[List[ValDef]]): List[List[Symbol]] = {
def enterValueParam(param: ValDef): Symbol = {
param.symbol = owner.newValueParameter(param.pos, param.name)
- .setInfo(typeCompleter(param));
+ .setInfo(typeCompleter(param)).setFlag(param.mods & IMPLICIT);
context.scope enter param.symbol;
param.symbol
}
@@ -80,7 +89,8 @@ trait Typers: Analyzer {
val parents = typechecker.parentTypes(templ) map (.tpe);
val decls = new Scope();
new Namer(context.make(templ, clazz, decls)).enterSyms(templ.body);
- ClassInfoType(parents, decls, clazz) }
+ ClassInfoType(parents, decls, clazz)
+ }
private def classSig(tparams: List[AbsTypeDef], tpt: Tree, impl: Template): Type = {
val tparamSyms = typechecker.reenterTypeParams(tparams);
@@ -91,6 +101,7 @@ trait Typers: Analyzer {
}
private def methodSig(tparams: List[AbsTypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): Type = {
+ def checkContractive: unit = {}; //todo: complete
val meth = context.owner;
val tparamSyms = typechecker.reenterTypeParams(tparams);
val vparamSymss = enterValueParams(meth, vparamss);
@@ -100,8 +111,14 @@ trait Typers: Analyzer {
else typechecker.transformExpr(rhs).tpe;
tpt.tpe
} else typechecker.transformType(tpt).tpe);
- def mkMethodType(vparams: List[Symbol], restpe: Type) =
- MethodType(vparams map (.tpe), restpe);
+ def mkMethodType(vparams: List[Symbol], restpe: Type) = {
+ val formals = vparams map (.tpe);
+ if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT)) {
+ if (settings.debug.value) System.out.println("create implicit");//debug
+ checkContractive;
+ new ImplicitMethodType(formals, restpe)
+ } else MethodType(formals, restpe);
+ }
makePolyType(
tparamSyms,
if (vparamSymss.isEmpty) PolyType(List(), restype)
@@ -130,7 +147,7 @@ trait Typers: Analyzer {
deconstIfNotFinal(sym,
if (tpt.isEmpty)
if (rhs.isEmpty) {
- unit.error(tpt.pos, "missing parameter type");
+ context.error(tpt.pos, "missing parameter type");
ErrorType
} else {
tpt.tpe = new TypeChecker(context.make(tree, sym))
@@ -153,9 +170,11 @@ trait Typers: Analyzer {
case Pair(from, to) :: rest =>
if (from != nme.WILDCARD && base != ErrorType &&
base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol)
- unit.error(tree.pos, from.decode + " is not a member of " + expr);
+ context.error(tree.pos, from.decode + " is not a member of " + expr);
+ if (from != nme.WILDCARD && (rest.exists (sel => sel._1 == from)))
+ context.error(tree.pos, from.decode + " is renamed twice");
if (to != null && to != nme.WILDCARD && (rest exists (sel => sel._2 == to)))
- unit.error(tree.pos, to.decode + " appears twice as a target of a renaming");
+ context.error(tree.pos, to.decode + " appears twice as a target of a renaming");
checkSelectors(rest)
case Nil =>
}
@@ -178,24 +197,26 @@ trait Typers: Analyzer {
def validate(sym: Symbol): unit = {
def checkNoConflict(flag1: int, flag2: int): unit =
if (sym.hasFlag(flag1) && sym.hasFlag(flag2))
- unit.error(sym.pos,
+ context.error(sym.pos,
if (flag1 == DEFERRED)
"abstract member may not have " + Flags.flagsToString(flag2) + " modifier";
else
"illegal combination of modifiers: " +
Flags.flagsToString(flag1) + " and " + Flags.flagsToString(flag2));
+ if (sym.hasFlag(IMPLICIT) && !sym.isTerm)
+ context.error(sym.pos, "`implicit' modifier can be used only for values, variables and methods");
if (sym.hasFlag(ABSTRACT) && !sym.isClass)
- unit.error(sym.pos, "`abstract' modifier can be used only for classes; " +
+ context.error(sym.pos, "`abstract' modifier can be used only for classes; " +
"\nit should be omitted for abstract members");
if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isClass)
- unit.error(sym.pos, "`override' modifier not allowed for classes");
+ context.error(sym.pos, "`override' modifier not allowed for classes");
if (sym.info.symbol == definitions.FunctionClass(0) &&
sym.isValueParameter && sym.owner.isClass && sym.owner.hasFlag(CASE))
- unit.error(sym.pos, "pass-by-name arguments not allowed for case class parameters");
+ context.error(sym.pos, "pass-by-name arguments not allowed for case class parameters");
if ((sym.flags & DEFERRED) != 0) {
if (!sym.isValueParameter && !sym.isTypeParameter &&
(!sym.owner.isClass || sym.owner.isModuleClass || sym.owner.isAnonymousClass)) {
- unit.error(sym.pos,
+ context.error(sym.pos,
"only classes can have declared but undefined members" +
(if (!sym.isVariable) ""
else "\n(Note that variables need to be initialized to be defined)"));
diff --git a/sources/scala/tools/nsc/util/LinkedList.scala b/sources/scala/tools/nsc/util/LinkedList.scala
new file mode 100644
index 0000000000..375e6ca615
--- /dev/null
+++ b/sources/scala/tools/nsc/util/LinkedList.scala
@@ -0,0 +1,11 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id$
+package scala.tools.nsc.util;
+
+class LinkedList[T] {
+ var next: LinkedList[T] = null;
+ var elem: T = _;
+}
diff --git a/sources/scala/tools/nsc/util/ListBuffer.scala b/sources/scala/tools/nsc/util/ListBuffer.scala
new file mode 100644
index 0000000000..bdc09412eb
--- /dev/null
+++ b/sources/scala/tools/nsc/util/ListBuffer.scala
@@ -0,0 +1,58 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id$
+package scala.tools.nsc.util;
+
+class ListBuffer[T] extends Iterator[T] {
+
+ private var first = new LinkedList[T];
+ private var limit = first;
+
+ def +=(x: T): unit = {
+ limit.elem = x;
+ limit.next = new LinkedList[T];
+ limit = limit.next;
+ }
+
+ def ++=(xs: Iterable[T]): unit =
+ for (val x <- xs.elements) +=(x);
+
+ def +(x: T): ListBuffer[T] = { +=(x); this }
+ def ++(xs: Iterable[T]): ListBuffer[T] = { ++=(xs); this }
+
+ def hasNext: boolean =
+ first != limit;
+
+ def next: T = {
+ assert(hasNext);
+ val x = first.elem;
+ first = first.next;
+ x
+ }
+
+ def elements: Iterator[T] = new Iterator[T] {
+ var first = ListBuffer.this.first;
+
+ def hasNext: boolean =
+ first != limit;
+
+ def next: T = {
+ assert(hasNext);
+ val x = first.elem;
+ first = first.next;
+ x
+ }
+ }
+
+ def clear: unit = { first = limit }
+
+ /** override for efficiency */
+ override def toList: List[T] = {
+ def mkList(p: LinkedList[T]): List[T] = if (p == limit) List() else p.elem :: mkList(p.next);
+ mkList(first)
+ }
+
+ override def toString(): String = toList.mkString("", ",", "");
+}