summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-08-29 14:38:38 +0000
committerMartin Odersky <odersky@gmail.com>2005-08-29 14:38:38 +0000
commit184a284ccc9c842adaaec728914f11a2cad33c18 (patch)
tree25ae4ff123300b6dc24f4c1a2ec0182105e75ec6 /sources
parent7d50bd127a071b84cc3d5e6e989b5f57d5988aaf (diff)
downloadscala-184a284ccc9c842adaaec728914f11a2cad33c18.tar.gz
scala-184a284ccc9c842adaaec728914f11a2cad33c18.tar.bz2
scala-184a284ccc9c842adaaec728914f11a2cad33c18.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rwxr-xr-xsources/scala/tools/nsc/Global.scala18
-rw-r--r--sources/scala/tools/nsc/Phase.scala1
-rwxr-xr-xsources/scala/tools/nsc/ast/TreeGen.scala13
-rw-r--r--sources/scala/tools/nsc/ast/TreeInfo.scala20
-rw-r--r--sources/scala/tools/nsc/ast/TreePrinters.scala2
-rw-r--r--sources/scala/tools/nsc/ast/Trees.scala27
-rwxr-xr-xsources/scala/tools/nsc/ast/parser/Parsers.scala9
-rw-r--r--sources/scala/tools/nsc/ast/parser/TreeBuilder.scala7
-rw-r--r--sources/scala/tools/nsc/backend/icode/GenICode.scala2
-rw-r--r--sources/scala/tools/nsc/matching/BerrySethis.scala6
-rw-r--r--sources/scala/tools/nsc/matching/DetWordAutoms.scala14
-rw-r--r--sources/scala/tools/nsc/matching/LeftTracers.scala4
-rw-r--r--sources/scala/tools/nsc/matching/PatternMatchers.scala5
-rw-r--r--sources/scala/tools/nsc/matching/PatternNodes.scala2
-rw-r--r--sources/scala/tools/nsc/matching/RightTracers.scala4
-rw-r--r--sources/scala/tools/nsc/matching/TransMatcher.scala24
-rw-r--r--sources/scala/tools/nsc/matching/WordAutoms.scala2
-rwxr-xr-xsources/scala/tools/nsc/symtab/Definitions.scala16
-rw-r--r--sources/scala/tools/nsc/symtab/Flags.scala14
-rwxr-xr-xsources/scala/tools/nsc/symtab/StdNames.scala6
-rwxr-xr-xsources/scala/tools/nsc/symtab/SymbolLoaders.scala2
-rwxr-xr-xsources/scala/tools/nsc/symtab/Symbols.scala90
-rwxr-xr-xsources/scala/tools/nsc/symtab/Types.scala11
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/PickleFormat.scala2
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/Pickler.scala17
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/UnPickler.scala18
-rwxr-xr-xsources/scala/tools/nsc/transform/AddInterfaces.scala51
-rwxr-xr-xsources/scala/tools/nsc/transform/Erasure.scala136
-rwxr-xr-xsources/scala/tools/nsc/transform/ExplicitOuter.scala132
-rwxr-xr-xsources/scala/tools/nsc/transform/Flatten.scala91
-rwxr-xr-xsources/scala/tools/nsc/transform/LambdaLift.scala317
-rw-r--r--sources/scala/tools/nsc/transform/TailCalls.scala3
-rw-r--r--sources/scala/tools/nsc/transform/Transform.scala2
-rwxr-xr-xsources/scala/tools/nsc/transform/UnCurry.scala12
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Namers.scala32
-rwxr-xr-xsources/scala/tools/nsc/typechecker/RefChecks.scala44
-rw-r--r--sources/scala/tools/nsc/typechecker/TreeCheckers.scala35
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala107
-rwxr-xr-xsources/scala/tools/nsc/util/HashSet.scala2
-rwxr-xr-xsources/scala/tools/nsc/util/Set.scala23
-rwxr-xr-xsources/scala/tools/nsc/util/TreeSet.scala52
41 files changed, 1048 insertions, 327 deletions
diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala
index 2f6f1e6075..4186eab583 100755
--- a/sources/scala/tools/nsc/Global.scala
+++ b/sources/scala/tools/nsc/Global.scala
@@ -56,8 +56,13 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
val copy = new LazyTreeCopier();
type AttrInfo = Pair[Type, List[Any]];
+
+ /** A map from symbols to their attributes */
val attributes = new HashMap[Symbol, List[AttrInfo]];
+ /** A map from parameter accessor symbols to their aliases */
+ val aliases = new HashMap[Symbol, Symbol];
+
// reporting -------------------------------------------------------
def error(msg: String) = reporter.error(null, msg);
@@ -144,6 +149,8 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
def apply(unit: CompilationUnit): unit;
private val isErased = prev.name == "erasure" || prev.erasedTypes;
override def erasedTypes: boolean = isErased;
+ private val isFlat = prev.name == "flatten" || prev.flatClasses;
+ override def flatClasses: boolean = isFlat;
def applyPhase(unit: CompilationUnit): unit = {
if (settings.debug.value) inform("[running phase " + name + " on " + unit + "]");
apply(unit)
@@ -186,6 +193,14 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
val global: Global.this.type = Global.this;
}
+ object lambdaLift extends LambdaLift {
+ val global: Global.this.type = Global.this;
+ }
+
+ object flatten extends Flatten {
+ val global: Global.this.type = Global.this;
+ }
+
object sampleTransform extends SampleTransform {
val global: Global.this.type = Global.this;
}
@@ -208,6 +223,8 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
transMatcher,
explicitOuter,
erasure,
+ lambdaLift,
+ flatten,
if (settings.Xshowicode.value) genicode
else sampleTransform);
@@ -239,6 +256,7 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
val namerPhase = phaseNamed("namer");
val typerPhase = phaseNamed("typer");
+ val refchecksPhase = phaseNamed("refchecks");
val erasurePhase = phaseNamed("erasure");
val typer = new analyzer.Typer(analyzer.NoContext.make(EmptyTree, definitions.RootClass, new Scope())) {
diff --git a/sources/scala/tools/nsc/Phase.scala b/sources/scala/tools/nsc/Phase.scala
index 536cd81390..31410ce162 100644
--- a/sources/scala/tools/nsc/Phase.scala
+++ b/sources/scala/tools/nsc/Phase.scala
@@ -23,6 +23,7 @@ abstract class Phase(val prev: Phase) {
def name: String;
def description: String = name;
def erasedTypes: boolean = false;
+ def flatClasses: boolean = false;
def run: unit;
override def toString() = name;
diff --git a/sources/scala/tools/nsc/ast/TreeGen.scala b/sources/scala/tools/nsc/ast/TreeGen.scala
index 4602059037..453ecced91 100755
--- a/sources/scala/tools/nsc/ast/TreeGen.scala
+++ b/sources/scala/tools/nsc/ast/TreeGen.scala
@@ -66,6 +66,17 @@ abstract class TreeGen {
tree
}
+ /** Cast `tree' to type `pt' */
+ def cast(tree: Tree, pt: Type): Tree = {
+ if (settings.debug.value) log("casting " + tree + ":" + tree.tpe + " to " + pt);
+ assert(!tree.tpe.isInstanceOf[MethodType], tree);
+ typer.typed {
+ atPos(tree.pos) {
+ Apply(TypeApply(Select(tree, Object_asInstanceOf), List(TypeTree(pt))), List())
+ }
+ }
+ }
+
/** Builds a reference with stable type to given symbol */
def mkStableRef(pre: Type, sym: Symbol): Tree = stabilize(mkRef(pre, sym));
def mkStableRef(sym: Symbol): Tree = stabilize(mkRef(sym));
@@ -75,13 +86,11 @@ abstract class TreeGen {
def Ident(sym: Symbol) = {
assert(sym.isTerm);
- sym.setFlag(ACCESSED);
global.Ident(sym.name) setSymbol sym setType sym.tpe;
}
def Select(qual: Tree, sym: Symbol) = {
assert(sym.isTerm);
- sym.setFlag(ACCESSED);
val result = global.Select(qual, sym.name) setSymbol sym;
if (qual.tpe != null) result setType qual.tpe.memberType(sym);
result
diff --git a/sources/scala/tools/nsc/ast/TreeInfo.scala b/sources/scala/tools/nsc/ast/TreeInfo.scala
index 0b18c18b4e..d0bd3011ea 100644
--- a/sources/scala/tools/nsc/ast/TreeInfo.scala
+++ b/sources/scala/tools/nsc/ast/TreeInfo.scala
@@ -94,19 +94,6 @@ abstract class TreeInfo {
false
}
- /** Is tree a pure constructor?
- */
- def isPureConstr(tree: Tree): boolean = tree match {
- case Ident(_) | Select(_, _) =>
- tree.symbol.isPrimaryConstructor
- case TypeApply(fn, _) =>
- isPureConstr(fn)
- case Apply(fn, List()) =>
- isPureConstr(fn)
- case _ =>
- false
- }
-
/** Is tree a self constructor call?
*/
def isSelfConstrCall(tree: Tree): boolean = tree match {
@@ -151,6 +138,13 @@ abstract class TreeInfo {
case _ => false
}
+ /** Is this pattern node a catch-all (wildcard or variable) pattern? */
+ def isDefaultCase(cdef: CaseDef) = cdef match {
+ case CaseDef(Ident(nme.WILDCARD), EmptyTree, _) => true
+ case CaseDef(Bind(_, Ident(nme.WILDCARD)), EmptyTree, _) => true
+ case _ => false
+ }
+
/** Is this pattern node a sequence-valued pattern? */
def isSequenceValued(tree: Tree): boolean = tree match {
case Bind(_, body) => isSequenceValued(body)
diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala
index fbf017fdbc..49dd0a3b05 100644
--- a/sources/scala/tools/nsc/ast/TreePrinters.scala
+++ b/sources/scala/tools/nsc/ast/TreePrinters.scala
@@ -272,7 +272,7 @@ abstract class TreePrinters {
case ClassDef(_, _, _, _, impl) => ClassDef(tree.symbol, impl)
case ModuleDef(_, _, impl) => ModuleDef(tree.symbol, impl)
case ValDef(_, _, _, rhs) => ValDef(tree.symbol, rhs)
- case DefDef(_, _, _, vparamss, _, rhs) => DefDef(tree.symbol, vparamss => rhs)
+ case DefDef(_, _, _, vparamss, _, rhs) => DefDef(tree.symbol, vparamss, rhs)
case AbsTypeDef(_, _, _, _) => AbsTypeDef(tree.symbol)
case AliasTypeDef(_, _, _, rhs) => AliasTypeDef(tree.symbol, rhs)
case _ => tree
diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala
index ed680a8814..cdfe4ce8b4 100644
--- a/sources/scala/tools/nsc/ast/Trees.scala
+++ b/sources/scala/tools/nsc/ast/Trees.scala
@@ -376,10 +376,8 @@ abstract class Trees: Global {
override def isType = selector.isTypeName;
}
- def Select(qualifier: Tree, sym: Symbol): Select = {
- sym.setFlag(ACCESSED);
- Select(qualifier, sym.name) setSymbol sym
- }
+ def Select(qualifier: Tree, sym: Symbol): Select =
+ Select(qualifier, sym.name) setSymbol sym;
/** Identifier */
case class Ident(name: Name)
@@ -388,10 +386,8 @@ abstract class Trees: Global {
override def isType = name.isTypeName;
}
- def Ident(sym: Symbol): Ident = {
- sym.setFlag(ACCESSED);
- Ident(sym.name) setSymbol sym
- }
+ def Ident(sym: Symbol): Ident =
+ Ident(sym.name) setSymbol sym;
/** Literal */
case class Literal(value: Constant)
@@ -921,7 +917,8 @@ abstract class Trees: Global {
def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
List.mapConserve(stats)(stat =>
if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat))
- else transform(stat));
+ else transform(stat)) filter (EmptyTree !=);
+ def transformUnit(unit: CompilationUnit): unit = { unit.body = transform(unit.body) }
def atOwner[A](owner: Symbol)(trans: => A): A = {
val prevOwner = currentOwner;
@@ -938,11 +935,11 @@ abstract class Trees: Global {
case EmptyTree =>
;
case PackageDef(name, stats) =>
- atOwner(tree.symbol) {
+ atOwner(tree.symbol.moduleClass) {
traverseTrees(stats)
}
case ClassDef(mods, name, tparams, tpt, impl) =>
- atOwner(tree.symbol.moduleClass) {
+ atOwner(tree.symbol) {
traverseTrees(tparams); traverse(tpt); traverse(impl)
}
case ModuleDef(mods, name, impl) =>
@@ -1074,6 +1071,14 @@ abstract class Trees: Global {
def apply(tree: Tree): Tree = { val tree1 = tree.duplicate; traverse(tree1); tree1 }
}
+ class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser {
+ override def traverse(tree: Tree): unit = {
+ if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.owner == oldowner)
+ tree.symbol.owner = newowner;
+ super.traverse(tree)
+ }
+ }
+
final class TreeList {
private var trees = List[Tree]();
def append(t: Tree): TreeList = { trees = t :: trees; this }
diff --git a/sources/scala/tools/nsc/ast/parser/Parsers.scala b/sources/scala/tools/nsc/ast/parser/Parsers.scala
index 79bc2b024c..b002dfd967 100755
--- a/sources/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/sources/scala/tools/nsc/ast/parser/Parsers.scala
@@ -753,7 +753,7 @@ abstract class Parsers: SyntaxAnalyzer {
* | SimpleExpr1 ArgumentExprs
*/
def simpleExpr(): Tree = {
- var t: Tree = _;
+ var t: Tree = null;
var isNew = false;
in.token match {
case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT |
@@ -1111,6 +1111,7 @@ abstract class Parsers: SyntaxAnalyzer {
*/
def paramClauses(owner: Name, implicitViews: List[Tree], ofCaseClass: boolean): List[List[ValDef]] = {
var implicitmod = 0;
+ var caseParam = ofCaseClass;
def param(): ValDef = {
atPos(in.pos) {
var mods = Flags.PARAM;
@@ -1119,8 +1120,9 @@ abstract class Parsers: SyntaxAnalyzer {
if (in.token == VAL) in.nextToken()
else {
if (mods != Flags.PARAMACCESSOR) accept(VAL);
- if (!ofCaseClass) mods = mods | Flags.PRIVATE | Flags.LOCAL;
+ if (!(caseParam)) mods = mods | Flags.PRIVATE | Flags.LOCAL;
}
+ if (caseParam) mods = mods | Flags.CASEACCESSOR;
}
val name = ident();
accept(COLON);
@@ -1149,13 +1151,14 @@ abstract class Parsers: SyntaxAnalyzer {
in.nextToken();
vds += paramClause();
accept(RPAREN);
+ caseParam = false
}
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)
+ addImplicitViews(owner, result, implicitViews)
}
/** ParamType ::= Type | `=>' Type | Type `*'
diff --git a/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala b/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 47648f339c..9ceb0dedff 100644
--- a/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -94,7 +94,7 @@ abstract class TreeBuilder {
if (parents.tail.isEmpty && stats.isEmpty)
New(parents.head, argss)
else {
- val x = freshName(nme.ANON_CLASS_NAME.toString()).toTypeName;
+ val x = nme.ANON_CLASS_NAME.toTypeName;
Block(
List(ClassDef(
FINAL | SYNTHETIC, x, List(), TypeTree(),
@@ -272,8 +272,9 @@ abstract class TreeBuilder {
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 | LOCAL | PRIVATE, freshName("view$"), tpt, EmptyTree);
+ def addImplicitViews(owner: Name, vparamss: List[List[ValDef]], implicitViews: List[Tree]): List[List[ValDef]] = {
+ val mods = if (owner.isTypeName) PARAMACCESSOR | LOCAL | PRIVATE else PARAM;
+ def makeViewParam(tpt: Tree) = ValDef(mods | IMPLICIT, freshName("view$"), tpt, EmptyTree);
if (implicitViews.isEmpty) vparamss
else vparamss ::: List(implicitViews map makeViewParam)
}
diff --git a/sources/scala/tools/nsc/backend/icode/GenICode.scala b/sources/scala/tools/nsc/backend/icode/GenICode.scala
index 727202ca72..e730351784 100644
--- a/sources/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/sources/scala/tools/nsc/backend/icode/GenICode.scala
@@ -248,7 +248,7 @@ abstract class GenICode extends SubComponent {
// normal method call
var invokeStyle =
- if (sym.isConstructor)
+ if (sym.isClassConstructor)
NewInstance;
else if (sym.isStatic)
Static(false)
diff --git a/sources/scala/tools/nsc/matching/BerrySethis.scala b/sources/scala/tools/nsc/matching/BerrySethis.scala
index 4e774ad94e..85638903b0 100644
--- a/sources/scala/tools/nsc/matching/BerrySethis.scala
+++ b/sources/scala/tools/nsc/matching/BerrySethis.scala
@@ -453,7 +453,7 @@ class BerrySethi {
def makeTransition(srcI:Integer, destI:Integer, label: Label): Unit = {
var src = srcI.intValue() ;
var dest = destI.intValue() ;
- var arrows: Vector = _; //, revArrows;
+ var arrows: Vector = null; //, revArrows;
//Label revLabel = new Pair( srcI, label );
label match {
case DefaultLabel() =>
@@ -660,8 +660,8 @@ class BindingBerrySethi extends BerrySethi {
override def makeTransition(srcI: Integer, destI: Integer, label: Label): Unit = {
val src = srcI.intValue() ;
val dest = destI.intValue() ;
- var arrows: Vector = _;
- var revArrows: Vector = _;
+ var arrows: Vector = null;
+ var revArrows: Vector = null;
val revLabel = new LPair(srcI, label);
label match {
case DefaultLabel() =>
diff --git a/sources/scala/tools/nsc/matching/DetWordAutoms.scala b/sources/scala/tools/nsc/matching/DetWordAutoms.scala
index 553b5b1e13..59bca48cb6 100644
--- a/sources/scala/tools/nsc/matching/DetWordAutoms.scala
+++ b/sources/scala/tools/nsc/matching/DetWordAutoms.scala
@@ -175,10 +175,10 @@ class DetWordAutom {
def determinize( nfa: NondetWordAutom ): Unit = {
//Console.println("DetWordAutom:determinize");
//System.out.println("nfa:");nfa.print();
- var states:TreeSet = _; // temp: Set[Set[Integer]]
- var deftrans:HashMap = _; // Set[Integer] -> Int
+ var states:TreeSet = null; // temp: Set[Set[Integer]]
+ var deftrans:HashMap = null; // Set[Integer] -> Int
- var trans: HashMap = _; // always points to a mapping ( Label -> Q )
+ var trans: HashMap = null; // always points to a mapping ( Label -> Q )
var ix = 0; // state index
this._labels = nfa.labels;
@@ -300,7 +300,7 @@ class DetWordAutom {
val state_x = indexMap.get( state ).asInstanceOf[Integer];
val defTarget = deftrans.get( state ).asInstanceOf[TreeSet];
- var defTarget_x: Integer = _;
+ var defTarget_x: Integer = null;
if( null != defTarget) {
defTarget_x = indexMap.get( defTarget ).asInstanceOf[Integer];
////System.out.println("deftarget" + defTarget);
@@ -316,7 +316,7 @@ class DetWordAutom {
while(labs.hasNext()) {
val label = labs.next();
val target = trans.get( label ).asInstanceOf[TreeSet];
- var target_x: Integer = _;
+ var target_x: Integer = null;
if( null != target ) {
// //System.out.println("target :"+target);
target_x = indexMap.get( target ).asInstanceOf[Integer];
@@ -375,7 +375,7 @@ class DetWordAutom {
* null if no such transition exists.
*/
def delta(i: Int, label: Label): Integer = {
- var target:Integer =_;
+ var target:Integer = null;
label match {
case DefaultLabel() =>
if (! hasDefault(i))
@@ -860,7 +860,7 @@ class DetWordAutom {
* gets flattened.
*/
def printBefore(states: TreeSet, deftrans: HashMap): Unit = {
- var trans: HashMap = _;
+ var trans: HashMap = null;
Console.println(states);
val it = states.iterator();
while (it.hasNext()) {
diff --git a/sources/scala/tools/nsc/matching/LeftTracers.scala b/sources/scala/tools/nsc/matching/LeftTracers.scala
index fe38779951..4ab525f70f 100644
--- a/sources/scala/tools/nsc/matching/LeftTracers.scala
+++ b/sources/scala/tools/nsc/matching/LeftTracers.scala
@@ -132,12 +132,12 @@ abstract class LeftTracerInScala extends Autom2Scala {
*/
def code_state(i: Int, elseBody: Tree): Tree = {
- var runFinished: Tree = _; // holds result of the run
+ var runFinished: Tree = null; // holds result of the run
var finalSwRes: Int = 0;
runFinished = run_finished(i);
- var stateBody: Tree = _ ; // action(delta) for one particular label/test
+ var stateBody: Tree = null ; // action(delta) for one particular label/test
// default action (fail if there is none)
diff --git a/sources/scala/tools/nsc/matching/PatternMatchers.scala b/sources/scala/tools/nsc/matching/PatternMatchers.scala
index c3ae5d9c4a..a87ef728f2 100644
--- a/sources/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/sources/scala/tools/nsc/matching/PatternMatchers.scala
@@ -386,8 +386,9 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt
// Console.println("newHeader :: casted="+casted);
// Console.println("newHeader :: casted.tpe="+casted.tpe);
//Console.println("newHeader :: ");
- val ts = casted.tpe.symbol.asInstanceOf[ClassSymbol]
- .caseFieldAccessors(index);
+ val caseAccs = casted.tpe.symbol.caseFieldAccessors;
+ if (caseAccs.length <= index) System.out.println("selecting " + index + " in case fields of " + casted.tpe.symbol + "=" + casted.tpe.symbol.caseFieldAccessors);//debug
+ val ts = caseAccs(index);
//Console.println("newHeader :: ts="+ts);
//val accType = casted.tpe.memberType(ts); // old scalac
//val accTree = global.typer.typed(Select(ident, ts)); // !
diff --git a/sources/scala/tools/nsc/matching/PatternNodes.scala b/sources/scala/tools/nsc/matching/PatternNodes.scala
index f16178dbab..382760eb38 100644
--- a/sources/scala/tools/nsc/matching/PatternNodes.scala
+++ b/sources/scala/tools/nsc/matching/PatternNodes.scala
@@ -35,7 +35,7 @@ trait PatternNodes: TransMatcher {
}
def dup(): PatternNode = {
- var res: PatternNode = _;
+ var res: PatternNode = null;
this match {
case h:Header =>
res = new Header(h.selector, h.next);
diff --git a/sources/scala/tools/nsc/matching/RightTracers.scala b/sources/scala/tools/nsc/matching/RightTracers.scala
index 8dc3d638a9..a916d07929 100644
--- a/sources/scala/tools/nsc/matching/RightTracers.scala
+++ b/sources/scala/tools/nsc/matching/RightTracers.scala
@@ -71,7 +71,7 @@ abstract class RightTracerInScala extends Autom2Scala {
case Star(t) =>
traverse(t);
case Bind(name, subtree) =>
- var sym: Symbol = _;
+ var sym: Symbol = null;
if( isVariableName( name )
&& isVariableSymbol( {sym = tree.symbol; tree.symbol} ))
handleVariableSymbol( sym );
@@ -136,7 +136,7 @@ abstract class RightTracerInScala extends Autom2Scala {
val helpVar = owner.newVariable( pos,
fresh.newName( realVar.name
.toString()+"RTIS" ));
- var rhs: Tree = _;
+ var rhs: Tree = null;
//System.out.println("RTiS making helpvar : "+realVar+" -> "+helpVar);
diff --git a/sources/scala/tools/nsc/matching/TransMatcher.scala b/sources/scala/tools/nsc/matching/TransMatcher.scala
index c35d3a0baa..5d7bb9de86 100644
--- a/sources/scala/tools/nsc/matching/TransMatcher.scala
+++ b/sources/scala/tools/nsc/matching/TransMatcher.scala
@@ -25,6 +25,7 @@ with RightTracers {
import global._;
import definitions._;
import posAssigner.atPos;
+ import typer.typed;
val phaseName = "transmatcher";
@@ -98,7 +99,7 @@ with RightTracers {
error("shouldn't happen?!");
case Bind(name, subtree) =>
- var sym: Symbol = _;
+ var sym: Symbol = null;
if (isVariableName(name)
&& isVariableSymbol( {sym = tree.symbol; tree.symbol} ))
@@ -139,7 +140,7 @@ with RightTracers {
def isRegular(pats:List[CaseDef]): Pair[List[CaseDef],Boolean] = {
var existsReg = false;
var isReg = false;
- var nilVars:List[Symbol] = _;
+ var nilVars:List[Symbol] = null;
def isRegular1(pat: Tree): Tree = pat match {
case Alternative(trees) =>
@@ -247,7 +248,7 @@ with RightTracers {
// global.log("internal pattern matching structure");
// pm.print();
//}
- pm.toTree();
+ pm.toTree()
}
}
override def transform(tree: Tree): Tree = tree match {
@@ -261,14 +262,19 @@ with RightTracers {
Console.println("BODY "+t.body.toString());
}
*/
- // @todo: remove from partial matcher
+ // @todo: remove from partial matcher
TransMatcher.this.currentOwner = currentOwner;
TransMatcher.this.resultType = tree.tpe;
- //Console.println("TransMatcher selector.tpe ="+selector.tpe+")");
- //Console.println("TransMatcher resultType ="+resultType+")");
- val t = handle(nselector, ncases.asInstanceOf[List[CaseDef]]);
- //Console.println(t.toString());
- t
+ //Console.println("TransMatcher selector.tpe ="+selector.tpe+")");
+ //Console.println("TransMatcher resultType ="+resultType+")");
+ val t =
+ typed {
+ atPos(tree.pos) {
+ handle(nselector, ncases.asInstanceOf[List[CaseDef]])
+ }
+ }
+ //Console.println(t.toString());
+ t
case _ =>
super.transform(tree);
}
diff --git a/sources/scala/tools/nsc/matching/WordAutoms.scala b/sources/scala/tools/nsc/matching/WordAutoms.scala
index 5912ad3900..1d02f0126e 100644
--- a/sources/scala/tools/nsc/matching/WordAutoms.scala
+++ b/sources/scala/tools/nsc/matching/WordAutoms.scala
@@ -34,7 +34,7 @@ abstract class WordAutomInScala extends Autom2Scala {
def getMatcherSwitch(selector: Tree, failTree: Tree, body: scala.List[Tree] /*, resultType: Type*/ ): Tree = {
- var result: Tree = _;
+ var result: Tree = null;
var ncases: scala.List[CaseDef] = Nil;
val it = body.reverse.elements;
//val tags = new Array[int](body.length);
diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala
index a620ec8190..275948bdc0 100755
--- a/sources/scala/tools/nsc/symtab/Definitions.scala
+++ b/sources/scala/tools/nsc/symtab/Definitions.scala
@@ -158,6 +158,7 @@ abstract class Definitions: SymbolTable {
var BoxedUnitClass: Symbol = _;
var BoxedUnitModule: Symbol = _;
def BoxedUnit_UNIT = getMember(BoxedUnitModule, "UNIT");
+ var ObjectRefClass: Symbol = _;
def getModule(fullname: Name): Symbol =
getModuleOrClass(fullname, true);
@@ -231,20 +232,24 @@ abstract class Definitions: SymbolTable {
owner.newTypeParameter(Position.NOPOS, "T" + index)
.setInfo(TypeBounds(AllClass.typeConstructor, AnyClass.typeConstructor));
- val boxedSym = new HashMap[Symbol, Symbol];
- val boxedArraySym = new HashMap[Symbol, Symbol];
+ val boxedClass = new HashMap[Symbol, Symbol];
+ val boxedArrayClass = new HashMap[Symbol, Symbol];
+ val refClass = new HashMap[Symbol, Symbol];
private val abbrvTag = new HashMap[Symbol, char];
private def getValueClass(name: String, tag: char): Symbol = {
val result = getClass("scala." + name);
- boxedSym(result) = getClass("scala.runtime.Boxed" + name);
- if (name != "Unit") boxedArraySym(result) = getClass("scala.runtime.Boxed" + name + "Array");
+ boxedClass(result) = getClass("scala.runtime.Boxed" + name);
+ if (name != "Unit") {
+ boxedArrayClass(result) = getClass("scala.runtime.Boxed" + name + "Array");
+ refClass(result) = getClass("scala.runtime." + name + "Ref");
+ }
abbrvTag(result) = tag;
result
}
/** Is symbol a value class? */
- def isValueClass(sym: Symbol): boolean = boxedSym contains sym;
+ def isValueClass(sym: Symbol): boolean = boxedClass contains sym;
/** Is symbol a value or array class? */
def isUnboxedClass(sym: Symbol): boolean = isValueClass(sym) || sym == ArrayClass;
@@ -368,6 +373,7 @@ abstract class Definitions: SymbolTable {
BoxedNumberClass = getClass("scala.runtime.BoxedNumber");
BoxedUnitClass = getClass("scala.runtime.BoxedUnit");
BoxedUnitModule = getModule("scala.runtime.BoxedUnit");
+ ObjectRefClass = getClass("scala.runtime.ObjectRef");
}
}
}
diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala
index a7a4d0bf1e..c7d187af97 100644
--- a/sources/scala/tools/nsc/symtab/Flags.scala
+++ b/sources/scala/tools/nsc/symtab/Flags.scala
@@ -42,7 +42,7 @@ object Flags {
// (typically, access methods for valdefs)
final val STATIC = 0x00800000; // static field, method or class
- final val ACCESSED = 0x01000000; // symbol was accessed at least once
+ final val CASEACCESSOR = 0x01000000; // symbol is a case parameter (or its accessor)
final val MODULE = 0x02000000; // symbol is module or class implementing a module
final val BRIDGE = 0x04000000; // function is a bridge method. Set by Erasure
final val ACCESSOR = 0x08000000; // a value or variable accessor
@@ -50,7 +50,7 @@ object Flags {
final val ACCESS_METHOD = 0x10000000; // function is an access function for a method in some
// outer class; set by ExplicitOuter
final val PARAMACCESSOR = 0x20000000; // for value definitions: is an access method for a final val parameter
- // for parameters: is a val parameter
+ // for parameters: is a val parameter
final val LABEL = 0x40000000; // symbol is a label. Set by TailCall
final val CAPTURED = 0x80000000l; // variable is accessed from nested function. Set by LambdaLift
@@ -59,8 +59,8 @@ object Flags {
final val OVERLOADED = 0x200000000l; // symbol is overloaded
final val TRANS_FLAG = 0x400000000l; // transient flag guaranteed to be reset after each phase.
- final val LIFTED = TRANS_FLAG; // transient flag for lambdalift
final val INCONSTRUCTOR = TRANS_FLAG; // transient flag for analyzer
+ final val FLATTENED = 0x800000000l; // class has been lifted out to package level
final val INITIALIZED = 0x1000000000l; // symbol's definition is complete
final val LOCKED = 0x2000000000l; // temporary flag to catch cyclic dependencies
@@ -82,16 +82,16 @@ object Flags {
final val ExplicitFlags = // these modifiers can be set explicitly in source programs.
PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED | OVERRIDE | CASE | IMPLICIT | ABSOVERRIDE;
final val PrintableFlags = // these modifiers appear in TreePrinter output.
- ExplicitFlags | LOCAL | SYNTHETIC | STABLE | ACCESSOR |
+ ExplicitFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | ACCESSOR |
ACCESS_METHOD | PARAMACCESSOR | LABEL | BRIDGE | STATIC;
final val GenFlags = // these modifiers can be in generated trees
SourceFlags | PrintableFlags;
- final val FieldFlags = MUTABLE | ACCESSED | PARAMACCESSOR | STATIC | FINAL;
+ final val FieldFlags = MUTABLE | CASEACCESSOR | PARAMACCESSOR | STATIC | FINAL;
final val AccessFlags = PRIVATE | PROTECTED;
final val VARIANCES = COVARIANT | CONTRAVARIANT;
final val ConstrFlags = JAVA;
- final val PickledFlags = 0xFFFFFFFF & ~LOCKED & ~INITIALIZED;
+ final val PickledFlags = 0xFFFFFFFF;
/** Module flags inherited by their module-class */
final val ModuleToClassFlags = AccessFlags | PACKAGE;
@@ -142,7 +142,7 @@ object Flags {
case STABLE => "<stable>"
case STATIC => "<static>"
- case ACCESSED => "<accessed>"
+ case CASEACCESSOR => "<caseaccessor>"
case ACCESSOR => "<accessor>"
case ACCESS_METHOD => "<access>"
diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala
index 0cdc909380..681efa46c3 100755
--- a/sources/scala/tools/nsc/symtab/StdNames.scala
+++ b/sources/scala/tools/nsc/symtab/StdNames.scala
@@ -31,7 +31,7 @@ abstract class StdNames: SymbolTable {
val NEWkw = newTermName("new");
val NULLkw = newTermName("null");
val OBJECTkw = newTermName("object");
- val OUTER = "$outer";
+ val OUTER = newTermName("$outer");
val OVERRIDEkw = newTermName("override");
val PACKAGEkw = newTermName("package");
val PRIVATEkw = newTermName("private");
@@ -76,8 +76,10 @@ abstract class StdNames: SymbolTable {
def TUPLE_FIELD(index: int) = newTermName(TUPLE_FIELD_PREFIX_STRING + index);
+ def LOCAL_NAME(name: Name) = newTermName(name.toString() + " ");
+ def isLocalName(name: Name) = name(name.length - 1) == ' ';
+ def GETTER_NAME(name: Name) = newTermName(name.toString().substring(0, name.length - 1));
def SETTER_NAME(name: Name) = encode(name.toString() + "_=");
- def LOCAL_NAME(name: Name) = encode(name.toString() + " ");
val ERROR = newTermName("<error>");
val ERRORtype = newTypeName("<error>");
diff --git a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
index 46e9ff6b42..1900dd82c8 100755
--- a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -80,7 +80,7 @@ abstract class SymbolLoaders {
/** Is the given name a valid input file base name? */
def isValid(name: String): boolean =
- name.length() > 0 && !name.endsWith("$class") && name.indexOf("$$anon") == -1;
+ name.length() > 0 && !name.endsWith("$class") && name.indexOf("$anon") == -1;
def enterPackage(str: String, completer: SymbolLoader): unit = {
val pkg = root.newPackage(Position.NOPOS, newTermName(str));
diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala
index 44340e8b1b..ea62d09721 100755
--- a/sources/scala/tools/nsc/symtab/Symbols.scala
+++ b/sources/scala/tools/nsc/symtab/Symbols.scala
@@ -18,11 +18,11 @@ abstract class Symbols: SymbolTable {
/** The class for all symbols */
abstract class Symbol(initOwner: Symbol, initPos: int, initName: Name) {
- var owner = initOwner;
- var name = initName;
+ var rawowner = initOwner;
+ var rawname = initName;
+ private var rawflags: long = 0;
var pos = initPos;
val id = { ids = ids + 1; ids }
- private var rawflags: long = 0;
def setPos(pos: int): this.type = { this.pos = pos; this }
@@ -35,7 +35,7 @@ abstract class Symbols: SymbolTable {
final def newValueParameter(pos: int, name: Name) =
newValue(pos, name).setFlag(PARAM);
final def newLocalDummy(pos: int) =
- newValue(pos, nme.LOCAL(owner)).setInfo(NoType);
+ newValue(pos, nme.LOCAL(this)).setInfo(NoType);
final def newMethod(pos: int, name: Name) =
newValue(pos, name).setFlag(METHOD);
final def newLabel(pos: int, name: Name) =
@@ -102,8 +102,9 @@ abstract class Symbols: SymbolTable {
final def isMethod = isTerm && hasFlag(METHOD);
final def isSourceMethod = isTerm && (flags & (METHOD | STABLE)) == METHOD;
final def isLabel = isTerm && hasFlag(LABEL);
- final def isConstructor = isTerm && (name == nme.CONSTRUCTOR);
+ final def isClassConstructor = isTerm && (name == nme.CONSTRUCTOR);
final def isMixinConstructor = isTerm && (name == nme.MIXIN_CONSTRUCTOR);
+ final def isConstructor = isTerm && (name == nme.CONSTRUCTOR) || (name == nme.MIXIN_CONSTRUCTOR);
final def isModule = isTerm && hasFlag(MODULE);
final def isPackage = isModule && hasFlag(PACKAGE);
final def isThisSym = isTerm && name == nme.this_;
@@ -125,10 +126,14 @@ abstract class Symbols: SymbolTable {
isTerm && !hasFlag(MUTABLE) && (!hasFlag(METHOD) || hasFlag(STABLE));
/** Does this symbol denote the primary constructor
- * of its enclosing class? */
+ * of its enclosing class or trait? */
final def isPrimaryConstructor =
isConstructor && owner.primaryConstructor == this;
+ /** Is this symbol an implementation class for a trait ? */
+ final def isImplClass: boolean =
+ name.endsWith(nme.IMPL_CLASS_SUFFIX);
+
/** Is this symbol static (i.e. with no outer instance)? */
final def isStatic: boolean = hasFlag(STATIC) || isRoot || owner.isStaticOwner;
@@ -157,6 +162,10 @@ abstract class Symbols: SymbolTable {
case _ => false
});
+ /** Is this class nested in another class or module (not a package)? */
+ final def isNestedClass: boolean =
+ isClass && !isRoot && !owner.isPackageClass;
+
/** Is this class locally defined?
* A class is local, if
* - it is anonymous, or
@@ -184,7 +193,13 @@ abstract class Symbols: SymbolTable {
else if (hasFlag(CONTRAVARIANT)) -1
else 0;
-// Flags ----------------------------------------------------------------------------
+// Flags, owner, and name attributes --------------------------------------------------------------
+
+ def owner: Symbol = rawowner;
+ final def owner_=(owner: Symbol): unit = { rawowner = owner }
+
+ def name: Name = rawname;
+ final def name_=(name: Name): unit = { rawname = name }
final def flags = {
val fs = rawflags & phase.flagMask;
@@ -254,14 +269,11 @@ abstract class Symbols: SymbolTable {
this
}
- /** Set new info valid from start of next phase. */
+ /** Set new info valid from start of this phase. */
final def updateInfo(info: Type): Symbol = {
- val current = phase;
- phase = phase.next;
assert(infos.start.id <= phase.id);
if (infos.start == phase) infos = infos.prev;
infos = new TypeHistory(phase, info, infos);
- phase = current;
this
}
@@ -409,10 +421,10 @@ abstract class Symbols: SymbolTable {
def enclMethod: Symbol = if (isSourceMethod) this else owner.enclMethod;
/** The primary constructor of a class */
- def primaryConstructor: Symbol = info.decl(nme.CONSTRUCTOR).alternatives.head;
-
- /** The (primary) trait constructor of (the implementation class of) a mixin */
- def mixinConstructor: Symbol = info.decl(nme.MIXIN_CONSTRUCTOR);
+ def primaryConstructor: Symbol = {
+ val c = info.decl(if (isTrait || isImplClass) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR);
+ if (c hasFlag OVERLOADED) c.alternatives.head else c
+ }
/** The self symbol of a class with explicit self type, or else the symbol itself.
*/
@@ -427,11 +439,14 @@ abstract class Symbols: SymbolTable {
/** If symbol is a class, the type this.type in this class, otherwise NoPrefix */
def thisType: Type = NoPrefix;
- /** Return every accessor of a primary constructor parameter in this case class */
- final def caseFieldAccessors: List[Symbol] = {
- assert(isClass && hasFlag(CASE));
- info.decls.toList filter (sym => !(sym hasFlag PRIVATE) && sym.hasFlag(PARAMACCESSOR))
- }
+ /** Return every accessor of a primary constructor parameter in this case class
+ * todo: limit to accessors for first constructor parameter section.
+ */
+ final def caseFieldAccessors: List[Symbol] =
+ info.decls.toList filter (sym => !(sym hasFlag PRIVATE) && sym.hasFlag(CASEACCESSOR));
+
+ final def constrParamAccessors: List[Symbol] =
+ info.decls.toList filter (sym => !sym.isMethod && sym.hasFlag(PARAMACCESSOR));
/** The symbol accessed by this accessor function.
*/
@@ -439,9 +454,13 @@ abstract class Symbols: SymbolTable {
assert(hasFlag(ACCESSOR));
val name1 = if (name.endsWith(nme._EQ)) name.subName(0, name.length - nme._EQ.length)
else name;
- owner.info.decl(name1.toString() + "$")
+ owner.info.decl(nme.LOCAL_NAME(name1))
}
+ /** The getter for this symbol */
+ final def getter: Symbol =
+ if (nme.isLocalName(name)) owner.info.decl(nme.GETTER_NAME(name)) else NoSymbol;
+
/** The class with the same name in the same package as this module or
* case class factory
*/
@@ -511,10 +530,7 @@ abstract class Symbols: SymbolTable {
/** The simple name of this Symbol (this is always a term name) */
final def simpleName: Name = name;
-/*
- if (isConstructor && !settings.debug.value)
- newTermName("<init owner.name.toTermName else name;
-*/
+
/** String representation of symbol's definition key word */
final def keyString: String =
if (isTrait)
@@ -541,7 +557,7 @@ abstract class Symbols: SymbolTable {
else if (isVariable) "variable"
else if (isPackage) "package"
else if (isModule) "object"
- else if (isConstructor) "constructor"
+ else if (isClassConstructor) "constructor"
else if (isSourceMethod) "method"
else if (isTerm) "value"
else "";
@@ -704,6 +720,21 @@ abstract class Symbols: SymbolTable {
thissym = this;
}
+ override def owner: Symbol =
+ if (phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass) rawowner.owner
+ else rawowner;
+
+ private var flatname = nme.EMPTY;
+
+ override def name: Name =
+ if (phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass) {
+ if (flatname == nme.EMPTY) {
+ assert(rawowner.isClass);
+ flatname = newTypeName(rawowner.name.toString() + "$" + rawname);
+ }
+ flatname
+ } else rawname;
+
private var thisTypeCache: Type = _;
private var thisTypePhase: Phase = null;
@@ -714,10 +745,9 @@ abstract class Symbols: SymbolTable {
thisTypePhase = phase;
if (!isValid(p)) {
thisTypeCache =
- if (isModuleClass && !isRoot && !phase.erasedTypes) {
- assert(sourceModule != NoSymbol, "" + this + " " + phase);
- singleType(owner.thisType, sourceModule);
- } else ThisType(this);
+ if (isModuleClass && !isRoot && !phase.erasedTypes)
+ singleType(owner.thisType, sourceModule);
+ else ThisType(this);
}
}
thisTypeCache
diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala
index b488685727..0c66540d66 100755
--- a/sources/scala/tools/nsc/symtab/Types.scala
+++ b/sources/scala/tools/nsc/symtab/Types.scala
@@ -800,7 +800,7 @@ abstract class Types: SymbolTable {
/** The canonical creator for this-types */
def ThisType(sym: Symbol): Type =
- if (phase.erasedTypes) sym.tpe else unique(new ThisType(sym) with UniqueType {});
+ if (phase.erasedTypes) sym.tpe else unique(new ThisType(sym) with UniqueType);
/** The canonical creator for single-types */
def singleType(pre: Type, sym: Symbol): Type = {
@@ -809,7 +809,7 @@ abstract class Types: SymbolTable {
else if (checkMalformedSwitch && !pre.isStable && !pre.isError)
throw new MalformedType(pre, sym.name.toString())
else
- unique(new SingleType(pre, rebind(pre, sym)) with UniqueType {})
+ unique(new SingleType(pre, rebind(pre, sym)) with UniqueType)
}
/** The canonical creator for super-types */
@@ -1050,11 +1050,13 @@ abstract class Types: SymbolTable {
val decls1 = mapOver(decls);
if ((parents1 eq parents) && (decls1 eq decls)) tp
else cloneDecls(refinedType(parents1, tp.symbol.owner), tp, decls1)
+/*
case ClassInfoType(parents, decls, clazz) =>
val parents1 = List.mapConserve(parents)(this);
val decls1 = mapOver(decls);
if ((parents1 eq parents) && (decls1 eq decls)) tp
else cloneDecls(ClassInfoType(parents1, new Scope(), clazz), tp, decls1)
+*/
case MethodType(paramtypes, result) =>
val paramtypes1 = List.mapConserve(paramtypes)(this);
val result1 = this(result);
@@ -1253,7 +1255,10 @@ abstract class Types: SymbolTable {
// Helper Methods -------------------------------------------------------------
final def isValid(p: Phase): boolean =
- p != null && infoTransformers.nextFrom(p).phase.id >= phase.id;
+ p != null &&
+ (if (phase.id > p.id) infoTransformers.nextFrom(p).phase.id >= phase.id
+ else infoTransformers.nextFrom(phase).phase.id >= p.id);
+
/** Do tp1 and tp2 denote equivalent types? */
def isSameType(tp1: Type, tp2: Type): boolean = (tp1 eq tp2) || {
diff --git a/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala b/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala
index 9aec7dc802..42aa2e933c 100755
--- a/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala
@@ -17,7 +17,7 @@ object PickleFormat {
* | 5 ALIASsym len_Nat SymbolInfo
* | 6 CLASSsym len_Nat SymbolInfo [thistype_Ref]
* | 7 MODULEsym len_Nat SymbolInfo
- * | 8 VALsym len_Nat SymbolInfo
+ * | 8 VALsym len_Nat SymbolInfo [alias_Ref]
* | 9 EXTref len_Nat name_Ref [owner_Ref]
* | 10 EXTMODCLASSref len_Nat name_Ref [owner_Ref]
* | 11 NOtpe len_Nat
diff --git a/sources/scala/tools/nsc/symtab/classfile/Pickler.scala b/sources/scala/tools/nsc/symtab/classfile/Pickler.scala
index 8123fe6973..1c221462c2 100755
--- a/sources/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -83,7 +83,12 @@ abstract class Pickler extends SubComponent {
putEntry(sym.name);
putSymbol(sym.owner);
putType(sym.info);
- if (sym.thisSym != sym) putType(sym.typeOfThis)
+ if (sym.thisSym != sym)
+ putType(sym.typeOfThis);
+ aliases.get(sym) match {
+ case Some(alias) => putSymbol(alias);
+ case None =>
+ }
} else if (sym != NoSymbol) {
putEntry(if (sym.isModuleClass) sym.name.toTermName else sym.name);
if (!sym.owner.isRoot) putSymbol(sym.owner);
@@ -170,7 +175,15 @@ abstract class Pickler extends SubComponent {
writeSymInfo(sym);
if (sym.isAbstractType) TYPEsym else ALIASsym
case sym: TermSymbol =>
- writeSymInfo(sym); if (sym.isModule) MODULEsym else VALsym
+ writeSymInfo(sym);
+ if (sym.isModule) MODULEsym
+ else {
+ aliases.get(sym) match {
+ case Some(alias) => writeRef(alias);
+ case None =>
+ }
+ VALsym
+ }
case NoType =>
NOtpe
case NoPrefix =>
diff --git a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala
index 8fd7f63cb9..3429ba88d7 100755
--- a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -19,7 +19,8 @@ abstract class UnPickler {
new UnPickle(bytes, offset, classRoot, moduleRoot);
} catch {
case ex: Throwable =>
- if (settings.debug.value) ex.printStackTrace();
+ ex.printStackTrace();//debug
+ System.out.println("EX");//debug
throw new RuntimeException("error reading Scala signature of " + classRoot.nameString + ": " + ex.getMessage());
}
@@ -119,10 +120,11 @@ abstract class UnPickler {
errorBadSignature("bad symbol tag: " + tag);
}
sym.setFlag(flags);
- sym.setInfo(new LazyTypeRef(inforef));
+ val aliasIndex = if ((sym hasFlag PARAMACCESSOR) && readIndex != end) readNat() else 0;
+ sym.setInfo(new LazyTypeRef(inforef, aliasIndex));
if (sym.owner.isClass && sym != classRoot && sym != moduleRoot &&
- !sym.isModuleClass && !sym.isRefinementClass && !sym.hasFlag(PARAM | LOCAL))
- symScope(sym.owner) enter sym
+ !sym.isModuleClass && !sym.isRefinementClass && !sym.isTypeParameter)
+ symScope(sym.owner) enter sym;
}
sym
}
@@ -195,8 +197,12 @@ abstract class UnPickler {
private def errorBadSignature(msg: String) =
throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg);
- private class LazyTypeRef(i: int) extends LazyType {
- override def complete(sym: Symbol): unit = sym setInfo at(i, readType);
+ private class LazyTypeRef(i: int, aliasIndex: int) extends LazyType {
+ def this(i: int) = this(i, 0);
+ override def complete(sym: Symbol): unit = {
+ sym setInfo at(i, readType);
+ if (aliasIndex != 0) aliases(sym) = at(aliasIndex, readSymbol);
+ }
override def load(sym: Symbol): unit = complete(sym)
}
}
diff --git a/sources/scala/tools/nsc/transform/AddInterfaces.scala b/sources/scala/tools/nsc/transform/AddInterfaces.scala
index 8161e69782..79bdada436 100755
--- a/sources/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/sources/scala/tools/nsc/transform/AddInterfaces.scala
@@ -27,11 +27,8 @@ abstract class AddInterfaces extends InfoTransform {
private def implClassName(sym: Symbol): Name =
newTermName(sym.name.toString() + nme.IMPL_CLASS_SUFFIX);
- def isImplClass(sym: Symbol): boolean =
- sym.name.endsWith(nme.IMPL_CLASS_SUFFIX);
-
private def needsImplClass(sym: Symbol): boolean =
- sym.isTrait && (!(sym hasFlag INTERFACE) || (sym hasFlag lateINTERFACE)) && !isImplClass(sym);
+ sym.isTrait && (!(sym hasFlag INTERFACE) || (sym hasFlag lateINTERFACE)) && !sym.isImplClass;
private def needsImplMethod(sym: Symbol): boolean =
sym.isMethod && isInterfaceMember(sym) &&
@@ -39,7 +36,7 @@ abstract class AddInterfaces extends InfoTransform {
private def isInterfaceMember(sym: Symbol): boolean =
sym.isType ||
- sym.isMethod && !(sym hasFlag (PRIVATE | BRIDGE | LABEL)) && !sym.isMixinConstructor;
+ sym.isMethod && !(sym hasFlag (PRIVATE | BRIDGE | LABEL)) && !sym.isConstructor;
private def implClass(iface: Symbol): Symbol = implClassMap.get(iface) match {
case Some(c) => c
@@ -49,7 +46,8 @@ abstract class AddInterfaces extends InfoTransform {
setFlag (iface.flags & ~(INTERFACE | lateINTERFACE))
setInfo new LazyImplClassType(iface);
impl.name = implClassName(iface);
- //impl.typeOfThis = iface.tpe;
+ //includeInTypeOfThis(iface, impl);
+ //includeInTypeOfThis(impl, impl);
implClassMap(iface) = impl;
if (settings.debug.value) log("generating impl class " + impl);
impl
@@ -63,7 +61,6 @@ abstract class AddInterfaces extends InfoTransform {
for (val sym <- ifaceDecls.elements) {
if (isInterfaceMember(sym)) {
if (needsImplMethod(sym)) {
- assert(!sym.isMixinConstructor);//debug
val impl = sym.cloneSymbol(implClass).setInfo(sym.info);
if (!impl.isExternal) implMethodMap(sym) = impl;
decls enter impl;
@@ -114,7 +111,7 @@ abstract class AddInterfaces extends InfoTransform {
else {
assert(!parents.head.symbol.isTrait);
if (clazz hasFlag INTERFACE) erasedTypeRef(ObjectClass) :: parents.tail
- else if (isImplClass(clazz) || clazz == ArrayClass) parents
+ else if (clazz.isImplClass || clazz == ArrayClass) parents
else traitToImplClass(parents)
}
val decls1 = addImplClasses(
@@ -127,11 +124,16 @@ abstract class AddInterfaces extends InfoTransform {
// Tree transformation --------------------------------------------------------------
- private def changeOwner(oldowner: Symbol, newowner: Symbol) = new Traverser {
- override def traverse(tree: Tree): unit =
- if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.owner == oldowner)
- tree.symbol.owner = newowner
- else super.traverse(tree)
+ private class ChangeOwnerAndReturnTraverser(oldowner: Symbol, newowner: Symbol)
+ extends ChangeOwnerTraverser(oldowner, newowner) {
+ override def traverse(tree: Tree): unit = {
+ tree match {
+ case Return(expr) =>
+ if (tree.symbol == oldowner) tree.symbol = newowner;
+ case _ =>
+ }
+ super.traverse(tree)
+ }
}
private def ifaceMemberDef(tree: Tree): Tree =
@@ -146,7 +148,7 @@ abstract class AddInterfaces extends InfoTransform {
implMethodMap.get(ifaceMethod) match {
case Some(implMethod) =>
tree.symbol = implMethod;
- changeOwner(ifaceMethod, implMethod).traverse(tree);
+ new ChangeOwnerAndReturnTraverser(ifaceMethod, implMethod).traverse(tree);
tree
case None =>
throw new Error("implMethod missing for " + ifaceMethod + " " + ifaceMethod.isExternal)
@@ -159,9 +161,10 @@ abstract class AddInterfaces extends InfoTransform {
private def implTemplate(clazz: Symbol, templ: Template): Template = atPos(templ.pos){
val templ1 = Template(templ.parents, templ.body map implMemberDef)
+ setPos templ.pos
setSymbol clazz.newLocalDummy(templ.pos);
- changeOwner(templ.symbol.owner, clazz).traverse(templ1);
- changeOwner(templ.symbol, templ1.symbol).traverse(templ1);
+ new ChangeOwnerTraverser(templ.symbol.owner, clazz).traverse(templ1);
+ new ChangeOwnerTraverser(templ.symbol, templ1.symbol).traverse(templ1);
templ1
}
@@ -182,7 +185,8 @@ abstract class AddInterfaces extends InfoTransform {
protected val traitTransformer = new Transformer {
override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
- super.transformStats(stats ::: implClassDefs(stats), exprOwner) filter (EmptyTree !=);
+ super.transformStats(stats, exprOwner) :::
+ super.transformStats(implClassDefs(stats), exprOwner);
override def transform(tree: Tree): Tree = {
val tree1 = tree match {
case ClassDef(mods, name, tparams, tpt, impl) =>
@@ -192,9 +196,16 @@ abstract class AddInterfaces extends InfoTransform {
}
else tree
case Template(parents, body) =>
- copy.Template(tree, tree.symbol.owner.info.parents map TypeTree, body)
+ val parents1 = tree.symbol.owner.info.parents map (t => TypeTree(t) setPos tree.pos);
+ copy.Template(tree, parents1, body)
case This(_) =>
- if (needsImplClass(tree.symbol)) This(implClass(tree.symbol)) else tree
+ if (needsImplClass(tree.symbol)) {
+ val impl = implClass(tree.symbol);
+ var owner = currentOwner;
+ while (owner != tree.symbol && owner != impl) owner = owner.owner;
+ if (owner == impl) This(impl) setPos tree.pos
+ else tree
+ } else tree
case Super(qual, mix) =>
val mix1 =
if (mix == nme.EMPTY.toTypeName) mix
@@ -206,7 +217,7 @@ abstract class AddInterfaces extends InfoTransform {
if (needsImplClass(ps.head.symbol)) implClass(ps.head.symbol).name
else mix
}
- if (needsImplClass(tree.symbol)) Super(implClass(tree.symbol), mix1)
+ if (needsImplClass(tree.symbol)) Super(implClass(tree.symbol), mix1) setPos tree.pos
else copy.Super(tree, qual, mix1)
case _ =>
tree
diff --git a/sources/scala/tools/nsc/transform/Erasure.scala b/sources/scala/tools/nsc/transform/Erasure.scala
index d9462c2118..ee8f6359bb 100755
--- a/sources/scala/tools/nsc/transform/Erasure.scala
+++ b/sources/scala/tools/nsc/transform/Erasure.scala
@@ -106,7 +106,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
else if (sym.isAbstractType)
TypeBounds(WildcardType, WildcardType)
else if (sym.isTerm && sym.owner == ArrayClass) {
- if (sym.isConstructor)
+ if (sym.isClassConstructor)
tp match {
case MethodType(formals, TypeRef(pre, sym, args)) =>
MethodType(formals map erasure, typeRef(erasure(pre), sym, args))
@@ -139,11 +139,11 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
else Block(List(tree), gen.mkRef(BoxedUnit_UNIT))
} else if (sym == ArrayClass) {
val elemClass = tree.tpe.typeArgs.head.symbol;
- val boxedClass = if (isValueClass(elemClass)) boxedArraySym(elemClass)
+ val boxedClass = if (isValueClass(elemClass)) boxedArrayClass(elemClass)
else BoxedObjectArrayClass;
Apply(Select(New(TypeTree(boxedClass.tpe)), nme.CONSTRUCTOR), List(tree))
} else {
- val boxedModule = boxedSym(tree.tpe.symbol).linkedModule;
+ val boxedModule = boxedClass(tree.tpe.symbol).linkedModule;
Apply(Select(gen.mkRef(boxedModule), nme.box), List(tree))
}
}
@@ -156,7 +156,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
if (pt.symbol == UnitClass) {
Literal(())
} else if (pt.symbol == BooleanClass) {
- val tree1 = adaptToType(tree, boxedSym(BooleanClass).tpe);
+ val tree1 = adaptToType(tree, boxedClass(BooleanClass).tpe);
Apply(Select(tree1, "booleanValue"), List())
} else if (pt.symbol == ArrayClass) {
val tree1 = adaptToType(tree, BoxedArrayClass.tpe);
@@ -179,17 +179,6 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
}
}
- /** Cast `tree' to type `pt' */
- private def cast(tree: Tree, pt: Type): Tree = {
- if (settings.debug.value) log("casting " + tree + ":" + tree.tpe + " to " + pt);
- assert(!tree.tpe.isInstanceOf[MethodType], tree);
- typed {
- atPos(tree.pos) {
- Apply(TypeApply(Select(tree, Object_asInstanceOf), List(TypeTree(pt))), List())
- }
- }
- }
-
/** Is symbol a member of unboxed arrays (which will be expanded directly later)? */
private def isUnboxedArrayMember(sym: Symbol) =
sym.name == nme.apply || sym.name == nme.length || sym.name == nme.update ||
@@ -210,13 +199,13 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
adaptToType(box(tree), pt)
else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.paramTypes.isEmpty) {
assert(tree.symbol.isStable);
- adaptToType(Apply(tree, List()) setType tree.tpe.resultType, pt)
+ adaptToType(Apply(tree, List()) setPos tree.pos setType tree.tpe.resultType, pt)
} else if (pt <:< tree.tpe)
- cast(tree, pt)
+ gen.cast(tree, pt)
else if (isUnboxedClass(pt.symbol) && !isUnboxedClass(tree.tpe.symbol))
adaptToType(unbox(tree, pt), pt)
else
- cast(tree, pt)
+ gen.cast(tree, pt)
}
// todo: remove after removing ==, != from value classes
@@ -242,52 +231,58 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
* - All forms of `x.m' where `x' is a boxed type and `m' is a member of an unboxed class
* become `x.m' where `m' is the corresponding member of the boxed class.
*/
- private def adaptMember(tree: Tree): Tree = tree match {
- case Apply(sel @ Select(qual, name), args) =>
- if (corresponds(sel.symbol, Any_==))
- Apply(Select(qual, Object_equals), args)
- else if (corresponds(sel.symbol, Any_!=))
- Apply(Select(Apply(Select(qual, Object_equals), args), Boolean_not), List())
- else qual match {
- case New(tpt) =>
- assert(tpt.isInstanceOf[TypeTree]);
- if (tpt.tpe.symbol == BoxedArrayClass) {
- assert(name == nme.CONSTRUCTOR);
- Typed(Apply(Select(New(TypeTree(BoxedAnyArrayClass.tpe)), name), args), tpt)
- } else tree
- case _ =>
- tree
- }
- case Select(qual, name) if (name != nme.CONSTRUCTOR) =>
- if (tree.symbol == Any_asInstanceOf || tree.symbol == Any_asInstanceOfErased)
- adaptMember(Select(qual, Object_asInstanceOf))
- else if (tree.symbol == Any_isInstanceOf || tree.symbol == Any_isInstanceOfErased)
- adaptMember(Select(qual, Object_isInstanceOf))
- else if (tree.symbol != NoSymbol && tree.symbol.owner == AnyClass)
- adaptMember(Select(qual, getMember(ObjectClass, name)))
- else {
- var qual1 = typedQualifier(qual);
- if ((isValueClass(qual1.tpe.symbol) && isBoxedValueMember(tree.symbol)) ||
- (qual1.tpe.symbol == ArrayClass && !isUnboxedArrayMember(tree.symbol))) {
- qual1 = box(qual1);
- } else if (!isValueClass(qual1.tpe.symbol) &&
- tree.symbol != NoSymbol && isValueClass(tree.symbol.owner)) {
- qual1 = unbox(qual1, tree.symbol.owner.tpe)
+ private def adaptMember(tree: Tree): Tree = {
+ tree match {
+ case Apply(sel @ Select(qual, name), args) =>
+ if (corresponds(sel.symbol, Any_==))
+ atPos(tree.pos) {
+ Apply(Select(qual, Object_equals), args)
+ }
+ else if (corresponds(sel.symbol, Any_!=))
+ atPos(tree.pos) {
+ Apply(Select(Apply(Select(qual, Object_equals), args), Boolean_not), List())
+ }
+ else qual match {
+ case New(tpt) =>
+ assert(tpt.isInstanceOf[TypeTree]);
+ if (tpt.tpe.symbol == BoxedArrayClass) {
+ assert(name == nme.CONSTRUCTOR);
+ atPos(tree.pos) {
+ Typed(Apply(Select(New(TypeTree(BoxedAnyArrayClass.tpe)), name), args), tpt)
+ }
+ } else tree
+ case _ =>
+ tree
+ }
+ case Select(qual, name) if (name != nme.CONSTRUCTOR) =>
+ if (tree.symbol == Any_asInstanceOf || tree.symbol == Any_asInstanceOfErased)
+ adaptMember(atPos(tree.pos)(Select(qual, Object_asInstanceOf)))
+ else if (tree.symbol == Any_isInstanceOf || tree.symbol == Any_isInstanceOfErased)
+ adaptMember(atPos(tree.pos)(Select(qual, Object_isInstanceOf)))
+ else if (tree.symbol != NoSymbol && tree.symbol.owner == AnyClass)
+ adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, name))))
+ else {
+ var qual1 = typedQualifier(qual);
+ if ((isValueClass(qual1.tpe.symbol) && isBoxedValueMember(tree.symbol)) ||
+ (qual1.tpe.symbol == ArrayClass && !isUnboxedArrayMember(tree.symbol))) {
+ qual1 = box(qual1);
+ } else if (!isValueClass(qual1.tpe.symbol) &&
+ tree.symbol != NoSymbol && isValueClass(tree.symbol.owner)) {
+ qual1 = unbox(qual1, tree.symbol.owner.tpe)
+ }
+ if (tree.symbol != NoSymbol)
+ if (isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.symbol))
+ tree.symbol = NoSymbol
+ else if (qual.tpe.isInstanceOf[MethodType] && qual.tpe.paramTypes.isEmpty) {
+ assert(qual.symbol.isStable);
+ qual1 = Apply(qual, List()) setPos qual.pos setType qual.tpe.resultType;
+ } else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.symbol isSubClass tree.symbol.owner)))
+ qual1 = gen.cast(qual1, tree.symbol.owner.tpe);
+ copy.Select(tree, qual1, name)
}
- if (tree.symbol != NoSymbol)
- if (isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.symbol))
- tree.symbol = NoSymbol
- else if (qual.tpe.isInstanceOf[MethodType] && qual.tpe.paramTypes.isEmpty) {
- assert(qual.symbol.isStable);
- qual1 = Apply(qual, List()) setType qual.tpe.resultType;
- } else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.symbol isSubClass tree.symbol.owner)))
- qual1 = cast(qual1, tree.symbol.owner.tpe);
- copy.Select(tree, qual1, name)
- }
- case Template(parents, body) =>
- copy.Template(tree, tree.symbol.owner.info.parents map TypeTree, body)
- case _ =>
- tree
+ case _ =>
+ tree
+ }
}
/** A replacement for the standard typer's `adapt' method */
@@ -312,8 +307,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
*/
private def checkNoDoubleDefs(root: Symbol): unit = {
def doubleDefError(sym1: Symbol, sym2: Symbol) = {
- val tpe1 = atPhase(typerPhase.next)(root.tpe.memberType(sym1));
- val tpe2 = atPhase(typerPhase.next)(root.tpe.memberType(sym2));
+ val tpe1 = atPhase(refchecksPhase.next)(root.tpe.memberType(sym1));
+ val tpe2 = atPhase(refchecksPhase.next)(root.tpe.memberType(sym2));
unit.error(
if (sym1.owner == root) sym1.pos else root.pos,
(if (sym1.owner == sym2.owner) "double definition:\n"
@@ -330,7 +325,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
val decls = root.info.decls;
var e = decls.elems;
while (e != null) {
- if (e.sym.isTerm && !e.sym.isConstructor && !e.sym.isMixinConstructor) {
+ if (e.sym.isTerm && !e.sym.isConstructor) {
var e1 = decls.lookupNextEntry(e);
while (e1 != null) {
if (atPhase(phase.next)(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym);
@@ -341,15 +336,12 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
}
for (val bc <- root.info.baseClasses.tail; val other <- bc.info.decls.toList) {
- if (other.isTerm &&
- !other.isConstructor &&
- !other.isMixinConstructor &&
- !(other hasFlag (PRIVATE | BRIDGE))) {
+ if (other.isTerm && !other.isConstructor && !(other hasFlag (PRIVATE | BRIDGE))) {
for (val member <- root.info.nonPrivateMember(other.name).alternatives) {
if (member != other &&
!(member hasFlag BRIDGE) &&
atPhase(phase.next)(member.tpe =:= other.tpe) &&
- !atPhase(typerPhase.next)(
+ !atPhase(refchecksPhase.next)(
root.thisType.memberType(member) matches root.thisType.memberType(other))) {
if (settings.debug.value) log("" + member.locationString + " " + member.infosString + other.locationString + " " + other.infosString);
doubleDefError(member, other)
@@ -374,7 +366,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
val bridgeTarget = new HashMap[Symbol, Symbol];
var bridges: List[Tree] = List();
for (val bc <- site.baseClasses.tail; val other <- bc.info.members) {
- if (other.isMethod && !other.isConstructor && !other.isMixinConstructor) {
+ if (other.isMethod && !other.isConstructor) {
for (val member <- site.nonPrivateMember(other.name).alternatives) {
if (member != other &&
!(member hasFlag DEFERRED) &&
diff --git a/sources/scala/tools/nsc/transform/ExplicitOuter.scala b/sources/scala/tools/nsc/transform/ExplicitOuter.scala
index bea9fd63ce..673ba1fdb8 100755
--- a/sources/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/sources/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -31,9 +31,9 @@ abstract class ExplicitOuter extends InfoTransform {
* 2. Add a mixin constructor $init$ to all traits except interfaces
* Leave all other types unchanged.
*/
- override def transformInfo(sym: Symbol, tp: Type): Type = tp match {
+ def transformInfo(sym: Symbol, tp: Type): Type = tp match {
case MethodType(formals, restpe) =>
- if ((sym.isConstructor || sym.isMixinConstructor) && !sym.owner.isStatic)
+ if (sym.isConstructor && !sym.owner.isStatic)
MethodType(formals ::: List(sym.owner.owner.enclClass.thisType), restpe)
else tp;
case ClassInfoType(parents, decls, clazz) =>
@@ -46,7 +46,7 @@ abstract class ExplicitOuter extends InfoTransform {
setFlag (LOCAL | PRIVATE | PARAMACCESSOR)
setInfo outerType);
decls1 enter (clazz.newMethod(clazz.pos, nme.OUTER)
- setFlag (PRIVATE | PARAMACCESSOR | ACCESSOR | STABLE | FINAL)
+ setFlag (PARAMACCESSOR | ACCESSOR | STABLE | FINAL)
setInfo MethodType(List(), outerType));
}
if (clazz.isTrait) {
@@ -65,6 +65,64 @@ abstract class ExplicitOuter extends InfoTransform {
private def makeMixinConstructor(clazz: Symbol): Symbol =
clazz.newMethod(clazz.pos, nme.MIXIN_CONSTRUCTOR) setInfo MethodType(List(), UnitClass.tpe);
+ /** A base class for transformers that maintain `outerParam' values for
+ * outer parameters of constructors.
+ * The class provides methods for referencing via outer.
+ */
+ class OuterPathTransformer extends Transformer {
+
+ /** The directly enclosing outer parameter, if we are in a constructor */
+ protected var outerParam: Symbol = NoSymbol;
+
+ /** The first outer selection from currently transformed tree
+ */
+ protected def outerValue: Tree =
+ if (outerParam != NoSymbol) gen.Ident(outerParam)
+ else outerSelect(gen.This(currentOwner.enclClass));
+
+ /** The path
+ * `base'.$outer ... .$outer
+ * which refers to the outer instance `to' of value `base
+ */
+ protected def outerPath(base: Tree, to: Symbol): Tree =
+ if (base.tpe.symbol == to) base else outerPath(outerSelect(base), to);
+
+ /** Select and apply outer accessor from `base'
+ */
+ private def outerSelect(base: Tree): Tree = {
+ assert(base.tpe != null, base);
+ assert(base.tpe.symbol != null, base);
+ val clazz = base.tpe.symbol.owner.enclClass;
+ Apply(
+ Select(base, base.tpe.member(nme.OUTER)) setType MethodType(List(), clazz.thisType),
+ List()) setType clazz.thisType
+ }
+
+ override def transform(tree: Tree): Tree = {
+ try {//debug
+ val savedOuterParam = outerParam;
+ tree match {
+ case Template(_, _) =>
+ outerParam = NoSymbol;
+ case DefDef(_, _, _, vparamss, _, _) =>
+ if (tree.symbol.isConstructor && !(tree.symbol.owner.isStatic)) {
+ val lastParam = vparamss.head.last;
+ assert(lastParam.name == nme.OUTER, tree);
+ outerParam = lastParam.symbol
+ }
+ case _ =>
+ }
+ val result = super.transform(tree);
+ outerParam = savedOuterParam;
+ result
+ } catch {//debug
+ case ex: Throwable =>
+ System.out.println("exception when transforming " + tree);
+ throw ex
+ }
+ }
+ }
+
class ExplicitOuterTransformer(unit: CompilationUnit) extends Transformer {
/** A map that takes triples consisting of
@@ -107,24 +165,6 @@ abstract class ExplicitOuter extends InfoTransform {
accessor
}
- /** The path
- * `from'.this.$outer ... .$outer
- * which is equivalent to an outer self reference `to'.this from within class `from'
- */
- def outerPath(base: Tree, to: Symbol): Tree =
- if (base.tpe.symbol == to) base else outerPath(outerSelect(base), to);
-
- /** Select and apply outer accessor from `base'
- */
- def outerSelect(base: Tree): Tree = {
- assert(base.tpe != null, base);
- assert(base.tpe.symbol != null, base);
- val clazz = base.tpe.symbol.owner.enclClass;
- Apply(
- Select(base, base.tpe.member(nme.OUTER)) setType MethodType(List(), clazz.thisType),
- List()) setType clazz.thisType;
- }
-
/** The first step performs the following transformations:
* 1. A class which is not an interface and is not static gets an outer link
* (@see outerDefs)
@@ -147,20 +187,10 @@ abstract class ExplicitOuter extends InfoTransform {
* is augmented to this.<init>(args, OUTER) where OUTER is the last parameter
* of the secondary constructor.
*/
- private val firstTransformer = new Transformer {
+ private val firstTransformer = new OuterPathTransformer {
var localTyper: analyzer.Typer = typer;
- /** The directly enclosing outer parameter, if we are in a constructor
- */
- var outerParam: Symbol = NoSymbol;
-
- /** The first outer selection from currently transformed tree
- */
- def outerValue: Tree =
- if (outerParam != NoSymbol) gen.Ident(outerParam)
- else outerSelect(gen.This(currentOwner.enclClass));
-
/** The two definitions
* val outer : C.this.type _;
* def outer(): C.this.type = outer ;
@@ -172,7 +202,7 @@ abstract class ExplicitOuter extends InfoTransform {
List(
localTyper.typed {
atPos(clazz.pos) {
- ValDef(outerVal, EmptyTree)
+ ValDef(outerVal)
}
},
localTyper.typed {
@@ -186,7 +216,7 @@ abstract class ExplicitOuter extends InfoTransform {
* def $init$(): Unit = ()
*/
def mixinConstructorDef(clazz: Symbol): Tree = localTyper.typed {
- DefDef(clazz.mixinConstructor, vparamss => Literal(()))
+ DefDef(clazz.primaryConstructor, vparamss => Literal(()))
}
/** Add calls to supermixin constructors
@@ -198,7 +228,7 @@ abstract class ExplicitOuter extends InfoTransform {
atPos(tree.pos) {
Apply(
localTyper.typedOperator {
- Select(Super(clazz, mixin.name), mixin.mixinConstructor)
+ Select(Super(clazz, mixin.name), mixin.primaryConstructor)
},
List()) setType UnitClass.tpe; // don't type this with typed(...),
// as constructor arguments might be missing
@@ -216,19 +246,16 @@ abstract class ExplicitOuter extends InfoTransform {
case Block(_, _) =>
assert(false, tree); tree
case expr =>
- Block(mixinConstructorCalls, expr) setType expr.tpe
+ Block(mixinConstructorCalls, expr) setType expr.tpe setPos expr.pos;
}
}
/** The first-step transformation method */
override def transform(tree: Tree): Tree = {
- try {
- val savedOuterParam = outerParam;
val sym = tree.symbol;
val tree1 = tree match {
case Template(parents, decls) =>
val savedLocalTyper = localTyper;
- outerParam = NoSymbol;
localTyper = localTyper.atOwner(tree, currentOwner);
var decls1 = decls;
if (!(currentOwner hasFlag INTERFACE)) {
@@ -240,13 +267,13 @@ abstract class ExplicitOuter extends InfoTransform {
localTyper = savedLocalTyper;
copy.Template(tree, parents, decls1);
case constrDef @ DefDef(mods, name, tparams, vparamss, tpt, rhs)
- if (sym.isConstructor || sym.isMixinConstructor) =>
+ if (sym.isConstructor) =>
val vparamss1 =
if (sym.owner.isStatic) vparamss
else { // (4)
val outerField = sym.owner.info.decl(nme.LOCAL_NAME(nme.OUTER));
- outerParam = sym.newValueParameter(sym.pos, nme.OUTER) setInfo outerField.info;
- List(vparamss.head ::: List(ValDef(outerParam, EmptyTree)))
+ val outerParam = sym.newValueParameter(sym.pos, nme.OUTER) setInfo outerField.info;
+ List(vparamss.head ::: List(ValDef(outerParam) setType NoType))
}
val rhs1 =
if ((sym.isPrimaryConstructor || sym.isMixinConstructor) && sym.owner != ArrayClass)
@@ -255,34 +282,31 @@ abstract class ExplicitOuter extends InfoTransform {
copy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs1);
case This(qual) =>
if (sym == currentOwner.enclClass || sym.isStatic) tree
- else atPos(tree.pos)(outerPath(outerValue, sym)) // (5)
+ else atPos(tree.pos)(outerPath(outerValue, sym)); // (5)
case Select(qual @ Super(_, mix), name) =>
val qsym = qual.symbol;
if (!needSuperAccessors || tree.symbol.isType || qsym == currentOwner.enclClass)
tree
else atPos(tree.pos) { // (6)
val accessor = superAccessor(qsym, tree.symbol, mix);
- Select(if (qsym.isStatic) This(qsym) else outerPath(outerValue, qsym), accessor)
+ Select(if (qsym.isStatic) This(qsym)
+ else outerPath(outerValue, qsym), accessor)
setType accessor.tpe
}
case Apply(sel @ Select(qual, name), args)
if ((name == nme.CONSTRUCTOR || name == nme.MIXIN_CONSTRUCTOR)
&& !sel.symbol.owner.isStatic) =>
val outerVal =
- if (qual.isInstanceOf[This]) { assert(outerParam != NoSymbol); outerValue } // (8)
- else gen.mkQualifier(qual.tpe.prefix); // (7)
+ atPos(tree.pos) {
+ if (qual.isInstanceOf[This]) { assert(outerParam != NoSymbol); outerValue } // (8)
+ else if (qual.tpe.prefix == NoPrefix) gen.This(currentOwner.enclClass)
+ else gen.mkQualifier(qual.tpe.prefix); // (7)
+ }
copy.Apply(tree, sel, args ::: List(outerVal))
case _ =>
tree
}
- val result = super.transform(tree1);
- outerParam = savedOuterParam;
- result
- } catch {//debug
- case ex: Throwable =>
- System.out.println("exception when transforming " + tree);
- throw ex
- }
+ super.transform(tree1)
}
}
diff --git a/sources/scala/tools/nsc/transform/Flatten.scala b/sources/scala/tools/nsc/transform/Flatten.scala
new file mode 100755
index 0000000000..7f4122c279
--- /dev/null
+++ b/sources/scala/tools/nsc/transform/Flatten.scala
@@ -0,0 +1,91 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author
+ */
+// $Id$
+package scala.tools.nsc.transform;
+
+import symtab._;
+import Flags._;
+import util.ListBuffer;
+import collection.mutable.HashMap;
+
+abstract class Flatten extends InfoTransform {
+ import global._;
+ import definitions._;
+
+ /** the following two members override abstract members in Transform */
+ val phaseName: String = "flatten";
+
+ private val flattened = new TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) if (pre.symbol.isClass && !pre.symbol.isPackageClass) =>
+ assert(args.isEmpty);
+ typeRef(sym.toplevelClass.owner.thisType, sym, args)
+ case ClassInfoType(parents, decls, clazz) =>
+ val parents1 = List.mapConserve(parents)(this);
+ if (parents1 eq parents) tp
+ else ClassInfoType(parents1, decls, clazz)
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
+ def transformInfo(sym: Symbol, tp: Type): Type = flattened(tp);
+
+ protected def newTransformer(unit: CompilationUnit): Transformer =
+ new Flattener(unit);
+
+ class Flattener(unit: CompilationUnit) extends Transformer {
+
+ /** Buffers for lifted out classes */
+ private val liftedDefs = new HashMap[Symbol, ListBuffer[Tree]];
+
+ override def transform(tree: Tree): Tree = {
+ tree match {
+ case PackageDef(_, _) =>
+ liftedDefs(tree.symbol.moduleClass) = new ListBuffer;
+ case _ =>
+ }
+ postTransform(super.transform(tree))
+ }
+
+ private def postTransform(tree: Tree): Tree = {
+ val sym = tree.symbol;
+ val tree1 = tree match {
+ case ClassDef(_, _, _, _, _) if sym.isNestedClass =>
+ liftedDefs(sym.toplevelClass.owner) += tree;
+ EmptyTree
+ case Super(qual, mix) if (mix != nme.EMPTY.toTypeName) =>
+ val ps = tree.symbol.info.parents dropWhile (p => p.symbol.name != mix);
+ assert(!ps.isEmpty, tree);
+ val mix1 = if (ps.head.symbol.isNestedClass) atPhase(phase.next)(ps.head.symbol.name)
+ else mix;
+ copy.Super(tree, qual, mix1)
+ case _ =>
+ tree
+ }
+ tree1 setType flattened(tree1.tpe);
+ if (sym != null && sym.isNestedClass && !(sym hasFlag FLATTENED)) {
+ sym setFlag FLATTENED;
+ atPhase(phase.next) {
+ System.out.println("re-enter " + sym + " in " + sym.owner);//debug
+ val scope = sym.owner.info.decls;
+ val old = scope lookup sym.name;
+ if (old != NoSymbol) scope unlink old;
+ scope enter sym;
+ }
+ }
+ tree1
+ }
+
+ /** Transform statements and add lifted definitions to them. */
+ override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
+ val stats1 = super.transformStats(stats, exprOwner);
+ if (currentOwner.isPackageClass && liftedDefs(currentOwner).hasNext)
+ stats1 ::: liftedDefs(currentOwner).toList
+ else
+ stats1
+ }
+ }
+}
diff --git a/sources/scala/tools/nsc/transform/LambdaLift.scala b/sources/scala/tools/nsc/transform/LambdaLift.scala
new file mode 100755
index 0000000000..353baf620b
--- /dev/null
+++ b/sources/scala/tools/nsc/transform/LambdaLift.scala
@@ -0,0 +1,317 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author
+ */
+// $Id$
+package scala.tools.nsc.transform;
+
+import symtab._;
+import Flags._;
+import util.{ListBuffer, TreeSet};
+import collection.mutable.HashMap;
+
+abstract class LambdaLift extends InfoTransform {
+ import global._;
+ import definitions._;
+ import typer.{typed}; // methods to type trees
+ import posAssigner.atPos; // for filling in tree positions
+
+ /** the following two members override abstract members in Transform */
+ val phaseName: String = "lambdalift";
+
+ private val lifted = new TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) =>
+ if (pre == NoPrefix && sym.isClass && !sym.isPackageClass) {
+ assert(args.isEmpty);
+ typeRef(apply(sym.owner.enclClass.thisType), sym, args)
+ } else mapOver(tp)
+ case ClassInfoType(parents, decls, clazz) =>
+ val parents1 = List.mapConserve(parents)(this);
+ if (parents1 eq parents) tp
+ else ClassInfoType(parents1, decls, clazz)
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
+ def transformInfo(sym: Symbol, tp: Type): Type = lifted(tp);
+
+ protected def newTransformer(unit: CompilationUnit): Transformer =
+ new LambdaLifter(unit);
+
+ class LambdaLifter(unit: CompilationUnit) extends explicitOuter.OuterPathTransformer {
+
+ /** A map storing free variables of functions and classes */
+ private val free = new HashMap[Symbol,SymSet];
+
+ /** A map storing the free variable proxies of functions and classes */
+ private val proxies = new HashMap[Symbol, List[Symbol]];
+
+ /** A hashtable storing calls between functions */
+ private val called = new HashMap[Symbol, SymSet];
+
+ /** The set of symbols that need to be renamed. */
+ private val renamable = newSymSet;
+
+ /** A flag to indicate whether new free variables have been found */
+ private var changedFreeVars: boolean = _;
+
+ /** Buffers for lifted out classes and methods */
+ private val liftedDefs = new HashMap[Symbol, ListBuffer[Tree]];
+
+ private type SymSet = TreeSet[Symbol];
+
+ private def newSymSet = new TreeSet[Symbol]((x, y) => x.isLess(y));
+
+ private def symSet(f: HashMap[Symbol, SymSet], sym: Symbol): SymSet = f.get(sym) match {
+ case Some(ss) => ss
+ case None => val ss = newSymSet; f(sym) = ss; ss
+ }
+
+ private def outer(sym: Symbol): Symbol =
+ if (sym.isConstructor) sym.owner.owner else sym.owner;
+
+ private def enclMethOrClass(sym: Symbol): Symbol = {
+ def localToConstr(sym: Symbol) =
+ if (sym.isLocalDummy) sym.owner.primaryConstructor else sym;
+ var encl = localToConstr(sym);
+ while (!encl.isMethod && !encl.isClass)
+ encl = localToConstr(outer(encl));
+ encl
+ }
+
+ /** Mark symbol `sym' as being free in `owner', unless `sym'
+ * is defined in `owner' or there is a class between `owner's owner
+ * and the owner of `sym'.
+ * Return `true' if there is no class between `owner' and
+ * the owner of sym.
+ * pre: sym.isLocal, (owner.isMethod || owner.isClass)
+ */
+ private def markFree(sym: Symbol, owner: Symbol): boolean = {
+ if (settings.debug.value) log("mark " + sym + " of " + sym.owner + " free in " + owner);
+ if (owner == enclMethOrClass(sym.owner)) true
+ else if (owner.isPackageClass || !markFree(sym, enclMethOrClass(outer(owner)))) false
+ else {
+ val ss = symSet(free, owner);
+ if (!(ss contains sym)) {
+ ss addEntry sym;
+ renamable addEntry sym;
+ changedFreeVars = true;
+ if (settings.debug.value) log("" + sym + " is free in " + owner);
+ if (sym.isVariable && !(sym hasFlag CAPTURED)) {
+ sym setFlag CAPTURED;
+ val symClass = sym.tpe.symbol;
+ atPhase(phase.next) {
+ sym updateInfo (
+ if (isValueClass(symClass)) refClass(symClass).tpe else ObjectRefClass.tpe)
+ }
+ }
+ }
+ !owner.isClass
+ }
+ }
+
+ def freeVars(sym: Symbol): Iterator[Symbol] = free.get(sym) match {
+ case Some(ss) => ss.elements
+ case None => Iterator.empty
+ }
+
+ /** The traverse function */
+ private val freeVarTraverser = new Traverser {
+ override def traverse(tree: Tree): unit = {
+ try { //debug
+ val sym = tree.symbol;
+ tree match {
+ case ClassDef(_, _, _, _, _) =>
+ liftedDefs(tree.symbol) = new ListBuffer;
+ if (sym.isLocal) renamable addEntry sym;
+ case DefDef(_, _, _, _, _, _) =>
+ if (sym.isLocal) renamable addEntry sym;
+ if (sym.isPrimaryConstructor) symSet(called, sym) addEntry sym.owner;
+ case Ident(name) =>
+ if (sym == NoSymbol) {
+ assert(name == nme.WILDCARD)
+ } else if (sym.isLocal) {
+ val owner = enclMethOrClass(currentOwner);
+ if (owner.isMethod && sym.isMethod) symSet(called, owner) addEntry sym;
+ else if (sym.isTerm) markFree(sym, owner)
+ }
+ case _ =>
+ }
+ super.traverse(tree)
+ } catch {//debug
+ case ex: Throwable =>
+ System.out.println("exception when traversing " + tree);
+ throw ex
+ }
+ }
+ }
+
+ /** Compute free variables map `fvs'.
+ * Also assign unique names to all
+ * value/variable/let that are free in some function or class, and to
+ * all class/function symbols that are owned by some function.
+ */
+ private def computeFreeVars: unit = {
+ freeVarTraverser.traverse(unit.body);
+
+ do {
+ changedFreeVars = false;
+ for (val caller <- called.keys;
+ val callee <- called(caller).elements;
+ val fv <- freeVars(callee))
+ markFree(fv, caller);
+ } while (changedFreeVars);
+
+ for (val sym <- renamable.elements) {
+ sym.name = unit.fresh.newName(sym.name.toString());
+ if (settings.debug.value) log("renamed: " + sym.name);
+ }
+
+ atPhase(phase.next) {
+ for (val owner <- free.keys) {
+ if (settings.debug.value)
+ log("free(" + owner + owner.locationString + ") = " + free(owner).elements.toList);
+ proxies(owner) =
+ for (val fv <- free(owner).elements.toList) yield {
+ val proxy = owner.newValue(owner.pos, fv.name)
+ setFlag (if (owner.isClass) PARAMACCESSOR | PRIVATE | LOCAL else PARAM)
+ setFlag SYNTHETIC
+ setInfo fv.info;
+ if (owner.isClass) owner.info.decls enter proxy;
+ proxy
+ }
+ }
+ }
+ }
+
+ private def proxy(sym: Symbol) = {
+ def searchIn(owner: Symbol): Symbol = {
+ if (settings.debug.value) log("searching for " + sym + " in " + owner + " " + enclMethOrClass(owner));//debug
+ proxies.get(enclMethOrClass(owner)) match {
+ case Some(ps) =>
+ ps filter (p => p.name == sym.name) match {
+ case List(p) => p
+ case List() => searchIn(outer(owner))
+ }
+ case None => searchIn(outer(owner))
+ }
+ }
+ if (settings.debug.value) log("proxy " + sym + " in " + sym.owner + " from " + currentOwner + " " + enclMethOrClass(sym.owner));//debug
+ if (enclMethOrClass(sym.owner) == enclMethOrClass(currentOwner)) sym
+ else searchIn(currentOwner)
+ }
+
+ private def proxyRef(sym: Symbol) = {
+ val psym = proxy(sym);
+ if (psym.isLocal) gen.Ident(psym)
+ else if (psym.owner == currentOwner.enclClass) gen.mkRef(psym)
+ else {
+ psym resetFlag (PRIVATE | LOCAL);
+ Select(outerPath(outerValue, psym.owner), psym) setType psym.tpe
+ }
+ }
+
+ private def addFreeArgs(pos: int, sym: Symbol, args: List[Tree]) = {
+ def freeArg(fv: Symbol) = atPos(pos)(proxyRef(fv));
+ val fvs = freeVars(sym).toList;
+ if (fvs.isEmpty) args else args ::: (fvs map freeArg)
+ }
+
+ private def addFreeParams(tree: Tree, sym: Symbol): Tree = proxies.get(sym) match {
+ case Some(ps) =>
+ val freeParams = ps map (p => ValDef(p) setPos tree.pos setType NoType);
+ tree match {
+ case DefDef(mods, name, tparams, List(vparams), tpt, rhs) =>
+ sym.updateInfo(
+ lifted(MethodType(sym.info.paramTypes ::: (ps map (.tpe)), sym.info.resultType)));
+ copy.DefDef(tree, mods, name, tparams, List(vparams ::: freeParams), tpt, rhs)
+ case ClassDef(mods, name, tparams, tpt, impl @ Template(parents, body)) =>
+ copy.ClassDef(tree, mods, name, tparams, tpt,
+ copy.Template(impl, parents, body ::: freeParams))
+ }
+ case None =>
+ tree
+ }
+
+ private def liftDef(tree: Tree): Tree = {
+ val sym = tree.symbol;
+ if (sym.isMethod) sym setFlag (PRIVATE | LOCAL);
+ sym.owner = sym.owner.enclClass;
+ liftedDefs(sym.owner) += tree;
+ sym.owner.info.decls enter sym;
+ EmptyTree
+ }
+
+ private def postTransform(tree: Tree): Tree = {
+ val sym = tree.symbol;
+ tree match {
+ case ClassDef(_, _, _, _, _) =>
+ if (sym.isLocal) liftDef(tree) else tree
+ case DefDef(_, _, _, _, _, _) =>
+ val tree1 = addFreeParams(tree, sym);
+ if (sym.isLocal) liftDef(tree1) else tree1
+ case ValDef(mods, name, tpt, rhs) =>
+ if (sym hasFlag CAPTURED) {
+ val tpt1 = TypeTree(sym.tpe) setPos tpt.pos;
+ val rhs1 =
+ atPos(rhs.pos) {
+ typed {
+ Apply(Select(New(TypeTree(sym.tpe)), nme.CONSTRUCTOR), List(rhs))
+ }
+ }
+ copy.ValDef(tree, mods, name, tpt1, rhs1)
+ } else tree
+ case Return(Block(stats, value)) =>
+ Block(stats, copy.Return(tree, value)) setType tree.tpe setPos tree.pos;
+ case Return(expr) =>
+ if (sym != currentOwner.enclMethod) {
+ System.out.println(sym);//debug
+ System.out.println(currentOwner.enclMethod);//debug
+ unit.error(tree.pos, "non-local return not yet implemented");
+ }
+ tree
+ case Apply(fn, args) =>
+ copy.Apply(tree, fn, addFreeArgs(tree.pos, sym, args));
+ case Assign(Apply(TypeApply(sel @ Select(qual, _), _), List()), rhs) =>
+ // eliminate casts introduced by selecting a captured variable field
+ // on the lhs of an assignment.
+ assert(sel.symbol == Object_asInstanceOf);
+ copy.Assign(tree, qual, rhs)
+ case Ident(name) =>
+ val tree1 =
+ if (sym != NoSymbol && sym.isLocal && sym.isTerm && !sym.isMethod &&
+ enclMethOrClass(sym.owner) != enclMethOrClass(currentOwner))
+ atPos(tree.pos)(proxyRef(sym))
+ else tree;
+ if (sym hasFlag CAPTURED)
+ atPos(tree.pos) {
+ val tp = tree.tpe;
+ val elemTree = typed { Select(tree1 setType sym.tpe, nme.elem) }
+ if (elemTree.tpe.symbol != tp.symbol) gen.cast(elemTree, tp) else elemTree
+ }
+ else tree1
+ case _ =>
+ tree
+ }
+ }
+
+ override def transform(tree: Tree): Tree =
+ postTransform(super.transform(tree) setType lifted(tree.tpe));
+
+ /** Transform statements and add lifted definitions to them. */
+ override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
+ val stats1 = super.transformStats(stats, exprOwner);
+ if (currentOwner.isClass && !currentOwner.isPackageClass && liftedDefs(currentOwner).hasNext)
+ stats1 ::: liftedDefs(currentOwner).toList
+ else
+ stats1
+ }
+
+ override def transformUnit(unit: CompilationUnit): unit = {
+ computeFreeVars;
+ atPhase(phase.next)(super.transformUnit(unit))
+ }
+ }
+}
diff --git a/sources/scala/tools/nsc/transform/TailCalls.scala b/sources/scala/tools/nsc/transform/TailCalls.scala
index 40e815203f..1a96619ef3 100644
--- a/sources/scala/tools/nsc/transform/TailCalls.scala
+++ b/sources/scala/tools/nsc/transform/TailCalls.scala
@@ -150,7 +150,8 @@ abstract class TailCalls extends Transform
copy.DefDef(tree, mods, name, tparams, vparams, tpt, newRHS);
} else {
log("Non-final method: " + name);
- DefDef(newCtx.currentMethod, (x) => transform(rhs, newCtx));
+ // Martin: OK like that?
+ copy.DefDef(tree, mods, name, tparams, vparams, tpt, transform(rhs, newCtx))
}
log("Leaving DefDef: " + name);
t1;
diff --git a/sources/scala/tools/nsc/transform/Transform.scala b/sources/scala/tools/nsc/transform/Transform.scala
index 0710e67641..cfdf796f27 100644
--- a/sources/scala/tools/nsc/transform/Transform.scala
+++ b/sources/scala/tools/nsc/transform/Transform.scala
@@ -19,7 +19,7 @@ abstract class Transform extends SubComponent {
/** The phase defined by this transform */
class Phase(prev: scala.tools.nsc.Phase) extends StdPhase(prev) {
def apply(unit: global.CompilationUnit): unit = {
- unit.body = newTransformer(unit).transform(unit.body);
+ newTransformer(unit).transformUnit(unit);
}
}
}
diff --git a/sources/scala/tools/nsc/transform/UnCurry.scala b/sources/scala/tools/nsc/transform/UnCurry.scala
index a97d27e38b..741e530a44 100755
--- a/sources/scala/tools/nsc/transform/UnCurry.scala
+++ b/sources/scala/tools/nsc/transform/UnCurry.scala
@@ -22,7 +22,7 @@ package scala.tools.nsc.transform;
* - for every argument list that is an escaped sequence
* (a_1:_*) => (a_1)g
* - convert implicit method types to method types
- * - todo: check-no-double-def in erasure
+ * - convert non-trivial catches in try statements to matches
*/
/*</export>*/
abstract class UnCurry extends InfoTransform {
@@ -120,6 +120,12 @@ abstract class UnCurry extends InfoTransform {
val pat1 = transform(pat);
inPattern = false;
copy.CaseDef(tree, pat1, transform(guard), transform(body))
+/*
+ case Try(body, catches, finally) =>
+ catches1 = catches map {
+ case cdef @ CaseDef(pat, guard, body) if TreeInfo.isDefaultCase(cdef) =>
+ CaseDef(TypedTree(Ident(TreeInfo.defaultCaseVar(pat)), TypeTree(ThrowableClass.tpe)))
+*/
case _ =>
val tree1 = super.transform(tree);
if (isByNameRef(tree1))
@@ -133,8 +139,8 @@ abstract class UnCurry extends InfoTransform {
if (tree.symbol.isMethod && (!tree.tpe.isInstanceOf[PolyType] || tree.tpe.typeParams.isEmpty)) {
if (!tree.tpe.isInstanceOf[MethodType]) tree.tpe = MethodType(List(), tree.tpe);
atPos(tree.pos)(Apply(tree, List()) setType tree.tpe.resultType)
- } else if (tree.isType) {
- TypeTree(tree.tpe)
+ } else if (tree.isType && !tree.isInstanceOf[TypeTree]) {
+ TypeTree(tree.tpe) setPos tree.pos
} else {
tree
}
diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala
index bb63df325d..601bb74ef5 100755
--- a/sources/scala/tools/nsc/typechecker/Namers.scala
+++ b/sources/scala/tools/nsc/typechecker/Namers.scala
@@ -14,6 +14,20 @@ trait Namers: Analyzer {
import global._;
import definitions._;
+ def updatePosFlags(sym: Symbol, pos: int, mods: int): Symbol = {
+ if (settings.debug.value) log("overwriting " + sym);
+ sym.pos = pos;
+ val oldflags = sym.flags & (INITIALIZED | LOCKED);
+ val newflags = mods & ~(INITIALIZED | LOCKED);
+ sym.flags = oldflags | newflags;
+ if (sym.isModule)
+ updatePosFlags(sym.moduleClass, pos, (mods & ModuleToClassFlags) | MODULE | FINAL);
+ if (sym.owner.isPackageClass && sym.linkedSym.rawInfo.isInstanceOf[loaders.SymbolLoader])
+ // pre-set linked symbol to NoType, in case it is not loaded together with this symbol.
+ sym.linkedSym.setInfo(NoType);
+ sym
+ }
+
class Namer(val context: Context) {
private def isTemplateContext(context: Context): boolean = context.tree match {
@@ -35,20 +49,6 @@ trait Namers: Analyzer {
sym.name.toString() + " is already defined as " +
(if (sym.hasFlag(CASE)) "case class " + sym.name else sym.toString()));
- private def updatePosFlags(sym: Symbol, pos: int, mods: int): Symbol = {
- if (settings.debug.value) log("overwriting " + sym);
- sym.pos = pos;
- val oldflags = sym.flags & (INITIALIZED | LOCKED);
- val newflags = mods & ~(INITIALIZED | LOCKED);
- sym.flags = oldflags | newflags;
- if (sym.isModule)
- updatePosFlags(sym.moduleClass, pos, (mods & ModuleToClassFlags) | MODULE | FINAL);
- if (sym.owner.isPackageClass && sym.linkedSym.rawInfo.isInstanceOf[loaders.SymbolLoader])
- // pre-set linked symbol to NoType, in case it is not loaded together with this symbol.
- sym.linkedSym.setInfo(NoType);
- sym
- }
-
def enterInScope(sym: Symbol): Symbol = {
if (!(sym.isSourceMethod && sym.owner.isClass)) {
val prev = context.scope.lookupEntry(sym.name);
@@ -284,7 +284,7 @@ trait Namers: Analyzer {
val restype =
if (tpt.isEmpty) {
tpt.tpe = if (meth.name == nme.CONSTRUCTOR) context.enclClass.owner.tpe
- else deconstIfNotFinal(meth, typer.typed(rhs).tpe);
+ else deconstIfNotFinal(meth, typer.computeType(rhs));
tpt.tpe
} else typer.typedType(tpt).tpe;
def mkMethodType(vparams: List[Symbol], restpe: Type) = {
@@ -359,7 +359,7 @@ trait Namers: Analyzer {
context.error(tpt.pos, "missing parameter type");
ErrorType
} else {
- tpt.tpe = deconstIfNotFinal(sym, newTyper(context.make(tree, sym)).typed(rhs).tpe);
+ tpt.tpe = deconstIfNotFinal(sym, newTyper(context.make(tree, sym)).computeType(rhs));
tpt.tpe
}
else typer.typedType(tpt).tpe
diff --git a/sources/scala/tools/nsc/typechecker/RefChecks.scala b/sources/scala/tools/nsc/typechecker/RefChecks.scala
index 885da9c542..0cceb34512 100755
--- a/sources/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/sources/scala/tools/nsc/typechecker/RefChecks.scala
@@ -8,7 +8,7 @@ package scala.tools.nsc.typechecker;
import symtab.Flags._;
import collection.mutable.HashMap;
import util.ListBuffer;
-import transform.Transform;
+import transform.InfoTransform;
/** Post-attribution checking and transformation.
* //todo: check whether we always check type parameter bounds.
@@ -32,7 +32,7 @@ import transform.Transform;
* different from java.lang.Object
* - Calls to case factory methods are replaced by new's.
*/
-abstract class RefChecks extends Transform {
+abstract class RefChecks extends InfoTransform {
import global._;
import definitions._;
@@ -43,6 +43,13 @@ abstract class RefChecks extends Transform {
val phaseName: String = "refchecks";
def newTransformer(unit: CompilationUnit): Transformer = new RefCheckTransformer(unit);
+ def transformInfo(sym: Symbol, tp: Type): Type = {
+ if (sym.isModule && !sym.isStatic) {
+ sym setFlag (METHOD | STABLE);
+ PolyType(List(), tp)
+ } else tp
+ }
+
class RefCheckTransformer(unit: CompilationUnit) extends Transformer {
// Override checking ------------------------------------------------------------
@@ -162,7 +169,6 @@ abstract class RefChecks extends Transform {
"\n and " + infoString(alt2) +
"\n override " + infoString(other));
} else if (member != NoSymbol && !(member hasFlag LOCAL)) {
- member.flags = member.flags | ACCESSED;
checkOverride(clazz, member, other);
}
}
@@ -352,7 +358,7 @@ abstract class RefChecks extends Transform {
}
private def enterReference(pos: int, sym: Symbol): unit =
- if (sym.isLocal && sym.isTerm) {
+ if (sym.isLocal) {
val e = currentLevel.scope.lookupEntry(sym.name);
if (e != null && sym == e.sym) {
var l = currentLevel;
@@ -477,7 +483,9 @@ abstract class RefChecks extends Transform {
val sym = tree.symbol;
val localTyper = typer.atOwner(currentOwner);
val cdef = ClassDef(mods | MODULE, name, List(), EmptyTree, impl)
- setSymbol sym.moduleClass setType NoType;
+ setPos tree.pos
+ setSymbol sym.moduleClass
+ setType NoType;
if (sym.isStatic) List(transform(cdef))
else {
val moduleType = sym.tpe;
@@ -492,17 +500,19 @@ abstract class RefChecks extends Transform {
ValDef(mvar, if (sym.isLocal) Literal(Constant(null)) else EmptyTree));
// def m: T = { if (m$ == null) m$ = new m$class; m$ }
- sym.setFlag(METHOD | STABLE);
- sym.setInfo(PolyType(List(), moduleType));
- val ddef = localTyper.typed(
- DefDef(sym, vparamss =>
- Block(
- List(
- If(
- Apply(Select(Ident(mvar), nme.EQ), List(Literal(Constant(null)))),
- Assign(Ident(mvar), New(TypeTree(moduleType), List(List()))),
- EmptyTree)),
- Ident(mvar))));
+ val ddef =
+ atPhase(phase.next) {
+ localTyper.typed {
+ DefDef(sym, vparamss =>
+ Block(
+ List(
+ If(
+ Apply(Select(Ident(mvar), nme.EQ), List(Literal(Constant(null)))),
+ Assign(Ident(mvar), New(TypeTree(moduleType), List(List()))),
+ EmptyTree)),
+ Ident(mvar)))
+ }
+ }
transformTrees(List(cdef, vdef, ddef))
}
@@ -583,7 +593,6 @@ abstract class RefChecks extends Transform {
if (sym.isSourceMethod && sym.hasFlag(CASE))
result = toConstructor
else if (name != nme.WILDCARD && name != nme.WILDCARD_STAR.toTypeName) {
- sym setFlag ACCESSED;
assert(sym != NoSymbol, tree);//debug
enterReference(tree.pos, sym);
}
@@ -592,7 +601,6 @@ abstract class RefChecks extends Transform {
if (sym.isSourceMethod && sym.hasFlag(CASE))
result = toConstructor
else {
- sym setFlag ACCESSED;
if (sym hasFlag DEFERRED) {
qual match {
case Super(qualifier, mixin) =>
diff --git a/sources/scala/tools/nsc/typechecker/TreeCheckers.scala b/sources/scala/tools/nsc/typechecker/TreeCheckers.scala
index 791f865f24..c2191eff3d 100644
--- a/sources/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/sources/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -57,12 +57,35 @@ abstract class TreeCheckers extends Analyzer {
override def typed(tree: Tree) = super.typed(tree); // doto remove for new compiler
object precheck extends Traverser {
- override def traverse(tree: Tree): unit = {
- if (tree.pos == Position.NOPOS)
- error(tree.pos, "tree without position: " + tree)
- else if (tree.tpe == null && phase.id >= typerPhase.id)
- error(tree.pos, "tree without type: " + tree)
- }
+ override def traverse(tree: Tree): unit =
+ try {
+ tree match {
+ case Apply(_, args) =>
+ assert(args forall (EmptyTree !=))
+ case _ =>
+ }
+ if (tree.pos == Position.NOPOS && tree != EmptyTree) {
+ error(tree.pos, "tree without position: " + tree)
+ } else if (tree.tpe == null && phase.id >= typerPhase.id) {
+ error(tree.pos, "tree without type: " + tree);
+ } else if (tree.isDef && tree.symbol.owner != currentOwner) {
+ var owner = currentOwner;
+ while (owner.isTerm && !owner.isMethod && tree.symbol.owner != owner)
+ owner = owner.owner;
+ if (tree.symbol.owner != owner) {
+ error(tree.pos, "" + tree.symbol + " has wrong owner: " + tree.symbol.owner +
+ tree.symbol.owner.locationString + ", should be: " +
+ currentOwner + currentOwner.locationString)
+ }
+ } else {
+ super.traverse(tree)
+ }
+ } catch {
+ case ex: Throwable =>
+ if (settings.debug.value)
+ System.out.println("exception when traversing " + tree);
+ throw(ex)
+ }
}
object postcheck extends Traverser {
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index 55ee7c475c..68c092b8c0 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -9,6 +9,7 @@ package scala.tools.nsc.typechecker;
import nsc.util.ListBuffer;
import symtab.Flags._;
import scala.tools.util.Position;
+import collection.mutable.HashMap;
/** Methods to create symbols and to enter them into scopes. */
abstract class Typers: Analyzer {
@@ -21,6 +22,8 @@ abstract class Typers: Analyzer {
var selcnt = 0;
var implcnt = 0;
+ private var transformed = new HashMap[Tree, Tree];
+
def newTyper(context: Context): Typer = new Typer(context);
class Typer(context0: Context) {
@@ -34,8 +37,8 @@ abstract class Typers: Analyzer {
private def inferView(pos: int, from: Type, to: Type, reportAmbiguous: boolean): Tree = {
if (settings.debug.value) log("infer view from " + from + " to " + to);//debug
- val res = inferImplicit(pos, functionType(List(from), to), true, reportAmbiguous);
- res
+ if (phase.erasedTypes) EmptyTree
+ else inferImplicit(pos, functionType(List(from), to), true, reportAmbiguous);
}
private def inferView(pos: int, from: Type, name: Name, reportAmbiguous: boolean): Tree = {
@@ -502,11 +505,69 @@ abstract class Typers: Analyzer {
val sym = vdef.symbol;
var tpt1 = checkNoEscaping.privates(sym, typedType(vdef.tpt));
val rhs1 =
- if (vdef.rhs.isEmpty) vdef.rhs
- else newTyper(context.make(vdef, sym)).typed(vdef.rhs, tpt1.tpe);
+ if (vdef.rhs.isEmpty) {
+ if ((sym hasFlag MUTABLE) && sym.owner.isTerm && phase.id <= typerPhase.id)
+ error(vdef.pos, "local variables must be initialized");
+ vdef.rhs
+ } else {
+ newTyper(context.make(vdef, sym)).transformedOrTyped(vdef.rhs, tpt1.tpe)
+ }
copy.ValDef(vdef, vdef.mods, vdef.name, tpt1, rhs1) setType NoType
}
+ /** Enter in global.aliases all aliases of local parameter accessors. */
+ def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree): unit = {
+ if (settings.debug.value) log("computing param aliases for " + clazz + ":" + clazz.primaryConstructor.tpe + ":" + rhs);//debug
+ def decompose(call: Tree): Pair[Tree, List[Tree]] = call match {
+ case Apply(fn, args) =>
+ val Pair(superConstr, args1) = decompose(fn);
+ val formals = fn.tpe.paramTypes;
+ val args2 = if (formals.isEmpty || formals.last.symbol != RepeatedParamClass) args
+ else args.take(formals.length - 1) ::: List(EmptyTree);
+ if (args2.length != formals.length) assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug
+ Pair(superConstr, args1 ::: args2)
+ case Block(stats, expr) =>
+ decompose(stats.head)
+ case _ =>
+ Pair(call, List())
+ }
+ val Pair(superConstr, superArgs) = decompose(rhs);
+ assert(superConstr.symbol != null, superConstr);//debug
+ if (superConstr.symbol.isPrimaryConstructor) {
+ val superClazz = superConstr.symbol.owner;
+ val superParamAccessors = superClazz.constrParamAccessors;
+ if (superParamAccessors.length != superArgs.length) {
+ System.out.println("" + superClazz + ":" + superClazz.info.decls.toList.filter(.hasFlag(PARAMACCESSOR)));
+ assert(false, "mismatch: " + superParamAccessors + ";" + rhs + ";" + superClazz.info.decls); //debug
+ }
+ List.map2(superParamAccessors, superArgs) { (superAcc, superArg) =>
+ superArg match {
+ case Ident(name) =>
+ if (vparamss.exists(.exists(vp => vp.symbol == superArg.symbol))) {
+ val alias = aliases.get(superAcc.initialize) match {
+ case Some(getter) =>
+ getter
+ case None =>
+ val getter = superAcc.getter;
+ if (getter != NoSymbol &&
+ superClazz.info.nonPrivateMember(getter.name) == getter) getter
+ else NoSymbol
+ }
+ if (alias != NoSymbol) {
+ var ownAcc = clazz.info.decl(name);
+ if (ownAcc hasFlag ACCESSOR) ownAcc = ownAcc.accessed;
+ assert(ownAcc hasFlag PARAMACCESSOR, clazz.toString() + " " + name);
+ System.out.println("" + ownAcc + " has alias " + alias + alias.locationString);//debug
+ aliases(ownAcc) = alias
+ }
+ }
+ case _ =>
+ }
+ }
+ ()
+ }
+ }
+
def typedDefDef(ddef: DefDef): DefDef = {
val meth = ddef.symbol;
reenterTypeParams(ddef.tparams);
@@ -526,10 +587,10 @@ abstract class Typers: Analyzer {
context.enclClass.owner.setFlag(INCONSTRUCTOR);
val result = typed(ddef.rhs, EXPRmode | INCONSTRmode, UnitClass.tpe);
context.enclClass.owner.resetFlag(INCONSTRUCTOR);
+ if (meth.isPrimaryConstructor && !phase.erasedTypes)
+ computeParamAliases(meth.owner, vparamss1, result);
result
- } else {
- typed(ddef.rhs, tpt1.tpe);
- }
+ } else transformedOrTyped(ddef.rhs, tpt1.tpe);
copy.DefDef(ddef, ddef.mods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
@@ -643,6 +704,7 @@ abstract class Typers: Analyzer {
setFlag FINAL setInfo MethodType(formals, body.tpe);
anonClass.info.decls enter applyMethod;
for (val vparam <- vparamSyms) vparam.owner = applyMethod;
+ new ChangeOwnerTraverser(context.owner, applyMethod).traverse(body);
var members = List(
DefDef(FINAL, nme.apply, List(), List(vparams), TypeTree(body.tpe), body)
setSymbol applyMethod);
@@ -657,16 +719,15 @@ abstract class Typers: Analyzer {
CaseDef(substParam(cdef.pat.duplicate),
substParam(cdef.guard.duplicate),
Literal(true));
- def isDefaultCase(cdef: CaseDef) = cdef match {
- case CaseDef(Ident(nme.WILDCARD), EmptyTree, _) => true
- case CaseDef(Bind(_, Ident(nme.WILDCARD)), EmptyTree, _) => true
- case _ => false
- }
- if (cases exists isDefaultCase) Literal(true)
- else Match(
- Ident(idparam),
- (cases map transformCase) :::
- List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))))
+ val result =
+ if (cases exists treeInfo.isDefaultCase) Literal(true)
+ else
+ Match(
+ Ident(idparam),
+ (cases map transformCase) :::
+ List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))));
+ new ChangeOwnerTraverser(applyMethod, isDefinedAtMethod).traverse(result);
+ result
}
members = DefDef(isDefinedAtMethod, vparamss => idbody(vparamss.head.head)) :: members;
}
@@ -1278,6 +1339,18 @@ abstract class Typers: Analyzer {
/** Types a type or type constructor tree */
def typedTypeConstructor(tree: Tree): Tree =
typed(tree, TYPEmode | FUNmode, WildcardType);
+
+ def computeType(tree: Tree): Type = {
+ val tree1 = typed(tree);
+ transformed(tree) = tree1;
+ tree1.tpe
+ }
+
+ def transformedOrTyped(tree: Tree, pt: Type): Tree = transformed.get(tree) match {
+ case Some(tree1) => transformed -= tree; tree1
+ case None => typed(tree, pt)
+ }
+
/*
def convertToTypeTree(tree: Tree): Tree = tree match {
case TypeTree() => tree
diff --git a/sources/scala/tools/nsc/util/HashSet.scala b/sources/scala/tools/nsc/util/HashSet.scala
index 0e26231d65..5751c49001 100755
--- a/sources/scala/tools/nsc/util/HashSet.scala
+++ b/sources/scala/tools/nsc/util/HashSet.scala
@@ -5,7 +5,7 @@
// $Id$
package scala.tools.nsc.util;
-class HashSet[T <: AnyRef](capacity: int) {
+class HashSet[T <: AnyRef](capacity: int) extends Set[T] {
private var size = capacity;
private var used = 0;
diff --git a/sources/scala/tools/nsc/util/Set.scala b/sources/scala/tools/nsc/util/Set.scala
new file mode 100755
index 0000000000..dab7898e39
--- /dev/null
+++ b/sources/scala/tools/nsc/util/Set.scala
@@ -0,0 +1,23 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id$
+package scala.tools.nsc.util;
+
+/** A common trait for lightweight sets.
+ */
+abstract class Set[T <: AnyRef] {
+
+ def findEntry(x: T): T;
+
+ def addEntry(x: T): unit;
+
+ def elements: Iterator[T];
+
+ def contains(x: T): boolean =
+ findEntry(x) != null;
+
+ def toList = elements.toList;
+
+}
diff --git a/sources/scala/tools/nsc/util/TreeSet.scala b/sources/scala/tools/nsc/util/TreeSet.scala
new file mode 100755
index 0000000000..552f06b3f4
--- /dev/null
+++ b/sources/scala/tools/nsc/util/TreeSet.scala
@@ -0,0 +1,52 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id$
+package scala.tools.nsc.util;
+
+/** Sets implemented as binary trees.
+ */
+class TreeSet[T <: AnyRef](less: (T, T) => boolean) extends Set[T] {
+
+ private class Tree(val elem: T) {
+ var l: Tree = null;
+ var r: Tree = null;
+ }
+
+ private var tree: Tree = null;
+
+ def findEntry(x: T): T = {
+ def find(t: Tree): T = {
+ if (t == null) null
+ else if (less(x, t.elem)) find(t.l)
+ else if (less(t.elem, x)) find(t.r)
+ else t.elem
+ }
+ find(tree)
+ }
+
+ def addEntry(x: T): unit = {
+ def add(t: Tree): Tree = {
+ if (t == null) new Tree(x)
+ else if (less(x, t.elem)) { t.l = add(t.l); t }
+ else if (less(t.elem, x)) { t.r = add(t.r); t }
+ else t
+ }
+ tree = add(tree)
+ }
+
+ def elements = {
+ def elems(t: Tree): Iterator[T] = {
+ var it = Iterator.single(t.elem);
+ if (t.l != null) it = elems(t.l) append it;
+ if (t.r != null) it = it append elems(t.r);
+ it
+ }
+ if (tree == null) Iterator.empty else elems(tree)
+ }
+
+ override def toString(): String = {
+ if (tree == null) "<empty>" else "(..." + tree.elem + "...)";
+ }
+}