001: package gnu.kawa.lispexpr;
002:
003: import gnu.bytecode.*;
004: import gnu.math.IntNum;
005: import gnu.math.DFloNum;
006: import gnu.expr.*;
007: import gnu.text.Char;
008: import gnu.mapping.Procedure;
009: import gnu.mapping.Values;
010:
011: /** Use to implement some special types that convert differently. */
012:
013: public class LangPrimType extends PrimType implements TypeValue {
014: Language language;
015: PrimType implementationType;
016:
017: public static final LangPrimType byteType = new LangPrimType(
018: Type.byte_type);
019: public static final LangPrimType shortType = new LangPrimType(
020: Type.short_type);
021: public static final LangPrimType intType = new LangPrimType(
022: Type.int_type);
023: public static final LangPrimType longType = new LangPrimType(
024: Type.long_type);
025: public static final LangPrimType floatType = new LangPrimType(
026: Type.float_type);
027: public static final LangPrimType doubleType = new LangPrimType(
028: Type.double_type);
029: public static final LangPrimType charType = new LangPrimType(
030: Type.char_type);
031: public static final LangPrimType voidType = new LangPrimType(
032: Type.void_type);
033:
034: public LangPrimType(PrimType type) {
035: super (type);
036: implementationType = type;
037: }
038:
039: public LangPrimType(PrimType type, Language language) {
040: super (type);
041: this .language = language;
042: implementationType = type;
043: }
044:
045: public LangPrimType(String nam, String sig, int siz,
046: Class reflectClass) {
047: super (nam, sig, siz, reflectClass);
048: }
049:
050: public LangPrimType(String nam, String sig, int siz,
051: Class reflectClass, Language language) {
052: this (nam, sig, siz, reflectClass);
053: implementationType = Type.signatureToPrimitive(sig.charAt(0));
054: this .language = language;
055: }
056:
057: public Type getImplementationType() {
058: return implementationType;
059: }
060:
061: public Object coerceFromObject(Object obj) {
062: if (obj.getClass() == reflectClass)
063: return obj;
064: char sig1 = getSignature().charAt(0);
065: switch (sig1) {
066: case 'Z':
067: return language.isTrue(obj) ? Boolean.TRUE : Boolean.FALSE;
068: case 'C':
069: return new Character(((Char) obj).charValue());
070: case 'V':
071: return Values.empty;
072: }
073: return super .coerceFromObject(obj);
074: }
075:
076: public char charValue(Object value) {
077: if (value instanceof Character)
078: return ((Character) value).charValue();
079: return ((Char) value).charValue();
080: }
081:
082: public void emitIsInstance(CodeAttr code) {
083: char sig1 = getSignature().charAt(0);
084: switch (sig1) {
085: case 'Z':
086: code.emitPop(1);
087: code.emitPushInt(1);
088: break;
089: case 'C':
090: ClassType scmCharType = ClassType.make("gnu.text.Char");
091: code.emitInstanceof(scmCharType);
092: break;
093: default:
094: super .emitIsInstance(code);
095: }
096: }
097:
098: public void emitCoerceFromObject(CodeAttr code) {
099: char sig1 = getSignature().charAt(0);
100: switch (sig1) {
101: case 'Z':
102: language.emitCoerceToBoolean(code);
103: break;
104: case 'C':
105: // We handle char specially, because Kawa does not use standard
106: // java.lang.Character type.
107: ClassType scmCharType = ClassType.make("gnu.text.Char");
108: Method charValueMethod = scmCharType.getDeclaredMethod(
109: "charValue", 0);
110: code.emitCheckcast(scmCharType);
111: code.emitInvokeVirtual(charValueMethod);
112: break;
113: default:
114: super .emitCoerceFromObject(code);
115: }
116: }
117:
118: public Object coerceToObject(Object obj) {
119: char sig1 = getSignature().charAt(0);
120: switch (sig1) {
121: case 'Z':
122: return language.booleanObject(((Boolean) obj)
123: .booleanValue());
124: case 'C':
125: if (obj instanceof Char)
126: return obj;
127: return Char.make(((Character) obj).charValue());
128: case 'B':
129: case 'S':
130: case 'I':
131: return IntNum.make(((Number) obj).intValue());
132: case 'J':
133: return IntNum.make(((Number) obj).longValue());
134: case 'D':
135: case 'F':
136: return DFloNum.make(((Number) obj).doubleValue());
137: case 'V':
138: // Perhaps we should return Language.noValue() instead?
139: return gnu.mapping.Values.empty;
140: }
141: return super .coerceToObject(obj);
142: }
143:
144: public void emitCoerceToObject(CodeAttr code) {
145: char sig1 = getSignature().charAt(0);
146: Type argType = null;
147: String cname = null;
148: switch (sig1) {
149: case 'Z':
150: code.emitIfIntNotZero();
151: language.emitPushBoolean(true, code);
152: code.emitElse();
153: language.emitPushBoolean(false, code);
154: code.emitFi();
155: break;
156: case 'C':
157: ClassType scmCharType = ClassType.make("gnu.text.Char");
158: Method makeCharMethod = scmCharType.getDeclaredMethod(
159: "make", 1);
160: code.emitInvokeStatic(makeCharMethod);
161: break;
162: case 'B':
163: case 'S':
164: case 'I':
165: cname = "gnu.math.IntNum";
166: argType = Type.int_type;
167: break;
168: case 'J':
169: cname = "gnu.math.IntNum";
170: argType = Type.long_type;
171: break;
172: case 'F':
173: code.emitConvert(Type.float_type, Type.double_type);
174: // ... fall through ...
175: case 'D':
176: cname = "gnu.math.DFloNum";
177: argType = Type.double_type;
178: break;
179: default:
180: super .emitCoerceToObject(code);
181: }
182: if (cname != null) {
183: ClassType clas = ClassType.make(cname);
184: Type[] args = { argType };
185: code.emitInvokeStatic(clas.getDeclaredMethod("make", args));
186: }
187: }
188:
189: public int compare(Type other) {
190: // Anything (except void) can be converted to boolean.
191: char sig1 = getSignature().charAt(0);
192: if (other instanceof PrimType) {
193: char sig2 = other.getSignature().charAt(0);
194: if (sig1 == sig2)
195: return 0;
196: if (sig1 == 'V')
197: return 1;
198: if (sig2 == 'V' || sig2 == 'Z')
199: return -1;
200: }
201: if (sig1 == 'V' || sig1 == 'Z')
202: return 1;
203: return super .compare(other);
204: }
205:
206: public void emitTestIf(Variable incoming, Declaration decl,
207: Compilation comp) {
208: char sig1 = getSignature().charAt(0);
209: /*
210: switch (sig1)
211: {
212: case 'Z':
213: }
214: */
215: CodeAttr code = comp.getCode();
216: if (incoming != null)
217: code.emitLoad(incoming);
218: if (decl != null) {
219: code.emitDup();
220: decl.compileStore(comp);
221: }
222: emitIsInstance(code);
223: code.emitIfIntNotZero();
224: }
225:
226: public void emitIsInstance(Variable incoming, Compilation comp,
227: Target target) {
228: gnu.kawa.reflect.InstanceOf.emitIsInstance(this , incoming,
229: comp, target);
230: }
231:
232: public Procedure getConstructor() {
233: return null;
234: }
235: }
|