diff options
Diffstat (limited to 'sources')
-rw-r--r-- | sources/examples/auction.scala | 6 | ||||
-rw-r--r-- | sources/scalac/ast/TreeGen.java | 2 | ||||
-rw-r--r-- | sources/scalac/symtab/EntryTags.java | 75 | ||||
-rw-r--r-- | sources/scalac/symtab/Symbol.java | 7 | ||||
-rw-r--r-- | sources/scalac/symtab/SymbolTablePrinter.java | 3 | ||||
-rw-r--r-- | sources/scalac/symtab/Type.java | 145 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/Pickle.java | 62 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/UnPickle.java | 54 | ||||
-rw-r--r-- | sources/scalac/transformer/Erasure.java | 3 | ||||
-rw-r--r-- | sources/scalac/transformer/UnCurry.java | 3 | ||||
-rw-r--r-- | sources/scalac/transformer/UnCurryPhase.java | 6 | ||||
-rw-r--r-- | sources/scalac/typechecker/Analyzer.java | 91 | ||||
-rw-r--r-- | sources/scalac/typechecker/Infer.java | 3 | ||||
-rw-r--r-- | sources/scalac/typechecker/RefCheck.java | 6 |
14 files changed, 385 insertions, 81 deletions
diff --git a/sources/examples/auction.scala b/sources/examples/auction.scala index 8e32831942..ecf121ef7d 100644 --- a/sources/examples/auction.scala +++ b/sources/examples/auction.scala @@ -3,6 +3,10 @@ package examples; import java.util.Date; import scala.concurrent._; +/** A simple demonstrator program implementing an online auction service + * The example uses the actor abstraction defined in the API of + * package scala.concurrent. + */ trait AuctionMessage; case class Offer(bid: int, client: Actor), // make a bid @@ -62,7 +66,7 @@ class Auction(seller: Actor, minBid: int, closing: Date) extends Actor { } } -////////////////////////// TEST ///////////////////////////////// +// ---- Test ------------------------------------------------------------- object testAuction { diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java index ebb6f29a61..c1e838f250 100644 --- a/sources/scalac/ast/TreeGen.java +++ b/sources/scalac/ast/TreeGen.java @@ -282,7 +282,7 @@ public class TreeGen implements Kinds, Modifiers, TypeTags { Tree id = mkRef(pos, pre1, sym); switch (sym.type()) { case MethodType(Symbol[] params, _): - assert params.length == 0 : sym; + assert params.length == 0 : pre; id = this.Apply(id, Tree.EMPTY_ARRAY); } return id; diff --git a/sources/scalac/symtab/EntryTags.java b/sources/scalac/symtab/EntryTags.java index 71df3f73ff..ade0cb60bd 100644 --- a/sources/scalac/symtab/EntryTags.java +++ b/sources/scalac/symtab/EntryTags.java @@ -15,24 +15,27 @@ public interface EntryTags { * Symtab = nentries_Nat {Entry} * Entry = 1 TERMNAME len_Nat NameInfo * | 2 TYPENAME len_Nat NameInfo - * | 3 NONEsym len_Nat - * | 4 TYPEsym len_Nat SymbolInfo lobound_Ref - * | 5 ALIASsym len_Nat SymbolInfo constrsym_Ref - * | 6 CLASSsym len_Nat SymbolInfo thistype_Ref constrsym_Ref - * | 7 VALsym len_Nat SymbolInfo [classsym_Ref] - * | 8 EXTref len_Nat name_Ref [owner_Ref] - * | 9 EXTMODCLASSref len_Nat name_Ref [owner_Ref] - * | 10 NOtpe len_Nat - * | 11 THIStpe len_Nat sym_Ref - * | 12 SINGLEtpe len_Nat type_Ref sym_Ref - * | 13 TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref} - * | 14 COMPOUNDtpe len_Nat classsym_Ref {tpe_Ref} - * | 15 METHODtpe len_Nat tpe_Ref {tpe_Ref} - * | 16 POLYTtpe len_Nat tpe_Ref {sym_Ref} - * | 17 OVERLOADEDtpe len_Nat {sym_Ref} {tpe_Ref} - * | 20 FLAGGEDtpe len_Nat flags_Nat tpe_Ref + * | 3 NUMBER lenNat NumInfo + * | 4 NONEsym len_Nat + * | 5 TYPEsym len_Nat SymbolInfo lobound_Ref + * | 6 ALIASsym len_Nat SymbolInfo constrsym_Ref + * | 7 CLASSsym len_Nat SymbolInfo thistype_Ref constrsym_Ref + * | 8 VALsym len_Nat SymbolInfo [classsym_Ref] + * | 9 EXTref len_Nat name_Ref [owner_Ref] + * | 10 EXTMODCLASSref len_Nat name_Ref [owner_Ref] + * | 11 NOtpe len_Nat + * | 12 THIStpe len_Nat sym_Ref + * | 13 SINGLEtpe len_Nat type_Ref sym_Ref + * | 14 CONSTANTtpe len_Nat type_Ref value_Ref + * | 15 TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref} + * | 16 COMPOUNDtpe len_Nat classsym_Ref {tpe_Ref} + * | 17 METHODtpe len_Nat tpe_Ref {tpe_Ref} + * | 18 POLYTtpe len_Nat tpe_Ref {sym_Ref} + * | 19 OVERLOADEDtpe len_Nat {sym_Ref} {tpe_Ref} + * | 22 FLAGGEDtpe len_Nat flags_Nat tpe_Ref * SymbolInfo = name_Ref owner_Ref flags_Nat info_Ref * NameInfo = <character sequence of length len_Nat in Utf8 format> + * NumInfo = <len_Nat-byte signed number in big endian format> * Ref = Nat * * len is remaining length after `len'. @@ -40,25 +43,27 @@ public interface EntryTags { int TERMname = 1, TYPEname = 2, - NONEsym = 3, - TYPEsym = 4, - ALIASsym = 5, - CLASSsym = 6, - VALsym = 7, - EXTref = 8, - EXTMODCLASSref = 9, - NOtpe = 10, - THIStpe = 11, - SINGLEtpe = 12, - TYPEREFtpe = 13, - COMPOUNDtpe = 14, - METHODtpe = 15, - POLYtpe = 16, - OVERLOADEDtpe = 17, - UNBOXEDtpe = 18, - UNBOXEDARRAYtpe = 19, - FLAGGEDtpe = 20, - ERRORtpe = 21; + NUMBER = 3, + NONEsym = 4, + TYPEsym = 5, + ALIASsym = 6, + CLASSsym = 7, + VALsym = 8, + EXTref = 9, + EXTMODCLASSref = 10, + NOtpe = 11, + THIStpe = 12, + SINGLEtpe = 13, + CONSTANTtpe = 14, + TYPEREFtpe = 15, + COMPOUNDtpe = 16, + METHODtpe = 17, + POLYtpe = 18, + OVERLOADEDtpe = 19, + UNBOXEDtpe = 20, + UNBOXEDARRAYtpe = 21, + FLAGGEDtpe = 22, + ERRORtpe = 23; int firstSymTag = NONEsym, lastSymTag = VALsym; int firstTypeTag = NOtpe, lastTypeTag = FLAGGEDtpe; diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index ea75fdbd52..7dd1823ad3 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -281,6 +281,13 @@ public abstract class Symbol implements Modifiers, Kinds { (flags & MUTABLE) == 0 && type().isObjectType()); } + /** Is this symbol final? + */ + public final boolean isFinal() { + return + (flags & (FINAL | PRIVATE)) != 0 || isLocal() || owner.isModuleClass(); + } + /** Does this symbol denote a variable? */ public final boolean isVariable() { return kind == VAL && (flags & MUTABLE) != 0; diff --git a/sources/scalac/symtab/SymbolTablePrinter.java b/sources/scalac/symtab/SymbolTablePrinter.java index a56a082d5d..c23a6107eb 100644 --- a/sources/scalac/symtab/SymbolTablePrinter.java +++ b/sources/scalac/symtab/SymbolTablePrinter.java @@ -526,6 +526,9 @@ public class SymbolTablePrinter { return this; case SingleType(Type pre, Symbol sym): return printPrefix(pre).printSymbolName(sym); + case ConstantType(Type base, Object value): + return printType(base) + .print("(").print(value.toString()).print(")"); case CompoundType(Type[] parts, Scope members): return printTypes(parts," with ").space() .printScope(members,true) diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index e574a35776..3635b51ca7 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -35,6 +35,17 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { assert this instanceof ExtSingleType; } + /** Type for a numeric or string constant. + */ + public case ConstantType(Type base, Object value) { + if (base.symbol() == Global.instance.definitions.BYTE_CLASS) + assert value instanceof Byte; + if (base.symbol() == Global.instance.definitions.CHAR_CLASS) + assert value instanceof Character; + if (base.symbol() == Global.instance.definitions.SHORT_CLASS) + assert value instanceof Short; + } + /** pre.sym[args] * sym represents a type * for example: scala.List[java.lang.String] is coded as @@ -136,6 +147,28 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } } + public static ConstantType constantType(Object value) { + return new ConstantType(value2type(value), value); + } + + private static Type value2type(Object value) { + if (value instanceof Character) + return Global.instance.definitions.CHAR_TYPE(); + else if (value instanceof Integer) + return Global.instance.definitions.INT_TYPE(); + else if (value instanceof Long) + return Global.instance.definitions.LONG_TYPE(); + else if (value instanceof Float) + return Global.instance.definitions.FLOAT_TYPE(); + else if (value instanceof Double) + return Global.instance.definitions.DOUBLE_TYPE(); + else if (value instanceof String) + return Global.instance.definitions.JAVA_STRING_TYPE(); + else if (value instanceof Boolean) + return Global.instance.definitions.BOOLEAN_TYPE(); + else throw new ApplicationError(); + } + public static Type singleTypeMethod(Type pre, Symbol sym) { Global global = Global.instance; if (global.currentPhase.id <= global.PHASE.UNCURRY.id()) @@ -242,6 +275,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return sym; case SingleType(_, Symbol sym): return sym; + case ConstantType(Type base, _): + return base.symbol(); case TypeVar(Type origin, _): return origin.symbol(); case CompoundType(_, _): @@ -282,6 +317,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return this; case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): return singleDeref().bound(); case TypeVar(Type origin, Constraint constr): if (constr.inst != NoType) return constr.inst.bound(); @@ -301,6 +337,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { case SingleType(Type pre, Symbol sym): // overridden in ExtSingleType throw new ApplicationError(); + case ConstantType(Type base, _): + return base; case TypeVar(Type origin, Constraint constr): if (constr.inst != NoType) return constr.inst.singleDeref(); else return this; @@ -317,6 +355,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { switch (tp) { case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): return tp.widen(); default: return tp; @@ -347,6 +386,18 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } } + /** If this type is a constant type, its underlying basetype; + * otherwise the type itself + */ + public Type deconst() { + switch (this) { + case ConstantType(Type base, _): + return base; + default: + return this; + } + } + /** If this type is a parameterless method, its underlying resulttype; * otherwise the type itself */ @@ -459,6 +510,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { switch (unalias()) { case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): return singleDeref().parents(); case TypeRef(Type pre, Symbol sym, Type[] args): if (sym.kind == CLASS) { @@ -587,6 +639,62 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return this; } + /** Numeric values + */ + public int intValue() { + switch (this) { + case ConstantType(_, Object value): + return toNumber(value).intValue(); + default: + throw new ApplicationError(); + } + } + public long longValue() { + switch (this) { + case ConstantType(_, Object value): + return toNumber(value).longValue(); + default: + throw new ApplicationError(); + } + } + public float floatValue() { + switch (this) { + case ConstantType(_, Object value): + return toNumber(value).floatValue(); + default: + throw new ApplicationError(); + } + } + public double doubleValue() { + switch (this) { + case ConstantType(_, Object value): + return toNumber(value).doubleValue(); + default: + throw new ApplicationError(); + } + } + public boolean booleanValue() { + switch (this) { + case ConstantType(_, Object value): + return ((Boolean)value).booleanValue(); + default: + throw new ApplicationError(); + } + } + public String stringValue() { + switch (this) { + case ConstantType(_, Object value): + return (String)value; + default: + throw new ApplicationError(); + } + } + private static Number toNumber(Object value) { + return (value instanceof Character) + ? new Integer(((Character)value).charValue()) + : (Number)value; + } + // Tests -------------------------------------------------------------------- /** Is this type a this type or singleton type? @@ -595,6 +703,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { switch (unalias()) { case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): return true; default: return false; @@ -624,6 +733,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { switch (unalias()) { case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): case CompoundType(_, _): case TypeRef(_, _, _): return true; @@ -675,7 +785,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return new Scope(); case TypeRef(_, Symbol sym, _): return sym.info().members(); - case SingleType(_, Symbol sym): + case SingleType(_, _): + case ConstantType(_, _): return singleDeref().members(); case CompoundType(Type[] basetypes, Scope members): return members; @@ -693,6 +804,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return Symbol.ERROR; case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): return singleDeref().lookup(name); case TypeRef(_, Symbol sym, _): return sym.info().lookup(name); @@ -722,6 +834,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return Symbol.ERROR; case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): return singleDeref().lookupNonPrivate(name); case TypeRef(_, Symbol sym, _): return sym.info().lookupNonPrivate(name, start); @@ -860,6 +973,10 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { Type pre1 = apply(pre); if (pre1 == pre) return tp; else return singleType(pre1, sym); + case ConstantType(Type base, Object value): + Type base1 = apply(base); + if (base1 == base) return tp; + else return new ConstantType(base1, value); case CompoundType(Type[] parts, Scope members): Type[] parts1 = map(parts); Scope members1 = map(members); @@ -1014,6 +1131,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): return singleDeref().baseType(clazz); case TypeRef(Type pre, Symbol sym, Type[] args): @@ -1687,9 +1805,11 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): switch (this) { case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): return this.isSameAs(that); } break; @@ -1795,6 +1915,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { case SingleType(_, _): if (this.singleDeref().isSubType(that)) return true; break; + case ConstantType(_, Object value): + if (this.singleDeref().isSubType(that)) return true; + break; case TypeVar(Type origin, Constraint constr): if (constr.inst != NoType) { return constr.inst.isSubType(that); @@ -1987,6 +2110,13 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } break; + case ConstantType(Type base, Object value): + switch (that) { + case ConstantType(Type base1, Object value1): + return base.isSameAs(base1) && value.equals(value1); + } + break; + case TypeRef(Type pre, Symbol sym, Type[] args): switch (that) { case TypeRef(Type pre1, Symbol sym1, Type[] args1): @@ -2560,6 +2690,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { break; case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): return Global.instance.definitions.ALL_TYPE(); } } @@ -2871,6 +3002,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { switch (this) { case ThisType(_): case SingleType(_, _): + case ConstantType(_, _): return singleDeref().erasure(); case TypeRef(Type pre, Symbol sym, Type[] args): switch (sym.kind) { @@ -2958,6 +3090,10 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return SINGLEtpe ^ (pre.hashCode() * 41) ^ (sym.hashCode() * (41*41)); + case ConstantType(Type base, Object value): + return CONSTANTtpe + ^ (base.hashCode() * 41) + ^ (value.hashCode() * (41*41)); case CompoundType(Type[] parts, Scope members): return symbol().hashCode(); //return COMPOUNDtpe @@ -3026,6 +3162,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return pre.equals(pre1) && sym == sym1; default: return false; } + case ConstantType(Type base, Object value): + switch (that) { + case ConstantType(Type base1, Object value1): + return base.equals(base1) && value.equals(value1); + default: return false; + } case CompoundType(Type[] parts, Scope members): switch (that) { case CompoundType(Type[] parts1, Scope members1): @@ -3194,6 +3336,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { case ThisType(Symbol sym): case TypeRef(Type pre, Symbol sym, Type[] args): case SingleType(Type pre, Symbol sym): + case ConstantType(Type base, Object value): case CompoundType(Type[] parts, Scope members): case MethodType(Symbol[] vparams, Type result): case PolyType(Symbol[] tparams, Type result): diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java index bdc552e507..871a417509 100644 --- a/sources/scalac/symtab/classfile/Pickle.java +++ b/sources/scalac/symtab/classfile/Pickle.java @@ -168,6 +168,10 @@ public class Pickle implements Kinds, Modifiers, EntryTags { putType(pre); putSymbol(sym); break; + case ConstantType(Type base, Object value): + putType(base); + putEntry(value); + break; case TypeRef(Type pre, Symbol sym, Type[] args): putType(pre); putSymbol(sym); @@ -258,6 +262,15 @@ public class Pickle implements Kinds, Modifiers, EntryTags { if (y != 0) patchNatPrefix(pos, y); } + /** Write a long number in signed big endian format, base 256. + */ + private void writeLong(long x) { + long y = x >> 8; + long z = x & 0xff; + if (-y != z >> 7) writeLong(y); + writeByte((int) z); + } + /** Write a reference to object, i.e., the object's number in the index. */ private void writeRef(Object ref) { @@ -281,6 +294,15 @@ public class Pickle implements Kinds, Modifiers, EntryTags { bp = bp + name.length(); } + /** Write a long number in big endian format, base 128. + * All but the last digits have bit 0x80 set. + */ + private void writeNumber(long x) { + writeByte(NUMBER); + writeByte(0); // space for length + writeLong(x); + } + /** Write a symbol entry. */ private void writeSymbol(Symbol sym) { @@ -367,6 +389,13 @@ public class Pickle implements Kinds, Modifiers, EntryTags { writeRef(sym); break; + case ConstantType(Type base, Object value): + writeByte(CONSTANTtpe); + writeByte(0); // space for length + writeRef(base); + writeRef(value); + break; + case TypeRef(Type pre, Symbol sym, Type[] args): writeByte(TYPEREFtpe); writeByte(0); // space for length @@ -425,11 +454,34 @@ public class Pickle implements Kinds, Modifiers, EntryTags { private void writeEntry(Object e) { int startpos = bp; - if (e instanceof Symbol) writeSymbol((Symbol) e); - else if (e instanceof Type) writeType((Type) e); - else if (e instanceof Name) writeName((Name) e); - else if (e instanceof FlagsAndType) writeFlagsAndType((FlagsAndType) e); - else throw new ApplicationError(); + if (e instanceof Symbol) + writeSymbol((Symbol) e); + else if (e instanceof Type) + writeType((Type) e); + else if (e instanceof Name) + writeName((Name) e); + else if (e instanceof FlagsAndType) + writeFlagsAndType((FlagsAndType) e); + else if (e instanceof String) + writeName(Name.fromString((String)e)); + else if (e instanceof Double) + writeNumber(Double.doubleToLongBits(((Double)e).doubleValue())); + else if (e instanceof Float) + writeNumber(Float.floatToIntBits(((Float)e).floatValue())); + else if (e instanceof Long) + writeNumber(((Long)e).longValue()); + else if (e instanceof Integer) + writeNumber(((Integer)e).intValue()); + else if (e instanceof Short) + writeNumber(((Short)e).intValue()); + else if (e instanceof Byte) + writeNumber(((Byte)e).intValue()); + else if (e instanceof Character) + writeNumber(((Character)e).charValue()); + else if (e instanceof Boolean) + writeNumber(((Boolean)e).booleanValue() ? 1 : 0); + else + throw new ApplicationError(e); patchNat(startpos + 1, bp - (startpos + 2)); } diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java index 482287fbb7..68c2a99177 100644 --- a/sources/scalac/symtab/classfile/UnPickle.java +++ b/sources/scalac/symtab/classfile/UnPickle.java @@ -17,7 +17,7 @@ import scalac.symtab.*; import Symbol.*; import Type.*; -public class UnPickle implements Kinds, Modifiers, EntryTags { +public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags { /*************************************************** * Symbol table attribute format: see EntryTags.java @@ -91,6 +91,15 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { return x; } + long readLong(int n) { + long x = 0; + for (int i = 0; i < n; i++) { + x = (x << 8) + (readByte() & 0xff); + } + int leading = 64 - (n * 8); + return x << leading >> leading; + } + boolean isTypeEntry(int i) { int tag = bytes[index[i]]; return (firstTypeTag <= tag && tag <= lastTypeTag); @@ -328,6 +337,11 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { case SINGLEtpe: tpe = Type.singleType(readTypeRef(), readSymbolRef()); break; + case CONSTANTtpe: + Type base = readTypeRef(); + Object value = readValueRef(base); + tpe = new Type.ConstantType(base, value); + break; case TYPEREFtpe: tpe = Type.TypeRef( readTypeRef(), readSymbolRef(), readTypeRefs(end)); @@ -436,6 +450,44 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { return flags; } + long getNumber(int n) { + int savedBp = bp; + bp = index[n]; + int tag = bytes[bp++]; + long x = readLong(readNat()); + bp = savedBp; + return x; + } + + long readNumberRef() { + return getNumber(readNat()); + } + + Object readValueRef(Type base) { + switch (base.unbox()) { + case UnboxedType(BYTE): + return new Byte((byte)readNumberRef()); + case UnboxedType(SHORT): + return new Short((short)readNumberRef()); + case UnboxedType(INT): + return new Integer((int)readNumberRef()); + case UnboxedType(CHAR): + return new Character((char)readNumberRef()); + case UnboxedType(LONG): + return new Long(readNumberRef()); + case UnboxedType(FLOAT): + return new Float(Float.intBitsToFloat((int)readNumberRef())); + case UnboxedType(DOUBLE): + return new Float(Double.longBitsToDouble(readNumberRef())); + case UnboxedType(BOOLEAN): + return new Boolean(readNumberRef() == 0 ? false : true); + case UnboxedType(STRING): + return readNameRef().toString(); + default: + return new ApplicationError("bad constant base type: " + base); + } + } + public static class BadSignature extends java.lang.Error { public BadSignature(UnPickle outer, String msg) { super("symbol data " + outer.sourceName + diff --git a/sources/scalac/transformer/Erasure.java b/sources/scalac/transformer/Erasure.java index 0b5b3b29d8..ae1a6ae658 100644 --- a/sources/scalac/transformer/Erasure.java +++ b/sources/scalac/transformer/Erasure.java @@ -232,7 +232,8 @@ public class Erasure extends Transformer implements Modifiers { return gen.Ident(tree.pos, symbol); case Literal(Object value): - return gen.mkLit(tree.pos, value); + return tree.setType(tree.type.erasure()); + //return gen.mkLit(tree.pos, value); case Block(_): case If(_, _, _): diff --git a/sources/scalac/transformer/UnCurry.java b/sources/scalac/transformer/UnCurry.java index 88d978fb43..32389d9841 100644 --- a/sources/scalac/transformer/UnCurry.java +++ b/sources/scalac/transformer/UnCurry.java @@ -113,7 +113,8 @@ public class UnCurry extends OwnerTransformer public Tree transform(Tree tree) { //new scalac.ast.printer.TextTreePrinter().print("uncurry: ").print(tree).println().end();//DEBUG //uncurry type and symbol - if (tree.type != null) tree.type = descr.uncurry(tree.type); + Type prevtype = tree.type; + if (prevtype != null) tree.type = descr.uncurry(prevtype); switch (tree) { case ClassDef(_, _, AbsTypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl): return copy.ClassDef( diff --git a/sources/scalac/transformer/UnCurryPhase.java b/sources/scalac/transformer/UnCurryPhase.java index e8bdc1b77e..3309bce67b 100644 --- a/sources/scalac/transformer/UnCurryPhase.java +++ b/sources/scalac/transformer/UnCurryPhase.java @@ -53,13 +53,13 @@ public class UnCurryPhase extends Phase implements Modifiers { else return Type.MethodType(params, newtp1); } case PolyType(Symbol[] tparams, Type tp1): + Type newtp1 = uncurry(tp1); switch (tp1) { case MethodType(_, _): - Type newtp1 = uncurry(tp1); if (newtp1 == tp1) return tp; else return Type.PolyType(tparams, newtp1); default: - Type newtp1 = Type.MethodType(Symbol.EMPTY_ARRAY, tp1); + newtp1 = Type.MethodType(Symbol.EMPTY_ARRAY, newtp1); if (tparams.length == 0) return newtp1; else return Type.PolyType(tparams, newtp1); } @@ -67,6 +67,8 @@ public class UnCurryPhase extends Phase implements Modifiers { return new Type.Map() { public Type apply(Type t) { return uncurry(t); } }.map(tp); + case ConstantType(Type base, _): + return base; default: return tp; } diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 5d96732ad0..b3cdccee72 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -29,20 +29,22 @@ import java.util.*; */ public class Analyzer extends Transformer implements Modifiers, Kinds { - private final Definitions definitions; + final Definitions definitions; private final DeSugarize desugarize; private final AnalyzerPhase descr; final Infer infer; + final ConstantFolder constfold; public Analyzer(Global global, AnalyzerPhase descr) { super(global); this.definitions = global.definitions; this.descr = descr; this.infer = new Infer(this); + this.constfold = new ConstantFolder(this); this.desugarize = new DeSugarize(this, global); } - private Unit unit; + Unit unit; private Context context; private Type pt; private int mode; @@ -595,17 +597,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { return fn.type == Type.ErrorType ? Type.ErrorType : Type.NoType; } - private Type value2Type(Object value) { - if (value instanceof Character) return definitions.CHAR_TYPE(); - else if (value instanceof Integer) return definitions.INT_TYPE(); - else if (value instanceof Long) return definitions.LONG_TYPE(); - else if (value instanceof Float) return definitions.FLOAT_TYPE(); - else if (value instanceof Double) return definitions.DOUBLE_TYPE(); - else if (value instanceof String) return definitions.JAVA_STRING_TYPE(); - else if (value instanceof Boolean) return definitions.BOOLEAN_TYPE(); - else throw new ApplicationError(); - } - private boolean isSetterMethod(Symbol sym) { return sym != null && !sym.isLocal() && @@ -1050,6 +1041,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } else { ((DefDef) tree).rhs = rhs = transform(rhs, EXPRmode); restype = rhs.type; + if (!sym.isFinal()) restype = restype.deconst(); // !!! restype = rhs.type.widen(); // !!! } restype = checkNoEscape(tpe.pos, restype); @@ -1080,6 +1072,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { ((ValDef) tree).rhs = rhs = transform(rhs, EXPRmode); } owntype = rhs.type; + if (sym.isVariable() || !sym.isFinal()) + owntype = owntype.deconst(); // !!! owntype = rhs.type.widen(); // !!! } popContext(); @@ -1188,10 +1182,18 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { this.context = curcontext; Type selftype = transform(tree, TYPEmode).type; - - sym.setInfo( - Type.compoundType( - new Type[]{selftype, clazz.type()}, Scope.EMPTY)); + switch (selftype) { + case CompoundType(Type[] parts, Scope members): + Type[] parts1 = new Type[parts.length + 1]; + System.arraycopy(parts, 0, parts1, 0, parts.length); + parts1[parts.length] = clazz.type(); + sym.setInfo(Type.compoundType(parts1, members)); + break; + default: + sym.setInfo( + Type.compoundType( + new Type[]{selftype, clazz.type()}, Scope.EMPTY)); + } this.unit = savedUnit; this.context= savedContext; @@ -1203,6 +1205,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { * context. */ Tree mkStable(Tree tree, Type pre, int mode, Type pt) { + switch (tree.type) { + case ConstantType(Type base, Object value): + return make.Literal(tree.pos, value).setType(tree.type); + } if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) && pre.isStable()) { Symbol sym = tree.symbol(); @@ -1362,8 +1368,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // this works as for superclass constructor calls the expected // type `pt' is always AnyType (see transformConstrInvocations). } - if (!(owntype instanceof Type.PolyType || - owntype.isSubType(pt))) { + if (!(owntype instanceof Type.PolyType || owntype.isSubType(pt))) { switch (tree) { case Literal(Object value): int n = Integer.MAX_VALUE; @@ -1371,15 +1376,19 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { n = ((Integer) value).intValue(); else if (value instanceof Character) n = ((Character) value).charValue(); + Object value1 = null; if (pt.symbol() == definitions.BYTE_CLASS && -128 <= n && n <= 127) - return copy.Literal(tree, new Byte((byte) n)).setType(pt); + value1 = new Byte((byte) n); else if (pt.symbol() == definitions.SHORT_CLASS && -32768 <= n && n <= 32767) - return copy.Literal(tree, new Short((short) n)).setType(pt); + value1 = new Short((short) n); else if (pt.symbol() == definitions.CHAR_CLASS && 0 <= n && n <= 65535) - return copy.Literal(tree, new Character((char) n)).setType(pt); + value1 = new Character((char) n); + if (value1 != null) + return make.Literal(tree.pos, value1) + .setType(Type.ConstantType(pt, value1)); } typeError(tree.pos, owntype, pt); Type.explainTypes(owntype, pt); @@ -1700,7 +1709,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (tparams.length == 0) { for (int i = 0; i < args.length; i++) { args[i] = transform(args[i], argMode, formals[i]); - argtypes[i] = args[i].type; + argtypes[i] = args[i].type.deconst(); } } else { // targs: the type arguments inferred from the prototype @@ -1724,7 +1733,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { : tparams[i].type(); for (int i = 0; i < args.length; i++) { - argtypes[i] = args[i].type; + argtypes[i] = args[i].type.deconst(); switch (argtypes[i]) { case PolyType(Symbol[] tparams1, Type restype1): argtypes[i] = infer.argumentTypeInstance( @@ -1757,14 +1766,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { case Type.ErrorType: for (int i = 0; i < args.length; i++) { args[i] = transform(args[i], argMode, Type.ErrorType); - argtypes[i] = args[i].type; + argtypes[i] = args[i].type.deconst(); } return argtypes; default: for (int i = 0; i < args.length; i++) { args[i] = transform(args[i], argMode, Type.AnyType); - argtypes[i] = args[i].type; + argtypes[i] = args[i].type.deconst(); } return argtypes; } @@ -2016,7 +2025,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if( name != Names.PATTERN_WILDCARD ) { //assert body.type != null; if( TreeInfo.isSequenceValued( body ) ) { - vble.setType( definitions.listType(pt) ); + vble.setType( definitions.LIST_TYPE(pt) ); } else { vble.setType( body.type ); } @@ -2213,6 +2222,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Tree[] args1 = transform(args, TYPEmode); Type[] argtypes = Tree.typeOf(args1); + // propagate errors in arguments + for (int i = 0; i < argtypes.length; i++) { + if (argtypes[i] == Type.ErrorType) { + return tree.setType(Type.ErrorType); + } + } + // resolve overloading switch (fn1.type) { case OverloadedType(Symbol[] alts, Type[] alttypes): @@ -2226,9 +2242,26 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // match against arguments switch (fn1.type) { case PolyType(Symbol[] tparams, Type restp): - if (tparams.length == argtypes.length) + if (tparams.length == argtypes.length) { + // constant fold asInstanceOf calls. + switch (fn1) { + case Select(Tree qual, Name name): + if (fn1.symbol() == definitions.ANY_AS && + qual.type instanceof Type.ConstantType) { + Type restp1 = constfold.foldAsInstanceOf( + tree.pos, + (Type.ConstantType)qual.type, + argtypes[0]); + switch (restp1) { + case ConstantType(_, Object value): + return make.Literal(tree.pos, value) + .setType(restp1); + } + } + } return copy.TypeApply(tree, fn1, args1) .setType(restp.subst(tparams, argtypes)); + } break; case ErrorType: return tree.setType(Type.ErrorType); @@ -2496,7 +2529,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } case Literal(Object value): - return tree.setType(value2Type(value)); + return tree.setType(Type.constantType(value)); case LabelDef(Name name, Ident[] params, Tree body): assert params.length == 0; diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java index 41f007059d..0ad12d6cd2 100644 --- a/sources/scalac/typechecker/Infer.java +++ b/sources/scalac/typechecker/Infer.java @@ -252,7 +252,8 @@ public class Infer implements Modifiers, Kinds { case ErrorType: case AnyType: case NoType: - case ThisType(Symbol sym): + case ThisType(_): + case ConstantType(_, _): return VARIANCES; case TypeRef(Type pre, Symbol sym, Type[] args): if (sym == tparam) return COVARIANT; diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java index a2b4cfe140..6bf3e9b0a5 100644 --- a/sources/scalac/typechecker/RefCheck.java +++ b/sources/scalac/typechecker/RefCheck.java @@ -842,16 +842,16 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { } } -// Type node eliminiation ------------------------------------------------------ +// Tree node simplification--------------------------------------------------- private Tree elimTypeNode(Tree tree) { if (tree.isType() && !tree.isMissing()) - return gen.mkType(tree.pos, tree.type); + return gen.mkType(tree.pos, tree.type.deconst()); else return tree; } -// Transformation --------------------------------------------------------------- +// Transformation ------------------------------------------------------------ public Tree[] transformStats(Tree[] stats) { pushLevel(); |