From 6749e5dd658522cb63600021a9ee5a86f911cfeb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 3 Mar 2003 14:33:53 +0000 Subject: *** empty log message *** --- sources/scalac/ast/TreeGen.java | 4 +- sources/scalac/ast/parser/Parser.java | 27 ++-- sources/scalac/symtab/Definitions.java | 61 +++++---- sources/scalac/symtab/Scope.java | 17 ++- sources/scalac/symtab/Symbol.java | 132 ++++++++++++++----- sources/scalac/symtab/Type.java | 58 ++++++--- .../scalac/symtab/classfile/AttributeParser.java | 2 +- .../scalac/symtab/classfile/ClassfileParser.java | 2 +- sources/scalac/transformer/LambdaLiftPhase.java | 2 +- sources/scalac/typechecker/Analyzer.java | 143 ++++++++++++--------- sources/scalac/typechecker/DeSugarize.java | 87 ++++++++++++- sources/scalac/typechecker/RefCheck.java | 7 +- sources/scalac/util/Name.java | 4 +- sources/scalac/util/Names.java | 3 + 14 files changed, 377 insertions(+), 172 deletions(-) (limited to 'sources/scalac') 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 ""; } } 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"); -- cgit v1.2.3