Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: runtime/vm/parser.cc

Issue 23482004: Evaluates arguments before throwing a NoSuchMethodError in constructor (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/bootstrap.h" 9 #include "vm/bootstrap.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 7188 matching lines...) Expand 10 before | Expand all | Expand 10 after
7199 ASSERT(is_malbounded); 7199 ASSERT(is_malbounded);
7200 } 7200 }
7201 arguments->Add(new LiteralNode(type_pos, String::ZoneHandle( 7201 arguments->Add(new LiteralNode(type_pos, String::ZoneHandle(
7202 Symbols::New(error.ToErrorCString())))); 7202 Symbols::New(error.ToErrorCString()))));
7203 return MakeStaticCall(Symbols::TypeError(), 7203 return MakeStaticCall(Symbols::TypeError(),
7204 PrivateCoreLibName(Symbols::ThrowNew()), 7204 PrivateCoreLibName(Symbols::ThrowNew()),
7205 arguments); 7205 arguments);
7206 } 7206 }
7207 7207
7208 7208
7209 // TODO(regis): Providing the argument values is not always feasible, since
7210 // evaluating them could throw an error.
7211 // Should NoSuchMethodError reflect the argument count and names instead of
7212 // argument values? Or should the spec specify a different evaluation order?
7213 AstNode* Parser::ThrowNoSuchMethodError(intptr_t call_pos, 7209 AstNode* Parser::ThrowNoSuchMethodError(intptr_t call_pos,
7214 const Class& cls, 7210 const Class& cls,
7215 const String& function_name, 7211 const String& function_name,
7212 ArgumentListNode* actuals,
regis 2013/08/28 21:10:54 function_arguments
zra 2013/08/28 22:47:00 Done.
7216 InvocationMirror::Call im_call, 7213 InvocationMirror::Call im_call,
7217 InvocationMirror::Type im_type) { 7214 InvocationMirror::Type im_type) {
7218 ArgumentListNode* arguments = new ArgumentListNode(call_pos); 7215 ArgumentListNode* arguments = new ArgumentListNode(call_pos);
7219 // Object receiver. 7216 // Object receiver.
7220 // TODO(regis): For now, we pass a class literal of the unresolved 7217 // TODO(regis): For now, we pass a class literal of the unresolved
7221 // method's owner, but this is not specified and will probably change. 7218 // method's owner, but this is not specified and will probably change.
7222 Type& type = Type::ZoneHandle( 7219 Type& type = Type::ZoneHandle(
7223 Type::New(cls, TypeArguments::Handle(), call_pos, Heap::kOld)); 7220 Type::New(cls, TypeArguments::Handle(), call_pos, Heap::kOld));
7224 type ^= ClassFinalizer::FinalizeType( 7221 type ^= ClassFinalizer::FinalizeType(
7225 current_class(), type, ClassFinalizer::kCanonicalize); 7222 current_class(), type, ClassFinalizer::kCanonicalize);
7226 arguments->Add(new LiteralNode(call_pos, type)); 7223 arguments->Add(new LiteralNode(call_pos, type));
7227 // String memberName. 7224 // String memberName.
7228 arguments->Add(new LiteralNode( 7225 arguments->Add(new LiteralNode(
7229 call_pos, String::ZoneHandle(Symbols::New(function_name)))); 7226 call_pos, String::ZoneHandle(Symbols::New(function_name))));
7230 // Smi invocation_type. 7227 // Smi invocation_type.
7231 if (cls.IsTopLevel()) { 7228 if (cls.IsTopLevel()) {
7232 ASSERT(im_call == InvocationMirror::kStatic || 7229 ASSERT(im_call == InvocationMirror::kStatic ||
7233 im_call == InvocationMirror::kTopLevel); 7230 im_call == InvocationMirror::kTopLevel);
7234 im_call = InvocationMirror::kTopLevel; 7231 im_call = InvocationMirror::kTopLevel;
7235 } 7232 }
7236 arguments->Add(new LiteralNode(call_pos, Smi::ZoneHandle( 7233 arguments->Add(new LiteralNode(call_pos, Smi::ZoneHandle(
7237 Smi::New(InvocationMirror::EncodeType(im_call, im_type))))); 7234 Smi::New(InvocationMirror::EncodeType(im_call, im_type)))));
7238 // List arguments. 7235 // List arguments.
7239 arguments->Add(new LiteralNode(call_pos, Array::ZoneHandle())); 7236 if (actuals == NULL) {
7237 arguments->Add(new LiteralNode(call_pos, Array::ZoneHandle()));
7238 } else {
7239 ArrayNode* array = new ArrayNode(
7240 call_pos, Type::ZoneHandle(Type::ArrayType()), actuals->nodes());
7241 arguments->Add(array);
7242 }
7240 // List argumentNames. 7243 // List argumentNames.
7241 arguments->Add(new LiteralNode(call_pos, Array::ZoneHandle())); 7244 if (actuals == NULL) {
7245 arguments->Add(new LiteralNode(call_pos, Array::ZoneHandle()));
7246 } else {
7247 arguments->Add(new LiteralNode(call_pos, actuals->names()));
7248 }
7242 // List existingArgumentNames. 7249 // List existingArgumentNames.
7243 // Check if there exists a function with the same name. 7250 // Check if there exists a function with the same name.
7244 Function& function = 7251 Function& function =
7245 Function::Handle(cls.LookupStaticFunction(function_name)); 7252 Function::Handle(cls.LookupStaticFunction(function_name));
7246 if (function.IsNull()) { 7253 if (function.IsNull()) {
7247 // TODO(srdjan): Store argument values into the argument list.
7248 arguments->Add(new LiteralNode(call_pos, Array::ZoneHandle())); 7254 arguments->Add(new LiteralNode(call_pos, Array::ZoneHandle()));
7249 } else { 7255 } else {
7250 const int total_num_parameters = function.NumParameters(); 7256 const int total_num_parameters = function.NumParameters();
7251 Array& array = 7257 Array& array =
7252 Array::ZoneHandle(Array::New(total_num_parameters, Heap::kOld)); 7258 Array::ZoneHandle(Array::New(total_num_parameters, Heap::kOld));
7253 // Skip receiver. 7259 // Skip receiver.
7254 for (int i = 0; i < total_num_parameters; i++) { 7260 for (int i = 0; i < total_num_parameters; i++) {
7255 array.SetAt(i, String::Handle(function.ParameterNameAt(i))); 7261 array.SetAt(i, String::Handle(function.ParameterNameAt(i)));
7256 } 7262 }
7257 arguments->Add(new LiteralNode(call_pos, array)); 7263 arguments->Add(new LiteralNode(call_pos, array));
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
7741 TRACE_PARSER("ParseActualParameters"); 7747 TRACE_PARSER("ParseActualParameters");
7742 ASSERT(CurrentToken() == Token::kLPAREN); 7748 ASSERT(CurrentToken() == Token::kLPAREN);
7743 const bool saved_mode = SetAllowFunctionLiterals(true); 7749 const bool saved_mode = SetAllowFunctionLiterals(true);
7744 ArgumentListNode* arguments; 7750 ArgumentListNode* arguments;
7745 if (implicit_arguments == NULL) { 7751 if (implicit_arguments == NULL) {
7746 arguments = new ArgumentListNode(TokenPos()); 7752 arguments = new ArgumentListNode(TokenPos());
7747 } else { 7753 } else {
7748 arguments = implicit_arguments; 7754 arguments = implicit_arguments;
7749 } 7755 }
7750 const GrowableObjectArray& names = 7756 const GrowableObjectArray& names =
7751 GrowableObjectArray::Handle(GrowableObjectArray::New()); 7757 GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld));
7752 bool named_argument_seen = false; 7758 bool named_argument_seen = false;
7753 if (LookaheadToken(1) != Token::kRPAREN) { 7759 if (LookaheadToken(1) != Token::kRPAREN) {
7754 String& arg_name = String::Handle(); 7760 String& arg_name = String::Handle();
7755 do { 7761 do {
7756 ASSERT((CurrentToken() == Token::kLPAREN) || 7762 ASSERT((CurrentToken() == Token::kLPAREN) ||
7757 (CurrentToken() == Token::kCOMMA)); 7763 (CurrentToken() == Token::kCOMMA));
7758 ConsumeToken(); 7764 ConsumeToken();
7759 if (IsIdentifier() && (LookaheadToken(1) == Token::kCOLON)) { 7765 if (IsIdentifier() && (LookaheadToken(1) == Token::kCOLON)) {
7760 named_argument_seen = true; 7766 named_argument_seen = true;
7761 // The canonicalization of the arguments descriptor array built in 7767 // The canonicalization of the arguments descriptor array built in
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
7830 } 7836 }
7831 } else { 7837 } else {
7832 EnsureSavedCurrentContext(); 7838 EnsureSavedCurrentContext();
7833 closure = GenerateStaticFieldLookup(field, call_pos); 7839 closure = GenerateStaticFieldLookup(field, call_pos);
7834 return new ClosureCallNode(call_pos, closure, arguments); 7840 return new ClosureCallNode(call_pos, closure, arguments);
7835 } 7841 }
7836 // Could not resolve static method: throw a NoSuchMethodError. 7842 // Could not resolve static method: throw a NoSuchMethodError.
7837 return ThrowNoSuchMethodError(ident_pos, 7843 return ThrowNoSuchMethodError(ident_pos,
7838 cls, 7844 cls,
7839 func_name, 7845 func_name,
7846 arguments,
7840 InvocationMirror::kStatic, 7847 InvocationMirror::kStatic,
7841 InvocationMirror::kMethod); 7848 InvocationMirror::kMethod);
7842 } else if (cls.IsTopLevel() && 7849 } else if (cls.IsTopLevel() &&
7843 (cls.library() == Library::CoreLibrary()) && 7850 (cls.library() == Library::CoreLibrary()) &&
7844 (func.name() == Symbols::Identical().raw())) { 7851 (func.name() == Symbols::Identical().raw())) {
7845 // This is the predefined toplevel function identical(a,b). Create 7852 // This is the predefined toplevel function identical(a,b). Create
7846 // a comparison node instead. 7853 // a comparison node instead.
7847 ASSERT(num_arguments == 2); 7854 ASSERT(num_arguments == 2);
7848 return new ComparisonNode(ident_pos, 7855 return new ComparisonNode(ident_pos,
7849 Token::kEQ_STRICT, 7856 Token::kEQ_STRICT,
(...skipping 1902 matching lines...) Expand 10 before | Expand all | Expand 10 after
9752 call_pos, 9759 call_pos,
9753 "class '%s' has no constructor or factory named '%s'", 9760 "class '%s' has no constructor or factory named '%s'",
9754 String::Handle(type_class.Name()).ToCString(), 9761 String::Handle(type_class.Name()).ToCString(),
9755 external_constructor_name.ToCString()); 9762 external_constructor_name.ToCString());
9756 const Error& error = Error::Handle(type.malformed_error()); 9763 const Error& error = Error::Handle(type.malformed_error());
9757 ErrorMsg(error); 9764 ErrorMsg(error);
9758 } 9765 }
9759 return ThrowNoSuchMethodError(call_pos, 9766 return ThrowNoSuchMethodError(call_pos,
9760 type_class, 9767 type_class,
9761 external_constructor_name, 9768 external_constructor_name,
9769 arguments,
9762 InvocationMirror::kConstructor, 9770 InvocationMirror::kConstructor,
9763 InvocationMirror::kMethod); 9771 InvocationMirror::kMethod);
9764 } else if (constructor.IsRedirectingFactory()) { 9772 } else if (constructor.IsRedirectingFactory()) {
9765 ClassFinalizer::ResolveRedirectingFactory(type_class, constructor); 9773 ClassFinalizer::ResolveRedirectingFactory(type_class, constructor);
9766 Type& redirect_type = Type::Handle(constructor.RedirectionType()); 9774 Type& redirect_type = Type::Handle(constructor.RedirectionType());
9767 if (!redirect_type.IsMalformed() && !redirect_type.IsInstantiated()) { 9775 if (!redirect_type.IsMalformed() && !redirect_type.IsInstantiated()) {
9768 // The type arguments of the redirection type are instantiated from the 9776 // The type arguments of the redirection type are instantiated from the
9769 // type arguments of the parsed type of the 'new' or 'const' expression. 9777 // type arguments of the parsed type of the 'new' or 'const' expression.
9770 Error& malformed_error = Error::Handle(); 9778 Error& malformed_error = Error::Handle();
9771 redirect_type ^= redirect_type.InstantiateFrom(type_arguments, 9779 redirect_type ^= redirect_type.InstantiateFrom(type_arguments,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
9819 ErrorMsg(call_pos, 9827 ErrorMsg(call_pos,
9820 "invalid arguments passed to constructor '%s' " 9828 "invalid arguments passed to constructor '%s' "
9821 "for class '%s': %s", 9829 "for class '%s': %s",
9822 external_constructor_name.ToCString(), 9830 external_constructor_name.ToCString(),
9823 String::Handle(type_class.Name()).ToCString(), 9831 String::Handle(type_class.Name()).ToCString(),
9824 error_message.ToCString()); 9832 error_message.ToCString());
9825 } 9833 }
9826 return ThrowNoSuchMethodError(call_pos, 9834 return ThrowNoSuchMethodError(call_pos,
9827 type_class, 9835 type_class,
9828 external_constructor_name, 9836 external_constructor_name,
9837 arguments,
9829 InvocationMirror::kConstructor, 9838 InvocationMirror::kConstructor,
9830 InvocationMirror::kMethod); 9839 InvocationMirror::kMethod);
9831 } 9840 }
9832 9841
9833 // Return a throw in case of a malformed type or report a compile-time error 9842 // Return a throw in case of a malformed type or report a compile-time error
9834 // if the constructor is const. 9843 // if the constructor is const.
9835 if (type.IsMalformed()) { 9844 if (type.IsMalformed()) {
9836 if (is_const) { 9845 if (is_const) {
9837 const Error& error = Error::Handle(type.malformed_error()); 9846 const Error& error = Error::Handle(type.malformed_error());
9838 ErrorMsg(error); 9847 ErrorMsg(error);
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
10472 void Parser::SkipQualIdent() { 10481 void Parser::SkipQualIdent() {
10473 ASSERT(IsIdentifier()); 10482 ASSERT(IsIdentifier());
10474 ConsumeToken(); 10483 ConsumeToken();
10475 if (CurrentToken() == Token::kPERIOD) { 10484 if (CurrentToken() == Token::kPERIOD) {
10476 ConsumeToken(); // Consume the kPERIOD token. 10485 ConsumeToken(); // Consume the kPERIOD token.
10477 ExpectIdentifier("identifier expected after '.'"); 10486 ExpectIdentifier("identifier expected after '.'");
10478 } 10487 }
10479 } 10488 }
10480 10489
10481 } // namespace dart 10490 } // namespace dart
OLDNEW
« runtime/vm/parser.h ('K') | « runtime/vm/parser.h ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698