1 7 34 35 package com.sun.tools.example.debug.expr; 36 37 import com.sun.jdi.*; 38 import java.util.*; 39 40 abstract class LValue { 41 42 protected Value jdiValue; 58 59 abstract Value getValue() throws InvocationException, 60 IncompatibleThreadStateException, 61 InvalidTypeException, 62 ClassNotLoadedException, 63 ParseException; 64 65 abstract void setValue0(Value value) 66 throws ParseException, InvalidTypeException, 67 ClassNotLoadedException; 68 69 abstract void invokeWith(List arguments) throws ParseException; 70 71 void setValue(Value value) throws ParseException { 72 try { 73 setValue0(value); 74 } catch (InvalidTypeException exc) { 75 throw new ParseException( 76 "Attempt to set value of incorrect type" + 77 exc); 78 } catch (ClassNotLoadedException exc) { 79 throw new ParseException( 80 "Attempt to set value before " + exc.className() + " was loaded" + 81 exc); 82 } 83 } 84 85 void setValue(LValue lval) throws ParseException { 86 setValue(lval.interiorGetValue()); 87 } 88 89 LValue memberLValue(ExpressionParser.GetFrame frameGetter, 90 String fieldName) throws ParseException { 91 try { 92 return memberLValue(fieldName, frameGetter.get().thread()); 93 } catch (IncompatibleThreadStateException exc) { 94 throw new ParseException("Thread not suspended"); 95 } 96 } 97 98 LValue memberLValue(String fieldName, ThreadReference thread) throws ParseException { 99 100 Value val = interiorGetValue(); 101 if ((val instanceof ArrayReference) && 102 "length".equals(fieldName)){ 103 return new LValueArrayLength((ArrayReference)val); 104 } 105 return new LValueInstanceMember(val, fieldName, thread); 106 } 107 108 Value getMassagedValue(ExpressionParser.GetFrame frameGetter) throws ParseException { 111 Value vv = interiorGetValue(); 112 113 if (vv instanceof ObjectReference && 116 !(vv instanceof StringReference) && 117 !(vv instanceof ArrayReference)) { 118 StackFrame frame; 119 try { 120 frame = frameGetter.get(); 121 } catch (IncompatibleThreadStateException exc) { 122 throw new ParseException("Thread not suspended"); 123 } 124 125 ThreadReference thread = frame.thread(); 126 LValue toStringMember = memberLValue("toString", thread); 127 toStringMember.invokeWith(new ArrayList()); 128 return toStringMember.interiorGetValue(); 129 } 130 return vv; 131 } 132 133 Value interiorGetValue() throws ParseException { 134 Value value; 135 try { 136 value = getValue(); 137 } catch (InvocationException e) { 138 throw new ParseException("Unable to complete expression. Exception " + 139 e.exception() + " thrown"); 140 } catch (IncompatibleThreadStateException itse) { 141 throw new ParseException("Unable to complete expression. Thread " + 142 "not suspended for method invoke"); 143 } catch (InvalidTypeException ite) { 144 throw new ParseException("Unable to complete expression. Method " + 145 "argument type mismatch"); 146 } catch (ClassNotLoadedException tnle) { 147 throw new ParseException("Unable to complete expression. Method " + 148 "argument type " + tnle.className() + 149 " not yet loaded"); 150 } 151 return value; 152 } 153 154 LValue arrayElementLValue(LValue lval) throws ParseException { 155 Value indexValue = lval.interiorGetValue(); 156 int index; 157 if ( (indexValue instanceof IntegerValue) || 158 (indexValue instanceof ShortValue) || 159 (indexValue instanceof ByteValue) || 160 (indexValue instanceof CharValue) ) { 161 index = ((PrimitiveValue)indexValue).intValue(); 162 } else { 163 throw new ParseException("Array index must be a integer type"); 164 } 165 return new LValueArrayElement(interiorGetValue(), index); 166 } 167 168 public String toString() { 169 try { 170 return interiorGetValue().toString(); 171 } catch (ParseException e) { 172 return "<Parse Exception>"; 173 } 174 } 175 176 static final int STATIC = 0; 177 static final int INSTANCE = 1; 178 179 static Field fieldByName(ReferenceType refType, String name, int kind) { 180 186 Field field = refType.fieldByName(name); 187 if (field != null) { 188 boolean isStatic = field.isStatic(); 189 if (((kind == STATIC) && !isStatic) || 190 ((kind == INSTANCE) && isStatic)) { 191 field = null; 192 } 193 } 194 200 return field; 201 } 202 203 static List methodsByName(ReferenceType refType, String name, int kind) { 204 List list = refType.methodsByName(name); 205 Iterator iter = list.iterator(); 206 while (iter.hasNext()) { 207 Method method = (Method)iter.next(); 208 boolean isStatic = method.isStatic(); 209 if (((kind == STATIC) && !isStatic) || 210 ((kind == INSTANCE) && isStatic)) { 211 iter.remove(); 212 } 213 } 214 return list; 215 } 216 217 static List primitiveTypeNames = new ArrayList(); 218 static { 219 primitiveTypeNames.add("boolean"); 220 primitiveTypeNames.add("byte"); 221 primitiveTypeNames.add("char"); 222 primitiveTypeNames.add("short"); 223 primitiveTypeNames.add("int"); 224 primitiveTypeNames.add("long"); 225 primitiveTypeNames.add("float"); 226 primitiveTypeNames.add("double"); 227 } 228 229 230 static final int SAME = 0; 231 static final int ASSIGNABLE = 1; 232 static final int DIFFERENT = 2; 233 243 static int argumentsMatch(List argTypes, List arguments) { 244 if (argTypes.size() != arguments.size()) { 245 return DIFFERENT; 246 } 247 248 Iterator typeIter = argTypes.iterator(); 249 Iterator valIter = arguments.iterator(); 250 int result = SAME; 251 252 while (typeIter.hasNext()) { 256 Type argType = (Type)typeIter.next(); 257 Value value = (Value)valIter.next(); 258 if (value == null) { 259 if (primitiveTypeNames.contains(argType.name())) { 261 return DIFFERENT; 262 } 263 } 266 if (!value.type().equals(argType)) { 267 if (isAssignableTo(value.type(), argType)) { 268 result = ASSIGNABLE; 269 } else { 270 return DIFFERENT; 271 } 272 } 273 } 274 return result; 275 } 276 277 278 281 static boolean isComponentAssignable(Type fromType, Type toType) { 282 if (fromType instanceof PrimitiveType) { 283 return fromType.equals(toType); 286 } 287 if (toType instanceof PrimitiveType) { 288 return false; 289 } 290 return isAssignableTo(fromType, toType); 293 } 294 295 static boolean isArrayAssignableTo(ArrayType fromType, Type toType) { 296 if (toType instanceof ArrayType) { 297 try { 298 Type toComponentType = ((ArrayType)toType).componentType(); 299 return isComponentAssignable(fromType.componentType(), toComponentType); 300 } catch (ClassNotLoadedException e) { 301 return false; 304 } 305 } 306 if (toType instanceof InterfaceType) { 307 return toType.name().equals("java.lang.Cloneable"); 309 } 310 return toType.name().equals("java.lang.Object"); 312 } 313 314 static boolean isAssignableTo(Type fromType, Type toType) { 315 if (fromType.equals(toType)) { 316 return true; 317 } 318 319 if (fromType instanceof BooleanType) { 321 if (toType instanceof BooleanType) { 322 return true; 323 } 324 return false; 325 } 326 if (toType instanceof BooleanType) { 327 return false; 328 } 329 330 if (fromType instanceof PrimitiveType) { 332 if (toType instanceof PrimitiveType) { 333 return true; 334 } 335 return false; 336 } 337 if (toType instanceof PrimitiveType) { 338 return false; 339 } 340 341 if (fromType instanceof ArrayType) { 343 return isArrayAssignableTo((ArrayType)fromType, toType); 344 } 345 List interfaces; 346 if (fromType instanceof ClassType) { 347 ClassType superclazz = ((ClassType)fromType).superclass(); 348 if ((superclazz != null) && isAssignableTo(superclazz, toType)) { 349 return true; 350 } 351 interfaces = ((ClassType)fromType).interfaces(); 352 } else { 353 interfaces = ((InterfaceType)fromType).superinterfaces(); 355 } 356 Iterator iter = interfaces.iterator(); 357 while (iter.hasNext()) { 358 InterfaceType interfaze = (InterfaceType)iter.next(); 359 if (isAssignableTo(interfaze, toType)) { 360 return true; 361 } 362 } 363 return false; 364 } 365 366 static Method resolveOverload(List overloads, List arguments) 367 throws ParseException { 368 369 if (overloads.size() == 1) { 374 return (Method)overloads.get(0); 375 } 376 377 Iterator iter = overloads.iterator(); 387 Method retVal = null; 388 int assignableCount = 0; 389 while (iter.hasNext()) { 390 Method mm = (Method)iter.next(); 391 List argTypes; 392 try { 393 argTypes = mm.argumentTypes(); 394 } catch (ClassNotLoadedException ee) { 395 continue; 399 } 400 int compare = argumentsMatch(argTypes, arguments); 401 if (compare == SAME) { 402 return mm; 403 } 404 if (compare == DIFFERENT) { 405 continue; 406 } 407 retVal = mm; 409 assignableCount++; 410 } 411 412 if (retVal != null) { 416 if (assignableCount == 1) { 417 return retVal; 418 } 419 throw new ParseException("Arguments match multiple methods"); 420 } 421 throw new ParseException("Arguments match no method"); 422 } 423 424 private static class LValueLocal extends LValue { 425 final StackFrame frame; 426 final LocalVariable var; 427 428 LValueLocal(StackFrame frame, LocalVariable var) { 429 this.frame = frame; 430 this.var = var; 431 } 432 433 Value getValue() { 434 if (jdiValue == null) { 435 jdiValue = frame.getValue(var); 436 } 437 return jdiValue; 438 } 439 440 void setValue0(Value val) throws InvalidTypeException, 441 ClassNotLoadedException { 442 frame.setValue(var, val); 443 jdiValue = val; 444 } 445 446 void invokeWith(List arguments) throws ParseException { 447 throw new ParseException(var.name() + " is not a method"); 448 } 449 } 450 451 private static class LValueInstanceMember extends LValue { 452 final ObjectReference obj; 453 final ThreadReference thread; 454 final Field matchingField; 455 final List overloads; 456 Method matchingMethod = null; 457 List methodArguments = null; 458 459 LValueInstanceMember(Value value, 460 String memberName, 461 ThreadReference thread) throws ParseException { 462 if (!(value instanceof ObjectReference)) { 463 throw new ParseException( 464 "Cannot access field of primitive type: " + value); 465 } 466 this.obj = (ObjectReference)value; 467 this.thread = thread; 468 ReferenceType refType = obj.referenceType(); 469 473 matchingField = LValue.fieldByName(refType, memberName, 474 LValue.INSTANCE); 475 overloads = LValue.methodsByName(refType, memberName, 476 LValue.INSTANCE); 477 if ((matchingField == null) && overloads.size() == 0) { 478 throw new ParseException("No instance field or method with the name " 479 + memberName + " in " + refType.name()); 480 } 481 } 482 483 Value getValue() throws InvocationException, InvalidTypeException, 484 ClassNotLoadedException, IncompatibleThreadStateException, 485 ParseException { 486 if (jdiValue != null) { 487 return jdiValue; 488 } 489 if (matchingMethod == null) { 490 if (matchingField == null) { 491 throw new ParseException("No such field in " + obj.referenceType().name()); 492 } 493 return jdiValue = obj.getValue(matchingField); 494 } else { 495 return jdiValue = obj.invokeMethod(thread, matchingMethod, methodArguments, 0); 496 } 497 } 498 499 void setValue0(Value val) throws ParseException, 500 InvalidTypeException, 501 ClassNotLoadedException { 502 if (matchingMethod != null) { 503 throw new ParseException("Cannot assign to a method invocation"); 504 } 505 obj.setValue(matchingField, val); 506 jdiValue = val; 507 } 508 509 void invokeWith(List arguments) throws ParseException { 510 if (matchingMethod != null) { 511 throw new ParseException("Invalid consecutive invocations"); 512 } 513 methodArguments = arguments; 514 matchingMethod = LValue.resolveOverload(overloads, arguments); 515 } 516 } 517 518 private static class LValueStaticMember extends LValue { 519 final ReferenceType refType; 520 final ThreadReference thread; 521 final Field matchingField; 522 final List overloads; 523 Method matchingMethod = null; 524 List methodArguments = null; 525 526 LValueStaticMember(ReferenceType refType, 527 String memberName, 528 ThreadReference thread) throws ParseException { 529 this.refType = refType; 530 this.thread = thread; 531 535 matchingField = LValue.fieldByName(refType, memberName, 536 LValue.STATIC); 537 overloads = LValue.methodsByName(refType, memberName, 538 LValue.STATIC); 539 if ((matchingField == null) && overloads.size() == 0) { 540 throw new ParseException("No static field or method with the name " 541 + memberName + " in " + refType.name()); 542 } 543 } 544 545 Value getValue() throws InvocationException, InvalidTypeException, 546 ClassNotLoadedException, IncompatibleThreadStateException, 547 ParseException { 548 if (jdiValue != null) { 549 return jdiValue; 550 } 551 if (matchingMethod == null) { 552 return jdiValue = refType.getValue(matchingField); 553 } else if (refType instanceof ClassType) { 554 ClassType clazz = (ClassType)refType; 555 return jdiValue = clazz.invokeMethod(thread, matchingMethod, methodArguments, 0); 556 } else { 557 throw new InvalidTypeException("Cannot invoke static method on " + 558 refType.name()); 559 } 560 } 561 562 void setValue0(Value val) 563 throws ParseException, InvalidTypeException, 564 ClassNotLoadedException { 565 if (matchingMethod != null) { 566 throw new ParseException("Cannot assign to a method invocation"); 567 } 568 if (!(refType instanceof ClassType)) { 569 throw new ParseException( 570 "Cannot set interface field: " + refType); 571 } 572 ((ClassType)refType).setValue(matchingField, val); 573 jdiValue = val; 574 } 575 576 void invokeWith(List arguments) throws ParseException { 577 if (matchingMethod != null) { 578 throw new ParseException("Invalid consecutive invocations"); 579 } 580 methodArguments = arguments; 581 matchingMethod = LValue.resolveOverload(overloads, arguments); 582 } 583 } 584 585 private static class LValueArrayLength extends LValue { 586 598 final ArrayReference arrayRef; 599 LValueArrayLength (ArrayReference value) { 600 this.arrayRef = value; 601 } 602 603 Value getValue() { 604 if (jdiValue == null) { 605 jdiValue = arrayRef.virtualMachine().mirrorOf(arrayRef.length()); 606 } 607 return jdiValue; 608 } 609 610 void setValue0(Value value) throws ParseException { 611 throw new ParseException("Cannot set constant: " + value); 612 } 613 614 void invokeWith(List arguments) throws ParseException { 615 throw new ParseException("Array element is not a method"); 616 } 617 } 618 619 private static class LValueArrayElement extends LValue { 620 final ArrayReference array; 621 final int index; 622 623 LValueArrayElement(Value value, int index) throws ParseException { 624 if (!(value instanceof ArrayReference)) { 625 throw new ParseException( 626 "Must be array type: " + value); 627 } 628 this.array = (ArrayReference)value; 629 this.index = index; 630 } 631 632 Value getValue() { 633 if (jdiValue == null) { 634 jdiValue = array.getValue(index); 635 } 636 return jdiValue; 637 } 638 639 void setValue0(Value val) throws InvalidTypeException, 640 ClassNotLoadedException { 641 array.setValue(index, val); 642 jdiValue = val; 643 } 644 645 void invokeWith(List arguments) throws ParseException { 646 throw new ParseException("Array element is not a method"); 647 } 648 } 649 650 private static class LValueConstant extends LValue { 651 final Value value; 652 653 LValueConstant(Value value) { 654 this.value = value; 655 } 656 657 Value getValue() { 658 if (jdiValue == null) { 659 jdiValue = value; 660 } 661 return jdiValue; 662 } 663 664 void setValue0(Value val) throws ParseException { 665 throw new ParseException("Cannot set constant: " + value); 666 } 667 668 void invokeWith(List arguments) throws ParseException { 669 throw new ParseException("Constant is not a method"); 670 } 671 } 672 673 static LValue make(VirtualMachine vm, boolean val) { 674 return new LValueConstant(vm.mirrorOf(val)); 675 } 676 677 static LValue make(VirtualMachine vm, byte val) { 678 return new LValueConstant(vm.mirrorOf(val)); 679 } 680 681 static LValue make(VirtualMachine vm, char val) { 682 return new LValueConstant(vm.mirrorOf(val)); 683 } 684 685 static LValue make(VirtualMachine vm, short val) { 686 return new LValueConstant(vm.mirrorOf(val)); 687 } 688 689 static LValue make(VirtualMachine vm, int val) { 690 return new LValueConstant(vm.mirrorOf(val)); 691 } 692 693 static LValue make(VirtualMachine vm, long val) { 694 return new LValueConstant(vm.mirrorOf(val)); 695 } 696 697 static LValue make(VirtualMachine vm, float val) { 698 return new LValueConstant(vm.mirrorOf(val)); 699 } 700 701 static LValue make(VirtualMachine vm, double val) { 702 return new LValueConstant(vm.mirrorOf(val)); 703 } 704 705 static LValue make(VirtualMachine vm, String val) throws ParseException { 706 return new LValueConstant(vm.mirrorOf(val)); 707 } 708 709 static LValue makeBoolean(VirtualMachine vm, Token token) { 710 return make(vm, token.image.charAt(0) == 't'); 711 } 712 713 static LValue makeCharacter(VirtualMachine vm, Token token) { 714 return make(vm, token.image.charAt(1)); 715 } 716 717 static LValue makeFloat(VirtualMachine vm, Token token) { 718 return make(vm, Float.valueOf(token.image).floatValue()); 719 } 720 721 static LValue makeDouble(VirtualMachine vm, Token token) { 722 return make(vm, Double.valueOf(token.image).doubleValue()); 723 } 724 725 static LValue makeInteger(VirtualMachine vm, Token token) { 726 return make(vm, Integer.parseInt(token.image)); 727 } 728 729 static LValue makeShort(VirtualMachine vm, Token token) { 730 return make(vm, Short.parseShort(token.image)); 731 } 732 733 static LValue makeLong(VirtualMachine vm, Token token) { 734 return make(vm, Long.parseLong(token.image)); 735 } 736 737 static LValue makeByte(VirtualMachine vm, Token token) { 738 return make(vm, Byte.parseByte(token.image)); 739 } 740 741 static LValue makeString(VirtualMachine vm, 742 Token token) throws ParseException { 743 int len = token.image.length(); 744 return make(vm, token.image.substring(1,len-1)); 745 } 746 747 static LValue makeNull(VirtualMachine vm, 748 Token token) throws ParseException { 749 return new LValueConstant(null); 750 } 751 752 static LValue makeThisObject(VirtualMachine vm, 753 ExpressionParser.GetFrame frameGetter, 754 Token token) throws ParseException { 755 if (frameGetter == null) { 756 throw new ParseException("No current thread"); 757 } else { 758 try { 759 StackFrame frame = frameGetter.get(); 760 ObjectReference thisObject = frame.thisObject(); 761 762 if (thisObject==null) { 763 throw new ParseException( 764 "No 'this'. In native or static method"); 765 } else { 766 return new LValueConstant(thisObject); 767 } 768 } catch (IncompatibleThreadStateException exc) { 769 throw new ParseException("Thread not suspended"); 770 } 771 } 772 } 773 774 static LValue makeNewObject(VirtualMachine vm, 775 ExpressionParser.GetFrame frameGetter, 776 String className, List arguments) throws ParseException { 777 List classes = vm.classesByName(className); 778 if (classes.size() == 0) { 779 throw new ParseException("No class named: " + className); 780 } 781 782 if (classes.size() > 1) { 783 throw new ParseException("More than one class named: " + 784 className); 785 } 786 ReferenceType refType = (ReferenceType)classes.get(0); 787 788 789 if (!(refType instanceof ClassType)) { 790 throw new ParseException("Cannot create instance of interface " + 791 className); 792 } 793 794 ClassType classType = (ClassType)refType; 795 List methods = new ArrayList(classType.methods()); Iterator iter = methods.iterator(); 797 while (iter.hasNext()) { 798 Method method = (Method)iter.next(); 799 if (!method.isConstructor()) { 800 iter.remove(); 801 } 802 } 803 Method constructor = LValue.resolveOverload(methods, arguments); 804 805 ObjectReference newObject; 806 try { 807 ThreadReference thread = frameGetter.get().thread(); 808 newObject = classType.newInstance(thread, constructor, arguments, 0); 809 } catch (InvocationException ie) { 810 throw new ParseException("Exception in " + className + " constructor: " + 811 ie.exception().referenceType().name()); 812 } catch (IncompatibleThreadStateException exc) { 813 throw new ParseException("Thread not suspended"); 814 } catch (Exception e) { 815 818 throw new ParseException("Unable to create " + className + " instance"); 819 } 820 return new LValueConstant(newObject); 821 } 822 823 private static LValue nFields(LValue lval, 824 StringTokenizer izer, 825 ThreadReference thread) 826 throws ParseException { 827 if (!izer.hasMoreTokens()) { 828 return lval; 829 } else { 830 return nFields(lval.memberLValue(izer.nextToken(), thread), izer, thread); 831 } 832 } 833 834 static LValue makeName(VirtualMachine vm, 835 ExpressionParser.GetFrame frameGetter, 836 String name) throws ParseException { 837 StringTokenizer izer = new StringTokenizer(name, "."); 838 String first = izer.nextToken(); 839 if (frameGetter != null) { 841 try { 842 StackFrame frame = frameGetter.get(); 843 ThreadReference thread = frame.thread(); 844 LocalVariable var; 845 try { 846 var = frame.visibleVariableByName(first); 847 } catch (AbsentInformationException e) { 848 var = null; 849 } 850 if (var != null) { 851 return nFields(new LValueLocal(frame, var), izer, thread); 852 } else { 853 ObjectReference thisObject = frame.thisObject(); 854 if (thisObject != null) { 855 LValue thisLValue = new LValueConstant(thisObject); 857 LValue fv; 858 try { 859 fv = thisLValue.memberLValue(first, thread); 860 } catch (ParseException exc) { 861 fv = null; 862 } 863 if (fv != null) { 864 return nFields(fv, izer, thread); 865 } 866 } 867 } 868 while (izer.hasMoreTokens()) { 870 List classes = vm.classesByName(first); 871 if (classes.size() > 0) { 872 if (classes.size() > 1) { 873 throw new ParseException("More than one class named: " + 874 first); 875 } else { 876 ReferenceType refType = (ReferenceType)classes.get(0); 877 LValue lval = new LValueStaticMember(refType, 878 izer.nextToken(), thread); 879 return nFields(lval, izer, thread); 880 } 881 } 882 first = first + '.' + izer.nextToken(); 883 } 884 } catch (IncompatibleThreadStateException exc) { 885 throw new ParseException("Thread not suspended"); 886 } 887 } 888 throw new ParseException("Name unknown: " + name); 889 } 890 891 static String stringValue(LValue lval, ExpressionParser.GetFrame frameGetter 892 ) throws ParseException { 893 Value val = lval.getMassagedValue(frameGetter); 894 if (val == null) { 895 return "null"; 896 } 897 if (val instanceof StringReference) { 898 return ((StringReference)val).value(); 899 } 900 return val.toString(); } 902 903 static LValue booleanOperation(VirtualMachine vm, Token token, 904 LValue rightL, 905 LValue leftL) throws ParseException { 906 String op = token.image; 907 Value right = rightL.interiorGetValue(); 908 Value left = leftL.interiorGetValue(); 909 if ( !(right instanceof PrimitiveValue) || 910 !(left instanceof PrimitiveValue) ) { 911 if (op.equals("==")) { 912 return make(vm, right.equals(left)); 913 } else if (op.equals("!=")) { 914 return make(vm, !right.equals(left)); 915 } else { 916 throw new ParseException("Operands or '" + op + 917 "' must be primitive"); 918 } 919 } 920 double rr = ((PrimitiveValue)right).doubleValue(); 922 double ll = ((PrimitiveValue)left).doubleValue(); 923 boolean res; 924 if (op.equals("<")) { 925 res = rr < ll; 926 } else if (op.equals(">")) { 927 res = rr > ll; 928 } else if (op.equals("<=")) { 929 res = rr <= ll; 930 } else if (op.equals(">=")) { 931 res = rr >= ll; 932 } else if (op.equals("==")) { 933 res = rr == ll; 934 } else if (op.equals("!=")) { 935 res = rr != ll; 936 } else { 937 throw new ParseException("Unknown operation: " + op); 938 } 939 return make(vm, res); 940 } 941 942 static LValue operation(VirtualMachine vm, Token token, 943 LValue rightL, LValue leftL, 944 ExpressionParser.GetFrame frameGetter 945 ) throws ParseException { 946 String op = token.image; 947 Value right = rightL.interiorGetValue(); 948 Value left = leftL.interiorGetValue(); 949 if ((right instanceof StringReference) || 950 (left instanceof StringReference)) { 951 if (op.equals("+")) { 952 return make(vm, stringValue(rightL, frameGetter) + 955 stringValue(leftL, frameGetter)); 956 } 957 } 958 if ((right instanceof ObjectReference) || 959 (left instanceof ObjectReference)) { 960 if (op.equals("==")) { 961 return make(vm, right.equals(left)); 962 } else if (op.equals("!=")) { 963 return make(vm, !right.equals(left)); 964 } else { 965 throw new ParseException("Invalid operation '" + 966 op + "' on an Object"); 967 } 968 } 969 if ((right instanceof BooleanValue) || 970 (left instanceof BooleanValue)) { 971 throw new ParseException("Invalid operation '" + 972 op + "' on a Boolean"); 973 } 974 PrimitiveValue primRight = (PrimitiveValue)right; 976 PrimitiveValue primLeft = (PrimitiveValue)left; 977 if ((primRight instanceof DoubleValue) || 978 (primLeft instanceof DoubleValue)) { 979 double rr = primRight.doubleValue(); 980 double ll = primLeft.doubleValue(); 981 double res; 982 if (op.equals("+")) { 983 res = rr + ll; 984 } else if (op.equals("-")) { 985 res = rr - ll; 986 } else if (op.equals("*")) { 987 res = rr * ll; 988 } else if (op.equals("/")) { 989 res = rr / ll; 990 } else { 991 throw new ParseException("Unknown operation: " + op); 992 } 993 return make(vm, res); 994 } 995 if ((primRight instanceof FloatValue) || 996 (primLeft instanceof FloatValue)) { 997 float rr = primRight.floatValue(); 998 float ll = primLeft.floatValue(); 999 float res; 1000 if (op.equals("+")) { 1001 res = rr + ll; 1002 } else if (op.equals("-")) { 1003 res = rr - ll; 1004 } else if (op.equals("*")) { 1005 res = rr * ll; 1006 } else if (op.equals("/")) { 1007 res = rr / ll; 1008 } else { 1009 throw new ParseException("Unknown operation: " + op); 1010 } 1011 return make(vm, res); 1012 } 1013 if ((primRight instanceof LongValue) || 1014 (primLeft instanceof LongValue)) { 1015 long rr = primRight.longValue(); 1016 long ll = primLeft.longValue(); 1017 long res; 1018 if (op.equals("+")) { 1019 res = rr + ll; 1020 } else if (op.equals("-")) { 1021 res = rr - ll; 1022 } else if (op.equals("*")) { 1023 res = rr * ll; 1024 } else if (op.equals("/")) { 1025 res = rr / ll; 1026 } else { 1027 throw new ParseException("Unknown operation: " + op); 1028 } 1029 return make(vm, res); 1030 } else { 1031 int rr = primRight.intValue(); 1032 int ll = primLeft.intValue(); 1033 int res; 1034 if (op.equals("+")) { 1035 res = rr + ll; 1036 } else if (op.equals("-")) { 1037 res = rr - ll; 1038 } else if (op.equals("*")) { 1039 res = rr * ll; 1040 } else if (op.equals("/")) { 1041 res = rr / ll; 1042 } else { 1043 throw new ParseException("Unknown operation: " + op); 1044 } 1045 return make(vm, res); 1046 } 1047 } 1048} 1049 | Popular Tags |