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

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

Issue 9665013: Generate a dynamic type error when creating an instance with a bound error. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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 "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 2934 matching lines...) Expand 10 before | Expand all | Expand 10 after
2945 ErrorMsg("type parameter name expected"); 2945 ErrorMsg("type parameter name expected");
2946 } 2946 }
2947 String& type_parameter_name = *CurrentLiteral(); 2947 String& type_parameter_name = *CurrentLiteral();
2948 type_parameter = TypeParameter::New(index, 2948 type_parameter = TypeParameter::New(index,
2949 type_parameter_name, 2949 type_parameter_name,
2950 token_index_); 2950 token_index_);
2951 ConsumeToken(); 2951 ConsumeToken();
2952 bound = Type::DynamicType(); 2952 bound = Type::DynamicType();
2953 if (CurrentToken() == Token::kEXTENDS) { 2953 if (CurrentToken() == Token::kEXTENDS) {
2954 ConsumeToken(); 2954 ConsumeToken();
2955 bound = ParseType(ClassFinalizer::kTryResolve); 2955 // A bound may refer to the owner of the type parameter it applies to,
2956 // i.e. to the class or interface currently being parsed.
2957 // Postpone resolution in order to avoid resolving the class and its
2958 // type parameters, as they are not fully parsed yet.
2959 bound = ParseType(ClassFinalizer::kDoNotResolve);
2956 } 2960 }
2957 type_parameters_array.Add(type_parameter); 2961 type_parameters_array.Add(type_parameter);
2958 bounds_array.Add(bound); 2962 bounds_array.Add(bound);
2959 index++; 2963 index++;
2960 } while (CurrentToken() == Token::kCOMMA); 2964 } while (CurrentToken() == Token::kCOMMA);
2961 Token::Kind token = CurrentToken(); 2965 Token::Kind token = CurrentToken();
2962 if ((token == Token::kGT) || (token == Token::kSHR)) { 2966 if ((token == Token::kGT) || (token == Token::kSHR)) {
2963 ConsumeRightAngleBracket(); 2967 ConsumeRightAngleBracket();
2964 } else { 2968 } else {
2965 ErrorMsg("right angle bracket expected"); 2969 ErrorMsg("right angle bracket expected");
(...skipping 2565 matching lines...) Expand 10 before | Expand all | Expand 10 after
5531 AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type) { 5535 AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type) {
5532 ASSERT(type.IsMalformed()); 5536 ASSERT(type.IsMalformed());
5533 ArgumentListNode* arguments = new ArgumentListNode(type_pos); 5537 ArgumentListNode* arguments = new ArgumentListNode(type_pos);
5534 // Location argument. 5538 // Location argument.
5535 arguments->Add(new LiteralNode( 5539 arguments->Add(new LiteralNode(
5536 type_pos, Integer::ZoneHandle(Integer::New(type_pos)))); 5540 type_pos, Integer::ZoneHandle(Integer::New(type_pos))));
5537 // Src value argument. 5541 // Src value argument.
5538 arguments->Add(new LiteralNode(type_pos, Instance::ZoneHandle())); 5542 arguments->Add(new LiteralNode(type_pos, Instance::ZoneHandle()));
5539 // Dst type name argument. 5543 // Dst type name argument.
5540 arguments->Add(new LiteralNode(type_pos, String::ZoneHandle( 5544 arguments->Add(new LiteralNode(type_pos, String::ZoneHandle(
5541 String::NewSymbol("malformed type")))); 5545 String::NewSymbol("malformed"))));
5542 // Dst type name argument. 5546 // Dst name argument.
5543 arguments->Add(new LiteralNode(type_pos, String::ZoneHandle( 5547 arguments->Add(new LiteralNode(type_pos, String::ZoneHandle(
5544 String::NewSymbol("")))); 5548 String::NewSymbol(""))));
5545 // Malformed type error. 5549 // Malformed type error.
5546 const Error& error = Error::Handle(type.malformed_error()); 5550 const Error& error = Error::Handle(type.malformed_error());
5547 arguments->Add(new LiteralNode(type_pos, String::ZoneHandle( 5551 arguments->Add(new LiteralNode(type_pos, String::ZoneHandle(
5548 String::NewSymbol(error.ToErrorCString())))); 5552 String::NewSymbol(error.ToErrorCString()))));
5549 return MakeStaticCall(kTypeErrorName, kThrowNewName, arguments); 5553 return MakeStaticCall(kTypeErrorName, kThrowNewName, arguments);
5550 } 5554 }
5551 5555
5552 5556
(...skipping 1781 matching lines...) Expand 10 before | Expand all | Expand 10 after
7334 bool is_const = false; 7338 bool is_const = false;
7335 if (CurrentToken() == Token::kCONST) { 7339 if (CurrentToken() == Token::kCONST) {
7336 is_const = true; 7340 is_const = true;
7337 ConsumeToken(); 7341 ConsumeToken();
7338 } 7342 }
7339 const intptr_t type_pos = token_index_; 7343 const intptr_t type_pos = token_index_;
7340 Error& malformed_error = Error::Handle(); 7344 Error& malformed_error = Error::Handle();
7341 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle( 7345 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(
7342 ParseTypeArguments(&malformed_error, 7346 ParseTypeArguments(&malformed_error,
7343 ClassFinalizer::kFinalizeWellFormed)); 7347 ClassFinalizer::kFinalizeWellFormed));
7348 // Map and List interfaces do not declare bounds on their type parameters, so
7349 // we should never see a malformed type error here.
7350 // Note that a bound error is the only possible malformed type error returned
7351 // when requesting kFinalizeWellFormed type finalization.
srdjan 2012/03/09 20:48:28 What if we change the libraries? Can we check some
regis 2012/03/09 21:08:37 We would need to add debug code here to resolve Ma
7352 ASSERT(malformed_error.IsNull());
7344 AstNode* primary = NULL; 7353 AstNode* primary = NULL;
7345 if ((CurrentToken() == Token::kLBRACK) || 7354 if ((CurrentToken() == Token::kLBRACK) ||
7346 (CurrentToken() == Token::kINDEX)) { 7355 (CurrentToken() == Token::kINDEX)) {
7347 primary = ParseListLiteral(type_pos, is_const, type_arguments); 7356 primary = ParseListLiteral(type_pos, is_const, type_arguments);
7348 } else if (CurrentToken() == Token::kLBRACE) { 7357 } else if (CurrentToken() == Token::kLBRACE) {
7349 primary = ParseMapLiteral(type_pos, is_const, type_arguments); 7358 primary = ParseMapLiteral(type_pos, is_const, type_arguments);
7350 } else { 7359 } else {
7351 ErrorMsg("unexpected token %s", Token::Str(CurrentToken())); 7360 ErrorMsg("unexpected token %s", Token::Str(CurrentToken()));
7352 } 7361 }
7353 return primary; 7362 return primary;
(...skipping 19 matching lines...) Expand all
7373 AstNode* Parser::ParseNewOperator() { 7382 AstNode* Parser::ParseNewOperator() {
7374 TRACE_PARSER("ParseNewOperator"); 7383 TRACE_PARSER("ParseNewOperator");
7375 const intptr_t new_pos = token_index_; 7384 const intptr_t new_pos = token_index_;
7376 ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST)); 7385 ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST));
7377 bool is_const = (CurrentToken() == Token::kCONST); 7386 bool is_const = (CurrentToken() == Token::kCONST);
7378 ConsumeToken(); 7387 ConsumeToken();
7379 if (!IsIdentifier()) { 7388 if (!IsIdentifier()) {
7380 ErrorMsg("type name expected"); 7389 ErrorMsg("type name expected");
7381 } 7390 }
7382 intptr_t type_pos = token_index_; 7391 intptr_t type_pos = token_index_;
7383
7384 // TODO(regis): Bounds error should not result in a compile time error,
7385 // but in a dynamic type error. Requesting kFinalizeWellFormed below is too
7386 // strict. See co19 issue 96.
7387 const AbstractType& type = AbstractType::Handle( 7392 const AbstractType& type = AbstractType::Handle(
7388 ParseType(ClassFinalizer::kFinalizeWellFormed)); 7393 ParseType(ClassFinalizer::kFinalizeWellFormed));
7394 // Malformed bounds never result in a compile time error, therefore, the
7395 // parsed type may be malformed although we requested kFinalizeWellFormed.
7396 // In that case, we throw a dynamic type error instead of calling the
7397 // constructor.
7389 if (type.IsTypeParameter()) { 7398 if (type.IsTypeParameter()) {
7390 ErrorMsg(type_pos, 7399 ErrorMsg(type_pos,
7391 "type parameter '%s' cannot be instantiated", 7400 "type parameter '%s' cannot be instantiated",
7392 String::Handle(type.Name()).ToCString()); 7401 String::Handle(type.Name()).ToCString());
7393 } 7402 }
7394 Class& type_class = Class::Handle(type.type_class()); 7403 Class& type_class = Class::Handle(type.type_class());
7395 String& type_class_name = String::Handle(type_class.Name()); 7404 String& type_class_name = String::Handle(type_class.Name());
7396 AbstractTypeArguments& type_arguments = 7405 AbstractTypeArguments& type_arguments =
7397 AbstractTypeArguments::ZoneHandle(type.arguments()); 7406 AbstractTypeArguments::ZoneHandle(type.arguments());
7398 7407
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
7541 } 7550 }
7542 7551
7543 type_arguments ^= type_arguments.Canonicalize(); 7552 type_arguments ^= type_arguments.Canonicalize();
7544 // Make the constructor call. 7553 // Make the constructor call.
7545 AstNode* new_object = NULL; 7554 AstNode* new_object = NULL;
7546 if (is_const) { 7555 if (is_const) {
7547 if (!constructor.is_const()) { 7556 if (!constructor.is_const()) {
7548 ErrorMsg("'const' requires const constructor: '%s'", 7557 ErrorMsg("'const' requires const constructor: '%s'",
7549 String::Handle(constructor.name()).ToCString()); 7558 String::Handle(constructor.name()).ToCString());
7550 } 7559 }
7560 if (type.IsMalformed()) {
7561 // Compile the throw of a dynamic type error due to a bound error.
7562 return ThrowTypeError(type_pos, type);
7563 }
7551 const Object& constructor_result = Object::Handle( 7564 const Object& constructor_result = Object::Handle(
7552 EvaluateConstConstructorCall(constructor_class, 7565 EvaluateConstConstructorCall(constructor_class,
7553 type_arguments, 7566 type_arguments,
7554 constructor, 7567 constructor,
7555 arguments)); 7568 arguments));
7556 if (constructor_result.IsUnhandledException()) { 7569 if (constructor_result.IsUnhandledException()) {
7557 new_object = CreateEvalConstConstructorThrow(new_pos, constructor_result); 7570 new_object = CreateEvalConstConstructorThrow(new_pos, constructor_result);
7558 } else { 7571 } else {
7559 Instance& const_instance = Instance::ZoneHandle(); 7572 Instance& const_instance = Instance::ZoneHandle();
7560 const_instance ^= constructor_result.raw(); 7573 const_instance ^= constructor_result.raw();
7561 new_object = new LiteralNode(new_pos, const_instance); 7574 new_object = new LiteralNode(new_pos, const_instance);
7562 } 7575 }
7563 } else { 7576 } else {
7564 CheckFunctionIsCallable(new_pos, constructor); 7577 CheckFunctionIsCallable(new_pos, constructor);
7565 CheckConstructorCallTypeArguments(new_pos, constructor, type_arguments); 7578 CheckConstructorCallTypeArguments(new_pos, constructor, type_arguments);
7566 if (!type_arguments.IsNull() && 7579 if (!type_arguments.IsNull() &&
7567 !type_arguments.IsInstantiated() && 7580 !type_arguments.IsInstantiated() &&
7568 (current_block_->scope->function_level() > 0)) { 7581 (current_block_->scope->function_level() > 0)) {
7569 // Make sure that the instantiator is captured. 7582 // Make sure that the instantiator is captured.
7570 CaptureReceiver(); 7583 CaptureReceiver();
7571 } 7584 }
7585 if (type.IsMalformed()) {
7586 // Compile the throw of a dynamic type error due to a bound error.
7587 return ThrowTypeError(type_pos, type);
7588 }
7572 // TODO(regis): If the type argument vector is not instantiated, we need to 7589 // TODO(regis): If the type argument vector is not instantiated, we need to
7573 // verify in checked mode at runtime that it is within its declared bounds. 7590 // verify in checked mode at runtime that it is within its declared bounds.
7574 new_object = new ConstructorCallNode( 7591 new_object = new ConstructorCallNode(
7575 new_pos, type_arguments, constructor, arguments); 7592 new_pos, type_arguments, constructor, arguments);
7576 } 7593 }
7577 return new_object; 7594 return new_object;
7578 } 7595 }
7579 7596
7580 7597
7581 String& Parser::Interpolate(ArrayNode* values) { 7598 String& Parser::Interpolate(ArrayNode* values) {
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after
8144 void Parser::SkipQualIdent() { 8161 void Parser::SkipQualIdent() {
8145 ASSERT(IsIdentifier()); 8162 ASSERT(IsIdentifier());
8146 ConsumeToken(); 8163 ConsumeToken();
8147 if (CurrentToken() == Token::kPERIOD) { 8164 if (CurrentToken() == Token::kPERIOD) {
8148 ConsumeToken(); // Consume the kPERIOD token. 8165 ConsumeToken(); // Consume the kPERIOD token.
8149 ExpectIdentifier("identifier expected after '.'"); 8166 ExpectIdentifier("identifier expected after '.'");
8150 } 8167 }
8151 } 8168 }
8152 8169
8153 } // namespace dart 8170 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698