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: }
|