KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > compiler > JvstTypeChecker


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */

15
16 package javassist.compiler;
17
18 import javassist.*;
19 import javassist.compiler.ast.*;
20
21 /* Type checker accepting extended Java syntax for Javassist.
22  */

23
24 public class JvstTypeChecker extends TypeChecker {
25     private JvstCodeGen codeGen;
26
27     public JvstTypeChecker(CtClass cc, ClassPool cp, JvstCodeGen gen) {
28         super(cc, cp);
29         codeGen = gen;
30     }
31
32     /* If the type of the expression compiled last is void,
33      * add ACONST_NULL and change exprType, arrayDim, className.
34      */

35     public void addNullIfVoid() {
36         if (exprType == VOID) {
37             exprType = CLASS;
38             arrayDim = 0;
39             className = jvmJavaLangObject;
40         }
41     }
42
43     /* To support $args, $sig, and $type.
44      * $args is an array of parameter list.
45      */

46     public void atMember(Member mem) throws CompileError {
47         String JavaDoc name = mem.get();
48         if (name.equals(codeGen.paramArrayName)) {
49             exprType = CLASS;
50             arrayDim = 1;
51             className = jvmJavaLangObject;
52         }
53         else if (name.equals(JvstCodeGen.sigName)) {
54             exprType = CLASS;
55             arrayDim = 1;
56             className = "java/lang/Class";
57         }
58         else if (name.equals(JvstCodeGen.dollarTypeName)
59                  || name.equals(JvstCodeGen.clazzName)) {
60             exprType = CLASS;
61             arrayDim = 0;
62             className = "java/lang/Class";
63         }
64         else
65             super.atMember(mem);
66     }
67
68     protected void atFieldAssign(Expr expr, int op, ASTree left, ASTree right)
69         throws CompileError
70     {
71         if (left instanceof Member
72             && ((Member)left).get().equals(codeGen.paramArrayName)) {
73             right.accept(this);
74             CtClass[] params = codeGen.paramTypeList;
75             if (params == null)
76                 return;
77
78             int n = params.length;
79             for (int i = 0; i < n; ++i)
80                 compileUnwrapValue(params[i]);
81         }
82         else
83             super.atFieldAssign(expr, op, left, right);
84     }
85
86     public void atCastExpr(CastExpr expr) throws CompileError {
87         ASTList classname = expr.getClassName();
88         if (classname != null && expr.getArrayDim() == 0) {
89             ASTree p = classname.head();
90             if (p instanceof Symbol && classname.tail() == null) {
91                 String JavaDoc typename = ((Symbol)p).get();
92                 if (typename.equals(codeGen.returnCastName)) {
93                     atCastToRtype(expr);
94                     return;
95                 }
96                 else if (typename.equals(JvstCodeGen.wrapperCastName)) {
97                     atCastToWrapper(expr);
98                     return;
99                 }
100             }
101         }
102
103         super.atCastExpr(expr);
104     }
105
106     /**
107      * Inserts a cast operator to the return type.
108      * If the return type is void, this does nothing.
109      */

110     protected void atCastToRtype(CastExpr expr) throws CompileError {
111         CtClass returnType = codeGen.returnType;
112         expr.getOprand().accept(this);
113         if (exprType == VOID || CodeGen.isRefType(exprType) || arrayDim > 0)
114             compileUnwrapValue(returnType);
115         else if (returnType instanceof CtPrimitiveType) {
116             CtPrimitiveType pt = (CtPrimitiveType)returnType;
117             int destType = MemberResolver.descToType(pt.getDescriptor());
118             exprType = destType;
119             arrayDim = 0;
120             className = null;
121         }
122     }
123
124     protected void atCastToWrapper(CastExpr expr) throws CompileError {
125         expr.getOprand().accept(this);
126         if (CodeGen.isRefType(exprType) || arrayDim > 0)
127             return; // Object type. do nothing.
128

129         CtClass clazz = resolver.lookupClass(exprType, arrayDim, className);
130         if (clazz instanceof CtPrimitiveType) {
131             exprType = CLASS;
132             arrayDim = 0;
133             className = jvmJavaLangObject;
134         }
135     }
136
137     /* Delegates to a ProcHandler object if the method call is
138      * $proceed(). It may process $cflow().
139      */

140     public void atCallExpr(CallExpr expr) throws CompileError {
141         ASTree method = expr.oprand1();
142         if (method instanceof Member) {
143             String JavaDoc name = ((Member)method).get();
144             if (codeGen.procHandler != null
145                 && name.equals(codeGen.proceedName)) {
146                 codeGen.procHandler.setReturnType(this,
147                                                   (ASTList)expr.oprand2());
148                 return;
149             }
150             else if (name.equals(JvstCodeGen.cflowName)) {
151                 atCflow((ASTList)expr.oprand2());
152                 return;
153             }
154         }
155
156         super.atCallExpr(expr);
157     }
158
159     /* To support $cflow().
160      */

161     protected void atCflow(ASTList cname) throws CompileError {
162         exprType = INT;
163         arrayDim = 0;
164         className = null;
165     }
166
167     /* To support $$. ($$) is equivalent to ($1, ..., $n).
168      * It can be used only as a parameter list of method call.
169      */

170     public boolean isParamListName(ASTList args) {
171         if (codeGen.paramTypeList != null
172             && args != null && args.tail() == null) {
173             ASTree left = args.head();
174             return (left instanceof Member
175                     && ((Member)left).get().equals(codeGen.paramListName));
176         }
177         else
178             return false;
179     }
180
181     public int getMethodArgsLength(ASTList args) {
182         String JavaDoc pname = codeGen.paramListName;
183         int n = 0;
184         while (args != null) {
185             ASTree a = args.head();
186             if (a instanceof Member && ((Member)a).get().equals(pname)) {
187                 if (codeGen.paramTypeList != null)
188                     n += codeGen.paramTypeList.length;
189             }
190             else
191                 ++n;
192
193             args = args.tail();
194         }
195
196         return n;
197     }
198
199     public void atMethodArgs(ASTList args, int[] types, int[] dims,
200                                 String JavaDoc[] cnames) throws CompileError {
201         CtClass[] params = codeGen.paramTypeList;
202         String JavaDoc pname = codeGen.paramListName;
203         int i = 0;
204         while (args != null) {
205             ASTree a = args.head();
206             if (a instanceof Member && ((Member)a).get().equals(pname)) {
207                 if (params != null) {
208                     int n = params.length;
209                     for (int k = 0; k < n; ++k) {
210                         CtClass p = params[k];
211                         setType(p);
212                         types[i] = exprType;
213                         dims[i] = arrayDim;
214                         cnames[i] = className;
215                         ++i;
216                     }
217                 }
218             }
219             else {
220                 a.accept(this);
221                 types[i] = exprType;
222                 dims[i] = arrayDim;
223                 cnames[i] = className;
224                 ++i;
225             }
226
227             args = args.tail();
228         }
229     }
230
231     /* called by Javac#recordSpecialProceed().
232      */

233     void compileInvokeSpecial(ASTree target, String JavaDoc classname,
234                               String JavaDoc methodname, String JavaDoc descriptor,
235                               ASTList args)
236         throws CompileError
237     {
238         target.accept(this);
239         int nargs = getMethodArgsLength(args);
240         atMethodArgs(args, new int[nargs], new int[nargs],
241                      new String JavaDoc[nargs]);
242         setReturnType(descriptor);
243         addNullIfVoid();
244     }
245
246     protected void compileUnwrapValue(CtClass type) throws CompileError
247     {
248         if (type == CtClass.voidType)
249             addNullIfVoid();
250         else
251             setType(type);
252     }
253
254     /* Sets exprType, arrayDim, and className;
255      * If type is void, then this method does nothing.
256      */

257     public void setType(CtClass type) throws CompileError {
258         setType(type, 0);
259     }
260
261     private void setType(CtClass type, int dim) throws CompileError {
262         if (type.isPrimitive()) {
263             CtPrimitiveType pt = (CtPrimitiveType)type;
264             exprType = MemberResolver.descToType(pt.getDescriptor());
265             arrayDim = dim;
266             className = null;
267         }
268         else if (type.isArray())
269             try {
270                 setType(type.getComponentType(), dim + 1);
271             }
272             catch (NotFoundException e) {
273                 throw new CompileError("undefined type: " + type.getName());
274             }
275         else {
276             exprType = CLASS;
277             arrayDim = dim;
278             className = MemberResolver.javaToJvmName(type.getName());
279         }
280     }
281 }
282
Popular Tags