summaryrefslogtreecommitdiff
path: root/sources/scalac
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-05-19 11:12:09 +0000
committerMartin Odersky <odersky@gmail.com>2003-05-19 11:12:09 +0000
commitf7f15007686e355a2d8668bf890603be90810e29 (patch)
treebdb8a9a813fd1a8b32bc20b6988eafe16de4a2f8 /sources/scalac
parent2300aac76adab6945ca2d2e3cb15320621a76150 (diff)
downloadscala-f7f15007686e355a2d8668bf890603be90810e29.tar.gz
scala-f7f15007686e355a2d8668bf890603be90810e29.tar.bz2
scala-f7f15007686e355a2d8668bf890603be90810e29.zip
*** empty log message ***
Diffstat (limited to 'sources/scalac')
-rw-r--r--sources/scalac/symtab/Symbol.java3
-rw-r--r--sources/scalac/symtab/Type.java146
-rw-r--r--sources/scalac/transformer/LambdaLift.java7
-rw-r--r--sources/scalac/transformer/LambdaLiftPhase.java27
-rw-r--r--sources/scalac/typechecker/Analyzer.java76
5 files changed, 195 insertions, 64 deletions
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index 3bb3f76e87..a259e0d62f 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -748,7 +748,8 @@ public abstract class Symbol implements Modifiers, Kinds {
/** String representation of location.
*/
public String locationString() {
- if (owner.kind == CLASS && !owner.isAnonymousClass())
+ if (owner.kind == CLASS && !owner.isAnonymousClass() ||
+ Global.instance.debug)
return " in " + owner;
else
return "";
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index 110a0f80bc..15c3d47649 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -141,6 +141,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
public Type widen() {
return type().widen();
}
+
/** If this type is a singleton type whose type is another, the end of the chain,
* otherwise the type itself.
*/
@@ -235,6 +236,25 @@ public class Type implements Modifiers, Kinds, TypeTags {
return this;
}
+ /** The lower approximation of this type (which must be a typeref)
+ */
+ public Type loBound() {
+ switch (unalias()) {
+ case TypeRef(Type pre, Symbol sym, Type[] args):
+ Type lb = Global.instance.definitions.ANY_TYPE;
+ if (sym.kind == TYPE) {
+ lb = sym.loBound().asSeenFrom(pre, sym.owner());
+ }
+ if (lb.isSameAs(Global.instance.definitions.ANY_TYPE) &&
+ this.isSubType(Global.instance.definitions.ANYREF_TYPE)) {
+ lb = Global.instance.definitions.ANYREF_TYPE;
+ }
+ return lb;
+ default:
+ throw new ApplicationError();
+ }
+ }
+
/** The thistype or singleton type corresponding to values of this type.
*/
public Type narrow() {
@@ -1306,9 +1326,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
case TypeRef(_, Symbol sym, _):
switch (that) {
case TypeRef(Type pre1, Symbol sym1, _):
- if (sym1.kind == TYPE &&
- this.isSubType(
- sym1.loBound().asSeenFrom(pre1, sym1.owner())))
+ if (sym1.kind == TYPE && this.isSubType(that.loBound()))
return true;
}
if (sym.kind == ALIAS)
@@ -1826,7 +1844,6 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
/** Return the least upper bound of non-empty array of types `tps'.
- * todo: treat types with refinements
*/
public static Type lub(Type[] tps) {
//System.out.println("lub" + ArrayApply.toString(tps));//DEBUG
@@ -1922,11 +1939,130 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
private static Type glb(Type[] tps) {
+ // step one: eliminate redunandant types; return if one one is left
tps = elimRedundant(tps, false);
if (tps.length == 1) return tps[0];
- else return NoType;
+
+ // step two: build arrays of all typerefs and all refinements
+ Type.List treftl = Type.List.EMPTY;
+ Type.List comptl = Type.List.EMPTY;
+ for (int i = 0; i < tps.length; i++) {
+ switch (tps[i]) {
+ case TypeRef(_, _, _):
+ treftl = new Type.List(tps[i], treftl);
+ break;
+ case CompoundType(Type[] parents, Scope members):
+ if (members.elems != Scope.Entry.NONE)
+ comptl = new Type.List(tps[i], comptl);
+ for (int j = 0; j < parents.length; j++)
+ treftl = new Type.List(parents[i], treftl);
+ break;
+ case ThisType(_):
+ case SingleType(_, _):
+ return Global.instance.definitions.ALL_TYPE;
+ }
+ }
+
+ CompoundType glbType = compoundType(Type.EMPTY_ARRAY, new Scope());
+ Type glbThisType = glbType.narrow();
+
+ // step 3: compute glb of all refinements.
+ Scope members = Scope.EMPTY;
+ if (comptl != List.EMPTY) {
+ Type[] comptypes = comptl.toArrayReverse();
+ Scope[] refinements = new Scope[comptypes.length];
+ for (int i = 0; i < comptypes.length; i++)
+ refinements[i] = comptypes[i].members();
+ if (!setGlb(glbType.members, refinements, glbThisType)) {
+ // refinements don't have lower bound, so approximate
+ // by AllRef
+ glbType.members = Scope.EMPTY;
+ treftl = new Type.List(
+ Global.instance.definitions.ALLREF_TYPE, treftl);
+ }
+ }
+
+ // eliminate redudant typerefs
+ Type[] treftypes = elimRedundant(treftl.toArrayReverse(), false);
+ if (treftypes.length != 1 || glbType.members.elems != Scope.Entry.NONE) {
+ // step 4: replace all abstract types by their lower bounds.
+ boolean hasAbstract = false;
+ for (int i = 0; i < treftypes.length; i++) {
+ if (treftypes[i].unalias().symbol().kind == TYPE)
+ hasAbstract = true;
+ }
+ if (hasAbstract) {
+ treftl = Type.List.EMPTY;
+ for (int i = 0; i < treftypes.length; i++) {
+ if (treftypes[i].unalias().symbol().kind == TYPE)
+ treftl = new Type.List(treftypes[i].loBound(), treftl);
+ else
+ treftl = new Type.List(treftypes[i], treftl);
+ }
+ treftypes = elimRedundant(treftl.toArrayReverse(), false);
+ }
+ }
+
+ if (treftypes.length != 1) {
+ // step 5: if there are conflicting instantiations of same
+ // class, replace them by lower bound.
+ Type lb = NoType;
+ for (int i = 0;
+ i < treftypes.length &&
+ lb != Global.instance.definitions.ALL_TYPE;
+ i++) {
+ for (int j = 0; j < i; j++) {
+ if (treftypes[j].symbol() == treftypes[i].symbol())
+ lb = treftypes[i].loBound();
+ }
+ }
+ if (lb != NoType) return lb;
+ }
+
+ if (treftypes.length == 1 && glbType.members.elems == Scope.Entry.NONE) {
+ return treftypes[0];
+ } else {
+ glbType.parts = treftypes;
+ return glbType;
+ }
+ }
+
+ private static boolean setGlb(Scope result, Scope[] ss, Type glbThisType) {
+ for (int i = 0; i < ss.length; i++)
+ for (Scope.Entry e = ss[i].elems; e != Scope.Entry.NONE; e = e.next)
+ if (!addMember(result, e.sym, glbThisType)) return false;
+ return true;
}
+ private static boolean addMember(Scope s, Symbol sym, Type glbThisType) {
+ Type syminfo = sym.info().substThis(sym.owner(), glbThisType);
+ Scope.Entry e = s.lookupEntry(sym.name);
+ if (e == Scope.Entry.NONE) {
+ Symbol sym1 = sym.cloneSymbol();
+ sym1.setOwner(glbThisType.symbol());
+ sym1.setInfo(syminfo);
+ s.enter(sym1);
+ return true;
+ } else {
+ Type einfo = e.sym.info();
+ if (einfo.isSameAs(syminfo)) {
+ return true;
+ } else if (einfo.isSubType(syminfo) && sym.kind != ALIAS) {
+ return true;
+ } else if (syminfo.isSubType(einfo) && e.sym.kind != ALIAS) {
+ e.sym.setInfo(syminfo);
+ return true;
+ } else if (sym.kind == VAL && e.sym.kind == VAL ||
+ sym.kind == TYPE && e.sym.kind == TYPE) {
+ e.sym.setInfo(glb(new Type[]{einfo, syminfo}));
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+
// Erasure --------------------------------------------------------------------------
public static Map erasureMap = new MapOnlyTypes() {
diff --git a/sources/scalac/transformer/LambdaLift.java b/sources/scalac/transformer/LambdaLift.java
index e6d2fc902b..fd89c3c260 100644
--- a/sources/scalac/transformer/LambdaLift.java
+++ b/sources/scalac/transformer/LambdaLift.java
@@ -310,7 +310,9 @@ public class LambdaLift extends OwnerTransformer
public Tree transform(Tree tree) {
//global.debugPrinter.print("lifting ").print(tree).println().end();//DEBUG
+ //System.out.print(tree.type + " --> ");//DEBUG
tree.type = descr.transform(tree.type, currentOwner);
+ //System.out.println(tree.type);//DEBUG
switch (tree) {
case ClassDef(_, _, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl):
Symbol sym = tree.symbol();
@@ -403,7 +405,7 @@ public class LambdaLift extends OwnerTransformer
return copy.Apply(
tree, fn1, addFreeArgs(tree.pos, get(free.fvs, fsym), args1));
- case Ident(_):
+ case Ident(Name name):
Symbol sym = tree.symbol();
if (sym.isLocal() &&
(sym.kind == TYPE || (sym.kind == VAL && !sym.isMethod()))) {
@@ -411,6 +413,7 @@ public class LambdaLift extends OwnerTransformer
}
Tree tree1 = copy.Ident(tree, sym).setType(
sym.typeAt(descr.nextPhase));
+ if (name != sym.name) ((Ident)tree1).name = sym.name;
if ((sym.flags & CAPTURED) != 0) return gen.Select(tree1, Names.elem);
else return tree1;
@@ -563,7 +566,7 @@ public class LambdaLift extends OwnerTransformer
gen.mkRef(
pos,
global.definitions.getClass(Names.scala_COLONCOLON).constructor()),
- new Tree[]{gen.mkType(pos, elemtpe), gen.mkType(pos, elemtpe)}),
+ new Tree[]{gen.mkType(pos, elemtpe)}),
new Tree[]{hd, tl}));
}
}
diff --git a/sources/scalac/transformer/LambdaLiftPhase.java b/sources/scalac/transformer/LambdaLiftPhase.java
index 11141db9b2..df31745da5 100644
--- a/sources/scalac/transformer/LambdaLiftPhase.java
+++ b/sources/scalac/transformer/LambdaLiftPhase.java
@@ -13,6 +13,7 @@ import scalac.util.*;
import scalac.parser.*;
import scalac.symtab.*;
import scalac.checkers.*;
+import java.util.ArrayList;
public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers {
@@ -43,7 +44,7 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers
public Type transformInfo(Symbol sym, Type tp) {
if (global.debug)
- global.log("transform info for " + sym + sym.locationString());
+ global.log("transform info for " + sym + ":" + tp + sym.locationString());
Type tp1 = tp;
if (sym != Symbol.NONE) {
switch (tp) {
@@ -53,7 +54,7 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers
break;
default:
if (sym.kind == CLASS)
- tp = transform(tp, sym);
+ tp1 = transform(tp, sym);
else
tp1 = transform(tp, sym.owner());
}
@@ -70,6 +71,7 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers
private class TransformTypeMap extends Type.MapOnlyTypes {
Symbol owner;
+// ArrayList/*<Symbol>*/ excluded = new ArrayList();
Type.Map setOwner(Symbol owner) { this.owner = owner; return this; }
public Type apply(Type tp) {
@@ -95,9 +97,24 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers
}
return Type.TypeRef(pre, sym, targs1);
}
+ } else if (sym.isLocal()) {
+ assert targs.length == 0;
+ return proxy(sym, owner).type();
}
}
break;
+/*
+ case PolyType(Symbol[] tparams, _):
+ if (tparams.length != 0) {
+ int len = excluded.size();
+ for (int i = 0; i < tparams.length; i++)
+ excluded.add(tparams[i]);
+ Type tp1 = map(tp);
+ for (int i = 0; i < tparams.length; i++)
+ excluded.remove(excluded.size() - 1);
+ return tp1;
+ }
+*/
}
return map(tp);
}
@@ -116,7 +133,7 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers
*/
Symbol proxy(Symbol fv, Symbol owner) {
if (global.debug)
- global.log("proxy " + fv + " in " + LambdaLift.asFunction(owner));
+ global.log("proxy " + fv + " of " + fv.owner() + " in " + LambdaLift.asFunction(owner));
Symbol o = owner;
while (o.kind != NONE) {
if (global.debug)
@@ -134,9 +151,9 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers
}
assert o.owner() != o;
o = o.owner();
-
}
- throw new ApplicationError("proxy " + fv + " in " + owner);
+ return fv;
+ //throw new ApplicationError("proxy " + fv + " in " + owner);
}
/** The type scala.Ref[tp]
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index f4d2ed8fa0..2bec0ab167 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -380,39 +380,38 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
*/
void validateBaseTypes(Symbol clazz) {
validateBaseTypes(clazz, clazz.type().parents(),
- new boolean[clazz.closure().length], 0);
+ new Type[clazz.closure().length], 0);
}
//where
- void validateBaseTypes(Symbol clazz, Type[] tps, boolean[] seen, int start) {
+ void validateBaseTypes(Symbol clazz, Type[] tps, Type[] seen, int start) {
for (int i = tps.length - 1; i >= start; i--) {
validateBaseTypes(clazz, tps[i].unalias(), seen, i == 0 ? 0 : 1);
}
}
- void validateBaseTypes(Symbol clazz, Type tp, boolean[] seen, int start) {
+ void validateBaseTypes(Symbol clazz, Type tp, Type[] seen, int start) {
Symbol baseclazz = tp.symbol();
if (baseclazz.kind == CLASS) {
int index = clazz.closurePos(baseclazz);
if (index < 0) return;
- if (seen[index]) {
+ if (seen[index] != null) {
// check that only uniform classes are inherited several times.
if (!clazz.isCompoundSym() && !baseclazz.isTrait()) {
error(clazz.pos, "illegal inheritance;\n" + clazz +
" inherits " + baseclazz + " twice");
}
- // check no two different type instances of same class
- // are inherited.
- Type tp1 = clazz.closure()[index];
- if (!tp1.isSameAs(tp)) {
+ // if there are two different type instances of same class
+ // check that second is a subtype of first.
+ if (!seen[index].isSubType(tp)) {
if (clazz.isCompoundSym())
error(clazz.pos,
"illegal combination;\n " + "compound type " +
" combines different type instances of " +
- baseclazz + ":\n" + tp + " and " + tp1);
+ baseclazz + ":\n" + tp + " and " + seen[index]);
else
error(clazz.pos, "illegal inheritance;\n " + clazz +
" inherits different type instances of " +
- baseclazz + ":\n" + tp + " and " + tp1);
+ baseclazz + ":\n" + tp + " and " + seen[index]);
}
}
// check that case classes do not inherit from case classes
@@ -420,7 +419,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
error(clazz.pos, "illegal inheritance;\n " + "case " + clazz +
" inherits from other case " + baseclazz);
- seen[index] = true;
+ seen[index] = tp;
validateBaseTypes(clazz, tp.parents(), seen, start);
}
}
@@ -468,8 +467,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
checkNonCyclic(
pos, pre.memberInfo(sym).subst(sym.typeParams(), args));
if (sym.kind == TYPE)
- checkNonCyclic(
- pos, sym.loBound().asSeenFrom(pre, sym.owner()));
+ checkNonCyclic(pos, tp.loBound());
sym.flags &= ~LOCKED;
}
break;
@@ -755,7 +753,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
void validateVariance(Symbol base, Type all, Type[] tps, int variance, Symbol[] tparams) {
for (int i = 0; i < tps.length; i++)
- if (tps[i] != tparams[i].type())
+// if (tps[i] != tparams[i].type())
validateVariance(base, all, tps[i], variance * tparams[i].variance());
}
@@ -825,12 +823,16 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (clazz.isLocalClass()) unit.mangler.setMangledName(clazz);
enterSym(tree, clazz.constructor());
- if ((mods & (ABSTRACTCLASS | CASE)) == CASE) {
- // enter case constructor method.
- enterInScope(
- new TermSymbol(
- tree.pos, name.toTermName(), owner, mods & (ACCESSFLAGS | CASE))
- .setInfo(new LazyConstrMethodType(tree)));
+ if ((mods & CASE) != 0) {
+ if (vparams.length == 0) {
+ error(tree.pos, "case class needs () parameter section");
+ } else if ((mods & ABSTRACTCLASS) == 0) {
+ // enter case constructor method.
+ enterInScope(
+ new TermSymbol(
+ tree.pos, name.toTermName(), owner, mods & (ACCESSFLAGS | CASE))
+ .setInfo(new LazyConstrMethodType(tree)));
+ }
}
return enterSym(tree, clazz);
@@ -1755,30 +1757,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return tree;
} else {
Symbol sym = tree.symbol();
- // convert nullary case methods to types
- // check that other idents or selects are stable.
+ // check that idents or selects are stable.
switch (tree) {
case Ident(_):
- if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0)
- return transform(
- make.Apply(
- tree.pos,
- copy.Ident(tree, sym.type().resultType().symbol()),
- Tree.EMPTY_ARRAY),
- mode, pt);
- else
- checkStable(tree);
- break;
- case Select(Tree qual, _):
- if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0)
- return transform(
- make.Apply(
- tree.pos,
- copy.Select(tree, sym.type().resultType().symbol(), qual),
- Tree.EMPTY_ARRAY),
- mode, pt);
- else
- checkStable(tree);
+ case Select(_, _):
+ checkStable(tree);
}
}
} else if ((mode & EXPRmode) != 0) {
@@ -1815,15 +1798,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return tree;
}
//where
- boolean isNullaryMethod(Symbol sym) {
- switch (sym.type()) {
- case PolyType(_, Type restpe):
- return !(restpe instanceof Type.MethodType);
- default:
- return false;
- }
- }
-
Type seqConstructorType(Type paramtp, Type resulttp) {
Symbol constr = resulttp.symbol().constructor();
Symbol param = new TermSymbol(