001: package gnu.bytecode;
002:
003: public class PrimType extends Type {
004:
005: public PrimType(String nam, String sig, int siz, Class reflectClass) {
006: super (nam, sig);
007: size = siz;
008: this .reflectClass = reflectClass;
009: Type.registerTypeForClass(reflectClass, this );
010: }
011:
012: protected PrimType(PrimType type) {
013: super (type.this _name, type.signature);
014: size = type.size;
015: reflectClass = type.reflectClass;
016: }
017:
018: public Object coerceFromObject(Object obj) {
019: if (obj.getClass() == reflectClass)
020: return obj;
021: char sig1 = (signature == null || signature.length() != 1) ? ' '
022: : signature.charAt(0);
023: switch (sig1) {
024: case 'B':
025: return new Byte(((Number) obj).byteValue());
026: case 'S':
027: return new Short(((Number) obj).shortValue());
028: case 'I':
029: return new Integer(((Number) obj).intValue());
030: case 'J':
031: return new Long(((Number) obj).longValue());
032: case 'F':
033: return new Float(((Number) obj).floatValue());
034: case 'D':
035: return new Double(((Number) obj).doubleValue());
036: }
037: throw new ClassCastException("don't know how to coerce "
038: + obj.getClass().getName() + " to " + getName());
039: }
040:
041: /** Coerce value to a char.
042: * Only defined if getSignature() is "C". */
043: public char charValue(Object value) {
044: return ((Character) value).charValue();
045: }
046:
047: /** Coerce value to a boolean.
048: * Only defined if getSignature() is "Z". */
049: public static boolean booleanValue(Object value) {
050: return !(value instanceof Boolean)
051: || ((Boolean) value).booleanValue();
052: }
053:
054: public void emitCoerceToObject(CodeAttr code) {
055: char sig1 = getSignature().charAt(0);
056: ClassType clas;
057: Method method;
058: String cname;
059: Type[] args;
060: switch (sig1) {
061: case 'Z':
062: clas = ClassType.make("java.lang.Boolean");
063: code.emitIfIntNotZero();
064: code.emitGetStatic(clas.getDeclaredField("TRUE"));
065: code.emitElse();
066: code.emitGetStatic(clas.getDeclaredField("FALSE"));
067: code.emitFi();
068: return;
069: case 'C':
070: cname = "java.lang.Character";
071: break;
072: case 'B':
073: cname = "java.lang.Byte";
074: break;
075: case 'S':
076: cname = "java.lang.Short";
077: break;
078: case 'I':
079: cname = "java.lang.Integer";
080: break;
081: case 'J':
082: cname = "java.lang.Long";
083: break;
084: case 'F':
085: cname = "java.lang.Float";
086: break;
087: case 'D':
088: cname = "java.lang.Double";
089: break;
090: default:
091: cname = null; // Should never happen.
092: }
093: clas = ClassType.make(cname);
094: args = new Type[1];
095: args[0] = this ;
096: method = clas.getDeclaredMethod("<init>", args);
097: code.emitNew(clas);
098: code.emitDupX();
099: code.emitSwap();
100: code.emitInvokeSpecial(method);
101: }
102:
103: public void emitIsInstance(CodeAttr code) {
104: char sig1 = (signature == null || signature.length() != 1) ? ' '
105: : signature.charAt(0);
106: if (sig1 == 'Z') // boolean
107: boolean_ctype.emitIsInstance(code);
108: else if (sig1 == 'V') {
109: code.emitPop(1);
110: code.emitPushInt(1);
111: }
112: // Have left out Character -> char, since not used by Kawa.
113: else
114: number_type.emitIsInstance(code);
115: }
116:
117: public void emitCoerceFromObject(CodeAttr code) {
118: char sig1 = (signature == null || signature.length() != 1) ? ' '
119: : signature.charAt(0);
120: if (sig1 == 'Z') // boolean
121: {
122: code.emitCheckcast(boolean_ctype);
123: code.emitInvokeVirtual(booleanValue_method);
124: } else if (sig1 == 'V')
125: code.emitPop(1);
126: else {
127: code.emitCheckcast(number_type);
128: if (sig1 == 'I' || sig1 == 'S' || sig1 == 'B')
129: code.emitInvokeVirtual(intValue_method);
130: else if (sig1 == 'J')
131: code.emitInvokeVirtual(longValue_method);
132: else if (sig1 == 'D')
133: code.emitInvokeVirtual(doubleValue_method);
134: else if (sig1 == 'F')
135: code.emitInvokeVirtual(floatValue_method);
136: // Have left out Character -> char, since not used by Kawa.
137: else
138: super .emitCoerceFromObject(code);
139: }
140: }
141:
142: public static int compare(PrimType type1, PrimType type2) {
143: char sig1 = type1.signature.charAt(0);
144: char sig2 = type2.signature.charAt(0);
145:
146: if (sig1 == sig2)
147: return 0;
148:
149: // Anything can be converted to void, but not vice versa.
150: if (sig1 == 'V')
151: return 1;
152: if (sig2 == 'V')
153: return -1;
154:
155: // In Java, no other type can be converted to/from boolean.
156: // Other languages, including C and Scheme are different:
157: // "everything" can be converted to a boolean.
158: if (sig1 == 'Z' || sig2 == 'Z')
159: return -3;
160:
161: if (sig1 == 'C')
162: return type2.size > 2 ? -1 : -3;
163: if (sig2 == 'C')
164: return type1.size > 2 ? 1 : -3;
165:
166: if (sig1 == 'D')
167: return 1;
168: if (sig2 == 'D')
169: return -1;
170: if (sig1 == 'F')
171: return 1;
172: if (sig2 == 'F')
173: return -1;
174: if (sig1 == 'J')
175: return 1;
176: if (sig2 == 'J')
177: return -1;
178: if (sig1 == 'I')
179: return 1;
180: if (sig2 == 'I')
181: return -1;
182: if (sig1 == 'S')
183: return 1;
184: if (sig2 == 'S')
185: return -1;
186: // Can we get here?
187: return -3;
188: }
189:
190: public int compare(Type other) {
191: if (other instanceof PrimType)
192: return compare(this , (PrimType) other);
193: if (!(other instanceof ClassType))
194: return -3;
195: char sig1 = signature.charAt(0);
196: String otherName = other.getName();
197: if (otherName == null)
198: return -1;
199: switch (sig1) {
200: case 'V':
201: return 1;
202: case 'Z':
203: case 'C':
204: break;
205: case 'D':
206: if (otherName.equals("java.lang.Double")
207: || otherName.equals("gnu.math.DFloNum"))
208: return 0; // Or maybe 1?
209: if (otherName.equals("java.lang.Float"))
210: return 1;
211: break;
212: case 'F':
213: if (otherName.equals("java.lang.Double")
214: || otherName.equals("gnu.math.DFloNum"))
215: return -1;
216: if (otherName.equals("java.lang.Float"))
217: return 0; // Or maybe 1?
218: break;
219: case 'I':
220: if (otherName.equals("java.lang.Integer"))
221: return 0; // Or maybe 1?
222: if (otherName.equals("gnu.math.IntNum"))
223: return -1;
224: /* fall through */
225: default:
226: if (otherName.equals("java.lang.Double")
227: || otherName.equals("java.lang.Float")
228: || otherName.equals("gnu.math.DFloNum"))
229: return -1;
230: }
231: if (otherName.equals("java.lang.Object")
232: || other == tostring_type)
233: return -1;
234: return -2;
235: }
236: }
|