From 2521f5270d8599a6407588cd3ab92143c77bc827 Mon Sep 17 00:00:00 2001 From: Matthias Zenger Date: Tue, 11 Nov 2003 13:21:09 +0000 Subject: Added support for | in algebraic patterns; Added support for reading ConstantValue attributes; --- sources/scalac/symtab/Type.java | 4332 ++++++++++---------- .../scalac/symtab/classfile/AttributeParser.java | 56 +- sources/scalac/symtab/classfile/ConstantPool.java | 18 +- sources/scalac/transformer/TransMatch.java | 37 +- .../transformer/matching/AlgebraicMatcher.java | 4 + .../transformer/matching/PatternMatcher.java | 195 +- .../scalac/transformer/matching/PatternNode.java | 13 +- .../transformer/matching/PatternNodeCreator.java | 71 +- sources/scalac/util/AbstractFileReader.java | 26 +- 9 files changed, 2425 insertions(+), 2327 deletions(-) diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 2bde3ac1d6..b419a83e7c 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -32,18 +32,18 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { * sym represents a valueS */ public case SingleType(Type pre, Symbol sym) { - assert this instanceof ExtSingleType; + 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; + 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] @@ -51,26 +51,26 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { * for example: scala.List[java.lang.String] is coded as * * TypeRef( - * SingleType(ThisType(definitions.ROOT_CLASS), definitions.SCALA), - * , - * new Type[]{ - * TypeRef( - * SingleType( - * SingleType(ThisType(definitions.ROOT_CLASS), definitions.JAVA), - * definitions.LANG), - * definitions.STRING, - * new Type[]{})}). + * SingleType(ThisType(definitions.ROOT_CLASS), definitions.SCALA), + * , + * new Type[]{ + * TypeRef( + * SingleType( + * SingleType(ThisType(definitions.ROOT_CLASS), definitions.JAVA), + * definitions.LANG), + * definitions.STRING, + * new Type[]{})}). * */ public case TypeRef(Type pre, Symbol sym, Type[] args) { - assert pre.isLegalPrefix() || pre == ErrorType : pre + "#" + sym; - assert sym.kind == ERROR || sym.isType() : pre + " # " + sym; + assert pre.isLegalPrefix() || pre == ErrorType : pre + "#" + sym; + assert sym.kind == ERROR || sym.isType() : pre + " # " + sym; } /** parts_1 with ... with parts_n { members } */ public case CompoundType(Type[] parts, Scope members) { - assert this instanceof ExtCompoundType; + assert this instanceof ExtCompoundType; } /** synthetic type of a method def ...(vparams): result = ... @@ -140,39 +140,39 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { public static final Type[] EMPTY_ARRAY = new Type[0]; public static SingleType singleType(Type pre, Symbol sym) { - if (pre.isStable() || pre == ErrorType) { - return new ExtSingleType(pre, sym); - } else { - throw new Type.Malformed(pre, sym.nameString() + ".type"); - } + if (pre.isStable() || pre == ErrorType) { + return new ExtSingleType(pre, sym); + } else { + throw new Type.Malformed(pre, sym.nameString() + ".type"); + } } public static ConstantType constantType(Object value) { - return new ConstantType(value2type(value), 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(); + 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()) - return singleType(pre, sym); + return singleType(pre, sym); else if (global.currentPhase.id <= global.PHASE.ERASURE.id()) return sym.type().singleTypeMethod0(pre, sym); else @@ -186,75 +186,75 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { case MethodType(Symbol[] args, Type result): return MethodType(args, result.singleTypeMethod0(pre, sym)); default: - return singleType(pre, sym); + return singleType(pre, sym); } } public static TypeRef appliedType(Type tycon, Type[] args) { - switch (tycon) { - case TypeRef(Type pre, Symbol sym, Type[] args1): - if (args == args1) return (TypeRef)tycon; - else return TypeRef(pre, sym, args); - default: - throw new ApplicationError(); - } + switch (tycon) { + case TypeRef(Type pre, Symbol sym, Type[] args1): + if (args == args1) return (TypeRef)tycon; + else return TypeRef(pre, sym, args); + default: + throw new ApplicationError(); + } } public static CompoundType compoundType(Type[] parts, Scope members, - Symbol clazz) { - ExtCompoundType res = new ExtCompoundType(parts, members); - res.tsym = clazz; - return res; + Symbol clazz) { + ExtCompoundType res = new ExtCompoundType(parts, members); + res.tsym = clazz; + return res; } public static CompoundType compoundType(Type[] parts, Scope members) { - ExtCompoundType res = new ExtCompoundType(parts, members); - res.tsym = new ClassSymbol( - Position.FIRSTPOS, Names.COMPOUND_NAME.toTypeName(), Symbol.NONE, - SYNTHETIC | ABSTRACT); - res.tsym.setInfo(res); - res.tsym.primaryConstructor().setInfo( - Type.MethodType(Symbol.EMPTY_ARRAY, Type.TypeRef(res.tsym.owner().thisType(), res.tsym, Type.EMPTY_ARRAY))); - return res; + ExtCompoundType res = new ExtCompoundType(parts, members); + res.tsym = new ClassSymbol( + Position.FIRSTPOS, Names.COMPOUND_NAME.toTypeName(), Symbol.NONE, + SYNTHETIC | ABSTRACT); + res.tsym.setInfo(res); + res.tsym.primaryConstructor().setInfo( + Type.MethodType(Symbol.EMPTY_ARRAY, Type.TypeRef(res.tsym.owner().thisType(), res.tsym, Type.EMPTY_ARRAY))); + return res; } public static Type typeRef(Type pre, Symbol sym, Type[] args) { - if (pre.isLegalPrefix() || pre == ErrorType) - return TypeRef(pre, sym, args); - else if (sym.kind == ALIAS && sym.typeParams().length == args.length) - return sym.info().subst(sym.typeParams(), args) - .asSeenFrom(pre, sym.owner()); - else - throw new Type.Malformed(pre, sym.nameString()); + if (pre.isLegalPrefix() || pre == ErrorType) + return TypeRef(pre, sym, args); + else if (sym.kind == ALIAS && sym.typeParams().length == args.length) + return sym.info().subst(sym.typeParams(), args) + .asSeenFrom(pre, sym.owner()); + else + throw new Type.Malformed(pre, sym.nameString()); } static class ExtSingleType extends SingleType { - Type tp = null; - int definedId = -1; - ExtSingleType(Type pre, Symbol sym) { - super(pre, sym); - } - public Type singleDeref() { - if (definedId != Global.instance.currentPhase.id) { - definedId = Global.instance.currentPhase.id; - tp = pre.memberType(sym).resultType(); - } - return tp; - } + Type tp = null; + int definedId = -1; + ExtSingleType(Type pre, Symbol sym) { + super(pre, sym); + } + public Type singleDeref() { + if (definedId != Global.instance.currentPhase.id) { + definedId = Global.instance.currentPhase.id; + tp = pre.memberType(sym).resultType(); + } + return tp; + } } static class ExtCompoundType extends CompoundType { - Symbol tsym; - ExtCompoundType(Type[] parts, Scope members) { - super(parts, members); - } - public Symbol symbol() { - return tsym; - } - void validate() {//debug - for (Scope.SymbolIterator it = members.iterator(true); it.hasNext(); ) - assert it.next().owner() == tsym; - } + Symbol tsym; + ExtCompoundType(Type[] parts, Scope members) { + super(parts, members); + } + public Symbol symbol() { + return tsym; + } + void validate() {//debug + for (Scope.SymbolIterator it = members.iterator(true); it.hasNext(); ) + assert it.next().owner() == tsym; + } } void validate() {//debug @@ -268,60 +268,60 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { public Symbol symbol() { switch (this) { case ErrorType: - return Symbol.ERROR; - case ThisType(Symbol sym): - return sym; + return Symbol.ERROR; + case ThisType(Symbol sym): + return sym; case TypeRef(_, Symbol sym, _): - return sym; - case SingleType(_, Symbol sym): - return sym; - case ConstantType(Type base, _): - return base.symbol(); - case TypeVar(Type origin, _): - return origin.symbol(); - case CompoundType(_, _): - // overridden in ExtCompoundType - throw new ApplicationError(); + return sym; + case SingleType(_, Symbol sym): + return sym; + case ConstantType(Type base, _): + return base.symbol(); + case TypeVar(Type origin, _): + return origin.symbol(); + case CompoundType(_, _): + // overridden in ExtCompoundType + throw new ApplicationError(); default: - return Symbol.NONE; - } + return Symbol.NONE; + } } public static Symbol[] symbol(Type[] tps) { - Symbol[] syms = new Symbol[tps.length]; - for (int i = 0; i < syms.length; i++) - syms[i] = tps[i].symbol(); - return syms; + Symbol[] syms = new Symbol[tps.length]; + for (int i = 0; i < syms.length; i++) + syms[i] = tps[i].symbol(); + return syms; } /** If this is a reference to a type constructor, add its * type parameters as arguments */ public Type withDefaultArgs() { - switch (this) { - case TypeRef(Type pre, Symbol sym, Type[] args): - if (args.length == 0 && sym.typeParams().length != 0) - return TypeRef(pre, sym, Symbol.type(sym.typeParams())); - } - return this; + switch (this) { + case TypeRef(Type pre, Symbol sym, Type[] args): + if (args.length == 0 && sym.typeParams().length != 0) + return TypeRef(pre, sym, Symbol.type(sym.typeParams())); + } + return this; } /** The upper bound of this type. Returns always a TypeRef whose * symbol is a class. */ public Type bound() { - switch (unalias()) { + switch (unalias()) { case TypeRef(Type pre, Symbol sym, _): if (sym.kind == TYPE) return pre.memberInfo(sym).bound(); assert sym.isClass() : Debug.show(sym) + " -- " + this; return this; - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): return singleDeref().bound(); - case TypeVar(Type origin, Constraint constr): - if (constr.inst != NoType) return constr.inst.bound(); - else return this; + case TypeVar(Type origin, Constraint constr): + if (constr.inst != NoType) return constr.inst.bound(); + else return this; default: throw Debug.abort("illegal case", this); } @@ -331,197 +331,197 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { * otherwise the type itself. */ public Type singleDeref() { - switch (this) { - case ThisType(Symbol sym): - return sym.typeOfThis(); - 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; - default: - return this; - } + switch (this) { + case ThisType(Symbol sym): + return sym.typeOfThis(); + 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; + default: + return this; + } } /** If this type is a thistype or singleton type, its underlying object type, * otherwise the type itself. */ public Type widen() { - Type tp = singleDeref(); - switch (tp) { - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - return tp.widen(); - default: - return tp; - } + Type tp = singleDeref(); + switch (tp) { + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + return tp.widen(); + default: + return tp; + } } private static Map widenMap = new Map() { - public Type apply(Type t) { - return t.widen(); - } - }; + public Type apply(Type t) { + return t.widen(); + } + }; public static Type[] widen(Type[] tps) { - return widenMap.map(tps); + return widenMap.map(tps); } /** The thistype or singleton type corresponding to values of this type. */ public Type narrow() { - switch (unalias()) { - case TypeRef(Type pre, Symbol sym, Type[] args): - if (sym.kind == CLASS) return sym.thisType(); - else return ThisType(sym); - case CompoundType(_, _): - return symbol().thisType(); - default: - return this; - } + switch (unalias()) { + case TypeRef(Type pre, Symbol sym, Type[] args): + if (sym.kind == CLASS) return sym.thisType(); + else return ThisType(sym); + case CompoundType(_, _): + return symbol().thisType(); + default: + return this; + } } /** 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; - } + 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 */ public Type derefDef() { - switch (this) { - case PolyType(Symbol[] tparams, Type restp): - if (tparams.length == 0) return restp; - } - return this; + switch (this) { + case PolyType(Symbol[] tparams, Type restp): + if (tparams.length == 0) return restp; + } + return this; } /** The lower approximation of this type (which must be a typeref) */ public Type loBound() { - switch (unalias()) { - case TypeRef(Type pre, Symbol sym, Type[] args): - Type lb = Global.instance.definitions.ALL_TYPE(); - if (sym.kind == TYPE) { - lb = pre.memberLoBound(sym); - } - if (lb.symbol() == Global.instance.definitions.ALL_CLASS && - this.symbol() != Global.instance.definitions.ALL_CLASS && - this.isSubType(Global.instance.definitions.ANYREF_TYPE())) { - lb = Global.instance.definitions.ALLREF_TYPE(); - } - return lb; - default: - throw new ApplicationError(); - } + switch (unalias()) { + case TypeRef(Type pre, Symbol sym, Type[] args): + Type lb = Global.instance.definitions.ALL_TYPE(); + if (sym.kind == TYPE) { + lb = pre.memberLoBound(sym); + } + if (lb.symbol() == Global.instance.definitions.ALL_CLASS && + this.symbol() != Global.instance.definitions.ALL_CLASS && + this.isSubType(Global.instance.definitions.ANYREF_TYPE())) { + lb = Global.instance.definitions.ALLREF_TYPE(); + } + return lb; + default: + throw new ApplicationError(); + } } /** If this is a this-type, named-type, applied type or single-type, its prefix, * otherwise NoType. */ public Type prefix() { - switch (this) { - case ThisType(Symbol sym): return sym.owner().thisType(); + switch (this) { + case ThisType(Symbol sym): return sym.owner().thisType(); case TypeRef(Type pre, _, _): return pre; case SingleType(Type pre, _): return pre; - case TypeVar(Type origin, Constraint constr): - if (constr.inst != NoType) return constr.inst.prefix(); - else return NoType; - default: return NoType; - } + case TypeVar(Type origin, Constraint constr): + if (constr.inst != NoType) return constr.inst.prefix(); + else return NoType; + default: return NoType; + } } /** Get all type arguments of this type. */ public Type[] typeArgs() { - switch (unalias()) { - case TypeRef(_, _, Type[] args): - return args; - default: - return Type.EMPTY_ARRAY; - } + switch (unalias()) { + case TypeRef(_, _, Type[] args): + return args; + default: + return Type.EMPTY_ARRAY; + } } /** Get type of `this' symbol corresponding to this type, extend * homomorphically to function types and poly types. */ public Type instanceType() { - switch (unalias()) { - case TypeRef(Type pre, Symbol sym, Type[] args): - if (sym != sym.thisSym()) - return sym.typeOfThis() - .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; + switch (unalias()) { + case TypeRef(Type pre, Symbol sym, Type[] args): + if (sym != sym.thisSym()) + return sym.typeOfThis() + .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() { - Type result = unalias(0);//debug - //if (this != result) System.out.println(this + " ==> " + result);//DEBUG - return result; + Type result = unalias(0);//debug + //if (this != result) System.out.println(this + " ==> " + result);//DEBUG + return result; } private Type unalias(int n) { - if (n == 100) - throw new Type.Error("alias chain too long (recursive type alias?): " + this); - switch (this) { + if (n == 100) + throw new Type.Error("alias chain too long (recursive type alias?): " + this); + switch (this) { case TypeRef(Type pre, Symbol sym, Type[] args): - if (sym.kind == ALIAS && sym.typeParams().length == args.length) - return sym.info().subst(sym.typeParams(), args) - .asSeenFrom(pre, sym.owner()).unalias(n + 1); - break; - case TypeVar(Type origin, Constraint constr): - if (constr.inst != NoType) return constr.inst.unalias(n + 1); - else return this; - } - return this; + if (sym.kind == ALIAS && sym.typeParams().length == args.length) + return sym.info().subst(sym.typeParams(), args) + .asSeenFrom(pre, sym.owner()).unalias(n + 1); + break; + case TypeVar(Type origin, Constraint constr): + if (constr.inst != NoType) return constr.inst.unalias(n + 1); + else return this; + } + return this; } /** The (prefix/argument-adapted) parents of this type. */ public Type[] parents() { - switch (unalias()) { - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - return singleDeref().parents(); - case TypeRef(Type pre, Symbol sym, Type[] args): - if (sym.kind == CLASS) { - assert sym.typeParams().length == args.length : sym + " " + ArrayApply.toString(args) + " " + sym.primaryConstructor().info();//debug - return subst(asSeenFrom(sym.info().parents(), pre, sym.owner()), - sym.typeParams(), args); - } else { - return new Type[]{sym.info().asSeenFrom(pre, sym.owner())}; - } + switch (unalias()) { + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + return singleDeref().parents(); + case TypeRef(Type pre, Symbol sym, Type[] args): + if (sym.kind == CLASS) { + assert sym.typeParams().length == args.length : sym + " " + ArrayApply.toString(args) + " " + sym.primaryConstructor().info();//debug + return subst(asSeenFrom(sym.info().parents(), pre, sym.owner()), + sym.typeParams(), args); + } else { + return new Type[]{sym.info().asSeenFrom(pre, sym.owner())}; + } case CompoundType(Type[] parts, _): - return parts; + return parts; default: return Type.EMPTY_ARRAY; } @@ -532,16 +532,16 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { */ public Symbol[] typeParams() { switch (this) { - case PolyType(Symbol[] tparams, _): - return tparams; + case PolyType(Symbol[] tparams, _): + return tparams; case MethodType(Symbol[] vparams, _): return Symbol.EMPTY_ARRAY; - case TypeRef(_, Symbol sym, Type[] args): - if (args.length == 0) return sym.typeParams(); - else return Symbol.EMPTY_ARRAY; + case TypeRef(_, Symbol sym, Type[] args): + if (args.length == 0) return sym.typeParams(); + else return Symbol.EMPTY_ARRAY; default: return Symbol.EMPTY_ARRAY; - } + } } /** Get value parameters of method type (a PolyType or MethodType) @@ -552,14 +552,14 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } private Symbol[] valueParams(boolean ok) { switch (this) { - case PolyType(_, Type result): - return result.valueParams(true); + case PolyType(_, Type result): + return result.valueParams(true); case MethodType(Symbol[] vparams, _): return vparams; default: if (ok) return Symbol.EMPTY_ARRAY; throw Debug.abort("illegal case", this); - } + } } /** If this type is a (possibly polymorphic) method type, its result type @@ -567,38 +567,38 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { * otherwise the type itself. */ public Type resultType() { - switch (this) { - case PolyType(_, Type tpe): - return tpe.resultType(); - case MethodType(_, Type tpe): - return tpe.resultType(); - default: - return this; - } + switch (this) { + case PolyType(_, Type tpe): + return tpe.resultType(); + case MethodType(_, Type tpe): + return tpe.resultType(); + default: + return this; + } } /** The number of value parameter sections of this type. */ public int paramSectionCount() { - switch (this) { - case PolyType(_, Type restpe): - return restpe.paramSectionCount(); - case MethodType(_, Type restpe): - return restpe.paramSectionCount() + 1; - default: return 0; - } + switch (this) { + case PolyType(_, Type restpe): + return restpe.paramSectionCount(); + case MethodType(_, Type restpe): + return restpe.paramSectionCount() + 1; + default: return 0; + } } /** The first parameter section of this type. */ public Symbol[] firstParams() { - switch (this) { - case PolyType(_, Type restpe): - return restpe.firstParams(); - case MethodType(Symbol[] params, _): - return params; - default: return Symbol.EMPTY_ARRAY; - } + switch (this) { + case PolyType(_, Type restpe): + return restpe.firstParams(); + case MethodType(Symbol[] params, _): + return params; + default: return Symbol.EMPTY_ARRAY; + } } /** If this type is overloaded, its alternative types, @@ -607,10 +607,10 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { public Type[] alternativeTypes() { switch (this) { case OverloadedType(_, Type[] alttypes): - return alttypes; - default: - return new Type[]{this}; - } + return alttypes; + default: + return new Type[]{this}; + } } /** If this type is overloaded, its alternative symbols, @@ -619,80 +619,80 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { public Symbol[] alternativeSymbols() { switch (this) { case OverloadedType(Symbol[] alts, _): - return alts; - default: - return Symbol.EMPTY_ARRAY; - } + return alts; + default: + return Symbol.EMPTY_ARRAY; + } } /** If type is a this type of a module class, transform to singletype of * module. */ public Type expandModuleThis() { - switch (this) { - case ThisType(Symbol sym): - if ((sym.flags & MODUL) != 0 && sym.module() != Symbol.NONE) { - return singleType( - sym.owner().thisType().expandModuleThis(), sym.module()); - } - } - return this; + switch (this) { + case ThisType(Symbol sym): + if ((sym.flags & MODUL) != 0 && sym.module() != Symbol.NONE) { + return singleType( + sym.owner().thisType().expandModuleThis(), sym.module()); + } + } + return this; } /** Numeric values */ public int intValue() { - switch (this) { - case ConstantType(_, Object value): - return toNumber(value).intValue(); - default: - throw new ApplicationError(); - } + 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(); - } + 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(); - } + 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(); - } + 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(); - } + switch (this) { + case ConstantType(_, Object value): + return ((Boolean)value).booleanValue(); + default: + throw new ApplicationError(); + } } public String stringValue() { - switch (this) { - case ConstantType(_, Object value): - return value.toString(); - default: - throw new ApplicationError(); - } + switch (this) { + case ConstantType(_, Object value): + return value.toString(); + default: + throw new ApplicationError(); + } } private static Number toNumber(Object value) { - return (value instanceof Character) - ? new Integer(((Character)value).charValue()) - : (Number)value; + return (value instanceof Character) + ? new Integer(((Character)value).charValue()) + : (Number)value; } // Tests -------------------------------------------------------------------- @@ -700,78 +700,78 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { /** Is this type a this type or singleton type? */ public boolean isStable() { - switch (unalias()) { - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - return true; - default: - return false; - } + switch (unalias()) { + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + return true; + default: + return false; + } } /** Is this type a legal prefix? */ public boolean isLegalPrefix() { - switch (unalias()) { - case ThisType(_): - case SingleType(_, _): - return true; - case TypeRef(_, Symbol sym, _): - return sym.kind == CLASS && - ((sym.flags & JAVA) != 0 || - (sym.flags & (TRAIT | ABSTRACT)) == 0); - default: - return false; - } + switch (unalias()) { + case ThisType(_): + case SingleType(_, _): + return true; + case TypeRef(_, Symbol sym, _): + return sym.kind == CLASS && + ((sym.flags & JAVA) != 0 || + (sym.flags & (TRAIT | ABSTRACT)) == 0); + default: + return false; + } } /** Is this type a reference to an object type? * todo: replace by this.isSubType(global.definitions.ANY_TYPE())? */ public boolean isObjectType() { - switch (unalias()) { - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - case CompoundType(_, _): - case TypeRef(_, _, _): - return true; - default: - return false; - } + switch (unalias()) { + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + case CompoundType(_, _): + case TypeRef(_, _, _): + return true; + default: + return false; + } } /** Is this type of the form scala.FunctionN[T_1, ..., T_n, +T] or * scala.Object with scala.FunctionN[T_1, ..., T_n, +T]? */ public boolean isFunctionType() { - switch (this) { - case TypeRef(Type pre, Symbol sym, Type[] args): - return sym.fullName().startsWith(Names.scala_Function) && - args.length > 0; - case CompoundType(Type[] parents, Scope members): - return members.isEmpty() && - parents.length == 2 && - parents[0].symbol().fullName() == Names.scala_Object && - parents[1].isFunctionType(); - } - return false; + switch (this) { + case TypeRef(Type pre, Symbol sym, Type[] args): + return sym.fullName().startsWith(Names.scala_Function) && + args.length > 0; + case CompoundType(Type[] parents, Scope members): + return members.isEmpty() && + parents.length == 2 && + parents[0].symbol().fullName() == Names.scala_Object && + parents[1].isFunctionType(); + } + return false; } /** Is this a polymorphic method type? */ public boolean isPolymorphic() { - return typeParams().length > 0; + return typeParams().length > 0; } /** Is this a parameterized or polymorphic method type? */ public boolean isParameterized() { - switch (this) { - case MethodType(_, _): return true; - default: return isPolymorphic(); - } + switch (this) { + case MethodType(_, _): return true; + default: return isPolymorphic(); + } } // Members and Lookup ------------------------------------------------------- @@ -781,17 +781,17 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { */ public Scope members() { switch (this) { - case ErrorType: - return new Scope(); - case TypeRef(_, Symbol sym, _): - return sym.info().members(); - case SingleType(_, _): - case ConstantType(_, _): - return singleDeref().members(); - case CompoundType(Type[] basetypes, Scope members): - return members; + case ErrorType: + return new Scope(); + case TypeRef(_, Symbol sym, _): + return sym.info().members(); + case SingleType(_, _): + case ConstantType(_, _): + return singleDeref().members(); + case CompoundType(Type[] basetypes, Scope members): + return members; default: - return Scope.EMPTY; + return Scope.EMPTY; } } @@ -800,28 +800,28 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { */ public Symbol lookup(Name name) { switch (this) { - case ErrorType: - return Symbol.ERROR; - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - return singleDeref().lookup(name); - case TypeRef(_, Symbol sym, _): - return sym.info().lookup(name); - case CompoundType(Type[] parts, Scope members): - Symbol sym = members.lookup(name); - if (sym.kind != NONE) return sym; - else return lookupNonPrivate(name); + case ErrorType: + return Symbol.ERROR; + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + return singleDeref().lookup(name); + case TypeRef(_, Symbol sym, _): + return sym.info().lookup(name); + case CompoundType(Type[] parts, Scope members): + Symbol sym = members.lookup(name); + if (sym.kind != NONE) return sym; + else return lookupNonPrivate(name); default: - return Symbol.NONE; - } + return Symbol.NONE; + } } /** Lookup non-private symbol with given name among all local and * inherited members of this type; return Symbol.NONE if not found. */ public Symbol lookupNonPrivate(Name name) { - return lookupNonPrivate(name, 0); + return lookupNonPrivate(name, 0); } /** Same as before, but with additional parameter `start'. @@ -830,35 +830,35 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { */ private Symbol lookupNonPrivate(Name name, int start) { switch (this) { - case ErrorType: - return Symbol.ERROR; - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - return singleDeref().lookupNonPrivate(name); - case TypeRef(_, Symbol sym, _): - return sym.info().lookupNonPrivate(name, start); - case CompoundType(Type[] parts, Scope members): - Symbol sym = members.lookup(name); - if (sym.kind != NONE && (sym.flags & PRIVATE) == 0) - return sym; - - // search base types in reverse; non-abstract members - // take precedence over abstract ones. - int i = parts.length; - sym = Symbol.NONE; - while (i > start && (sym.kind == NONE || (sym.flags & DEFERRED) != 0)) { - i--; - Symbol sym1 = parts[i].lookupNonPrivate(name, i == 0 ? 0 : 1); - if (sym1.kind != NONE && - (sym1.flags & PRIVATE) == 0 && - (sym.kind == NONE || (sym1.flags & DEFERRED) == 0)) - sym = sym1; - } - return sym; + case ErrorType: + return Symbol.ERROR; + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + return singleDeref().lookupNonPrivate(name); + case TypeRef(_, Symbol sym, _): + return sym.info().lookupNonPrivate(name, start); + case CompoundType(Type[] parts, Scope members): + Symbol sym = members.lookup(name); + if (sym.kind != NONE && (sym.flags & PRIVATE) == 0) + return sym; + + // search base types in reverse; non-abstract members + // take precedence over abstract ones. + int i = parts.length; + sym = Symbol.NONE; + while (i > start && (sym.kind == NONE || (sym.flags & DEFERRED) != 0)) { + i--; + Symbol sym1 = parts[i].lookupNonPrivate(name, i == 0 ? 0 : 1); + if (sym1.kind != NONE && + (sym1.flags & PRIVATE) == 0 && + (sym.kind == NONE || (sym1.flags & DEFERRED) == 0)) + sym = sym1; + } + return sym; default: - return Symbol.NONE; - } + return Symbol.NONE; + } } /** @@ -900,27 +900,27 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { // Set Owner ------------------------------------------------------------------ public Type setOwner(Symbol owner) { - switch (this) { - case PolyType(Symbol[] tparams, Type restpe): - Type restpe1 = restpe.setOwner(owner); - if (restpe1 == restpe) return this; - else return Type.PolyType(tparams, restpe1); - case MethodType(Symbol[] params, Type restpe): - Symbol[] params1 = params; - if (params.length > 0 && - params[0].owner() != owner && params[0].owner() != Symbol.NONE) { - params1 = new Symbol[params.length]; - for (int i = 0; i < params.length; i++) - params1[i] = params[i].cloneSymbol(); - } - for (int i = 0; i < params.length; i++) - params1[i].setOwner(owner); - Type restpe1 = restpe.setOwner(owner); - if (params1 == params && restpe1 == restpe) return this; - else return Type.MethodType(params1, restpe1); - default: - return this; - } + switch (this) { + case PolyType(Symbol[] tparams, Type restpe): + Type restpe1 = restpe.setOwner(owner); + if (restpe1 == restpe) return this; + else return Type.PolyType(tparams, restpe1); + case MethodType(Symbol[] params, Type restpe): + Symbol[] params1 = params; + if (params.length > 0 && + params[0].owner() != owner && params[0].owner() != Symbol.NONE) { + params1 = new Symbol[params.length]; + for (int i = 0; i < params.length; i++) + params1[i] = params[i].cloneSymbol(); + } + for (int i = 0; i < params.length; i++) + params1[i].setOwner(owner); + Type restpe1 = restpe.setOwner(owner); + if (params1 == params && restpe1 == restpe) return this; + else return Type.MethodType(params1, restpe1); + default: + return this; + } } // Maps -------------------------------------------------------------------------- @@ -929,7 +929,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { */ public abstract static class Map { - public abstract Type apply(Type t); + public abstract Type apply(Type t); /** * This method assumes that all symbols in MethodTypes and @@ -953,153 +953,153 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } } - /** Apply map to all top-level components of this type. - */ - public Type map(Type tp) { - switch (tp) { - case ErrorType: - case AnyType: - case NoType: - case UnboxedType(_): - case TypeVar(_, _): - case ThisType(_): - return tp; - case TypeRef(Type pre, Symbol sym, Type[] args): - Type pre1 = apply(pre); - Type[] args1 = map(args); - if (pre1 == pre && args1 == args) return tp; - else return typeRef(pre1, sym, args1); - case SingleType(Type pre, Symbol sym): - 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); - if (parts1 == parts && members1 == members) { - return tp; - } else if (members1 == members && !tp.symbol().isCompoundSym()) { - return compoundType(parts1, members, tp.symbol()); - } else { - Scope members2 = new Scope(); - //Type tp1 = compoundType(parts1, members2); - Type tp1 = (tp.symbol().isCompoundSym()) ? compoundType(parts1, members2) - : compoundType(parts1, members2, tp.symbol()); - Symbol[] syms1 = members1.elements(); - Symbol[] syms2 = new Symbol[syms1.length]; - for (int i = 0; i < syms2.length; i++) { - syms2[i] = syms1[i].cloneSymbol(tp1.symbol()); - } - for (int i = 0; i < syms2.length; i++) { - syms2[i].setInfo(syms1[i].info().subst(syms1, syms2)); - if (syms2[i].kind == TYPE) - syms2[i].setLoBound(syms1[i].loBound().subst(syms1, syms2)); - } - for (int i = 0; i < syms2.length; i++) { - members2.enter(syms2[i]); - } - return tp1; - } - - case MethodType(Symbol[] vparams, Type result): - Symbol[] vparams1 = map(vparams); - Type result1 = apply(result); - if (vparams1 == vparams && result1 == result) return tp; - else return MethodType(vparams1, result1); - case PolyType(Symbol[] tparams, Type result): - Symbol[] tparams1 = map(tparams); - Type result1 = apply(result); - if (tparams1 != tparams) result1 = result1.subst(tparams, tparams1); - if (tparams1 == tparams && result1 == result) return tp; - else return PolyType(tparams1, result1); - case OverloadedType(Symbol[] alts, Type[] alttypes): - Type[] alttypes1 = map(alttypes); - if (alttypes1 == alttypes) return tp; - else return OverloadedType(alts, alttypes1); - case UnboxedArrayType(Type elemtp): - Type elemtp1 = apply(elemtp); - if (elemtp1 == elemtp) return tp; - else return UnboxedArrayType(elemtp1); - default: - throw new ApplicationError(tp + " " + tp.symbol()); - } - } - - public final Symbol map(Symbol sym) { + /** Apply map to all top-level components of this type. + */ + public Type map(Type tp) { + switch (tp) { + case ErrorType: + case AnyType: + case NoType: + case UnboxedType(_): + case TypeVar(_, _): + case ThisType(_): + return tp; + case TypeRef(Type pre, Symbol sym, Type[] args): + Type pre1 = apply(pre); + Type[] args1 = map(args); + if (pre1 == pre && args1 == args) return tp; + else return typeRef(pre1, sym, args1); + case SingleType(Type pre, Symbol sym): + 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); + if (parts1 == parts && members1 == members) { + return tp; + } else if (members1 == members && !tp.symbol().isCompoundSym()) { + return compoundType(parts1, members, tp.symbol()); + } else { + Scope members2 = new Scope(); + //Type tp1 = compoundType(parts1, members2); + Type tp1 = (tp.symbol().isCompoundSym()) ? compoundType(parts1, members2) + : compoundType(parts1, members2, tp.symbol()); + Symbol[] syms1 = members1.elements(); + Symbol[] syms2 = new Symbol[syms1.length]; + for (int i = 0; i < syms2.length; i++) { + syms2[i] = syms1[i].cloneSymbol(tp1.symbol()); + } + for (int i = 0; i < syms2.length; i++) { + syms2[i].setInfo(syms1[i].info().subst(syms1, syms2)); + if (syms2[i].kind == TYPE) + syms2[i].setLoBound(syms1[i].loBound().subst(syms1, syms2)); + } + for (int i = 0; i < syms2.length; i++) { + members2.enter(syms2[i]); + } + return tp1; + } + + case MethodType(Symbol[] vparams, Type result): + Symbol[] vparams1 = map(vparams); + Type result1 = apply(result); + if (vparams1 == vparams && result1 == result) return tp; + else return MethodType(vparams1, result1); + case PolyType(Symbol[] tparams, Type result): + Symbol[] tparams1 = map(tparams); + Type result1 = apply(result); + if (tparams1 != tparams) result1 = result1.subst(tparams, tparams1); + if (tparams1 == tparams && result1 == result) return tp; + else return PolyType(tparams1, result1); + case OverloadedType(Symbol[] alts, Type[] alttypes): + Type[] alttypes1 = map(alttypes); + if (alttypes1 == alttypes) return tp; + else return OverloadedType(alts, alttypes1); + case UnboxedArrayType(Type elemtp): + Type elemtp1 = apply(elemtp); + if (elemtp1 == elemtp) return tp; + else return UnboxedArrayType(elemtp1); + default: + throw new ApplicationError(tp + " " + tp.symbol()); + } + } + + public final Symbol map(Symbol sym) { return map(sym, false); } - public Symbol map(Symbol sym, boolean dontClone) { - Type tp = sym.info(); - Type tp1 = apply(tp); + public Symbol map(Symbol sym, boolean dontClone) { + Type tp = sym.info(); + Type tp1 = apply(tp); if (tp != tp1) { if (!dontClone) sym = sym.cloneSymbol(); sym.setInfo(tp1); dontClone = true; } - if (sym.kind == TYPE) { - Type lb = sym.loBound(); - Type lb1 = apply(lb); - if (lb != lb1) { + if (sym.kind == TYPE) { + Type lb = sym.loBound(); + Type lb1 = apply(lb); + if (lb != lb1) { if (!dontClone) sym = sym.cloneSymbol(); sym.setLoBound(lb1); } } - return sym; - } - - public Type[] map(Type[] tps) { - Type[] tps1 = tps; - for (int i = 0; i < tps.length; i++) { - Type tp = tps[i]; - Type tp1 = apply(tp); - if (tp1 != tp && tps1 == tps) { - tps1 = new Type[tps.length]; - System.arraycopy(tps, 0, tps1, 0, i); - } - tps1[i] = tp1; - } - return tps1; - } - - /** Apply map to all elements of this array of symbols, - * preserving recursive references to symbols in the array. - */ - public final Symbol[] map(Symbol[] syms) { + return sym; + } + + public Type[] map(Type[] tps) { + Type[] tps1 = tps; + for (int i = 0; i < tps.length; i++) { + Type tp = tps[i]; + Type tp1 = apply(tp); + if (tp1 != tp && tps1 == tps) { + tps1 = new Type[tps.length]; + System.arraycopy(tps, 0, tps1, 0, i); + } + tps1[i] = tp1; + } + return tps1; + } + + /** Apply map to all elements of this array of symbols, + * preserving recursive references to symbols in the array. + */ + public final Symbol[] map(Symbol[] syms) { return map(syms, false); } - public Symbol[] map(Symbol[] syms, boolean dontClone) { - Symbol[] syms1 = syms; - for (int i = 0; i < syms.length; i++) { - Symbol sym = syms[i]; - Symbol sym1 = map(sym, dontClone); - if (sym != sym1 && syms1 == syms) { - syms1 = new Symbol[syms.length]; - System.arraycopy(syms, 0, syms1, 0, i); - } - syms1[i] = sym1; - } - if (syms1 != syms) { - for (int i = 0; i < syms1.length; i++) { - if (syms1[i] == syms[i]) - syms1[i] = syms[i].cloneSymbol(); - } + public Symbol[] map(Symbol[] syms, boolean dontClone) { + Symbol[] syms1 = syms; + for (int i = 0; i < syms.length; i++) { + Symbol sym = syms[i]; + Symbol sym1 = map(sym, dontClone); + if (sym != sym1 && syms1 == syms) { + syms1 = new Symbol[syms.length]; + System.arraycopy(syms, 0, syms1, 0, i); + } + syms1[i] = sym1; + } + if (syms1 != syms) { + for (int i = 0; i < syms1.length; i++) { + if (syms1[i] == syms[i]) + syms1[i] = syms[i].cloneSymbol(); + } new SubstSymMap(syms, syms1).map(syms1, true); - } - return syms1; - } + } + return syms1; + } - /** Apply map to all elements of this array of this scope. - */ - public Scope map(Scope s) { - Symbol[] members = s.elements(); - Symbol[] members1 = map(members); - if (members == members1) return s; - else return new Scope(members1); - } + /** Apply map to all elements of this array of this scope. + */ + public Scope map(Scope s) { + Symbol[] members = s.elements(); + Symbol[] members1 = map(members); + if (members == members1) return s; + else return new Scope(members1); + } } public abstract static class MapOnlyTypes extends Map { @@ -1112,9 +1112,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { public Type apply(Type tp) { return tp; } public Type applyParams(Type tp) { return tp; } public Type map(Type tp) { return tp; } - public Symbol map(Symbol sym, boolean dontClone) { return sym; } + public Symbol map(Symbol sym, boolean dontClone) { return sym; } public Type[] map(Type[] tps) { return tps; } - public Symbol[] map(Symbol[] syms, boolean dontClone) { return syms; } + public Symbol[] map(Symbol[] syms, boolean dontClone) { return syms; } public Scope map(Scope scope) { return scope; } }; @@ -1124,103 +1124,103 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { * such a type does not exist. */ public Type baseType(Symbol clazz) { - //System.out.println(this + ".baseType(" + clazz + ")");//DEBUG - switch (this) { - case ErrorType: - return ErrorType; - - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - return singleDeref().baseType(clazz); - - case TypeRef(Type pre, Symbol sym, Type[] args): - if (sym == clazz) - return this; - else if (sym.kind == TYPE) - return sym.info() - .asSeenFrom(pre, sym.owner()).baseType(clazz); - else if (sym.kind == ALIAS) - if (sym.typeParams().length == args.length) - return sym.info().subst(sym.typeParams(), args) - .asSeenFrom(pre, sym.owner()).baseType(clazz); - else return Type.NoType; - else if (clazz.isCompoundSym()) - return NoType; - else { - return sym.baseType(clazz) - .asSeenFrom(pre, sym.owner()) - .subst(sym.typeParams(), args); - } - - case CompoundType(Type[] parts, _): - for (int i = parts.length - 1; i >= 0; i--) { - Type result = parts[i].baseType(clazz); - if (result != NoType) return result; - } - break; - - case UnboxedArrayType(_): - if (clazz == Global.instance.definitions.ANY_CLASS || - clazz == Global.instance.definitions.ANYREF_CLASS) - return clazz.type(); - } - return NoType; + //System.out.println(this + ".baseType(" + clazz + ")");//DEBUG + switch (this) { + case ErrorType: + return ErrorType; + + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + return singleDeref().baseType(clazz); + + case TypeRef(Type pre, Symbol sym, Type[] args): + if (sym == clazz) + return this; + else if (sym.kind == TYPE) + return sym.info() + .asSeenFrom(pre, sym.owner()).baseType(clazz); + else if (sym.kind == ALIAS) + if (sym.typeParams().length == args.length) + return sym.info().subst(sym.typeParams(), args) + .asSeenFrom(pre, sym.owner()).baseType(clazz); + else return Type.NoType; + else if (clazz.isCompoundSym()) + return NoType; + else { + return sym.baseType(clazz) + .asSeenFrom(pre, sym.owner()) + .subst(sym.typeParams(), args); + } + + case CompoundType(Type[] parts, _): + for (int i = parts.length - 1; i >= 0; i--) { + Type result = parts[i].baseType(clazz); + if (result != NoType) return result; + } + break; + + case UnboxedArrayType(_): + if (clazz == Global.instance.definitions.ANY_CLASS || + clazz == Global.instance.definitions.ANYREF_CLASS) + return clazz.type(); + } + return NoType; } /** Return overriding instance of `sym' in this type, * or `sym' itself if none exists. */ public Symbol rebind(Symbol sym) { - if ((sym.flags & (PRIVATE | MODUL)) == 0) { - Symbol sym1 = lookupNonPrivate(sym.name); - if (sym1.kind != NONE) { - if ((sym1.flags & LOCKED) != 0) - throw new Type.Error("illegal cyclic reference involving " + sym1); - //System.out.println("rebinding " + sym + " to " + sym1);//DEBUG - return sym1; - } - } - return sym; + if ((sym.flags & (PRIVATE | MODUL)) == 0) { + Symbol sym1 = lookupNonPrivate(sym.name); + if (sym1.kind != NONE) { + if ((sym1.flags & LOCKED) != 0) + throw new Type.Error("illegal cyclic reference involving " + sym1); + //System.out.println("rebinding " + sym + " to " + sym1);//DEBUG + return sym1; + } + } + return sym; } /** A map to implement `asSeenFrom'. */ static class AsSeenFromMap extends Map { - private final Type pre; - private final Symbol clazz; + private final Type pre; + private final Symbol clazz; private final boolean local; - AsSeenFromMap(Type pre, Symbol clazz) { - this.pre = pre; this.clazz = clazz; + AsSeenFromMap(Type pre, Symbol clazz) { + this.pre = pre; this.clazz = clazz; Global global = Global.instance; this.local =global.PHASE.EXPLICITOUTER.id() " + ArrayApply.toString(to); - return new SubstTypeMap(from, to).apply(this); - } else return this; + if (to.length != 0) { + assert from.length == to.length + : this + ": " + Debug.show(from) + " <> " + ArrayApply.toString(to); + return new SubstTypeMap(from, to).apply(this); + } else return this; } /** Substitute types `to' for occurrences of symbols `from' in these types. */ public static Type[] subst(Type[] these, Symbol[] from, Type[] to) { - if (these.length != 0 && to.length != 0) { - assert from.length == to.length; - return new SubstTypeMap(from, to).map(these); - } else return these; + if (these.length != 0 && to.length != 0) { + assert from.length == to.length; + return new SubstTypeMap(from, to).map(these); + } else return these; } /** A map for substitutions of thistypes. */ public static class SubstThisMap extends Map { - Symbol from; - Type to; - public SubstThisMap(Symbol from, Type to) { - this.from = from; - this.to = to; - } + Symbol from; + Type to; + public SubstThisMap(Symbol from, Type to) { + this.from = from; + this.to = to; + } public SubstThisMap(Symbol oldSym, Symbol newSym) { this(oldSym, newSym.thisType()); } - public Type apply(Type t) { - switch (t) { - case ThisType(Symbol sym): - if (sym == from) return to; - else return t; - default: - return map(t); - } - } + public Type apply(Type t) { + switch (t) { + case ThisType(Symbol sym): + if (sym == from) return to; + else return t; + default: + return map(t); + } + } } public Type substThis(Symbol from, Type to) { - return new SubstThisMap(from, to).apply(this); + return new SubstThisMap(from, to).apply(this); } public static Type[] substThis(Type[] these, Symbol from, Type to) { - return new SubstThisMap(from, to).map(these); + return new SubstThisMap(from, to).map(these); } static class ContainsMap extends Map { - boolean result = false; - Symbol sym; - ContainsMap(Symbol sym) { - this.sym = sym; - } - public Type apply(Type t) { - if (!result) { - switch (t) { - case TypeRef(Type pre, Symbol sym1, Type[] args): - if (sym == sym1) result = true; - else { map(pre); map(args); } - break; - case SingleType(Type pre, Symbol sym1): - map(pre); - if (sym == sym1) result = true; - break; - default: - map(t); - } - } - return t; - } + boolean result = false; + Symbol sym; + ContainsMap(Symbol sym) { + this.sym = sym; + } + public Type apply(Type t) { + if (!result) { + switch (t) { + case TypeRef(Type pre, Symbol sym1, Type[] args): + if (sym == sym1) result = true; + else { map(pre); map(args); } + break; + case SingleType(Type pre, Symbol sym1): + map(pre); + if (sym == sym1) result = true; + break; + default: + map(t); + } + } + return t; + } } /** Does this type contain symbol `sym'? */ public boolean contains(Symbol sym) { - ContainsMap f = new ContainsMap(sym); - f.apply(this); - return f.result; + ContainsMap f = new ContainsMap(sym); + f.apply(this); + return f.result; } /** Does this type contain any of the symbols `syms'? */ public boolean containsSome(Symbol[] syms) { - for (int i = 0; i < syms.length; i++) - if (contains(syms[i])) return true; - return false; + for (int i = 0; i < syms.length; i++) + if (contains(syms[i])) return true; + return false; } // Cloning --------------------------------------------------------------- @@ -1772,513 +1772,513 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { /** Is this type a subtype of that type? */ public boolean isSubType(Type that) { - if (explainSwitch) { - for (int i = 0; i < indent; i++) System.out.print(" "); - System.out.println(this + " < " + that + "?"); - indent++; - } - boolean result = isSubType0(that); - if (explainSwitch) { - indent--; - for (int i = 0; i < indent; i++) System.out.print(" "); - System.out.println(result); - } - return result; + if (explainSwitch) { + for (int i = 0; i < indent; i++) System.out.print(" "); + System.out.println(this + " < " + that + "?"); + indent++; + } + boolean result = isSubType0(that); + if (explainSwitch) { + indent--; + for (int i = 0; i < indent; i++) System.out.print(" "); + System.out.println(result); + } + return result; } public boolean isSubType0(Type that) { - if (this == that) return true; - - switch (this) { - case ErrorType: - case AnyType: - return true; - } - - switch (that) { - case ErrorType: - case AnyType: - return true; - - case NoType: - return false; - - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - switch (this) { - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - return this.isSameAs(that); - } - break; - - case TypeRef(Type pre1, Symbol sym1, Type[] args1): - switch (this) { - case TypeRef(Type pre, Symbol sym, Type[] args): - if (pre.isSubType(pre1) && - (sym == sym1 || sym == pre.rebind(sym1)) && - isSubArgs(args, args1, sym.typeParams()) - || - sym.kind == TYPE && pre.memberInfo(sym).isSubType(that)) - return true; - break; - } - if (sym1.kind == CLASS) { - Type base = this.baseType(sym1); - if (this != base && base.isSubType(that)) - return true; - } - break; - - case CompoundType(Type[] parts1, Scope members1): - int i = 0; - while (i < parts1.length && isSubType(parts1[i])) i++; - if (i == parts1.length && specializes(members1)) - return true; - break; - - case MethodType(Symbol[] ps1, Type res1): - switch (this) { - case MethodType(Symbol[] ps, Type res): - if (ps.length != ps1.length) return false; - for (int i = 0; i < ps.length; i++) { - Symbol p1 = ps1[i]; - Symbol p = ps[i]; - if (!p1.type().isSameAs(p.type()) || - (p1.flags & (DEF | REPEATED)) != (p.flags & (DEF | REPEATED))) - return false; - } - return res.isSubType(res1); - } - break; - - case PolyType(Symbol[] ps1, Type res1): - switch (this) { - case PolyType(Symbol[] ps, Type res): - if (ps.length != ps1.length) return false; - for (int i = 0; i < ps.length; i++) - if (!ps1[i].info().subst(ps1, ps).isSameAs(ps[i].info()) || - !ps[i].loBound().isSameAs(ps1[i].loBound().subst(ps1, ps))) - return false; - return res.isSubType(res1.subst(ps1, ps)); - } - break; - - case OverloadedType(Symbol[] alts1, Type[] alttypes1): - for (int i = 0; i < alttypes1.length; i++) { - if (!isSubType(alttypes1[i])) - return false; - } - return true; - - case UnboxedType(int tag1): - switch (this) { - case UnboxedType(int tag): - return tag == tag1 || + if (this == that) return true; + + switch (this) { + case ErrorType: + case AnyType: + return true; + } + + switch (that) { + case ErrorType: + case AnyType: + return true; + + case NoType: + return false; + + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + switch (this) { + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + return this.isSameAs(that); + } + break; + + case TypeRef(Type pre1, Symbol sym1, Type[] args1): + switch (this) { + case TypeRef(Type pre, Symbol sym, Type[] args): + if (pre.isSubType(pre1) && + (sym == sym1 || sym == pre.rebind(sym1)) && + isSubArgs(args, args1, sym.typeParams()) + || + sym.kind == TYPE && pre.memberInfo(sym).isSubType(that)) + return true; + break; + } + if (sym1.kind == CLASS) { + Type base = this.baseType(sym1); + if (this != base && base.isSubType(that)) + return true; + } + break; + + case CompoundType(Type[] parts1, Scope members1): + int i = 0; + while (i < parts1.length && isSubType(parts1[i])) i++; + if (i == parts1.length && specializes(members1)) + return true; + break; + + case MethodType(Symbol[] ps1, Type res1): + switch (this) { + case MethodType(Symbol[] ps, Type res): + if (ps.length != ps1.length) return false; + for (int i = 0; i < ps.length; i++) { + Symbol p1 = ps1[i]; + Symbol p = ps[i]; + if (!p1.type().isSameAs(p.type()) || + (p1.flags & (DEF | REPEATED)) != (p.flags & (DEF | REPEATED))) + return false; + } + return res.isSubType(res1); + } + break; + + case PolyType(Symbol[] ps1, Type res1): + switch (this) { + case PolyType(Symbol[] ps, Type res): + if (ps.length != ps1.length) return false; + for (int i = 0; i < ps.length; i++) + if (!ps1[i].info().subst(ps1, ps).isSameAs(ps[i].info()) || + !ps[i].loBound().isSameAs(ps1[i].loBound().subst(ps1, ps))) + return false; + return res.isSubType(res1.subst(ps1, ps)); + } + break; + + case OverloadedType(Symbol[] alts1, Type[] alttypes1): + for (int i = 0; i < alttypes1.length; i++) { + if (!isSubType(alttypes1[i])) + return false; + } + return true; + + case UnboxedType(int tag1): + switch (this) { + case UnboxedType(int tag): + return tag == tag1 || (tag < tag1 && tag1 <= DOUBLE && tag1 != CHAR); - } - break; - - case UnboxedArrayType(UnboxedType(int tag1)): - switch (this) { - case UnboxedArrayType(UnboxedType(int tag)): - return tag1 == tag; - } - break; - - case UnboxedArrayType(Type elemtp1): - switch (this) { - case UnboxedArrayType(Type elemtp): - return elemtp.isSubType(elemtp1); - } - break; - - case TypeVar(Type origin, Constraint constr): - //todo: should we test for equality with origin? - if (constr.inst != NoType) { - return this.isSubType(constr.inst); - } else { - constr.lobounds = new List(this, constr.lobounds); - return true; - } - - default: - throw new ApplicationError(this + " <: " + that); - } - - switch (this) { - case NoType: - return false; - case ThisType(_): - 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); - } else { - constr.hibounds = new List(that, constr.hibounds); - return true; - } - - case TypeRef(_, Symbol sym, Type[] args): - switch (that) { - case TypeRef(Type pre1, Symbol sym1, _): - if (sym1.kind == TYPE && this.isSubType(that.loBound())) - return true; - } - if (sym.kind == ALIAS && sym.typeParams().length == args.length) - return this.unalias().isSubType(that); - else if (sym == Global.instance.definitions.ALL_CLASS) - return that.isSubType(Global.instance.definitions.ANY_TYPE()); - else if (sym == Global.instance.definitions.ALLREF_CLASS) - return - that.symbol() == Global.instance.definitions.ANY_CLASS || - (that.symbol() != Global.instance.definitions.ALL_CLASS && - that.isSubType(Global.instance.definitions.ANYREF_TYPE())); - break; - - case OverloadedType(Symbol[] alts, Type[] alttypes): - for (int i = 0; i < alttypes.length; i++) { - if (alttypes[i].isSubType(that)) return true; - } - break; - - case CompoundType(Type[] parts, Scope members): - int i = 0; - while (i < parts.length) { - if (parts[i].isSubType(that)) return true; - i++; - } - break; - - case UnboxedArrayType(_): + } + break; + + case UnboxedArrayType(UnboxedType(int tag1)): + switch (this) { + case UnboxedArrayType(UnboxedType(int tag)): + return tag1 == tag; + } + break; + + case UnboxedArrayType(Type elemtp1): + switch (this) { + case UnboxedArrayType(Type elemtp): + return elemtp.isSubType(elemtp1); + } + break; + + case TypeVar(Type origin, Constraint constr): + //todo: should we test for equality with origin? + if (constr.inst != NoType) { + return this.isSubType(constr.inst); + } else { + constr.lobounds = new List(this, constr.lobounds); + return true; + } + + default: + throw new ApplicationError(this + " <: " + that); + } + + switch (this) { + case NoType: + return false; + case ThisType(_): + 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); + } else { + constr.hibounds = new List(that, constr.hibounds); + return true; + } + + case TypeRef(_, Symbol sym, Type[] args): + switch (that) { + case TypeRef(Type pre1, Symbol sym1, _): + if (sym1.kind == TYPE && this.isSubType(that.loBound())) + return true; + } + if (sym.kind == ALIAS && sym.typeParams().length == args.length) + return this.unalias().isSubType(that); + else if (sym == Global.instance.definitions.ALL_CLASS) + return that.isSubType(Global.instance.definitions.ANY_TYPE()); + else if (sym == Global.instance.definitions.ALLREF_CLASS) + return + that.symbol() == Global.instance.definitions.ANY_CLASS || + (that.symbol() != Global.instance.definitions.ALL_CLASS && + that.isSubType(Global.instance.definitions.ANYREF_TYPE())); + break; + + case OverloadedType(Symbol[] alts, Type[] alttypes): + for (int i = 0; i < alttypes.length; i++) { + if (alttypes[i].isSubType(that)) return true; + } + break; + + case CompoundType(Type[] parts, Scope members): + int i = 0; + while (i < parts.length) { + if (parts[i].isSubType(that)) return true; + i++; + } + break; + + case UnboxedArrayType(_): if (Global.instance.definitions.JAVA_OBJECT_TYPE().isSubType(that)) return true; // !!! we should probably also test for Clonable, Serializable, ... - } + } - switch (that) { - case TypeRef(_, Symbol sym1, Type[] args): - if (sym1.kind == ALIAS && sym1.typeParams().length == args.length) - return this.isSubType(that.unalias()); - break; - } + switch (that) { + case TypeRef(_, Symbol sym1, Type[] args): + if (sym1.kind == ALIAS && sym1.typeParams().length == args.length) + return this.isSubType(that.unalias()); + break; + } - return false; + return false; } /** Are types `these' subtypes of corresponding types `those'? */ public static boolean isSubType(Type[] these, Type[] those) { - if (these.length != those.length) return false; - for (int i = 0; i < these.length; i++) { - if (!these[i].isSubType(those[i])) return false; - } - return true; + if (these.length != those.length) return false; + for (int i = 0; i < these.length; i++) { + if (!these[i].isSubType(those[i])) return false; + } + return true; } /** Are types `these' arguments types conforming to corresponding types `those'? */ static boolean isSubArgs(Type[] these, Type[] those, Symbol[] tparams) { - if (these.length != those.length) return false; - for (int i = 0; i < these.length; i++) { - if ((tparams[i].flags & COVARIANT) != 0) { - if (!these[i].isSubType(those[i])) return false; - } else if ((tparams[i].flags & CONTRAVARIANT) != 0) { - //System.out.println("contra: " + these[i] + " " + those[i] + " " + those[i].isSubType(these[i]));//DEBUG - if (!those[i].isSubType(these[i])) return false; - } else { - if (!these[i].isSameAs(those[i])) return false; - } - } - return true; + if (these.length != those.length) return false; + for (int i = 0; i < these.length; i++) { + if ((tparams[i].flags & COVARIANT) != 0) { + if (!these[i].isSubType(those[i])) return false; + } else if ((tparams[i].flags & CONTRAVARIANT) != 0) { + //System.out.println("contra: " + these[i] + " " + those[i] + " " + those[i].isSubType(these[i]));//DEBUG + if (!those[i].isSubType(these[i])) return false; + } else { + if (!these[i].isSameAs(those[i])) return false; + } + } + return true; } public static boolean isSubSet(Type[] alts, Type[] alts1) { - for (int i = 0; i < alts.length; i++) { - int j = 0; - while (j < alts1.length && !alts1[j].isSameAs(alts[i])) j++; - if (j == alts1.length) return false; - } - return true; + for (int i = 0; i < alts.length; i++) { + int j = 0; + while (j < alts1.length && !alts1[j].isSameAs(alts[i])) j++; + if (j == alts1.length) return false; + } + return true; } /** Does this type implement all symbols in scope `s' with same or stronger types? */ public boolean specializes(Scope s) { - for (Scope.SymbolIterator it = s.iterator(true); it.hasNext();) { - if (!specializes(it.next())) return false; - } - return true; + for (Scope.SymbolIterator it = s.iterator(true); it.hasNext();) { + if (!specializes(it.next())) return false; + } + return true; } /** Does this type implement symbol `sym1' with same or stronger type? */ public boolean specializes(Symbol sym1) { - if (explainSwitch) { - for (int i = 0; i < indent; i++) System.out.print(" "); - System.out.println(this + " specializes " + sym1 + "?"); - indent++; - } - boolean result = specializes0(sym1); - if (explainSwitch) { - indent--; - for (int i = 0; i < indent; i++) System.out.print(" "); - System.out.println(result); - } - return result; + if (explainSwitch) { + for (int i = 0; i < indent; i++) System.out.print(" "); + System.out.println(this + " specializes " + sym1 + "?"); + indent++; + } + boolean result = specializes0(sym1); + if (explainSwitch) { + indent--; + for (int i = 0; i < indent; i++) System.out.print(" "); + System.out.println(result); + } + return result; } private boolean specializes0(Symbol sym1) { - Type self = narrow(); - Symbol[] tparams = symbol().typeParams(); - Type[] targs = typeArgs(); - Symbol sym = lookup(sym1.name); - return - sym.kind != NONE && - (sym == sym1 - || - (sym.kind == sym1.kind || sym1.kind == TYPE) && - self.memberInfo(sym).subst(tparams, targs) - .isSubType(sym1.info().substThis(sym1.owner(), self)) && - sym1.loBound().substThis(sym1.owner(), self) - .isSubType(self.memberLoBound(sym).subst(tparams, targs)) - || - (sym.kind == TYPE && sym1.kind == ALIAS && - sym1.info().unalias().isSameAs(sym.type()))); + Type self = narrow(); + Symbol[] tparams = symbol().typeParams(); + Type[] targs = typeArgs(); + Symbol sym = lookup(sym1.name); + return + sym.kind != NONE && + (sym == sym1 + || + (sym.kind == sym1.kind || sym1.kind == TYPE) && + self.memberInfo(sym).subst(tparams, targs) + .isSubType(sym1.info().substThis(sym1.owner(), self)) && + sym1.loBound().substThis(sym1.owner(), self) + .isSubType(self.memberLoBound(sym).subst(tparams, targs)) + || + (sym.kind == TYPE && sym1.kind == ALIAS && + sym1.info().unalias().isSameAs(sym.type()))); } /** Is this type the same as that type? */ public boolean isSameAs(Type that) { - if (explainSwitch) { - for (int i = 0; i < indent; i++) System.out.print(" "); - System.out.println(this + " = " + that + "?"); - indent++; - } - boolean result = isSameAs0(that); - if (explainSwitch) { - indent--; - for (int i = 0; i < indent; i++) System.out.print(" "); - System.out.println(result); - } - return result; + if (explainSwitch) { + for (int i = 0; i < indent; i++) System.out.print(" "); + System.out.println(this + " = " + that + "?"); + indent++; + } + boolean result = isSameAs0(that); + if (explainSwitch) { + indent--; + for (int i = 0; i < indent; i++) System.out.print(" "); + System.out.println(result); + } + return result; } public boolean isSameAs0(Type that) { - if (this == that) return true; - - switch (this) { - case ErrorType: - case AnyType: - return true; - - case ThisType(Symbol sym): - switch (that) { - case ThisType(Symbol sym1): - return sym == sym1; - case SingleType(Type pre1, Symbol sym1): - return sym1.isModule() - && sym == sym1.moduleClass() - && sym.owner().thisType().isSameAs(pre1) - || - deAlias(that) != that && - this.isSameAs(deAlias(that)); - } - break; - - case SingleType(Type pre, Symbol sym): - switch (that) { - case SingleType(Type pre1, Symbol sym1): - return sym == sym1 && pre.isSameAs(pre1) - || - (deAlias(this) != this || deAlias(that) != that) && + if (this == that) return true; + + switch (this) { + case ErrorType: + case AnyType: + return true; + + case ThisType(Symbol sym): + switch (that) { + case ThisType(Symbol sym1): + return sym == sym1; + case SingleType(Type pre1, Symbol sym1): + return sym1.isModule() + && sym == sym1.moduleClass() + && sym.owner().thisType().isSameAs(pre1) + || + deAlias(that) != that && + this.isSameAs(deAlias(that)); + } + break; + + case SingleType(Type pre, Symbol sym): + switch (that) { + case SingleType(Type pre1, Symbol sym1): + return sym == sym1 && pre.isSameAs(pre1) + || + (deAlias(this) != this || deAlias(that) != that) && deAlias(this).isSameAs(deAlias(that)); - case ThisType(Symbol sym1): - return sym.isModule() - && sym.moduleClass() == sym1 - && pre.isSameAs(sym1.owner().thisType()) - || - deAlias(this) != this && - deAlias(this).isSameAs(that); - } - 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): - if (sym == sym1 && pre.isSameAs(pre1) && isSameAs(args, args1)) - return true; - } - break; - - case CompoundType(Type[] parts, Scope members): - switch (that) { - case CompoundType(Type[] parts1, Scope members1): - if (parts.length != parts1.length) return false; - for (int i = 0; i < parts.length; i++) - if (!parts[i].isSameAs(parts1[i])) return false; - return isSameAs(members, members1); - } - break; - - case MethodType(Symbol[] ps, Type res): - switch (that) { - case MethodType(Symbol[] ps1, Type res1): - if (ps.length != ps1.length) return false; - for (int i = 0; i < ps.length; i++) { - Symbol p1 = ps1[i]; - Symbol p = ps[i]; - if (!p1.type().isSameAs(p.type()) || - (p1.flags & (DEF | REPEATED)) != (p.flags & (DEF | REPEATED))) - return false; - } - return res.isSameAs(res1); - } - break; - - case PolyType(Symbol[] ps, Type res): - switch (that) { - case PolyType(Symbol[] ps1, Type res1): - if (ps.length != ps1.length) return false; - for (int i = 0; i < ps.length; i++) - if (!ps1[i].info().subst(ps1, ps).isSameAs(ps[i].info()) || - !ps1[i].loBound().subst(ps1, ps).isSameAs(ps[i].loBound())) - return false; - return res.isSameAs(res1.subst(ps1, ps)); - } - break; - - case OverloadedType(Symbol[] alts, Type[] alttypes): - switch (that) { - case OverloadedType(Symbol[] alts1, Type[] alttypes1): - return isSubSet(alttypes1, alttypes) - && isSubSet(alttypes, alttypes1); - } - break; - - case UnboxedType(int kind): - switch (that) { - case UnboxedType(int kind1): - return kind == kind1; - } - break; - - case UnboxedArrayType(Type elemtp): - switch (that) { - case UnboxedArrayType(Type elemtp1): - return elemtp.isSameAs(elemtp1); - } - break; - } - - switch (that) { - case ErrorType: - case AnyType: - return true; - case NoType: - return false; - case TypeVar(Type origin, Constraint constr): - if (constr.inst != NoType) return constr.inst.isSameAs(this); - else return constr.instantiate(this.any2typevar()); - } - - switch (this) { - case NoType: - return false; - case TypeRef(_, Symbol sym, Type[] args): - if (sym.kind == ALIAS && sym.typeParams().length == args.length) - return this.unalias().isSameAs(that); - break; - case TypeVar(Type origin, Constraint constr): - if (constr.inst != NoType) return constr.inst.isSameAs(that); - else return constr.instantiate(that.any2typevar()); - } - - switch (that) { - case TypeRef(_, Symbol sym, Type[] args): - if (sym.kind == ALIAS && sym.typeParams().length == args.length) - return this.isSameAs(that.unalias()); - } - - return false; + case ThisType(Symbol sym1): + return sym.isModule() + && sym.moduleClass() == sym1 + && pre.isSameAs(sym1.owner().thisType()) + || + deAlias(this) != this && + deAlias(this).isSameAs(that); + } + 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): + if (sym == sym1 && pre.isSameAs(pre1) && isSameAs(args, args1)) + return true; + } + break; + + case CompoundType(Type[] parts, Scope members): + switch (that) { + case CompoundType(Type[] parts1, Scope members1): + if (parts.length != parts1.length) return false; + for (int i = 0; i < parts.length; i++) + if (!parts[i].isSameAs(parts1[i])) return false; + return isSameAs(members, members1); + } + break; + + case MethodType(Symbol[] ps, Type res): + switch (that) { + case MethodType(Symbol[] ps1, Type res1): + if (ps.length != ps1.length) return false; + for (int i = 0; i < ps.length; i++) { + Symbol p1 = ps1[i]; + Symbol p = ps[i]; + if (!p1.type().isSameAs(p.type()) || + (p1.flags & (DEF | REPEATED)) != (p.flags & (DEF | REPEATED))) + return false; + } + return res.isSameAs(res1); + } + break; + + case PolyType(Symbol[] ps, Type res): + switch (that) { + case PolyType(Symbol[] ps1, Type res1): + if (ps.length != ps1.length) return false; + for (int i = 0; i < ps.length; i++) + if (!ps1[i].info().subst(ps1, ps).isSameAs(ps[i].info()) || + !ps1[i].loBound().subst(ps1, ps).isSameAs(ps[i].loBound())) + return false; + return res.isSameAs(res1.subst(ps1, ps)); + } + break; + + case OverloadedType(Symbol[] alts, Type[] alttypes): + switch (that) { + case OverloadedType(Symbol[] alts1, Type[] alttypes1): + return isSubSet(alttypes1, alttypes) + && isSubSet(alttypes, alttypes1); + } + break; + + case UnboxedType(int kind): + switch (that) { + case UnboxedType(int kind1): + return kind == kind1; + } + break; + + case UnboxedArrayType(Type elemtp): + switch (that) { + case UnboxedArrayType(Type elemtp1): + return elemtp.isSameAs(elemtp1); + } + break; + } + + switch (that) { + case ErrorType: + case AnyType: + return true; + case NoType: + return false; + case TypeVar(Type origin, Constraint constr): + if (constr.inst != NoType) return constr.inst.isSameAs(this); + else return constr.instantiate(this.any2typevar()); + } + + switch (this) { + case NoType: + return false; + case TypeRef(_, Symbol sym, Type[] args): + if (sym.kind == ALIAS && sym.typeParams().length == args.length) + return this.unalias().isSameAs(that); + break; + case TypeVar(Type origin, Constraint constr): + if (constr.inst != NoType) return constr.inst.isSameAs(that); + else return constr.instantiate(that.any2typevar()); + } + + switch (that) { + case TypeRef(_, Symbol sym, Type[] args): + if (sym.kind == ALIAS && sym.typeParams().length == args.length) + return this.isSameAs(that.unalias()); + } + + return false; } //where Type deAlias(Type tp) { - switch (tp) { - case SingleType(_, _): - Type tp1 = tp.singleDeref(); - if (tp1.isStable()) return deAlias(tp1); - } - return tp; - } + switch (tp) { + case SingleType(_, _): + Type tp1 = tp.singleDeref(); + if (tp1.isStable()) return deAlias(tp1); + } + return tp; + } /** Are types `these' the same as corresponding types `those'? */ public static boolean isSameAs(Type[] these, Type[] those) { - if (these.length != those.length) return false; - for (int i = 0; i < these.length; i++) { - if (!these[i].isSameAs(those[i])) return false; - } - return true; + if (these.length != those.length) return false; + for (int i = 0; i < these.length; i++) { + if (!these[i].isSameAs(those[i])) return false; + } + return true; } /** Do scopes `s1' and `s2' define he same symbols with the same kinds and infos? */ public boolean isSameAs(Scope s1, Scope s2) { - return isSubScope(s1, s2) && isSubScope(s2, s1); + return isSubScope(s1, s2) && isSubScope(s2, s1); } /** Does scope `s1' define all symbols of scope `s2' with the same kinds and infos? */ private boolean isSubScope(Scope s1, Scope s2) { - for (Scope.SymbolIterator it = s2.iterator(); it.hasNext(); ) { - Symbol sym2 = it.next(); - Symbol sym1 = s1.lookup(sym2.name); - if (sym1.kind != sym2.kind || - !sym1.info().isSameAs( - sym2.info().substThis( - sym2.owner(), sym1.owner().thisType())) || - !sym1.loBound().isSameAs( - sym2.loBound().substThis( - sym2.owner(), sym1.owner().thisType()))) - return false; - } - return true; + for (Scope.SymbolIterator it = s2.iterator(); it.hasNext(); ) { + Symbol sym2 = it.next(); + Symbol sym1 = s1.lookup(sym2.name); + if (sym1.kind != sym2.kind || + !sym1.info().isSameAs( + sym2.info().substThis( + sym2.owner(), sym1.owner().thisType())) || + !sym1.loBound().isSameAs( + sym2.loBound().substThis( + sym2.owner(), sym1.owner().thisType()))) + return false; + } + return true; } boolean isSameAsAll(Type[] tps) { - int i = 1; - while (i < tps.length && isSameAs(tps[i])) i++; - return i == tps.length; + int i = 1; + while (i < tps.length && isSameAs(tps[i])) i++; + return i == tps.length; } /** Map every occurrence of AnyType to a fresh type variable. */ public static Map any2typevarMap = new Map() { - public Type apply(Type t) { return t.any2typevar(); } + public Type apply(Type t) { return t.any2typevar(); } }; public Type any2typevar() { - switch (this) { - case AnyType: - return TypeVar(this, new Constraint()); - default: - return any2typevarMap.map(this); - } + switch (this) { + case AnyType: + return TypeVar(this, new Constraint()); + default: + return any2typevarMap.map(this); + } } // Closures and Least Upper Bounds --------------------------------------------------- @@ -2287,17 +2287,17 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { * its direct and indirect (pre-) base types, sorted by Symbol.isLess(). */ public Type[] closure() { - switch (this.widen().unalias()) { + switch (this.widen().unalias()) { case TypeRef(Type pre, Symbol sym, Type[] args): - return subst( - asSeenFrom(sym.closure(), pre, sym.owner()), - sym.typeParams(), args); + return subst( + asSeenFrom(sym.closure(), pre, sym.owner()), + sym.typeParams(), args); - case CompoundType(Type[] parts, Scope members): - Type[][] closures = new Type[parts.length][]; - for (int i = 0; i < parts.length; i++) - closures[i] = parts[i].closure(); - return union(closures); + case CompoundType(Type[] parts, Scope members): + Type[][] closures = new Type[parts.length][]; + for (int i = 0; i < parts.length; i++) + closures[i] = parts[i].closure(); + return union(closures); default: return new Type[]{this}; @@ -2309,92 +2309,92 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { * is a subtype of the former. */ static private Type[] union(Type[][] closures) { - if (closures.length == 1) return closures[0]; // fast special case - int[] index = new int[closures.length]; - int totalsize = 0; - for (int i = 0; i < index.length; i++) { - index[i] = 0; - totalsize = totalsize + closures[i].length; - } - Type[] res = new Type[totalsize]; - int j = 0; - - while (true) { - // find minimal element - Type min = null; - for (int i = 0; i < index.length; i++) { - if (index[i] < closures[i].length) { - Type cltype = closures[i][index[i]]; - if (min == null || - cltype.symbol().isLess(min.symbol()) || - cltype.symbol() == min.symbol()) { - min = cltype; - } - } - } - if (min == null) break; - - res[j] = min; - j = j + 1; - - // bump all indices that start with minimal element - for (int i = 0; i < index.length; i++) { - if (index[i] < closures[i].length && - closures[i][index[i]].symbol() == min.symbol()) - index[i] = index[i] + 1; - } - } - Type[] result = new Type[j]; - System.arraycopy(res, 0, result, 0, j); - return result; + if (closures.length == 1) return closures[0]; // fast special case + int[] index = new int[closures.length]; + int totalsize = 0; + for (int i = 0; i < index.length; i++) { + index[i] = 0; + totalsize = totalsize + closures[i].length; + } + Type[] res = new Type[totalsize]; + int j = 0; + + while (true) { + // find minimal element + Type min = null; + for (int i = 0; i < index.length; i++) { + if (index[i] < closures[i].length) { + Type cltype = closures[i][index[i]]; + if (min == null || + cltype.symbol().isLess(min.symbol()) || + cltype.symbol() == min.symbol()) { + min = cltype; + } + } + } + if (min == null) break; + + res[j] = min; + j = j + 1; + + // bump all indices that start with minimal element + for (int i = 0; i < index.length; i++) { + if (index[i] < closures[i].length && + closures[i][index[i]].symbol() == min.symbol()) + index[i] = index[i] + 1; + } + } + Type[] result = new Type[j]; + System.arraycopy(res, 0, result, 0, j); + return result; } /** return intersection of non-empty array of closures */ static private Type[] intersection(Type[][] closures) { - if (closures.length == 1) return closures[0]; // fast special case - int[] index = new int[closures.length]; - Type[] mintypes = new Type[closures.length]; - int minsize = Integer.MAX_VALUE; - for (int i = 0; i < index.length; i++) { - index[i] = 0; - if (closures[i].length < minsize) minsize = closures[i].length; - } - Type[] res = new Type[minsize]; - int j = 0; - - L: - while (true) { - // find minimal element - Symbol minsym = null; - for (int i = 0; i < index.length; i++) { - if (index[i] == closures[i].length) break L; - Symbol clsym = closures[i][index[i]].symbol(); - if (minsym == null || clsym.isLess(minsym)) minsym = clsym; - } - - boolean agree = true; - // bump all indices that start with minimal element - for (int i = 0; i < index.length; i++) { - Type cltype = closures[i][index[i]]; - if (cltype.symbol() == minsym) { - mintypes[i] = cltype; - index[i] = index[i] + 1; - } else { - agree = false; - } - } - if (agree) { - Type mintype = argLub(mintypes); - if (mintype.symbol().kind == CLASS) { - res[j] = mintype; - j = j + 1; - } - } - } - Type[] result = new Type[j]; - System.arraycopy(res, 0, result, 0, j); - return result; + if (closures.length == 1) return closures[0]; // fast special case + int[] index = new int[closures.length]; + Type[] mintypes = new Type[closures.length]; + int minsize = Integer.MAX_VALUE; + for (int i = 0; i < index.length; i++) { + index[i] = 0; + if (closures[i].length < minsize) minsize = closures[i].length; + } + Type[] res = new Type[minsize]; + int j = 0; + + L: + while (true) { + // find minimal element + Symbol minsym = null; + for (int i = 0; i < index.length; i++) { + if (index[i] == closures[i].length) break L; + Symbol clsym = closures[i][index[i]].symbol(); + if (minsym == null || clsym.isLess(minsym)) minsym = clsym; + } + + boolean agree = true; + // bump all indices that start with minimal element + for (int i = 0; i < index.length; i++) { + Type cltype = closures[i][index[i]]; + if (cltype.symbol() == minsym) { + mintypes[i] = cltype; + index[i] = index[i] + 1; + } else { + agree = false; + } + } + if (agree) { + Type mintype = argLub(mintypes); + if (mintype.symbol().kind == CLASS) { + res[j] = mintype; + j = j + 1; + } + } + } + Type[] result = new Type[j]; + System.arraycopy(res, 0, result, 0, j); + return result; } /** same as lub, but all types are instances of the same class, @@ -2402,575 +2402,575 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { */ //todo: catch lubs not within bounds. static Type argLub(Type[] tps) { - tps = elimRedundant(tps, true); - if (tps.length == 1) return tps[0]; - - Type pre = tps[0].prefix(); - Symbol sym = tps[0].symbol(); - Symbol[] tparams = sym.typeParams(); - Type[] args = new Type[tparams.length]; - Type[][] argss = new Type[args.length][tps.length]; - for (int i = 0; i < tps.length; i++) { - switch (tps[i]) { - case TypeRef(Type pre1, Symbol sym1, Type[] args1): - assert sym == sym1; - assert args1.length == args.length; - if (!pre.isSameAs(pre1)) return NoType; - for (int j = 0; j < args1.length; j++) - argss[j][i] = args1[j]; - break; - case ErrorType: - return ErrorType; - default: - assert false : tps[i]; - } - } - for (int j = 0; j < args.length; j++) { - if ((tparams[j].flags & COVARIANT) != 0) - args[j] = lub(argss[j]); - else if ((tparams[j].flags & CONTRAVARIANT) != 0) - args[j] = glb(argss[j]); - else return NoType; - } - return typeRef(pre, sym, args); + tps = elimRedundant(tps, true); + if (tps.length == 1) return tps[0]; + + Type pre = tps[0].prefix(); + Symbol sym = tps[0].symbol(); + Symbol[] tparams = sym.typeParams(); + Type[] args = new Type[tparams.length]; + Type[][] argss = new Type[args.length][tps.length]; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case TypeRef(Type pre1, Symbol sym1, Type[] args1): + assert sym == sym1; + assert args1.length == args.length; + if (!pre.isSameAs(pre1)) return NoType; + for (int j = 0; j < args1.length; j++) + argss[j][i] = args1[j]; + break; + case ErrorType: + return ErrorType; + default: + assert false : tps[i]; + } + } + for (int j = 0; j < args.length; j++) { + if ((tparams[j].flags & COVARIANT) != 0) + args[j] = lub(argss[j]); + else if ((tparams[j].flags & CONTRAVARIANT) != 0) + args[j] = glb(argss[j]); + else return NoType; + } + return typeRef(pre, sym, args); } /** The frontier of a closure C is the minimal set of types such that * the union of the closures of these types equals C. */ static private Type[] frontier(Type[] closure) { - Type[] front = new Type[closure.length]; - int j = 0; - for (int i = 0; i < closure.length; i++) { - int k = 0; - Type tp = closure[i]; - while (k < j && !front[k].symbol().isSubClass(tp.symbol())) - k++; - if (k == j) { - front[j] = tp; - j++; - } - } - Type[] result = new Type[j]; - System.arraycopy(front, 0, result, 0, j); - return result; + Type[] front = new Type[closure.length]; + int j = 0; + for (int i = 0; i < closure.length; i++) { + int k = 0; + Type tp = closure[i]; + while (k < j && !front[k].symbol().isSubClass(tp.symbol())) + k++; + if (k == j) { + front[j] = tp; + j++; + } + } + Type[] result = new Type[j]; + System.arraycopy(front, 0, result, 0, j); + return result; } /** remove types that are subtypes of some other type. */ static private Type[] elimRedundant(Type[] tps, boolean elimLower) { - Type.List tl = Type.List.EMPTY; - int nredundant = 0; - boolean[] redundant = new boolean[tps.length]; - for (int i = 0; i < tps.length; i++) { - switch (tps[i]) { - case ErrorType: - return new Type[]{ErrorType}; - case MethodType(_, _): - case PolyType(_, _): - case OverloadedType(_, _): - return new Type[]{NoType}; - default: - assert tps[i].isObjectType(): tps[i]; - for (int j = 0; j < i && !redundant[i]; j++) { - if (!redundant[j]) { - if (tps[i].isSubType(tps[j])) { - redundant[elimLower ? i : j] = true; - nredundant++; - } else if (tps[j].isSubType(tps[i])) { - redundant[elimLower ? j : i] = true; - nredundant++; - } - } - } - } - } - - if (nredundant != 0) { - Type[] tps1 = new Type[tps.length - nredundant]; - int n = 0; - for (int i = 0; i < tps.length; i++) { - if (!redundant[i]) tps1[n++] = tps[i]; - } - return tps1; - } else { - return tps; - } + Type.List tl = Type.List.EMPTY; + int nredundant = 0; + boolean[] redundant = new boolean[tps.length]; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case ErrorType: + return new Type[]{ErrorType}; + case MethodType(_, _): + case PolyType(_, _): + case OverloadedType(_, _): + return new Type[]{NoType}; + default: + assert tps[i].isObjectType(): tps[i]; + for (int j = 0; j < i && !redundant[i]; j++) { + if (!redundant[j]) { + if (tps[i].isSubType(tps[j])) { + redundant[elimLower ? i : j] = true; + nredundant++; + } else if (tps[j].isSubType(tps[i])) { + redundant[elimLower ? j : i] = true; + nredundant++; + } + } + } + } + } + + if (nredundant != 0) { + Type[] tps1 = new Type[tps.length - nredundant]; + int n = 0; + for (int i = 0; i < tps.length; i++) { + if (!redundant[i]) tps1[n++] = tps[i]; + } + return tps1; + } else { + return tps; + } } /** Return the least upper bound of non-empty array of types `tps'. */ public static Type lub(Type[] tps) { - //System.out.println("lub" + ArrayApply.toString(tps));//DEBUG - - if (tps.length == 0) return Global.instance.definitions.ALL_TYPE(); - - //If all types are method types with same parameters, - //compute lub of their result types. - switch (tps[0]) { - case PolyType(Symbol[] tparams, _): - return polyLub(tps, tparams); - case MethodType(Symbol[] vparams, _): - return methodLub(tps, vparams); - } - - // remove types that are subtypes of some other type. - tps = elimRedundant(tps, true); - if (tps.length == 1) return tps[0]; - - // intersect closures and build frontier. - Type[][] closures = new Type[tps.length][]; - for (int i = 0; i < tps.length; i++) { - closures[i] = tps[i].closure(); - } - Type[] allBaseTypes = intersection(closures); - Type[] leastBaseTypes = frontier(allBaseTypes); - assert leastBaseTypes.length > 0 : ArrayApply.toString(tps); - - // add refinements where necessary - Scope members = new Scope(); - Type lubType = compoundType(leastBaseTypes, members); - Type lubThisType = lubType.narrow(); - //System.out.println("lubtype = " + lubType);//DEBUG - - Symbol[] rsyms = new Symbol[tps.length]; - Type[] rtps = new Type[tps.length]; - Type[] rlbs = new Type[tps.length]; - for (int i = 0; i < allBaseTypes.length; i++) { - for (Scope.SymbolIterator it = allBaseTypes[i].members().iterator(); - it.hasNext(); ) { - Symbol sym = it.next(); - Name name = sym.name; - if ((sym.flags & PRIVATE) == 0 && lubType.lookup(name) == sym) { - Type symType = memberTp(lubThisType, sym); - Type symLoBound = lubThisType.memberLoBound(sym); - int j = 0; - while (j < tps.length) { - rsyms[j] = tps[j].lookupNonPrivate(name); - if (rsyms[j] == sym) break; - rtps[j] = memberTp(tps[j], rsyms[j]) - .substThis(tps[j].symbol(), lubThisType); - rlbs[j] = tps[j].memberLoBound(rsyms[j]) - .substThis(tps[j].symbol(), lubThisType); - if (rtps[j].isSameAs(symType) && - rlbs[j].isSameAs(symLoBound)) break; - j++; - } - if (j == tps.length) { - Symbol lubSym = lub(rsyms, rtps, rlbs, lubType.symbol()); - if (lubSym.kind != NONE && - !(lubSym.kind == sym.kind && - lubSym.info().isSameAs(symType) && - lubSym.loBound().isSameAs(symType))) - members.enter(lubSym); - } - } - } - } - //System.out.print("lub "); System.out.print(ArrayApply.toString(tps)); System.out.println(" = " + lubType);//DEBUG - if (leastBaseTypes.length == 1 && members.isEmpty()) - return leastBaseTypes[0]; - else return lubType; + //System.out.println("lub" + ArrayApply.toString(tps));//DEBUG + + if (tps.length == 0) return Global.instance.definitions.ALL_TYPE(); + + //If all types are method types with same parameters, + //compute lub of their result types. + switch (tps[0]) { + case PolyType(Symbol[] tparams, _): + return polyLub(tps, tparams); + case MethodType(Symbol[] vparams, _): + return methodLub(tps, vparams); + } + + // remove types that are subtypes of some other type. + tps = elimRedundant(tps, true); + if (tps.length == 1) return tps[0]; + + // intersect closures and build frontier. + Type[][] closures = new Type[tps.length][]; + for (int i = 0; i < tps.length; i++) { + closures[i] = tps[i].closure(); + } + Type[] allBaseTypes = intersection(closures); + Type[] leastBaseTypes = frontier(allBaseTypes); + assert leastBaseTypes.length > 0 : ArrayApply.toString(tps); + + // add refinements where necessary + Scope members = new Scope(); + Type lubType = compoundType(leastBaseTypes, members); + Type lubThisType = lubType.narrow(); + //System.out.println("lubtype = " + lubType);//DEBUG + + Symbol[] rsyms = new Symbol[tps.length]; + Type[] rtps = new Type[tps.length]; + Type[] rlbs = new Type[tps.length]; + for (int i = 0; i < allBaseTypes.length; i++) { + for (Scope.SymbolIterator it = allBaseTypes[i].members().iterator(); + it.hasNext(); ) { + Symbol sym = it.next(); + Name name = sym.name; + if ((sym.flags & PRIVATE) == 0 && lubType.lookup(name) == sym) { + Type symType = memberTp(lubThisType, sym); + Type symLoBound = lubThisType.memberLoBound(sym); + int j = 0; + while (j < tps.length) { + rsyms[j] = tps[j].lookupNonPrivate(name); + if (rsyms[j] == sym) break; + rtps[j] = memberTp(tps[j], rsyms[j]) + .substThis(tps[j].symbol(), lubThisType); + rlbs[j] = tps[j].memberLoBound(rsyms[j]) + .substThis(tps[j].symbol(), lubThisType); + if (rtps[j].isSameAs(symType) && + rlbs[j].isSameAs(symLoBound)) break; + j++; + } + if (j == tps.length) { + Symbol lubSym = lub(rsyms, rtps, rlbs, lubType.symbol()); + if (lubSym.kind != NONE && + !(lubSym.kind == sym.kind && + lubSym.info().isSameAs(symType) && + lubSym.loBound().isSameAs(symType))) + members.enter(lubSym); + } + } + } + } + //System.out.print("lub "); System.out.print(ArrayApply.toString(tps)); System.out.println(" = " + lubType);//DEBUG + if (leastBaseTypes.length == 1 && members.isEmpty()) + return leastBaseTypes[0]; + else return lubType; } //where - private static Type memberTp(Type base, Symbol sym) { - return sym.kind == CLASS ? base.memberType(sym) : base.memberInfo(sym); - } + private static Type memberTp(Type base, Symbol sym) { + return sym.kind == CLASS ? base.memberType(sym) : base.memberInfo(sym); + } private static Type polyLub(Type[] tps, Symbol[] tparams0) { - Type[][] hiboundss = new Type[tparams0.length][tps.length]; - Type[][] loboundss = new Type[tparams0.length][tps.length]; - Type[] restps = new Type[tps.length]; - for (int i = 0; i < tps.length; i++) { - switch (tps[i]) { - case PolyType(Symbol[] tparams, Type restp): - if (tparams.length == tparams0.length) { - for (int j = 0; j < tparams0.length; j++) { - hiboundss[j][i] = tparams[j].info() - .subst(tparams, tparams0); - loboundss[j][i] = tparams[j].loBound() - .subst(tparams, tparams0); - } - restps[i] = restp.subst(tparams, tparams0); - } else { - return Type.NoType; - } - break; - default: - return Type.NoType; - } - } - Type[] hibounds = new Type[tparams0.length]; - Type[] lobounds = new Type[tparams0.length]; - for (int j = 0; j < tparams0.length; j++) { - hibounds[j] = glb(hiboundss[j]); - lobounds[j] = lub(loboundss[j]); - } - Symbol[] tparams = new Symbol[tparams0.length]; - for (int j = 0; j < tparams.length; j++) { - tparams[j] = tparams0[j].cloneSymbol(Symbol.NONE) - .setInfo(hibounds[j].subst(tparams0, tparams)) - .setLoBound(lobounds[j].subst(tparams0, tparams)); - } - return Type.PolyType(tparams, lub(restps).subst(tparams0, tparams)); + Type[][] hiboundss = new Type[tparams0.length][tps.length]; + Type[][] loboundss = new Type[tparams0.length][tps.length]; + Type[] restps = new Type[tps.length]; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case PolyType(Symbol[] tparams, Type restp): + if (tparams.length == tparams0.length) { + for (int j = 0; j < tparams0.length; j++) { + hiboundss[j][i] = tparams[j].info() + .subst(tparams, tparams0); + loboundss[j][i] = tparams[j].loBound() + .subst(tparams, tparams0); + } + restps[i] = restp.subst(tparams, tparams0); + } else { + return Type.NoType; + } + break; + default: + return Type.NoType; + } + } + Type[] hibounds = new Type[tparams0.length]; + Type[] lobounds = new Type[tparams0.length]; + for (int j = 0; j < tparams0.length; j++) { + hibounds[j] = glb(hiboundss[j]); + lobounds[j] = lub(loboundss[j]); + } + Symbol[] tparams = new Symbol[tparams0.length]; + for (int j = 0; j < tparams.length; j++) { + tparams[j] = tparams0[j].cloneSymbol(Symbol.NONE) + .setInfo(hibounds[j].subst(tparams0, tparams)) + .setLoBound(lobounds[j].subst(tparams0, tparams)); + } + return Type.PolyType(tparams, lub(restps).subst(tparams0, tparams)); } private static Type methodLub(Type[] tps, Symbol[] vparams0) { - Type[] restps = new Type[tps.length]; - for (int i = 0; i < tps.length; i++) { - switch (tps[i]) { - case MethodType(Symbol[] vparams, Type restp): - if (vparams.length != vparams0.length) - return Type.NoType; - for (int j = 0; j < vparams.length; j++) - if (!vparams[j].type().isSameAs(vparams0[j].type()) || - (vparams[j].flags & (DEF | REPEATED)) != - (vparams0[j].flags & (DEF | REPEATED))) - return Type.NoType; - restps[i] = restp; - } - } - Symbol[] vparams = new Symbol[vparams0.length]; - for (int j = 0; j < vparams.length; j++) { - vparams[j] = vparams0[j].cloneSymbol(Symbol.NONE); - } - return Type.MethodType(vparams, lub(restps)); + Type[] restps = new Type[tps.length]; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case MethodType(Symbol[] vparams, Type restp): + if (vparams.length != vparams0.length) + return Type.NoType; + for (int j = 0; j < vparams.length; j++) + if (!vparams[j].type().isSameAs(vparams0[j].type()) || + (vparams[j].flags & (DEF | REPEATED)) != + (vparams0[j].flags & (DEF | REPEATED))) + return Type.NoType; + restps[i] = restp; + } + } + Symbol[] vparams = new Symbol[vparams0.length]; + for (int j = 0; j < vparams.length; j++) { + vparams[j] = vparams0[j].cloneSymbol(Symbol.NONE); + } + return Type.MethodType(vparams, lub(restps)); } private static Symbol lub(Symbol[] syms, Type[] tps, Type[] lbs, Symbol owner) { - //System.out.println("lub" + ArrayApply.toString(syms));//DEBUG - int lubKind = syms[0].kind; - for (int i = 1; i < syms.length; i++) { - Symbol sym = syms[i]; - if (sym.kind == ERROR) return Symbol.NONE; - if (sym.isType() && sym.kind != lubKind) lubKind = TYPE; - } - if (lubKind == syms[0].kind && tps[0].isSameAsAll(tps)) { - return syms[0].cloneSymbol(); - } - - Type lubType = lub(tps); - if (lubType == Type.NoType) return Symbol.NONE; - Symbol lubSym; - switch (lubKind) { - case VAL: - lubSym = new TermSymbol(syms[0].pos, syms[0].name, owner, 0); - break; - case TYPE: case ALIAS: case CLASS: - lubSym = new AbsTypeSymbol(syms[0].pos, syms[0].name, owner, 0); - lubSym.setLoBound(glb(lbs)); - break; - default: - throw new ApplicationError(); - } - lubSym.setInfo(lubType.setOwner(lubSym)); - return lubSym; + //System.out.println("lub" + ArrayApply.toString(syms));//DEBUG + int lubKind = syms[0].kind; + for (int i = 1; i < syms.length; i++) { + Symbol sym = syms[i]; + if (sym.kind == ERROR) return Symbol.NONE; + if (sym.isType() && sym.kind != lubKind) lubKind = TYPE; + } + if (lubKind == syms[0].kind && tps[0].isSameAsAll(tps)) { + return syms[0].cloneSymbol(); + } + + Type lubType = lub(tps); + if (lubType == Type.NoType) return Symbol.NONE; + Symbol lubSym; + switch (lubKind) { + case VAL: + lubSym = new TermSymbol(syms[0].pos, syms[0].name, owner, 0); + break; + case TYPE: case ALIAS: case CLASS: + lubSym = new AbsTypeSymbol(syms[0].pos, syms[0].name, owner, 0); + lubSym.setLoBound(glb(lbs)); + break; + default: + throw new ApplicationError(); + } + lubSym.setInfo(lubType.setOwner(lubSym)); + return lubSym; } public static Type glb(Type[] tps) { - if (tps.length == 0) return Global.instance.definitions.ANY_TYPE(); - - // step one: eliminate redunandant types; return if one one is left - tps = elimRedundant(tps, false); - if (tps.length == 1) return tps[0]; - - // step two: build arrays of all typerefs and all refinements - Type.List treftl = Type.List.EMPTY; - Type.List comptl = Type.List.EMPTY; - for (int i = 0; i < tps.length; i++) { - switch (tps[i]) { - case TypeRef(_, _, _): - treftl = new Type.List(tps[i], treftl); - break; - case CompoundType(Type[] parents, Scope members): - if (!members.isEmpty()) - comptl = new Type.List(tps[i], comptl); - for (int j = 0; j < parents.length; j++) - treftl = new Type.List(parents[j], treftl); - break; - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - return Global.instance.definitions.ALL_TYPE(); - } - } - - CompoundType glbType = compoundType(Type.EMPTY_ARRAY, new Scope()); - Type glbThisType = glbType.narrow(); - - // step 3: compute glb of all refinements. - Scope members = Scope.EMPTY; - if (comptl != List.EMPTY) { - Type[] comptypes = comptl.toArrayReverse(); - Scope[] refinements = new Scope[comptypes.length]; - for (int i = 0; i < comptypes.length; i++) - refinements[i] = comptypes[i].members(); - if (!setGlb(glbType.members, refinements, glbThisType)) { - // refinements don't have lower bound, so approximate - // by AllRef - glbType.members = Scope.EMPTY; - treftl = new Type.List( - Global.instance.definitions.ALLREF_TYPE(), treftl); - } - } - - // eliminate redudant typerefs - Type[] treftypes = elimRedundant(treftl.toArrayReverse(), false); - if (treftypes.length != 1 || !glbType.members.isEmpty()) { - // step 4: replace all abstract types by their lower bounds. - boolean hasAbstract = false; - for (int i = 0; i < treftypes.length; i++) { - if (treftypes[i].unalias().symbol().kind == TYPE) - hasAbstract = true; - } - if (hasAbstract) { - treftl = Type.List.EMPTY; - for (int i = 0; i < treftypes.length; i++) { - if (treftypes[i].unalias().symbol().kind == TYPE) - treftl = new Type.List(treftypes[i].loBound(), treftl); - else - treftl = new Type.List(treftypes[i], treftl); - } - treftypes = elimRedundant(treftl.toArrayReverse(), false); - } - } - - if (treftypes.length != 1) { - // step 5: if there are conflicting instantiations of same - // class, replace them by lub/glb of arguments or lower bound. - Type lb = NoType; - for (int i = 0; - i < treftypes.length && - lb.symbol() != Global.instance.definitions.ALL_CLASS; - i++) { - for (int j = 0; j < i; j++) { - if (treftypes[j].symbol() == treftypes[i].symbol()) - lb = argGlb(treftypes[j], treftypes[i]); - } - } - if (lb != NoType) return lb; - } - - if (treftypes.length == 1 && glbType.members.isEmpty()) { - return treftypes[0]; - } else { - glbType.parts = treftypes; - return glbType; - } + if (tps.length == 0) return Global.instance.definitions.ANY_TYPE(); + + // step one: eliminate redunandant types; return if one one is left + tps = elimRedundant(tps, false); + if (tps.length == 1) return tps[0]; + + // step two: build arrays of all typerefs and all refinements + Type.List treftl = Type.List.EMPTY; + Type.List comptl = Type.List.EMPTY; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case TypeRef(_, _, _): + treftl = new Type.List(tps[i], treftl); + break; + case CompoundType(Type[] parents, Scope members): + if (!members.isEmpty()) + comptl = new Type.List(tps[i], comptl); + for (int j = 0; j < parents.length; j++) + treftl = new Type.List(parents[j], treftl); + break; + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + return Global.instance.definitions.ALL_TYPE(); + } + } + + CompoundType glbType = compoundType(Type.EMPTY_ARRAY, new Scope()); + Type glbThisType = glbType.narrow(); + + // step 3: compute glb of all refinements. + Scope members = Scope.EMPTY; + if (comptl != List.EMPTY) { + Type[] comptypes = comptl.toArrayReverse(); + Scope[] refinements = new Scope[comptypes.length]; + for (int i = 0; i < comptypes.length; i++) + refinements[i] = comptypes[i].members(); + if (!setGlb(glbType.members, refinements, glbThisType)) { + // refinements don't have lower bound, so approximate + // by AllRef + glbType.members = Scope.EMPTY; + treftl = new Type.List( + Global.instance.definitions.ALLREF_TYPE(), treftl); + } + } + + // eliminate redudant typerefs + Type[] treftypes = elimRedundant(treftl.toArrayReverse(), false); + if (treftypes.length != 1 || !glbType.members.isEmpty()) { + // step 4: replace all abstract types by their lower bounds. + boolean hasAbstract = false; + for (int i = 0; i < treftypes.length; i++) { + if (treftypes[i].unalias().symbol().kind == TYPE) + hasAbstract = true; + } + if (hasAbstract) { + treftl = Type.List.EMPTY; + for (int i = 0; i < treftypes.length; i++) { + if (treftypes[i].unalias().symbol().kind == TYPE) + treftl = new Type.List(treftypes[i].loBound(), treftl); + else + treftl = new Type.List(treftypes[i], treftl); + } + treftypes = elimRedundant(treftl.toArrayReverse(), false); + } + } + + if (treftypes.length != 1) { + // step 5: if there are conflicting instantiations of same + // class, replace them by lub/glb of arguments or lower bound. + Type lb = NoType; + for (int i = 0; + i < treftypes.length && + lb.symbol() != Global.instance.definitions.ALL_CLASS; + i++) { + for (int j = 0; j < i; j++) { + if (treftypes[j].symbol() == treftypes[i].symbol()) + lb = argGlb(treftypes[j], treftypes[i]); + } + } + if (lb != NoType) return lb; + } + + if (treftypes.length == 1 && glbType.members.isEmpty()) { + return treftypes[0]; + } else { + glbType.parts = treftypes; + return glbType; + } } private static Type argGlb(Type tp1, Type tp2) { - switch (tp1) { - case TypeRef(Type pre1, Symbol sym1, Type[] args1): - switch (tp2) { - case TypeRef(Type pre2, Symbol sym2, Type[] args2): - assert sym1 == sym2; - if (pre1.isSameAs(pre2)) { - Symbol[] tparams = sym1.typeParams(); - Type[] args = new Type[tparams.length]; - for (int i = 0; i < tparams.length; i++) { - if (args1[i].isSameAs(args2[i])) - args[i] = args1[i]; - else if ((tparams[i].flags & COVARIANT) != 0) - args[i]= lub(new Type[]{args1[i], args2[i]}); - else if ((tparams[i].flags & CONTRAVARIANT) != 0) - args[i]= glb(new Type[]{args1[i], args2[i]}); - else - return glb(new Type[]{tp1.loBound(), tp2.loBound()}); - } - return typeRef(pre1, sym1, args); - } - } - } - return glb(new Type[]{tp1.loBound(), tp2.loBound()}); + switch (tp1) { + case TypeRef(Type pre1, Symbol sym1, Type[] args1): + switch (tp2) { + case TypeRef(Type pre2, Symbol sym2, Type[] args2): + assert sym1 == sym2; + if (pre1.isSameAs(pre2)) { + Symbol[] tparams = sym1.typeParams(); + Type[] args = new Type[tparams.length]; + for (int i = 0; i < tparams.length; i++) { + if (args1[i].isSameAs(args2[i])) + args[i] = args1[i]; + else if ((tparams[i].flags & COVARIANT) != 0) + args[i]= lub(new Type[]{args1[i], args2[i]}); + else if ((tparams[i].flags & CONTRAVARIANT) != 0) + args[i]= glb(new Type[]{args1[i], args2[i]}); + else + return glb(new Type[]{tp1.loBound(), tp2.loBound()}); + } + return typeRef(pre1, sym1, args); + } + } + } + return glb(new Type[]{tp1.loBound(), tp2.loBound()}); } /** Set scope `result' to glb of scopes `ss'. Return true iff succeeded. */ private static boolean setGlb(Scope result, Scope[] ss, Type glbThisType) { - for (int i = 0; i < ss.length; i++) - for (Scope.SymbolIterator it = ss[i].iterator(); it.hasNext(); ) - if (!addMember(result, it.next(), glbThisType)) return false; - return true; + for (int i = 0; i < ss.length; i++) + for (Scope.SymbolIterator it = ss[i].iterator(); it.hasNext(); ) + if (!addMember(result, it.next(), glbThisType)) return false; + return true; } /** Add member `sym' to scope `s'. If`s' has already a member with same name, * overwrite its info/low bound to form glb of both symbols. */ private static boolean addMember(Scope s, Symbol sym, Type glbThisType) { - Type syminfo = sym.info().substThis(sym.owner(), glbThisType); - Type symlb = sym.loBound().substThis(sym.owner(), glbThisType); - Scope.Entry e = s.lookupEntry(sym.name); - if (e == Scope.Entry.NONE) { - Symbol sym1 = sym.cloneSymbol(glbThisType.symbol()); - sym1.setInfo(syminfo); - if (sym1.kind == TYPE) sym1.setLoBound(symlb); - s.enter(sym1); - } else { - Type einfo = e.sym.info(); - if (einfo.isSameAs(syminfo)) { - } else if (einfo.isSubType(syminfo) && sym.kind != ALIAS) { - } else if (syminfo.isSubType(einfo) && e.sym.kind != ALIAS) { - e.sym.setInfo(syminfo); - } else if (sym.kind == VAL && e.sym.kind == VAL || - sym.kind == TYPE && e.sym.kind == TYPE) { - e.sym.setInfo(glb(new Type[]{einfo, syminfo}).setOwner(e.sym)); - } else { - return false; - } - if (e.sym.kind == TYPE && sym.kind == TYPE) { - Type elb = e.sym.loBound(); - if (elb.isSameAs(symlb)) { - } else if (symlb.isSubType(elb)) { - } else if (elb.isSubType(symlb)) { - e.sym.setLoBound(symlb); - } else { - e.sym.setLoBound(lub(new Type[]{elb, symlb})); - } - } - } - return true; + Type syminfo = sym.info().substThis(sym.owner(), glbThisType); + Type symlb = sym.loBound().substThis(sym.owner(), glbThisType); + Scope.Entry e = s.lookupEntry(sym.name); + if (e == Scope.Entry.NONE) { + Symbol sym1 = sym.cloneSymbol(glbThisType.symbol()); + sym1.setInfo(syminfo); + if (sym1.kind == TYPE) sym1.setLoBound(symlb); + s.enter(sym1); + } else { + Type einfo = e.sym.info(); + if (einfo.isSameAs(syminfo)) { + } else if (einfo.isSubType(syminfo) && sym.kind != ALIAS) { + } else if (syminfo.isSubType(einfo) && e.sym.kind != ALIAS) { + e.sym.setInfo(syminfo); + } else if (sym.kind == VAL && e.sym.kind == VAL || + sym.kind == TYPE && e.sym.kind == TYPE) { + e.sym.setInfo(glb(new Type[]{einfo, syminfo}).setOwner(e.sym)); + } else { + return false; + } + if (e.sym.kind == TYPE && sym.kind == TYPE) { + Type elb = e.sym.loBound(); + if (elb.isSameAs(symlb)) { + } else if (symlb.isSubType(elb)) { + } else if (elb.isSubType(symlb)) { + e.sym.setLoBound(symlb); + } else { + e.sym.setLoBound(lub(new Type[]{elb, symlb})); + } + } + } + return true; } private static Type polyGlb(Type[] tps, Symbol[] tparams0) { - Type[][] hiboundss = new Type[tparams0.length][tps.length]; - Type[][] loboundss = new Type[tparams0.length][tps.length]; - Type[] restps = new Type[tps.length]; - for (int i = 0; i < tps.length; i++) { - switch (tps[i]) { - case PolyType(Symbol[] tparams, Type restp): - if (tparams.length == tparams0.length) { - for (int j = 0; j < tparams0.length; j++) { - hiboundss[j][i] = tparams[j].info() - .subst(tparams, tparams0); - loboundss[j][i] = tparams[j].loBound() - .subst(tparams, tparams0); - } - restps[i] = restp.subst(tparams, tparams0); - } else { - return Type.NoType; - } - break; - default: - return Type.NoType; - } - } - Type[] hibounds = new Type[tparams0.length]; - Type[] lobounds = new Type[tparams0.length]; - for (int j = 0; j < tparams0.length; j++) { - hibounds[j] = lub(hiboundss[j]); - lobounds[j] = glb(loboundss[j]); - } - Symbol[] tparams = new Symbol[tparams0.length]; - for (int j = 0; j < tparams.length; j++) { - tparams[j] = tparams0[j].cloneSymbol(Symbol.NONE) - .setInfo(hibounds[j].subst(tparams0, tparams)) - .setLoBound(lobounds[j].subst(tparams0, tparams)); - } - return Type.PolyType(tparams, glb(restps).subst(tparams0, tparams)); + Type[][] hiboundss = new Type[tparams0.length][tps.length]; + Type[][] loboundss = new Type[tparams0.length][tps.length]; + Type[] restps = new Type[tps.length]; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case PolyType(Symbol[] tparams, Type restp): + if (tparams.length == tparams0.length) { + for (int j = 0; j < tparams0.length; j++) { + hiboundss[j][i] = tparams[j].info() + .subst(tparams, tparams0); + loboundss[j][i] = tparams[j].loBound() + .subst(tparams, tparams0); + } + restps[i] = restp.subst(tparams, tparams0); + } else { + return Type.NoType; + } + break; + default: + return Type.NoType; + } + } + Type[] hibounds = new Type[tparams0.length]; + Type[] lobounds = new Type[tparams0.length]; + for (int j = 0; j < tparams0.length; j++) { + hibounds[j] = lub(hiboundss[j]); + lobounds[j] = glb(loboundss[j]); + } + Symbol[] tparams = new Symbol[tparams0.length]; + for (int j = 0; j < tparams.length; j++) { + tparams[j] = tparams0[j].cloneSymbol(Symbol.NONE) + .setInfo(hibounds[j].subst(tparams0, tparams)) + .setLoBound(lobounds[j].subst(tparams0, tparams)); + } + return Type.PolyType(tparams, glb(restps).subst(tparams0, tparams)); } private static Type methodGlb(Type[] tps, Symbol[] vparams0) { - Type[] restps = new Type[tps.length]; - for (int i = 0; i < tps.length; i++) { - switch (tps[i]) { - case MethodType(Symbol[] vparams, Type restp): - if (vparams.length != vparams0.length) - return Type.NoType; - for (int j = 0; j < vparams.length; j++) - if (!vparams[i].type().isSameAs(vparams0[i].type()) || - (vparams[i].flags & (DEF | REPEATED)) != - (vparams0[i].flags & (DEF | REPEATED))) - return Type.NoType; - restps[i] = restp; - } - } - Symbol[] vparams = new Symbol[vparams0.length]; - for (int j = 0; j < vparams.length; j++) { - vparams[j] = vparams0[j].cloneSymbol(Symbol.NONE); - } - return Type.MethodType(vparams, glb(restps)); + Type[] restps = new Type[tps.length]; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case MethodType(Symbol[] vparams, Type restp): + if (vparams.length != vparams0.length) + return Type.NoType; + for (int j = 0; j < vparams.length; j++) + if (!vparams[i].type().isSameAs(vparams0[i].type()) || + (vparams[i].flags & (DEF | REPEATED)) != + (vparams0[i].flags & (DEF | REPEATED))) + return Type.NoType; + restps[i] = restp; + } + } + Symbol[] vparams = new Symbol[vparams0.length]; + for (int j = 0; j < vparams.length; j++) { + vparams[j] = vparams0[j].cloneSymbol(Symbol.NONE); + } + return Type.MethodType(vparams, glb(restps)); } // Erasure -------------------------------------------------------------------------- public static Map erasureMap = new MapOnlyTypes() { - public Type apply(Type t) { return t.erasure(); } + public Type apply(Type t) { return t.erasure(); } }; private static final Type[] unboxedType = - new Type[LastUnboxedTag + 1 - FirstUnboxedTag]; + new Type[LastUnboxedTag + 1 - FirstUnboxedTag]; private static final Type[] unboxedArrayType = - new Type[LastUnboxedTag + 1 - FirstUnboxedTag]; + new Type[LastUnboxedTag + 1 - FirstUnboxedTag]; private static final Name[] unboxedName = - new Name[LastUnboxedTag + 1 - FirstUnboxedTag]; + new Name[LastUnboxedTag + 1 - FirstUnboxedTag]; private static final Name[] boxedName = - new Name[LastUnboxedTag + 1 - FirstUnboxedTag]; + new Name[LastUnboxedTag + 1 - FirstUnboxedTag]; private static final Name[] boxedFullName = - new Name[LastUnboxedTag + 1 - FirstUnboxedTag]; + new Name[LastUnboxedTag + 1 - FirstUnboxedTag]; private static void mkStdClassType(int kind, String unboxedstr, String boxedstr) { - unboxedType[kind - FirstUnboxedTag] = UnboxedType(kind); - unboxedArrayType[kind - FirstUnboxedTag] = UnboxedArrayType(unboxedType(kind)); - unboxedName[kind - FirstUnboxedTag] = Name.fromString(unboxedstr); - boxedName[kind - FirstUnboxedTag] = Name.fromString(boxedstr); - boxedFullName[kind - FirstUnboxedTag] = Name.fromString("scala." + boxedstr); + unboxedType[kind - FirstUnboxedTag] = UnboxedType(kind); + unboxedArrayType[kind - FirstUnboxedTag] = UnboxedArrayType(unboxedType(kind)); + unboxedName[kind - FirstUnboxedTag] = Name.fromString(unboxedstr); + boxedName[kind - FirstUnboxedTag] = Name.fromString(boxedstr); + boxedFullName[kind - FirstUnboxedTag] = Name.fromString("scala." + boxedstr); } static { - mkStdClassType(BYTE, "byte", "Byte"); - mkStdClassType(SHORT, "short", "Short"); - mkStdClassType(CHAR, "char", "Char"); - mkStdClassType(INT, "int", "Int"); - mkStdClassType(LONG, "long", "Long"); - mkStdClassType(FLOAT, "float", "Float"); - mkStdClassType(DOUBLE, "double", "Double"); - mkStdClassType(BOOLEAN, "boolean", "Boolean"); - mkStdClassType(UNIT, "void", "Unit"); + mkStdClassType(BYTE, "byte", "Byte"); + mkStdClassType(SHORT, "short", "Short"); + mkStdClassType(CHAR, "char", "Char"); + mkStdClassType(INT, "int", "Int"); + mkStdClassType(LONG, "long", "Long"); + mkStdClassType(FLOAT, "float", "Float"); + mkStdClassType(DOUBLE, "double", "Double"); + mkStdClassType(BOOLEAN, "boolean", "Boolean"); + mkStdClassType(UNIT, "void", "Unit"); } /** Return unboxed type of given kind. */ public static Type unboxedType(int kind) { - return unboxedType[kind - FirstUnboxedTag]; + return unboxedType[kind - FirstUnboxedTag]; } /** Return unboxed array type of given element kind. */ public static Type unboxedArrayType(int kind) { - return unboxedArrayType[kind - FirstUnboxedTag]; + return unboxedArrayType[kind - FirstUnboxedTag]; } /** Return the name of unboxed type of given kind. */ public static Name unboxedName(int kind) { - return unboxedName[kind - FirstUnboxedTag]; + return unboxedName[kind - FirstUnboxedTag]; } /** Return the name of boxed type of given kind. */ public static Name boxedName(int kind) { - return boxedName[kind - FirstUnboxedTag]; + return boxedName[kind - FirstUnboxedTag]; } /** Return the full name of boxed type of given kind. */ public static Name boxedFullName(int kind) { - return boxedFullName[kind - FirstUnboxedTag]; + return boxedFullName[kind - FirstUnboxedTag]; } /** If type is boxed, return its unboxed equivalent; otherwise return the type * itself. */ public Type unbox() { - switch (this) { - case TypeRef(Type pre, Symbol sym, Type[] args): - if ((sym.flags & MODUL) == 0) { - Name fullname = sym.fullName(); - if (fullname == Names.scala_Array && args.length == 1) { + switch (this) { + case TypeRef(Type pre, Symbol sym, Type[] args): + if ((sym.flags & MODUL) == 0) { + Name fullname = sym.fullName(); + if (fullname == Names.scala_Array && args.length == 1) { Type item = args[0].unalias(); Type bound = item.upperBound(); - // todo: check with Philippe if this is what we want. + // todo: check with Philippe if this is what we want. if (item.symbol().isClass() || (bound.symbol() != Global.instance.definitions.ANY_CLASS && bound.symbol() != Global.instance.definitions.ANYVAL_CLASS)) @@ -2981,72 +2981,72 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { for (int i = 0; i < boxedFullName.length; i++) { if (boxedFullName[i] == fullname) return unboxedType[i]; } - } - } - return this; + } + } + return this; } //where - private Type upperBound() { - switch (this) { - case TypeRef(Type pre, Symbol sym, Type[] args): - if (sym.kind == ALIAS && sym.typeParams().length == args.length - || sym.kind == TYPE) - return pre.memberInfo(sym).upperBound(); - } - return this; - } + private Type upperBound() { + switch (this) { + case TypeRef(Type pre, Symbol sym, Type[] args): + if (sym.kind == ALIAS && sym.typeParams().length == args.length + || sym.kind == TYPE) + return pre.memberInfo(sym).upperBound(); + } + return this; + } /** Return the erasure of this type. */ public Type erasure() { - switch (this) { - case ThisType(_): - case SingleType(_, _): - case ConstantType(_, _): - return singleDeref().erasure(); - case TypeRef(Type pre, Symbol sym, Type[] args): - switch (sym.kind) { - case ALIAS: case TYPE: - return sym.info().asSeenFrom(pre, sym.owner()).erasure(); - - case CLASS: + switch (this) { + case ThisType(_): + case SingleType(_, _): + case ConstantType(_, _): + return singleDeref().erasure(); + case TypeRef(Type pre, Symbol sym, Type[] args): + switch (sym.kind) { + case ALIAS: case TYPE: + return sym.info().asSeenFrom(pre, sym.owner()).erasure(); + + case CLASS: if (sym == Global.instance.definitions.UNIT_CLASS) return this; - Name fullname = sym.fullName(); - if (fullname == Names.java_lang_Object || - fullname == Names.scala_AnyRef || - fullname == Names.scala_AnyVal || - fullname == Names.scala_All || - fullname == Names.scala_AllRef) - return TypeRef(localThisType, Global.instance.definitions.ANY_CLASS, EMPTY_ARRAY); - else { - Type this1 = unbox(); - if (this1 != this) return this1; + Name fullname = sym.fullName(); + if (fullname == Names.java_lang_Object || + fullname == Names.scala_AnyRef || + fullname == Names.scala_AnyVal || + fullname == Names.scala_All || + fullname == Names.scala_AllRef) + return TypeRef(localThisType, Global.instance.definitions.ANY_CLASS, EMPTY_ARRAY); + else { + Type this1 = unbox(); + if (this1 != this) return this1; else return TypeRef(localThisType, sym, EMPTY_ARRAY); - } - - default: throw new ApplicationError(sym + " has wrong kind: " + sym.kind); - } - case CompoundType(Type[] parents, _): - if (parents.length > 0) return parents[0].erasure(); - else return this; - case MethodType(Symbol[] params, Type tp): - Symbol[] params1 = erasureMap.map(params); - Type tp1 = tp.fullErasure(); - switch (tp1) { - case MethodType(Symbol[] params2, Type tp2): - Symbol[] newparams = new Symbol[params1.length + params2.length]; - System.arraycopy(params1, 0, newparams, 0, params1.length); - System.arraycopy(params2, 0, newparams, params1.length, params2.length); - return MethodType(newparams, tp2); - default: - if (params1 == params && tp1 == tp) return this; - else return MethodType(params1, tp1); - } - case PolyType(_, Type result): - return result.erasure(); - default: - return erasureMap.map(this); - } + } + + default: throw new ApplicationError(sym + " has wrong kind: " + sym.kind); + } + case CompoundType(Type[] parents, _): + if (parents.length > 0) return parents[0].erasure(); + else return this; + case MethodType(Symbol[] params, Type tp): + Symbol[] params1 = erasureMap.map(params); + Type tp1 = tp.fullErasure(); + switch (tp1) { + case MethodType(Symbol[] params2, Type tp2): + Symbol[] newparams = new Symbol[params1.length + params2.length]; + System.arraycopy(params1, 0, newparams, 0, params1.length); + System.arraycopy(params2, 0, newparams, params1.length, params2.length); + return MethodType(newparams, tp2); + default: + if (params1 == params && tp1 == tp) return this; + else return MethodType(params1, tp1); + } + case PolyType(_, Type result): + return result.erasure(); + default: + return erasureMap.map(this); + } } /** Return the full erasure of the type. Full erasure is the same @@ -3067,164 +3067,164 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } public String toLongString() { - String str = toString(); - if (str.endsWith(".type")) return str + " (with underlying type " + widen() + ")"; - else return str; + String str = toString(); + if (str.endsWith(".type")) return str + " (with underlying type " + widen() + ")"; + else return str; } public int hashCode() { - switch (this) { - case ErrorType: - return ERROR; - case NoType: - return NOtpe; - case ThisType(Symbol sym): - return THIStpe - ^ (sym.hashCode() * 41); - case TypeRef(Type pre, Symbol sym, Type[] args): - return TYPEREFtpe - ^ (pre.hashCode() * 41) - ^ (sym.hashCode() * (41*41)) + switch (this) { + case ErrorType: + return ERROR; + case NoType: + return NOtpe; + case ThisType(Symbol sym): + return THIStpe + ^ (sym.hashCode() * 41); + case TypeRef(Type pre, Symbol sym, Type[] args): + return TYPEREFtpe + ^ (pre.hashCode() * 41) + ^ (sym.hashCode() * (41*41)) ^ (hashCode(args) * (41*41*41)); - case SingleType(Type pre, Symbol sym): - 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 - // ^ (hashCode(parts) * 41) - // ^ (members.hashCode() * (41 * 41)); - case MethodType(Symbol[] vparams, Type result): - int h = METHODtpe; - for (int i = 0; i < vparams.length; i++) - h = (h << 4) ^ (vparams[i].flags & SOURCEFLAGS); - return h - ^ (hashCode(Symbol.type(vparams)) * 41) - ^ (result.hashCode() * (41 * 41)); - case PolyType(Symbol[] tparams, Type result): - return POLYtpe - ^ (hashCode(tparams) * 41) - ^ (result.hashCode() * (41 * 41)); - case OverloadedType(Symbol[] alts, Type[] alttypes): - return OVERLOADEDtpe - ^ (hashCode(alts) * 41) - ^ (hashCode(alttypes) * (41 * 41)); - case UnboxedType(int kind): - return UNBOXEDtpe - ^ (kind * 41); - case UnboxedArrayType(Type elemtp): - return UNBOXEDARRAYtpe - ^ (elemtp.hashCode() * 41); - default: - throw new ApplicationError(); - } + case SingleType(Type pre, Symbol sym): + 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 + // ^ (hashCode(parts) * 41) + // ^ (members.hashCode() * (41 * 41)); + case MethodType(Symbol[] vparams, Type result): + int h = METHODtpe; + for (int i = 0; i < vparams.length; i++) + h = (h << 4) ^ (vparams[i].flags & SOURCEFLAGS); + return h + ^ (hashCode(Symbol.type(vparams)) * 41) + ^ (result.hashCode() * (41 * 41)); + case PolyType(Symbol[] tparams, Type result): + return POLYtpe + ^ (hashCode(tparams) * 41) + ^ (result.hashCode() * (41 * 41)); + case OverloadedType(Symbol[] alts, Type[] alttypes): + return OVERLOADEDtpe + ^ (hashCode(alts) * 41) + ^ (hashCode(alttypes) * (41 * 41)); + case UnboxedType(int kind): + return UNBOXEDtpe + ^ (kind * 41); + case UnboxedArrayType(Type elemtp): + return UNBOXEDARRAYtpe + ^ (elemtp.hashCode() * 41); + default: + throw new ApplicationError(); + } } public static int hashCode(Object[] elems) { - int h = 0; - for (int i = 0; i < elems.length; i++) - h = h * 41 + elems[i].hashCode(); - return h; + int h = 0; + for (int i = 0; i < elems.length; i++) + h = h * 41 + elems[i].hashCode(); + return h; } // todo: change in relation to needs. public boolean equals(Object other) { - if (this == other) { - return true; - } else if (other instanceof Type) { - Type that = (Type) other; - switch (this) { - case ErrorType: - return that == ErrorType; - case NoType: - return that == NoType; - case ThisType(Symbol sym): - switch (that) { - case ThisType(Symbol sym1): - return sym == sym1; - default: return false; - } - case TypeRef(Type pre, Symbol sym, Type[] args): - switch (that) { - case TypeRef(Type pre1, Symbol sym1, Type[] args1): - return pre.equals(pre1) && sym == sym1 && equals(args, args1); - default: return false; - } - case SingleType(Type pre, Symbol sym): - switch (that) { - case SingleType(Type pre1, Symbol sym1): - 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): - return this.symbol() == that.symbol(); - //return parts.equals(parts1) && members.equals(members1); - default: return false; - } - case MethodType(Symbol[] vparams, Type result): - switch (that) { - case MethodType(Symbol[] vparams1, Type result1): - if (vparams.length != vparams1.length) - return false; - for (int i = 0; i < vparams.length; i++) - if ((vparams[i].flags & SOURCEFLAGS) != - (vparams1[i].flags & SOURCEFLAGS)) - return false; - return - equals(Symbol.type(vparams), Symbol.type(vparams1)) && - result.equals(result1); - default: return false; - } - case PolyType(Symbol[] tparams, Type result): - switch (that) { - case PolyType(Symbol[] tparams1, Type result1): - return equals(tparams, tparams1) && result.equals(result1); - default: return false; - } - case OverloadedType(Symbol[] alts, Type[] alttypes): - switch (that) { - case OverloadedType(Symbol[] alts1, Type[] alttypes1): - return equals(alts, alts1) && equals(alttypes, alttypes1); - default: return false; - } - case UnboxedType(int kind): - switch (that) { - case UnboxedType(int kind1): - return kind == kind1; - default: return false; - } - case UnboxedArrayType(Type elemtp): - switch (that) { - case UnboxedArrayType(Type elemtp1): - return elemtp.equals(elemtp1); - default: return false; - } - default: - } - } - return false; + if (this == other) { + return true; + } else if (other instanceof Type) { + Type that = (Type) other; + switch (this) { + case ErrorType: + return that == ErrorType; + case NoType: + return that == NoType; + case ThisType(Symbol sym): + switch (that) { + case ThisType(Symbol sym1): + return sym == sym1; + default: return false; + } + case TypeRef(Type pre, Symbol sym, Type[] args): + switch (that) { + case TypeRef(Type pre1, Symbol sym1, Type[] args1): + return pre.equals(pre1) && sym == sym1 && equals(args, args1); + default: return false; + } + case SingleType(Type pre, Symbol sym): + switch (that) { + case SingleType(Type pre1, Symbol sym1): + 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): + return this.symbol() == that.symbol(); + //return parts.equals(parts1) && members.equals(members1); + default: return false; + } + case MethodType(Symbol[] vparams, Type result): + switch (that) { + case MethodType(Symbol[] vparams1, Type result1): + if (vparams.length != vparams1.length) + return false; + for (int i = 0; i < vparams.length; i++) + if ((vparams[i].flags & SOURCEFLAGS) != + (vparams1[i].flags & SOURCEFLAGS)) + return false; + return + equals(Symbol.type(vparams), Symbol.type(vparams1)) && + result.equals(result1); + default: return false; + } + case PolyType(Symbol[] tparams, Type result): + switch (that) { + case PolyType(Symbol[] tparams1, Type result1): + return equals(tparams, tparams1) && result.equals(result1); + default: return false; + } + case OverloadedType(Symbol[] alts, Type[] alttypes): + switch (that) { + case OverloadedType(Symbol[] alts1, Type[] alttypes1): + return equals(alts, alts1) && equals(alttypes, alttypes1); + default: return false; + } + case UnboxedType(int kind): + switch (that) { + case UnboxedType(int kind1): + return kind == kind1; + default: return false; + } + case UnboxedArrayType(Type elemtp): + switch (that) { + case UnboxedArrayType(Type elemtp1): + return elemtp.equals(elemtp1); + default: return false; + } + default: + } + } + return false; } public static boolean equals(Object[] elems1, Object[] elems2) { - if (elems1.length != elems2.length) return false; - for (int i = 0; i < elems1.length; i++) { - if (!elems1[i].equals(elems2[i])) return false; - } - return true; + if (elems1.length != elems2.length) return false; + for (int i = 0; i < elems1.length; i++) { + if (!elems1[i].equals(elems2[i])) return false; + } + return true; } // Type.List class ----------------------------------------------------------------- @@ -3232,42 +3232,42 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { /** A class for lists of types. */ public static class List { - public Type head; - public List tail; - public List(Type head, List tail) { - this.head = head; this.tail = tail; - } - public int length() { - return (this == EMPTY) ? 0 : 1 + tail.length(); - } - public Type[] toArray() { - Type[] ts = new Type[length()]; - copyToArray(ts, 0, 1); - return ts; - } - public void copyToArray(Type[] ts, int start, int delta) { - if (this != EMPTY) { - ts[start] = head; - tail.copyToArray(ts, start+delta, delta); - } - } - public Type[] toArrayReverse() { - Type[] ts = new Type[length()]; - copyToArray(ts, ts.length - 1, -1); - return ts; - } - - public String toString() { - if (this == EMPTY) return "List()"; - else return head + "::" + tail; - } - - public static List EMPTY = new List(null, null); - - public static List append(List l, Type tp) { - return (l == EMPTY) ? new List(tp, EMPTY) - : new List(l.head, append(l.tail, tp)); - } + public Type head; + public List tail; + public List(Type head, List tail) { + this.head = head; this.tail = tail; + } + public int length() { + return (this == EMPTY) ? 0 : 1 + tail.length(); + } + public Type[] toArray() { + Type[] ts = new Type[length()]; + copyToArray(ts, 0, 1); + return ts; + } + public void copyToArray(Type[] ts, int start, int delta) { + if (this != EMPTY) { + ts[start] = head; + tail.copyToArray(ts, start+delta, delta); + } + } + public Type[] toArrayReverse() { + Type[] ts = new Type[length()]; + copyToArray(ts, ts.length - 1, -1); + return ts; + } + + public String toString() { + if (this == EMPTY) return "List()"; + else return head + "::" + tail; + } + + public static List EMPTY = new List(null, null); + + public static List append(List l, Type tp) { + return (l == EMPTY) ? new List(tp, EMPTY) + : new List(l.head, append(l.tail, tp)); + } } // Type.Constraint class ------------------------------------------------------- @@ -3276,20 +3276,20 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { * of type variables. */ public static class Constraint { - public List lobounds = List.EMPTY; - public List hibounds = List.EMPTY; - public Type inst = NoType; - - public boolean instantiate(Type tp) { - for (List l = lobounds; l != List.EMPTY; l = l.tail) { - if (!l.head.isSubType(tp)) return false; - } - for (List l = hibounds; l != List.EMPTY; l = l.tail) { - if (!tp.isSubType(l.head)) return false; - } - inst = tp; - return true; - } + public List lobounds = List.EMPTY; + public List hibounds = List.EMPTY; + public Type inst = NoType; + + public boolean instantiate(Type tp) { + for (List l = lobounds; l != List.EMPTY; l = l.tail) { + if (!l.head.isSubType(tp)) return false; + } + for (List l = hibounds; l != List.EMPTY; l = l.tail) { + if (!tp.isSubType(l.head)) return false; + } + inst = tp; + return true; + } } // Type.Error class -------------------------------------------------------------- @@ -3297,34 +3297,34 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { /** A class for throwing type errors */ public static class Error extends java.lang.Error { - public String msg; - public Error(String msg) { - super(msg); - this.msg = msg; - } + public String msg; + public Error(String msg) { + super(msg); + this.msg = msg; + } } public static class Malformed extends Error { - public Malformed(Type pre, String tp) { - super("malformed type: " + pre + "#" + tp); - } + public Malformed(Type pre, String tp) { + super("malformed type: " + pre + "#" + tp); + } } /** A class for throwing type errors */ public static class VarianceError extends Error { - public VarianceError(String msg) { - super(msg); - } + public VarianceError(String msg) { + super(msg); + } } public static void explainTypes(Type found, Type required) { - if (Global.instance.explaintypes) { - boolean s = explainSwitch; - explainSwitch = true; - found.isSubType(required); - explainSwitch = s; - } + if (Global.instance.explaintypes) { + boolean s = explainSwitch; + explainSwitch = true; + found.isSubType(required); + explainSwitch = s; + } } } diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java index 7de745ee1f..3e1ac9da20 100644 --- a/sources/scalac/symtab/classfile/AttributeParser.java +++ b/sources/scalac/symtab/classfile/AttributeParser.java @@ -34,6 +34,8 @@ public class AttributeParser implements ClassfileConstants { this.parser = parser; } + /** convert an attribute name into an attribute id + */ public int nameToId(Name name) { if (name == SOURCEFILE_N) return SOURCEFILE_ATTR; @@ -62,6 +64,9 @@ public class AttributeParser implements ClassfileConstants { return BAD_ATTR; } + /** read all attributes associated with symbol 'sym' which are + * contained in 'attrs'. + */ public Symbol readAttributes(Symbol def, Type type, int attrs) { char nattr = in.nextChar(); for (int i = 0; i < nattr; i++) { @@ -79,6 +84,8 @@ public class AttributeParser implements ClassfileConstants { return def; } + /** read a single attribute 'attr' for symbol 'sym' with type 'type'. + */ public void readAttribute(Symbol sym, Type type, int attr, int attrLen) { switch (attr) { // class attributes @@ -93,9 +100,9 @@ public class AttributeParser implements ClassfileConstants { Name name = (Name)pool.readPool(in.nextChar()); int flags = in.nextChar(); if (name != null) { - inner.owner(outer); - inner.mangled(name); - inner.flags = flags; + // inner.owner(outer); + // inner.mangled(name); + // inner.flags = flags; } } */ in.skip(attrLen); @@ -126,9 +133,9 @@ public class AttributeParser implements ClassfileConstants { sym.flags |= Modifiers.DEPRECATED; return; case CONSTANT_VALUE_ATTR: - // Type ctype = (Type)reader.readPool(in.nextChar()); - // def.type = types.coerce(ctype, def.type); - in.skip(attrLen); + Object constVal = pool.readPool(in.nextChar()); + //System.out.println(sym.owner() + "." + sym + ": " + constVal + " of type " + constantType(type, constVal)); + sym.setFirstInfo(constantType(type, constVal)); return; case META_ATTR: //System.out.println("parsing meta data for " + sym); @@ -152,10 +159,45 @@ public class AttributeParser implements ClassfileConstants { } } + /** return the constant type for the given constant. + */ + Type constantType(Type base, Object value) { + if (base.symbol() == parser.global.definitions.BYTE_CLASS) + value = new Byte(((Number)value).byteValue()); + if (base.symbol() == parser.global.definitions.CHAR_CLASS) + value = new Character((char)((Number)value).intValue()); + if (base.symbol() == parser.global.definitions.SHORT_CLASS) + value = new Short(((Number)value).shortValue()); + return Type.ConstantType(base, value); + } + + /** return the type of a given constant. + */ + Type typeOfValue(Object value) { + if (value instanceof Character) + return parser.make.charType(); + else if (value instanceof Integer) + return parser.make.intType(); + else if (value instanceof Long) + return parser.make.longType(); + else if (value instanceof Float) + return parser.make.floatType(); + else if (value instanceof Double) + return parser.make.doubleType(); + else if (value instanceof String) + return parser.global.definitions.JAVA_STRING_CLASS.typeConstructor(); + else if (value instanceof Boolean) + return parser.make.booleanType(); + else + throw new ApplicationError("unknown constant type"); + } + Scope tvars = new Scope(); + /** a parser class for parsing meta type information in classfiles + * generated by pico. + */ class MetaParser { - Symbol owner; StringTokenizer scanner; Type defaultType; diff --git a/sources/scalac/symtab/classfile/ConstantPool.java b/sources/scalac/symtab/classfile/ConstantPool.java index 4260b9e6ad..a4113ed9e7 100644 --- a/sources/scalac/symtab/classfile/ConstantPool.java +++ b/sources/scalac/symtab/classfile/ConstantPool.java @@ -97,14 +97,11 @@ public class ConstantPool implements ClassfileConstants { case CONSTANT_UTF8: poolObj[i] = Name.fromAscii(in.buf, index + 3, in.getChar(index + 1)); break; - case CONSTANT_UNICODE: throw new RuntimeException("can't read unicode strings in classfiles"); - case CONSTANT_CLASS: poolObj[i] = classOrType(readExternal(in.getChar(index + 1))); break; - case CONSTANT_FIELDREF: { //Symbol owner = (Symbol)readPool(in.getChar(index + 1)); //NameAndType nt = (NameAndType)readPool(in.getChar(index + 3)); @@ -112,7 +109,6 @@ public class ConstantPool implements ClassfileConstants { // .type(sigparser.sigToType(Name.names, nt.sig.index, nt.sig.length())); throw new RuntimeException("can't read constant_fieldrefs in classfiles"); } - case CONSTANT_METHODREF: case CONSTANT_INTFMETHODREF: { //Symbol owner = (Symbol)readPool(in.getChar(index + 1)); @@ -121,19 +117,25 @@ public class ConstantPool implements ClassfileConstants { // .type(sigparser.sigToType(Name.names, nt.sig.index, nt.sig.length())); throw new RuntimeException("can't read constant_methodrefs in classfiles"); } - case CONSTANT_NAMEANDTYPE: poolObj[i] = new NameAndType((Name)readPool(in.getChar(index + 1)), readExternal(in.getChar(index + 3))); break; - case CONSTANT_STRING: + poolObj[i] = ((Name)readPool(in.getChar(index + 1))).toString(); + break; case CONSTANT_INTEGER: + poolObj[i] = new Integer(in.getInt(index + 1)); + break; case CONSTANT_FLOAT: + poolObj[i] = new Float(in.getFloat(index + 1)); + break; case CONSTANT_LONG: + poolObj[i] = new Long(in.getLong(index + 1)); + break; case CONSTANT_DOUBLE: - throw new RuntimeException("can't read constants in classfiles"); - + poolObj[i] = new Double(in.getDouble(index + 1)); + break; default: throw new RuntimeException("bad constant pool tag: " + in.byteAt(index)); } diff --git a/sources/scalac/transformer/TransMatch.java b/sources/scalac/transformer/TransMatch.java index 4cea1d9770..5942f28b94 100644 --- a/sources/scalac/transformer/TransMatch.java +++ b/sources/scalac/transformer/TransMatch.java @@ -91,25 +91,24 @@ public class TransMatch extends OwnerTransformer { int i = 0; while (i < cases.length) { containsReg = TestRegTraverser.apply(cases[i]) || containsReg; - Set nilvars = TestRegTraverser.getNilVariables(); - if(!nilvars.isEmpty()) { - //System.err.println("nilvars present"); - Tree[] newBody = new Tree[ nilvars.size() + 1 ]; - int j=0; - for( Iterator it = nilvars.iterator(); it.hasNext(); ) { - Symbol v = (Symbol) it.next(); - newBody[ j++ ] = unit.global.treeGen.ValDef(v, - unit.global.treeGen.Nil(cases[i].pos)); - } - newBody[ newBody.length - 1 ] = cases[i].body; - cases[i].body = unit.global.treeGen.mkBlock( newBody ); - } - i++; - } - + Set nilvars = TestRegTraverser.getNilVariables(); + if(!nilvars.isEmpty()) { + //System.err.println("nilvars present"); + Tree[] newBody = new Tree[ nilvars.size() + 1 ]; + int j=0; + for( Iterator it = nilvars.iterator(); it.hasNext(); ) { + Symbol v = (Symbol) it.next(); + newBody[ j++ ] = unit.global.treeGen.ValDef(v, + unit.global.treeGen.Nil(cases[i].pos)); + } + newBody[ newBody.length - 1 ] = cases[i].body; + cases[i].body = unit.global.treeGen.mkBlock( newBody ); + } + i++; + } if (containsReg) { - AlgebraicMatcher am = new AlgebraicMatcher( unit ); - Matcher matcher = new Matcher( currentOwner, root, restpe ); + AlgebraicMatcher am = new AlgebraicMatcher( unit ); + Matcher matcher = new Matcher( currentOwner, root, restpe ); am.construct( matcher, cases ); return matcher.tree; } else { @@ -117,7 +116,7 @@ public class TransMatch extends OwnerTransformer { currentOwner, restpe); pm.enter(cases); if (global.log()) { - global.log("internal pattern matching structure"); + global.log("internal pattern matching structure"); pm.print(); } return pm.toTree(); diff --git a/sources/scalac/transformer/matching/AlgebraicMatcher.java b/sources/scalac/transformer/matching/AlgebraicMatcher.java index 9bcddb3e11..4708dd6258 100644 --- a/sources/scalac/transformer/matching/AlgebraicMatcher.java +++ b/sources/scalac/transformer/matching/AlgebraicMatcher.java @@ -53,6 +53,10 @@ public class AlgebraicMatcher extends PatternMatcher { for( int i = 0; i < cases.length; i++ ) { enter( cases[ i ] );//(CaseDef) cases[i], i); } + if (unit.global.log()) { + unit.global.log("internal pattern matching structure"); + print(); + } _m.tree = toTree(); } diff --git a/sources/scalac/transformer/matching/PatternMatcher.java b/sources/scalac/transformer/matching/PatternMatcher.java index 99a921e2e4..793cc83a7e 100644 --- a/sources/scalac/transformer/matching/PatternMatcher.java +++ b/sources/scalac/transformer/matching/PatternMatcher.java @@ -52,7 +52,7 @@ public class PatternMatcher extends PatternTool { public PatternMatcher(Unit unit, Tree selector, Symbol owner, Type resultType) { super(unit); - initialize(selector, owner, resultType, true); + initialize(selector, owner, resultType, true); } /** constructor, used in subclass ALgebraicMatcher @@ -75,10 +75,10 @@ public class PatternMatcher extends PatternTool { owner, Modifiers.MUTABLE); this.resultVar.setType(resultType); - this.owner = owner; + this.owner = owner; this.selector = selector; this.optimize &= (unit.global.target == Global.TARGET_JVM); - this.doBinding = doBinding; + this.doBinding = doBinding; } /** pretty printer @@ -160,8 +160,18 @@ public class PatternMatcher extends PatternTool { if (patNode.or != null) print(patNode.or, ind); break; - case Body(_, _, Tree[] stats): - System.out.println(indent + "BODY(" + stats.length + ")"); + case AltPat(Header header): + System.out.println(indent + "-- ALTERNATIVES:"); + print(header, indent + " * "); + print(patNode.and, indent + " * -> "); + if (patNode.or != null) + print(patNode.or, indent); + break; + case Body(_, Tree[] guards, Tree[] stats): + if ((guards.length == 0) && (stats.length == 0)) + System.out.println(indent + "true"); + else + System.out.println(indent + "BODY(" + stats.length + ")"); break; } } @@ -187,9 +197,8 @@ public class PatternMatcher extends PatternTool { target.and = mk.Body(caseDef.pos, env.boundVars(), guard, body); else if (target.and instanceof Body) updateBody((Body)target.and, env.boundVars(), guard, body); - else { + else unit.error(pat.pos, "duplicate case"); - } } } @@ -274,82 +283,81 @@ public class PatternMatcher extends PatternTool { } protected boolean isSeqApply( Tree.Apply tree ) { - return (tree.args.length == 1 && - (tree.type.symbol().flags & Modifiers.CASE) == 0); + return (tree.args.length == 1 && + (tree.type.symbol().flags & Modifiers.CASE) == 0); } protected PatternNode patternNode(Tree tree, Header header, CaseEnv env) { switch (tree) { - case Bind(Name name, Typed( Ident( Names.PATTERN_WILDCARD ), Tree tpe)): // little opt. for x@_:Type - if(header.type.isSubType(tpe.type)) { - PatternNode node = mk.DefaultPat(tree.pos, tpe.type); - env.newBoundVar( tree.symbol(), tree.type, header.selector ); - return node; - } else { - ConstrPat node = mk.ConstrPat(tree.pos, tpe.type); - env.newBoundVar( tree.symbol(), tree.type, gen.Ident(tree.pos, node.casted)); - return node; - } - case Bind(Name name, Ident( Names.PATTERN_WILDCARD )): // little opt. for x@_ - PatternNode node = mk.DefaultPat(tree.pos, header.type); - if ((env != null) && (tree.symbol() != defs.PATTERN_WILDCARD)) - env.newBoundVar(tree.symbol(),tree.type, header.selector); - return node; - - case Bind(Name name, Tree pat): - PatternNode node = patternNode(pat, header, env); - if ((env != null) && (tree.symbol() != defs.PATTERN_WILDCARD)) - env.newBoundVar( tree.symbol(), - tree.type, - header.selector); + case Bind(Name name, Typed( Ident( Names.PATTERN_WILDCARD ), Tree tpe)): // little opt. for x@_:Type + if(header.type.isSubType(tpe.type)) { + PatternNode node = mk.DefaultPat(tree.pos, tpe.type); + env.newBoundVar( tree.symbol(), tree.type, header.selector ); + return node; + } else { + ConstrPat node = mk.ConstrPat(tree.pos, tpe.type); + env.newBoundVar( tree.symbol(), tree.type, gen.Ident(tree.pos, node.casted)); + return node; + } + case Bind(Name name, Ident( Names.PATTERN_WILDCARD )): // little opt. for x@_ + PatternNode node = mk.DefaultPat(tree.pos, header.type); + if ((env != null) && (tree.symbol() != defs.PATTERN_WILDCARD)) + env.newBoundVar(tree.symbol(),tree.type, header.selector); + return node; + + case Bind(Name name, Tree pat): + PatternNode node = patternNode(pat, header, env); + if ((env != null) && (tree.symbol() != defs.PATTERN_WILDCARD)) + env.newBoundVar( tree.symbol(), + tree.type, + header.selector); + return node; + case Apply(Tree fn, Tree[] args): // pattern with args + if(isSeqApply((Apply)tree)) { + if (!delegateSequenceMatching) { + switch (args[0]) { + case Sequence(Tree[] ts): + return mk.SequencePat( tree.pos, tree.type, ts.length ); + } + } else { + PatternNode res = mk.ConstrPat(tree.pos, tree.type); + res.and = mk.Header(tree.pos, header.type, header.selector); + res.and.and = mk.SeqContainerPat( tree.pos, tree.type, args[ 0 ] ); + return res; + } + } else if ((fn.symbol() != null) && fn.symbol().isStable()) + return mk.VariablePat(tree.pos, tree); + return mk.ConstrPat(tree.pos, tree.type); + case Typed(Ident ident, Tree tpe): // variable pattern + boolean doTest = header.type.isSubType(tpe.type); + PatternNode node = doTest ? + mk.DefaultPat(tree.pos, tpe.type) + : mk.ConstrPat(tree.pos, tpe.type); + if ((env != null) && (ident.symbol() != defs.PATTERN_WILDCARD)) + switch (node) { + case ConstrPat(Symbol casted): + env.newBoundVar( + ((Tree.Typed)tree).expr.symbol(), + tpe.type, + gen.Ident(tree.pos, casted)); + break; + default: + env.newBoundVar( + ((Tree.Typed)tree).expr.symbol(), + tpe.type, + doTest ? header.selector : gen.Ident(tree.pos, ((ConstrPat) node).casted)); + } return node; - case Apply(Tree fn, Tree[] args): // pattern with args - if( isSeqApply((Apply) tree ) ) { - if ( !delegateSequenceMatching ) { - switch (args[0]) { - case Sequence(Tree[] ts): - return mk.SequencePat( tree.pos, tree.type, ts.length ); - } - } else { - PatternNode res = mk.ConstrPat(tree.pos, tree.type); - res.and = mk.Header(tree.pos, header.type, header.selector); - res.and.and = mk.SeqContainerPat( tree.pos, tree.type, args[ 0 ] ); - return res; - } - } - return mk.ConstrPat(tree.pos, tree.type); - - case Typed(Ident ident, Tree tpe): // variable pattern - boolean doTest = header.type.isSubType(tpe.type); - PatternNode node = doTest ? - mk.DefaultPat(tree.pos, tpe.type) - : mk.ConstrPat(tree.pos, tpe.type); - if ((env != null) && (ident.symbol() != defs.PATTERN_WILDCARD)) - switch (node) { - case ConstrPat(Symbol casted): - env.newBoundVar( - ((Tree.Typed)tree).expr.symbol(), - tpe.type, - gen.Ident(tree.pos, casted)); - break; - default: - env.newBoundVar( - ((Tree.Typed)tree).expr.symbol(), - tpe.type, - doTest ? header.selector : gen.Ident(tree.pos, ((ConstrPat) node).casted)); - } - return node; - case Ident(Name name): // pattern without args or variable - if (tree.symbol() == defs.PATTERN_WILDCARD) + case Ident(Name name): // pattern without args or variable + if (tree.symbol() == defs.PATTERN_WILDCARD) return mk.DefaultPat(tree.pos, header.type); else if (tree.symbol().isPrimaryConstructor()) { - assert false; // this may not happen ?? ----------------- Burak - return mk.ConstrPat(tree.pos, tree.type); + assert false; // this may not happen ?? ----------------- Burak + return mk.ConstrPat(tree.pos, tree.type); } else if (name.isVariable()) {// should be Bind ------------ Burak - assert false; + assert false; if (env != null) - env.newBoundVar( - tree.symbol(), + env.newBoundVar(tree.symbol(), tree.type, header.selector); return mk.DefaultPat(tree.pos, header.type); @@ -368,17 +376,19 @@ public class PatternMatcher extends PatternTool { } else { return mk.SeqContainerPat(tree.pos, tree.type, tree); } - case Alternative(Tree[] ts): // CAN THIS WORK ? - assert ts.length > 0; - PatternNode res = patternNode( ts[ 0 ], header, env ); - for (int i = 1; i < ts.length; i++) { - res.or = patternNode(ts[i], header, env); - res = res.or ; + case Alternative(Tree[] ts): + assert ts.length > 1; + PatternNode subroot = mk.ConstrPat(header.pos, header.type); + subroot.and = mk.Header(header.pos, header.type, header.selector.duplicate()); + CaseEnv subenv = new CaseEnv(owner, unit); + for (int i = 0; i < ts.length; i++) { + PatternNode target = enter1(ts[i], -1, subroot, subroot.symbol(), subenv); + target.and = mk.Body(tree.pos); } - return res; + return mk.AltPat(tree.pos, (Header)subroot.and); default: new scalac.ast.printer.TextTreePrinter().print(tree).flush(); - throw new ApplicationError("unit "+unit+" tree"+tree); + throw new ApplicationError("unit = " + unit + "; tree = "+tree); } } @@ -603,7 +613,13 @@ public class PatternMatcher extends PatternTool { PatternNode patNode = root.and; while (patNode != null) { PatternNode node = patNode; - while ((node = node.or) != null) + while ((node = node.or) != null) { + switch (node) { + case ConstantPat(_): + break; + default: + return false; + } switch (node.and) { case Body(ValDef[][] bound, Tree[] guard, _): if ((guard.length > 1) || @@ -614,6 +630,7 @@ public class PatternMatcher extends PatternTool { default: return false; } + } patNode = patNode.next(); } return true; @@ -828,7 +845,12 @@ public class PatternMatcher extends PatternTool { node = next; break; case Body(ValDef[][] bound, Tree[] guard, Tree[] body): - if (!doBinding) bound = new ValDef[][] { new ValDef[] {} }; + if ((bound.length == 0) && + (guard.length == 0) && + (body.length == 0)) { + return gen.mkBooleanLit(node.pos, true); // cf.Or(res, gen.mkBooleanLit(node.pos, true)); + } else if (!doBinding) + bound = new ValDef[][]{new ValDef[]{}}; for (int i = guard.length - 1; i >= 0; i--) { Tree[] ts = new Tree[bound[i].length + 1]; System.arraycopy(bound[i], 0, ts, 0, bound[i].length); @@ -986,6 +1008,11 @@ public class PatternMatcher extends PatternTool { cf.Equals(selector.duplicate(), tree), toTree(node.and), toTree(node.or, selector.duplicate())); + case AltPat(Header header): + return gen.If( + toTree(header), + toTree(node.and), + toTree(node.or, selector.duplicate())); default: throw new ApplicationError(); } diff --git a/sources/scalac/transformer/matching/PatternNode.java b/sources/scalac/transformer/matching/PatternNode.java index 3cd583c5d8..03e73fda97 100644 --- a/sources/scalac/transformer/matching/PatternNode.java +++ b/sources/scalac/transformer/matching/PatternNode.java @@ -14,9 +14,9 @@ import scalac.ast.*; import scalac.symtab.*; import scalac.typechecker.*; -/** intermediary data structure for algebraic matching - */ +/** Intermediate data structure for algebraic matcher + */ public class PatternNode { public int pos = Position.FIRSTPOS; public Type type; @@ -27,11 +27,11 @@ public class PatternNode { public case Body(Tree.ValDef[][] bound, Tree[] guard, Tree[] body); public case DefaultPat(); public case ConstrPat(Symbol casted); - public case SequencePat(Symbol casted, int len); // only used in PatternMatcher - public case SeqContainerPat(Symbol casted, Tree seqpat); // in AlgebraicMatcher public case ConstantPat(Object value); public case VariablePat(Tree tree); - + public case AltPat(Header subheader); + public case SequencePat(Symbol casted, int len); // only used in PatternMatcher + public case SeqContainerPat(Symbol casted, Tree seqpat); // in AlgebraicMatcher public PatternNode dup() { PatternNode res; @@ -60,6 +60,9 @@ public class PatternNode { case VariablePat(Tree tree): res = VariablePat(tree); break; + case AltPat(Header subheader): + res = AltPat(subheader); + break; default: throw new ApplicationError(); } diff --git a/sources/scalac/transformer/matching/PatternNodeCreator.java b/sources/scalac/transformer/matching/PatternNodeCreator.java index 16574d625b..d0a2cddef1 100644 --- a/sources/scalac/transformer/matching/PatternNodeCreator.java +++ b/sources/scalac/transformer/matching/PatternNodeCreator.java @@ -17,6 +17,15 @@ import java.util.Vector ; public class PatternNodeCreator extends PatternTool { + /** the owner of the variable symbols that might be created */ + Symbol owner; + + public PatternNodeCreator(Unit unit, Symbol owner) { + super(unit); + assert owner != null; + this.owner = owner; + } + public SequencePat SequencePat(int pos, Type type, int len) { Symbol sym = newVar(Position.FIRSTPOS, type); SequencePat node = new SequencePat(sym, len); @@ -24,6 +33,7 @@ public class PatternNodeCreator extends PatternTool { node.type = type; return node; } + public SeqContainerPat SeqContainerPat(int pos, Type type, Tree seqpat) { Symbol sym = newVar(Position.NOPOS, type); SeqContainerPat node = new SeqContainerPat(sym, seqpat); @@ -31,29 +41,40 @@ public class PatternNodeCreator extends PatternTool { node.type = type; return node; } + public static DefaultPat DefaultPat(int pos, Type type) { - DefaultPat node = new DefaultPat(); - node.pos = pos; - node.type = type; - return node; + DefaultPat node = new DefaultPat(); + node.pos = pos; + node.type = type; + return node; } + public ConstrPat ConstrPat(int pos, Type type) { - ConstrPat node = new ConstrPat(newVar(pos, type)); - node.pos = pos; - node.type = type; - return node; + ConstrPat node = new ConstrPat(newVar(pos, type)); + node.pos = pos; + node.type = type; + return node; } + public static ConstantPat ConstantPat(int pos, Type type, Object value) { - ConstantPat node = new ConstantPat( value ); - node.pos = pos; - node.type = type; - return node; + ConstantPat node = new ConstantPat( value ); + node.pos = pos; + node.type = type; + return node; } + public static VariablePat VariablePat(int pos, Tree tree) { - VariablePat node = new VariablePat( tree ); - node.pos = pos; - node.type = tree.type; - return node; + VariablePat node = new VariablePat( tree ); + node.pos = pos; + node.type = tree.type; + return node; + } + + public static AltPat AltPat(int pos, Header header) { + AltPat node = new AltPat(header); + node.pos = pos; + node.type = header.type; + return node; } // factories @@ -64,11 +85,19 @@ public class PatternNodeCreator extends PatternTool { node.type = type; return node; } + + public Body Body(int pos) { + Body node = new Body(new ValDef[0][], new Tree[0], new Tree[0]); + node.pos = pos; + return node; + } + public Body Body(int pos, ValDef[] bound, Tree guard, Tree body) { Body node = new Body(new ValDef[][]{bound}, new Tree[]{guard}, new Tree[]{body}); node.pos = pos; return node; } + public TermSymbol newVar(int pos, Name name, Type type) { TermSymbol sym = new TermSymbol(pos, name, owner, 0); sym.setType(type); @@ -76,16 +105,8 @@ public class PatternNodeCreator extends PatternTool { //System.out.println("owner: "+sym.owner()); return sym; } + public TermSymbol newVar(int pos, Type type) { return newVar(pos, fresh.newName("temp"), type); } - - /** the owner of the variable symbols that might be created */ - Symbol owner; - - public PatternNodeCreator( Unit unit, Symbol owner ) { - super( unit ); - assert owner != null; - this.owner = owner; - } } diff --git a/sources/scalac/util/AbstractFileReader.java b/sources/scalac/util/AbstractFileReader.java index 2f7d0e1e21..3ecd385dc6 100644 --- a/sources/scalac/util/AbstractFileReader.java +++ b/sources/scalac/util/AbstractFileReader.java @@ -73,35 +73,35 @@ public class AbstractFileReader { /** extract a character at position bp from buf */ - public char getChar(int bp) { - return (char)(((buf[bp] & 0xff) << 8) + (buf[bp+1] & 0xff)); + public char getChar(int mybp) { + return (char)(((buf[mybp] & 0xff) << 8) + (buf[mybp+1] & 0xff)); } /** extract an integer at position bp from buf */ - public int getInt(int bp) { - return ((buf[bp ] & 0xff) << 24) + - ((buf[bp+1] & 0xff) << 16) + - ((buf[bp+2] & 0xff) << 8) + - (buf[bp+3] & 0xff); + public int getInt(int mybp) { + return ((buf[mybp ] & 0xff) << 24) + + ((buf[mybp+1] & 0xff) << 16) + + ((buf[mybp+2] & 0xff) << 8) + + (buf[mybp+3] & 0xff); } /** extract a long integer at position bp from buf */ - public long getLong(int bp) { - return ((long)(getInt(bp)) << 32) + (getInt(bp + 4) & 0xffffffffL); + public long getLong(int mybp) { + return ((long)(getInt(mybp)) << 32) + (getInt(mybp + 4) & 0xffffffffL); } /** extract a float at position bp from buf */ - public strictfp float getFloat(int bp) { - return Float.intBitsToFloat(getInt(bp)); + public strictfp float getFloat(int mybp) { + return Float.intBitsToFloat(getInt(mybp)); } /** extract a double at position bp from buf */ - public strictfp double getDouble(int bp) { - return Double.longBitsToDouble(getLong(bp)); + public strictfp double getDouble(int mybp) { + return Double.longBitsToDouble(getLong(mybp)); } /** skip next 'n' bytes -- cgit v1.2.3