Source Code Cross Referenced for ByteCodeQVisitor.java in  » Testing » PolePosition-0.20 » com » versant » core » jdo » query » mem » 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 » Testing » PolePosition 0.20 » com.versant.core.jdo.query.mem 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998 - 2005 Versant Corporation
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         * Versant Corporation - initial API and implementation
0010:         */
0011:        package com.versant.core.jdo.query.mem;
0012:
0013:        import com.versant.core.jdo.query.*;
0014:        import com.versant.core.jdo.query.MemVisitor;
0015:        import com.versant.core.common.NotImplementedException;
0016:        import com.versant.core.common.OID;
0017:        import com.versant.core.metadata.FieldMetaData;
0018:        import com.versant.core.metadata.ClassMetaData;
0019:        import com.versant.core.metadata.MDStatics;
0020:        import com.versant.core.metadata.MDStaticUtils;
0021:
0022:        import java.util.*;
0023:        import java.math.BigInteger;
0024:        import java.math.BigDecimal;
0025:        import java.lang.Integer;
0026:
0027:        import com.versant.lib.bcel.generic.*;
0028:        import com.versant.lib.bcel.Constants;
0029:
0030:        import com.versant.core.common.BindingSupportImpl;
0031:        import com.versant.core.jdo.QueryStateWrapper;
0032:
0033:        /**
0034:         * Walks Node tree generating bytecode for the filter.
0035:         */
0036:        public class ByteCodeQVisitor implements  MemVisitor {
0037:
0038:            private ClassMetaData candidateClass;
0039:            private ClassGen cg;
0040:            private ConstantPoolGen cp;
0041:            private InstructionList il;
0042:            private MethodGen mg;
0043:            private InstructionFactory factory;
0044:            private Map paramMap;
0045:
0046:            private int valueLVCount;
0047:
0048:            private final Map varToIndexMap = new HashMap();
0049:
0050:            private boolean first = true;
0051:
0052:            private static final int COMP_EQ = 1;
0053:            private static final int COMP_GE = 2;
0054:            private static final int COMP_LT = 3;
0055:            private static final int COMP_GT = 4;
0056:            private static final int COMP_LE = 5;
0057:            private static final int COMP_NE = 6;
0058:
0059:            private CompiledMemQuery compiledMemQuery;
0060:            private static final String NAME_Q_STATE_WRAPPER = QueryStateWrapper.class
0061:                    .getName();
0062:            private static final String M_NAME_GETSTATE = "getState";
0063:            private static final String NAME_COLLECTION = Collection.class
0064:                    .getName();
0065:            private static final String NAME_ITERATOR = Iterator.class
0066:                    .getName();
0067:
0068:            private static final String NAME_COMPARABLE = Comparable.class
0069:                    .getName();
0070:            private static final String NAME_OBJECT = Object.class.getName();
0071:            private static final String NAME_NUMBER = Number.class.getName();
0072:
0073:            private static final ObjectType OBJECT_TYPE_COLLECTION = new ObjectType(
0074:                    NAME_COLLECTION);
0075:            private static final ObjectType OBJECT_TYPE_ITERATOR = new ObjectType(
0076:                    NAME_ITERATOR);
0077:            private static final ObjectType OBJECT_TYPE_NUMBER = new ObjectType(
0078:                    NAME_NUMBER);
0079:            private static final Type[] ARG_TYPES_INT = new Type[] { Type.INT };
0080:            private static final Type[] ARG_TYPES_OBJECT = new Type[] { Type.OBJECT };
0081:            private static final Type[] ARG_TYPES_STRING = new Type[] { Type.STRING };
0082:            private static final String NAME_STRING = String.class.getName();
0083:            private static final ObjectType OBJECT_TYPE_STRING = new ObjectType(
0084:                    NAME_STRING);
0085:            private static final ObjectType OBJECT_TYPE_OID = new ObjectType(
0086:                    OID.class.getName());
0087:            private static final String NAME_STRING_BUFFER = StringBuffer.class
0088:                    .getName();
0089:            private static final ObjectType OBJECT_TYPE_STRING_BUFFER = new ObjectType(
0090:                    NAME_STRING_BUFFER);
0091:            private static final String NAME_BIG_INT = BigInteger.class
0092:                    .getName();
0093:
0094:            private static final ObjectType RET_TYPE_BIG_INT = new ObjectType(
0095:                    NAME_BIG_INT);
0096:            private static final Type[] ARG_TYPES_BIG_INT = new Type[] { RET_TYPE_BIG_INT };
0097:            private static final String NAME_BIG_DEC = BigDecimal.class
0098:                    .getName();
0099:            private static final ObjectType RET_TYPE_BIG_DEC = new ObjectType(
0100:                    NAME_BIG_DEC);
0101:            private static final Type[] ARG_TYPES_BIG_DEC = new Type[] { RET_TYPE_BIG_DEC };
0102:
0103:            public ByteCodeQVisitor(ClassGen classGen,
0104:                    InstructionFactory instructionFactory, String name,
0105:                    ClassMetaData candidateClass,
0106:                    CompiledMemQuery compiledMemQuery) {
0107:                this .compiledMemQuery = compiledMemQuery;
0108:                this .candidateClass = candidateClass;
0109:
0110:                cg = classGen;
0111:                factory = instructionFactory;
0112:                cp = cg.getConstantPool();
0113:                this .il = new InstructionList();
0114:                mg = new MethodGen(Constants.ACC_PUBLIC, // access flags
0115:                        Type.BOOLEAN, // return type
0116:                        new Type[] { new ObjectType(NAME_Q_STATE_WRAPPER),
0117:                                new ArrayType(Type.OBJECT, 1) }, new String[] {
0118:                                "state", "params" }, // arg names
0119:                        "exec", name, // method, class
0120:                        il, cp);
0121:            }
0122:
0123:            public void setParamMap(Map paramMap) {
0124:                this .paramMap = paramMap;
0125:            }
0126:
0127:            public void finish() {
0128:                il.append(InstructionConstants.IRETURN);
0129:                mg.removeNOPs();
0130:                mg.setMaxLocals();
0131:                mg.setMaxStack();
0132:                cg.addMethod(mg.getMethod());
0133:                il.dispose();
0134:            }
0135:
0136:            public Field visitNode(Node node, Object obj) {
0137:                throw new NotImplementedException();
0138:            }
0139:
0140:            /**
0141:             * Find the variable with name or null if none.
0142:             */
0143:            private VarNode findVar(String name) {
0144:                VarNode[] vars = compiledMemQuery.vars;
0145:                if (vars == null)
0146:                    return null;
0147:                for (int i = vars.length - 1; i >= 0; i--) {
0148:                    VarNode v = vars[i];
0149:                    if (v.getIdentifier().equals(name))
0150:                        return v;
0151:                }
0152:                return null;
0153:            }
0154:
0155:            /**
0156:             * Must refactor
0157:             * @param node
0158:             * @param obj
0159:             * @return
0160:             */
0161:            public Field visitLiteralNode(LiteralNode node, Object obj) {
0162:                BCField f = new BCField();
0163:                switch (node.type) {
0164:                case LiteralNode.TYPE_STRING:
0165:                    f.bcType = MDStatics.STRING;
0166:                    f.classType = String.class;
0167:                    f.ih = il.append(new PUSH(cp, node.value));
0168:                    break;
0169:                case LiteralNode.TYPE_BOOLEAN:
0170:                    f.bcType = MDStatics.BOOLEAN;
0171:                    f.classType = Boolean.TYPE;
0172:                    f.ih = il.append(new PUSH(cp, Boolean.valueOf(node.value)));
0173:                    break;
0174:                case LiteralNode.TYPE_CHAR:
0175:                    f.bcType = MDStatics.CHAR;
0176:                    f.classType = Character.TYPE;
0177:                    f.ih = il.append(new PUSH(cp, node.value.toCharArray()[0]));
0178:                    break;
0179:                case LiteralNode.TYPE_LONG:
0180:                    f.bcType = MDStatics.LONG;
0181:                    f.classType = Long.TYPE;
0182:                    f.ih = il.append(new PUSH(cp, Long.parseLong(node.value)));
0183:                    break;
0184:                case LiteralNode.TYPE_DOUBLE:
0185:                    f.bcType = MDStatics.DOUBLE;
0186:                    f.classType = Double.TYPE;
0187:                    f.ih = il.append(new PUSH(cp, Double
0188:                            .parseDouble(node.value)));
0189:                    break;
0190:                case LiteralNode.TYPE_NULL:
0191:                case LiteralNode.TYPE_OTHER:
0192:                    f.bcType = MDStatics.NULL;
0193:                    f.classType = Object.class;
0194:                    //                f.ih = il.append(InstructionConstants.ACONST_NULL);
0195:                    //                /**
0196:                    //                 * This will probally be nulls
0197:                    //                 */
0198:                    //                throw new NotImplementedException();
0199:                    break;
0200:                default:
0201:                    throw BindingSupportImpl.getInstance().runtime(
0202:                            "Unkown literal type  " + node.type);
0203:                }
0204:                return f;
0205:            }
0206:
0207:            /**
0208:             * This may be an state field on a state eg person.person
0209:             * @param node
0210:             * @param obj
0211:             * @return
0212:             */
0213:            public Field visitFieldNavNode(FieldNavNode node, Object obj) {
0214:                return visitStateFieldNavNodeRoot(node, candidateClass);
0215:            }
0216:
0217:            private Field visitStateFieldNavNodeRoot(FieldNavNode node,
0218:                    ClassMetaData currentClass) {
0219:                Field result = null;
0220:                FieldMetaData f = null;
0221:
0222:                VarNode varNode = findVar(node.lexeme);
0223:                if (varNode != null) {
0224:                    first = false;
0225:                    Object o = varToIndexMap.get(varNode.getIdentifier());
0226:                    il.append(new ALOAD(((Integer) o).intValue()));
0227:                    if (node.childList instanceof  FieldNavNode) {
0228:                        result = visitStateFieldNavNode(
0229:                                (FieldNavNode) node.childList,
0230:                                varNode.getCmd(), null);
0231:                    } else {
0232:                        result = visitFieldNode((FieldNode) node.childList,
0233:                                varNode.getCmd());
0234:                    }
0235:                } else {
0236:                    f = currentClass.getFieldMetaData(node.lexeme);
0237:                    if (f == null) {
0238:                        throw BindingSupportImpl.getInstance().runtime(
0239:                                "Class " + currentClass
0240:                                        + " does not have a field "
0241:                                        + node.lexeme);
0242:                    }
0243:                    switch (f.category) {
0244:                    case FieldMetaData.CATEGORY_SIMPLE:
0245:                        break;
0246:                    case FieldMetaData.CATEGORY_REF:
0247:                        InstructionHandle ih = null;
0248:                        il.append(new ALOAD(1));//load the state
0249:                        il.append(new PUSH(cp, f.stateFieldNo));
0250:                        il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER,
0251:                                M_NAME_GETSTATE, new ObjectType(
0252:                                        NAME_Q_STATE_WRAPPER), ARG_TYPES_INT,
0253:                                Constants.INVOKEVIRTUAL));
0254:                        first = false;
0255:                        if (node.childList instanceof  FieldNavNode) {
0256:                            result = visitStateFieldNavNode(
0257:                                    (FieldNavNode) node.childList,
0258:                                    f.typeMetaData, ih);
0259:                        } else {
0260:                            result = visitFieldNode((FieldNode) node.childList,
0261:                                    f.typeMetaData);
0262:                        }
0263:                    case FieldMetaData.CATEGORY_MAP:
0264:                        break;
0265:                    case FieldMetaData.CATEGORY_COLLECTION:
0266:                        break;
0267:                    case FieldMetaData.CATEGORY_TRANSACTIONAL:
0268:                        break;
0269:                    case FieldMetaData.CATEGORY_ARRAY:
0270:                        break;
0271:                    }
0272:                }
0273:                return result;
0274:            }
0275:
0276:            private Field visitStateFieldNavNode(FieldNavNode node,
0277:                    ClassMetaData currentClass, InstructionHandle ih) {
0278:                Field result = null;
0279:                FieldMetaData f = currentClass.getFieldMetaData(node.lexeme);
0280:                if (f == null) {
0281:                    throw BindingSupportImpl.getInstance().runtime(
0282:                            "Class " + currentClass + " does not have a field "
0283:                                    + node.lexeme);
0284:                }
0285:                switch (f.category) {
0286:                case FieldMetaData.CATEGORY_SIMPLE:
0287:                    break;
0288:                case FieldMetaData.CATEGORY_REF:
0289:                    il.append(new PUSH(cp, f.stateFieldNo));
0290:                    il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER,
0291:                            M_NAME_GETSTATE, new ObjectType(
0292:                                    NAME_Q_STATE_WRAPPER), ARG_TYPES_INT,
0293:                            Constants.INVOKEVIRTUAL));
0294:                    if (node.childList instanceof  FieldNavNode) {
0295:                        result = visitStateFieldNavNode(
0296:                                (FieldNavNode) node.childList, f.typeMetaData,
0297:                                ih);
0298:                    } else {
0299:                        result = visitFieldNode((FieldNode) node.childList,
0300:                                f.typeMetaData);
0301:                    }
0302:                case FieldMetaData.CATEGORY_MAP:
0303:                    break;
0304:                case FieldMetaData.CATEGORY_COLLECTION:
0305:                    break;
0306:                case FieldMetaData.CATEGORY_TRANSACTIONAL:
0307:                    break;
0308:                case FieldMetaData.CATEGORY_ARRAY:
0309:                    break;
0310:                }
0311:                return result;
0312:            }
0313:
0314:            /**
0315:             * This is used from a methodNode to deduce the name of a var node.
0316:             * @param mNode
0317:             * @return
0318:             */
0319:            private String getLVName(MethodNode mNode) {
0320:                return ((VarNode) mNode.childList.next).getIdentifier();
0321:            }
0322:
0323:            public Field visitMethodNode(MethodNode node, Object obj) {
0324:                Field result = null;
0325:                switch (node.getMethod()) {
0326:                case MethodNode.CONTAINS:
0327:                    if (node.childList.next instanceof  VarNode) {
0328:                        doContainsMethod(node);
0329:                    } else {
0330:                        doContainMethodParam(node);
0331:                    }
0332:                    break;
0333:                case MethodNode.ENDS_WITH:
0334:                case MethodNode.STARTS_WITH:
0335:                    doStringWithMethod(node);
0336:                    break;
0337:                case MethodNode.IS_EMPTY:
0338:                    doIsEmpty(node);
0339:                    break;
0340:                case MethodNode.CONTAINS_KEY:
0341:                    doContainsKey(node);
0342:                    break;
0343:                case MethodNode.TO_LOWER_CASE:
0344:                    result = toLowerCase(node);
0345:                    break;
0346:                default:
0347:                    throw new NotImplementedException();
0348:                }
0349:                return result;
0350:            }
0351:
0352:            private BCField toLowerCase(MethodNode node) {
0353:                first = true;
0354:                BCField f = (BCField) node.childList.visit(this , null);
0355:                il.append(factory.createInvoke(NAME_STRING, "toLowerCase",
0356:                        Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
0357:                return f;
0358:            }
0359:
0360:            private boolean isVarContainsMethodNode(MethodNode node) {
0361:                if ((node.getMethod() == MethodNode.CONTAINS)
0362:                        && (node.childList.next instanceof  VarNode)) {
0363:                    return true;
0364:                }
0365:                return false;
0366:            }
0367:
0368:            private void doStringWithMethod(MethodNode node) {
0369:                String name = node.getName();
0370:                BCField fl = (BCField) node.childList.visit(this , null);
0371:                if (fl.bcType != MDStatics.STRING) {
0372:                    throw BindingSupportImpl.getInstance().invalidOperation(
0373:                            "The " + name
0374:                                    + " may only be used on a String field");
0375:                }
0376:                node.childList.next.visit(this , null);
0377:                il.append(factory.createCheckCast(OBJECT_TYPE_STRING));
0378:                il.append(factory.createInvoke(NAME_STRING, name, Type.BOOLEAN,
0379:                        ARG_TYPES_STRING, Constants.INVOKEVIRTUAL));
0380:            }
0381:
0382:            private void doIsEmpty(MethodNode node) {
0383:                first = true;
0384:                node.childList.visit(this , null);
0385:                il.append(factory.createCheckCast(OBJECT_TYPE_COLLECTION));
0386:                il.append(factory.createInvoke(NAME_COLLECTION, "isEmpty",
0387:                        Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE));
0388:            }
0389:
0390:            private void doContainsKey(MethodNode node) {
0391:                first = true;
0392:                node.childList.visit(this , null);
0393:                try {
0394:                    il.delete(il.getEnd());
0395:                } catch (TargetLostException e) {
0396:                    throw BindingSupportImpl.getInstance().internal(
0397:                            e.getMessage(), e);
0398:                }
0399:                node.childList.next.visit(this , null);
0400:                il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER,
0401:                        "containsKey", Type.BOOLEAN, new Type[] { Type.INT,
0402:                                Type.OBJECT }, Constants.INVOKEVIRTUAL));
0403:            }
0404:
0405:            private void doContainMethodParam(MethodNode node) {
0406:                first = true;
0407:                BCField bcField = (BCField) node.childList.visit(this , null);
0408:                if (Map.class.isAssignableFrom(bcField.classType)) {
0409:                    if (bcField.getFMD().isElementTypePC()) {
0410:                        try {
0411:                            il.delete(il.getEnd());
0412:                        } catch (TargetLostException e) {
0413:                            throw BindingSupportImpl.getInstance().internal(
0414:                                    e.getMessage(), e);
0415:                        }
0416:                        il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER,
0417:                                "getInternalOIDValueCollectionForMap",
0418:                                OBJECT_TYPE_COLLECTION, ARG_TYPES_INT,
0419:                                Constants.INVOKEVIRTUAL));
0420:                    } else {
0421:                        try {
0422:                            il.delete(il.getEnd());
0423:                        } catch (TargetLostException e) {
0424:                            throw BindingSupportImpl.getInstance().internal(
0425:                                    e.getMessage(), e);
0426:                        }
0427:                        il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER,
0428:                                "getInternalValueCollectionForMap",
0429:                                OBJECT_TYPE_COLLECTION, ARG_TYPES_INT,
0430:                                Constants.INVOKEVIRTUAL));
0431:                    }
0432:                    bcField = (BCField) node.childList.next.visit(this , null);
0433:                    if (bcField.bcType == MDStatics.NULL) {
0434:                        il.append(InstructionConstants.ACONST_NULL);
0435:                    }
0436:                    il.append(factory.createInvoke(NAME_COLLECTION, "contains",
0437:                            Type.BOOLEAN, ARG_TYPES_OBJECT,
0438:                            Constants.INVOKEINTERFACE));
0439:                } else {
0440:                    if (bcField.getFMD().isElementTypePC()) {
0441:                        try {
0442:                            il.delete(il.getEnd());
0443:                        } catch (TargetLostException e) {
0444:                            throw BindingSupportImpl.getInstance().internal(
0445:                                    e.getMessage(), e);
0446:                        }
0447:                        il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER,
0448:                                "getInternalOIDCollection",
0449:                                OBJECT_TYPE_COLLECTION, ARG_TYPES_INT,
0450:                                Constants.INVOKEVIRTUAL));
0451:                    } else {
0452:                        il.append(factory
0453:                                .createCheckCast(OBJECT_TYPE_COLLECTION));
0454:                    }
0455:                    bcField = (BCField) node.childList.next.visit(this , null);
0456:                    if (bcField.bcType == MDStatics.NULL) {
0457:                        il.append(InstructionConstants.ACONST_NULL);
0458:                    }
0459:                    il.append(factory.createInvoke(NAME_COLLECTION, "contains",
0460:                            Type.BOOLEAN, ARG_TYPES_OBJECT,
0461:                            Constants.INVOKEINTERFACE));
0462:                }
0463:            }
0464:
0465:            private void doContainsMethod(MethodNode node) {
0466:                GOTO gotoEnd = new GOTO(null);
0467:                String lv = getLVName(node);
0468:
0469:                //create localVar for declared var
0470:                il.append(InstructionConstants.ACONST_NULL);
0471:                LocalVariableGen var1 = mg.addLocalVariable(lv, new ObjectType(
0472:                        NAME_Q_STATE_WRAPPER), null, null);
0473:                int var1Index = var1.getIndex();
0474:                varToIndexMap.put(lv, new Integer(var1Index));
0475:                il.append(new ASTORE(var1Index));
0476:                var1.setStart(il.append(new NOP()));
0477:
0478:                first = true;
0479:                node.childList.visit(this , null);
0480:                //cast to collection
0481:                il.append(factory.createCheckCast(OBJECT_TYPE_COLLECTION));
0482:
0483:                //create a localvar for the collection by name col
0484:                LocalVariableGen colLV = mg.addLocalVariable(lv + "Col",
0485:                        OBJECT_TYPE_COLLECTION, null, null);
0486:                int colLVIndex = colLV.getIndex();
0487:                colLV.setStart(il.append(new ASTORE(colLVIndex)));
0488:
0489:                il.append(new ALOAD(colLVIndex));
0490:                il.append(factory.createInvoke(NAME_COLLECTION, "isEmpty",
0491:                        Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE));
0492:
0493:                InstructionHandle end = null;
0494:
0495:                if (node.next == null) {
0496:                    il.append(InstructionConstants.ICONST_1);
0497:                    il.append(InstructionConstants.IXOR);
0498:                } else {
0499:                    il.append(InstructionConstants.DUP);
0500:                    IFEQ ifNotEmpty = new IFEQ(null);
0501:                    il.append(ifNotEmpty);
0502:                    // else jump to end
0503:                    il.append(InstructionConstants.POP);
0504:                    il.append(InstructionConstants.ICONST_0);
0505:                    il.append(gotoEnd);
0506:
0507:                    //create the iterator
0508:                    InstructionHandle createIter = il.append(new ALOAD(
0509:                            colLVIndex));
0510:                    il.append(factory.createInvoke(NAME_COLLECTION, "iterator",
0511:                            OBJECT_TYPE_ITERATOR, Type.NO_ARGS,
0512:                            Constants.INVOKEINTERFACE));
0513:                    LocalVariableGen itLV = mg.addLocalVariable(lv + "Iter",
0514:                            OBJECT_TYPE_ITERATOR, null, null);
0515:                    int itLVIndex = itLV.getIndex();
0516:                    itLV.setStart(il.append(new ASTORE(itLVIndex)));
0517:
0518:                    GOTO gotoHasNext = new GOTO(null);
0519:                    il.append(gotoHasNext);
0520:
0521:                    InstructionHandle loadIterForNext = il.append(new ALOAD(
0522:                            itLVIndex));
0523:                    il.append(factory.createInvoke(NAME_ITERATOR, "next",
0524:                            Type.OBJECT, Type.NO_ARGS,
0525:                            Constants.INVOKEINTERFACE));
0526:                    il.append(factory.createCheckCast(new ObjectType(
0527:                            NAME_Q_STATE_WRAPPER)));
0528:                    il.append(new ASTORE(var1Index));
0529:
0530:                    //visit the expr
0531:                    //This must leave a 1 or 0 on the stack
0532:                    il.append(InstructionConstants.POP);
0533:                    node.next.visit(this , null);
0534:                    il.append(InstructionConstants.DUP);
0535:                    IFEQ ifNonTrue = new IFEQ(null);
0536:                    il.append(ifNonTrue);
0537:                    GOTO gotoEnd2 = new GOTO(null);
0538:                    il.append(gotoEnd2);
0539:
0540:                    //createthe hasNext of the iter
0541:                    InstructionHandle loadIterForHasNext = il.append(new ALOAD(
0542:                            itLVIndex));
0543:                    il.append(factory.createInvoke(NAME_ITERATOR, "hasNext",
0544:                            Type.BOOLEAN, Type.NO_ARGS,
0545:                            Constants.INVOKEINTERFACE));
0546:                    IFNE ifMore = new IFNE(loadIterForNext);
0547:                    il.append(ifMore);
0548:
0549:                    gotoHasNext.setTarget(loadIterForHasNext);
0550:                    ifNonTrue.setTarget(loadIterForHasNext);
0551:                    ifNotEmpty.setTarget(createIter);
0552:
0553:                    end = il.append(new NOP());
0554:                    gotoEnd2.setTarget(end);
0555:                    gotoEnd.setTarget(end);
0556:                }
0557:
0558:            }
0559:
0560:            public Field visitPrimaryExprNode(PrimaryExprNode node, Object obj) {
0561:                return null;
0562:            }
0563:
0564:            public Field visitFieldNode(FieldNode node, ClassMetaData cmd) {
0565:                if (cmd == null) {
0566:                    return visitFieldNodeImp(candidateClass
0567:                            .getFieldMetaData(node.lexeme), node);
0568:                } else {
0569:                    return visitFieldNodeImp(cmd.getFieldMetaData(node.lexeme),
0570:                            node);
0571:                }
0572:            }
0573:
0574:            private Field visitFieldNodeImp(FieldMetaData fmd, FieldNode node) {
0575:                BCField field;
0576:                if (fmd == null) {
0577:                    throw BindingSupportImpl.getInstance().runtime(
0578:                            "Class " + candidateClass.qname
0579:                                    + " does not have a field: " + node.lexeme);
0580:                }
0581:                field = new BCStateField(fmd);
0582:                if (first) {
0583:                    field.ih = il.append(new ALOAD(1));//load state on stack
0584:                    first = false;
0585:                    il.append(new PUSH(cp, fmd.stateFieldNo));
0586:                } else {
0587:                    field.ih = il.append(new PUSH(cp, fmd.stateFieldNo));
0588:                }
0589:                if (fmd.typeMetaData == null) {
0590:                    if (!fmd.isElementTypePC()) {
0591:                        il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER,
0592:                                fmd.stateGetMethodName,
0593:                                getBCellStateFieldType(fmd), ARG_TYPES_INT,
0594:                                Constants.INVOKEVIRTUAL));
0595:                    } else {
0596:                        il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER,
0597:                                "getInternalStateCollection",
0598:                                OBJECT_TYPE_COLLECTION, ARG_TYPES_INT,
0599:                                Constants.INVOKEVIRTUAL));
0600:                    }
0601:                } else {
0602:                    il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER,
0603:                            "getOID", OBJECT_TYPE_OID, ARG_TYPES_INT,
0604:                            Constants.INVOKEVIRTUAL));
0605:                }
0606:                return field;
0607:            }
0608:
0609:            public Field visitFieldNode(FieldNode node, Object obj) {
0610:                return visitFieldNodeImp(candidateClass
0611:                        .getFieldMetaData(node.lexeme), node);
0612:            }
0613:
0614:            private static final Type getBCellStateFieldType(FieldMetaData fmd) {
0615:                switch (fmd.category) {
0616:                case MDStatics.CATEGORY_SIMPLE:
0617:                    return getTypeFromTypeCode(fmd.typeCode);
0618:                default:
0619:                    return Type.OBJECT;
0620:                }
0621:            }
0622:
0623:            private static Type getTypeFromTypeCode(int typeCode) {
0624:                switch (typeCode) {
0625:                case MDStatics.INT:
0626:                    return Type.INT;
0627:                case MDStatics.LONG:
0628:                    return Type.LONG;
0629:                case MDStatics.SHORT:
0630:                    return Type.SHORT;
0631:                case MDStatics.STRING:
0632:                    return Type.STRING;
0633:                case MDStatics.BOOLEAN:
0634:                    return Type.BOOLEAN;
0635:                case MDStatics.BYTE:
0636:                    return Type.BYTE;
0637:                case MDStatics.CHAR:
0638:                    return Type.CHAR;
0639:                case MDStatics.DOUBLE:
0640:                    return Type.DOUBLE;
0641:                case MDStatics.FLOAT:
0642:                    return Type.FLOAT;
0643:                default:
0644:                    return Type.OBJECT;
0645:                }
0646:            }
0647:
0648:            private Field doCompare(BinaryNode node, int type) {
0649:                Object obj = null;
0650:                first = true;
0651:                BCField fl = (BCField) node.getLeft().visit(this , obj);
0652:                first = true;
0653:                BCField fr = (BCField) node.getRight().visit(this , obj);
0654:                InstructionHandle nopHandle = il
0655:                        .append(InstructionConstants.NOP);
0656:                int widestType = getWidestType(fl.bcType, fr.bcType);
0657:
0658:                if (fl.isPrimitive() && fr.isPrimitive()) {
0659:                    promotePrimToPrim(widestType, fl, fr.ih);
0660:                    promotePrimToPrim(widestType, fr, nopHandle);
0661:                    switch (widestType) {
0662:                    case MDStatics.BYTE:
0663:                    case MDStatics.SHORT:
0664:                    case MDStatics.CHAR:
0665:                    case MDStatics.INT:
0666:                        writeIIEq(type);
0667:                        break;
0668:                    case MDStatics.LONG:
0669:                        writeLLEq(type);
0670:                        break;
0671:                    case MDStatics.FLOAT:
0672:                        writeFFEq(type);
0673:                        break;
0674:                    case MDStatics.DOUBLE:
0675:                        writeDDEq(type);
0676:                        break;
0677:                    case MDStatics.BOOLEAN:
0678:                        writeIIEq(type);
0679:                        break;
0680:                    default:
0681:                        throw BindingSupportImpl.getInstance().internal(
0682:                                "Comparing field type'"
0683:                                        + MDStaticUtils.toSimpleName(fl.bcType)
0684:                                        + "' to" + " field type '"
0685:                                        + MDStaticUtils.toSimpleName(fl.bcType)
0686:                                        + "' is not implemented correctly.");
0687:                    }
0688:                } else if (!fl.isPrimitive() && !fr.isPrimitive()) {
0689:                    promoteToObjects(widestType, fl, fr.ih);
0690:                    promoteToObjects(widestType, fr, nopHandle);
0691:                    if (fl.bcType == MDStatics.NULL
0692:                            || fr.bcType == MDStatics.NULL) {
0693:                        if (type == COMP_EQ) {
0694:                            IFNONNULL ifnull = new IFNONNULL(null);
0695:                            il.append(ifnull);
0696:                            il.append(InstructionConstants.ICONST_1);
0697:                            GOTO gotoEnd = new GOTO(null);
0698:                            il.append(gotoEnd);
0699:                            InstructionHandle falseHandle = il
0700:                                    .append(InstructionConstants.ICONST_0);
0701:                            InstructionHandle endHandle = il
0702:                                    .append(InstructionConstants.NOP);
0703:                            ifnull.setTarget(falseHandle);
0704:                            gotoEnd.setTarget(endHandle);
0705:                        } else if (type == COMP_NE) {
0706:                            IFNULL ifnull = new IFNULL(null);
0707:                            il.append(ifnull);
0708:                            il.append(InstructionConstants.ICONST_1);
0709:                            GOTO gotoEnd = new GOTO(null);
0710:                            il.append(gotoEnd);
0711:                            InstructionHandle falseHandle = il
0712:                                    .append(InstructionConstants.ICONST_0);
0713:                            InstructionHandle endHandle = il
0714:                                    .append(InstructionConstants.NOP);
0715:                            ifnull.setTarget(falseHandle);
0716:                            gotoEnd.setTarget(endHandle);
0717:                        } else {
0718:                            throw BindingSupportImpl
0719:                                    .getInstance()
0720:                                    .invalidOperation(
0721:                                            "Only '==' and '!=' operators is implemented for comparing to a null value");
0722:                        }
0723:                    } else if (Comparable.class.isAssignableFrom(fl.classType)) {
0724:                        writeComparable(type);
0725:                    } else {
0726:                        il.append(factory.createInvoke(NAME_OBJECT, "equals",
0727:                                Type.BOOLEAN, ARG_TYPES_OBJECT,
0728:                                Constants.INVOKEVIRTUAL));
0729:                    }
0730:                } else {
0731:                    if (widestType == MDStatics.BIGDECIMAL
0732:                            || widestType == MDStatics.BIGINTEGER) {
0733:                        if (fl.isPrimitive()) {
0734:                            promotePrimToBig(widestType, fl, fr.ih);
0735:                        } else {
0736:                            promotePrimToBig(widestType, fr, nopHandle);
0737:                        }
0738:                        writeComparable(type);
0739:                    } else {
0740:                        promoteAllToPrim(widestType, fl, fr.ih);
0741:                        promoteAllToPrim(widestType, fr, nopHandle);
0742:                        switch (widestType) {
0743:                        case MDStatics.BOOLEAN:
0744:                        case MDStatics.BOOLEANW:
0745:                        case MDStatics.BYTE:
0746:                        case MDStatics.BYTEW:
0747:                        case MDStatics.SHORT:
0748:                        case MDStatics.SHORTW:
0749:                        case MDStatics.CHAR:
0750:                        case MDStatics.CHARW:
0751:                        case MDStatics.INT:
0752:                        case MDStatics.INTW:
0753:                            writeIIEq(type);
0754:                            break;
0755:                        case MDStatics.LONG:
0756:                        case MDStatics.LONGW:
0757:                            writeLLEq(type);
0758:                            break;
0759:                        case MDStatics.FLOAT:
0760:                        case MDStatics.FLOATW:
0761:                            writeFFEq(type);
0762:                            break;
0763:                        case MDStatics.DOUBLE:
0764:                        case MDStatics.DOUBLEW:
0765:                            writeDDEq(type);
0766:                            break;
0767:                        default:
0768:                            throw BindingSupportImpl
0769:                                    .getInstance()
0770:                                    .internal(
0771:                                            "Comparing field type'"
0772:                                                    + MDStaticUtils
0773:                                                            .toSimpleName(fl.bcType)
0774:                                                    + "' to"
0775:                                                    + " field type '"
0776:                                                    + MDStaticUtils
0777:                                                            .toSimpleName(fl.bcType)
0778:                                                    + "' is not implemented correctly.");
0779:                        }
0780:                    }
0781:                }
0782:                return null;
0783:            }
0784:
0785:            private void writeComparable(int type) {
0786:                il.append(factory.createInvoke(NAME_COMPARABLE, "compareTo",
0787:                        Type.INT, ARG_TYPES_OBJECT, Constants.INVOKEINTERFACE));
0788:                BranchInstruction bInstr = null;
0789:                switch (type) {
0790:                case COMP_EQ:
0791:                    bInstr = new IFNE(null);
0792:                    break;
0793:                case COMP_GE:
0794:                    bInstr = new IFLT(null);
0795:                    break;
0796:                case COMP_LT:
0797:                    bInstr = new IFGE(null);
0798:                    break;
0799:                case COMP_GT:
0800:                    bInstr = new IFLE(null);
0801:                    break;
0802:                case COMP_LE:
0803:                    bInstr = new IFGT(null);
0804:                    break;
0805:                case COMP_NE:
0806:                    bInstr = new IFEQ(null);
0807:                    break;
0808:                default:
0809:                    throw BindingSupportImpl.getInstance().internal(
0810:                            "No operator of type '" + type + "'");
0811:                }
0812:                il.append(bInstr);
0813:                il.append(InstructionConstants.ICONST_1);
0814:                GOTO gotoEnd = new GOTO(null);
0815:                il.append(gotoEnd);
0816:                //goto end
0817:                InstructionHandle loadFalse = il
0818:                        .append(InstructionConstants.ICONST_0);
0819:                InstructionHandle endHandle = il
0820:                        .append(InstructionConstants.NOP);
0821:
0822:                bInstr.setTarget(loadFalse);
0823:                gotoEnd.setTarget(endHandle);
0824:            }
0825:
0826:            public Field visitEqualNode(EqualNode node, Object obj) {
0827:                return doCompare(node, COMP_EQ);
0828:            }
0829:
0830:            public Field visitNotEqualNode(NotEqualNode node, Object obj) {
0831:                return doCompare(node, COMP_NE);
0832:            }
0833:
0834:            public Field visitLikeNode(LikeNode node, Object obj) {
0835:                return null;
0836:            }
0837:
0838:            private void writeIIEq(int compType) {
0839:                BranchInstruction bInstr = null;
0840:                switch (compType) {
0841:                case COMP_EQ:
0842:                    bInstr = new IF_ICMPNE(null);
0843:                    break;
0844:                case COMP_GE:
0845:                    bInstr = new IF_ICMPLT(null);
0846:                    break;
0847:                case COMP_LT:
0848:                    bInstr = new IF_ICMPGE(null);
0849:                    break;
0850:                case COMP_GT:
0851:                    bInstr = new IF_ICMPLE(null);
0852:                    break;
0853:                case COMP_LE:
0854:                    bInstr = new IF_ICMPGT(null);
0855:                    break;
0856:                case COMP_NE:
0857:                    bInstr = new IF_ICMPEQ(null);
0858:                    break;
0859:                default:
0860:                    throw BindingSupportImpl.getInstance().internal(
0861:                            "No operator of type '" + compType + "'");
0862:                }
0863:                il.append(bInstr);
0864:                il.append(InstructionConstants.ICONST_1);
0865:                GOTO gotoEnd = new GOTO(null);
0866:                il.append(gotoEnd);
0867:                //goto end
0868:                InstructionHandle loadFalse = il
0869:                        .append(InstructionConstants.ICONST_0);
0870:                InstructionHandle endHandle = il
0871:                        .append(InstructionConstants.NOP);
0872:
0873:                bInstr.setTarget(loadFalse);
0874:                gotoEnd.setTarget(endHandle);
0875:            }
0876:
0877:            private void writeDDEq(int compType) {
0878:                BranchInstruction bInstr = null;
0879:                il.append(new DCMPL());
0880:                switch (compType) {
0881:                case COMP_EQ:
0882:                    bInstr = new IFNE(null);
0883:                    break;
0884:                case COMP_GE:
0885:                    bInstr = new IFLT(null);
0886:                    break;
0887:                case COMP_LT:
0888:                    bInstr = new IFGE(null);
0889:                    break;
0890:                case COMP_GT:
0891:                    bInstr = new IFLE(null);
0892:                    break;
0893:                case COMP_LE:
0894:                    bInstr = new IFGT(null);
0895:                    break;
0896:                case COMP_NE:
0897:                    bInstr = new IFEQ(null);
0898:                    break;
0899:                default:
0900:                    throw BindingSupportImpl.getInstance().internal(
0901:                            "No operator of type '" + compType + "'");
0902:                }
0903:                il.append(bInstr);
0904:                il.append(InstructionConstants.ICONST_1);
0905:                GOTO gotoEnd = new GOTO(null);
0906:                il.append(gotoEnd);
0907:                //goto end
0908:                InstructionHandle loadFalse = il
0909:                        .append(InstructionConstants.ICONST_0);
0910:                InstructionHandle endHandle = il
0911:                        .append(InstructionConstants.NOP);
0912:
0913:                bInstr.setTarget(loadFalse);
0914:                gotoEnd.setTarget(endHandle);
0915:            }
0916:
0917:            private void writeFFEq(int compType) {
0918:                BranchInstruction bInstr = null;
0919:                il.append(new FCMPL());
0920:                switch (compType) {
0921:                case COMP_EQ:
0922:                    bInstr = new IFNE(null);
0923:                    break;
0924:                case COMP_GE:
0925:                    bInstr = new IFLT(null);
0926:                    break;
0927:                case COMP_LT:
0928:                    bInstr = new IFGE(null);
0929:                    break;
0930:                case COMP_GT:
0931:                    bInstr = new IFLE(null);
0932:                    break;
0933:                case COMP_LE:
0934:                    bInstr = new IFGT(null);
0935:                    break;
0936:                case COMP_NE:
0937:                    bInstr = new IFEQ(null);
0938:                    break;
0939:                default:
0940:                    throw BindingSupportImpl.getInstance().internal(
0941:                            "No operator of type '" + compType + "'");
0942:                }
0943:                il.append(bInstr);
0944:                il.append(InstructionConstants.ICONST_1);
0945:                GOTO gotoEnd = new GOTO(null);
0946:                il.append(gotoEnd);
0947:                //goto end
0948:                InstructionHandle loadFalse = il
0949:                        .append(InstructionConstants.ICONST_0);
0950:                InstructionHandle endHandle = il
0951:                        .append(InstructionConstants.NOP);
0952:
0953:                bInstr.setTarget(loadFalse);
0954:                gotoEnd.setTarget(endHandle);
0955:            }
0956:
0957:            private void writeLLEq(int type) {
0958:                BranchInstruction bInstr = null;
0959:                switch (type) {
0960:                case COMP_EQ:
0961:                    il.append(new LCMP());
0962:                    bInstr = new IFNE(null);
0963:                    break;
0964:                case COMP_GE:
0965:                    il.append(new LCMP());
0966:                    bInstr = new IFLT(null);
0967:                    break;
0968:                case COMP_GT:
0969:                    il.append(new LCMP());
0970:                    bInstr = new IFLE(null);
0971:                    break;
0972:                case COMP_LE:
0973:                    il.append(new LCMP());
0974:                    bInstr = new IFGT(null);
0975:                    break;
0976:                case COMP_LT:
0977:                    il.append(new LCMP());
0978:                    bInstr = new IFGE(null);
0979:                    break;
0980:                case COMP_NE:
0981:                    il.append(new LCMP());
0982:                    bInstr = new IFEQ(null);
0983:                    break;
0984:                default:
0985:                    throw BindingSupportImpl.getInstance().internal(
0986:                            "No operator of type '" + type + "'");
0987:                }
0988:                il.append(bInstr);
0989:                il.append(InstructionConstants.ICONST_1);
0990:                GOTO gotoEnd = new GOTO(null);
0991:                il.append(gotoEnd);
0992:                //goto end
0993:                InstructionHandle loadFalse = il
0994:                        .append(InstructionConstants.ICONST_0);
0995:                InstructionHandle endHandle = il
0996:                        .append(InstructionConstants.NOP);
0997:
0998:                bInstr.setTarget(loadFalse);
0999:                gotoEnd.setTarget(endHandle);
1000:            }
1001:
1002:            public Field visitAndNode(AndNode node, Object obj) {
1003:                List ifFalseList = new ArrayList();
1004:                first = true;
1005:                node.childList.visit(this , obj);
1006:
1007:                //leave if the child is an methodNode
1008:                if (node.childList instanceof  MethodNode) {
1009:                    MethodNode mNode = (MethodNode) node.childList;
1010:                    if (isVarContainsMethodNode(mNode))
1011:                        return null;
1012:                }
1013:
1014:                il.append(InstructionConstants.DUP);
1015:                IFEQ ifFalse = new IFEQ(null);
1016:                il.append(ifFalse);
1017:
1018:                IFEQ ifFalseVar = null;
1019:                Node n = node.childList.next;
1020:                while (n != null) {
1021:                    first = true;
1022:                    //pop the uncesc value
1023:                    il.append(InstructionConstants.POP);
1024:                    n.visit(this , obj);
1025:                    il.append(InstructionConstants.DUP);
1026:                    ifFalseVar = new IFEQ(null);
1027:                    ifFalseList.add(ifFalseVar);
1028:                    il.append(ifFalseVar);
1029:                    n = n.next;
1030:                }
1031:
1032:                InstructionHandle endHandle = il.append(new NOP());
1033:                ifFalse.setTarget(endHandle);
1034:
1035:                for (int i = 0; i < ifFalseList.size(); i++) {
1036:                    ((IFEQ) ifFalseList.get(i)).setTarget(endHandle);
1037:                }
1038:                return null;
1039:            }
1040:
1041:            public Field visitOrNode(OrNode node, Object obj) {
1042:                List ifFalseList = new ArrayList();
1043:                node.childList.visit(this , obj);
1044:
1045:                il.append(InstructionConstants.DUP);
1046:                IFNE ifTrue = new IFNE(null);
1047:                il.append(ifTrue);
1048:                //
1049:                IFNE ifTrueVar = null;
1050:                Node n = node.childList.next;
1051:
1052:                while (n != null) {
1053:                    first = true;
1054:                    //pop the uncesc value
1055:                    il.append(InstructionConstants.POP);
1056:                    n.visit(this , obj);
1057:                    il.append(InstructionConstants.DUP);
1058:                    ifTrueVar = new IFNE(null);
1059:                    ifFalseList.add(ifTrueVar);
1060:                    il.append(ifTrueVar);
1061:                    n = n.next;
1062:                }
1063:
1064:                InstructionHandle endHandle = il.append(new NOP());
1065:                ifTrue.setTarget(endHandle);
1066:
1067:                for (int i = 0; i < ifFalseList.size(); i++) {
1068:                    ((BranchInstruction) ifFalseList.get(i))
1069:                            .setTarget(endHandle);
1070:                }
1071:                return null;
1072:            }
1073:
1074:            public Field visitMultiplyNode(MultiplyNode node, Object obj) {
1075:                BCField result = null;
1076:                BCField f = (BCField) node.childList.visit(this , obj);
1077:                BCField fnNext = null;
1078:                int widestType = 0;
1079:
1080:                List fieldsToPromote = new ArrayList();
1081:                fieldsToPromote.add(f);
1082:                for (Node n = node.childList.next; n != null; n = n.next) {
1083:                    first = true;
1084:                    fnNext = (BCField) n.visit(this , null);
1085:                    fieldsToPromote.add(fnNext);
1086:                    widestType = getWidestType(f.bcType, fnNext.bcType);
1087:                    f = fnNext;
1088:                }
1089:                InstructionHandle nopHandle = il
1090:                        .append(InstructionConstants.NOP);
1091:                int n = fieldsToPromote.size();
1092:                int lastIndex = n - 1;
1093:                for (int i = 0; i < n; i++) {
1094:                    BCField bcField1 = (BCField) fieldsToPromote.get(i);
1095:                    BCField bcField2 = (i == lastIndex) ? null
1096:                            : (BCField) fieldsToPromote.get(i + 1);
1097:                    if (bcField2 == null) {
1098:                        promoteTo(widestType, bcField1, nopHandle);
1099:                    } else {
1100:                        promoteTo(widestType, bcField1, bcField2.ih);
1101:                    }
1102:                }
1103:
1104:                if (fieldsToPromote.size() == 2) {
1105:                    insertMultiply(widestType, nopHandle, node.ops[0]);
1106:                } else {
1107:                    for (int i = 1; i < n; i++) {
1108:                        if (i == lastIndex) {
1109:                            insertMultiply(widestType, nopHandle,
1110:                                    node.ops[i - 1]);
1111:                        } else {
1112:                            BCField bcField2 = (BCField) fieldsToPromote
1113:                                    .get(i + 1);
1114:                            insertMultiply(widestType, bcField2.ih,
1115:                                    node.ops[i - 1]);
1116:                        }
1117:                    }
1118:                }
1119:                result = new BCField();
1120:                result.bcType = widestType;
1121:                result.classType = MDStaticUtils.toSimpleClass(MDStaticUtils
1122:                        .toSimpleName(widestType));
1123:                return result;
1124:            }
1125:
1126:            public Field visitAddNode(AddNode node, Object obj) {
1127:                BCField result = null;
1128:                first = true;
1129:                BCField f = (BCField) node.childList.visit(this , obj);
1130:                BCField fnNext = null;
1131:                int widestType = 0;
1132:                if (f.bcType == MDStatics.STRING) {
1133:                    il.append(factory.createNew(NAME_STRING_BUFFER));
1134:                    il.append(InstructionConstants.DUP);
1135:                    il.append(factory.createInvoke(NAME_STRING_BUFFER,
1136:                            "<init>", Type.VOID, Type.NO_ARGS,
1137:                            Constants.INVOKESPECIAL));
1138:                    LocalVariableGen lg = mg.addLocalVariable("buffer",
1139:                            OBJECT_TYPE_STRING_BUFFER, null, null);
1140:                    int bufferIndex = lg.getIndex();
1141:                    lg.setStart(il.append(new ASTORE(bufferIndex)));
1142:                    il.append(new ALOAD(bufferIndex));
1143:                    il.append(InstructionConstants.SWAP);
1144:                    il.append(factory.createInvoke(NAME_STRING_BUFFER,
1145:                            "append", OBJECT_TYPE_STRING_BUFFER,
1146:                            ARG_TYPES_STRING, Constants.INVOKEVIRTUAL));
1147:
1148:                    for (Node n = node.childList.next; n != null; n = n.next) {
1149:                        first = true;
1150:                        n.visit(this , null);
1151:                        il.append(factory.createInvoke(NAME_STRING_BUFFER,
1152:                                "append", OBJECT_TYPE_STRING_BUFFER,
1153:                                ARG_TYPES_STRING, Constants.INVOKEVIRTUAL));
1154:                    }
1155:                    il.append(factory.createInvoke(NAME_STRING_BUFFER,
1156:                            "toString", Type.STRING, Type.NO_ARGS,
1157:                            Constants.INVOKEVIRTUAL));
1158:                    result = new BCField();
1159:                    result.setBcType(MDStatics.STRING);
1160:                    result.classType = String.class;
1161:                } else {
1162:                    List fieldsToPromote = new ArrayList();
1163:                    fieldsToPromote.add(f);
1164:                    for (Node n = node.childList.next; n != null; n = n.next) {
1165:                        first = true;
1166:                        fnNext = (BCField) n.visit(this , null);
1167:                        fieldsToPromote.add(fnNext);
1168:                        widestType = getWidestType(f.bcType, fnNext.bcType);
1169:                        f = fnNext;
1170:                    }
1171:                    InstructionHandle nopHandle = il
1172:                            .append(InstructionConstants.NOP);
1173:                    int n = fieldsToPromote.size();
1174:                    int lastIndex = n - 1;
1175:                    for (int i = 0; i < n; i++) {
1176:                        BCField bcField1 = (BCField) fieldsToPromote.get(i);
1177:                        BCField bcField2 = (i == lastIndex) ? null
1178:                                : (BCField) fieldsToPromote.get(i + 1);
1179:                        if (bcField2 == null) {
1180:                            promoteTo(widestType, bcField1, nopHandle);
1181:                        } else {
1182:                            promoteTo(widestType, bcField1, bcField2.ih);
1183:                        }
1184:                    }
1185:
1186:                    if (fieldsToPromote.size() == 2) {
1187:                        insertAddOp(widestType, nopHandle, node.ops[0]);
1188:                    } else {
1189:                        for (int i = 1; i < n; i++) {
1190:                            if (i == lastIndex) {
1191:                                insertAddOp(widestType, nopHandle,
1192:                                        node.ops[i - 1]);
1193:                            } else {
1194:                                BCField bcField2 = (BCField) fieldsToPromote
1195:                                        .get(i + 1);
1196:                                insertAddOp(widestType, bcField2.ih,
1197:                                        node.ops[i - 1]);
1198:                            }
1199:                        }
1200:                    }
1201:                    result = new BCField();
1202:                    result.bcType = widestType;
1203:                    result.classType = MDStaticUtils
1204:                            .toSimpleClass(MDStaticUtils
1205:                                    .toSimpleName(widestType));
1206:                }
1207:                return result;
1208:            }
1209:
1210:            private void insertMultiply(int widestType,
1211:                    InstructionHandle insertHandle, int type) {
1212:                if (type == MultiplyNode.OP_TIMES) {
1213:                    switch (widestType) {
1214:                    case MDStatics.BYTE:
1215:                    case MDStatics.SHORT:
1216:                    case MDStatics.CHAR:
1217:                    case MDStatics.INT:
1218:                        il.insert(insertHandle, InstructionConstants.IMUL);
1219:                        break;
1220:                    case MDStatics.LONG:
1221:                        il.insert(insertHandle, InstructionConstants.LMUL);
1222:                        break;
1223:                    case MDStatics.FLOAT:
1224:                        il.insert(insertHandle, InstructionConstants.FMUL);
1225:                        break;
1226:                    case MDStatics.DOUBLE:
1227:                        il.insert(insertHandle, InstructionConstants.DMUL);
1228:                        break;
1229:                    case MDStatics.BIGINTEGER:
1230:                        il.insert(insertHandle, factory.createInvoke(
1231:                                NAME_BIG_INT, "multiply", RET_TYPE_BIG_INT,
1232:                                ARG_TYPES_BIG_INT, Constants.INVOKEVIRTUAL));
1233:                        break;
1234:                    case MDStatics.BIGDECIMAL:
1235:                        il.insert(insertHandle, factory.createInvoke(
1236:                                NAME_BIG_DEC, "multiply", RET_TYPE_BIG_DEC,
1237:                                ARG_TYPES_BIG_DEC, Constants.INVOKEVIRTUAL));
1238:                        break;
1239:                    default:
1240:                        throw BindingSupportImpl
1241:                                .getInstance()
1242:                                .internal(
1243:                                        "The '*' operator is not implemented correctly for type '"
1244:                                                + MDStaticUtils
1245:                                                        .toSimpleName(widestType)
1246:                                                + "'");
1247:                    }
1248:                } else {
1249:                    switch (widestType) {
1250:                    case MDStatics.BYTE:
1251:                    case MDStatics.SHORT:
1252:                    case MDStatics.CHAR:
1253:                    case MDStatics.INT:
1254:                        il.insert(insertHandle, InstructionConstants.IDIV);
1255:                        break;
1256:                    case MDStatics.LONG:
1257:                        il.insert(insertHandle, InstructionConstants.LDIV);
1258:                        break;
1259:                    case MDStatics.FLOAT:
1260:                        il.insert(insertHandle, InstructionConstants.FDIV);
1261:                        break;
1262:                    case MDStatics.DOUBLE:
1263:                        il.insert(insertHandle, InstructionConstants.DDIV);
1264:                        break;
1265:                    case MDStatics.BIGINTEGER:
1266:                        il.insert(insertHandle, factory.createInvoke(
1267:                                NAME_BIG_INT, "divide", RET_TYPE_BIG_INT,
1268:                                ARG_TYPES_BIG_INT, Constants.INVOKEVIRTUAL));
1269:                        break;
1270:                    case MDStatics.BIGDECIMAL:
1271:                        il.insert(insertHandle, factory.createInvoke(
1272:                                NAME_BIG_DEC, "divide", RET_TYPE_BIG_DEC,
1273:                                ARG_TYPES_BIG_DEC, Constants.INVOKEVIRTUAL));
1274:                        break;
1275:                    default:
1276:                        throw BindingSupportImpl
1277:                                .getInstance()
1278:                                .internal(
1279:                                        "The '/' operator is not implemented correctly for type '"
1280:                                                + MDStaticUtils
1281:                                                        .toSimpleName(widestType)
1282:                                                + "'");
1283:                    }
1284:                }
1285:            }
1286:
1287:            private void insertAddOp(int widestType,
1288:                    InstructionHandle insertHandle, int type) {
1289:                if (type == AddNode.OP_PLUS) {
1290:                    switch (widestType) {
1291:                    case MDStatics.BYTE:
1292:                    case MDStatics.SHORT:
1293:                    case MDStatics.CHAR:
1294:                    case MDStatics.INT:
1295:                        il.insert(insertHandle, InstructionConstants.IADD);
1296:                        break;
1297:                    case MDStatics.LONG:
1298:                        il.insert(insertHandle, InstructionConstants.LADD);
1299:                        break;
1300:                    case MDStatics.FLOAT:
1301:                        il.insert(insertHandle, InstructionConstants.FADD);
1302:                        break;
1303:                    case MDStatics.DOUBLE:
1304:                        il.insert(insertHandle, InstructionConstants.DADD);
1305:                        break;
1306:                    case MDStatics.BIGINTEGER:
1307:                        il.insert(insertHandle, factory.createInvoke(
1308:                                NAME_BIG_INT, "add", RET_TYPE_BIG_INT,
1309:                                ARG_TYPES_BIG_INT, Constants.INVOKEVIRTUAL));
1310:                        break;
1311:                    case MDStatics.BIGDECIMAL:
1312:                        il.insert(insertHandle, factory.createInvoke(
1313:                                NAME_BIG_DEC, "add", RET_TYPE_BIG_DEC,
1314:                                ARG_TYPES_BIG_DEC, Constants.INVOKEVIRTUAL));
1315:                        break;
1316:                    default:
1317:                        throw BindingSupportImpl
1318:                                .getInstance()
1319:                                .internal(
1320:                                        "The '+' operator is not implemented correctly for type '"
1321:                                                + MDStaticUtils
1322:                                                        .toSimpleName(widestType)
1323:                                                + "'");
1324:                    }
1325:                } else {
1326:                    switch (widestType) {
1327:                    case MDStatics.BYTE:
1328:                    case MDStatics.SHORT:
1329:                    case MDStatics.CHAR:
1330:                    case MDStatics.INT:
1331:                        il.insert(insertHandle, InstructionConstants.ISUB);
1332:                        break;
1333:                    case MDStatics.LONG:
1334:                        il.insert(insertHandle, InstructionConstants.LSUB);
1335:                        break;
1336:                    case MDStatics.FLOAT:
1337:                        il.insert(insertHandle, InstructionConstants.FSUB);
1338:                        break;
1339:                    case MDStatics.DOUBLE:
1340:                        il.insert(insertHandle, InstructionConstants.DSUB);
1341:                        break;
1342:                    case MDStatics.BIGINTEGER:
1343:                        il.insert(insertHandle, factory.createInvoke(
1344:                                NAME_BIG_INT, "subtract", RET_TYPE_BIG_INT,
1345:                                ARG_TYPES_BIG_INT, Constants.INVOKEVIRTUAL));
1346:                        break;
1347:                    case MDStatics.BIGDECIMAL:
1348:                        il.insert(insertHandle, factory.createInvoke(
1349:                                NAME_BIG_DEC, "subtract", RET_TYPE_BIG_DEC,
1350:                                ARG_TYPES_BIG_DEC, Constants.INVOKEVIRTUAL));
1351:                        break;
1352:                    default:
1353:                        throw BindingSupportImpl
1354:                                .getInstance()
1355:                                .internal(
1356:                                        "The '-' operator is not implemented correctly for type '"
1357:                                                + MDStaticUtils
1358:                                                        .toSimpleName(widestType)
1359:                                                + "'");
1360:                    }
1361:                }
1362:            }
1363:
1364:            private void promoteTo(int typePromoteTo, BCField otherType,
1365:                    InstructionHandle insertHandle) {
1366:                if (otherType.bcType == typePromoteTo) {
1367:                    if (otherType.bcType == MDStatics.BIGINTEGER) {
1368:                        //add a cast
1369:                        il.insert(insertHandle, factory
1370:                                .createCheckCast(RET_TYPE_BIG_INT));
1371:                    } else if (otherType.bcType == MDStatics.BIGDECIMAL) {
1372:                        //add a cast
1373:                        il.insert(insertHandle, factory
1374:                                .createCheckCast(RET_TYPE_BIG_DEC));
1375:                    }
1376:                    return;
1377:                }
1378:                switch (typePromoteTo) {
1379:                case MDStatics.BYTE:
1380:                case MDStatics.SHORT:
1381:                case MDStatics.CHAR:
1382:                case MDStatics.INT:
1383:                    if (!otherType.isPrimitive()) {
1384:                        il.insert(insertHandle, factory
1385:                                .createCheckCast(OBJECT_TYPE_NUMBER));
1386:                        il.insert(insertHandle, factory.createInvoke(
1387:                                NAME_NUMBER, "intValue", Type.INT,
1388:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
1389:                    }
1390:                    break;
1391:                case MDStatics.LONG:
1392:                    if (!otherType.isPrimitive()) {
1393:                        il.insert(insertHandle, factory
1394:                                .createCheckCast(OBJECT_TYPE_NUMBER));
1395:                        il.insert(insertHandle, factory.createInvoke(
1396:                                NAME_NUMBER, "longValue", Type.LONG,
1397:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
1398:                    } else {
1399:                        il.insert(insertHandle, InstructionConstants.I2L);
1400:                    }
1401:                    break;
1402:                case MDStatics.FLOAT:
1403:                    if (!otherType.isPrimitive()) {
1404:                        il.insert(insertHandle, factory
1405:                                .createCheckCast(OBJECT_TYPE_NUMBER));
1406:                        il.insert(insertHandle, factory.createInvoke(
1407:                                NAME_NUMBER, "floatValue", Type.FLOAT,
1408:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
1409:                    } else {
1410:                        if (otherType.bcType == MDStatics.LONG) {
1411:                            il.insert(insertHandle, InstructionConstants.L2F);
1412:                        } else {
1413:                            il.insert(insertHandle, InstructionConstants.I2F);
1414:                        }
1415:                    }
1416:                    break;
1417:                case MDStatics.DOUBLE:
1418:                    if (!otherType.isPrimitive()) {
1419:                        il.insert(insertHandle, factory
1420:                                .createCheckCast(OBJECT_TYPE_NUMBER));
1421:                        il.insert(insertHandle, factory.createInvoke(
1422:                                NAME_NUMBER, "doubleValue", Type.DOUBLE,
1423:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
1424:                    } else {
1425:                        switch (otherType.bcType) {
1426:                        case MDStatics.BYTE:
1427:                        case MDStatics.SHORT:
1428:                        case MDStatics.CHAR:
1429:                        case MDStatics.INT:
1430:                            il.insert(insertHandle, InstructionConstants.I2D);
1431:                            break;
1432:                        case MDStatics.LONG:
1433:                            il.insert(insertHandle, InstructionConstants.L2D);
1434:                            break;
1435:                        case MDStatics.FLOAT:
1436:                            il.insert(insertHandle, InstructionConstants.F2D);
1437:                            break;
1438:                        }
1439:                    }
1440:                    break;
1441:                case MDStatics.BIGINTEGER:
1442:                    insertBigTypeFromPrim(insertHandle, otherType, NAME_BIG_INT);
1443:                    break;
1444:                case MDStatics.BIGDECIMAL:
1445:                    insertBigTypeFromPrim(insertHandle, otherType, NAME_BIG_DEC);
1446:                    break;
1447:                default:
1448:                    throw BindingSupportImpl.getInstance().internal(
1449:                            "Promoting to type '"
1450:                                    + MDStaticUtils.toSimpleName(typePromoteTo)
1451:                                    + "' is not supported");
1452:                }
1453:
1454:            }
1455:
1456:            private void insertBigTypeFromObject(
1457:                    InstructionHandle insertHandle, String typeName) {
1458:                LocalVariableGen valueOfLV = null;
1459:                int colLVIndex;
1460:
1461:                il.insert(insertHandle, factory.createInvoke(NAME_OBJECT,
1462:                        "toString", OBJECT_TYPE_STRING, Type.NO_ARGS,
1463:                        Constants.INVOKEVIRTUAL));
1464:
1465:                //create a localvar for the string
1466:                valueOfLV = mg.addLocalVariable("valueOfString"
1467:                        + valueLVCount++, Type.STRING, null, null);
1468:                colLVIndex = valueOfLV.getIndex();
1469:                valueOfLV.setStart(il.insert(insertHandle, new ASTORE(
1470:                        colLVIndex)));
1471:
1472:                il.insert(insertHandle, factory.createNew(typeName));
1473:                il.insert(insertHandle, InstructionConstants.DUP);
1474:                il.insert(insertHandle, new ALOAD(colLVIndex));
1475:                il.insert(insertHandle, factory.createInvoke(typeName,
1476:                        "<init>", Type.VOID, ARG_TYPES_STRING,
1477:                        Constants.INVOKESPECIAL));
1478:            }
1479:
1480:            private void insertBigTypeFromPrim(InstructionHandle insertHandle,
1481:                    BCField otherType, String typeName) {
1482:                LocalVariableGen valueOfLV;
1483:                int colLVIndex;
1484:
1485:                il.insert(insertHandle, factory.createInvoke(NAME_STRING,
1486:                        "valueOf", OBJECT_TYPE_STRING,
1487:                        new Type[] { getTypeFromTypeCode(otherType.bcType) },
1488:                        Constants.INVOKESTATIC));
1489:
1490:                //create a localvar for the string
1491:                valueOfLV = mg.addLocalVariable("valueOfString"
1492:                        + valueLVCount++, Type.STRING, null, null);
1493:                colLVIndex = valueOfLV.getIndex();
1494:                valueOfLV.setStart(il.insert(insertHandle, new ASTORE(
1495:                        colLVIndex)));
1496:
1497:                il.insert(insertHandle, factory.createNew(typeName));
1498:                il.insert(insertHandle, InstructionConstants.DUP);
1499:                il.insert(insertHandle, new ALOAD(colLVIndex));
1500:                il.insert(insertHandle, factory.createInvoke(typeName,
1501:                        "<init>", Type.VOID, ARG_TYPES_STRING,
1502:                        Constants.INVOKESPECIAL));
1503:            }
1504:
1505:            /**
1506:             * This will check if the type to promote to is either a BigInteger or a BigDecimal. If either is true
1507:             * the the other type must be converted to a the corresponding type.
1508:             *
1509:             * @param typePromoteTo
1510:             * @param otherType
1511:             * @param insertHandle
1512:             */
1513:            private void promoteToObjects(int typePromoteTo, BCField otherType,
1514:                    InstructionHandle insertHandle) {
1515:                if (typePromoteTo == otherType.bcType) {
1516:                    return;
1517:                }
1518:                switch (typePromoteTo) {
1519:                case MDStatics.BIGINTEGER:
1520:                    insertBigTypeFromObject(insertHandle, NAME_BIG_INT);
1521:                    break;
1522:                case MDStatics.BIGDECIMAL:
1523:                    insertBigTypeFromObject(insertHandle, NAME_BIG_DEC);
1524:                    break;
1525:                default:
1526:                    //do nothing. This is a no-op
1527:                }
1528:
1529:            }
1530:
1531:            /**
1532:             * This must promote a prim to an big type.
1533:             *
1534:             * @param typePromoteTo
1535:             * @param otherType
1536:             * @param insertHandle
1537:             */
1538:            private void promotePrimToBig(int typePromoteTo, BCField otherType,
1539:                    InstructionHandle insertHandle) {
1540:                if (typePromoteTo == otherType.bcType) {
1541:                    return;
1542:                }
1543:                switch (typePromoteTo) {
1544:                case MDStatics.BIGINTEGER:
1545:                    insertBigTypeFromPrim(insertHandle, otherType, NAME_BIG_INT);
1546:                    break;
1547:                case MDStatics.BIGDECIMAL:
1548:                    insertBigTypeFromPrim(insertHandle, otherType, NAME_BIG_DEC);
1549:                    break;
1550:                default:
1551:                    throw BindingSupportImpl.getInstance().internal(
1552:                            "Only 'BigInteger' and 'BigDecimal' is supported");
1553:                }
1554:
1555:            }
1556:
1557:            /**
1558:             * This will promote a primitive to a bigger primitive.
1559:             *
1560:             * @param typePromoteTo
1561:             * @param otherType
1562:             * @param insertHandle
1563:             */
1564:            private void promotePrimToPrim(int typePromoteTo,
1565:                    BCField otherType, InstructionHandle insertHandle) {
1566:                if (otherType.bcType == typePromoteTo) {
1567:                    return;
1568:                }
1569:                switch (typePromoteTo) {
1570:                case MDStatics.BYTE:
1571:                case MDStatics.SHORT:
1572:                case MDStatics.CHAR:
1573:                case MDStatics.INT:
1574:                    break;
1575:                case MDStatics.LONG:
1576:                    il.insert(insertHandle, InstructionConstants.I2L);
1577:                    break;
1578:                case MDStatics.FLOAT:
1579:                    if (otherType.bcType == MDStatics.LONG) {
1580:                        il.insert(insertHandle, InstructionConstants.L2F);
1581:                    } else {
1582:                        il.insert(insertHandle, InstructionConstants.I2F);
1583:                    }
1584:                    break;
1585:                case MDStatics.DOUBLE:
1586:                    switch (otherType.bcType) {
1587:                    case MDStatics.BYTE:
1588:                    case MDStatics.SHORT:
1589:                    case MDStatics.CHAR:
1590:                    case MDStatics.INT:
1591:                        il.insert(insertHandle, InstructionConstants.I2D);
1592:                        break;
1593:                    case MDStatics.LONG:
1594:                        il.insert(insertHandle, InstructionConstants.L2D);
1595:                        break;
1596:                    case MDStatics.FLOAT:
1597:                        il.insert(insertHandle, InstructionConstants.F2D);
1598:                        break;
1599:                    }
1600:                    break;
1601:                case MDStatics.BOOLEAN:
1602:                    throw BindingSupportImpl
1603:                            .getInstance()
1604:                            .invalidOperation(
1605:                                    "Promoting between primitives and boolean's is not allowed");
1606:                default:
1607:                    throw BindingSupportImpl.getInstance().internal(
1608:                            "Promoting from type '"
1609:                                    + MDStaticUtils
1610:                                            .toSimpleName(otherType.bcType)
1611:                                    + "'" + " to type '"
1612:                                    + MDStaticUtils.toSimpleName(typePromoteTo)
1613:                                    + "' is not implemented correctly");
1614:                }
1615:
1616:            }
1617:
1618:            /**
1619:             * Promote all to primitives
1620:             * @param typePromoteTo
1621:             * @param otherType
1622:             * @param insertHandle
1623:             */
1624:            private void promoteAllToPrim(int typePromoteTo, BCField otherType,
1625:                    InstructionHandle insertHandle) {
1626:                if (otherType.bcType == typePromoteTo
1627:                        && otherType.isPrimitive()) {
1628:                    return;
1629:                }
1630:                switch (typePromoteTo) {
1631:                case MDStatics.BYTE:
1632:                case MDStatics.SHORT:
1633:                case MDStatics.CHAR:
1634:                case MDStatics.INT:
1635:                case MDStatics.INTW:
1636:                    if (!otherType.isPrimitive()) {
1637:                        il.insert(insertHandle, factory
1638:                                .createCheckCast(OBJECT_TYPE_NUMBER));
1639:                        il.insert(insertHandle, factory.createInvoke(
1640:                                NAME_NUMBER, "intValue", Type.INT,
1641:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
1642:                    }
1643:                    break;
1644:                case MDStatics.LONG:
1645:                case MDStatics.LONGW:
1646:                    if (!otherType.isPrimitive()) {
1647:                        il.insert(insertHandle, factory
1648:                                .createCheckCast(OBJECT_TYPE_NUMBER));
1649:                        il.insert(insertHandle, factory.createInvoke(
1650:                                NAME_NUMBER, "longValue", Type.LONG,
1651:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
1652:                    } else {
1653:                        il.insert(insertHandle, InstructionConstants.I2L);
1654:                    }
1655:                    break;
1656:                case MDStatics.FLOAT:
1657:                case MDStatics.FLOATW:
1658:                    if (!otherType.isPrimitive()) {
1659:                        il.insert(insertHandle, factory
1660:                                .createCheckCast(OBJECT_TYPE_NUMBER));
1661:                        il.insert(insertHandle, factory.createInvoke(
1662:                                NAME_NUMBER, "floatValue", Type.FLOAT,
1663:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
1664:                    } else {
1665:                        if (otherType.bcType == MDStatics.LONG) {
1666:                            il.insert(insertHandle, InstructionConstants.L2F);
1667:                        } else {
1668:                            il.insert(insertHandle, InstructionConstants.I2F);
1669:                        }
1670:                    }
1671:                    break;
1672:                case MDStatics.DOUBLE:
1673:                case MDStatics.DOUBLEW:
1674:                    if (!otherType.isPrimitive()) {
1675:                        il.insert(insertHandle, factory
1676:                                .createCheckCast(OBJECT_TYPE_NUMBER));
1677:                        il.insert(insertHandle, factory.createInvoke(
1678:                                NAME_NUMBER, "doubleValue", Type.DOUBLE,
1679:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
1680:                    } else {
1681:                        switch (otherType.bcType) {
1682:                        case MDStatics.BYTE:
1683:                        case MDStatics.SHORT:
1684:                        case MDStatics.CHAR:
1685:                        case MDStatics.INT:
1686:                            il.insert(insertHandle, InstructionConstants.I2D);
1687:                            break;
1688:                        case MDStatics.LONG:
1689:                            il.insert(insertHandle, InstructionConstants.L2D);
1690:                            break;
1691:                        case MDStatics.FLOAT:
1692:                            il.insert(insertHandle, InstructionConstants.F2D);
1693:                            break;
1694:                        }
1695:                    }
1696:                    break;
1697:                case MDStatics.BOOLEAN:
1698:                case MDStatics.BOOLEANW:
1699:                    if (!otherType.isPrimitive()) {
1700:                        il.insert(insertHandle, factory
1701:                                .createCheckCast(new ObjectType(Boolean.class
1702:                                        .getName())));
1703:                        il.insert(insertHandle, factory.createInvoke(
1704:                                Boolean.class.getName(), "booleanValue",
1705:                                Type.BOOLEAN, Type.NO_ARGS,
1706:                                Constants.INVOKEVIRTUAL));
1707:                    }
1708:                    break;
1709:                default:
1710:                    throw BindingSupportImpl.getInstance().internal(
1711:                            "Promoting from type '"
1712:                                    + MDStaticUtils
1713:                                            .toSimpleName(otherType.bcType)
1714:                                    + "'" + " to type '"
1715:                                    + MDStaticUtils.toSimpleName(typePromoteTo)
1716:                                    + "' is not implemented correctly");
1717:                }
1718:
1719:            }
1720:
1721:            /**
1722:             * This must check the types and determine the wider of the 2.
1723:             * @param typeL
1724:             * @param typeR
1725:             * @return
1726:             */
1727:            private int getWidestType(int typeL, int typeR) {
1728:                if (typeL == typeR) {
1729:                    return typeL;
1730:                }
1731:                int lValue = getWidth(typeL);
1732:                int rValue = getWidth(typeR);
1733:                if (lValue < rValue) {
1734:                    return typeR;
1735:                } else {
1736:                    return typeL;
1737:                }
1738:            }
1739:
1740:            private int getWidth(int type) {
1741:                switch (type) {
1742:                case MDStatics.BOOLEAN:
1743:                case MDStatics.BOOLEANW:
1744:                case MDStatics.BYTE:
1745:                case MDStatics.BYTEW:
1746:                    return 1;
1747:                case MDStatics.SHORT:
1748:                case MDStatics.SHORTW:
1749:                    return 1;
1750:                case MDStatics.CHAR:
1751:                case MDStatics.CHARW:
1752:                    return 1;
1753:                case MDStatics.INT:
1754:                case MDStatics.INTW:
1755:                    return 1;
1756:                case MDStatics.LONG:
1757:                case MDStatics.LONGW:
1758:                    return 2;
1759:                case MDStatics.FLOAT:
1760:                case MDStatics.FLOATW:
1761:                    return 3;
1762:                case MDStatics.DOUBLE:
1763:                case MDStatics.DOUBLEW:
1764:                    return 4;
1765:                case MDStatics.BIGINTEGER:
1766:                    return 8;
1767:                case MDStatics.BIGDECIMAL:
1768:                    return 16;
1769:                case MDStatics.NULL:
1770:                    return -1;
1771:                default:
1772:                    return -1;
1773:                }
1774:            }
1775:
1776:            public Field visitUnaryOpNode(UnaryOpNode node, Object obj) {
1777:                BCField result = null;
1778:                switch (node.op) {
1779:                case UnaryOpNode.OP_BANG:
1780:                    node.childList.visit(this , null);
1781:                    IFNE ifTrue = new IFNE(null);
1782:                    il.append(ifTrue);
1783:                    il.append(InstructionConstants.ICONST_1);
1784:                    GOTO gotoEnd = new GOTO(null);
1785:                    il.append(gotoEnd);
1786:                    InstructionHandle toFalseHandle = il
1787:                            .append(InstructionConstants.ICONST_0);
1788:                    ifTrue.setTarget(toFalseHandle);
1789:                    gotoEnd.setTarget(il.append(InstructionConstants.NOP));
1790:                    break;
1791:                case UnaryOpNode.OP_MINUS:
1792:                    result = (BCField) node.childList.visit(this , null);
1793:                    switch (result.bcType) {
1794:                    case MDStatics.BYTE:
1795:                    case MDStatics.CHAR:
1796:                    case MDStatics.SHORT:
1797:                    case MDStatics.INT:
1798:                        il.append(InstructionConstants.INEG);
1799:                        break;
1800:                    case MDStatics.BYTEW:
1801:                    case MDStatics.CHARW:
1802:                    case MDStatics.SHORTW:
1803:                    case MDStatics.INTW:
1804:                        il.append(factory.createCheckCast(OBJECT_TYPE_NUMBER));
1805:                        il.append(factory
1806:                                .createInvoke(NAME_NUMBER, "intValue",
1807:                                        Type.INT, Type.NO_ARGS,
1808:                                        Constants.INVOKEVIRTUAL));
1809:                        il.append(InstructionConstants.INEG);
1810:                        result = new BCField();
1811:                        result.classType = Integer.TYPE;
1812:                        result.bcType = MDStatics.INT;
1813:                        break;
1814:                    case MDStatics.LONGW:
1815:                        il.append(factory.createCheckCast(OBJECT_TYPE_NUMBER));
1816:                        il.append(factory.createInvoke(NAME_NUMBER,
1817:                                "longValue", Type.LONG, Type.NO_ARGS,
1818:                                Constants.INVOKEVIRTUAL));
1819:                        result = new BCField();
1820:                        result.classType = Long.TYPE;
1821:                        result.bcType = MDStatics.LONG;
1822:                    case MDStatics.LONG:
1823:                        il.append(InstructionConstants.LNEG);
1824:                        break;
1825:                    case MDStatics.FLOATW:
1826:                        il.append(factory.createCheckCast(OBJECT_TYPE_NUMBER));
1827:                        il.append(factory.createInvoke(NAME_NUMBER,
1828:                                "floatValue", Type.FLOAT, Type.NO_ARGS,
1829:                                Constants.INVOKEVIRTUAL));
1830:                        result = new BCField();
1831:                        result.classType = Float.TYPE;
1832:                        result.bcType = MDStatics.FLOAT;
1833:                    case MDStatics.FLOAT:
1834:                        il.append(InstructionConstants.FNEG);
1835:                        break;
1836:                    case MDStatics.DOUBLEW:
1837:                        il.append(factory.createCheckCast(OBJECT_TYPE_NUMBER));
1838:                        il.append(factory.createInvoke(NAME_NUMBER,
1839:                                "doubleValue", Type.DOUBLE, Type.NO_ARGS,
1840:                                Constants.INVOKEVIRTUAL));
1841:                        result = new BCField();
1842:                        result.classType = Double.TYPE;
1843:                        result.bcType = MDStatics.DOUBLE;
1844:                    case MDStatics.DOUBLE:
1845:                        il.append(InstructionConstants.DNEG);
1846:                        break;
1847:                    default:
1848:                        throw new NotImplementedException();
1849:                    }
1850:                    break;
1851:                case UnaryOpNode.OP_PLUS:
1852:                    result = (BCField) node.childList.visit(this , null);
1853:                    break;
1854:                case UnaryOpNode.OP_TILDE:
1855:                    result = (BCField) node.childList.visit(this , null);
1856:                    InstructionHandle nopHandle = il
1857:                            .append(InstructionConstants.NOP);
1858:                    promoteAllToPrim(result.bcType, result, nopHandle);
1859:                    switch (result.bcType) {
1860:                    case MDStatics.BYTE:
1861:                    case MDStatics.CHAR:
1862:                    case MDStatics.SHORT:
1863:                    case MDStatics.INT:
1864:                    case MDStatics.BYTEW:
1865:                    case MDStatics.CHARW:
1866:                    case MDStatics.SHORTW:
1867:                    case MDStatics.INTW:
1868:                        if (result.bcType != MDStatics.INT) {
1869:                            result = new BCField();
1870:                            result.bcType = MDStatics.INT;
1871:                            result.classType = Integer.TYPE;
1872:                        }
1873:                        il.append(InstructionConstants.ICONST_M1);
1874:                        il.append(InstructionConstants.IXOR);
1875:                        break;
1876:                    case MDStatics.LONG:
1877:                    case MDStatics.LONGW:
1878:                        if (result.bcType != MDStatics.LONG) {
1879:                            result = new BCField();
1880:                            result.bcType = MDStatics.LONG;
1881:                            result.classType = Long.TYPE;
1882:                        }
1883:                        il.append(new PUSH(cp, -1l));
1884:                        il.append(InstructionConstants.LXOR);
1885:                        break;
1886:                    default:
1887:                        throw new NotImplementedException();
1888:                    }
1889:                    break;
1890:                default:
1891:                    throw new NotImplementedException("UnaryNode type '"
1892:                            + node.op + "' is not implemented correctly");
1893:                }
1894:                return result;
1895:            }
1896:
1897:            public Field visitCompareOpNode(CompareOpNode node, Object obj) {
1898:                return doCompare(node, getCompType(node));
1899:            }
1900:
1901:            private final int getCompType(CompareOpNode node) {
1902:                switch (node.op) {
1903:                case CompareOpNode.GT:
1904:                    return COMP_GT;
1905:                case CompareOpNode.LT:
1906:                    return COMP_LT;
1907:                case CompareOpNode.GE:
1908:                    return COMP_GE;
1909:                case CompareOpNode.LE:
1910:                    return COMP_LE;
1911:                default:
1912:                    throw BindingSupportImpl.getInstance().internal(
1913:                            "No operator of type '" + node.op + "'");
1914:                }
1915:            }
1916:
1917:            public Field visitUnaryNode(UnaryNode node, Object obj) {
1918:                node.childList.visit(this , obj);
1919:                return null;
1920:            }
1921:
1922:            public Field visitBinaryNode(BinaryNode node, Object obj) {
1923:                return null;
1924:            }
1925:
1926:            public Field visitMultiNode(Node node, Object obj) {
1927:                return null;
1928:            }
1929:
1930:            public Field visitCastNode(CastNode node, Object obj) {
1931:                return null;
1932:            }
1933:
1934:            public Field visitParamNode(ParamNode node, Object obj) {
1935:                BCField field = null;
1936:                Object paramValue = paramMap.get(node.getIdentifier());
1937:                if (paramValue == null) {
1938:                    field = new BCField();
1939:                    field.bcType = MDStatics.NULL;
1940:                    field.classType = Object.class;
1941:                } else {
1942:                    Class clazz = paramValue.getClass();
1943:                    if (OID.class.isAssignableFrom(clazz)) {
1944:                        field = new BCField();
1945:                        field.classType = clazz;
1946:                        field.bcType = MDStaticUtils.toTypeCode(clazz);
1947:                        field.ih = il.append(new ALOAD(2));
1948:                        il.append(new PUSH(cp, node.getIndex()));
1949:                        il.append(new AALOAD());
1950:                    } else {
1951:                        field = new BCField();
1952:                        field.classType = clazz;
1953:                        field.bcType = MDStaticUtils.toTypeCode(clazz);
1954:                        field.ih = il.append(new ALOAD(2));
1955:                        il.append(new PUSH(cp, node.getIndex()));
1956:                        il.append(new AALOAD());
1957:                    }
1958:                }
1959:                return field;
1960:            }
1961:
1962:            public Field visitParamNodeProxy(ParamNodeProxy node, Object obj) {
1963:                return node.getParamNode().visit(this , obj);
1964:            }
1965:
1966:            public Field visitArgNode(ArgNode node, Object obj) {
1967:                return null;
1968:            }
1969:
1970:            public Field visitArrayNode(ArrayNode node, Object obj) {
1971:                return null;
1972:            }
1973:
1974:            public Field visitImportNode(ImportNode node, Object obj) {
1975:                return null;
1976:            }
1977:
1978:            public Field visitLeafNode(LeafNode node, Object obj) {
1979:                return null;
1980:            }
1981:
1982:            public Field visitOrderNode(OrderNode node, Object obj) {
1983:                return null;
1984:            }
1985:
1986:            public Field visitVarNode(VarNode node, Object obj) {
1987:                return null;
1988:            }
1989:
1990:            public Field visitVarNodeProxy(VarNodeProxy node, Object obj) {
1991:                return node.getVarNode().visit(this , obj);
1992:            }
1993:
1994:            public Field visitReservedFieldNode(ReservedFieldNode node,
1995:                    Object obj) {
1996:                return null;
1997:            }
1998:
1999:            private class BCStateField extends BCField {
2000:                private InstructionHandle ih;
2001:                private FieldMetaData fmd;
2002:
2003:                public BCStateField(FieldMetaData fmd) {
2004:                    this .fmd = fmd;
2005:                    initFromFMD(fmd);
2006:                }
2007:
2008:                private void initFromFMD(FieldMetaData fmd) {
2009:                    this .classType = fmd.type;
2010:                    bcType = fmd.typeCode;
2011:
2012:                }
2013:
2014:                public BCStateField(InstructionHandle ih) {
2015:                    this .ih = ih;
2016:                }
2017:
2018:                public InstructionHandle getIh() {
2019:                    return ih;
2020:                }
2021:
2022:                public void setIh(InstructionHandle ih) {
2023:                    this .ih = ih;
2024:                }
2025:
2026:                public FieldMetaData getFMD() {
2027:                    return fmd;
2028:                }
2029:            }
2030:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.