jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java
changeset 51 6fe31bc95bbc
parent 2 90ce3da70b43
child 715 f16baef3a20e
equal deleted inserted replaced
50:a437b3f9d7f4 51:6fe31bc95bbc
   189                                              (field != null));
   189                                              (field != null));
   190 ***/
   190 ***/
   191         return field;
   191         return field;
   192     }
   192     }
   193 
   193 
   194     static List methodsByName(ReferenceType refType, String name, int kind) {
   194     static List<Method> methodsByName(ReferenceType refType,
   195         List list = refType.methodsByName(name);
   195                                       String name, int kind) {
   196         Iterator iter = list.iterator();
   196         List<Method> list = refType.methodsByName(name);
       
   197         Iterator<Method> iter = list.iterator();
   197         while (iter.hasNext()) {
   198         while (iter.hasNext()) {
   198             Method method = (Method)iter.next();
   199             Method method = iter.next();
   199             boolean isStatic = method.isStatic();
   200             boolean isStatic = method.isStatic();
   200             if (((kind == STATIC) && !isStatic) ||
   201             if (((kind == STATIC) && !isStatic) ||
   201                 ((kind == INSTANCE) && isStatic)) {
   202                 ((kind == INSTANCE) && isStatic)) {
   202                 iter.remove();
   203                 iter.remove();
   203             }
   204             }
   229      * from the type of the argument value.
   230      * from the type of the argument value.
   230      * DIFFERENT means that in at least one pair, the
   231      * DIFFERENT means that in at least one pair, the
   231      * argType is not assignable from the type of the argument value.
   232      * argType is not assignable from the type of the argument value.
   232      * IE, one is an Apple and the other is an Orange.
   233      * IE, one is an Apple and the other is an Orange.
   233      */
   234      */
   234     static int argumentsMatch(List argTypes, List arguments) {
   235     static int argumentsMatch(List<Type> argTypes, List<Value> arguments) {
   235         if (argTypes.size() != arguments.size()) {
   236         if (argTypes.size() != arguments.size()) {
   236             return DIFFERENT;
   237             return DIFFERENT;
   237         }
   238         }
   238 
   239 
   239         Iterator typeIter = argTypes.iterator();
   240         Iterator<Type> typeIter = argTypes.iterator();
   240         Iterator valIter = arguments.iterator();
   241         Iterator<Value> valIter = arguments.iterator();
   241         int result = SAME;
   242         int result = SAME;
   242 
   243 
   243         // If any pair aren't the same, change the
   244         // If any pair aren't the same, change the
   244         // result to ASSIGNABLE.  If any pair aren't
   245         // result to ASSIGNABLE.  If any pair aren't
   245         // assignable, return DIFFERENT
   246         // assignable, return DIFFERENT
   246         while (typeIter.hasNext()) {
   247         while (typeIter.hasNext()) {
   247             Type argType = (Type)typeIter.next();
   248             Type argType = typeIter.next();
   248             Value value = (Value)valIter.next();
   249             Value value = valIter.next();
   249             if (value == null) {
   250             if (value == null) {
   250                 // Null values can be passed to any non-primitive argument
   251                 // Null values can be passed to any non-primitive argument
   251                 if (primitiveTypeNames.contains(argType.name())) {
   252                 if (primitiveTypeNames.contains(argType.name())) {
   252                     return DIFFERENT;
   253                     return DIFFERENT;
   253                 }
   254                 }
   331 
   332 
   332         // neither one is primitive.
   333         // neither one is primitive.
   333         if (fromType instanceof ArrayType) {
   334         if (fromType instanceof ArrayType) {
   334             return isArrayAssignableTo((ArrayType)fromType, toType);
   335             return isArrayAssignableTo((ArrayType)fromType, toType);
   335         }
   336         }
   336         List interfaces;
   337         List<InterfaceType> interfaces;
   337         if (fromType instanceof ClassType) {
   338         if (fromType instanceof ClassType) {
   338             ClassType superclazz = ((ClassType)fromType).superclass();
   339             ClassType superclazz = ((ClassType)fromType).superclass();
   339             if ((superclazz != null) && isAssignableTo(superclazz, toType)) {
   340             if ((superclazz != null) && isAssignableTo(superclazz, toType)) {
   340                 return true;
   341                 return true;
   341             }
   342             }
   342             interfaces = ((ClassType)fromType).interfaces();
   343             interfaces = ((ClassType)fromType).interfaces();
   343         } else {
   344         } else {
   344             // fromType must be an InterfaceType
   345             // fromType must be an InterfaceType
   345             interfaces = ((InterfaceType)fromType).superinterfaces();
   346             interfaces = ((InterfaceType)fromType).superinterfaces();
   346         }
   347         }
   347         Iterator iter = interfaces.iterator();
   348         for (InterfaceType interfaze : interfaces) {
   348         while (iter.hasNext()) {
       
   349             InterfaceType interfaze = (InterfaceType)iter.next();
       
   350             if (isAssignableTo(interfaze, toType)) {
   349             if (isAssignableTo(interfaze, toType)) {
   351                 return true;
   350                 return true;
   352             }
   351             }
   353         }
   352         }
   354         return false;
   353         return false;
   355     }
   354     }
   356 
   355 
   357     static Method resolveOverload(List overloads, List arguments)
   356     static Method resolveOverload(List<Method> overloads,
       
   357                                   List<Value> arguments)
   358                                        throws ParseException {
   358                                        throws ParseException {
   359 
   359 
   360         // If there is only one method to call, we'll just choose
   360         // If there is only one method to call, we'll just choose
   361         // that without looking at the args.  If they aren't right
   361         // that without looking at the args.  If they aren't right
   362         // the invoke will return a better error message than we
   362         // the invoke will return a better error message than we
   363         // could generate here.
   363         // could generate here.
   364         if (overloads.size() == 1) {
   364         if (overloads.size() == 1) {
   365             return (Method)overloads.get(0);
   365             return overloads.get(0);
   366         }
   366         }
   367 
   367 
   368         // Resolving overloads is beyond the scope of this exercise.
   368         // Resolving overloads is beyond the scope of this exercise.
   369         // So, we will look for a method that matches exactly the
   369         // So, we will look for a method that matches exactly the
   370         // types of the arguments.  If we can't find one, then
   370         // types of the arguments.  If we can't find one, then
   372         // from the arg types, we will use that.  Otherwise,
   372         // from the arg types, we will use that.  Otherwise,
   373         // it is an error.  We won't guess which of multiple possible
   373         // it is an error.  We won't guess which of multiple possible
   374         // methods to call. And, since casts aren't implemented,
   374         // methods to call. And, since casts aren't implemented,
   375         // the user can't use them to pick a particular overload to call.
   375         // the user can't use them to pick a particular overload to call.
   376         // IE, the user is out of luck in this case.
   376         // IE, the user is out of luck in this case.
   377         Iterator iter = overloads.iterator();
       
   378         Method retVal = null;
   377         Method retVal = null;
   379         int assignableCount = 0;
   378         int assignableCount = 0;
   380         while (iter.hasNext()) {
   379         for (Method mm : overloads) {
   381             Method mm = (Method)iter.next();
   380             List<Type> argTypes;
   382             List argTypes;
       
   383             try {
   381             try {
   384                 argTypes = mm.argumentTypes();
   382                 argTypes = mm.argumentTypes();
   385             } catch (ClassNotLoadedException ee) {
   383             } catch (ClassNotLoadedException ee) {
   386                 // This probably won't happen for the
   384                 // This probably won't happen for the
   387                 // method that we are really supposed to
   385                 // method that we are really supposed to
   441 
   439 
   442     private static class LValueInstanceMember extends LValue {
   440     private static class LValueInstanceMember extends LValue {
   443         final ObjectReference obj;
   441         final ObjectReference obj;
   444         final ThreadReference thread;
   442         final ThreadReference thread;
   445         final Field matchingField;
   443         final Field matchingField;
   446         final List overloads;
   444         final List<Method> overloads;
   447         Method matchingMethod = null;
   445         Method matchingMethod = null;
   448         List<Value> methodArguments = null;
   446         List<Value> methodArguments = null;
   449 
   447 
   450         LValueInstanceMember(Value value,
   448         LValueInstanceMember(Value value,
   451                             String memberName,
   449                             String memberName,
   508 
   506 
   509     private static class LValueStaticMember extends LValue {
   507     private static class LValueStaticMember extends LValue {
   510         final ReferenceType refType;
   508         final ReferenceType refType;
   511         final ThreadReference thread;
   509         final ThreadReference thread;
   512         final Field matchingField;
   510         final Field matchingField;
   513         final List overloads;
   511         final List<Method> overloads;
   514         Method matchingMethod = null;
   512         Method matchingMethod = null;
   515         List<Value> methodArguments = null;
   513         List<Value> methodArguments = null;
   516 
   514 
   517         LValueStaticMember(ReferenceType refType,
   515         LValueStaticMember(ReferenceType refType,
   518                           String memberName,
   516                           String memberName,
   763     }
   761     }
   764 
   762 
   765     static LValue makeNewObject(VirtualMachine vm,
   763     static LValue makeNewObject(VirtualMachine vm,
   766                                  ExpressionParser.GetFrame frameGetter,
   764                                  ExpressionParser.GetFrame frameGetter,
   767                                 String className, List<Value> arguments) throws ParseException {
   765                                 String className, List<Value> arguments) throws ParseException {
   768         List classes = vm.classesByName(className);
   766         List<ReferenceType> classes = vm.classesByName(className);
   769         if (classes.size() == 0) {
   767         if (classes.size() == 0) {
   770             throw new ParseException("No class named: " + className);
   768             throw new ParseException("No class named: " + className);
   771         }
   769         }
   772 
   770 
   773         if (classes.size() > 1) {
   771         if (classes.size() > 1) {
   774             throw new ParseException("More than one class named: " +
   772             throw new ParseException("More than one class named: " +
   775                                      className);
   773                                      className);
   776         }
   774         }
   777         ReferenceType refType = (ReferenceType)classes.get(0);
   775         ReferenceType refType = classes.get(0);
   778 
   776 
   779 
   777 
   780         if (!(refType instanceof ClassType)) {
   778         if (!(refType instanceof ClassType)) {
   781             throw new ParseException("Cannot create instance of interface " +
   779             throw new ParseException("Cannot create instance of interface " +
   782                                      className);
   780                                      className);
   783         }
   781         }
   784 
   782 
   785         ClassType classType = (ClassType)refType;
   783         ClassType classType = (ClassType)refType;
   786         List<Method> methods = new ArrayList<Method>(classType.methods()); // writable
   784         List<Method> methods = new ArrayList<Method>(classType.methods()); // writable
   787         Iterator iter = methods.iterator();
   785         Iterator<Method> iter = methods.iterator();
   788         while (iter.hasNext()) {
   786         while (iter.hasNext()) {
   789             Method method = (Method)iter.next();
   787             Method method = iter.next();
   790             if (!method.isConstructor()) {
   788             if (!method.isConstructor()) {
   791                 iter.remove();
   789                 iter.remove();
   792             }
   790             }
   793         }
   791         }
   794         Method constructor = LValue.resolveOverload(methods, arguments);
   792         Method constructor = LValue.resolveOverload(methods, arguments);
   856                         }
   854                         }
   857                     }
   855                     }
   858                 }
   856                 }
   859                 // check for class name
   857                 // check for class name
   860                 while (izer.hasMoreTokens()) {
   858                 while (izer.hasMoreTokens()) {
   861                     List classes = vm.classesByName(first);
   859                     List<ReferenceType> classes = vm.classesByName(first);
   862                     if (classes.size() > 0) {
   860                     if (classes.size() > 0) {
   863                         if (classes.size() > 1) {
   861                         if (classes.size() > 1) {
   864                             throw new ParseException("More than one class named: " +
   862                             throw new ParseException("More than one class named: " +
   865                                                      first);
   863                                                      first);
   866                         } else {
   864                         } else {
   867                             ReferenceType refType = (ReferenceType)classes.get(0);
   865                             ReferenceType refType = classes.get(0);
   868                             LValue lval = new LValueStaticMember(refType,
   866                             LValue lval = new LValueStaticMember(refType,
   869                                                             izer.nextToken(), thread);
   867                                                             izer.nextToken(), thread);
   870                             return nFields(lval, izer, thread);
   868                             return nFields(lval, izer, thread);
   871                         }
   869                         }
   872                     }
   870                     }