Index: runtime/vm/code_generator.cc |
=================================================================== |
--- runtime/vm/code_generator.cc (revision 14352) |
+++ runtime/vm/code_generator.cc (working copy) |
@@ -1190,7 +1190,45 @@ |
return; // Return closure object. |
} |
} |
- Exceptions::ThrowByType(Exceptions::kObjectNotClosure, invoke_arguments); |
+ |
srdjan
2012/10/31 17:52:51
Please add a comment saying that the object is not
regis
2012/10/31 18:04:37
Added:
// The result instance is not a closure,
|
+ // TODO(regis): Factorize the following code. |
+ |
+ // TODO(regis): Args should be passed. |
+ const Array& function_args = Array::Handle(); |
+ const String& function_name = String::Handle(Symbols::Call()); |
+ GrowableArray<const Object*> dart_arguments; |
srdjan
2012/10/31 17:52:51
dart_arguments(4);
regis
2012/10/31 18:04:37
Done (5).
|
+ |
+ // TODO(regis): Resolve and invoke "call" method, if existing. |
+ |
+ const Object& null_object = Object::Handle(Object::null()); |
srdjan
2012/10/31 17:52:51
Why not just Object::Handle();?
regis
2012/10/31 18:04:37
Done.
|
+ dart_arguments.Add(&receiver); |
+ dart_arguments.Add(&function_name); |
+ dart_arguments.Add(&function_args); |
+ dart_arguments.Add(&null_object); |
+ |
+ // Report if a function with same name (but different arguments) has been |
srdjan
2012/10/31 17:52:51
Maybe adapt argument that we are not looking at an
regis
2012/10/31 18:04:37
Done.
|
+ // found. |
+ { |
+ Class& instance_class = Class::Handle(receiver.clazz()); |
+ Function& function = |
+ Function::Handle(instance_class.LookupDynamicFunction(function_name)); |
+ while (function.IsNull()) { |
+ instance_class = instance_class.SuperClass(); |
+ if (instance_class.IsNull()) break; |
+ function = instance_class.LookupDynamicFunction(function_name); |
+ } |
+ if (!function.IsNull()) { |
+ const int total_num_parameters = function.NumParameters(); |
+ const Array& array = Array::Handle(Array::New(total_num_parameters - 1)); |
+ // Skip receiver. |
+ for (int i = 1; i < total_num_parameters; i++) { |
+ array.SetAt(i - 1, String::Handle(function.ParameterNameAt(i))); |
+ } |
+ dart_arguments.Add(&array); |
+ } |
+ } |
+ Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments); |
+ UNREACHABLE(); |
} |
@@ -1329,27 +1367,75 @@ |
} |
-// Report that an object is not a closure. |
+// A non-closure object was invoked as a closure, so call the "call" method |
+// on it. |
// Arg0: non-closure object. |
// Arg1: arguments array. |
+// TODO(regis): Rename this entry? |
DEFINE_RUNTIME_ENTRY(ReportObjectNotClosure, 2) { |
ASSERT(arguments.Count() == |
kReportObjectNotClosureRuntimeEntry.argument_count()); |
- const Instance& bad_closure = Instance::CheckedHandle(arguments.At(0)); |
- if (bad_closure.IsNull()) { |
- GrowableArray<const Object*> args; |
- Exceptions::ThrowByType(Exceptions::kObjectNotClosure, args); |
+ const Instance& instance = Instance::CheckedHandle(arguments.At(0)); |
+ const Array& function_args = Array::CheckedHandle(arguments.At(1)); |
+ const String& function_name = String::Handle(Symbols::Call()); |
+ GrowableArray<const Object*> dart_arguments; |
+ if (instance.IsNull()) { |
+ dart_arguments.Add(&function_name); |
+ dart_arguments.Add(&function_args); |
+ // TODO(regis): Change to Exceptions::kNoSuchMethod. |
srdjan
2012/10/31 17:52:51
Remove TODO
regis
2012/10/31 18:04:37
Done.
|
+ Exceptions::ThrowByType(Exceptions::kNullPointer, dart_arguments); |
+ UNREACHABLE(); |
} |
- GrowableArray<const Object*> args; |
- Exceptions::ThrowByType(Exceptions::kObjectNotClosure, args); |
+ |
+ // TODO(regis): Resolve and invoke "call" method, if existing. |
+ |
+ const Object& null_object = Object::Handle(Object::null()); |
+ dart_arguments.Add(&instance); |
+ dart_arguments.Add(&function_name); |
+ dart_arguments.Add(&function_args); |
+ dart_arguments.Add(&null_object); |
+ |
+ // Report if a function with same name (but different arguments) has been |
+ // found. |
srdjan
2012/10/31 17:52:51
ditto 'a function with ...' -> 'function named "ca
regis
2012/10/31 18:04:37
Done.
|
+ Class& instance_class = Class::Handle(instance.clazz()); |
+ Function& function = |
+ Function::Handle(instance_class.LookupDynamicFunction(function_name)); |
+ while (function.IsNull()) { |
+ instance_class = instance_class.SuperClass(); |
+ if (instance_class.IsNull()) break; |
+ function = instance_class.LookupDynamicFunction(function_name); |
+ } |
+ if (!function.IsNull()) { |
+ const int total_num_parameters = function.NumParameters(); |
+ const Array& array = Array::Handle(Array::New(total_num_parameters - 1)); |
+ // Skip receiver. |
+ for (int i = 1; i < total_num_parameters; i++) { |
+ array.SetAt(i - 1, String::Handle(function.ParameterNameAt(i))); |
+ } |
+ dart_arguments.Add(&array); |
+ } |
+ Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments); |
+ UNREACHABLE(); |
} |
+// A closure object was invoked with incompatible arguments. |
+// TODO(regis): Deprecated. This case should be handled by a noSuchMethod call. |
DEFINE_RUNTIME_ENTRY(ClosureArgumentMismatch, 0) { |
ASSERT(arguments.Count() == |
kClosureArgumentMismatchRuntimeEntry.argument_count()); |
- GrowableArray<const Object*> args; |
- Exceptions::ThrowByType(Exceptions::kClosureArgumentMismatch, args); |
+ const Instance& instance = Instance::Handle(); // Incorrect. OK for now. |
+ const Array& function_args = Array::Handle(); // Incorrect. OK for now. |
+ const String& function_name = String::Handle(Symbols::Call()); |
+ GrowableArray<const Object*> dart_arguments; |
+ |
+ const Object& null_object = Object::Handle(Object::null()); |
srdjan
2012/10/31 17:52:51
Why not Object::Handle(); ?
regis
2012/10/31 18:04:37
Done.
|
+ dart_arguments.Add(&instance); |
+ dart_arguments.Add(&function_name); |
+ dart_arguments.Add(&function_args); |
+ dart_arguments.Add(&null_object); |
+ Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments); |
+ UNREACHABLE(); |
} |