📄 type.java
字号:
case CHAR: return (this.tag == that.tag || this.tag + 2 <= that.tag && that.tag <= DOUBLE); case SHORT: case INT: case LONG: case FLOAT: case DOUBLE: return this.tag <= that.tag && that.tag <= DOUBLE; case BOOLEAN: case VOID: return this.tag == that.tag; case BOT: return (that.tag == BOT || that.tag == CLASS || that.tag == ARRAY); default: throw new AssertionError("isSubType " + this.tag); } } /** * Is this type a supertype of that type? * overridden for partial types. */ public boolean isSuperType(Type that) { return that.isSubType(this); } /** * Is this type a subtype of every type in given list `those'? * (not defined for Method and ForAll types) */ public boolean isSubType(List those) { for (List l = those; l.nonEmpty(); l = l.tail) { if (!this.isSubType((Type) l.head)) return false; } return true; } /** * Same for lists of types, if lists are of different length, return false. */ public static boolean isSubTypes(List these, List those) { while (these.tail != null && those.tail != null && ((Type) these.head).isSubType((Type) those.head)) { these = these.tail; those = those.tail; } return these.tail == null && those.tail == null; } /** * If this switch is true, we allow assigning character constants to byte * provided they fit in the range. */ private static final boolean looseInterpretation = true; /** * Is this type assignable to that type? Equivalent to subtype * except for constant values. (not defined for Method and ForAll types) */ public boolean isAssignable(Type that) { if (this.tag <= INT && this.constValue != null) { int value = ((Number) this.constValue).intValue(); switch (that.tag) { case BYTE: if ((looseInterpretation || this.tag != CHAR) && Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE) return true; break; case CHAR: if (Character.MIN_VALUE <= value && value <= Character.MAX_VALUE) return true; break; case SHORT: if (Short.MIN_VALUE <= value && value <= Short.MAX_VALUE) return true; break; case INT: return true; } } return this.isSubType(that); } /** * If this type is castable to that type, return the result of the cast * otherwise return null; * that type is assumed to be an erased type. * (not defined for Method and ForAll types). */ public boolean isCastable(Type that) { if (that.tag == ERROR) return true; switch (this.tag) { case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT: case DOUBLE: return that.tag <= DOUBLE; case BOOLEAN: return that.tag == BOOLEAN; case VOID: return false; case BOT: return this.isSubType(that); default: throw new AssertionError(); } } /** * The underlying method type of this type. */ public MethodType asMethodType() { throw new AssertionError(); } /** * Does this type have the same arguments as that type? * It is assumed that both types are (possibly polymorphic) method types. * Monomorphic method types "have the same arguments", * if their argument lists are equal. * Polymorphic method types "have the same arguments", * if they have the same arguments after renaming all type variables * of one to corresponding type variables in the other, where * correspondence is by position in the type parameter list. */ public boolean hasSameArgs(Type that) { throw new AssertionError(); } /** * Complete loading all classes in this type. */ public void complete() { } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new AssertionError(e); } } /** * An empty list of types. */ public static final List emptyList = new List(); public static class ClassType extends Type { /** * The enclosing type of this type. If this is the type of an inner * class, outer_field refers to the type of its enclosing * instance class, in all other cases it referes to noType. */ public Type outer_field; /** * The type parameters of this type (to be set once class is loaded). */ public List typarams_field; /** * A cache variable for the type parameters of this type, * appended to all parameters of its enclosing class. * @see allparams() */ public List allparams_field; /** * The supertype of this class (to be set once class is loaded). */ public Type supertype_field; /** * The interfaces of this class (to be set once class is loaded). */ public List interfaces_field; public ClassType(Type outer, List typarams, TypeSymbol tsym) { super(CLASS, tsym); this.outer_field = outer; this.typarams_field = typarams; this.allparams_field = null; this.supertype_field = null; this.interfaces_field = null; } /** * make a compound type from non-empty list of types * @param bounds the types from which the compound type is formed * @param tsym the compound type's type symbol * @param supertype is objectType if all bounds are interfaces, * null otherwise. */ static Type makeCompoundType(List bounds, TypeSymbol tsym, Type supertype) { ClassSymbol bc = new ClassSymbol(ABSTRACT | PUBLIC | SYNTHETIC | COMPOUND, tsym.name, tsym); bc.erasure_field = ((Type) bounds.head).erasure(); bc.members_field = new Scope(bc); ClassType bt = (ClassType) bc.type; bt.allparams_field = Type.emptyList; if (supertype != null) { bt.supertype_field = supertype; bt.interfaces_field = bounds; } else { bt.supertype_field = (Type) bounds.head; bt.interfaces_field = bounds.tail; } return bt; } /** * Same as previous function, except that third parameter is * computed directly. Note that this test might cause a symbol completion. * Hence, this version of makeCompoundType may not be called during * a classfile read. */ static Type makeCompoundType(List bounds, TypeSymbol tsym) { Type supertype = (((Type) bounds.head).tsym.flags() & INTERFACE) != 0 ? ((Type) bounds.head).supertype() : null; return makeCompoundType(bounds, tsym, supertype); } public Type constType(Object constValue) { Type t = new ClassType(outer_field, typarams_field, tsym); t.constValue = constValue; return t; } public String toString() { StringBuffer buf = new StringBuffer(); if (outer().tag == CLASS && tsym.owner.kind == TYP) { buf.append(outer().toString()); buf.append("."); buf.append(className(tsym, false)); } else { buf.append(className(tsym, true)); } if (typarams().nonEmpty()) { buf.append('<'); buf.append(typarams().toString()); buf.append(">"); } return buf.toString(); } private String className(Symbol sym, boolean longform) { if (sym.name.len == 0) return "<anonymous " + (sym.type.interfaces().nonEmpty() ? (Type) sym.type.interfaces().head : sym.type.supertype()) + ">" + (moreInfo ? String.valueOf(sym.hashCode()) : ""); else if (longform) return sym.fullName().toString(); else return sym.name.toString(); } /** * The Java source which this type represents. Use of this method * will result in the loss of the plain-language description for * the type. */ public String toJava() { StringBuffer buf = new StringBuffer(); if (outer().tag == CLASS && tsym.owner.kind == TYP) { buf.append(outer().toJava()); buf.append("."); buf.append(javaClassName(tsym, false)); } else { buf.append(javaClassName(tsym, true)); } if (typarams().nonEmpty()) { buf.append('<'); buf.append(typarams().toString()); buf.append(">"); } return buf.toString(); } private String javaClassName(Symbol sym, boolean longform) { if (sym.name.len == 0) { String s; if (sym.type.interfaces().nonEmpty()) { s = Log.getLocalizedString("anonymous.class", ((Type) sym.type.interfaces().head).toJava()); } else { s = Log.getLocalizedString("anonymous.class", sym.type.supertype().toJava()); } if (moreInfo) s += String.valueOf(sym.hashCode()); return s; } else if (longform) { return sym.fullName().toString(); } else { return sym.name.toString(); } } public List typarams() { if (typarams_field == null) { complete(); typarams_field = tsym.type.typarams(); } return typarams_field; } public Type outer() { if (outer_field == null) { complete(); outer_field = tsym.type.outer(); } return outer_field; } public Type supertype() { if (supertype_field == null) { complete(); Type st = ((ClassType) tsym.type).supertype_field; if (st == null) { supertype_field = noType; } else if (this == tsym.type) { supertype_field = st; } else { List ownparams = classBound().allparams(); List symparams = tsym.type.allparams(); supertype_field = (ownparams.isEmpty()) ? st.erasure() : st.subst(symparams, ownparams); } } return supertype_field; } public List interfaces() { if (interfaces_field == null) { complete(); List is = ((ClassType) tsym.type).interfaces_field; if (is == null) { interfaces_field = Type.emptyList; } else if (this == tsym.type) { interfaces_field = is; } else { List ownparams = allparams(); List symparams = tsym.type.allparams(); if (ownparams.isEmpty()) interfaces_field = erasure(is); else interfaces_field = subst(is, symparams, ownparams); } } return interfaces_field; } public List allparams() { if (allparams_field == null) { allparams_field = typarams().prependList(outer().allparams()); } return allparams_field; } public Type asSuper(Symbol sym) { if (tsym == sym) { return this; } else { Type st = supertype(); if (st.tag == CLASS || st.tag == ERROR) { Type t = st.asSuper(sym); if (t != null) return t; } if ((sym.flags() & INTERFACE) != 0) { for (List l = interfaces(); l.nonEmpty(); l = l.tail) { Type t = ((Type) l.head).asSuper(sym); if (t != null) return t; } } return null; } } public Type asOuterSuper(Symbol sym) { Type t = this; do { Type s = t.asSuper(sym); if (s != null) return s; t = t.outer(); } while (t.tag == CLASS) ; return null; } public Type classBound() { Type outer1 = outer().classBound(); if (outer1 != outer_field) return new ClassType(outer1, typarams(), tsym); else return this; } public Type asSub(Symbol sym) { if (tsym == sym) { return this; } else { Type base = sym.type.asSuper(tsym); if (base == null) return null; ListBuffer from = new ListBuffer(); ListBuffer to = new ListBuffer(); adapt(base, this, from, to); Type res = sym.type.subst(from.toList(), to.toList()); if (!res.isSubType(this)) return null; for (List l = sym.type.allparams(); l.nonEmpty(); l = l.tail) if (res.contains((Type) l.head) && !this.contains((Type) l.head)) return res.erasure(); return res; } } /** * Adapt a type by computing a substitution which * maps a source type to a target type. * @param from the source type * @param target the target type * @param from the type variables of the computed substitution * @param to the types of the computed substitution. */ private static void adapt(Type source, Type target, ListBuffer from, ListBuffer to) { if (source.tag == target.tag) { switch (source.tag) { case CLASS: adapt(source.allparams(), target.allparams(), from, to); break; case ARRAY: adapt(source.elemtype(), target.elemtype(), from, to); } } } /** * Adapt a type by computing a substitution which * maps a list of source types to a list of target types. * @param source the source type * @param target the target type * @param from the type variables of the computed substitution * @param to the types of the computed substitution. */ private static void adapt(List source, List target, ListBuffer from, ListBuffer to) { if (source.length() == target.length()) { while (source.nonEmpty()) { adapt((Type) source.head, (Type) target.head, from, to); source = source.tail; target = target.tail; } } } public Type memberType(Symbol sym) { Symbol owner = sym.owner; long flags = sym.flags();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -