Source Code Cross Referenced for TypeChecker.java in  » Byte-Code » Javassist » javassist » compiler » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Byte Code » Javassist » javassist.compiler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Javassist, a Java-bytecode translator toolkit.
003:         * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004:         *
005:         * The contents of this file are subject to the Mozilla Public License Version
006:         * 1.1 (the "License"); you may not use this file except in compliance with
007:         * the License.  Alternatively, the contents of this file may be used under
008:         * the terms of the GNU Lesser General Public License Version 2.1 or later.
009:         *
010:         * Software distributed under the License is distributed on an "AS IS" basis,
011:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012:         * for the specific language governing rights and limitations under the
013:         * License.
014:         */
015:
016:        package javassist.compiler;
017:
018:        import javassist.CtClass;
019:        import javassist.CtField;
020:        import javassist.ClassPool;
021:        import javassist.Modifier;
022:        import javassist.NotFoundException;
023:        import javassist.compiler.ast.*;
024:        import javassist.bytecode.*;
025:
026:        public class TypeChecker extends Visitor implements  Opcode, TokenId {
027:            static final String javaLangObject = "java.lang.Object";
028:            static final String jvmJavaLangObject = "java/lang/Object";
029:            static final String jvmJavaLangString = "java/lang/String";
030:            static final String jvmJavaLangClass = "java/lang/Class";
031:
032:            /* The following fields are used by atXXX() methods
033:             * for returning the type of the compiled expression.
034:             */
035:            protected int exprType; // VOID, NULL, CLASS, BOOLEAN, INT, ...
036:            protected int arrayDim;
037:            protected String className; // JVM-internal representation
038:
039:            protected MemberResolver resolver;
040:            protected CtClass this Class;
041:            protected MethodInfo this Method;
042:
043:            public TypeChecker(CtClass cc, ClassPool cp) {
044:                resolver = new MemberResolver(cp);
045:                this Class = cc;
046:                this Method = null;
047:            }
048:
049:            /*
050:             * Converts an array of tuples of exprType, arrayDim, and className
051:             * into a String object.
052:             */
053:            protected static String argTypesToString(int[] types, int[] dims,
054:                    String[] cnames) {
055:                StringBuffer sbuf = new StringBuffer();
056:                sbuf.append('(');
057:                int n = types.length;
058:                if (n > 0) {
059:                    int i = 0;
060:                    while (true) {
061:                        typeToString(sbuf, types[i], dims[i], cnames[i]);
062:                        if (++i < n)
063:                            sbuf.append(',');
064:                        else
065:                            break;
066:                    }
067:                }
068:
069:                sbuf.append(')');
070:                return sbuf.toString();
071:            }
072:
073:            /*
074:             * Converts a tuple of exprType, arrayDim, and className
075:             * into a String object.
076:             */
077:            protected static StringBuffer typeToString(StringBuffer sbuf,
078:                    int type, int dim, String cname) {
079:                String s;
080:                if (type == CLASS)
081:                    s = MemberResolver.jvmToJavaName(cname);
082:                else if (type == NULL)
083:                    s = "Object";
084:                else
085:                    try {
086:                        s = MemberResolver.getTypeName(type);
087:                    } catch (CompileError e) {
088:                        s = "?";
089:                    }
090:
091:                sbuf.append(s);
092:                while (dim-- > 0)
093:                    sbuf.append("[]");
094:
095:                return sbuf;
096:            }
097:
098:            /**
099:             * Records the currently compiled method.
100:             */
101:            public void setThisMethod(MethodInfo m) {
102:                this Method = m;
103:            }
104:
105:            protected static void fatal() throws CompileError {
106:                throw new CompileError("fatal");
107:            }
108:
109:            /**
110:             * Returns the JVM-internal representation of this class name.
111:             */
112:            protected String getThisName() {
113:                return MemberResolver.javaToJvmName(this Class.getName());
114:            }
115:
116:            /**
117:             * Returns the JVM-internal representation of this super class name.
118:             */
119:            protected String getSuperName() throws CompileError {
120:                return MemberResolver.javaToJvmName(MemberResolver
121:                        .getSuperclass(this Class).getName());
122:            }
123:
124:            /* Converts a class name into a JVM-internal representation.
125:             *
126:             * It may also expand a simple class name to java.lang.*.
127:             * For example, this converts Object into java/lang/Object.
128:             */
129:            protected String resolveClassName(ASTList name) throws CompileError {
130:                return resolver.resolveClassName(name);
131:            }
132:
133:            /* Expands a simple class name to java.lang.*.
134:             * For example, this converts Object into java/lang/Object.
135:             */
136:            protected String resolveClassName(String jvmName)
137:                    throws CompileError {
138:                return resolver.resolveJvmClassName(jvmName);
139:            }
140:
141:            public void atNewExpr(NewExpr expr) throws CompileError {
142:                if (expr.isArray())
143:                    atNewArrayExpr(expr);
144:                else {
145:                    CtClass clazz = resolver.lookupClassByName(expr
146:                            .getClassName());
147:                    String cname = clazz.getName();
148:                    ASTList args = expr.getArguments();
149:                    atMethodCallCore(clazz, MethodInfo.nameInit, args);
150:                    exprType = CLASS;
151:                    arrayDim = 0;
152:                    className = MemberResolver.javaToJvmName(cname);
153:                }
154:            }
155:
156:            public void atNewArrayExpr(NewExpr expr) throws CompileError {
157:                int type = expr.getArrayType();
158:                ASTList size = expr.getArraySize();
159:                ASTList classname = expr.getClassName();
160:                ASTree init = expr.getInitializer();
161:                if (init != null)
162:                    init.accept(this );
163:
164:                if (size.length() > 1)
165:                    atMultiNewArray(type, classname, size);
166:                else {
167:                    ASTree sizeExpr = size.head();
168:                    if (sizeExpr != null)
169:                        sizeExpr.accept(this );
170:
171:                    exprType = type;
172:                    arrayDim = 1;
173:                    if (type == CLASS)
174:                        className = resolveClassName(classname);
175:                    else
176:                        className = null;
177:                }
178:            }
179:
180:            public void atArrayInit(ArrayInit init) throws CompileError {
181:                ASTList list = init;
182:                while (list != null) {
183:                    ASTree h = list.head();
184:                    list = list.tail();
185:                    if (h != null)
186:                        h.accept(this );
187:                }
188:            }
189:
190:            protected void atMultiNewArray(int type, ASTList classname,
191:                    ASTList size) throws CompileError {
192:                int count, dim;
193:                dim = size.length();
194:                for (count = 0; size != null; size = size.tail()) {
195:                    ASTree s = size.head();
196:                    if (s == null)
197:                        break; // int[][][] a = new int[3][4][];
198:
199:                    ++count;
200:                    s.accept(this );
201:                }
202:
203:                exprType = type;
204:                arrayDim = dim;
205:                if (type == CLASS)
206:                    className = resolveClassName(classname);
207:                else
208:                    className = null;
209:            }
210:
211:            public void atAssignExpr(AssignExpr expr) throws CompileError {
212:                // =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, >>>=
213:                int op = expr.getOperator();
214:                ASTree left = expr.oprand1();
215:                ASTree right = expr.oprand2();
216:                if (left instanceof  Variable)
217:                    atVariableAssign(expr, op, (Variable) left,
218:                            ((Variable) left).getDeclarator(), right);
219:                else {
220:                    if (left instanceof  Expr) {
221:                        Expr e = (Expr) left;
222:                        if (e.getOperator() == ARRAY) {
223:                            atArrayAssign(expr, op, (Expr) left, right);
224:                            return;
225:                        }
226:                    }
227:
228:                    atFieldAssign(expr, op, left, right);
229:                }
230:            }
231:
232:            /* op is either =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, or >>>=.
233:             *
234:             * expr and var can be null.
235:             */
236:            private void atVariableAssign(Expr expr, int op, Variable var,
237:                    Declarator d, ASTree right) throws CompileError {
238:                int varType = d.getType();
239:                int varArray = d.getArrayDim();
240:                String varClass = d.getClassName();
241:
242:                if (op != '=')
243:                    atVariable(var);
244:
245:                right.accept(this );
246:                exprType = varType;
247:                arrayDim = varArray;
248:                className = varClass;
249:            }
250:
251:            private void atArrayAssign(Expr expr, int op, Expr array,
252:                    ASTree right) throws CompileError {
253:                atArrayRead(array.oprand1(), array.oprand2());
254:                int aType = exprType;
255:                int aDim = arrayDim;
256:                String cname = className;
257:                right.accept(this );
258:                exprType = aType;
259:                arrayDim = aDim;
260:                className = cname;
261:            }
262:
263:            protected void atFieldAssign(Expr expr, int op, ASTree left,
264:                    ASTree right) throws CompileError {
265:                CtField f = fieldAccess(left);
266:                atFieldRead(f);
267:                int fType = exprType;
268:                int fDim = arrayDim;
269:                String cname = className;
270:                right.accept(this );
271:                exprType = fType;
272:                arrayDim = fDim;
273:                className = cname;
274:            }
275:
276:            public void atCondExpr(CondExpr expr) throws CompileError {
277:                booleanExpr(expr.condExpr());
278:                expr.thenExpr().accept(this );
279:                int type1 = exprType;
280:                int dim1 = arrayDim;
281:                String cname1 = className;
282:                expr.elseExpr().accept(this );
283:
284:                if (dim1 == 0 && dim1 == arrayDim)
285:                    if (CodeGen.rightIsStrong(type1, exprType))
286:                        expr
287:                                .setThen(new CastExpr(exprType, 0, expr
288:                                        .thenExpr()));
289:                    else if (CodeGen.rightIsStrong(exprType, type1)) {
290:                        expr.setElse(new CastExpr(type1, 0, expr.elseExpr()));
291:                        exprType = type1;
292:                    }
293:            }
294:
295:            /*
296:             * If atBinExpr() substitutes a new expression for the original
297:             * binary-operator expression, it changes the operator name to '+'
298:             * (if the original is not '+') and sets the new expression to the
299:             * left-hand-side expression and null to the right-hand-side expression. 
300:             */
301:            public void atBinExpr(BinExpr expr) throws CompileError {
302:                int token = expr.getOperator();
303:                int k = CodeGen.lookupBinOp(token);
304:                if (k >= 0) {
305:                    /* arithmetic operators: +, -, *, /, %, |, ^, &, <<, >>, >>>
306:                     */
307:                    if (token == '+') {
308:                        Expr e = atPlusExpr(expr);
309:                        if (e != null) {
310:                            /* String concatenation has been translated into
311:                             * an expression using StringBuffer.
312:                             */
313:                            e = CallExpr.makeCall(Expr.make('.', e, new Member(
314:                                    "toString")), null);
315:                            expr.setOprand1(e);
316:                            expr.setOprand2(null); // <---- look at this!
317:                            className = jvmJavaLangString;
318:                        }
319:                    } else {
320:                        ASTree left = expr.oprand1();
321:                        ASTree right = expr.oprand2();
322:                        left.accept(this );
323:                        int type1 = exprType;
324:                        right.accept(this );
325:                        if (!isConstant(expr, token, left, right))
326:                            computeBinExprType(expr, token, type1);
327:                    }
328:                } else {
329:                    /* equation: &&, ||, ==, !=, <=, >=, <, >
330:                     */
331:                    booleanExpr(expr);
332:                }
333:            }
334:
335:            /* EXPR must be a + expression.
336:             * atPlusExpr() returns non-null if the given expression is string
337:             * concatenation.  The returned value is "new StringBuffer().append..".
338:             */
339:            private Expr atPlusExpr(BinExpr expr) throws CompileError {
340:                ASTree left = expr.oprand1();
341:                ASTree right = expr.oprand2();
342:                if (right == null) {
343:                    // this expression has been already type-checked.
344:                    // see atBinExpr() above.
345:                    left.accept(this );
346:                    return null;
347:                }
348:
349:                if (isPlusExpr(left)) {
350:                    Expr newExpr = atPlusExpr((BinExpr) left);
351:                    if (newExpr != null) {
352:                        right.accept(this );
353:                        exprType = CLASS;
354:                        arrayDim = 0;
355:                        className = "java/lang/StringBuffer";
356:                        return makeAppendCall(newExpr, right);
357:                    }
358:                } else
359:                    left.accept(this );
360:
361:                int type1 = exprType;
362:                int dim1 = arrayDim;
363:                String cname = className;
364:                right.accept(this );
365:
366:                if (isConstant(expr, '+', left, right))
367:                    return null;
368:
369:                if ((type1 == CLASS && dim1 == 0 && jvmJavaLangString
370:                        .equals(cname))
371:                        || (exprType == CLASS && arrayDim == 0 && jvmJavaLangString
372:                                .equals(className))) {
373:                    ASTList sbufClass = ASTList.make(new Symbol("java"),
374:                            new Symbol("lang"), new Symbol("StringBuffer"));
375:                    ASTree e = new NewExpr(sbufClass, null);
376:                    exprType = CLASS;
377:                    arrayDim = 0;
378:                    className = "java/lang/StringBuffer";
379:                    return makeAppendCall(makeAppendCall(e, left), right);
380:                } else {
381:                    computeBinExprType(expr, '+', type1);
382:                    return null;
383:                }
384:            }
385:
386:            private boolean isConstant(BinExpr expr, int op, ASTree left,
387:                    ASTree right) throws CompileError {
388:                left = stripPlusExpr(left);
389:                right = stripPlusExpr(right);
390:                ASTree newExpr = null;
391:                if (left instanceof  StringL && right instanceof  StringL
392:                        && op == '+')
393:                    newExpr = new StringL(((StringL) left).get()
394:                            + ((StringL) right).get());
395:                else if (left instanceof  IntConst)
396:                    newExpr = ((IntConst) left).compute(op, right);
397:                else if (left instanceof  DoubleConst)
398:                    newExpr = ((DoubleConst) left).compute(op, right);
399:
400:                if (newExpr == null)
401:                    return false; // not a constant expression
402:                else {
403:                    expr.setOperator('+');
404:                    expr.setOprand1(newExpr);
405:                    expr.setOprand2(null);
406:                    newExpr.accept(this ); // for setting exprType, arrayDim, ...
407:                    return true;
408:                }
409:            }
410:
411:            /* CodeGen.atSwitchStmnt() also calls stripPlusExpr().
412:             */
413:            static ASTree stripPlusExpr(ASTree expr) {
414:                if (expr instanceof  BinExpr) {
415:                    BinExpr e = (BinExpr) expr;
416:                    if (e.getOperator() == '+' && e.oprand2() == null)
417:                        return e.getLeft();
418:                } else if (expr instanceof  Expr) { // note: BinExpr extends Expr.
419:                    Expr e = (Expr) expr;
420:                    int op = e.getOperator();
421:                    if (op == MEMBER) {
422:                        ASTree cexpr = getConstantFieldValue((Member) e
423:                                .oprand2());
424:                        if (cexpr != null)
425:                            return cexpr;
426:                    } else if (op == '+' && e.getRight() == null)
427:                        return e.getLeft();
428:                } else if (expr instanceof  Member) {
429:                    ASTree cexpr = getConstantFieldValue((Member) expr);
430:                    if (cexpr != null)
431:                        return cexpr;
432:                }
433:
434:                return expr;
435:            }
436:
437:            /**
438:             * If MEM is a static final field, this method returns a constant
439:             * expression representing the value of that field.
440:             */
441:            private static ASTree getConstantFieldValue(Member mem) {
442:                return getConstantFieldValue(mem.getField());
443:            }
444:
445:            public static ASTree getConstantFieldValue(CtField f) {
446:                if (f == null)
447:                    return null;
448:
449:                Object value = f.getConstantValue();
450:                if (value == null)
451:                    return null;
452:
453:                if (value instanceof  String)
454:                    return new StringL((String) value);
455:                else if (value instanceof  Double || value instanceof  Float) {
456:                    int token = (value instanceof  Double) ? DoubleConstant
457:                            : FloatConstant;
458:                    return new DoubleConst(((Number) value).doubleValue(),
459:                            token);
460:                } else if (value instanceof  Number) {
461:                    int token = (value instanceof  Long) ? LongConstant
462:                            : IntConstant;
463:                    return new IntConst(((Number) value).longValue(), token);
464:                } else if (value instanceof  Boolean)
465:                    return new Keyword(
466:                            ((Boolean) value).booleanValue() ? TokenId.TRUE
467:                                    : TokenId.FALSE);
468:                else
469:                    return null;
470:            }
471:
472:            private static boolean isPlusExpr(ASTree expr) {
473:                if (expr instanceof  BinExpr) {
474:                    BinExpr bexpr = (BinExpr) expr;
475:                    int token = bexpr.getOperator();
476:                    return token == '+';
477:                }
478:
479:                return false;
480:            }
481:
482:            private static Expr makeAppendCall(ASTree target, ASTree arg) {
483:                return CallExpr.makeCall(Expr.make('.', target, new Member(
484:                        "append")), new ASTList(arg));
485:            }
486:
487:            private void computeBinExprType(BinExpr expr, int token, int type1)
488:                    throws CompileError {
489:                // arrayDim should be 0.
490:                int type2 = exprType;
491:                if (token == LSHIFT || token == RSHIFT || token == ARSHIFT)
492:                    exprType = type1;
493:                else
494:                    insertCast(expr, type1, type2);
495:
496:                if (CodeGen.isP_INT(exprType))
497:                    exprType = INT; // type1 may be BYTE, ...
498:            }
499:
500:            private void booleanExpr(ASTree expr) throws CompileError {
501:                int op = CodeGen.getCompOperator(expr);
502:                if (op == EQ) { // ==, !=, ...
503:                    BinExpr bexpr = (BinExpr) expr;
504:                    bexpr.oprand1().accept(this );
505:                    int type1 = exprType;
506:                    int dim1 = arrayDim;
507:                    bexpr.oprand2().accept(this );
508:                    if (dim1 == 0 && arrayDim == 0)
509:                        insertCast(bexpr, type1, exprType);
510:                } else if (op == '!')
511:                    ((Expr) expr).oprand1().accept(this );
512:                else if (op == ANDAND || op == OROR) {
513:                    BinExpr bexpr = (BinExpr) expr;
514:                    bexpr.oprand1().accept(this );
515:                    bexpr.oprand2().accept(this );
516:                } else
517:                    // others
518:                    expr.accept(this );
519:
520:                exprType = BOOLEAN;
521:                arrayDim = 0;
522:            }
523:
524:            private void insertCast(BinExpr expr, int type1, int type2)
525:                    throws CompileError {
526:                if (CodeGen.rightIsStrong(type1, type2))
527:                    expr.setLeft(new CastExpr(type2, 0, expr.oprand1()));
528:                else
529:                    exprType = type1;
530:            }
531:
532:            public void atCastExpr(CastExpr expr) throws CompileError {
533:                String cname = resolveClassName(expr.getClassName());
534:                expr.getOprand().accept(this );
535:                exprType = expr.getType();
536:                arrayDim = expr.getArrayDim();
537:                className = cname;
538:            }
539:
540:            public void atInstanceOfExpr(InstanceOfExpr expr)
541:                    throws CompileError {
542:                expr.getOprand().accept(this );
543:                exprType = BOOLEAN;
544:                arrayDim = 0;
545:            }
546:
547:            public void atExpr(Expr expr) throws CompileError {
548:                // array access, member access,
549:                // (unary) +, (unary) -, ++, --, !, ~
550:
551:                int token = expr.getOperator();
552:                ASTree oprand = expr.oprand1();
553:                if (token == '.') {
554:                    String member = ((Symbol) expr.oprand2()).get();
555:                    if (member.equals("length"))
556:                        atArrayLength(expr);
557:                    else if (member.equals("class"))
558:                        atClassObject(expr); // .class
559:                    else
560:                        atFieldRead(expr);
561:                } else if (token == MEMBER) { // field read
562:                    String member = ((Symbol) expr.oprand2()).get();
563:                    if (member.equals("class"))
564:                        atClassObject(expr); // .class
565:                    else
566:                        atFieldRead(expr);
567:                } else if (token == ARRAY)
568:                    atArrayRead(oprand, expr.oprand2());
569:                else if (token == PLUSPLUS || token == MINUSMINUS)
570:                    atPlusPlus(token, oprand, expr);
571:                else if (token == '!')
572:                    booleanExpr(expr);
573:                else if (token == CALL) // method call
574:                    fatal();
575:                else {
576:                    oprand.accept(this );
577:                    if (!isConstant(expr, token, oprand))
578:                        if (token == '-' || token == '~')
579:                            if (CodeGen.isP_INT(exprType))
580:                                exprType = INT; // type may be BYTE, ...
581:                }
582:            }
583:
584:            private boolean isConstant(Expr expr, int op, ASTree oprand) {
585:                oprand = stripPlusExpr(oprand);
586:                if (oprand instanceof  IntConst) {
587:                    IntConst c = (IntConst) oprand;
588:                    long v = c.get();
589:                    if (op == '-')
590:                        v = -v;
591:                    else if (op == '~')
592:                        v = ~v;
593:                    else
594:                        return false;
595:
596:                    c.set(v);
597:                } else if (oprand instanceof  DoubleConst) {
598:                    DoubleConst c = (DoubleConst) oprand;
599:                    if (op == '-')
600:                        c.set(-c.get());
601:                    else
602:                        return false;
603:                } else
604:                    return false;
605:
606:                expr.setOperator('+');
607:                return true;
608:            }
609:
610:            public void atCallExpr(CallExpr expr) throws CompileError {
611:                String mname = null;
612:                CtClass targetClass = null;
613:                ASTree method = expr.oprand1();
614:                ASTList args = (ASTList) expr.oprand2();
615:
616:                if (method instanceof  Member) {
617:                    mname = ((Member) method).get();
618:                    targetClass = this Class;
619:                } else if (method instanceof  Keyword) { // constructor
620:                    mname = MethodInfo.nameInit; // <init>
621:                    if (((Keyword) method).get() == SUPER)
622:                        targetClass = MemberResolver.getSuperclass(this Class);
623:                    else
624:                        targetClass = this Class;
625:                } else if (method instanceof  Expr) {
626:                    Expr e = (Expr) method;
627:                    mname = ((Symbol) e.oprand2()).get();
628:                    int op = e.getOperator();
629:                    if (op == MEMBER) // static method
630:                        targetClass = resolver.lookupClass(((Symbol) e
631:                                .oprand1()).get(), false);
632:                    else if (op == '.') {
633:                        ASTree target = e.oprand1();
634:                        try {
635:                            target.accept(this );
636:                        } catch (NoFieldException nfe) {
637:                            if (nfe.getExpr() != target)
638:                                throw nfe;
639:
640:                            // it should be a static method.
641:                            exprType = CLASS;
642:                            arrayDim = 0;
643:                            className = nfe.getField(); // JVM-internal
644:                            e.setOperator(MEMBER);
645:                            e.setOprand1(new Symbol(MemberResolver
646:                                    .jvmToJavaName(className)));
647:                        }
648:
649:                        if (arrayDim > 0)
650:                            targetClass = resolver.lookupClass(javaLangObject,
651:                                    true);
652:                        else if (exprType == CLASS /* && arrayDim == 0 */)
653:                            targetClass = resolver
654:                                    .lookupClassByJvmName(className);
655:                        else
656:                            badMethod();
657:                    } else
658:                        badMethod();
659:                } else
660:                    fatal();
661:
662:                MemberResolver.Method minfo = atMethodCallCore(targetClass,
663:                        mname, args);
664:                expr.setMethod(minfo);
665:            }
666:
667:            private static void badMethod() throws CompileError {
668:                throw new CompileError("bad method");
669:            }
670:
671:            /**
672:             * @return  a pair of the class declaring the invoked method
673:             *          and the MethodInfo of that method.  Never null.
674:             */
675:            public MemberResolver.Method atMethodCallCore(CtClass targetClass,
676:                    String mname, ASTList args) throws CompileError {
677:                int nargs = getMethodArgsLength(args);
678:                int[] types = new int[nargs];
679:                int[] dims = new int[nargs];
680:                String[] cnames = new String[nargs];
681:                atMethodArgs(args, types, dims, cnames);
682:
683:                MemberResolver.Method found = resolver.lookupMethod(
684:                        targetClass, this Class, this Method, mname, types, dims,
685:                        cnames);
686:                if (found == null) {
687:                    String clazz = targetClass.getName();
688:                    String signature = argTypesToString(types, dims, cnames);
689:                    String msg;
690:                    if (mname.equals(MethodInfo.nameInit))
691:                        msg = "cannot find constructor " + clazz + signature;
692:                    else
693:                        msg = mname + signature + " not found in " + clazz;
694:
695:                    throw new CompileError(msg);
696:                }
697:
698:                String desc = found.info.getDescriptor();
699:                setReturnType(desc);
700:                return found;
701:            }
702:
703:            public int getMethodArgsLength(ASTList args) {
704:                return ASTList.length(args);
705:            }
706:
707:            public void atMethodArgs(ASTList args, int[] types, int[] dims,
708:                    String[] cnames) throws CompileError {
709:                int i = 0;
710:                while (args != null) {
711:                    ASTree a = args.head();
712:                    a.accept(this );
713:                    types[i] = exprType;
714:                    dims[i] = arrayDim;
715:                    cnames[i] = className;
716:                    ++i;
717:                    args = args.tail();
718:                }
719:            }
720:
721:            void setReturnType(String desc) throws CompileError {
722:                int i = desc.indexOf(')');
723:                if (i < 0)
724:                    badMethod();
725:
726:                char c = desc.charAt(++i);
727:                int dim = 0;
728:                while (c == '[') {
729:                    ++dim;
730:                    c = desc.charAt(++i);
731:                }
732:
733:                arrayDim = dim;
734:                if (c == 'L') {
735:                    int j = desc.indexOf(';', i + 1);
736:                    if (j < 0)
737:                        badMethod();
738:
739:                    exprType = CLASS;
740:                    className = desc.substring(i + 1, j);
741:                } else {
742:                    exprType = MemberResolver.descToType(c);
743:                    className = null;
744:                }
745:            }
746:
747:            private void atFieldRead(ASTree expr) throws CompileError {
748:                atFieldRead(fieldAccess(expr));
749:            }
750:
751:            private void atFieldRead(CtField f) throws CompileError {
752:                FieldInfo finfo = f.getFieldInfo2();
753:                String type = finfo.getDescriptor();
754:
755:                int i = 0;
756:                int dim = 0;
757:                char c = type.charAt(i);
758:                while (c == '[') {
759:                    ++dim;
760:                    c = type.charAt(++i);
761:                }
762:
763:                arrayDim = dim;
764:                exprType = MemberResolver.descToType(c);
765:
766:                if (c == 'L')
767:                    className = type.substring(i + 1, type.indexOf(';', i + 1));
768:                else
769:                    className = null;
770:            }
771:
772:            /* if EXPR is to access a static field, fieldAccess() translates EXPR
773:             * into an expression using '#' (MEMBER).  For example, it translates
774:             * java.lang.Integer.TYPE into java.lang.Integer#TYPE.  This translation
775:             * speeds up type resolution by MemberCodeGen.
776:             */
777:            protected CtField fieldAccess(ASTree expr) throws CompileError {
778:                if (expr instanceof  Member) {
779:                    Member mem = (Member) expr;
780:                    String name = mem.get();
781:                    try {
782:                        CtField f = this Class.getField(name);
783:                        if (Modifier.isStatic(f.getModifiers()))
784:                            mem.setField(f);
785:
786:                        return f;
787:                    } catch (NotFoundException e) {
788:                        // EXPR might be part of a static member access?
789:                        throw new NoFieldException(name, expr);
790:                    }
791:                } else if (expr instanceof  Expr) {
792:                    Expr e = (Expr) expr;
793:                    int op = e.getOperator();
794:                    if (op == MEMBER) {
795:                        Member mem = (Member) e.oprand2();
796:                        CtField f = resolver.lookupField(((Symbol) e.oprand1())
797:                                .get(), mem);
798:                        mem.setField(f);
799:                        return f;
800:                    } else if (op == '.')
801:                        try {
802:                            e.oprand1().accept(this );
803:                            if (exprType == CLASS && arrayDim == 0)
804:                                return resolver.lookupFieldByJvmName(className,
805:                                        (Symbol) e.oprand2());
806:                        } catch (NoFieldException nfe) {
807:                            if (nfe.getExpr() != e.oprand1())
808:                                throw nfe;
809:
810:                            /* EXPR should be a static field.
811:                             * If EXPR might be part of a qualified class name,
812:                             * lookupFieldByJvmName2() throws NoFieldException.
813:                             */
814:                            Member fname = (Member) e.oprand2();
815:                            String jvmClassName = nfe.getField();
816:                            CtField f = resolver.lookupFieldByJvmName2(
817:                                    jvmClassName, fname, expr);
818:                            e.setOperator(MEMBER);
819:                            e.setOprand1(new Symbol(MemberResolver
820:                                    .jvmToJavaName(jvmClassName)));
821:                            fname.setField(f);
822:                            return f;
823:                        }
824:                }
825:
826:                throw new CompileError("bad filed access");
827:            }
828:
829:            public void atClassObject(Expr expr) throws CompileError {
830:                exprType = CLASS;
831:                arrayDim = 0;
832:                className = jvmJavaLangClass;
833:            }
834:
835:            public void atArrayLength(Expr expr) throws CompileError {
836:                expr.oprand1().accept(this );
837:                exprType = INT;
838:                arrayDim = 0;
839:            }
840:
841:            public void atArrayRead(ASTree array, ASTree index)
842:                    throws CompileError {
843:                array.accept(this );
844:                int type = exprType;
845:                int dim = arrayDim;
846:                String cname = className;
847:                index.accept(this );
848:                exprType = type;
849:                arrayDim = dim - 1;
850:                className = cname;
851:            }
852:
853:            private void atPlusPlus(int token, ASTree oprand, Expr expr)
854:                    throws CompileError {
855:                boolean isPost = oprand == null; // ++i or i++?
856:                if (isPost)
857:                    oprand = expr.oprand2();
858:
859:                if (oprand instanceof  Variable) {
860:                    Declarator d = ((Variable) oprand).getDeclarator();
861:                    exprType = d.getType();
862:                    arrayDim = d.getArrayDim();
863:                } else {
864:                    if (oprand instanceof  Expr) {
865:                        Expr e = (Expr) oprand;
866:                        if (e.getOperator() == ARRAY) {
867:                            atArrayRead(e.oprand1(), e.oprand2());
868:                            // arrayDim should be 0.
869:                            int t = exprType;
870:                            if (t == INT || t == BYTE || t == CHAR
871:                                    || t == SHORT)
872:                                exprType = INT;
873:
874:                            return;
875:                        }
876:                    }
877:
878:                    atFieldPlusPlus(oprand);
879:                }
880:            }
881:
882:            protected void atFieldPlusPlus(ASTree oprand) throws CompileError {
883:                CtField f = fieldAccess(oprand);
884:                atFieldRead(f);
885:                int t = exprType;
886:                if (t == INT || t == BYTE || t == CHAR || t == SHORT)
887:                    exprType = INT;
888:            }
889:
890:            public void atMember(Member mem) throws CompileError {
891:                atFieldRead(mem);
892:            }
893:
894:            public void atVariable(Variable v) throws CompileError {
895:                Declarator d = v.getDeclarator();
896:                exprType = d.getType();
897:                arrayDim = d.getArrayDim();
898:                className = d.getClassName();
899:            }
900:
901:            public void atKeyword(Keyword k) throws CompileError {
902:                arrayDim = 0;
903:                int token = k.get();
904:                switch (token) {
905:                case TRUE:
906:                case FALSE:
907:                    exprType = BOOLEAN;
908:                    break;
909:                case NULL:
910:                    exprType = NULL;
911:                    break;
912:                case THIS:
913:                case SUPER:
914:                    exprType = CLASS;
915:                    if (token == THIS)
916:                        className = getThisName();
917:                    else
918:                        className = getSuperName();
919:                    break;
920:                default:
921:                    fatal();
922:                }
923:            }
924:
925:            public void atStringL(StringL s) throws CompileError {
926:                exprType = CLASS;
927:                arrayDim = 0;
928:                className = jvmJavaLangString;
929:            }
930:
931:            public void atIntConst(IntConst i) throws CompileError {
932:                arrayDim = 0;
933:                int type = i.getType();
934:                if (type == IntConstant || type == CharConstant)
935:                    exprType = (type == IntConstant ? INT : CHAR);
936:                else
937:                    exprType = LONG;
938:            }
939:
940:            public void atDoubleConst(DoubleConst d) throws CompileError {
941:                arrayDim = 0;
942:                if (d.getType() == DoubleConstant)
943:                    exprType = DOUBLE;
944:                else
945:                    exprType = FLOAT;
946:            }
947:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.