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