01: // Copyright (c) 1999 Per M.A. Bothner.
02: // This is free software; for terms and warranty disclaimer see ./COPYING.
03:
04: package gnu.expr;
05:
06: import gnu.bytecode.*;
07: import gnu.mapping.Values;
08:
09: public class StackTarget extends Target {
10: Type type;
11:
12: public StackTarget(Type type) {
13: this .type = type;
14: }
15:
16: public Type getType() {
17: return type;
18: }
19:
20: public static Target getInstance(Type type) {
21: return (type.isVoid() ? Target.Ignore
22: : type == Type.pointer_type ? Target.pushObject
23: : new StackTarget(type));
24: }
25:
26: protected boolean compileFromStack0(Compilation comp, Type stackType) {
27: return compileFromStack0(comp, stackType, type);
28: }
29:
30: static boolean compileFromStack0(Compilation comp, Type stackType,
31: Type type) {
32: if (type == stackType)
33: return true;
34: CodeAttr code = comp.getCode();
35: if (stackType.isVoid()) {
36: comp.compileConstant(Values.empty);
37: stackType = Type.pointer_type;
38: } else if (stackType instanceof PrimType
39: && type instanceof PrimType) {
40: code.emitConvert(stackType, type);
41: return true;
42: }
43:
44: if (stackType instanceof ArrayType) {
45: if (type == Type.pointer_type
46: || "java.lang.Cloneable".equals(type.getName()))
47: return true;
48: // FIXME should check if stackType is compatible array type.
49: } else {
50: stackType.emitCoerceToObject(code);
51: stackType = code.topType();
52: }
53: return !CodeAttr.castNeeded(stackType, type);
54: }
55:
56: public static void convert(Compilation comp, Type stackType,
57: Type targetType) {
58: if (!compileFromStack0(comp, stackType, targetType))
59: emitCoerceFromObject(targetType, comp);
60: }
61:
62: protected static void emitCoerceFromObject(Type type,
63: Compilation comp) {
64: CodeAttr code = comp.getCode();
65: if (type instanceof gnu.kawa.reflect.OccurrenceType) {
66: // Kludge (OccurrenceType doesn't implement emitCoerceFromObject):
67: comp.compileConstant(type, Target.pushObject);
68: code.emitSwap();
69: code.emitInvokeVirtual(ClassType.make("gnu.bytecode.Type")
70: .getDeclaredMethod("coerceFromObject", 1));
71: } else {
72: comp.usedClass(type);
73: type.emitCoerceFromObject(code);
74: }
75: }
76:
77: public void compileFromStack(Compilation comp, Type stackType) {
78: if (!compileFromStack0(comp, stackType))
79: emitCoerceFromObject(type, comp);
80: }
81: }
|