summaryrefslogtreecommitdiff
path: root/sources/scalac
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-03-03 14:33:53 +0000
committerMartin Odersky <odersky@gmail.com>2003-03-03 14:33:53 +0000
commit6749e5dd658522cb63600021a9ee5a86f911cfeb (patch)
treea22d4bf7f2bf71b5775418dfddaa31a1640313d1 /sources/scalac
parente1fb3fb655a067039870016b3a47e2305d692d98 (diff)
downloadscala-6749e5dd658522cb63600021a9ee5a86f911cfeb.tar.gz
scala-6749e5dd658522cb63600021a9ee5a86f911cfeb.tar.bz2
scala-6749e5dd658522cb63600021a9ee5a86f911cfeb.zip
*** empty log message ***
Diffstat (limited to 'sources/scalac')
-rw-r--r--sources/scalac/ast/TreeGen.java4
-rw-r--r--sources/scalac/ast/parser/Parser.java27
-rw-r--r--sources/scalac/symtab/Definitions.java61
-rw-r--r--sources/scalac/symtab/Scope.java17
-rw-r--r--sources/scalac/symtab/Symbol.java132
-rw-r--r--sources/scalac/symtab/Type.java58
-rw-r--r--sources/scalac/symtab/classfile/AttributeParser.java2
-rw-r--r--sources/scalac/symtab/classfile/ClassfileParser.java2
-rw-r--r--sources/scalac/transformer/LambdaLiftPhase.java2
-rw-r--r--sources/scalac/typechecker/Analyzer.java143
-rw-r--r--sources/scalac/typechecker/DeSugarize.java87
-rw-r--r--sources/scalac/typechecker/RefCheck.java7
-rw-r--r--sources/scalac/util/Name.java4
-rw-r--r--sources/scalac/util/Names.java3
14 files changed, 377 insertions, 172 deletions
diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java
index d29903f14e..1eb59ca0e0 100644
--- a/sources/scalac/ast/TreeGen.java
+++ b/sources/scalac/ast/TreeGen.java
@@ -534,9 +534,7 @@ public class TreeGen implements Kinds, Modifiers {
pos, Names.ANON_CLASS_NAME.toTypeName(), owner, 0);
clazz.setInfo(Type.compoundType(new Type[]{f0t}, new Scope(), clazz));
clazz.constructor().setInfo(
- Type.MethodType(
- Symbol.EMPTY_ARRAY,
- Type.TypeRef(owner.thisType(), clazz, Type.EMPTY_ARRAY)));
+ Type.MethodType(Symbol.EMPTY_ARRAY, clazz.typeConstructor()));
Symbol applyMeth = new TermSymbol(pos, Names.apply, clazz, FINAL)
.setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, tp));
diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java
index 7455080054..8243d73411 100644
--- a/sources/scalac/ast/parser/Parser.java
+++ b/sources/scalac/ast/parser/Parser.java
@@ -168,7 +168,7 @@ public class Parser implements Tokens {
*/
Tree makeBinop(boolean isExpr, int pos, Tree left, Name op, Tree right) {
if (isExpr) {
- if (op.leftAssoc()) {
+ if (op.isLeftAssoc()) {
return make.Apply(pos,
make.Select(pos, left, NameTransformer.encode(op)),
new Tree[]{right});
@@ -339,7 +339,7 @@ public class Parser implements Tokens {
int prec, boolean leftAssoc) {
if (sp != base &&
operators[sp-1].precedence() == prec &&
- operators[sp-1].leftAssoc() != leftAssoc) {
+ operators[sp-1].isLeftAssoc() != leftAssoc) {
syntaxError(
positions[sp-1],
"left- and right-associative operators with same precedence may not be mixed",
@@ -666,9 +666,16 @@ public class Parser implements Tokens {
return make.If(pos, cond, thenp, elsep) ;
} else if (s.token == FOR) {
s.nextToken();
- accept(LPAREN);
- Tree[] enums = enumerators();
- accept(RPAREN);
+ Tree[] enums;
+ if (s.token == LBRACE) {
+ accept(LBRACE);
+ enums = enumerators();
+ accept(RBRACE);
+ } else {
+ accept(LPAREN);
+ enums = enumerators();
+ accept(RPAREN);
+ }
if (s.token == DO) {
return makeFor(s.skipToken(), enums, Names.foreach, Names.foreach, expr());
} else if (s.token == YIELD) {
@@ -712,7 +719,7 @@ public class Parser implements Tokens {
Tree top = prefixExpr();
while (s.token == IDENTIFIER) {
top = reduceStack(
- true, base, top, s.name.precedence(), s.name.leftAssoc());
+ true, base, top, s.name.precedence(), s.name.isLeftAssoc());
push(top, s.pos, s.name);
ident();
if (isExprIntro()) {
@@ -972,7 +979,7 @@ public class Parser implements Tokens {
}
while (s.token == IDENTIFIER) {
top = reduceStack(
- false, base, top, s.name.precedence(), s.name.leftAssoc());
+ false, base, top, s.name.precedence(), s.name.isLeftAssoc());
push(top, s.pos, s.name);
ident();
top = simplePattern();
@@ -1439,7 +1446,7 @@ public class Parser implements Tokens {
tparams, vparams, restype, Tree.Empty);
}
- /** TypeDef ::= Id [TypeParamClause] `=' Type
+ /** TypeDef ::= Id `=' Type
* TypeSig ::= Id [`<:' Type]
*/
Tree typeDefOrSig(int mods) {
@@ -1449,10 +1456,6 @@ public class Parser implements Tokens {
s.nextToken();
return make.TypeDef(pos, mods | Modifiers.DEFERRED, name,
Tree.ExtTypeDef.EMPTY_ARRAY, type());
- } else if (s.token == LBRACKET) {
- TypeDef[] tparams = typeParamClauseOpt();
- accept(EQUALS);
- return make.TypeDef(pos, mods, name, tparams, type());
} else if (s.token == EQUALS) {
s.nextToken();
return make.TypeDef(pos, mods, name,
diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java
index f9e5a6f0ec..a842885d31 100644
--- a/sources/scalac/symtab/Definitions.java
+++ b/sources/scalac/symtab/Definitions.java
@@ -45,6 +45,10 @@ public class Definitions {
public final Symbol SCALARUNTIME_CLASS;
public final Type SCALARUNTIME_TYPE;
+ /** the partial function class
+ */
+ public final Symbol PARTIALFUNCTION_CLASS;
+
/** the null value
*/
public final Symbol NULL;
@@ -191,61 +195,61 @@ public class Definitions {
ANY_CLASS = new ClassSymbol(
Position.NOPOS, Names.Any.toTypeName(), SCALA_CLASS, Modifiers.JAVA);
SCALA_CLASS.members().enter(ANY_CLASS);
- ANY_TYPE = monoType(ANY_CLASS);
+ ANY_TYPE = ANY_CLASS.typeConstructor();
ANY_CLASS.setInfo(Type.compoundType(Type.EMPTY_ARRAY, new Scope(), ANY_CLASS));
ANY_CLASS.constructor().setInfo(
Type.PolyType(Symbol.EMPTY_ARRAY, ANY_TYPE));
// the java.lang.OBJECT class
JAVA_OBJECT_CLASS = getClass(Names.java_lang_Object);
- JAVA_OBJECT_TYPE = monoType(JAVA_OBJECT_CLASS);
+ JAVA_OBJECT_TYPE = JAVA_OBJECT_CLASS.typeConstructor();
JAVA_OBJECT_CLASS.setInfo(pparser.classCompletion);
+ // the scala.PartialFunction class
+ PARTIALFUNCTION_CLASS = getClass(Names.scala_PartialFunction);
+
// the scala.ANYREF class
ANYREF_CLASS = new TypeSymbol(
Kinds.ALIAS, Position.NOPOS, Names.AnyRef.toTypeName(),
SCALA_CLASS, Modifiers.JAVA)
.setInfo(JAVA_OBJECT_TYPE);
- ANYREF_CLASS.constructor().setInfo(
- Type.PolyType(Symbol.EMPTY_ARRAY, Type.NoType));
-
- ANYREF_TYPE = monoType(ANYREF_CLASS);
+ ANYREF_TYPE = ANYREF_CLASS.typeConstructor();
SCALA.members().enter(ANYREF_CLASS);
// the scala.OBJECT class
OBJECT_CLASS = getClass(Names.scala_Object);
- OBJECT_TYPE = monoType(OBJECT_CLASS);
+ OBJECT_TYPE = OBJECT_CLASS.typeConstructor();
// the scala.ANYVAL class
ANYVAL_CLASS = getClass(Names.scala_AnyVal);
- ANYVAL_TYPE = monoType(ANYVAL_CLASS);
+ ANYVAL_TYPE = ANYVAL_CLASS.typeConstructor();
// the primitive types
DOUBLE_CLASS = getClass(Names.scala_Double);
- DOUBLE_TYPE = monoType(DOUBLE_CLASS);
+ DOUBLE_TYPE = DOUBLE_CLASS.typeConstructor();
FLOAT_CLASS = getClass(Names.scala_Float);
- FLOAT_TYPE = monoType(FLOAT_CLASS);
+ FLOAT_TYPE = FLOAT_CLASS.typeConstructor();
LONG_CLASS = getClass(Names.scala_Long);
- LONG_TYPE = monoType(LONG_CLASS);
+ LONG_TYPE = LONG_CLASS.typeConstructor();
INT_CLASS = getClass(Names.scala_Int);
- INT_TYPE = monoType(INT_CLASS);
+ INT_TYPE = INT_CLASS.typeConstructor();
CHAR_CLASS = getClass(Names.scala_Char);
- CHAR_TYPE = monoType(CHAR_CLASS);
+ CHAR_TYPE = CHAR_CLASS.typeConstructor();
SHORT_CLASS = getClass(Names.scala_Short);
- SHORT_TYPE = monoType(SHORT_CLASS);
+ SHORT_TYPE = SHORT_CLASS.typeConstructor();
BYTE_CLASS = getClass(Names.scala_Byte);
- BYTE_TYPE = monoType(BYTE_CLASS);
+ BYTE_TYPE = BYTE_CLASS.typeConstructor();
BOOLEAN_CLASS = getClass(Names.scala_Boolean);
- BOOLEAN_TYPE = monoType(BOOLEAN_CLASS);
+ BOOLEAN_TYPE = BOOLEAN_CLASS.typeConstructor();
UNIT_CLASS = getClass(Names.scala_Unit);
- UNIT_TYPE = monoType(UNIT_CLASS);
+ UNIT_TYPE = UNIT_CLASS.typeConstructor();
// the array class
ARRAY_CLASS = getClass(Names.scala_Array);
// add members to java.lang.Throwable
JAVA_THROWABLE_CLASS = getClass(Names.java_lang_Throwable);
- JAVA_THROWABLE_TYPE = monoType(JAVA_THROWABLE_CLASS);
+ JAVA_THROWABLE_TYPE = JAVA_THROWABLE_CLASS.typeConstructor();
THROW = new TermSymbol(
Position.NOPOS, Names.throw_, JAVA_THROWABLE_CLASS, Modifiers.FINAL);
Symbol tvar = newTypeParameter(THROW, ANY_TYPE);
@@ -254,13 +258,11 @@ public class Definitions {
// add the java.lang.String class to the scala package
JAVA_STRING_CLASS = getClass(Names.java_lang_String);
- JAVA_STRING_TYPE = monoType(JAVA_STRING_CLASS);
+ JAVA_STRING_TYPE = JAVA_STRING_CLASS.typeConstructor();
STRING_CLASS = new TypeSymbol(
Kinds.ALIAS, Position.NOPOS, Names.String.toTypeName(), SCALA_CLASS, 0)
.setInfo(JAVA_STRING_TYPE);
- STRING_CLASS.constructor().setInfo(
- Type.PolyType(Symbol.EMPTY_ARRAY, Type.NoType));
- STRING_TYPE = monoType(STRING_CLASS);
+ STRING_TYPE = STRING_CLASS.typeConstructor();
SCALA.members().enter(STRING_CLASS);
SEQ_CLASS = getClass(Names.scala_Seq);
@@ -384,12 +386,8 @@ public class Definitions {
return getClass(fullname).type();
}
- public Type monoType(Symbol c) {
- return Type.TypeRef(c.owner().thisType(), c, Type.EMPTY_ARRAY);
- }
-
public Type getJavaType(Name fullname) {
- return monoType(getClass(fullname));
+ return getClass(fullname).typeConstructor();
}
private void loadBooleanMembers() {
@@ -402,7 +400,7 @@ public class Definitions {
}
public Type arrayType(Type elemtpe) {
- return Type.appliedType(monoType(ARRAY_CLASS), new Type[]{elemtpe});
+ return Type.appliedType(ARRAY_CLASS.typeConstructor(), new Type[]{elemtpe});
}
public Type functionType(Type[] argtps, Type restp) {
@@ -414,6 +412,13 @@ public class Definitions {
argtps1);
}
+ public Type partialFunctionType(Type argtpe, Type restpe) {
+ Type[] argtps1 = new Type[2];
+ argtps1[0] = argtpe;
+ argtps1[1] = Type.covarType(restpe);
+ return Type.appliedType(PARTIALFUNCTION_CLASS.typeConstructor(), argtps1);
+ }
+
public Type seqType(Type argtpe) {
return Type.appliedType(getType(Names.scala_Seq), new Type[]{argtpe});
}
diff --git a/sources/scalac/symtab/Scope.java b/sources/scalac/symtab/Scope.java
index 3bd22f51ed..f1fa915c55 100644
--- a/sources/scalac/symtab/Scope.java
+++ b/sources/scalac/symtab/Scope.java
@@ -210,19 +210,22 @@ public class Scope {
/** remove entry
*/
public void unlink(Entry e) {
- Entry e1 = hashtable[e.sym.name.index & HASHMASK];
- if (e1 == e) {
- hashtable[e.sym.name.index & HASHMASK] = e.tail;
- } else {
- while (e1.tail != e) e1 = e1.tail;
- }
if (elems == e) {
elems = e.next;
} else {
- e1 = elems;
+ Entry e1 = elems;
while (e1.next != e) e1 = e1.next;
e1.next = e.next;
}
+ if (hashtable != null) {
+ Entry e1 = hashtable[e.sym.name.index & HASHMASK];
+ if (e1 == e) {
+ hashtable[e.sym.name.index & HASHMASK] = e.tail;
+ } else {
+ while (e1.tail != e) e1 = e1.tail;
+ e1.tail = e.tail;
+ }
+ }
elemsCache = null;
}
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index b8e1821daa..20ab5b3366 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -113,9 +113,16 @@ public abstract class Symbol implements Modifiers, Kinds {
return this;
}
- /** Set type -- this is an alias for setInfo(Type info) */
+ /** Set type -- this is an alias for setInfo(Type info)
+ */
public Symbol setType(Type info) { return setInfo(info); }
+ /** Set type of `this' in current class
+ */
+ public Symbol setTypeOfThis(Type tp) {
+ throw new ApplicationError(this + ".setTypeOfThis");
+ }
+
public Symbol updateInfo(Type info) {
// Global.instance.currentPhase.setInfo(this, info);
if (infos.limit <= Global.instance.currentPhase.id) {
@@ -481,9 +488,11 @@ public abstract class Symbol implements Modifiers, Kinds {
int nextid = infos.limit;
assert infos != TypeIntervalList.EMPTY : this;
if (nextid < id) {
+ PhaseDescriptor curphase = Global.instance.currentPhase;
do {
+ Global.instance.currentPhase = Global.instance.phases[nextid];
Type newInfo =
- Global.instance.phases[nextid].transformInfo(this, infos.info);
+ Global.instance.currentPhase.transformInfo(this, infos.info);
if (newInfo != infos.info) {
infos = new TypeIntervalList(infos);
infos.info = newInfo;
@@ -491,6 +500,7 @@ public abstract class Symbol implements Modifiers, Kinds {
nextid++;
infos.limit = nextid;
} while (nextid < id);
+ Global.instance.currentPhase = curphase;
return infos.info;
} else {
TypeIntervalList infos1 = infos;
@@ -528,14 +538,25 @@ public abstract class Symbol implements Modifiers, Kinds {
return tps;
}
+ /** The type constructor of a symbol is:
+ * For a type symbol, the type corresponding to the symbol itself, excluding
+ * parameters.
+ * Not applicable for term symbols.
+ */
+ public Type typeConstructor() {
+ throw new ApplicationError("typeConstructor inapplicable for " + this);
+ }
+
/** Get this.type corresponding to this symbol
*/
public Type thisType() {
return Type.localThisType;
}
+ /** Get type of `this' in current class.
+ */
public Type typeOfThis() {
- return Type.localThisType;
+ return type();
}
/** A total ordering between symbols that refines the class
@@ -857,10 +878,10 @@ public class TermSymbol extends Symbol {
TermSymbol sym = new TermSymbol(pos, name, owner, flags | MODUL | FINAL);
Symbol clazz = new ClassSymbol(
pos, name.toTypeName(), owner, flags | MODUL | FINAL, sym);
- Type clazztype = Type.TypeRef(owner.thisType(), clazz, Type.EMPTY_ARRAY);
- clazz.constructor().setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, clazztype));
+ clazz.constructor().setInfo(
+ Type.MethodType(Symbol.EMPTY_ARRAY, clazz.typeConstructor()));
sym.clazz = clazz;
- sym.setInfo(clazztype);
+ sym.setInfo(clazz.typeConstructor());
return sym;
}
@@ -910,6 +931,10 @@ public class TermSymbol extends Symbol {
return other;
}
+ public Symbol[] typeParams() {
+ return type().typeParams();
+ }
+
public Symbol primaryConstructorClass() {
return isConstructor() && clazz != null ? clazz : this;
}
@@ -927,56 +952,42 @@ public class TypeSymbol extends Symbol {
*/
private ClosureIntervalList closures = ClosureIntervalList.EMPTY;
- /** The symbol's type template */
- private Type template;
-
- /** The primary constructor of this type */
- public final Symbol constructor;
+ /** A cache for type constructors
+ */
+ private Type tycon = null;
/** Constructor */
public TypeSymbol(int kind, int pos, Name name, Symbol owner, int flags) {
super(kind, pos, name, owner, flags);
- this.constructor = TermSymbol.newConstructor(this, flags);
- if (kind == TYPE) { // provide a constructor type
- this.constructor().setInfo(
- Type.PolyType(Symbol.EMPTY_ARRAY, Type.NoType));
- }
}
+
/** Return a fresh symbol with the same fields as this one.
*/
public Symbol cloneSymbol() {
if (Global.instance.debug) System.out.println("cloning " + this + this.locationString());
TypeSymbol other = new TypeSymbol(kind, pos, name, owner(), flags);
other.setInfo(info());
- other.constructor.setInfo(constructor.info());
return other;
}
- /** Get self type */
+ /** Get type constructor */
+ public Type typeConstructor() {
+ if (tycon == null)
+ tycon = Type.TypeRef(owner().thisType(), this, Type.EMPTY_ARRAY);
+ return tycon;
+ }
+
+ /** Get type */
public Type type() {
- if (template == null || template.typeArgs().length != typeParams().length) {
- template = Type.TypeRef(
- owner().thisType(), this, type(typeParams()));
- }
- return template;
+ return typeConstructor();
}
- //todo: needed?
+ /** Get type at phase id */
public Type typeAt(int id) {
return type();
}
- /** Get type parameters */
- public Symbol[] typeParams() {
- return constructor.info().typeParams();
- }
-
- /** Get primary constructor */
- public Symbol constructor() {
- return constructor;
- }
-
public Type[] closure() {
if (kind == ALIAS) return info().symbol().closure();
int id = Global.instance.currentPhase.id;
@@ -1069,6 +1080,12 @@ public class ClassSymbol extends TypeSymbol {
/** The mangled class name */
private Name mangled;
+ /** The symbol's type template */
+ private Type template;
+
+ /** The primary constructor of this type */
+ public final Symbol constructor;
+
/** The module belonging to the class. This means:
* For Java classes, its statics parts.
* For module classes, the corresponding module.
@@ -1076,10 +1093,19 @@ public class ClassSymbol extends TypeSymbol {
*/
private Symbol module = NONE;
+ /** The given type of self, or NoType, if no explicit type was given.
+ */
+ private Symbol thisSym = this;
+
+ /** A cache for this.thisType()
+ */
+ private Type thistp = Type.ThisType(this);
+
/** Principal Constructor for module classes and classes with static members.
*/
public ClassSymbol(int pos, Name name, Symbol owner, int flags) {
super(CLASS, pos, name, owner, flags);
+ this.constructor = TermSymbol.newConstructor(this, flags);
this.mangled = name;
}
@@ -1103,6 +1129,7 @@ public class ClassSymbol extends TypeSymbol {
*/
public ClassSymbol(Name name, Symbol owner, ClassParser parser) {
super(CLASS, Position.NOPOS, name, owner, JAVA);
+ this.constructor = TermSymbol.newConstructor(this, flags);
this.module = TermSymbol.newCompanionModule(this, JAVA, parser.staticsParser(this));
this.mangled = name;
this.setInfo(parser);
@@ -1116,9 +1143,17 @@ public class ClassSymbol extends TypeSymbol {
other.constructor.setInfo(constructor.info());
other.mangled = mangled;
other.module = module;
+ other.thisSym = thisSym;
return other;
}
+ /** copy all fields to `sym'
+ */
+ public void copyTo(Symbol sym) {
+ super.copyTo(sym);
+ if (thisSym != this) sym.setTypeOfThis(typeOfThis());
+ }
+
/** Get module */
public Symbol module() {
return module;
@@ -1153,12 +1188,39 @@ public class ClassSymbol extends TypeSymbol {
}
}
- private Type thistp = Type.ThisType(this);
+ /** Get type parameters */
+ public Symbol[] typeParams() {
+ return constructor.info().typeParams();
+ }
+
+ /** Get type */
+ public Type type() {
+ if (template == null || template.typeArgs().length != typeParams().length) {
+ template = Type.TypeRef(
+ owner().thisType(), this, type(typeParams()));
+ }
+ return template;
+ }
public Type thisType() {
return thistp;
}
+ public Type typeOfThis() {
+ return thisSym.type();
+ }
+
+ public Symbol setTypeOfThis(Type tp) {
+ thisSym = new TermSymbol(this.pos, Names.this_, this, SYNTHETIC);
+ thisSym.setInfo(tp);
+ return this;
+ }
+
+ /** Get primary constructor */
+ public Symbol constructor() {
+ return constructor;
+ }
+
/** Return the next enclosing class */
public Symbol enclClass() {
return this;
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index 7e94662d9a..3a95a2805d 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -186,7 +186,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
public Type widen() {
switch (this) {
case ThisType(Symbol sym):
- return sym.type();
+ return sym.typeOfThis();
case SingleType(Type pre, Symbol sym):
// overridden in ExtSingleType
throw new ApplicationError();
@@ -249,6 +249,30 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
}
+ /** Get type of `this' symbol corresponding to this type, extend
+ * homomorphically to function types and method types.
+ */
+ public Type instanceType() {
+ switch (unalias()) {
+ case TypeRef(Type pre, Symbol sym, Type[] args):
+ Type tp1 = sym.typeOfThis();
+ if (tp1 != sym.type())
+ return tp1.asSeenFrom(pre, sym.owner()).subst(sym.typeParams(), args);
+ break;
+ case MethodType(Symbol[] params, Type restp):
+ Type restp1 = restp.instanceType();
+ if (restp1 != restp)
+ return MethodType(params, restp1);
+ break;
+ case PolyType(Symbol[] tparams, Type restp):
+ Type restp1 = restp.instanceType();
+ if (restp1 != restp)
+ return PolyType(tparams, restp1);
+ break;
+ }
+ return this;
+ }
+
/** Remove all aliases
*/
public Type unalias() {
@@ -261,9 +285,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
if (n == 20) throw new Type.Error("recursive type alias: " + this);
switch (this) {
case TypeRef(Type pre, Symbol sym, Type[] args):
- if (sym.kind == ALIAS) {
- return pre.memberInfo(sym).subst(sym.typeParams(), args).unalias(n + 1);
- }
+ if (sym.kind == ALIAS) return pre.memberInfo(sym).unalias(n + 1);
break;
case TypeVar(Type origin, Constraint constr):
if (constr.inst != NoType) return constr.inst.unalias(n + 1);
@@ -303,8 +325,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
case PolyType(Symbol[] tparams, _):
return tparams;
case TypeRef(_, Symbol sym, _):
- if (sym.kind == CLASS || sym.kind == ALIAS) return sym.typeParams();
- break;
+ if (sym.kind == CLASS) return sym.typeParams();
+ else return sym.info().typeParams();
}
return Symbol.EMPTY_ARRAY;
}
@@ -433,7 +455,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
public boolean isFunctionType() {
switch (this) {
case TypeRef(Type pre, Symbol sym, Type[] args):
- if (sym.fullName().startsWith(Names.Function)) {
+ if (sym.fullName().startsWith(Names.scala_Function)) {
for (int i = 0; i < args.length - 1; i++)
if (args[i].isCovarType()) return false;
return args.length > 0 && args[args.length - 1].isCovarType();
@@ -693,11 +715,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
case TypeRef(Type pre, Symbol sym, Type[] args):
if (sym == clazz)
return this;
- else if (sym.kind == TYPE)
+ else if (sym.kind == TYPE || sym.kind == ALIAS)
return pre.memberInfo(sym).baseType(clazz);
- else if (sym.kind == ALIAS)
- return pre.memberInfo(sym).baseType(clazz)
- .subst(sym.typeParams(), args);
else if (clazz.isCompoundSym())
return NoType;
else
@@ -811,14 +830,15 @@ public class Type implements Modifiers, Kinds, TypeTags {
switch (pre.baseType(ownclass)) {
case TypeRef(_, Symbol basesym, Type[] baseargs):
Symbol[] baseparams = basesym.typeParams();
- for (int i = 0; i < baseparams.length; i++)
- if (sym == baseparams[i]) return baseargs[i];//???
+ for (int i = 0; i < baseparams.length; i++) {
+ if (sym == baseparams[i]) return baseargs[i];
+ }
break;
case ErrorType:
return ErrorType;
}
throw new ApplicationError(
- this + " cannot be instantiated from " + pre);
+ this + " in " + ownclass + " cannot be instantiated from " + pre);
} else {
return toInstance(
pre.baseType(clazz).prefix(), clazz.owner());
@@ -1115,8 +1135,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
*/
public boolean containsSome(Symbol[] syms) {
for (int i = 0; i < syms.length; i++)
- if (contains(syms[i])) return false;
- return true;
+ if (contains(syms[i])) return true;
+ return false;
}
// Comparisons ------------------------------------------------------------------
@@ -1789,6 +1809,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
e = e.next) {
Name name = e.sym.name;
if ((e.sym.flags & PRIVATE) == 0 && lubType.lookup(name) == e.sym) {
+ //todo: not memberType?
Type symType = lubThisType.memberInfo(e.sym);
int j = 0;
while (j < tps.length) {
@@ -2025,6 +2046,11 @@ public class Type implements Modifiers, Kinds, TypeTags {
System.arraycopy(args, 0, params, 0, params.length);
return ArrayApply.toString(params, "(", ",", ") => ") +
args[params.length].dropVariance();
+ } else if (sym.isAnonymousClass()) {
+ return "<template: " +
+ ArrayApply.toString(
+ pre.memberInfo(sym).parents(), "", "", " with ") +
+ "{...}>";
}
}
Type pre1 = (Global.instance.debug) ? pre : pre.expandModuleThis();
diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java
index 0ed09b44d0..a9e0790889 100644
--- a/sources/scalac/symtab/classfile/AttributeParser.java
+++ b/sources/scalac/symtab/classfile/AttributeParser.java
@@ -322,7 +322,7 @@ public class AttributeParser implements ClassfileConstants {
types.toArray(args);
return Type.TypeRef(clazz.owner().thisType(), clazz, args);
} else {
- return parser.defs.monoType(clazz);
+ return clazz.typeConstructor();
}
}
diff --git a/sources/scalac/symtab/classfile/ClassfileParser.java b/sources/scalac/symtab/classfile/ClassfileParser.java
index 686b832459..61b7c88691 100644
--- a/sources/scalac/symtab/classfile/ClassfileParser.java
+++ b/sources/scalac/symtab/classfile/ClassfileParser.java
@@ -53,7 +53,7 @@ public class ClassfileParser implements ClassfileConstants {
this.global = global;
this.in = in;
this.c = c;
- this.ctype = Type.TypeRef(c.owner().thisType(), c, Type.EMPTY_ARRAY);
+ this.ctype = c.typeConstructor();
this.make = new JavaTypeCreator(global);
this.sigs = new Signatures(global, make);
this.pool = new ConstantPool(in, sigs);
diff --git a/sources/scalac/transformer/LambdaLiftPhase.java b/sources/scalac/transformer/LambdaLiftPhase.java
index 4b86c37acf..1960175ae8 100644
--- a/sources/scalac/transformer/LambdaLiftPhase.java
+++ b/sources/scalac/transformer/LambdaLiftPhase.java
@@ -64,7 +64,7 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers
case TypeRef(Type pre, Symbol sym, Type[] targs):
switch (pre) {
case ThisType(_):
- if (sym.constructor().isUpdated(nextPhase)) {
+ if (sym.kind == CLASS && sym.constructor().isUpdated(nextPhase)) {
Symbol[] tparams =
sym.constructor().infoAt(nextPhase).typeParams();
int i = tparams.length;
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 232ba4a0c9..dd8a65ff22 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -27,6 +27,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
private final DeSugarize desugarize;
private final AnalyzerPhase descr;
final Infer infer;
+ final Transformer duplicator;
public Analyzer(Global global, AnalyzerPhase descr) {
super(global, descr);
@@ -34,6 +35,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
this.descr = descr;
this.infer = new Infer(this);
this.desugarize = new DeSugarize(this, global);
+ this.duplicator = new Transformer(
+ global, descr, make, new StrictTreeFactory(make));
}
/** Phase variables, used and set in transformers;
@@ -152,19 +155,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return fn.type == Type.ErrorType ? Type.ErrorType : Type.NoType;
}
- private Tree deepCopy(Tree tree) {
- switch (tree) {
- case Ident(Name name):
- return make.Ident(tree.pos, name)
- .setSymbol(tree.symbol()).setType(tree.type);
- case Select(Tree qual, Name name):
- return make.Select(tree.pos, deepCopy(qual), name)
- .setSymbol(tree.symbol()).setType(tree.type);
- default:
- return tree;
- }
- }
-
static Name value2TypeName(Object value) {
if (value instanceof Character) return Name.fromString("scala.Char");
else if (value instanceof Integer) return Name.fromString("scala.Int");
@@ -293,15 +283,19 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
* - final classes are only inherited by classes which are
* nested within definition of base class, or that occur within same
* statement sequence.
+ * - self-type of current class is a subtype of self-type of each parent class.
*/
- void validateParentClasses(Tree[] constrs, Type[] parents) {
+ void validateParentClasses(Tree[] constrs, Type[] parents, Type selfType) {
if (parents.length == 0 || !checkClassType(constrs[0].pos, parents[0])) return;
- for (int i = 1; i < parents.length; i++) {
+ for (int i = 0; i < parents.length; i++) {
if (!checkClassType(constrs[i].pos, parents[i])) return;
- Type[] grandparents = parents[i].parents();
- if (grandparents.length > 0 && !parents[0].isSubType(grandparents[0]))
- error(constrs[i].pos, "illegal inheritance;\n " + parents[0] +
- " does not conform to " + parents[i] + "'s supertype");
+ if (1 <= i) {
+ Type[] grandparents = parents[i].parents();
+ if (grandparents.length > 0 &&
+ !parents[0].isSubType(grandparents[0]))
+ error(constrs[i].pos, "illegal inheritance;\n " + parents[0] +
+ " does not conform to " + parents[i] + "'s supertype");
+ }
Symbol bsym = parents[i].symbol();
if ((bsym.flags & FINAL) != 0) {
// are we in same scope as base type definition?
@@ -316,6 +310,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
}
}
+ if (!selfType.isSubType(parents[i].instanceType())) {
+ error(constrs[i].pos, "illegal inheritance;\n self-type " +
+ selfType + " does not conform to " + parents[i] +
+ "'s selftype " + parents[i].instanceType());
+ }
}
}
@@ -444,7 +443,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
try {
return checkNoEscapeMap.apply(tp);
} catch (Type.Error ex) {
- error(pos, tp + "///" + ex.msg);
+ error(pos, ex.msg);
return Type.ErrorType;
}
}
@@ -496,6 +495,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return error(tree, "stable identifier required");
}
+ /** Check that (abstract) type can be instantiated.
+ */
+ void checkInstantiatable(int pos, Type tp) {
+ error(pos, tp.symbol() + " is abstract; cannot be instantiated");
+ }
+
/** Check all members of class `clazz' for overriding conditions.
*/
void checkAllOverrides(Symbol clazz) {
@@ -628,7 +633,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (clazz.isLocalClass()) unit.mangler.setMangledName(clazz);
enterSym(tree, clazz.constructor());
- if ((mods & CASE) != 0) {
+ if ((mods & (ABSTRACTCLASS | CASE)) == CASE) {
// enter case constructor method.
enterInScope(
new TermSymbol(
@@ -652,10 +657,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case TypeDef(int mods, Name name, _, _):
int kind = (mods & (DEFERRED | PARAM)) != 0 ? TYPE : ALIAS;
- TypeSymbol tsym = new TypeSymbol(kind, tree.pos, name, owner, mods);
- if (kind == ALIAS)
- tsym.constructor().setInfo(new LazyTreeType(tree));
- return enterSym(tree, tsym);
+ return enterSym(tree, new TypeSymbol(kind, tree.pos, name, owner, mods));
case Import(Tree expr, Name[] selectors):
return enterImport(tree,
@@ -700,7 +702,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (other.isPreloaded()) {
// symbol was preloaded from package;
// need to overwrite definition.
- if (global.debug) System.out.println("overwriting " + other);//debug
+ if (global.debug) System.out.println(sym + " overwrites " + other);//debug
sym.copyTo(other);
if (sym.isModule()) {
sym.moduleClass().copyTo(
@@ -742,11 +744,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
/** Define symbol associated with `tree' using given `context'.
*/
- void defineSym(Tree tree, Unit unit, Infer infer, Context context) {
+ void defineSym(Tree tree, Unit unit, Infer infer, Context curcontext) {
Unit savedUnit = this.unit;
this.unit = unit;
Context savedContext = this.context;
- this.context = context;
+ this.context = curcontext;
int savedMode = this.mode;
this.mode = EXPRmode;
Type savedPt = this.pt;
@@ -756,7 +758,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (global.debug) System.out.println("defining " + sym);//debug
Type owntype;
switch (tree) {
- case ClassDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, _, Tree.Template templ):
+ case ClassDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ):
assert (mods & LOCKED) == 0 || sym.isAnonymousClass(): sym; // to catch repeated evaluations
((ClassDef) tree).mods |= LOCKED;
@@ -766,6 +768,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
pushContext(tree, sym.constructor(), new Scope(context.scope));
Symbol[] tparamSyms = enterParams(tparams);
Symbol[][] vparamSyms = enterParams(vparams);
+ for (int i = 0; i < vparamSyms.length; i++)
+ for (int j = 0; j < vparamSyms[i].length; j++)
+ context.scope.unlink(
+ context.scope.lookupEntry(vparamSyms[i][j].name));
Type constrtype = makeMethodType(
tparamSyms,
vparamSyms,
@@ -773,7 +779,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
sym.constructor().setInfo(constrtype);
// necessary so that we can access tparams
sym.constructor().flags |= INITIALIZED;
+ if (tpe != Tree.Empty)
+ sym.setTypeOfThis(transform(tpe, TYPEmode).type);
+ reenterParams(vparams);
defineTemplate(templ, sym);
owntype = templ.type;
popContext();
@@ -812,31 +821,31 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case DefDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs):
pushContext(tree, sym, new Scope(context.scope));
Symbol[] tparamSyms = enterParams(tparams);
+ Type restpe = null;
+ if (tpe != Tree.Empty) {
+ restpe = transform(tpe, TYPEmode).type;
+ }
Symbol[][] vparamSyms = enterParams(vparams);
- Type restpe;
if (tpe == Tree.Empty) {
int rhsmode = name.isConstrName() ? CONSTRmode : EXPRmode;
((DefDef) tree).rhs = rhs = transform(rhs, rhsmode);
restpe = rhs.type.widen();
- } else {
- restpe = transform(tpe, TYPEmode).type;
}
popContext();
owntype = makeMethodType(tparamSyms, vparamSyms, restpe);
break;
case TypeDef(int mods, Name name, Tree.TypeDef[] tparams, Tree rhs):
+ //todo: alwyas have context.owner as owner.
if (sym.kind == TYPE) {
pushContext(rhs, context.owner, context.scope);
- this.context.delayArgs = true;
+ context.delayArgs = true;
owntype = transform(rhs, TYPEmode).type;
owntype.symbol().initialize();//to detect cycles
popContext();
} else { // sym.kind == ALIAS
pushContext(tree, sym, new Scope(context.scope));
- Symbol[] tparamSyms = enterParams(tparams);
- sym.constructor().setInfo(Type.PolyType(tparamSyms, Type.NoType));
- owntype = transform(rhs, TYPEmode).type;
+ owntype = transform(rhs, TYPEmode | FUNmode).type;
popContext();
}
break;
@@ -921,8 +930,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
/** Re-enter type parameters in current scope.
*/
void reenterParams(Tree[] params) {
- for (int i = 0; i < params.length; i++)
+ for (int i = 0; i < params.length; i++) {
context.scope.enter(params[i].symbol());
+ }
}
/** Re-enter value parameters in current scope.
@@ -1014,7 +1024,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
sym = sym1;
sym.flags |= (ACCESSED | SELECTOR);
- Tree qual = checkStable(deepCopy(lastimports.importPrefix()));
+ Tree qual = checkStable(duplicator.transform(lastimports.importPrefix()));
pre = qual.type;
//new TextTreePrinter().print(name + " => ").print(lastimports.tree).print("." + name).println().end();//DEBUG
tree = make.Select(tree.pos, qual, name);
@@ -1048,7 +1058,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
} else {
sym.flags |= (ACCESSED | SELECTOR);
Type symtype = qual.type.memberType(sym);
- //System.out.println(sym.name + ":" + symtype);//debug
+ //System.out.println(sym.name + ":" + symtype);//DEBUG
if (uninst.length != 0) {
switch (symtype) {
case PolyType(Symbol[] tparams, Type restype):
@@ -1156,7 +1166,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Tree[] parents1 = transformConstrInvocations(
templ.pos, templ.parents, false, Type.AnyType);
if (owner.kind != ERROR) {
- validateParentClasses(templ.parents, owner.info().parents());
+ validateParentClasses(
+ templ.parents, owner.info().parents(), owner.typeOfThis());
validateBaseTypes(owner);
}
pushContext(templ, owner, owner.members());
@@ -1358,12 +1369,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
* Insert `apply' function if needed.
*/
Tree transform(Tree tree, int mode, Type pt) {
- //new TextTreePrinter().print("transforming ").print(tree).println().end();//DEBUG
int savedMode = this.mode;
Type savedPt = this.pt;
this.mode = mode;
this.pt = pt;
Tree tree1 = adapt(transform(tree), mode, pt);
+
this.mode = savedMode;
this.pt = savedPt;
return tree1;
@@ -1562,11 +1573,16 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case ClassDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ):
pushContext(tree, sym.constructor(), new Scope(context.scope));
reenterParams(tparams);
- reenterParams(vparams);
Tree.TypeDef[] tparams1 = transform(tparams);
- Tree.ValDef[][] vparams1 = transform(vparams);
Tree tpe1 = transform(tpe);
+ reenterParams(vparams);
+ Tree.ValDef[][] vparams1 = transform(vparams);
Tree.Template templ1 = transformTemplate(templ, sym);
+ if ((sym.flags & ABSTRACTCLASS) == 0 &&
+ !sym.type().isSubType(sym.typeOfThis()))
+ error(sym.pos, sym +
+ " needs to be abstract; it does not conform to its self-type " +
+ sym.typeOfThis());
popContext();
return copy.ClassDef(tree, mods, name, tparams1, vparams1, tpe1, templ1)
.setType(definitions.UNIT_TYPE);
@@ -1592,10 +1608,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case DefDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs):
pushContext(tree, sym, new Scope(context.scope));
reenterParams(tparams);
- reenterParams(vparams);
Tree.TypeDef[] tparams1 = transform(tparams);
- Tree.ValDef[][] vparams1 = transform(vparams);
Tree tpe1 = transform(tpe, TYPEmode);
+ reenterParams(vparams);
+ Tree.ValDef[][] vparams1 = transform(vparams);
Tree rhs1 = rhs;
if (tpe1 == Tree.Empty) {
tpe1 = gen.mkType(rhs1.pos, rhs1.type.widen());
@@ -1612,7 +1628,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
pushContext(tree, sym, new Scope(context.scope));
reenterParams(tparams);
Tree.TypeDef[] tparams1 = transform(tparams);
- Tree rhs1 = transform(rhs, TYPEmode);
+ int mode = TYPEmode;
+ if (sym.kind == ALIAS) mode |= FUNmode;
+ Tree rhs1 = transform(rhs, mode);
popContext();
return copy.TypeDef(tree, mods, name, tparams1, rhs1)
.setType(definitions.UNIT_TYPE);
@@ -1642,6 +1660,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
.setType(tp);
case Visitor(Tree.CaseDef[] cases):
+ if (infer.isFullyDefined(pt)) {
+ Type pt1 = pt.baseType(definitions.PARTIALFUNCTION_CLASS);
+ if (pt1.symbol() == definitions.PARTIALFUNCTION_CLASS)
+ return transform(
+ desugarize.partialFunction(tree, pt1.typeArgs()));
+ }
return transform(desugarize.Visitor(tree));
case Assign(Apply(Tree funarray, Tree[] vparam), Tree rhs):
@@ -1685,13 +1709,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
copy.Template(templ, new Tree[]{parent1}, body)
.setType(parent1.type).setSymbol(Symbol.NONE);
Type owntype = parent1.type;
- if ((owntype.symbol().constructor().flags &
- ABSTRACTCLASS) != 0) {
- error(tree.pos, owntype.symbol() +
- " is abstract; cannot be instantiated");
- }
+ if ((owntype.symbol().constructor().flags & ABSTRACTCLASS) != 0)
+ checkInstantiatable(tree.pos, owntype);
return copy.New(tree, templ1)
- .setType(owntype);
+ .setType(owntype.instanceType());
} else {
pushContext(tree, context.owner, new Scope(context.scope));
Tree cd = make.ClassDef(
@@ -1718,7 +1739,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
while (it.hasNext()) {
Symbol sym1 = it.next();
Symbol basesym1 = base.lookupNonPrivate(sym1.name);
- if (basesym1.kind != NONE && !basesym1.info().isSameAs(sym1.info()))
+ if (basesym1.kind != NONE &&
+ !base.symbol().thisType().memberType(basesym1)
+ .isSameAs(sym1.type()))
refinement.enter(sym1);
}
if (refinement.elems == Scope.Entry.NONE &&
@@ -1806,14 +1829,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Symbol fsym = TreeInfo.methSymbol(tree1);
if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
fsym != null && (fsym.flags & CASE) != 0) {
- Symbol constr = fsym.type().resultType().symbol().constructor();
+ Symbol constr = fsym.owner().info()
+ .lookup(fsym.name.toTypeName()).constructor();
Template templ = make.Template(
tree1.pos,
new Tree[]{desugarize.toConstructor(tree1, constr)},
Tree.EMPTY_ARRAY);
templ.setSymbol(Symbol.NONE).setType(tree1.type);
return adapt(
- make.New(tree1.pos, templ).setType(tree1.type), mode, pt);
+ make.New(tree1.pos, templ).setType(tree1.type.instanceType()), mode, pt);
} else {
return tree1;
}
@@ -1919,8 +1943,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Tree tpe1 = transform(tpe, TYPEmode | FUNmode);
Tree[] args1 = transform(args, TYPEmode);
Type[] argtypes = Tree.typeOf(args);
- Symbol clazz = tpe1.type.unalias().symbol();
- Symbol[] tparams = clazz.typeParams();
+ Symbol[] tparams = tpe1.type.typeParams();
if (tpe1.type != Type.ErrorType) {
if (tparams.length != args.length) {
if (tparams.length == 0)
@@ -1968,7 +1991,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
}
}
- return error(tree, ex.msg);
+ throw ex;//debug
+ //return error(tree, ex.msg);
}
}
@@ -2005,6 +2029,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
this.c = context;
}
public void complete(Symbol sym) {
+ //System.out.println("completing " + sym);//debug
//if (sym.isConstructor()) sym.constructorClass().initialize();
//else if (sym.isModule()) sym.moduleClass().initialize();
defineSym(tree, u, i, c);
@@ -2019,7 +2044,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
super(tree);
}
public void complete(Symbol sym) {
- sym.setInfo(tree.symbol().constructor().type());
+ sym.setInfo(tree.symbol().constructor().type().instanceType());
}
}
}
diff --git a/sources/scalac/typechecker/DeSugarize.java b/sources/scalac/typechecker/DeSugarize.java
index 15c5713293..cc6654232f 100644
--- a/sources/scalac/typechecker/DeSugarize.java
+++ b/sources/scalac/typechecker/DeSugarize.java
@@ -5,7 +5,6 @@
** **
** $Id$
\* */
-
package scalac.typechecker;
import java.io.*;
@@ -49,6 +48,10 @@ public class DeSugarize implements Kinds, Modifiers {
*/
protected final FreshNameCreator freshNameCreator;
+ /** the tree duplicator
+ */
+ final Transformer duplicator;
+
/** the constructor
*/
public DeSugarize(Analyzer analyzer, Global global) {
@@ -58,9 +61,9 @@ public class DeSugarize implements Kinds, Modifiers {
this.gen = analyzer.gen;
this.infer = analyzer.infer;
this.freshNameCreator = global.freshNameCreator;
+ this.duplicator = analyzer.duplicator;
}
-
// Auxiliary definitions and functions -------------------------------------------
/** introduce fresh variable of the form "deS$56"
@@ -217,7 +220,83 @@ public class DeSugarize implements Kinds, Modifiers {
global.definitions.functionType(targs1, targs[targs1.length]));
print(tree, "postfun", result);
return result;
- } else return tree;
+ } else {
+ print(tree, "postfun", tree);
+ return tree;
+ }
+ }
+
+ /** Cases, Argtpe, Restpe ==>
+ * (new scala.PartialFunction[Argtpe, Restpe] {
+ * def apply(x: Argtpe): Restpe = x match {Cases}
+ * def isDefinedAt(x: Argtpe): scala.Boolean = x match {Cases'}
+ * }: scala.PartialFunction[Argtpe, +Restpe])
+ * WHERE
+ * case P1 if G1 => E1, ..., Pn if Gn => En) = Cases
+ * Cases' = case P1 if G1 => True, ..., Pn if Gn => True, _ => False
+ * Argtpe = targs[0]
+ * Restpe = targs[1]
+ */
+ public Tree partialFunction(Tree tree, Type[] targs) {
+ Type argtpe = targs[0];
+ Type restpe = targs[1].dropVariance();
+ Tree constr = make.TypeApply(tree.pos,
+ make.Select(tree.pos,
+ make.Ident(tree.pos, Names.scala),
+ Names.PartialFunction.toConstrName()),
+ new Tree[]{gen.mkType(tree.pos, argtpe), gen.mkType(tree.pos, restpe)});
+ Name x = getvar();
+ ValDef param = (ValDef) make.ValDef(
+ tree.pos, PARAM, x, gen.mkType(tree.pos, argtpe), Tree.Empty);
+ ValDef[][] vparams = new ValDef[][]{new ValDef[]{param}};
+ Tree body = make.Apply(tree.pos,
+ make.Select(tree.pos,
+ make.Ident(tree.pos, x), Names.match), new Tree[]{tree});
+ Tree applyDef = make.DefDef(
+ tree.pos, 0, Names.apply, Tree.ExtTypeDef.EMPTY_ARRAY, vparams,
+ gen.mkType(tree.pos, restpe), body);
+ Tree tree1 = isDefinedAtVisitor(tree);
+ Tree body1 = make.Apply(tree.pos,
+ make.Select(tree.pos,
+ make.Ident(tree.pos, x), Names.match), new Tree[]{tree1});
+ Tree isDefinedAtDef = make.DefDef(
+ tree.pos, 0, Names.isDefinedAt, Tree.ExtTypeDef.EMPTY_ARRAY,
+ duplicator.transform(vparams),
+ gen.mkType(tree.pos, global.definitions.BOOLEAN_TYPE), body1);
+ Tree newTree = make.New(tree.pos,
+ make.Template(
+ tree.pos, new Tree[]{constr}, new Tree[]{applyDef, isDefinedAtDef}));
+ Tree result = make.Typed(tree.pos,
+ tree,
+ gen.mkType(tree.pos,
+ global.definitions.partialFunctionType(targs[0], targs[1])));
+ print(tree, "partialfun", result);
+ return result;
+ }
+
+ private Tree isDefinedAtVisitor(Tree tree) {
+ switch (tree) {
+ case Visitor(CaseDef[] cases):
+ CaseDef[] cases1 = new CaseDef[cases.length + 1];
+ for (int i = 0; i < cases.length; i++) {
+ switch (cases[i]) {
+ case CaseDef(Tree pat, Tree guard, _):
+ cases1[i] = (CaseDef) make.CaseDef(cases[i].pos,
+ duplicator.transform(pat),
+ duplicator.transform(guard),
+ make.Select(tree.pos,
+ make.Ident(tree.pos, Names.scala), Names.True));
+ }
+ }
+ cases1[cases.length] = (CaseDef) make.CaseDef(tree.pos,
+ make.Ident(tree.pos, Names.WILDCARD),
+ Tree.Empty,
+ make.Select(tree.pos,
+ make.Ident(tree.pos, Names.scala), Names.False));
+ return make.Visitor(tree.pos, cases1);
+ default:
+ throw new ApplicationError("visitor expected", tree);
+ }
}
/** match => this.match
@@ -247,7 +326,7 @@ public class DeSugarize implements Kinds, Modifiers {
case Visitor(CaseDef[] cases):
Name x = getvar();
ValDef param = (ValDef) make.ValDef(
- tree.pos, 0, x, Tree.Empty, Tree.Empty);
+ tree.pos, PARAM, x, Tree.Empty, Tree.Empty);
Tree xuse = make.Ident(tree.pos, x);
// x.match {cases}
Tree body = make.Apply(tree.pos,
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index b45a9d3a2f..753c81986b 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -97,7 +97,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
case ValDef(_, _, _, _):
sym = stat.symbol();
}
- if (sym != null) {
+ if (sym != null && sym.isLocal()) {
scopes[level].enter(sym);
symIndex.put(sym, new Integer(index));
}
@@ -163,7 +163,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
Symbol sym = tree.symbol();
resultTree = transform(tree);
//todo: handle variables
- if (index <= maxindex[level]) {
+ if (sym.isLocal() && index <= maxindex[level]) {
if (Global.instance.debug)
System.out.println(refsym[level] + ":" + refsym[level].type());
unit.error(
@@ -189,7 +189,8 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
return copy.Block(tree, stats1);
case Ident(Name name):
Scope.Entry e = scopes[level].lookupEntry(name);
- if (tree.symbol() == e.sym) {
+ Symbol sym = tree.symbol();
+ if (sym.isLocal() && sym == e.sym) {
int i = level;
while (scopes[i] != e.owner) i--;
int symindex = ((Integer) symIndex.get(tree.symbol())).intValue();
diff --git a/sources/scalac/util/Name.java b/sources/scalac/util/Name.java
index 0c04fe2dcb..2522cb59f8 100644
--- a/sources/scalac/util/Name.java
+++ b/sources/scalac/util/Name.java
@@ -385,7 +385,7 @@ public final class Name {
/** is this operator left associative
*/
- public boolean leftAssoc() {
- return names[index] != ':';
+ public boolean isLeftAssoc() {
+ return names[index + len -1] != ':';
}
}
diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java
index ac41d1192b..54b0509f23 100644
--- a/sources/scalac/util/Names.java
+++ b/sources/scalac/util/Names.java
@@ -44,6 +44,7 @@ public class Names {
public static final Name Long = Name.fromString("Long");
public static final Name Nil = Name.fromString("Nil");
public static final Name Object = Name.fromString("Object");
+ public static final Name PartialFunction = Name.fromString("PartialFunction");
public static final Name Predef = Name.fromString("Predef");
public static final Name Seq = Name.fromString("Seq");
public static final Name Short = Name.fromString("Short");
@@ -61,6 +62,7 @@ public class Names {
public static final Name foreach = Name.fromString("foreach");
public static final Name hashCode = Name.fromString("hashCode");
public static final Name is = Name.fromString("is");
+ public static final Name isDefinedAt = Name.fromString("isDefinedAt");
public static final Name java = Name.fromString("java");
public static final Name java_lang = Name.fromString("java.lang");
public static final Name java_lang_Object = Name.fromString("java.lang.Object");
@@ -89,6 +91,7 @@ public class Names {
public static final Name scala_Long = Name.fromString("scala.Long");
public static final Name scala_Nil = Name.fromString("scala.Nil");
public static final Name scala_Object = Name.fromString("scala.Object");
+ public static final Name scala_PartialFunction = Name.fromString("scala.PartialFunction");
public static final Name scala_Predef = Name.fromString("scala.Predef");
public static final Name scala_Ref = Name.fromString("scala.Ref");
public static final Name scala_Seq = Name.fromString("scala.Seq");