types.java
来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,804 行 · 第 1/5 页
JAVA
1,804 行
}; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="isAssignable"> public boolean isAssignable(Type t, Type s) { return isAssignable(t, s, Warner.noWarnings); } /** * Is t assignable to s?<br> * Equivalent to subtype except for constant values and raw * types.<br> * (not defined for Method and ForAll types) */ public boolean isAssignable(Type t, Type s, Warner warn) { if (t.tag == ERROR) return true; if (t.tag <= INT && t.constValue() != null) { int value = ((Number)t.constValue()).intValue(); switch (s.tag) { case BYTE: if (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; case CLASS: switch (unboxedType(s).tag) { case BYTE: case CHAR: case SHORT: return isAssignable(t, unboxedType(s), warn); } break; } } return isConvertible(t, s, warn); } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="erasure"> /** * The erasure of t {@code |t|} -- the type that results when all * type parameters in t are deleted. */ public Type erasure(Type t) { if (t.tag <= lastBaseTag) return t; /* fast special case */ else return erasure.visit(t); } // where private UnaryVisitor<Type> erasure = new UnaryVisitor<Type>() { public Type visitType(Type t, Void ignored) { if (t.tag <= lastBaseTag) return t; /*fast special case*/ else return t.map(erasureFun); } @Override public Type visitWildcardType(WildcardType t, Void ignored) { return erasure(upperBound(t)); } @Override public Type visitClassType(ClassType t, Void ignored) { return t.tsym.erasure(Types.this); } @Override public Type visitTypeVar(TypeVar t, Void ignored) { return erasure(t.bound); } @Override public Type visitErrorType(ErrorType t, Void ignored) { return t; } }; private Mapping erasureFun = new Mapping ("erasure") { public Type apply(Type t) { return erasure(t); } }; public List<Type> erasure(List<Type> ts) { return Type.map(ts, erasureFun); } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="makeCompoundType"> /** * Make a compound type from non-empty list of types * * @param bounds the types from which the compound type is formed * @param supertype is objectType if all bounds are interfaces, * null otherwise. */ public Type makeCompoundType(List<Type> bounds, Type supertype) { ClassSymbol bc = new ClassSymbol(ABSTRACT|PUBLIC|SYNTHETIC|COMPOUND|ACYCLIC, Type.moreInfo ? names.fromString(bounds.toString()) : names.empty, syms.noSymbol); if (bounds.head.tag == TYPEVAR) // error condition, recover bc.erasure_field = syms.objectType; else bc.erasure_field = erasure(bounds.head); bc.members_field = new Scope(bc); ClassType bt = (ClassType)bc.type; bt.allparams_field = List.nil(); if (supertype != null) { bt.supertype_field = supertype; bt.interfaces_field = bounds; } else { bt.supertype_field = bounds.head; bt.interfaces_field = bounds.tail; } assert bt.supertype_field.tsym.completer != null || !bt.supertype_field.isInterface() : bt.supertype_field; return bt; } /** * Same as {@link #makeCompoundType(List,Type)}, except that the * second parameter is computed directly. Note that this might * cause a symbol completion. Hence, this version of * makeCompoundType may not be called during a classfile read. */ public Type makeCompoundType(List<Type> bounds) { Type supertype = (bounds.head.tsym.flags() & INTERFACE) != 0 ? supertype(bounds.head) : null; return makeCompoundType(bounds, supertype); } /** * A convenience wrapper for {@link #makeCompoundType(List)}; the * arguments are converted to a list and passed to the other * method. Note that this might cause a symbol completion. * Hence, this version of makeCompoundType may not be called * during a classfile read. */ public Type makeCompoundType(Type bound1, Type bound2) { return makeCompoundType(List.of(bound1, bound2)); } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="supertype"> public Type supertype(Type t) { return supertype.visit(t); } // where private UnaryVisitor<Type> supertype = new UnaryVisitor<Type>() { public Type visitType(Type t, Void ignored) { // A note on wildcards: there is no good way to // determine a supertype for a super bounded wildcard. return null; } @Override public Type visitClassType(ClassType t, Void ignored) { if (t.supertype_field == null) { Type supertype = ((ClassSymbol)t.tsym).getSuperclass(); // An interface has no superclass; its supertype is Object. if (t.isInterface()) supertype = ((ClassType)t.tsym.type).supertype_field; if (t.supertype_field == null) { List<Type> actuals = classBound(t).allparams(); List<Type> formals = t.tsym.type.allparams(); if (actuals.isEmpty()) { if (formals.isEmpty()) // Should not happen. See comments below in interfaces t.supertype_field = supertype; else t.supertype_field = erasure(supertype); } else { t.supertype_field = subst(supertype, formals, actuals); } } } return t.supertype_field; } /** * The supertype is always a class type. If the type * variable's bounds start with a class type, this is also * the supertype. Otherwise, the supertype is * java.lang.Object. */ @Override public Type visitTypeVar(TypeVar t, Void ignored) { if (t.bound.tag == TYPEVAR || (!t.bound.isCompound() && !t.bound.isInterface())) { return t.bound; } else { return supertype(t.bound); } } @Override public Type visitArrayType(ArrayType t, Void ignored) { if (t.elemtype.isPrimitive() || isSameType(t.elemtype, syms.objectType)) return arraySuperType(); else return new ArrayType(supertype(t.elemtype), t.tsym); } @Override public Type visitErrorType(ErrorType t, Void ignored) { return t; } }; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="interfaces"> /** * Return the interfaces implemented by this class. */ public List<Type> interfaces(Type t) { return interfaces.visit(t); } // where private UnaryVisitor<List<Type>> interfaces = new UnaryVisitor<List<Type>>() { public List<Type> visitType(Type t, Void ignored) { return List.nil(); } @Override public List<Type> visitClassType(ClassType t, Void ignored) { if (t.interfaces_field == null) { List<Type> interfaces = ((ClassSymbol)t.tsym).getInterfaces(); if (t.interfaces_field == null) { // If t.interfaces_field is null, then t must // be a parameterized type (not to be confused // with a generic type declaration). // Terminology: // Parameterized type: List<String> // Generic type declaration: class List<E> { ... } // So t corresponds to List<String> and // t.tsym.type corresponds to List<E>. // The reason t must be parameterized type is // that completion will happen as a side // effect of calling // ClassSymbol.getInterfaces. Since // t.interfaces_field is null after // completion, we can assume that t is not the // type of a class/interface declaration. assert t != t.tsym.type : t.toString(); List<Type> actuals = t.allparams(); List<Type> formals = t.tsym.type.allparams(); if (actuals.isEmpty()) { if (formals.isEmpty()) { // In this case t is not generic (nor raw). // So this should not happen. t.interfaces_field = interfaces; } else { t.interfaces_field = erasure(interfaces); } } else { t.interfaces_field = upperBounds(subst(interfaces, formals, actuals)); } } } return t.interfaces_field; } @Override public List<Type> visitTypeVar(TypeVar t, Void ignored) { if (t.bound.isCompound()) return interfaces(t.bound); if (t.bound.isInterface()) return List.of(t.bound); return List.nil(); } }; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="isDerivedRaw"> Map<Type,Boolean> isDerivedRawCache = new HashMap<Type,Boolean>(); public boolean isDerivedRaw(Type t) { Boolean result = isDerivedRawCache.get(t); if (result == null) { result = isDerivedRawInternal(t); isDerivedRawCache.put(t, result); } return result; } public boolean isDerivedRawInternal(Type t) { if (t.isErroneous()) return false; return t.isRaw() || supertype(t) != null && isDerivedRaw(supertype(t)) || isDerivedRaw(interfaces(t)); } public boolean isDerivedRaw(List<Type> ts) { List<Type> l = ts; while (l.nonEmpty() && !isDerivedRaw(l.head)) l = l.tail; return l.nonEmpty(); } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="setBounds"> /** * Set the bounds field of the given type variable to reflect a * (possibly multiple) list of bounds. * @param t a type variable * @param bounds the bounds, must be nonempty * @param supertype is objectType if all bounds are interfaces, * null otherwise. */ public void setBounds(TypeVar t, List<Type> bounds, Type supertype) { if (bounds.tail.isEmpty()) t.bound = bounds.head; else t.bound = makeCompoundType(bounds, supertype); t.rank_field = -1; } /** * Same as {@link #setBounds(Type.TypeVar,List,Type)}, except that * third parameter is computed directly. Note that this test * might cause a symbol completion. Hence, this version of * setBounds may not be called during a classfile read. */ public void setBounds(TypeVar t, List<Type> bounds) { Type supertype = (bounds.head.tsym.flags() & INTERFACE) != 0 ? supertype(bounds.head) : null; setBounds(t, bounds, supertype); t.rank_field = -1; } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="getBounds"> /** * Return list of bounds of the given type variable. */ public List<Type> getBounds(TypeVar t) { if (t.bound.isErroneous() || !t.bound.isCompound()) return List.of(t.bound); else if ((erasure(t).tsym.fl
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?