KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > expr > CheckedTarget


1 // Copyright (c) 1999 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.expr;
5 import gnu.bytecode.*;
6 import gnu.mapping.WrongType;
7
8 /** Same as StackTarget, but catch ClassCastException.
9  * Generate code so that if coercion fails, catch ClassCastException,
10  * and re-throw a WrongType. This gives better error messages. */

11
12 public class CheckedTarget extends StackTarget
13 {
14   LambdaExp proc;
15   String JavaDoc procname;
16   /** 1-origin argument index,
17       or WrongType.ARG_CAST, or WrongType-ARG_VARNAME. */

18   int argno;
19
20   public CheckedTarget(Type type)
21   {
22     super(type);
23     argno = WrongType.ARG_CAST;
24   }
25
26   public CheckedTarget(Type type, LambdaExp proc, int argno)
27   {
28     super(type);
29     this.proc = proc;
30     this.procname = proc.getName();
31     this.argno = argno;
32   }
33
34   public CheckedTarget(Type type, String JavaDoc procname, int argno)
35   {
36     super(type);
37     this.procname = procname;
38     this.argno = argno;
39   }
40
41   public static Target getInstance(Type type, String JavaDoc procname, int argno)
42   {
43     return (type == Type.pointer_type ? Target.pushObject
44             : new CheckedTarget(type, procname, argno));
45   }
46
47   public static Target getInstance(Type type, LambdaExp proc, int argno)
48   {
49     return (type == Type.pointer_type ? Target.pushObject
50             : new CheckedTarget(type, proc, argno));
51   }
52
53   public static Target getInstance(Type type)
54   {
55     return (type == Type.pointer_type ? Target.pushObject
56             : new CheckedTarget(type));
57   }
58
59   static ClassType typeClassCastException;
60   static ClassType typeWrongType;
61   static Method initWrongTypeStringMethod;
62   static Method initWrongTypeProcMethod;
63
64   private static void initWrongType()
65   {
66     if (typeClassCastException == null)
67       typeClassCastException = ClassType.make("java.lang.ClassCastException");
68     if (typeWrongType == null)
69       {
70         typeWrongType= ClassType.make("gnu.mapping.WrongType");
71         Type[] args = new Type[4];
72         args[0] = typeClassCastException;
73         args[1] = Compilation.javaStringType;
74         args[2] = Type.int_type;
75     args[3] = Type.pointer_type;
76         initWrongTypeStringMethod
77           = typeWrongType.addMethod("<init>", Access.PUBLIC,
78                                     args, Type.void_type);
79         args = new Type[4];
80         args[0] = typeClassCastException;
81         args[1] = Compilation.typeProcedure;
82         args[2] = Type.int_type;
83     args[3] = Type.pointer_type;
84         initWrongTypeProcMethod
85           = typeWrongType.addMethod("<init>", Access.PUBLIC,
86                                     args, Type.void_type);
87       }
88   }
89
90   public void compileFromStack(Compilation comp, Type stackType)
91   {
92     if (! compileFromStack0(comp, stackType))
93       emitCheckedCoerce(comp, proc, procname, argno, type, null);
94   }
95
96   public static void emitCheckedCoerce(Compilation comp,
97                                        String JavaDoc procname, int argno, Type type)
98   {
99     emitCheckedCoerce(comp, null, procname, argno, type, null);
100   }
101
102   public static void emitCheckedCoerce(Compilation comp, LambdaExp proc,
103                                        int argno, Type type)
104   {
105     emitCheckedCoerce(comp, proc, proc.getName(), argno, type, null);
106   }
107
108   public static void emitCheckedCoerce(Compilation comp, LambdaExp proc,
109                                        int argno, Type type, Variable argValue)
110   {
111     emitCheckedCoerce(comp, proc, proc.getName(), argno, type, argValue);
112   }
113
114   static void emitCheckedCoerce(Compilation comp, LambdaExp proc,
115                                 String JavaDoc procname, int argno, Type type,
116                 Variable argValue)
117   {
118     CodeAttr code = comp.getCode();
119     // If we're not in a try statement, it is more efficient to defer
120
// the handler to the end of the procedure (thus avoiding a goto,
121
// and potentially improving locality). If we're in a try statement,
122
// we can't safely do that
123
boolean isInTry = code.isInTry();
124     initWrongType();
125     Label startTry = new Label(code);
126     Scope tmpScope;
127     if (argValue == null && type != Type.tostring_type)
128       {
129     tmpScope = code.pushScope();
130     argValue = code.addLocal(Type.pointer_type);
131     code.emitDup(1);
132     code.emitStore(argValue);
133       }
134     else
135       tmpScope = null;
136     int startPC = code.getPC();
137     startTry.define(code);
138     emitCoerceFromObject(type, comp);
139
140     int endPC = code.getPC();
141     // If no cast was needed, no code has been generated.
142
// Thus endPC is equal to startPC and we can stop safely.
143
// Also, tostring_type can never raise an exception, so we don't need
144
// to catch it.
145
if (endPC == startPC
146     || type == Type.tostring_type)
147       {
148         // FIXME should remove generated store to argValue, by truncating
149
// PC to startPC. But take care with startPC.position.
150
if (tmpScope != null)
151       code.popScope();
152     return;
153       }
154
155     Label endTry = new Label(code);
156     endTry.define(code);
157
158     Label endLabel = new Label(code);
159     if (isInTry)
160       code.emitGoto(endLabel);
161     int fragment_cookie = 0;
162     if (! isInTry)
163       fragment_cookie = code.beginFragment(new Label(code), endLabel);
164     code.addHandler(startTry, endTry, typeClassCastException);
165     // Push arguments:
166
// ClassCastException is already pushed
167
code.pushType(typeClassCastException);
168     boolean thisIsProc = false;
169     if (proc != null && proc.isClassGenerated()
170         && ! comp.method.getStaticFlag())
171       {
172         if (comp.method.getDeclaringClass() == proc.getCompiledClassType(comp))
173           thisIsProc = true;
174       }
175     int line = comp.getLineNumber();
176     if (line > 0)
177       code.putLineNumber(line);
178     code.emitNew(typeWrongType);
179     code.emitDupX(); // dup_x1
180
code.emitSwap();
181     if (thisIsProc)
182       code.emitPushThis();
183     else
184       code.emitPushString(procname == null && argno != WrongType.ARG_CAST
185               ? "lambda"
186               : procname);
187     code.emitPushInt(argno);
188     code.emitLoad(argValue);
189     code.emitInvokeSpecial(thisIsProc ? initWrongTypeProcMethod
190                            : initWrongTypeStringMethod);
191     if (tmpScope != null)
192       code.popScope();
193     code.emitThrow();
194     if (isInTry)
195       endLabel.define(code);
196     else
197       code.endFragment(fragment_cookie);
198   }
199 }
200
Popular Tags