summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-08-03 22:18:10 +0000
committerMartin Odersky <odersky@gmail.com>2005-08-03 22:18:10 +0000
commit2a5f62338c30ba6d06aa10c8fb809ce92462f96c (patch)
tree052924741ede17387be41de5e9ff0d13d0d59fd4 /sources
parente12958a079cbffcfdb8142ab668581664f671334 (diff)
downloadscala-2a5f62338c30ba6d06aa10c8fb809ce92462f96c.tar.gz
scala-2a5f62338c30ba6d06aa10c8fb809ce92462f96c.tar.bz2
scala-2a5f62338c30ba6d06aa10c8fb809ce92462f96c.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rw-r--r--sources/scala/Enumeration.scala2
-rwxr-xr-xsources/scala/tools/nsc/Global.scala35
-rwxr-xr-xsources/scala/tools/nsc/Main.scala3
-rw-r--r--sources/scala/tools/nsc/Phase.scala8
-rw-r--r--sources/scala/tools/nsc/SubComponent.scala12
-rwxr-xr-xsources/scala/tools/nsc/ast/TreeGen.scala19
-rw-r--r--sources/scala/tools/nsc/ast/TreeInfo.scala19
-rw-r--r--sources/scala/tools/nsc/ast/TreePrinters.scala23
-rw-r--r--sources/scala/tools/nsc/ast/Trees.scala112
-rw-r--r--sources/scala/tools/nsc/matching/PatternMatchers.scala6
-rw-r--r--sources/scala/tools/nsc/matching/TransMatcher.scala3
-rw-r--r--sources/scala/tools/nsc/symtab/Flags.scala26
-rwxr-xr-xsources/scala/tools/nsc/symtab/Names.scala4
-rwxr-xr-xsources/scala/tools/nsc/symtab/StdNames.scala3
-rwxr-xr-xsources/scala/tools/nsc/symtab/SymbolLoaders.scala15
-rwxr-xr-xsources/scala/tools/nsc/symtab/SymbolTable.scala1
-rwxr-xr-xsources/scala/tools/nsc/symtab/Symbols.scala42
-rwxr-xr-xsources/scala/tools/nsc/symtab/Types.scala46
-rwxr-xr-xsources/scala/tools/nsc/transform/AddInterfaces.scala243
-rwxr-xr-xsources/scala/tools/nsc/transform/Erasure.scala136
-rwxr-xr-xsources/scala/tools/nsc/transform/ExplicitOuter.scala366
-rw-r--r--sources/scala/tools/nsc/transform/Transform.scala6
-rwxr-xr-xsources/scala/tools/nsc/transform/UnCurry.scala4
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Infer.scala13
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Namers.scala9
-rwxr-xr-xsources/scala/tools/nsc/typechecker/RefChecks.scala17
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala36
-rwxr-xr-xsources/scala/tools/nsc/util/HashSet.scala56
-rw-r--r--sources/scala/xml/transform/BasicTransformer.scala4
29 files changed, 1053 insertions, 216 deletions
diff --git a/sources/scala/Enumeration.scala b/sources/scala/Enumeration.scala
index 8348e92ab7..4515a8c4bf 100644
--- a/sources/scala/Enumeration.scala
+++ b/sources/scala/Enumeration.scala
@@ -114,7 +114,7 @@ abstract class Enumeration(initial: Int, names: String*) {
trait Value extends Ordered[Value] {
def id: Int;
- def compareTo[S >: Value <% Ordered[S]](that: S): Int = that match {
+ override def compareTo[S >: Value <% Ordered[S]](that: S): Int = that match {
case that1: Value => id - that1.id
case _ => -(that compareTo this)
}
diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala
index 963421de06..2f6f1e6075 100755
--- a/sources/scala/tools/nsc/Global.scala
+++ b/sources/scala/tools/nsc/Global.scala
@@ -12,7 +12,7 @@ import scala.collection.mutable.{HashSet,HashMap}
import symtab._;
import symtab.classfile.{PickleBuffer, Pickler};
-import util._;
+import util.ListBuffer;
import ast._;
import ast.parser._;
import typechecker._;
@@ -132,6 +132,13 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
// Phases ------------------------------------------------------------
+ var globalPhase: Phase = NoPhase;
+
+ override def phase_=(p: Phase): unit = {
+ assert(p.id <= globalPhase.id + 1);
+ super.phase_=(p)
+ }
+
abstract class GlobalPhase(prev: Phase) extends Phase(prev) {
def run: unit = units foreach applyPhase;
def apply(unit: CompilationUnit): unit;
@@ -170,6 +177,11 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
object transMatcher extends TransMatcher {
val global: Global.this.type = Global.this;
}
+
+ object explicitOuter extends ExplicitOuter {
+ val global: Global.this.type = Global.this;
+ }
+
object erasure extends Erasure {
val global: Global.this.type = Global.this;
}
@@ -194,8 +206,10 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
uncurry,
tailCalls,
transMatcher,
+ explicitOuter,
erasure,
- sampleTransform);
+ if (settings.Xshowicode.value) genicode
+ else sampleTransform);
val parserPhase = syntaxAnalyzer.newPhase(NoPhase);
val firstPhase = parserPhase;
@@ -212,17 +226,20 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
}
}
- // temporary: icode is turned on explicitely
- if (settings.Xshowicode.value)
- p = genicode.newPhase(p);
-
val terminalPhase = new GlobalPhase(p) {
def name = "terminal";
def apply(unit: CompilationUnit): unit = {}
}
- val namerPhase = parserPhase.next;
- val typerPhase = namerPhase.next;
+ def phaseNamed(name: String): Phase = {
+ var p: Phase = firstPhase;
+ while (p.next != p && p.name != name) p = p.next;
+ if (p.name != name) NoPhase else p
+ }
+
+ val namerPhase = phaseNamed("namer");
+ val typerPhase = phaseNamed("typer");
+ val erasurePhase = phaseNamed("erasure");
val typer = new analyzer.Typer(analyzer.NoContext.make(EmptyTree, definitions.RootClass, new Scope())) {
override def typed(tree: Tree, mode: int, pt: Type): Tree = {
@@ -252,8 +269,6 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
/** A map from compiled top-level symbols to their picklers */
val symData = new HashMap[Symbol, PickleBuffer];
- var globalPhase: Phase = NoPhase;
-
def compileSources(sources: List[SourceFile]): unit = {
val startTime = System.currentTimeMillis();
unitbuf.clear;
diff --git a/sources/scala/tools/nsc/Main.scala b/sources/scala/tools/nsc/Main.scala
index c29f097bfe..a36e82d8c9 100755
--- a/sources/scala/tools/nsc/Main.scala
+++ b/sources/scala/tools/nsc/Main.scala
@@ -59,7 +59,8 @@ object Main {
else
compiler.compile(command.files);
} catch {
- case ex @ FatalError(msg) =>
+ case ex: FatalError => // todo: replace with ex @ FatalError(msg)
+ val msg = ex.msg;
if (command.settings.debug.value)
ex.printStackTrace();
reporter.error(null, "fatal error: " + msg);
diff --git a/sources/scala/tools/nsc/Phase.scala b/sources/scala/tools/nsc/Phase.scala
index 9fd2322845..536cd81390 100644
--- a/sources/scala/tools/nsc/Phase.scala
+++ b/sources/scala/tools/nsc/Phase.scala
@@ -5,9 +5,16 @@
// $Id$
package scala.tools.nsc;
+import symtab.Flags;
+
abstract class Phase(val prev: Phase) {
val id: int = if (prev == null) 0 else prev.id + 1;
+ def newFlags: long = 0l;
+ private var fmask: long =
+ if (prev == null) Flags.InitialFlags else prev.flagMask | newFlags;
+ def flagMask: long = fmask;
+
private var nx: Phase = this;
if (prev != null) prev.nx = this;
@@ -16,7 +23,6 @@ abstract class Phase(val prev: Phase) {
def name: String;
def description: String = name;
def erasedTypes: boolean = false;
-
def run: unit;
override def toString() = name;
diff --git a/sources/scala/tools/nsc/SubComponent.scala b/sources/scala/tools/nsc/SubComponent.scala
index 680c3cda77..556b6538ad 100644
--- a/sources/scala/tools/nsc/SubComponent.scala
+++ b/sources/scala/tools/nsc/SubComponent.scala
@@ -8,10 +8,22 @@ package scala.tools.nsc;
/** An nsc sub-component.
*/
abstract class SubComponent {
+
+ /** The global environment; overridden by instantiation in Global. */
val global: Global;
+
+ /** The name of the phase */
val phaseName: String;
+
+ /** New flags defined by the phase which are not valid before */
+ def phaseNewFlags: long = 0;
+
+ /** The phase factory */
def newPhase(prev: Phase): Phase;
+
+ /** A standard phase template */
abstract class StdPhase(prev: Phase) extends global.GlobalPhase(prev) {
def name = phaseName;
+ override def newFlags = phaseNewFlags;
}
}
diff --git a/sources/scala/tools/nsc/ast/TreeGen.scala b/sources/scala/tools/nsc/ast/TreeGen.scala
index eadb2fe5bc..4602059037 100755
--- a/sources/scala/tools/nsc/ast/TreeGen.scala
+++ b/sources/scala/tools/nsc/ast/TreeGen.scala
@@ -33,9 +33,15 @@ abstract class TreeGen {
}
case TypeRef(pre, sym, args) =>
assert(phase.erasedTypes);
- (if (sym.isModuleClass && !sym.isRoot)
- Select(mkQualifier(sym.owner.tpe), sym.sourceModule)
- else This(sym)) setType sym.tpe
+ if (sym.isModuleClass && !sym.isRoot) {
+ val qual = Select(mkQualifier(sym.owner.tpe), sym.sourceModule);
+ qual.tpe match {
+ case MethodType(List(), restpe) =>
+ Apply(qual, List()) setType restpe
+ case _ =>
+ qual
+ }
+ } else This(sym)
}
/** Builds a reference to given symbol with given stable prefix. */
@@ -65,19 +71,19 @@ abstract class TreeGen {
def mkStableRef(sym: Symbol): Tree = stabilize(mkRef(sym));
def This(sym: Symbol): Tree =
- global.This(sym.name) setSymbol sym setType atPhase(phase.next)(sym.thisType);
+ global.This(sym.name) setSymbol sym setType sym.thisType;
def Ident(sym: Symbol) = {
assert(sym.isTerm);
sym.setFlag(ACCESSED);
- global.Ident(sym.name) setSymbol sym setType atPhase(phase.next)(sym.tpe);
+ 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 atPhase(phase.next)(qual.tpe.memberType(sym));
+ if (qual.tpe != null) result setType qual.tpe.memberType(sym);
result
}
@@ -89,7 +95,6 @@ abstract class TreeGen {
definitions.Any_isInstanceOfErased
else
definitions.Any_isInstanceOf;
-
Apply(
TypeApply(
Select(value, sym),
diff --git a/sources/scala/tools/nsc/ast/TreeInfo.scala b/sources/scala/tools/nsc/ast/TreeInfo.scala
index 672a01377a..0b18c18b4e 100644
--- a/sources/scala/tools/nsc/ast/TreeInfo.scala
+++ b/sources/scala/tools/nsc/ast/TreeInfo.scala
@@ -34,6 +34,21 @@ abstract class TreeInfo {
case _ => false
}
+ /** Is tree legal as a member definition of an interface?
+ */
+ def isInterfaceMember(tree: Tree): boolean = tree match {
+ case EmptyTree => true
+ case Import(_, _) => true
+ case AbsTypeDef(_, _, _, _) => true
+ case AliasTypeDef(_, _, _, _) => true
+ case DefDef(mods, _, _, _, _, __) => (mods & DEFERRED) != 0
+ case ValDef(mods, _, _, _) => (mods & DEFERRED) != 0
+ case DocDef(_, definition) => isInterfaceMember(definition)
+ case Attributed(_, definition) => isInterfaceMember(definition)
+ case _ => false
+ }
+
+
/** Is tree a pure definition?
*/
def isPureDef(tree: Tree): boolean = tree match {
@@ -43,12 +58,14 @@ abstract class TreeInfo {
| AbsTypeDef(_, _, _, _)
| AliasTypeDef(_, _, _, _)
| Import(_, _)
- | DefDef(_, nme.CONSTRUCTOR, _, _, _, _) =>
+ | DefDef(_, _, _, _, _, _) =>
true
case ValDef(mods, _, _, rhs) =>
(mods & MUTABLE) == 0 && isPureExpr(rhs)
case DocDef(_, definition) =>
isPureDef(definition)
+ case Attributed(_, definition) =>
+ isPureDef(definition)
case _ =>
false
}
diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala
index 3571d192e6..fbf017fdbc 100644
--- a/sources/scala/tools/nsc/ast/TreePrinters.scala
+++ b/sources/scala/tools/nsc/ast/TreePrinters.scala
@@ -79,7 +79,14 @@ abstract class TreePrinters {
def printOpt(prefix: String, tree: Tree): unit =
if (!tree.isEmpty) { print(prefix); print(tree) }
- def printModifiers(flags: int): unit = {
+ def printFlags(tree: Tree, flags: long): unit =
+ printModifiers(
+ if (tree.symbol == NoSymbol) flags
+ else if (settings.debug.value) tree.symbol.flags
+ else tree.symbol.flags & SourceFlags.asInstanceOf[long]);
+ //todo: check codegen so that we can remove this
+
+ def printModifiers(flags: long): unit = {
val mask = if (settings.debug.value) -1 else PrintableFlags;
val s = flagsToString(flags & mask);
if (s.length() != 0) print(s + " ")
@@ -94,7 +101,7 @@ abstract class TreePrinters {
print("<empty>");
case ClassDef(mods, name, tparams, tp, impl) =>
- printModifiers(mods); print("class " + symName(tree, name));
+ printFlags(tree, mods); print("class " + symName(tree, name));
printTypeParams(tparams);
printOpt(": ", tp); print(" extends "); print(impl);
@@ -102,11 +109,11 @@ abstract class TreePrinters {
print("package "); print(packaged); printColumn(stats, " {", ";", "}")
case ModuleDef(mods, name, impl) =>
- printModifiers(mods); print("object " + symName(tree, name));
+ printFlags(tree, mods); print("object " + symName(tree, name));
print(" extends "); print(impl);
case ValDef(mods, name, tp, rhs) =>
- printModifiers(mods);
+ printFlags(tree, mods);
print(if ((mods & MUTABLE) != 0) "var " else "val ");
print(symName(tree, name));
printOpt(": ", tp);
@@ -116,16 +123,16 @@ abstract class TreePrinters {
}
case DefDef(mods, name, tparams, vparamss, tp, rhs) =>
- printModifiers(mods);
+ printFlags(tree, mods);
print("def " + symName(tree, name));
printTypeParams(tparams); vparamss foreach printValueParams;
printOpt(": ", tp); printOpt(" = ", rhs);
case AbsTypeDef(mods, name, lo, hi) =>
- printModifiers(mods); print("type "); printParam(tree);
+ printFlags(tree, mods); print("type "); printParam(tree);
case AliasTypeDef(mods, name, tparams, rhs) =>
- printModifiers(mods); print("type " + symName(tree, name));
+ printFlags(tree, mods); print("type " + symName(tree, name));
printTypeParams(tparams); printOpt(" = ", rhs);
case LabelDef(name, params, rhs) =>
@@ -265,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(_, _, _, _, _, 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 4577110125..ed680a8814 100644
--- a/sources/scala/tools/nsc/ast/Trees.scala
+++ b/sources/scala/tools/nsc/ast/Trees.scala
@@ -38,6 +38,8 @@ abstract class Trees: Global {
buffer.toString()
}
+ override def hashCode(): int = super.hashCode();
+
override def equals(that: Any): boolean = that match {
case t: Tree => this eq t
case _ => false
@@ -83,6 +85,17 @@ abstract class Trees: Global {
owner.newValueParameter(owner.pos, freshName()).setInfo(formal);
}
+ private def syntheticParams(owner: Symbol, mtp: Type): List[List[Symbol]] = mtp match {
+ case PolyType(_, restp) =>
+ syntheticParams(owner, restp)
+ case MethodType(formals, restp) =>
+ syntheticParams(owner, formals) :: syntheticParams(owner, restp)
+ case _ =>
+ List()
+ }
+
+// def nextPhase = if (phase.id > globalPhase.id) phase else phase.next;
+
// ----- tree node alternatives --------------------------------------
/** The empty tree */
@@ -105,13 +118,11 @@ abstract class Trees: Global {
def ClassDef(sym: Symbol, impl: Template): ClassDef =
posAssigner.atPos(sym.pos) {
- atPhase(phase.next) {
- ClassDef(flags2mods(sym.flags),
- sym.name,
- sym.typeParams map AbsTypeDef,
- TypeTree(sym.typeOfThis),
- impl) setSymbol sym
- }
+ ClassDef(flags2mods(sym.flags),
+ sym.name,
+ sym.typeParams map AbsTypeDef,
+ if (sym.thisSym == sym) EmptyTree else TypeTree(sym.typeOfThis),
+ impl) setSymbol sym
}
/** Construct class definition with given class symbol, value parameters, supercall arguments
@@ -130,9 +141,7 @@ abstract class Trees: Global {
def ModuleDef(sym: Symbol, impl: Template): ModuleDef =
posAssigner.atPos(sym.pos) {
- atPhase(phase.next) {
- ModuleDef(flags2mods(sym.flags), sym.name, impl)
- }
+ ModuleDef(flags2mods(sym.flags), sym.name, impl)
}
/** Value definition */
@@ -143,9 +152,7 @@ abstract class Trees: Global {
def ValDef(sym: Symbol, rhs: Tree): ValDef =
posAssigner.atPos(sym.pos) {
- atPhase(phase.next) {
- ValDef(flags2mods(sym.flags), sym.name, TypeTree(sym.tpe), rhs) setSymbol sym
- }
+ ValDef(flags2mods(sym.flags), sym.name, TypeTree(sym.tpe), rhs) setSymbol sym
}
def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree);
@@ -154,40 +161,33 @@ abstract class Trees: Global {
case class DefDef(mods: int, name: Name, tparams: List[AbsTypeDef],
vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree)
extends DefTree {
- assert(tpt.isType); assert(rhs.isTerm);
- }
+ assert(tpt.isType);
+ assert(rhs.isTerm);
+ }
- def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef =
+ def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef =
posAssigner.atPos(sym.pos) {
- atPhase(phase.next) {
- def mk(tparams: List[Symbol], vparamss: List[List[Symbol]], tpe: Type): DefDef = tpe match {
- case PolyType(tparams, restpe) =>
- mk(tparams, List(), restpe)
- case MethodType(formals, restpe) =>
- mk(tparams, vparamss ::: List(syntheticParams(sym, formals)), restpe)
- case _ =>
- DefDef(
- flags2mods(sym.flags),
- sym.name,
- tparams map AbsTypeDef,
- vparamss map (.map(ValDef)),
- TypeTree(tpe),
- rhs(vparamss)) setSymbol sym
- }
- mk(List(), List(), sym.tpe)
- }
+ DefDef(flags2mods(sym.flags),
+ sym.name,
+ sym.typeParams map AbsTypeDef,
+ vparamss,
+ TypeTree(sym.tpe.finalResultType),
+ rhs) setSymbol sym
}
+ def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef = {
+ val vparamss = syntheticParams(sym, sym.tpe);
+ DefDef(sym, vparamss map (.map(ValDef)), rhs(vparamss));
+ }
+
/** Abstract type or type parameter */
case class AbsTypeDef(mods: int, name: Name, lo: Tree, hi: Tree)
extends DefTree;
def AbsTypeDef(sym: Symbol): AbsTypeDef =
posAssigner.atPos(sym.pos) {
- atPhase(phase.next) {
- AbsTypeDef(flags2mods(sym.flags), sym.name,
- TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi))
- }
+ AbsTypeDef(flags2mods(sym.flags), sym.name,
+ TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi))
}
/** Type alias */
@@ -196,9 +196,7 @@ abstract class Trees: Global {
def AliasTypeDef(sym: Symbol, rhs: Tree): AliasTypeDef =
posAssigner.atPos(sym.pos) {
- atPhase(phase.next) {
- AliasTypeDef(flags2mods(sym.flags), sym.name, sym.typeParams map AbsTypeDef, rhs)
- }
+ AliasTypeDef(flags2mods(sym.flags), sym.name, sym.typeParams map AbsTypeDef, rhs)
}
/** Labelled expression - the symbols in the array (must be Idents!)
@@ -211,13 +209,13 @@ abstract class Trees: Global {
* jumps within a Block.
*/
case class LabelDef(name: Name, params: List[Ident], rhs: Tree)
- extends DefTree with TermTree;
+ extends DefTree with TermTree {
+ assert(rhs.isTerm);
+ }
def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef =
posAssigner.atPos(sym.pos) {
- atPhase(phase.next) {
- LabelDef(sym.name, params map Ident, rhs) setSymbol sym
- }
+ LabelDef(sym.name, params map Ident, rhs) setSymbol sym
}
/** Import clause */
@@ -811,7 +809,7 @@ abstract class Trees: Global {
tree
case PackageDef(name, stats) =>
atOwner(tree.symbol.moduleClass) {
- copy.PackageDef(tree, name, transformTrees(stats))
+ copy.PackageDef(tree, name, transformStats(stats, currentOwner))
}
case ClassDef(mods, name, tparams, tpt, impl) =>
atOwner(tree.symbol) {
@@ -911,7 +909,7 @@ abstract class Trees: Global {
def transformTemplate(tree: Template): Template =
transform(tree: Tree).asInstanceOf[Template];
def transformAbsTypeDefs(trees: List[AbsTypeDef]): List[AbsTypeDef] =
- List.mapConserve(trees)(tree=> transform(tree).asInstanceOf[AbsTypeDef]);
+ List.mapConserve(trees)(tree => transform(tree).asInstanceOf[AbsTypeDef]);
def transformValDefs(trees: List[ValDef]): List[ValDef] =
List.mapConserve(trees)(tree => transform(tree).asInstanceOf[ValDef]);
def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] =
@@ -937,14 +935,16 @@ abstract class Trees: Global {
class Traverser {
protected var currentOwner: Symbol = definitions.RootClass;
def traverse(tree: Tree): unit = tree match {
- case ClassDef(mods, name, tparams, tpt, impl) =>
- atOwner(tree.symbol.moduleClass) {
- traverseTrees(tparams); traverse(tpt); traverse(impl)
- }
+ case EmptyTree =>
+ ;
case PackageDef(name, stats) =>
atOwner(tree.symbol) {
traverseTrees(stats)
}
+ case ClassDef(mods, name, tparams, tpt, impl) =>
+ atOwner(tree.symbol.moduleClass) {
+ traverseTrees(tparams); traverse(tpt); traverse(impl)
+ }
case ModuleDef(mods, name, impl) =>
atOwner(tree.symbol.moduleClass) {
traverse(impl)
@@ -1011,8 +1011,18 @@ abstract class Trees: Global {
traverse(fun); traverseTrees(args)
case Apply(fun, args) =>
traverse(fun); traverseTrees(args)
+ case Super(_, _) =>
+ ;
+ case This(_) =>
+ ;
case Select(qualifier, selector) =>
traverse(qualifier)
+ case Ident(_) =>
+ ;
+ case Literal(_) =>
+ ;
+ case TypeTree() =>
+ ;
case SingletonTypeTree(ref) =>
traverse(ref)
case SelectFromTypeTree(qualifier, selector) =>
@@ -1021,8 +1031,6 @@ abstract class Trees: Global {
traverse(templ)
case AppliedTypeTree(tpt, args) =>
traverse(tpt); traverseTrees(args)
- case EmptyTree | Super(_, _) | This(_) | Ident(_) | Literal(_) | TypeTree() =>
- {}
}
def traverseTrees(trees: List[Tree]): unit =
diff --git a/sources/scala/tools/nsc/matching/PatternMatchers.scala b/sources/scala/tools/nsc/matching/PatternMatchers.scala
index 7d9c01ec8d..c3ae5d9c4a 100644
--- a/sources/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/sources/scala/tools/nsc/matching/PatternMatchers.scala
@@ -568,10 +568,10 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt
try {
funct(inner)
} catch {
- case Break(res1) =>
- res = res1;
+ case ex: Break =>
+ res = ex.res;
set = true;
- case Break2() =>
+ case ex: Break2 =>
}
if(set) return res;
case _ =>
diff --git a/sources/scala/tools/nsc/matching/TransMatcher.scala b/sources/scala/tools/nsc/matching/TransMatcher.scala
index 749213bc6c..c35d3a0baa 100644
--- a/sources/scala/tools/nsc/matching/TransMatcher.scala
+++ b/sources/scala/tools/nsc/matching/TransMatcher.scala
@@ -237,7 +237,8 @@ with RightTracers {
}.construct( matcher, cases );
matcher.tree
*/
- scala.Predef.error("not yet implemented");
+ System.out.println("" + sel + " match " + ocases);
+ scala.Predef.error("regular expressions not yet implemented");
} else {
val pm = new PatternMatcher();
pm.initialize(sel, currentOwner, true );
diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala
index 14c5febb3d..a7a4d0bf1e 100644
--- a/sources/scala/tools/nsc/symtab/Flags.scala
+++ b/sources/scala/tools/nsc/symtab/Flags.scala
@@ -23,7 +23,7 @@ object Flags {
final val DEFERRED = 0x00000100; // was `abstract' for members
final val METHOD = 0x00000200; // a def parameter
final val TRAIT = 0x00000400; // a trait
- final val MODULE = 0x00000800; // symbol is module or class implementing a module
+ final val INTERFACE = 0x00000800; // symbol is an interface
final val MUTABLE = 0x00001000; // symbol is a mutable variable.
final val PARAM = 0x00002000; // symbol is a (value or type) parameter to a method
@@ -43,7 +43,7 @@ object Flags {
final val STATIC = 0x00800000; // static field, method or class
final val ACCESSED = 0x01000000; // symbol was accessed at least once
- final val SELECTOR = 0x02000000; // symbol was used as selector in Select
+ 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
@@ -55,19 +55,30 @@ object Flags {
final val LABEL = 0x40000000; // symbol is a label. Set by TailCall
final val CAPTURED = 0x80000000l; // variable is accessed from nested function. Set by LambdaLift
- final val INTERFACE = 0x100000000l; // symbol is an interface
- final val IS_ERROR = 0x200000000l; // symbol is an error symbol
- final val OVERLOADED = 0x400000000l; // symbol is overloaded
+ final val IS_ERROR = 0x100000000l; // symbol is an error symbol
+ final val OVERLOADED = 0x200000000l; // symbol is overloaded
- final val TRANS_FLAG = 0x800000000l; // transient flag guaranteed to be reset after each phase.
+ 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 INITIALIZED = 0x1000000000l; // symbol's definition is complete
final val LOCKED = 0x2000000000l; // temporary flag to catch cyclic dependencies
+ final val InitialFlags = 0x000000FFFFFFFFFFl; // flags that are enabled from phase 1.
+ final val LateFlags = 0x000FFF0000000000l; // flags that override flags in 0xFFF.
+ final val AntiFlags = 0x7FF0000000000000l; // flags that cancel flags in 0x7FF
+ final val LateShift = 40l;
+ final val AntiShift = 52l;
+
+ // late flags (set by a transformer phase)
+ final val lateDEFERRED = (DEFERRED: long) << LateShift;
+ final val lateINTERFACE = (INTERFACE: long) << LateShift;
+ final val notPRIVATE = (PRIVATE: long) << AntiShift;
+ final val notPROTECTED = (PROTECTED: long) << AntiShift;
+
// masks
- final val SourceFlags = 0x001FFFFF; // these modifiers can be set in source programs.
+ final val SourceFlags = 0x002FFFFF; // these modifiers can be set in source programs.
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.
@@ -132,7 +143,6 @@ object Flags {
case STATIC => "<static>"
case ACCESSED => "<accessed>"
- case SELECTOR => "<selector>"
case ACCESSOR => "<accessor>"
case ACCESS_METHOD => "<access>"
diff --git a/sources/scala/tools/nsc/symtab/Names.scala b/sources/scala/tools/nsc/symtab/Names.scala
index db919b182a..180c23a1d9 100755
--- a/sources/scala/tools/nsc/symtab/Names.scala
+++ b/sources/scala/tools/nsc/symtab/Names.scala
@@ -218,8 +218,8 @@ class Names {
final def endsWith(suffix: Name, end: int): boolean = {
var i = 1;
while (i <= suffix.length && i <= end && chrs(index + end - i) == chrs(suffix.start + suffix.length - i))
- i = i - 1;
- i == suffix.length
+ i = i + 1;
+ i > suffix.length
}
/** the subname with characters from start to end-1
diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala
index 154a0584f3..0cdc909380 100755
--- a/sources/scala/tools/nsc/symtab/StdNames.scala
+++ b/sources/scala/tools/nsc/symtab/StdNames.scala
@@ -31,6 +31,7 @@ abstract class StdNames: SymbolTable {
val NEWkw = newTermName("new");
val NULLkw = newTermName("null");
val OBJECTkw = newTermName("object");
+ val OUTER = "$outer";
val OVERRIDEkw = newTermName("override");
val PACKAGEkw = newTermName("package");
val PRIVATEkw = newTermName("private");
@@ -89,6 +90,7 @@ abstract class StdNames: SymbolTable {
val COMPOUND_NAME = newTermName("<ct>");
val ANON_CLASS_NAME = newTermName("$anon");
val ANONFUN_CLASS_NAME = newTermName("$anonfun");
+ val IMPL_CLASS_SUFFIX = newTermName("$class");
val REFINE_CLASS_NAME = newTermName("<refinement>");
val EMPTY_PACKAGE_NAME = newTermName("<empty>");
val IMPORT = newTermName("<import>");
@@ -99,6 +101,7 @@ abstract class StdNames: SymbolTable {
val BYNAME_PARAM_CLASS_NAME = newTermName("<byname>");
val CONSTRUCTOR = newTermName("<init>");
+ val MIXIN_CONSTRUCTOR = newTermName("$init$");
val INITIALIZER = newTermName("<init>");
val INLINED_INITIALIZER = newTermName("$init$");
diff --git a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
index 3229024b2f..46e9ff6b42 100755
--- a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -78,6 +78,10 @@ abstract class SymbolLoaders {
assert(root.isPackageClass, root);
root.setInfo(new PackageClassInfoType(new Scope(), root));
+ /** 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;
+
def enterPackage(str: String, completer: SymbolLoader): unit = {
val pkg = root.newPackage(Position.NOPOS, newTermName(str));
pkg.moduleClass.setInfo(completer);
@@ -110,14 +114,17 @@ abstract class SymbolLoaders {
if (filename != "META_INF" && !packages.isDefinedAt(filename)) packages(filename) = file;
} else if (filename.endsWith(".symbl")) {
val name = filename.substring(0, filename.length() - 6);
- if (!classes.isDefinedAt(name) ||
- classes(name).getName().endsWith(".class")) classes(name) = file;
+ if (isValid(name) &&
+ (!classes.isDefinedAt(name) || classes(name).getName().endsWith(".class")))
+ classes(name) = file;
} else if (filename.endsWith(".class")) {
val name = filename.substring(0, filename.length() - 6);
- if (!classes.isDefinedAt(name)) classes(name) = file;
+ if (isValid(name) && !classes.isDefinedAt(name))
+ classes(name) = file;
} else if (filename.endsWith(".scala")) {
val name = filename.substring(0, filename.length() - 6);
- if (!sources.isDefinedAt(name)) sources(name) = file;
+ if (isValid(name) && !sources.isDefinedAt(name))
+ sources(name) = file;
}
}
for (val Pair(name, sfile) <- sources.elements) {
diff --git a/sources/scala/tools/nsc/symtab/SymbolTable.scala b/sources/scala/tools/nsc/symtab/SymbolTable.scala
index afcebe2f7e..a7c0a61328 100755
--- a/sources/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/sources/scala/tools/nsc/symtab/SymbolTable.scala
@@ -19,7 +19,6 @@ abstract class SymbolTable extends Names
def rootLoader: LazyType;
def log(msg: Object): unit;
- private var CNT = 0;
private var ph: Phase = NoPhase;
def phase: Phase = ph;
def phase_=(p: Phase): unit = {
diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala
index e6f09c8888..44340e8b1b 100755
--- a/sources/scala/tools/nsc/symtab/Symbols.scala
+++ b/sources/scala/tools/nsc/symtab/Symbols.scala
@@ -24,6 +24,8 @@ abstract class Symbols: SymbolTable {
val id = { ids = ids + 1; ids }
private var rawflags: long = 0;
+ def setPos(pos: int): this.type = { this.pos = pos; this }
+
// Creators -------------------------------------------------------------------
final def newValue(pos: int, name: Name) =
@@ -100,7 +102,8 @@ 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 isConstructor = isTerm && (name == nme.CONSTRUCTOR);
+ final def isMixinConstructor = isTerm && (name == nme.MIXIN_CONSTRUCTOR);
final def isModule = isTerm && hasFlag(MODULE);
final def isPackage = isModule && hasFlag(PACKAGE);
final def isThisSym = isTerm && name == nme.this_;
@@ -183,12 +186,15 @@ abstract class Symbols: SymbolTable {
// Flags ----------------------------------------------------------------------------
- final def flags = rawflags;
+ final def flags = {
+ val fs = rawflags & phase.flagMask;
+ (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift)
+ }
final def flags_=(fs: long) = rawflags = fs;
final def setFlag(mask: long): this.type = { rawflags = rawflags | mask; this }
final def resetFlag(mask: long): this.type = { rawflags = rawflags & ~mask; this }
- final def getFlag(mask: long): long = rawflags & mask;
- final def hasFlag(mask: long): boolean = (rawflags & mask) != 0;
+ final def getFlag(mask: long): long = flags & mask;
+ final def hasFlag(mask: long): boolean = (flags & mask) != 0;
final def resetFlags: unit = { rawflags = rawflags & SourceFlags }
// Info and Type -------------------------------------------------------------------
@@ -217,12 +223,14 @@ abstract class Symbols: SymbolTable {
}
rawflags = rawflags | LOCKED;
val current = phase;
- phase = infos.start;
- tp.complete(this);
- // if (settings.debug.value && (rawflags & INITIALIZED) != 0) System.out.println("completed " + this/* + ":" + info*/);//DEBUG
-
- rawflags = rawflags & ~LOCKED;
- phase = current;
+ try {
+ phase = infos.start;
+ tp.complete(this);
+ // if (settings.debug.value && (rawflags & INITIALIZED) != 0) System.out.println("completed " + this/* + ":" + info*/);//DEBUG
+ rawflags = rawflags & ~LOCKED
+ } finally {
+ phase = current
+ }
cnt = cnt + 1;
// allow for two completions:
// one: sourceCompleter to LazyType, two: LazyType to completed type
@@ -233,7 +241,6 @@ abstract class Symbols: SymbolTable {
/** Set initial info. */
def setInfo(info: Type): this.type = {
- if (name == newTypeName("Array") && info.isInstanceOf[PolyType]) assert(info.typeParams.length == 1, info);
if (limit == NoPhase) {
assert(phase != NoPhase);
infos = new TypeHistory(phase, info, null);
@@ -285,7 +292,7 @@ abstract class Symbols: SymbolTable {
}
/** Initialize the symbol */
- final def initialize: Symbol = {
+ final def initialize: this.type = {
if ((rawflags & INITIALIZED) == 0) info;
this
}
@@ -404,6 +411,9 @@ abstract class Symbols: SymbolTable {
/** 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);
+
/** The self symbol of a class with explicit self type, or else the symbol itself.
*/
def thisSym: Symbol = this;
@@ -605,6 +615,8 @@ abstract class Symbols: SymbolTable {
}
}
+ def infosString = infos.toString();
+
/** String representation of symbol's variance */
private def varianceString: String =
if (variance == 1) "+"
@@ -702,8 +714,8 @@ abstract class Symbols: SymbolTable {
thisTypePhase = phase;
if (!isValid(p)) {
thisTypeCache =
- if (isModuleClass && !isRoot) {
- assert(sourceModule != NoSymbol);
+ if (isModuleClass && !isRoot && !phase.erasedTypes) {
+ assert(sourceModule != NoSymbol, "" + this + " " + phase);
singleType(owner.thisType, sourceModule);
} else ThisType(this);
}
@@ -765,5 +777,5 @@ abstract class Symbols: SymbolTable {
case class CyclicReference(sym: Symbol, info: Type) extends TypeError("illegal cyclic reference involving " + sym);
/** A class for type histories */
- private class TypeHistory(val start: Phase, val info: Type, val prev: TypeHistory);
+ private case class TypeHistory(start: Phase, info: Type, prev: TypeHistory);
}
diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala
index 212142866f..b488685727 100755
--- a/sources/scala/tools/nsc/symtab/Types.scala
+++ b/sources/scala/tools/nsc/symtab/Types.scala
@@ -156,7 +156,8 @@ abstract class Types: SymbolTable {
* and instantiate all parameters by arguments of `pre'.
* Proceed analogously for thistypes referring to outer classes. */
def asSeenFrom(pre: Type, clazz: Symbol): Type =
- new AsSeenFromMap(pre, clazz) apply this;
+ if (!phase.erasedTypes || pre.symbol == ArrayClass) new AsSeenFromMap(pre, clazz) apply this;
+ else this;
/** The info of `sym', seen as a member of this type. */
def memberInfo(sym: Symbol): Type =
@@ -473,6 +474,7 @@ abstract class Types: SymbolTable {
abstract case class SuperType(thistpe: Type, supertp: Type) extends SingletonType {
override def symbol = thistpe.symbol;
override def singleDeref = supertp;
+ override def prefix: Type = supertp.prefix;
override def prefixString =
if (thistpe.prefixString.endsWith("this."))
thistpe.prefixString.substring(0, thistpe.prefixString.length() - 5) + "super."
@@ -803,7 +805,7 @@ abstract class Types: SymbolTable {
/** The canonical creator for single-types */
def singleType(pre: Type, sym: Symbol): Type = {
if (phase.erasedTypes)
- sym.tpe
+ sym.tpe.resultType
else if (checkMalformedSwitch && !pre.isStable && !pre.isError)
throw new MalformedType(pre, sym.name.toString())
else
@@ -896,7 +898,7 @@ abstract class Types: SymbolTable {
var uniques = 0;
var accesses = 0;
- var collisions = 0;
+ var collisions = 0; //todo: use HashSet!
/* statistics
var uniqueThis = 0;
@@ -1006,6 +1008,17 @@ abstract class Types: SymbolTable {
trait TypeMap extends Function1[Type, Type] {
// deferred inherited: def apply(tp: Type): Type
+ private def cloneDecls(result: Type, tp: Type, decls: Scope): Type = {
+ val syms1 = decls.toList;
+ for (val sym <- syms1)
+ result.decls.enter(sym.cloneSymbol(result.symbol));
+ val syms2 = result.decls.toList;
+ val resultThis = result.symbol.thisType;
+ for (val sym <- syms2)
+ sym.setInfo(sym.info.substSym(syms1, syms2).substThis(tp.symbol, resultThis));
+ result
+ }
+
/** Map this function over given type */
def mapOver(tp: Type): Type = tp match {
case ErrorType | WildcardType | NoType | NoPrefix | ThisType(_) | ConstantType(_) =>
@@ -1032,21 +1045,16 @@ abstract class Types: SymbolTable {
val hi1 = this(hi);
if ((lo1 eq lo) && (hi1 eq hi)) tp
else TypeBounds(lo1, hi1)
- case RefinedType(parents, refinement) =>
+ case RefinedType(parents, decls) =>
val parents1 = List.mapConserve(parents)(this);
- val refinement1 = mapOver(refinement);
- if ((parents1 eq parents) && (refinement1 eq refinement)) tp
- else {
- val result = refinedType(parents1, tp.symbol.owner);
- val syms1 = refinement1.toList;
- for (val sym <- syms1)
- result.decls.enter(sym.cloneSymbol(result.symbol));
- val syms2 = result.decls.toList;
- val resultThis = ThisType(result.symbol);
- for (val sym <- syms2)
- sym.setInfo(sym.info.substSym(syms1, syms2).substThis(tp.symbol, resultThis));
- result
- }
+ 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);
@@ -1096,7 +1104,7 @@ abstract class Types: SymbolTable {
}
abstract class TypeTraverser extends TypeMap {
- def traverse(tp: Type): TypeTraverser;
+ def traverse(tp: Type): TypeTraverser; //todo: return unit instead?
def apply(tp: Type): Type = { traverse(tp); tp }
}
@@ -1265,7 +1273,6 @@ abstract class Types: SymbolTable {
case Pair(SingleType(pre1, sym1), SingleType(pre2, sym2))
if ((sym1 == sym2) && (pre1 =:= pre2)) =>
true
- /*
case Pair(SingleType(pre1, sym1), ThisType(sym2))
if (sym1.isModule &&
sym1.moduleClass == sym2 &&
@@ -1276,7 +1283,6 @@ abstract class Types: SymbolTable {
sym2.moduleClass == sym1 &&
pre2 =:= sym1.owner.thisType) =>
true
- */
case Pair(ConstantType(value1), ConstantType(value2)) =>
value1 == value2
case Pair(TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
diff --git a/sources/scala/tools/nsc/transform/AddInterfaces.scala b/sources/scala/tools/nsc/transform/AddInterfaces.scala
new file mode 100755
index 0000000000..61c7c307c0
--- /dev/null
+++ b/sources/scala/tools/nsc/transform/AddInterfaces.scala
@@ -0,0 +1,243 @@
+/* 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 AddInterfaces extends InfoTransform {
+ import global._; // the global environment
+ import definitions._; // standard classes and methods
+ import posAssigner.atPos; // for filling in tree positions
+
+ override def phaseNewFlags: long = lateDEFERRED | lateINTERFACE;
+
+// Type transformation
+
+ def erasedTypeRef(sym: Symbol): Type;
+
+ private val implClassMap = new HashMap[Symbol, Symbol];
+ private val implMethodMap = new HashMap[Symbol, Symbol];
+
+ 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);
+
+ private def needsImplMethod(sym: Symbol): boolean =
+ sym.isMethod && isInterfaceMember(sym) &&
+ (!(sym hasFlag DEFERRED) || (sym hasFlag lateDEFERRED));
+
+ private def isInterfaceMember(sym: Symbol): boolean =
+ sym.isType ||
+ sym.isMethod && !(sym hasFlag (PRIVATE | BRIDGE | LABEL)) && !sym.isMixinConstructor;
+
+ private def implClass(iface: Symbol): Symbol = implClassMap.get(iface) match {
+ case Some(c) => c
+ case None =>
+ atPhase(erasurePhase) {
+ val impl = iface.cloneSymbolImpl(iface.owner)
+ setFlag (iface.flags & ~(INTERFACE | lateINTERFACE))
+ setInfo new LazyImplClassType(iface);
+ impl.name = implClassName(iface);
+ //impl.typeOfThis = iface.tpe;
+ implClassMap(iface) = impl;
+ if (settings.debug.value) log("generating impl class " + impl);
+ impl
+ }
+ }
+
+ private class LazyImplClassType(iface: Symbol) extends LazyType {
+
+ def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = {
+ val decls = new Scope();
+ 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;
+ sym setFlag lateDEFERRED
+ }
+ } else {
+ sym.owner = implClass;
+ decls enter sym;
+ }
+ }
+ decls
+ }
+
+ override def complete(sym: Symbol): unit = {
+ def implType(tp: Type): Type = tp match {
+ case ClassInfoType(parents, decls, _) =>
+ ClassInfoType(traitToImplClass(parents) ::: List(iface.tpe), implDecls(sym, decls), sym)
+ case PolyType(tparams, restpe) =>
+ PolyType(tparams, implType(restpe))
+ }
+ sym.setInfo(atPhase(erasurePhase)(implType(iface.info)));
+ }
+
+ override def load(clazz: Symbol): unit = complete(clazz)
+ }
+
+ private def traitToImplClass(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) if (needsImplClass(sym)) =>
+ typeRef(pre, implClass(sym), args)
+ case _ =>
+ tp
+ }
+
+ private def traitToImplClass(parents: List[Type]): List[Type] =
+ parents.head :: (parents.tail map traitToImplClass);
+
+ private def addImplClasses(decls: Scope): Scope = {
+ for (val sym <- decls.elements)
+ if (needsImplClass(sym)) decls enter implClass(sym);
+ decls
+ }
+
+ def transformTraitInfo(tp: Type): Type = tp match {
+ case ClassInfoType(parents, decls, clazz) =>
+ if (needsImplClass(clazz)) clazz setFlag lateINTERFACE;
+ var parents1 =
+ if (parents.isEmpty) List()
+ else {
+ assert(!parents.head.symbol.isTrait);
+ if (clazz hasFlag INTERFACE) erasedTypeRef(ObjectClass) :: parents.tail
+ else if (isImplClass(clazz)) parents
+ else traitToImplClass(parents)
+ }
+ val decls1 = addImplClasses(
+ if (clazz hasFlag INTERFACE) new Scope(decls.toList filter isInterfaceMember)
+ else new Scope(decls));
+ ClassInfoType(parents1, decls1, clazz)
+ case _ =>
+ tp
+ }
+
+// 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 def ifaceMemberDef(tree: Tree): Tree =
+ if (!tree.isDef || !isInterfaceMember(tree.symbol)) EmptyTree
+ else if (needsImplMethod(tree.symbol)) DefDef(tree.symbol, vparamss => EmptyTree)
+ else tree;
+
+ private def ifaceTemplate(templ: Template): Template =
+ copy.Template(templ, templ.parents, templ.body map ifaceMemberDef);
+
+ private def implMethodDef(tree: Tree, ifaceMethod: Symbol): Tree =
+ implMethodMap.get(ifaceMethod) match {
+ case Some(implMethod) =>
+ tree.symbol = implMethod;
+ changeOwner(ifaceMethod, implMethod).traverse(tree);
+ tree
+ case None =>
+ throw new Error("implMethod missing for " + ifaceMethod + " " + ifaceMethod.isExternal)
+ }
+
+ private def implMemberDef(tree: Tree): Tree =
+ if (!tree.isDef || !isInterfaceMember(tree.symbol)) tree
+ else if (needsImplMethod(tree.symbol)) implMethodDef(tree, tree.symbol)
+ else EmptyTree;
+
+ private def implTemplate(clazz: Symbol, templ: Template): Template = atPos(templ.pos){
+ val templ1 = Template(templ.parents, templ.body map implMemberDef)
+ setSymbol clazz.newLocalDummy(templ.pos);
+ changeOwner(templ.symbol.owner, clazz).traverse(templ1);
+ changeOwner(templ.symbol, templ1.symbol).traverse(templ1);
+ templ1
+ }
+
+ def implClassDefs(trees: List[Tree]): List[Tree] = {
+ val buf = new ListBuffer[Tree];
+ for (val tree <- trees)
+ tree match {
+ case ClassDef(_, _, _, _, impl) =>
+ if (needsImplClass(tree.symbol))
+ buf += {
+ val clazz = implClass(tree.symbol).initialize;
+ ClassDef(clazz, implTemplate(clazz, impl))
+ }
+ case _ =>
+ }
+ buf.toList
+ }
+
+ protected val traitTransformer = new Transformer {
+ override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
+ super.transformStats(stats ::: implClassDefs(stats), exprOwner) filter (EmptyTree !=);
+ override def transform(tree: Tree): Tree = {
+ val tree1 = tree match {
+ case ClassDef(mods, name, tparams, tpt, impl) =>
+ if (needsImplClass(tree.symbol)) {
+ implClass(tree.symbol).initialize; // to force lateDEFERRED flags
+ copy.ClassDef(tree, mods | INTERFACE, name, tparams, tpt, ifaceTemplate(impl))
+ }
+ else tree
+ case Template(parents, body) =>
+ copy.Template(tree, tree.symbol.owner.info.parents map TypeTree, body)
+ case This(_) =>
+ if (needsImplClass(tree.symbol)) This(implClass(tree.symbol)) else tree
+ case Super(qual, mix) =>
+ val mix1 =
+ if (mix == nme.EMPTY.toTypeName) mix
+ else {
+ val ps = atPhase(erasurePhase) {
+ tree.symbol.info.parents dropWhile (p => p.symbol.name != mix)
+ }
+ assert(!ps.isEmpty, tree);
+ if (needsImplClass(ps.head.symbol)) implClass(ps.head.symbol).name
+ else mix
+ }
+ if (needsImplClass(tree.symbol)) Super(implClass(tree.symbol), mix1)
+ else copy.Super(tree, qual, mix1)
+ case _ =>
+ tree
+ }
+ super.transform(tree1)
+ }
+ }
+}
+/*
+ val ensureNoEscapes = new TypeTraverser {
+ def ensureNoEscape(sym: Symbol): unit = {
+ if (sym.hasFlag(PRIVATE)) {
+ var o = currentOwner;
+ while (o != NoSymbol && o != sym.owner && !o.isLocal && !o.hasFlag(PRIVATE))
+ o = o.owner;
+ if (o == sym.owner) makeNotPrivate(sym);
+ }
+ }
+ def traverse(t: Type): TypeTraverser = {
+ t match {
+ case TypeRef(qual, sym, args) =>
+ ensureNoEscape(sym);
+ mapOver(t);
+ case ClassInfoType(parents, decls, clazz) =>
+ parents foreach { p => traverse; () }
+ traverse(t.typeOfThis);
+ case _ =>
+ mapOver(t)
+ }
+ this
+ }
+ }
+
+*/
diff --git a/sources/scala/tools/nsc/transform/Erasure.scala b/sources/scala/tools/nsc/transform/Erasure.scala
index a04b8b31ea..5f64349469 100755
--- a/sources/scala/tools/nsc/transform/Erasure.scala
+++ b/sources/scala/tools/nsc/transform/Erasure.scala
@@ -11,7 +11,7 @@ import Flags._;
import scala.tools.util.Position;
import util.ListBuffer;
-abstract class Erasure extends InfoTransform with typechecker.Analyzer {
+abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
import global._; // the global environment
import definitions._; // standard classes and methods
import typer.{typed}; // methods to type trees
@@ -40,14 +40,12 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
* - For a polymorphic type, the erasure of its result type
* - For the class info type of java.lang.Object, the same type without any parents
* - For a class info type of a value class, the same type without any parents
- * - For any other class info type with parents Ps, the same type with parents |Ps}, but
+ * - For any other class info type with parents Ps, the same type with parents |Ps|, but
* with duplicate references of Object removed.
* - for all other types, the type itself (with any sub-components erased)
*/
private val erasure = new TypeMap {
def apply(tp: Type): Type = tp match {
- case ConstantType(value) =>
- tp
case st: SubType =>
apply(st.supertype)
case TypeRef(pre, sym, args) =>
@@ -81,9 +79,10 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
}
/** Type reference after erasure */
- private def erasedTypeRef(sym: Symbol): Type = typeRef(erasure(sym.owner.tpe), sym, List());
+ def erasedTypeRef(sym: Symbol): Type = typeRef(erasure(sym.owner.tpe), sym, List());
/** Remove duplicate references to class Object in a list of parent classes
+ * todo: needed?
*/
private def removeDoubleObject(tps: List[Type]): List[Type] = tps match {
case List() => List()
@@ -93,26 +92,35 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
}
/** The symbol's erased info. This is the type's erasure, except for the following symbols
- * - For $asInstanceOf : [T]T
- * - For $isInstanceOf : [T]scala#Boolean
- * - For class Array : [T]C where C is the erased classinfo of the Array class
- * - For the Array[T].<init>: {scala#Int)Array[T]
- * - For a type parameter : A type bounds type consisting of the erasures of its bounds.
+ * - For $asInstanceOf : [T]T
+ * - For $isInstanceOf : [T]scala#Boolean
+ * - For class Array : [T]C where C is the erased classinfo of the Array class
+ * - For Array[T].<init> : {scala#Int)Array[T]
+ * - For a type parameter : A type bounds type consisting of the erasures of its bounds.
*/
def transformInfo(sym: Symbol, tp: Type): Type =
if (sym == Object_asInstanceOf)
sym.info
else if (sym == Object_isInstanceOf || sym == ArrayClass)
PolyType(sym.info.typeParams, erasure(sym.info.resultType))
- else if (sym.name == nme.CONSTRUCTOR && sym.owner == ArrayClass)
- tp match {
- case MethodType(formals, TypeRef(pre, sym, args)) =>
- MethodType(formals map erasure, typeRef(erasure(pre), sym, args))
- }
else if (sym.isAbstractType)
- erasure.mapOver(tp)
- else
- erasure(tp);
+ TypeBounds(WildcardType, WildcardType)
+ else if (sym.isTerm && sym.owner == ArrayClass) {
+ if (sym.isConstructor)
+ tp match {
+ case MethodType(formals, TypeRef(pre, sym, args)) =>
+ MethodType(formals map erasure, typeRef(erasure(pre), sym, args))
+ }
+ else if (sym.name == nme.apply)
+ tp
+ else if (sym.name == nme.update)
+ tp match {
+ case MethodType(List(index, tvar), restpe) =>
+ MethodType(List(erasure(index), tvar), erasure(restpe))
+ }
+ else erasure(tp)
+ } else
+ transformTraitInfo(erasure(tp));
// -------- boxing/unboxing --------------------------------------------------------
@@ -127,7 +135,8 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
atPos(tree.pos) {
val sym = tree.tpe.symbol;
if (sym == UnitClass) {
- gen.mkRef(BoxedUnit_UNIT)
+ if (treeInfo.isPureExpr(tree)) gen.mkRef(BoxedUnit_UNIT)
+ 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)
@@ -172,7 +181,8 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
/** Cast `tree' to type `pt' */
private def cast(tree: Tree, pt: Type): Tree = {
- if (settings.debug.value) log("casting " + tree + " to " + pt);
+ 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())
@@ -198,7 +208,10 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
tree
else if (isUnboxedClass(tree.tpe.symbol) && !isUnboxedClass(pt.symbol))
adaptToType(box(tree), pt)
- else if (pt <:< tree.tpe)
+ else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.paramTypes.isEmpty) {
+ assert(tree.symbol.isStable);
+ adaptToType(Apply(tree, List()) setType tree.tpe.resultType, pt)
+ } else if (pt <:< tree.tpe)
cast(tree, pt)
else if (isUnboxedClass(pt.symbol) && !isUnboxedClass(tree.tpe.symbol))
adaptToType(unbox(tree, pt), pt)
@@ -206,6 +219,11 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
cast(tree, pt)
}
+ // todo: remove after removing ==, != from value classes
+ private def corresponds(sym: Symbol, anyMember: Symbol): boolean =
+ sym == anyMember ||
+ sym != NoSymbol && isValueClass(sym.owner) && sym.name == anyMember.name && sym.tpe == anyMember.tpe;
+
/** Replace member references as follows:
* - `x == y' for `==' in class Any becomes `x equals y' with `equals' in class Object
@@ -226,9 +244,9 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
*/
private def adaptMember(tree: Tree): Tree = tree match {
case Apply(sel @ Select(qual, name), args) =>
- if (sel.symbol == Any_==)
+ if (corresponds(sel.symbol, Any_==))
Apply(Select(qual, Object_equals), args)
- else if (sel.symbol == Any_!=)
+ else if (corresponds(sel.symbol, Any_!=))
Apply(Select(Apply(Select(qual, Object_equals), args), Boolean_not), List())
else qual match {
case New(tpt) =>
@@ -256,11 +274,18 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
tree.symbol != NoSymbol && isValueClass(tree.symbol.owner)) {
qual1 = unbox(qual1, tree.symbol.owner.tpe)
}
- if (tree.symbol != NoSymbol &&
- isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.symbol))
- tree.symbol = NoSymbol;
+ 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
}
@@ -269,8 +294,9 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
override protected def adapt(tree: Tree, mode: int, pt: Type): Tree = adaptToType(tree, pt);
/** A replacement for the standard typer's `typed1' method */
- override protected def typed1(tree: Tree, mode: int, pt: Type): Tree =
- super.typed1(adaptMember(tree), mode, pt);
+ override protected def typed1(tree: Tree, mode: int, pt: Type): Tree = {
+ super.typed1(adaptMember(tree), mode, pt)
+ }
}
/** The erasure transformer */
@@ -284,7 +310,7 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
* - A template inherits two members `m' with different types,
* but their erased types are the same.
*/
- private def checkNoDoubleDefs(root: Symbol): unit = atPhase(phase.next) {
+ 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));
@@ -298,16 +324,16 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
sym2 + ":" + tpe2 +
(if (sym2.owner == root) " at line " + Position.line(sym2.pos) else sym2.locationString) +
"\nhave same type" +
- (if (tpe1 =:= tpe2) "" else " after erasure: " + sym1.tpe))
+ (if (tpe1 =:= tpe2) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe)))
}
val decls = root.info.decls;
var e = decls.elems;
while (e != null) {
- if (e.sym.isTerm && !e.sym.isConstructor) {
+ if (e.sym.isTerm && !e.sym.isConstructor && !e.sym.isMixinConstructor) {
var e1 = decls.lookupNextEntry(e);
while (e1 != null) {
- if (e1.sym.info =:= e.sym.info) doubleDefError(e.sym, e1.sym);
+ if (atPhase(phase.next)(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym);
e1 = decls.lookupNextEntry(e1)
}
}
@@ -315,12 +341,19 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
}
for (val bc <- root.info.baseClasses.tail; val other <- bc.info.decls.toList) {
- if (other.isTerm && !other.isConstructor && !(other hasFlag PRIVATE)) {
+ if (other.isTerm &&
+ !other.isConstructor &&
+ !other.isMixinConstructor &&
+ !(other hasFlag (PRIVATE | BRIDGE))) {
for (val member <- root.info.nonPrivateMember(other.name).alternatives) {
- if (member != other && (member.tpe =:= other.tpe) &&
+ if (member != other &&
+ !(member hasFlag BRIDGE) &&
+ atPhase(phase.next)(member.tpe =:= other.tpe) &&
!atPhase(typerPhase.next)(
- root.tpe.memberType(member) =:= root.tpe.memberType(other)))
+ 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)
+ }
}
}
}
@@ -336,12 +369,12 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
* in the template.
*/
private def bridgeDefs(owner: Symbol): List[Tree] = {
- val site = owner.tpe;
+ val site = owner.thisType;
val bridgesScope = new Scope();
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) {
+ if (other.isMethod && !other.isConstructor && !other.isMixinConstructor) {
for (val member <- site.nonPrivateMember(other.name).alternatives) {
if (member != other &&
!(member hasFlag DEFERRED) &&
@@ -354,17 +387,20 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
while (e != null && !((e.sym.tpe =:= otpe) && (bridgeTarget(e.sym) == member)))
e = bridgesScope.lookupNextEntry(e);
if (e == null) {
- val bridge = other.cloneSymbol(owner).setInfo(otpe).setFlag(BRIDGE);
+ val bridge = other.cloneSymbolImpl(owner)
+ setPos(owner.pos) setFlag (member.flags | BRIDGE) setInfo otpe;
if (settings.debug.value)
log("generating bridge from " + other + ":" + otpe + other.locationString + " to " + member + ":" + erasure(member.tpe) + "=" + bridge + ":" + bridge.tpe);
bridgeTarget(bridge) = member;
bridgesScope enter bridge;
bridges =
- atPos(bridge.pos) {
- DefDef(bridge, vparamss =>
- ((Select(This(owner), bridgeTarget(bridge)): Tree) /: vparamss)
- ((fun, vparams) => Apply(fun, vparams map Ident)))
- } :: bridges;
+ atPhase(phase.next) {
+ atPos(bridge.pos) {
+ DefDef(bridge, vparamss =>
+ ((Select(This(owner), bridgeTarget(bridge)): Tree) /: vparamss)
+ ((fun, vparams) => Apply(fun, vparams map Ident)))
+ } :: bridges;
+ }
}
}
}
@@ -386,7 +422,6 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
* - Reset all other type attributes to `null, thus enforcing a retyping.
*/
private val preTransformer = new Transformer {
- def elimEmpty(trees: List[Tree]): List[Tree] = trees filter (EmptyTree !=);
override def transform(tree: Tree): Tree = {
val tree1 = tree match {
case ClassDef(mods, name, tparams, tpt, impl) =>
@@ -400,13 +435,10 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
case TypeApply(fun, args) if (fun.symbol.owner != AnyClass) =>
// leave type tests/type casts, remove all other type applications
fun
- case PackageDef(name, stats) =>
- copy.PackageDef(tree, name, elimEmpty(stats))
case Template(parents, body) =>
+ //System.out.println("checking no dble defs " + tree);//DEBUG
checkNoDoubleDefs(tree.symbol.owner);
- copy.Template(tree, parents, elimEmpty(body) ::: bridgeDefs(currentOwner))
- case Block(stats, expr) =>
- copy.Block(tree, elimEmpty(stats), expr)
+ copy.Template(tree, parents, body ::: bridgeDefs(currentOwner));
case _ =>
tree
}
@@ -428,7 +460,11 @@ abstract class Erasure extends InfoTransform with typechecker.Analyzer {
*/
override def transform(tree: Tree): Tree = {
val tree1 = preTransformer.transform(tree);
- atPhase(phase.next) { newTyper(startContext).typed(tree1) }
+ atPhase(phase.next) {
+ val tree2 = traitTransformer.transform(tree1);
+ if (settings.debug.value) log("tree after addinterfaces: \n" + tree2);
+ newTyper(startContext).typed(tree2)
+ }
}
}
}
diff --git a/sources/scala/tools/nsc/transform/ExplicitOuter.scala b/sources/scala/tools/nsc/transform/ExplicitOuter.scala
new file mode 100755
index 0000000000..f1ac3392e8
--- /dev/null
+++ b/sources/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -0,0 +1,366 @@
+/* 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 ExplicitOuter extends InfoTransform {
+ import global._;
+ import definitions._;
+ import posAssigner.atPos;
+
+ override def phaseNewFlags: long = notPRIVATE | notPROTECTED;
+
+ /** the following two members override abstract members in Transform */
+ val phaseName: String = "explicitouter";
+
+ final val needSuperAccessors = false;
+
+ protected def newTransformer(unit: CompilationUnit): Transformer =
+ new ExplicitOuterTransformer(unit);
+
+ /** The type transformation method:
+ * 1. Add an outer paramter to the formal parameters of a constructor or mixin constructor
+ * in a non-static class;
+ * 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 {
+ case MethodType(formals, restpe) =>
+ if ((sym.isConstructor || sym.isMixinConstructor) && !sym.owner.isStatic)
+ MethodType(formals ::: List(sym.owner.owner.enclClass.thisType), restpe)
+ else tp;
+ case ClassInfoType(parents, decls, clazz) =>
+ var decls1 = decls;
+ if (!(clazz hasFlag INTERFACE)) {
+ if (!clazz.isStatic) {
+ decls1 = new Scope(decls1.toList);
+ val outerType = clazz.owner.enclClass.thisType;
+ decls1 enter (clazz.newValue(clazz.pos, nme.LOCAL_NAME(nme.OUTER))
+ setFlag (LOCAL | PRIVATE | PARAMACCESSOR)
+ setInfo outerType);
+ decls1 enter (clazz.newMethod(clazz.pos, nme.OUTER)
+ setFlag (PRIVATE | PARAMACCESSOR | ACCESSOR | STABLE | FINAL)
+ setInfo MethodType(List(), outerType));
+ }
+ if (clazz.isTrait) {
+ decls1 = new Scope(decls1.toList);
+ decls1 enter makeMixinConstructor(clazz);
+ }
+ }
+ if (decls1 eq decls) tp else ClassInfoType(parents, decls1, clazz)
+ case PolyType(tparams, restp) =>
+ val restp1 = transformInfo(sym, restp);
+ if (restp eq restp1) tp else PolyType(tparams, restp1)
+ case _ =>
+ tp
+ }
+
+ private def makeMixinConstructor(clazz: Symbol): Symbol =
+ clazz.newMethod(clazz.pos, nme.MIXIN_CONSTRUCTOR) setInfo MethodType(List(), UnitClass.tpe);
+
+ class ExplicitOuterTransformer(unit: CompilationUnit) extends Transformer {
+
+ /** A map that takes triples consisting of
+ * - the class symbol that contains the accessor
+ * - the symbol accessed by the accessor
+ * - the mixin qualifier of the symbol
+ * to super accessor symbols.
+ * //todo: not clear whether we need to this for all super calls symbols, or just
+ * protected ones (or all calls to protected from inner classes)?
+ */
+ private val superAccessors = new HashMap[Triple[Symbol, Symbol, Name], Symbol];
+
+ /** Generate a superclass accessor symbol and enter in `superAccessors' unless one
+ * exists already.
+ */
+ def superAccessor(clazz: Symbol, accessed: Symbol, mix: Name): Symbol =
+ superAccessors.get(Triple(clazz, accessed, mix)) match {
+ case Some(accessor) =>
+ accessor
+ case None =>
+ val accessor = makeSuperAccessor(clazz, accessed, mix);
+ superAccessors(Triple(clazz, accessed, mix)) = accessor;
+ accessor
+ }
+
+ /** Generate a superclass acessor symbol named `NAME$super$MIX' in class `class'
+ * where NAME is the name of the accessed symbol `accessed'
+ * and MIX is the mixin qualifier of the super call `mix'.
+ * The method is initially `private'; will be widened later
+ */
+ def makeSuperAccessor(clazz: Symbol, accessed: Symbol, mix: Name): Symbol = {
+ assert(accessed.isMethod);
+ val accessorName = newTermName(
+ accessed.name.toString() + "$super" +
+ (if (mix == nme.EMPTY.toTypeName) "" else "$" + mix));
+ val accessor = clazz.newMethod(clazz.pos, accessorName)
+ setFlag PRIVATE
+ setInfo clazz.tpe.memberType(accessed);
+ clazz.info.decls enter accessor;
+ 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)
+ * 2. A mixin which is not also an interface gets a mixin constructor
+ * (@see mixinConstructorDef)
+ * 3. Constructor bodies are augmented by calls to supermixin constructors
+ * (@see addMixinConstructorCalls)
+ * 4. A constructor of a class with an outer link gets an outer parameter.
+ * 5. A reference C.this where C refers to an outer class is replaced by a selection
+ * this.$outer ... .$outer (@see outerPath)
+ * 6. A reference C.super.M where C refers to an outer class and M is a term member of C
+ * is replaced by a selection
+ * this.$outer ... .$outer.M$super
+ * where M$super is the super accessor symbol of M (@see superAccessor).
+ * 7. A call to a constructor Q.<init>(args) or Q.$init$(args) where Q != this and
+ * the constructor belongs to a non-static class is augmented by an outer argument.
+ * E.g. Q.<init>(args, OUTER) where OUTER is the qualifier corresponding to the
+ * singleton type Q.
+ * 8. A call to a constructor this.<init>(args) in a secondary constructor
+ * is augmented to this.<init>(args, OUTER) where OUTER is the last parameter
+ * of the secondary constructor.
+ */
+ private val firstTransformer = new Transformer {
+
+ 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 ;
+ * Here, C is the class enclosing the class `clazz' containing the two definitions.
+ */
+ def outerDefs(clazz: Symbol): List[Tree] = {
+ val outerVal = clazz.info.decl(nme.LOCAL_NAME(nme.OUTER));
+ val outerDef = clazz.info.decl(nme.OUTER);
+ List(
+ localTyper.typed {
+ atPos(clazz.pos) {
+ ValDef(outerVal, EmptyTree)
+ }
+ },
+ localTyper.typed {
+ atPos(clazz.pos) {
+ DefDef(outerDef, vparamss => Select(This(clazz), outerVal))
+ }
+ })
+ }
+
+ /** The mixin constructor definition
+ * def $init$(): Unit = ()
+ */
+ def mixinConstructorDef(clazz: Symbol): Tree = localTyper.typed {
+ DefDef(clazz.mixinConstructor, vparamss => Literal(()))
+ }
+
+ /** Add calls to supermixin constructors
+ * super[mix].$init$()
+ * to `tree'. `tree' which is assumed to be the body of a constructor of class `clazz'.
+ */
+ def addMixinConstructorCalls(tree: Tree, clazz: Symbol): Tree = {
+ def mixinConstructorCall(mixin: Symbol): Tree =
+ atPos(tree.pos) {
+ Apply(
+ localTyper.typedOperator {
+ Select(Super(clazz, mixin.name), mixin.mixinConstructor)
+ },
+ List()) setType UnitClass.tpe; // don't type this with typed(...),
+ // as constructor arguments might be missing
+ }
+ val mixinConstructorCalls =
+ for (val mixin <- clazz.info.parents.tail; !(mixin.symbol hasFlag INTERFACE)) yield
+ mixinConstructorCall(mixin.symbol);
+ tree match {
+ case Block(supercall :: stats, expr) =>
+ assert(supercall match {
+ case Apply(Select(Super(_, _), _), _) => true
+ case _ => false
+ });
+ copy.Block(tree, supercall :: mixinConstructorCalls ::: stats, expr);
+ case Block(_, _) =>
+ assert(false, tree); tree
+ case expr =>
+ Block(mixinConstructorCalls, expr) setType expr.tpe
+ }
+ }
+
+ /** 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)) {
+ if (!currentOwner.isStatic)
+ decls1 = decls1 ::: outerDefs(currentOwner); // (1)
+ if (currentOwner.isTrait)
+ decls1 = decls1 ::: List(mixinConstructorDef(currentOwner)) // (2)
+ }
+ localTyper = savedLocalTyper;
+ copy.Template(tree, parents, decls1);
+ case constrDef @ DefDef(mods, name, tparams, vparamss, tpt, rhs)
+ if (sym.isConstructor || sym.isMixinConstructor) =>
+ 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 rhs1 =
+ if (sym.isPrimaryConstructor || sym.isMixinConstructor)
+ addMixinConstructorCalls(rhs, sym.owner); // (3)
+ else rhs;
+ 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)
+ 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)
+ 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)
+ 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
+ }
+ }
+ }
+
+ /** The second step performs the following transformations:
+ * 1. Add definitions of superaccessors to the members of a class
+ * (@see makeSuperAccessorDefs)
+ * 2. Remove private modifiers from members M of mixins T that are accessed with a qualifier
+ * different from T.this. (@see makeNotPrivate)
+ * 3. Remove `private' modifier from class members M that are accessed from an inner class.
+ * 4. Remove `protected' modifier from class members M that are accessed
+ * without a super qualifier accessed from an inner class. (@see makeNotPrivate)
+ * 5. Remove `private' and `protected' modifiers from type symbols
+ */
+ private val secondTransformer = new Transformer {
+
+ /** Add a definition for each super accessor in `clazz':
+ * def NAME$super$MIX(args) = super[MIX].NAME(args)
+ */
+ def makeSuperAccessorDefs(clazz: Symbol, typer: analyzer.Typer): List[Tree] =
+ (for (val Pair(Triple(owner, accessed, mix), accessor) <- superAccessors.elements;
+ owner == clazz) yield
+ typer.typed {
+ atPos(clazz.pos) {
+ DefDef(accessor, vparamss =>
+ Apply(Select(Super(clazz, mix), accessed), vparamss.head map Ident))
+ }
+ }).toList;
+
+ /** Remove private modifier from symbol `sym's definition. If `sym' is a
+ * term symbol rename it by appending $$<fully-qualified-name-of-enclosing-class
+ * to avoid name clashes.
+ */
+ def makeNotPrivate(sym: Symbol): unit =
+ if (sym hasFlag PRIVATE) {
+ if (sym.isTerm)
+ sym.name = newTermName(
+ sym.name.toString() + "$$" + sym.owner.enclClass.fullNameString('$'));
+ sym setFlag notPRIVATE;
+ }
+
+ /** The second-step transformation method */
+ override def transform(tree: Tree): Tree = {
+ val sym = tree.symbol;
+ val tree1 = super.transform(tree);
+ tree1 match {
+ case Template(parents, stats) => // (1)
+ val accessors = makeSuperAccessorDefs(sym.owner, typer.atOwner(tree1, currentOwner));
+ if (accessors.isEmpty) tree1
+ else copy.Template(tree1, parents, stats ::: accessors)
+ case Select(qual, name) =>
+ if ((sym hasFlag PRIVATE) &&
+ ((sym.owner.isTrait && qual.tpe != sym.owner.thisType) || // (2)
+ currentOwner.enclClass != sym.owner)) // (3)
+ makeNotPrivate(sym)
+ else if ((sym hasFlag PROTECTED) &&
+ !(qual.isInstanceOf[Super] ||
+ (qual.tpe.widen.symbol isSubClass currentOwner.enclClass)))
+ sym setFlag notPROTECTED;
+ tree1
+ case _ =>
+ if (sym != null && sym.isType) {
+ if (sym hasFlag PRIVATE) sym setFlag notPRIVATE;
+ if (sym hasFlag PROTECTED) sym setFlag notPROTECTED;
+ }
+ tree1
+ }
+ }
+ }
+
+ /** The main transformation method:
+ * First, perform step 1 on whole tree of compilation unit.
+ * Then, perform step 2 on resulting tree
+ */
+ override def transform(tree: Tree) =
+ atPhase(phase.next) {
+ secondTransformer.transform(firstTransformer.transform(tree))
+ }
+ }
+}
+
+
diff --git a/sources/scala/tools/nsc/transform/Transform.scala b/sources/scala/tools/nsc/transform/Transform.scala
index 912800f0c3..0710e67641 100644
--- a/sources/scala/tools/nsc/transform/Transform.scala
+++ b/sources/scala/tools/nsc/transform/Transform.scala
@@ -9,8 +9,14 @@ package scala.tools.nsc.transform;
* A transform contains a compiler phase which applies a tree transformer.
*/
abstract class Transform extends SubComponent {
+
+ /** The transformer factory */
protected def newTransformer(unit: global.CompilationUnit): global.Transformer;
+
+ /** Create a new phase which applies transformer */
def newPhase(prev: scala.tools.nsc.Phase): StdPhase = new Phase(prev);
+
+ /** 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);
diff --git a/sources/scala/tools/nsc/transform/UnCurry.scala b/sources/scala/tools/nsc/transform/UnCurry.scala
index ac2d14b959..a97d27e38b 100755
--- a/sources/scala/tools/nsc/transform/UnCurry.scala
+++ b/sources/scala/tools/nsc/transform/UnCurry.scala
@@ -107,7 +107,7 @@ abstract class UnCurry extends InfoTransform {
List.map2(formals, args1) ((formal, arg) =>
if (formal.symbol != ByNameParamClass) arg
else if (isByNameRef(arg)) arg setType functionType(List(), arg.tpe)
- else typed(Function(List(), arg) setPos arg.pos))
+ else typer.atOwner(currentOwner).typed(Function(List(), arg) setPos arg.pos))
}
}
@@ -139,6 +139,8 @@ abstract class UnCurry extends InfoTransform {
tree
}
tree match {
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ copy.DefDef(tree, mods, name, tparams, List(List.flatten(vparamss)), tpt, rhs);
case Apply(Apply(fn, args), args1) =>
copy.Apply(tree, fn, args ::: args1)
case Ident(name) =>
diff --git a/sources/scala/tools/nsc/typechecker/Infer.scala b/sources/scala/tools/nsc/typechecker/Infer.scala
index b50da84cb8..fb40563938 100755
--- a/sources/scala/tools/nsc/typechecker/Infer.scala
+++ b/sources/scala/tools/nsc/typechecker/Infer.scala
@@ -31,13 +31,16 @@ abstract class Infer: Analyzer {
/** A fresh type varable with given type parameter as origin. */
def freshVar(tparam: Symbol): TypeVar = new TypeVar(tparam.tpe, new TypeConstraint);
- private class NoInstance(msg: String) extends RuntimeException(msg);
+ //todo: remove comments around following privates; right now they cause an IllegalAccess
+ // error when built with scalac
- private class DeferredNoInstance(getmsg: () => String) extends NoInstance("") {
+ /*private*/ class NoInstance(msg: String) extends RuntimeException(msg);
+
+ /*private*/ class DeferredNoInstance(getmsg: () => String) extends NoInstance("") {
override def getMessage(): String = getmsg()
}
- private object instantiateMap extends TypeMap {
+ /*private*/ object instantiateMap extends TypeMap {
def apply(t: Type): Type = instantiate(t)
}
@@ -209,6 +212,8 @@ abstract class Infer: Analyzer {
} else {
val sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super]));
if (sym1 == NoSymbol) {
+ if (settings.debug.value) System.out.println(context);
+ System.out.println(tree);
errorTree(tree, sym.toString() + " cannot be accessed in " + pre.widen)
} else {
var owntype = pre.memberType(sym1);
@@ -395,7 +400,7 @@ abstract class Infer: Analyzer {
* given two prototypes `strictPt', and `lenientPt'.
* `strictPt' is the first attempt prototype where type parameters
* are left unchanged. `lenientPt' is the fall-back prototype where type parameters
- * are replaced by `AnyType's. We try to instantiate first to `strictPt' and then,
+ * are replaced by `WildcardType's. We try to instantiate first to `strictPt' and then,
* if this fails, to `lenientPt'. If both attempts fail, an error is produced.
*/
def inferArgumentInstance(tree: Tree, undetparams: List[Symbol], strictPt: Type, lenientPt: Type): unit = {
diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala
index 2e1e5231ea..bb63df325d 100755
--- a/sources/scala/tools/nsc/typechecker/Namers.scala
+++ b/sources/scala/tools/nsc/typechecker/Namers.scala
@@ -128,20 +128,21 @@ trait Namers: Analyzer {
val namer = new Namer(
context.make(tree, tree.symbol.moduleClass, tree.symbol.info.decls));
namer.enterSyms(stats);
- case ClassDef(mods, name, tparams, _, _) =>
+ case ClassDef(mods, name, tparams, _, impl) =>
if ((mods & (CASE | ABSTRACT)) == CASE) { // enter case factory method.
tree.symbol = enterCaseFactorySymbol(
tree.pos, mods & AccessFlags | METHOD | CASE, name.toTermName)
setInfo innerNamer.caseFactoryCompleter(tree)
- }
- tree.symbol = enterClassSymbol(tree.pos, mods, name);
+ }
+ val mods1: int = if (impl.body forall treeInfo.isInterfaceMember) mods | INTERFACE else mods;
+ tree.symbol = enterClassSymbol(tree.pos, mods1, name);
finishWith(tparams)
case ModuleDef(mods, name, _) =>
tree.symbol = enterModuleSymbol(tree.pos, mods | MODULE | FINAL, name);
tree.symbol.moduleClass.setInfo(innerNamer.typeCompleter(tree));
finish
case ValDef(mods, name, tp, rhs) =>
- if (context.owner.isClass & (mods & PRIVATE) == 0) {
+ if (context.owner.isClass & (mods & LOCAL) == 0) {
val accmods = ACCESSOR | (if ((mods & MUTABLE) != 0) mods & ~MUTABLE
else mods | STABLE);
val getter = owner.newMethod(tree.pos, name)
diff --git a/sources/scala/tools/nsc/typechecker/RefChecks.scala b/sources/scala/tools/nsc/typechecker/RefChecks.scala
index 59801f9316..885da9c542 100755
--- a/sources/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/sources/scala/tools/nsc/typechecker/RefChecks.scala
@@ -439,13 +439,13 @@ abstract class RefChecks extends Transform {
if (clazz hasFlag CASE) {
ts += tagMethod;
if (clazz.isModuleClass) {
- ts += moduleToStringMethod;
+ if (!hasImplementation(nme.toString_)) ts += moduleToStringMethod;
if (clazz.isSubClass(SerializableClass)) {
// If you serialize a singleton and then deserialize it twice,
// you will have two instances of your singleton, unless you implement
// the readResolve() method (see http://www.javaworld.com/javaworld/
// jw-04-2003/jw-0425-designpatterns_p.html)
- ts += readResolveMethod;
+ if (!hasImplementation(nme.readResolve)) ts += readResolveMethod;
}
} else {
ts += caseElementMethod;
@@ -473,10 +473,11 @@ abstract class RefChecks extends Transform {
}
def transformStat(tree: Tree, index: int): List[Tree] = tree match {
- case ModuleDef(_, name, impl) =>
+ case ModuleDef(mods, name, impl) =>
val sym = tree.symbol;
- //val localTyper = typer.atOwner(currentOwner);
- val cdef = typed(ClassDef(sym.moduleClass, impl));
+ val localTyper = typer.atOwner(currentOwner);
+ val cdef = ClassDef(mods | MODULE, name, List(), EmptyTree, impl)
+ setSymbol sym.moduleClass setType NoType;
if (sym.isStatic) List(transform(cdef))
else {
val moduleType = sym.tpe;
@@ -487,12 +488,13 @@ abstract class RefChecks extends Transform {
mvar setFlag (PRIVATE | LOCAL | SYNTHETIC);
sym.owner.info.decls.enter(mvar);
}
- val vdef = typed(ValDef(mvar, if (sym.isLocal) Literal(Constant(null)) else EmptyTree));
+ val vdef = localTyper.typed(
+ 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 = typed(
+ val ddef = localTyper.typed(
DefDef(sym, vparamss =>
Block(
List(
@@ -591,7 +593,6 @@ abstract class RefChecks extends Transform {
result = toConstructor
else {
sym setFlag ACCESSED;
- if (!treeInfo.isSelf(qual, currentOwner.enclClass)) sym.flags = sym.flags | SELECTOR;
if (sym hasFlag DEFERRED) {
qual match {
case Super(qualifier, mixin) =>
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index 2aeef22c0c..55ee7c475c 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -3,6 +3,7 @@
* @author Martin Odersky
*/
// $Id$
+//todo: rewrite or disallow new T where T is a trait (currently: <init> not a member of T)
package scala.tools.nsc.typechecker;
import nsc.util.ListBuffer;
@@ -193,8 +194,8 @@ abstract class Typers: Analyzer {
} else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && !sym.isValue) { // (2)
errorTree(tree, sym.toString() + " is not a value");
} else if (sym.isStable && pre.isStable && tree.tpe.symbol != ByNameParamClass &&
- (pt.isStable || (mode & QUALmode) != 0 && !sym.isConstant ||
- sym.isModule && !sym.isMethod)) {
+ (pt.isStable || (mode & QUALmode) != 0 && !sym.isConstant ||
+ sym.isModule && !sym.isMethod)) {
tree.setType(singleType(pre, sym))
} else tree
}
@@ -403,17 +404,17 @@ abstract class Typers: Analyzer {
error(parent.pos, "" + psym + " is not a trait; cannot be used as mixin");
else if (psym.hasFlag(FINAL))
error(parent.pos, "illegal inheritance from final class");
- else if (psym.isSealed) {
+ else if (psym.isSealed && !phase.erasedTypes) {
// are we in same scope as base type definition?
val e = defscope.lookupEntry(psym.name);
if (!(e.sym == psym && e.owner == defscope)) {
// we are not within same statement sequence
var c = context;
while (c != NoContext && c.owner != psym) c = c.outer.enclClass;
- if (c == NoContext) error(parent.pos, "illegal inheritance from sealed class")
+ if (c == NoContext) error(parent.pos, "illegal inheritance from sealed " + psym)
}
}
- if (!(selfType <:< parent.tpe.typeOfThis)) {
+ if (!(selfType <:< parent.tpe.typeOfThis) && !phase.erasedTypes) {
System.out.println(context.owner);//debug
System.out.println(context.owner.thisSym);//debug
error(parent.pos, "illegal inheritance;\n self-type " +
@@ -449,14 +450,15 @@ abstract class Typers: Analyzer {
}
def addGetterSetter(stat: Tree): List[Tree] = stat match {
- case ValDef(mods, name, tpe, rhs) if (mods & PRIVATE) == 0 =>
+ case ValDef(mods, name, tpe, rhs) if (mods & LOCAL) == 0 =>
val vdef = copy.ValDef(stat, mods | PRIVATE | LOCAL, nme.LOCAL_NAME(name), tpe, rhs);
val getter: DefDef = {
val sym = vdef.symbol;
val getter = sym.owner.info.decl(name).suchThat(.hasFlag(ACCESSOR));
val result = atPos(vdef.pos)(
DefDef(getter, vparamss =>
- if ((mods & DEFERRED) != 0) EmptyTree else typed(gen.mkRef(sym), EXPRmode, sym.tpe)));
+ if ((mods & DEFERRED) != 0) EmptyTree
+ else typed(Select(This(sym.owner), sym), EXPRmode, sym.tpe)));
checkNoEscaping.privates(result.symbol, result.tpt);
result
}
@@ -466,7 +468,8 @@ abstract class Typers: Analyzer {
atPos(vdef.pos)(
DefDef(setter, vparamss =>
if ((mods & DEFERRED) != 0) EmptyTree
- else typed(Assign(gen.mkRef(getter.symbol), gen.mkRef(vparamss.head.head)))))
+ else typed(Assign(Select(This(sym.owner), getter.symbol),
+ Ident(vparamss.head.head)))))
}
val gs = if ((mods & MUTABLE) != 0) List(getter, setter) else List(getter);
if ((mods & DEFERRED) != 0) gs else vdef :: gs
@@ -632,6 +635,7 @@ abstract class Typers: Analyzer {
val body = typed(fun.body, respt);
val formals = vparamSyms map (.tpe);
val funtpe = typeRef(clazz.tpe.prefix, clazz, formals ::: List(body.tpe));
+ assert(context.owner != RootClass);//debug
val anonClass = context.owner.newAnonymousFunctionClass(fun.pos) setFlag (FINAL | SYNTHETIC);
anonClass setInfo ClassInfoType(
List(ObjectClass.tpe, funtpe, ScalaObjectClass.tpe), new Scope(), anonClass);
@@ -807,11 +811,17 @@ abstract class Typers: Analyzer {
def typedSelect(qual: Tree, name: Name): Tree = {
val sym =
if (tree.symbol != NoSymbol) {
- val alts = qual.tpe.member(name).alternatives;
- if (!(alts exists (alt =>
- alt == tree.symbol || alt.isTerm && (alt.tpe matches tree.symbol.tpe))))
- assert(false, "symbol " + tree.symbol + " not in " + alts + " of " + qual.tpe);
- tree.symbol;
+ if (phase.erasedTypes && qual.isInstanceOf[Super]) qual.tpe = tree.symbol.owner.tpe;
+ if (settings.debug.value) { // todo: replace by settings.check.value?
+ val alts = qual.tpe.member(tree.symbol.name).alternatives;
+ if (!(alts exists (alt =>
+ alt == tree.symbol || alt.isTerm && (alt.tpe matches tree.symbol.tpe))))
+ assert(false, "symbol " + tree.symbol + tree.symbol.locationString + " not in " + alts + " of " + qual.tpe +
+ "\n members = " + qual.tpe.members +
+ "\n type history = " + qual.tpe.symbol.infosString +
+ "\n phase = " + phase);
+ }
+ tree.symbol
} else {
qual.tpe.member(name)
}
diff --git a/sources/scala/tools/nsc/util/HashSet.scala b/sources/scala/tools/nsc/util/HashSet.scala
new file mode 100755
index 0000000000..0e26231d65
--- /dev/null
+++ b/sources/scala/tools/nsc/util/HashSet.scala
@@ -0,0 +1,56 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id$
+package scala.tools.nsc.util;
+
+class HashSet[T <: AnyRef](capacity: int) {
+
+ private var size = capacity;
+ private var used = 0;
+ private var table = new Array[Object](size);
+
+ def findEntry(x: T): T = {
+ var h = x.hashCode() % size;
+ var entry = table(h);
+ while (entry != null && entry != x) {
+ h = (h + 1) % size;
+ entry = table(h)
+ }
+ entry.asInstanceOf[T]
+ }
+
+ def addEntry(x: T): unit = {
+ if (used >= (size >> 2)) growTable;
+ used = used + 1;
+ var h = x.hashCode() % size;
+ while (table(h) != null) {
+ h = (h + 1) % size
+ }
+ table(h) = x
+ }
+
+ def elements = new Iterator[T] {
+ private var i = 0;
+ def hasNext: boolean = {
+ while (i < size && table(i) == null) i = i + 1;
+ i < size
+ }
+ def next: T =
+ if (hasNext) { i = i + 1; table(i - 1).asInstanceOf[T] }
+ else null
+ }
+
+ private def growTable: unit = {
+ val oldtable = table;
+ size = size * 2;
+ table = new Array[Object](size);
+ var i = 0;
+ while (i < oldtable.length) {
+ val entry = oldtable(i);
+ if (entry != null) addEntry(entry.asInstanceOf[T]);
+ i = i + 1
+ }
+ }
+}
diff --git a/sources/scala/xml/transform/BasicTransformer.scala b/sources/scala/xml/transform/BasicTransformer.scala
index 56bbc16201..a260f82105 100644
--- a/sources/scala/xml/transform/BasicTransformer.scala
+++ b/sources/scala/xml/transform/BasicTransformer.scala
@@ -61,7 +61,9 @@ trait BasicTransformer extends Function1[Node,Node] {
}
ns
} catch {
- case NeedsCopy(n2) =>
+ case n: NeedsCopy =>
+ // todo: replace with NeedsCopy(n2), once pattern matcher can handle try's
+ val n2 = n.result;
val nb = buffer(i, ns);
nb ++ n2;
transform(it, nb);