git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@51 379699f6-c40d-0410-875b-85095c16579estable
parent
92f7046e3f
commit
4f6e9bf4b5
@ -0,0 +1,117 @@ |
|||||||
|
/* ArrayType Copyright (C) 1997-1998 Jochen Hoenicke. |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation; either version 2, or (at your option) |
||||||
|
* any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; see the file COPYING. If not, write to |
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
package jode; |
||||||
|
|
||||||
|
/** |
||||||
|
* This type represents an array type. |
||||||
|
* |
||||||
|
* @author Jochen Hoenicke |
||||||
|
*/ |
||||||
|
public class ArrayType extends Type { |
||||||
|
Type elementType; |
||||||
|
|
||||||
|
public ArrayType(Type elementType) { |
||||||
|
super(TC_ARRAY); |
||||||
|
this.elementType = elementType; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getElementType() { |
||||||
|
return elementType; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getBottom() { |
||||||
|
return tArray(elementType.getBottom()); |
||||||
|
} |
||||||
|
|
||||||
|
public Type getTop() { |
||||||
|
return tArray(elementType.getTop()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create the type corresponding to the range from bottomType to this. |
||||||
|
* @param bottomType the start point of the range |
||||||
|
* @return the range type, or tError if not possible. |
||||||
|
*/ |
||||||
|
public Type createRangeType(Type bottomType) { |
||||||
|
/* tUnknown , tArray(x) -> <tObject, tArray(x)> |
||||||
|
* tObject , tArray(x) -> <tObject, tArray(x)> |
||||||
|
* tArray(y), tArray(x) -> tArray( <y,x> ) |
||||||
|
*/ |
||||||
|
return (bottomType == tUnknown || bottomType == tObject) |
||||||
|
? tRange(tObject, this) |
||||||
|
: (bottomType.typecode == TC_ARRAY) |
||||||
|
? tArray(elementType.createRangeType |
||||||
|
(((ArrayType)bottomType).elementType)) |
||||||
|
: tError; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the common sub type of this and type. |
||||||
|
* @param type the other type. |
||||||
|
* @return the common sub type. |
||||||
|
*/ |
||||||
|
public Type getSpecializedType(Type type) { |
||||||
|
/* tArray(x), tUnknown -> tArray(x) |
||||||
|
* tArray(x), tObject -> tArray(x) |
||||||
|
* tArray(x), tArray(y) -> tArray(x.getSpecialized(y)) |
||||||
|
* tArray(x), other -> tError |
||||||
|
*/ |
||||||
|
return (type == tUnknown || type == tObject) |
||||||
|
? this |
||||||
|
: (type.getTypeCode() == TC_ARRAY) |
||||||
|
? tArray(elementType.getSpecializedType |
||||||
|
(((ArrayType)type).elementType)) |
||||||
|
: tError; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the common super type of this and type. |
||||||
|
* @param type the other type. |
||||||
|
* @return the common super type. |
||||||
|
*/ |
||||||
|
public Type getGeneralizedType(Type type) { |
||||||
|
/* tArray(x), tUnknown -> tArray(x) |
||||||
|
* tArray(x), tClass(y) -> tObject |
||||||
|
* tArray(x), tArray(y) -> tArray(x.getGeneralized(y)) |
||||||
|
* tArray(x), other -> tError |
||||||
|
*/ |
||||||
|
return (type == tUnknown) |
||||||
|
? this |
||||||
|
: (type.getTypeCode() == TC_CLASS) |
||||||
|
? tObject |
||||||
|
: (type.getTypeCode() == TC_ARRAY) |
||||||
|
? tArray(elementType.getGeneralizedType |
||||||
|
(((ArrayType)type).elementType)) |
||||||
|
: tError; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString() { |
||||||
|
return elementType.toString()+"[]"; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean equals(Object o) { |
||||||
|
if (o == this) |
||||||
|
return true; |
||||||
|
if (o instanceof ArrayType) { |
||||||
|
ArrayType type = (ArrayType) o; |
||||||
|
return type.elementType.equals(elementType); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,95 @@ |
|||||||
|
/* |
||||||
|
* RangeType (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode; |
||||||
|
import java.util.Hashtable; |
||||||
|
|
||||||
|
/** |
||||||
|
* This class represents an object type which isn't fully known. |
||||||
|
* The real object type lies in a range of types between topType |
||||||
|
* and bottomType. <p> |
||||||
|
* |
||||||
|
* For a totally unknown type topType is tObject and bottomType is |
||||||
|
* null. It is always garanteed that topType is an Array or an Object |
||||||
|
* and that bottomType is null or an Array or an Object. <p> |
||||||
|
* |
||||||
|
* @author Jochen Hoenicke |
||||||
|
* @date 98/08/06 |
||||||
|
*/ |
||||||
|
public class RangeType extends Type { |
||||||
|
final Type bottomType; |
||||||
|
final Type topType; |
||||||
|
|
||||||
|
public RangeType(Type bottomType, Type topType) { |
||||||
|
super(TC_RANGE); |
||||||
|
this.bottomType = bottomType; |
||||||
|
this.topType = topType; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getBottom() { |
||||||
|
return bottomType; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getTop() { |
||||||
|
return topType; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create the type corresponding to the range from bottomType to this. |
||||||
|
* @param bottomType the start point of the range |
||||||
|
* @return the range type, or tError if not possible. |
||||||
|
*/ |
||||||
|
public Type createRangeType(Type bottomType) { |
||||||
|
throw new AssertError("createRangeType called on RangeType"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the common sub type of this and type. |
||||||
|
* @param type the other type. |
||||||
|
* @return the common sub type. |
||||||
|
*/ |
||||||
|
public Type getSpecializedType(Type type) { |
||||||
|
throw new AssertError("getSpecializedType called on RangeType"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the common super type of this and type. |
||||||
|
* @param type the other type. |
||||||
|
* @return the common super type. |
||||||
|
*/ |
||||||
|
public Type getGeneralizedType(Type type) { |
||||||
|
throw new AssertError("getGeneralizedType called on RangeType"); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString() |
||||||
|
{ |
||||||
|
if (jode.Decompiler.isTypeDebugging) |
||||||
|
return "<" + bottomType + "-" + topType + ">"; |
||||||
|
return topType.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean equals(Object o) { |
||||||
|
if (o instanceof RangeType) { |
||||||
|
RangeType type = (RangeType) o; |
||||||
|
return topType.equals(type.topType) |
||||||
|
&& bottomType.equals(type.bottomType); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,464 @@ |
|||||||
|
/* |
||||||
|
* Type (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode; |
||||||
|
import java.util.Hashtable; |
||||||
|
|
||||||
|
/** |
||||||
|
* This is my type class. It differs from sun.tools.java.Type, in |
||||||
|
* that it maintains a type range. This type range may be implicit or |
||||||
|
* explicit. <p> |
||||||
|
* |
||||||
|
* |
||||||
|
* Think of this global type hierarchie: |
||||||
|
* <pre> |
||||||
|
* |
||||||
|
* tUnknown |
||||||
|
* / | \ |
||||||
|
* / | \ |
||||||
|
* tObject boolean int |
||||||
|
* / \ | |
||||||
|
* / tArray short |
||||||
|
* other | |
||||||
|
* classes byte |
||||||
|
* </pre> |
||||||
|
* |
||||||
|
* int implements the "interface" tBoolByte. boolean and byte |
||||||
|
* implement the "interface" tBoolByte which extends tBoolInt. |
||||||
|
* |
||||||
|
* The type tBoolInt is <tBoolInt, tUnknown>, the type tBoolByte is |
||||||
|
* <tBoolByte, tUnknown> (hard coded in <code>getTop</code>). The |
||||||
|
* type tUInt is <int, byte>. |
||||||
|
* |
||||||
|
* Note that tUnknown is no valid type, so we can replace |
||||||
|
* <tUnknown, byte> with <int, byte> |
||||||
|
* <tUnknown, tArray> with <tObject, tArray> |
||||||
|
* |
||||||
|
* The main operation on a type range is the intersection. To do this |
||||||
|
* on class ranges we need three more operations: specialization, |
||||||
|
* generalization and createRange. <p> |
||||||
|
* |
||||||
|
* specialization chooses the common sub type of the two types. It |
||||||
|
* is used to find the start point of the intersected interval. <p> |
||||||
|
* |
||||||
|
* generalization chooses the common super type of two types. It |
||||||
|
* is used to find the end point of the intersected interval. <p> |
||||||
|
* |
||||||
|
* When the new interval is created with <code>createRangeType</code> |
||||||
|
* the start and end points are adjusted so that they only consists of |
||||||
|
* possible types. |
||||||
|
* |
||||||
|
* @author Jochen Hoenicke */ |
||||||
|
public class Type { |
||||||
|
|
||||||
|
public static final int TC_BOOLEAN = 0; |
||||||
|
public static final int TC_BYTE = 1; |
||||||
|
public static final int TC_CHAR = 2; |
||||||
|
public static final int TC_SHORT = 3; |
||||||
|
public static final int TC_INT = 4; |
||||||
|
public static final int TC_LONG = 5; |
||||||
|
public static final int TC_FLOAT = 6; |
||||||
|
public static final int TC_DOUBLE = 7; |
||||||
|
public static final int TC_NULL = 8; |
||||||
|
public static final int TC_ARRAY = 9; |
||||||
|
public static final int TC_CLASS = 10; |
||||||
|
public static final int TC_VOID = 11; |
||||||
|
public static final int TC_METHOD = 12; |
||||||
|
public static final int TC_ERROR = 13; |
||||||
|
public static final int TC_UNKNOWN = 101; |
||||||
|
public static final int TC_RANGE = 103; |
||||||
|
public static final int TC_BOOLBYTE = 105; |
||||||
|
public static final int TC_BOOLINT = 106; |
||||||
|
|
||||||
|
protected static JodeEnvironment env; |
||||||
|
|
||||||
|
public static final Hashtable classHash = new Hashtable(); |
||||||
|
public static final Hashtable arrayHash = new Hashtable(); |
||||||
|
|
||||||
|
public static final Type tBoolean = new Type(TC_BOOLEAN); |
||||||
|
public static final Type tByte = new Type(TC_BYTE); |
||||||
|
public static final Type tChar = new Type(TC_CHAR); |
||||||
|
public static final Type tShort = new Type(TC_SHORT); |
||||||
|
public static final Type tInt = new Type(TC_INT); |
||||||
|
public static final Type tLong = new Type(TC_LONG); |
||||||
|
public static final Type tFloat = new Type(TC_FLOAT); |
||||||
|
public static final Type tDouble = new Type(TC_DOUBLE); |
||||||
|
public static final Type tVoid = new Type(TC_VOID); |
||||||
|
public static final Type tError = new Type(TC_ERROR); |
||||||
|
public static final Type tUnknown = new Type(TC_UNKNOWN); |
||||||
|
public static final Type tUInt = tRange(tInt, tByte); |
||||||
|
public static final Type tBoolInt = new Type(TC_BOOLINT); |
||||||
|
public static final Type tBoolByte= new Type(TC_BOOLBYTE); |
||||||
|
public static final Type tObject = tClass("java.lang.Object"); |
||||||
|
public static final Type tUObject = tRange(tObject, tUnknown); |
||||||
|
public static final Type tString = tClass("java.lang.String"); |
||||||
|
public static final Type tStringBuffer = tClass("java.lang.StringBuffer"); |
||||||
|
|
||||||
|
public static final Type tType(String type) { |
||||||
|
if (type == null || type.length() == 0) |
||||||
|
return tError; |
||||||
|
switch(type.charAt(0)) { |
||||||
|
case 'Z': |
||||||
|
return tBoolean; |
||||||
|
case 'B': |
||||||
|
return tByte; |
||||||
|
case 'C': |
||||||
|
return tChar; |
||||||
|
case 'S': |
||||||
|
return tShort; |
||||||
|
case 'I': |
||||||
|
return tInt; |
||||||
|
case 'F': |
||||||
|
return tFloat; |
||||||
|
case 'J': |
||||||
|
return tLong; |
||||||
|
case 'D': |
||||||
|
return tDouble; |
||||||
|
case 'V': |
||||||
|
return tVoid; |
||||||
|
case '[': |
||||||
|
return tArray(tType(type.substring(1))); |
||||||
|
case 'L': |
||||||
|
int index = type.indexOf(';'); |
||||||
|
if (index != type.length()-1) |
||||||
|
return tError; |
||||||
|
return tClass(type.substring(1, index).replace('/', '.')); |
||||||
|
} |
||||||
|
throw new AssertError("Unknown type signature: "+type); |
||||||
|
} |
||||||
|
|
||||||
|
public static final Type tType(sun.tools.java.Type type) { |
||||||
|
return tType(type.getTypeSignature()); |
||||||
|
} |
||||||
|
|
||||||
|
public static final Type tClass(String clazzname) { |
||||||
|
Object result = classHash.get(clazzname); |
||||||
|
if (result == null) { |
||||||
|
result = new ClassInterfacesType(clazzname); |
||||||
|
classHash.put(clazzname, result); |
||||||
|
} |
||||||
|
return (Type) result; |
||||||
|
} |
||||||
|
|
||||||
|
public static final Type tArray(Type type) { |
||||||
|
if (type == tError) |
||||||
|
return type; |
||||||
|
Type result = (Type) arrayHash.get(type); |
||||||
|
if (result == null) { |
||||||
|
result = new ArrayType(type); |
||||||
|
arrayHash.put(type, result); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public static final Type tRange(Type bottom, Type top) { |
||||||
|
if (bottom.typecode == TC_RANGE |
||||||
|
|| top.typecode == TC_RANGE) |
||||||
|
throw new AssertError("tRange("+bottom+","+top+")"); |
||||||
|
return new RangeType(bottom, top); |
||||||
|
} |
||||||
|
|
||||||
|
public static Type tSuperType(Type type) { |
||||||
|
if (type == tBoolInt || type == tBoolByte) |
||||||
|
return tBoolInt; |
||||||
|
return type.getTop().createRangeType(tUnknown); |
||||||
|
} |
||||||
|
|
||||||
|
public static Type tSubType(Type type) { |
||||||
|
return tUnknown.createRangeType(type.getBottom()); |
||||||
|
} |
||||||
|
|
||||||
|
public static Type tClassOrArray(sun.tools.java.Identifier ident) { |
||||||
|
if (ident.toString().charAt(0) == '[') |
||||||
|
return Type.tType(ident.toString()); |
||||||
|
else |
||||||
|
return Type.tClass(ident.toString()); |
||||||
|
} |
||||||
|
|
||||||
|
public static void setEnvironment(JodeEnvironment e) { |
||||||
|
env = e; |
||||||
|
} |
||||||
|
|
||||||
|
int typecode; |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new type with the given type code. |
||||||
|
*/ |
||||||
|
protected Type(int typecode) { |
||||||
|
this.typecode = typecode; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getBottom() { |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Type getTop() { |
||||||
|
return (this == tBoolByte || this == tBoolInt) ? tUnknown : this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return the type code of the type. |
||||||
|
*/ |
||||||
|
public int getTypeCode() { |
||||||
|
return typecode; |
||||||
|
} |
||||||
|
|
||||||
|
public int stackSize() |
||||||
|
{ |
||||||
|
switch(typecode) { |
||||||
|
case TC_VOID: |
||||||
|
case TC_ERROR: |
||||||
|
return 0; |
||||||
|
default: |
||||||
|
return 1; |
||||||
|
case TC_DOUBLE: |
||||||
|
case TC_LONG: |
||||||
|
return 2; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the common sub type of this and type. |
||||||
|
* @param type the other type. |
||||||
|
* @return the common sub type. |
||||||
|
*/ |
||||||
|
public Type getSpecializedType(Type type) { |
||||||
|
/* tError , x -> tError |
||||||
|
* tUnknown, x -> x |
||||||
|
* x , x -> x |
||||||
|
* boolean , boolint -> boolean |
||||||
|
* byte , boolint -> byte |
||||||
|
* boolean , boolbyte -> boolean |
||||||
|
* byte , boolbyte -> byte |
||||||
|
* short , boolbyte -> byte |
||||||
|
* int , boolbyte -> byte |
||||||
|
* byte , short -> byte |
||||||
|
* boolint , short -> short |
||||||
|
* boolint , boolbyte -> boolbyte |
||||||
|
* boolbyte, short -> tError |
||||||
|
*/ |
||||||
|
return (this == tError || type == tError) ? tError |
||||||
|
: (this == type || type == tUnknown) ? this |
||||||
|
: (this == tUnknown) ? type |
||||||
|
|
||||||
|
: (typecode == TC_BOOLEAN) ? |
||||||
|
/* TC_BOOLEAN is only compatible to TC_BOOLINT / TC_BOOLBYTE */ |
||||||
|
((type == tBoolInt || type == tBoolByte) ? this : tError) |
||||||
|
|
||||||
|
: (typecode <= TC_INT) |
||||||
|
/* TC_BYTE, ..., TC_INT are compatible to higher |
||||||
|
* types and TC_BOOLINT, TC_BYTE is compatible to TC_BOOLBYTE |
||||||
|
*/ |
||||||
|
? (( type.typecode == TC_BOOLEAN) ? tError |
||||||
|
: (type.typecode <= typecode) ? type |
||||||
|
: (type.typecode <= TC_INT |
||||||
|
|| type.typecode == TC_BOOLINT) ? this |
||||||
|
: (this == tByte && type == tBoolByte) ? this |
||||||
|
: tError) |
||||||
|
|
||||||
|
: (typecode == TC_BOOLINT) |
||||||
|
/* TC_BOOLEAN,...,TC_INT all implement TC_BOOLINT |
||||||
|
*/ |
||||||
|
? ( (type.typecode <= TC_INT |
||||||
|
|| type.typecode == TC_BOOLBYTE) ? type : tError ) |
||||||
|
|
||||||
|
: (typecode == TC_BOOLBYTE) |
||||||
|
/* TC_BOOLEAN, TC_BYTE implement TC_BOOLBYTE; |
||||||
|
* TC_BYTE extend TC_SHORT, TC_INT. |
||||||
|
* TC_BOOLBYTE extends TC_BOOLINT. |
||||||
|
*/ |
||||||
|
? ( (type.typecode <= TC_BYTE) ? type |
||||||
|
: (type.typecode <= TC_INT) ? tByte |
||||||
|
: (type == tBoolInt) ? this : tError ) |
||||||
|
|
||||||
|
: tError; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the common super type of this and type. |
||||||
|
* @param type the other type. |
||||||
|
* @return the common super type. |
||||||
|
*/ |
||||||
|
public Type getGeneralizedType(Type type) { |
||||||
|
/* Note that type can't be boolint/boolbyte (set getBottom) */ |
||||||
|
/* tError , x -> tError |
||||||
|
* tUnknown, x -> x |
||||||
|
* x , x -> x |
||||||
|
* byte , short -> short |
||||||
|
*/ |
||||||
|
|
||||||
|
return (this == tError || type == tError) ? tError |
||||||
|
: (this == type || type == tUnknown) ? this |
||||||
|
: (this == tUnknown) ? type |
||||||
|
|
||||||
|
: (typecode >= TC_BYTE && typecode <= TC_INT) |
||||||
|
/* TC_BYTE, ..., TC_INT are compatible to higher |
||||||
|
*/ |
||||||
|
? ((type.typecode < TC_BYTE) ? tError |
||||||
|
: (type.typecode <= typecode) ? this |
||||||
|
: (type.typecode <= TC_INT) ? type : tError) |
||||||
|
|
||||||
|
: tError; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create the type corresponding to the range from bottomType to this. |
||||||
|
* @param bottomType the start point of the range |
||||||
|
* @return the range type, or tError if not possible. |
||||||
|
*/ |
||||||
|
public Type createRangeType(Type bottomType) { |
||||||
|
/* Note that this can't be tBoolByte or tBoolInt */ |
||||||
|
/* x , tError -> tError |
||||||
|
* object , tUnknown -> <object, tUnknown> |
||||||
|
* boolean , tUnknown -> boolean |
||||||
|
* int , tUnknown -> <int, byte> |
||||||
|
* boolint , tUnknown -> boolint |
||||||
|
* x , x -> x |
||||||
|
* tUnknown, boolean -> boolean |
||||||
|
* tUnknown, short -> <int, short> |
||||||
|
* short , byte -> <short, byte> |
||||||
|
* byte , short -> tError |
||||||
|
* tUnknown, float -> float |
||||||
|
*/ |
||||||
|
|
||||||
|
return (this == tError || bottomType == tError) ? tError |
||||||
|
: (this == bottomType) ? this |
||||||
|
|
||||||
|
: (this == tUnknown) |
||||||
|
? ((bottomType == tBoolInt |
||||||
|
|| bottomType == tBoolByte |
||||||
|
|| bottomType == tBoolean |
||||||
|
|| bottomType == tByte ) ? bottomType |
||||||
|
:(bottomType.typecode <= TC_INT) |
||||||
|
? tRange(bottomType, tByte) |
||||||
|
: tRange(bottomType, this)) |
||||||
|
|
||||||
|
: (this == tBoolean) |
||||||
|
? ((bottomType == tBoolInt |
||||||
|
|| bottomType == tBoolByte |
||||||
|
|| bottomType == tUnknown) ? this : tError) |
||||||
|
|
||||||
|
: (typecode <= TC_INT) |
||||||
|
/* tUnknown, short -> <int, short> |
||||||
|
* short , byte -> <short, byte> |
||||||
|
* byte , short -> tError |
||||||
|
* boolint , short -> <int, short> |
||||||
|
* boolbyte, byte -> byte |
||||||
|
* boolbyte, short -> tError |
||||||
|
*/ |
||||||
|
? ((bottomType.typecode < typecode) |
||||||
|
? tError |
||||||
|
|
||||||
|
: (bottomType.typecode <= TC_INT) |
||||||
|
? tRange(bottomType, this) |
||||||
|
|
||||||
|
: (bottomType.typecode == TC_BOOLBYTE |
||||||
|
&& bottomType == tByte) |
||||||
|
? tByte |
||||||
|
|
||||||
|
: (bottomType.typecode == TC_BOOLINT |
||||||
|
|| bottomType.typecode == TC_UNKNOWN) |
||||||
|
? (this == tInt) ? tInt : tRange(tInt, this) |
||||||
|
|
||||||
|
: tError) |
||||||
|
: (bottomType.typecode == TC_UNKNOWN) ? this |
||||||
|
: tError; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Intersect this type with another type and return the new type. |
||||||
|
* @param type the other type. |
||||||
|
* @return the intersection, or tError, if a type conflict happens. |
||||||
|
*/ |
||||||
|
public final Type intersection(Type type) { |
||||||
|
|
||||||
|
Type top = getTop().getGeneralizedType(type.getTop()); |
||||||
|
Type bottom = getBottom().getSpecializedType(type.getBottom()); |
||||||
|
Type result = top.createRangeType(bottom); |
||||||
|
|
||||||
|
if (result == tError) { |
||||||
|
boolean oldTypeDebugging = Decompiler.isTypeDebugging; |
||||||
|
Decompiler.isTypeDebugging = true; |
||||||
|
System.err.println("intersecting "+ this +" and "+ type |
||||||
|
+ " to <" + bottom + "," + top + ">" |
||||||
|
+ " to <error>"); |
||||||
|
Decompiler.isTypeDebugging = oldTypeDebugging; |
||||||
|
if (oldTypeDebugging) |
||||||
|
throw new AssertError("type error"); |
||||||
|
} else if (Decompiler.isTypeDebugging) { |
||||||
|
if (this.equals(type)) { |
||||||
|
// System.err.println("intersecting identical: "+this);
|
||||||
|
// Thread.dumpStack();
|
||||||
|
} else |
||||||
|
System.err.println("intersecting "+ this +" and "+ type + |
||||||
|
" to " + result); |
||||||
|
|
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if this and <unknown -- type&rt; are not disjunct. |
||||||
|
* @param type a simple type; this mustn't be a range type. |
||||||
|
* @return true if this is the case. |
||||||
|
*/ |
||||||
|
public final boolean isOfType(Type type) { |
||||||
|
return (getTop().getGeneralizedType(type.getTop()).createRangeType |
||||||
|
(getBottom().getSpecializedType(type.getBottom())) != tError); |
||||||
|
// return (getSpecializedType(type).equals(type));
|
||||||
|
} |
||||||
|
|
||||||
|
public String toString() { |
||||||
|
switch (typecode) { |
||||||
|
case TC_BOOLINT: |
||||||
|
if (Decompiler.isTypeDebugging) |
||||||
|
return "<bool or int>"; |
||||||
|
/* fall through */ |
||||||
|
case TC_BOOLBYTE: |
||||||
|
if (Decompiler.isTypeDebugging) |
||||||
|
return "<bool or byte>"; |
||||||
|
/* fall through */ |
||||||
|
case TC_BOOLEAN: |
||||||
|
return "boolean"; |
||||||
|
case TC_BYTE: |
||||||
|
return "byte"; |
||||||
|
case TC_CHAR: |
||||||
|
return "char"; |
||||||
|
case TC_SHORT: |
||||||
|
return "short"; |
||||||
|
case TC_INT: |
||||||
|
return "int"; |
||||||
|
case TC_LONG: |
||||||
|
return "long"; |
||||||
|
case TC_FLOAT: |
||||||
|
return "float"; |
||||||
|
case TC_DOUBLE: |
||||||
|
return "double"; |
||||||
|
case TC_NULL: |
||||||
|
return "null"; |
||||||
|
case TC_VOID: |
||||||
|
return "void"; |
||||||
|
case TC_UNKNOWN: |
||||||
|
return "<unknown>"; |
||||||
|
case TC_ERROR: |
||||||
|
default: |
||||||
|
return "<error>"; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue