KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > compiler > TypeChecker


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.CtClass;
19 import javassist.CtField;
20 import javassist.ClassPool;
21 import javassist.Modifier;
22 import javassist.NotFoundException;
23 import javassist.compiler.ast.*;
24 import javassist.bytecode.*;
25
26 public class TypeChecker extends Visitor implements Opcode, TokenId {
27     static final String JavaDoc javaLangObject = "java.lang.Object";
28     static final String JavaDoc jvmJavaLangObject = "java/lang/Object";
29     static final String JavaDoc jvmJavaLangString = "java/lang/String";
30     static final String JavaDoc jvmJavaLangClass = "java/lang/Class";
31
32     /* The following fields are used by atXXX() methods
33      * for returning the type of the compiled expression.
34      */

35     protected int exprType; // VOID, NULL, CLASS, BOOLEAN, INT, ...
36
protected int arrayDim;
37     protected String JavaDoc className; // JVM-internal representation
38

39     protected MemberResolver resolver;
40     protected CtClass thisClass;
41     protected MethodInfo thisMethod;
42
43     public TypeChecker(CtClass cc, ClassPool cp) {
44         resolver = new MemberResolver(cp);
45         thisClass = cc;
46         thisMethod = null;
47     }
48
49     /**
50      * Records the currently compiled method.
51      */

52     public void setThisMethod(MethodInfo m) {
53         thisMethod = m;
54     }
55
56     protected static void fatal() throws CompileError {
57         throw new CompileError("fatal");
58     }
59
60     /**
61      * Returns the JVM-internal representation of this class name.
62      */

63     protected String JavaDoc getThisName() {
64         return MemberResolver.javaToJvmName(thisClass.getName());
65     }
66
67     /**
68      * Returns the JVM-internal representation of this super class name.
69      */

70     protected String JavaDoc getSuperName() throws CompileError {
71         return MemberResolver.javaToJvmName(
72                         MemberResolver.getSuperclass(thisClass).getName());
73     }
74
75     /* Converts a class name into a JVM-internal representation.
76      *
77      * It may also expand a simple class name to java.lang.*.
78      * For example, this converts Object into java/lang/Object.
79      */

80     protected String JavaDoc resolveClassName(ASTList name) throws CompileError {
81         return resolver.resolveClassName(name);
82     }
83
84     /* Expands a simple class name to java.lang.*.
85      * For example, this converts Object into java/lang/Object.
86      */

87     protected String JavaDoc resolveClassName(String JavaDoc jvmName) throws CompileError {
88         return resolver.resolveJvmClassName(jvmName);
89     }
90
91     public void atNewExpr(NewExpr expr) throws CompileError {
92         if (expr.isArray())
93             atNewArrayExpr(expr);
94         else {
95             CtClass clazz = resolver.lookupClassByName(expr.getClassName());
96             String JavaDoc cname = clazz.getName();
97             ASTList args = expr.getArguments();
98             atMethodCallCore(clazz, MethodInfo.nameInit, args);
99             exprType = CLASS;
100             arrayDim = 0;
101             className = MemberResolver.javaToJvmName(cname);
102         }
103     }
104
105     public void atNewArrayExpr(NewExpr expr) throws CompileError {
106         int type = expr.getArrayType();
107         ASTList size = expr.getArraySize();
108         ASTList classname = expr.getClassName();
109         if (size.length() > 1)
110             atMultiNewArray(type, classname, size);
111         else {
112             size.head().accept(this);
113             exprType = type;
114             arrayDim = 1;
115             if (type == CLASS)
116                 className = resolveClassName(classname);
117             else
118                 className = null;
119         }
120     }
121
122     protected void atMultiNewArray(int type, ASTList classname, ASTList size)
123         throws CompileError
124     {
125         int count, dim;
126         dim = size.length();
127         for (count = 0; size != null; size = size.tail()) {
128             ASTree s = size.head();
129             if (s == null)
130                 break; // int[][][] a = new int[3][4][];
131

132             ++count;
133             s.accept(this);
134         }
135
136         exprType = type;
137         arrayDim = dim;
138         if (type == CLASS)
139             className = resolveClassName(classname);
140         else
141             className = null;
142     }
143
144     public void atAssignExpr(AssignExpr expr) throws CompileError {
145         // =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, >>>=
146
int op = expr.getOperator();
147         ASTree left = expr.oprand1();
148         ASTree right = expr.oprand2();
149         if (left instanceof Variable)
150             atVariableAssign(expr, op, (Variable)left,
151                              ((Variable)left).getDeclarator(),
152                              right);
153         else {
154             if (left instanceof Expr) {
155                 Expr e = (Expr)left;
156                 if (e.getOperator() == ARRAY) {
157                     atArrayAssign(expr, op, (Expr)left, right);
158                     return;
159                 }
160             }
161
162             atFieldAssign(expr, op, left, right);
163         }
164     }
165
166     /* op is either =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, or >>>=.
167      *
168      * expr and var can be null.
169      */

170     private void atVariableAssign(Expr expr, int op, Variable var,
171                                   Declarator d, ASTree right)
172         throws CompileError
173     {
174         int varType = d.getType();
175         int varArray = d.getArrayDim();
176         String JavaDoc varClass = d.getClassName();
177
178         if (op != '=')
179             atVariable(var);
180
181         right.accept(this);
182         exprType = varType;
183         arrayDim = varArray;
184         className = varClass;
185     }
186
187     private void atArrayAssign(Expr expr, int op, Expr array,
188                         ASTree right) throws CompileError
189     {
190         atArrayRead(array.oprand1(), array.oprand2());
191         int aType = exprType;
192         int aDim = arrayDim;
193         String JavaDoc cname = className;
194         right.accept(this);
195         exprType = aType;
196         arrayDim = aDim;
197         className = cname;
198     }
199
200     protected void atFieldAssign(Expr expr, int op, ASTree left, ASTree right)
201         throws CompileError
202     {
203         CtField f = fieldAccess(left);
204         atFieldRead(f);
205         int fType = exprType;
206         int fDim = arrayDim;
207         String JavaDoc cname = className;
208         right.accept(this);
209         exprType = fType;
210         arrayDim = fDim;
211         className = cname;
212     }
213
214     public void atCondExpr(CondExpr expr) throws CompileError {
215         booleanExpr(expr.condExpr());
216         expr.thenExpr().accept(this);
217         int type1 = exprType;
218         int dim1 = arrayDim;
219         String JavaDoc cname1 = className;
220         expr.elseExpr().accept(this);
221
222         if (dim1 == 0 && dim1 == arrayDim)
223             if (CodeGen.rightIsStrong(type1, exprType))
224                 expr.setThen(new CastExpr(exprType, 0, expr.thenExpr()));
225             else if (CodeGen.rightIsStrong(exprType, type1)) {
226                 expr.setElse(new CastExpr(type1, 0, expr.elseExpr()));
227                 exprType = type1;
228             }
229     }
230
231     /*
232      * If atBinExpr() substitutes a new expression for the original
233      * binary-operator expression, it changes the operator name to '+'
234      * (if the original is not '+') and sets the new expression to the
235      * left-hand-side expression and null to the right-hand-side expression.
236      */

237     public void atBinExpr(BinExpr expr) throws CompileError {
238         int token = expr.getOperator();
239         int k = CodeGen.lookupBinOp(token);
240         if (k >= 0) {
241             /* arithmetic operators: +, -, *, /, %, |, ^, &, <<, >>, >>>
242              */

243             if (token == '+') {
244                 Expr e = atPlusExpr(expr);
245                 if (e != null) {
246                     /* String concatenation has been translated into
247                      * an expression using StringBuffer.
248                      */

249                     e = CallExpr.makeCall(Expr.make('.', e,
250                                             new Member("toString")), null);
251                     expr.setOprand1(e);
252                     expr.setOprand2(null); // <---- look at this!
253
className = jvmJavaLangString;
254                 }
255             }
256             else {
257                 ASTree left = expr.oprand1();
258                 ASTree right = expr.oprand2();
259                 left.accept(this);
260                 int type1 = exprType;
261                 right.accept(this);
262                 if (!isConstant(expr, token, left, right))
263                     computeBinExprType(expr, token, type1);
264             }
265         }
266         else {
267             /* equation: &&, ||, ==, !=, <=, >=, <, >
268             */

269             booleanExpr(expr);
270         }
271     }
272
273     /* EXPR must be a + expression.
274      * atPlusExpr() returns non-null if the given expression is string
275      * concatenation. The returned value is "new StringBuffer().append..".
276      */

277     private Expr atPlusExpr(BinExpr expr) throws CompileError {
278         ASTree left = expr.oprand1();
279         ASTree right = expr.oprand2();
280         if (right == null) {
281             // this expression has been already type-checked.
282
// see atBinExpr() above.
283
left.accept(this);
284             return null;
285         }
286
287         if (isPlusExpr(left)) {
288             Expr newExpr = atPlusExpr((BinExpr)left);
289             if (newExpr != null) {
290                 right.accept(this);
291                 exprType = CLASS;
292                 arrayDim = 0;
293                 className = "java/lang/StringBuffer";
294                 return makeAppendCall(newExpr, right);
295             }
296         }
297         else
298             left.accept(this);
299
300         int type1 = exprType;
301         int dim1 = arrayDim;
302         String JavaDoc cname = className;
303         right.accept(this);
304
305         if (isConstant(expr, '+', left, right))
306             return null;
307
308         if ((type1 == CLASS && dim1 == 0 && jvmJavaLangString.equals(cname))
309             || (exprType == CLASS && arrayDim == 0
310                 && jvmJavaLangString.equals(className))) {
311             ASTList sbufClass = ASTList.make(new Symbol("java"),
312                             new Symbol("lang"), new Symbol("StringBuffer"));
313             ASTree e = new NewExpr(sbufClass, null);
314             exprType = CLASS;
315             arrayDim = 0;
316             className = "java/lang/StringBuffer";
317             return makeAppendCall(makeAppendCall(e, left), right);
318         }
319         else {
320             computeBinExprType(expr, '+', type1);
321             return null;
322         }
323     }
324
325     private boolean isConstant(BinExpr expr, int op, ASTree left,
326                                ASTree right) throws CompileError
327     {
328         left = stripPlusExpr(left);
329         right = stripPlusExpr(right);
330         ASTree newExpr = null;
331         if (left instanceof StringL && right instanceof StringL && op == '+')
332             newExpr = new StringL(((StringL)left).get()
333                                   + ((StringL)right).get());
334         else if (left instanceof IntConst)
335             newExpr = ((IntConst)left).compute(op, right);
336         else if (left instanceof DoubleConst)
337             newExpr = ((DoubleConst)left).compute(op, right);
338
339         if (newExpr == null)
340             return false; // not a constant expression
341
else {
342             expr.setOperator('+');
343             expr.setOprand1(newExpr);
344             expr.setOprand2(null);
345             newExpr.accept(this); // for setting exprType, arrayDim, ...
346
return true;
347         }
348     }
349
350     /* CodeGen.atSwitchStmnt() also calls stripPlusExpr().
351      */

352     static ASTree stripPlusExpr(ASTree expr) {
353         if (expr instanceof BinExpr) {
354             BinExpr e = (BinExpr)expr;
355             if (e.getOperator() == '+' && e.oprand2() == null)
356                 return e.getLeft();
357         }
358         else if (expr instanceof Expr) { // note: BinExpr extends Expr.
359
Expr e = (Expr)expr;
360             int op = e.getOperator();
361             if (op == MEMBER) {
362                 ASTree cexpr = getConstantFieldValue((Member)e.oprand2());
363                 if (cexpr != null)
364                     return cexpr;
365             }
366             else if (op == '+' && e.getRight() == null)
367                 return e.getLeft();
368         }
369         else if (expr instanceof Member) {
370             ASTree cexpr = getConstantFieldValue((Member)expr);
371             if (cexpr != null)
372                 return cexpr;
373         }
374
375         return expr;
376     }
377
378     /**
379      * If MEM is a static final field, this method returns a constant
380      * expression representing the value of that field.
381      */

382     private static ASTree getConstantFieldValue(Member mem) {
383         return getConstantFieldValue(mem.getField());
384     }
385
386     public static ASTree getConstantFieldValue(CtField f) {
387         if (f == null)
388             return null;
389
390         Object JavaDoc value = f.getConstantValue();
391         if (value == null)
392             return null;
393
394         if (value instanceof String JavaDoc)
395             return new StringL((String JavaDoc)value);
396         else if (value instanceof Double JavaDoc || value instanceof Float JavaDoc) {
397             int token = (value instanceof Double JavaDoc)
398                         ? DoubleConstant : FloatConstant;
399             return new DoubleConst(((Number JavaDoc)value).doubleValue(), token);
400         }
401         else if (value instanceof Number JavaDoc) {
402             int token = (value instanceof Long JavaDoc) ? LongConstant : IntConstant;
403             return new IntConst(((Number JavaDoc)value).longValue(), token);
404         }
405         else if (value instanceof Boolean JavaDoc)
406             return new Keyword(((Boolean JavaDoc)value).booleanValue()
407                                ? TokenId.TRUE : TokenId.FALSE);
408         else
409             return null;
410     }
411
412     private static boolean isPlusExpr(ASTree expr) {
413         if (expr instanceof BinExpr) {
414             BinExpr bexpr = (BinExpr)expr;
415             int token = bexpr.getOperator();
416             return token == '+';
417         }
418
419         return false;
420     }
421
422     private static Expr makeAppendCall(ASTree target, ASTree arg) {
423         return CallExpr.makeCall(Expr.make('.', target, new Member("append")),
424                                  new ASTList(arg));
425     }
426
427     private void computeBinExprType(BinExpr expr, int token, int type1)
428         throws CompileError
429     {
430         // arrayDim should be 0.
431
int type2 = exprType;
432         if (token == LSHIFT || token == RSHIFT || token == ARSHIFT)
433             exprType = type1;
434         else
435             insertCast(expr, type1, type2);
436
437         if (CodeGen.isP_INT(exprType))
438             exprType = INT; // type1 may be BYTE, ...
439
}
440
441     private void booleanExpr(ASTree expr)
442         throws CompileError
443     {
444         int op = CodeGen.getCompOperator(expr);
445         if (op == EQ) { // ==, !=, ...
446
BinExpr bexpr = (BinExpr)expr;
447             bexpr.oprand1().accept(this);
448             int type1 = exprType;
449             int dim1 = arrayDim;
450             bexpr.oprand2().accept(this);
451             if (dim1 == 0 && arrayDim == 0)
452                 insertCast(bexpr, type1, exprType);
453         }
454         else if (op == '!')
455             ((Expr)expr).oprand1().accept(this);
456         else if (op == ANDAND || op == OROR) {
457             BinExpr bexpr = (BinExpr)expr;
458             bexpr.oprand1().accept(this);
459             bexpr.oprand2().accept(this);
460         }
461         else // others
462
expr.accept(this);
463
464         exprType = BOOLEAN;
465         arrayDim = 0;
466     }
467
468     private void insertCast(BinExpr expr, int type1, int type2)
469         throws CompileError
470     {
471         if (CodeGen.rightIsStrong(type1, type2))
472             expr.setLeft(new CastExpr(type2, 0, expr.oprand1()));
473         else
474             exprType = type1;
475     }
476
477     public void atCastExpr(CastExpr expr) throws CompileError {
478         String JavaDoc cname = resolveClassName(expr.getClassName());
479         expr.getOprand().accept(this);
480         exprType = expr.getType();
481         arrayDim = expr.getArrayDim();
482         className = cname;
483     }
484
485     public void atInstanceOfExpr(InstanceOfExpr expr) throws CompileError {
486         expr.getOprand().accept(this);
487         exprType = BOOLEAN;
488         arrayDim = 0;
489     }
490
491     public void atExpr(Expr expr) throws CompileError {
492         // array access, member access,
493
// (unary) +, (unary) -, ++, --, !, ~
494

495         int token = expr.getOperator();
496         ASTree oprand = expr.oprand1();
497         if (token == '.') {
498             String JavaDoc member = ((Symbol)expr.oprand2()).get();
499             if (member.equals("length"))
500                 atArrayLength(expr);
501             else if (member.equals("class"))
502                 atClassObject(expr); // .class
503
else
504                 atFieldRead(expr);
505         }
506         else if (token == MEMBER) { // field read
507
String JavaDoc member = ((Symbol)expr.oprand2()).get();
508             if (member.equals("class"))
509                 atClassObject(expr); // .class
510
else
511                 atFieldRead(expr);
512         }
513         else if (token == ARRAY)
514             atArrayRead(oprand, expr.oprand2());
515         else if (token == PLUSPLUS || token == MINUSMINUS)
516             atPlusPlus(token, oprand, expr);
517         else if (token == '!')
518             booleanExpr(expr);
519         else if (token == CALL) // method call
520
fatal();
521         else {
522             oprand.accept(this);
523             if (!isConstant(expr, token, oprand))
524                 if (token == '-' || token == '~')
525                     if (CodeGen.isP_INT(exprType))
526                         exprType = INT; // type may be BYTE, ...
527
}
528     }
529
530     private boolean isConstant(Expr expr, int op, ASTree oprand) {
531         oprand = stripPlusExpr(oprand);
532         if (oprand instanceof IntConst) {
533             IntConst c = (IntConst)oprand;
534             long v = c.get();
535             if (op == '-')
536                 v = -v;
537             else if (op == '~')
538                 v = ~v;
539             else
540                 return false;
541
542             c.set(v);
543         }
544         else if (oprand instanceof DoubleConst) {
545             DoubleConst c = (DoubleConst)oprand;
546             if (op == '-')
547                 c.set(-c.get());
548             else
549                 return false;
550         }
551         else
552             return false;
553
554         expr.setOperator('+');
555         return true;
556     }
557
558     public void atCallExpr(CallExpr expr) throws CompileError {
559         String JavaDoc mname = null;
560         CtClass targetClass = null;
561         ASTree method = expr.oprand1();
562         ASTList args = (ASTList)expr.oprand2();
563
564         if (method instanceof Member) {
565             mname = ((Member)method).get();
566             targetClass = thisClass;
567         }
568         else if (method instanceof Keyword) { // constructor
569
mname = MethodInfo.nameInit; // <init>
570
if (((Keyword)method).get() == SUPER)
571                 targetClass = MemberResolver.getSuperclass(thisClass);
572             else
573                 targetClass = thisClass;
574         }
575         else if (method instanceof Expr) {
576             Expr e = (Expr)method;
577             mname = ((Symbol)e.oprand2()).get();
578             int op = e.getOperator();
579             if (op == MEMBER) // static method
580
targetClass
581                         = resolver.lookupClass(((Symbol)e.oprand1()).get(),
582                                                false);
583             else if (op == '.') {
584                 ASTree target = e.oprand1();
585                 try {
586                     target.accept(this);
587                 }
588                 catch (NoFieldException nfe) {
589                     if (nfe.getExpr() != target)
590                         throw nfe;
591
592                     // it should be a static method.
593
exprType = CLASS;
594                     arrayDim = 0;
595                     className = nfe.getField(); // JVM-internal
596
e.setOperator(MEMBER);
597                     e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(
598                                                             className)));
599                 }
600
601                 if (arrayDim > 0)
602                     targetClass = resolver.lookupClass(javaLangObject, true);
603                 else if (exprType == CLASS /* && arrayDim == 0 */)
604                     targetClass = resolver.lookupClassByJvmName(className);
605                 else
606                     badMethod();
607             }
608             else
609                 badMethod();
610         }
611         else
612             fatal();
613
614         MemberResolver.Method minfo
615                 = atMethodCallCore(targetClass, mname, args);
616         expr.setMethod(minfo);
617     }
618
619     private static void badMethod() throws CompileError {
620         throw new CompileError("bad method");
621     }
622
623     /**
624      * @return a pair of the class declaring the invoked method
625      * and the MethodInfo of that method. Never null.
626      */

627     public MemberResolver.Method atMethodCallCore(CtClass targetClass,
628                                                   String JavaDoc mname, ASTList args)
629         throws CompileError
630     {
631         int nargs = getMethodArgsLength(args);
632         int[] types = new int[nargs];
633         int[] dims = new int[nargs];
634         String JavaDoc[] cnames = new String JavaDoc[nargs];
635         atMethodArgs(args, types, dims, cnames);
636
637         MemberResolver.Method found
638             = resolver.lookupMethod(targetClass, thisMethod, mname,
639                                     types, dims, cnames, false);
640         if (found == null) {
641             String JavaDoc msg;
642             if (mname.equals(MethodInfo.nameInit))
643                 msg = "constructor not found";
644             else
645                 msg = "Method " + mname + " not found in "
646                     + targetClass.getName();
647
648             throw new CompileError(msg);
649         }
650
651         String JavaDoc desc = found.info.getDescriptor();
652         setReturnType(desc);
653         return found;
654     }
655
656     public int getMethodArgsLength(ASTList args) {
657         return ASTList.length(args);
658     }
659
660     public void atMethodArgs(ASTList args, int[] types, int[] dims,
661                              String JavaDoc[] cnames) throws CompileError {
662         int i = 0;
663         while (args != null) {
664             ASTree a = args.head();
665             a.accept(this);
666             types[i] = exprType;
667             dims[i] = arrayDim;
668             cnames[i] = className;
669             ++i;
670             args = args.tail();
671         }
672     }
673
674     void setReturnType(String JavaDoc desc) throws CompileError {
675         int i = desc.indexOf(')');
676         if (i < 0)
677             badMethod();
678
679         char c = desc.charAt(++i);
680         int dim = 0;
681         while (c == '[') {
682             ++dim;
683             c = desc.charAt(++i);
684         }
685
686         arrayDim = dim;
687         if (c == 'L') {
688             int j = desc.indexOf(';', i + 1);
689             if (j < 0)
690                 badMethod();
691
692             exprType = CLASS;
693             className = desc.substring(i + 1, j);
694         }
695         else {
696             exprType = MemberResolver.descToType(c);
697             className = null;
698         }
699     }
700
701     private void atFieldRead(ASTree expr) throws CompileError {
702         atFieldRead(fieldAccess(expr));
703     }
704
705     private void atFieldRead(CtField f) throws CompileError {
706         FieldInfo finfo = f.getFieldInfo2();
707         String JavaDoc type = finfo.getDescriptor();
708
709         int i = 0;
710         int dim = 0;
711         char c = type.charAt(i);
712         while (c == '[') {
713             ++dim;
714             c = type.charAt(++i);
715         }
716
717         arrayDim = dim;
718         exprType = MemberResolver.descToType(c);
719
720         if (c == 'L')
721             className = type.substring(i + 1, type.indexOf(';', i + 1));
722         else
723             className = null;
724     }
725
726     /* if EXPR is to access a static field, fieldAccess() translates EXPR
727      * into an expression using '#' (MEMBER). For example, it translates
728      * java.lang.Integer.TYPE into java.lang.Integer#TYPE. This translation
729      * speeds up type resolution by MemberCodeGen.
730      */

731     protected CtField fieldAccess(ASTree expr) throws CompileError {
732         if (expr instanceof Member) {
733             Member mem = (Member)expr;
734             String JavaDoc name = mem.get();
735             try {
736                 CtField f = thisClass.getField(name);
737                 if (Modifier.isStatic(f.getModifiers()))
738                     mem.setField(f);
739
740                 return f;
741             }
742             catch (NotFoundException e) {
743                 // EXPR might be part of a static member access?
744
throw new NoFieldException(name, expr);
745             }
746         }
747         else if (expr instanceof Expr) {
748             Expr e = (Expr)expr;
749             int op = e.getOperator();
750             if (op == MEMBER) {
751                 Member mem = (Member)e.oprand2();
752                 CtField f
753                     = resolver.lookupField(((Symbol)e.oprand1()).get(), mem);
754                 mem.setField(f);
755                 return f;
756             }
757             else if (op == '.')
758                 try {
759                     e.oprand1().accept(this);
760                     if (exprType == CLASS && arrayDim == 0)
761                         return resolver.lookupFieldByJvmName(className,
762                                                     (Symbol)e.oprand2());
763                 }
764                 catch (NoFieldException nfe) {
765                     if (nfe.getExpr() != e.oprand1())
766                         throw nfe;
767
768                     /* EXPR should be a static field.
769                      * If EXPR might be part of a qualified class name,
770                      * lookupFieldByJvmName2() throws NoFieldException.
771                      */

772                     Member fname = (Member)e.oprand2();
773                     String JavaDoc jvmClassName = nfe.getField();
774                     CtField f = resolver.lookupFieldByJvmName2(jvmClassName,
775                                                                fname, expr);
776                     e.setOperator(MEMBER);
777                     e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(
778                                                             jvmClassName)));
779                     fname.setField(f);
780                     return f;
781                 }
782         }
783
784         throw new CompileError("bad filed access");
785     }
786
787     public void atClassObject(Expr expr) throws CompileError {
788         exprType = CLASS;
789         arrayDim = 0;
790         className =jvmJavaLangClass;
791     }
792
793     public void atArrayLength(Expr expr) throws CompileError {
794         expr.oprand1().accept(this);
795         exprType = INT;
796         arrayDim = 0;
797     }
798
799     public void atArrayRead(ASTree array, ASTree index)
800         throws CompileError
801     {
802         array.accept(this);
803         int type = exprType;
804         int dim = arrayDim;
805         String JavaDoc cname = className;
806         index.accept(this);
807         exprType = type;
808         arrayDim = dim - 1;
809         className = cname;
810     }
811
812     private void atPlusPlus(int token, ASTree oprand, Expr expr)
813         throws CompileError
814     {
815         boolean isPost = oprand == null; // ++i or i++?
816
if (isPost)
817             oprand = expr.oprand2();
818
819         if (oprand instanceof Variable) {
820             Declarator d = ((Variable)oprand).getDeclarator();
821             exprType = d.getType();
822             arrayDim = d.getArrayDim();
823         }
824         else {
825             if (oprand instanceof Expr) {
826                 Expr e = (Expr)oprand;
827                 if (e.getOperator() == ARRAY) {
828                     atArrayRead(e.oprand1(), e.oprand2());
829                     // arrayDim should be 0.
830
int t = exprType;
831                     if (t == INT || t == BYTE || t == CHAR || t == SHORT)
832                         exprType = INT;
833
834                     return;
835                 }
836             }
837
838             atFieldPlusPlus(oprand);
839         }
840     }
841
842     protected void atFieldPlusPlus(ASTree oprand) throws CompileError
843     {
844         CtField f = fieldAccess(oprand);
845         atFieldRead(f);
846         int t = exprType;
847         if (t == INT || t == BYTE || t == CHAR || t == SHORT)
848             exprType = INT;
849     }
850
851     public void atMember(Member mem) throws CompileError {
852         atFieldRead(mem);
853     }
854
855     public void atVariable(Variable v) throws CompileError {
856         Declarator d = v.getDeclarator();
857         exprType = d.getType();
858         arrayDim = d.getArrayDim();
859         className = d.getClassName();
860     }
861
862     public void atKeyword(Keyword k) throws CompileError {
863         arrayDim = 0;
864         int token = k.get();
865         switch (token) {
866         case TRUE :
867         case FALSE :
868             exprType = BOOLEAN;
869             break;
870         case NULL :
871             exprType = NULL;
872             break;
873         case THIS :
874         case SUPER :
875             exprType = CLASS;
876             if (token == THIS)
877                 className = getThisName();
878             else
879                 className = getSuperName();
880             break;
881         default :
882             fatal();
883         }
884     }
885
886     public void atStringL(StringL s) throws CompileError {
887         exprType = CLASS;
888         arrayDim = 0;
889         className = jvmJavaLangString;
890     }
891
892     public void atIntConst(IntConst i) throws CompileError {
893         arrayDim = 0;
894         int type = i.getType();
895         if (type == IntConstant || type == CharConstant)
896             exprType = (type == IntConstant ? INT : CHAR);
897         else
898             exprType = LONG;
899     }
900
901     public void atDoubleConst(DoubleConst d) throws CompileError {
902         arrayDim = 0;
903         if (d.getType() == DoubleConstant)
904             exprType = DOUBLE;
905         else
906             exprType = FLOAT;
907     }
908 }
909
Popular Tags