Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 9100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9111 AstNode* Parser::ParseNewOperator() { | 9111 AstNode* Parser::ParseNewOperator() { |
| 9112 TRACE_PARSER("ParseNewOperator"); | 9112 TRACE_PARSER("ParseNewOperator"); |
| 9113 const intptr_t new_pos = TokenPos(); | 9113 const intptr_t new_pos = TokenPos(); |
| 9114 ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST)); | 9114 ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST)); |
| 9115 bool is_const = (CurrentToken() == Token::kCONST); | 9115 bool is_const = (CurrentToken() == Token::kCONST); |
| 9116 ConsumeToken(); | 9116 ConsumeToken(); |
| 9117 if (!IsIdentifier()) { | 9117 if (!IsIdentifier()) { |
| 9118 ErrorMsg("type name expected"); | 9118 ErrorMsg("type name expected"); |
| 9119 } | 9119 } |
| 9120 intptr_t type_pos = TokenPos(); | 9120 intptr_t type_pos = TokenPos(); |
| 9121 AbstractType& type = AbstractType::Handle( | 9121 AbstractType& type = AbstractType::ZoneHandle( |
| 9122 ParseType(ClassFinalizer::kCanonicalizeForCreation)); | 9122 ParseType(ClassFinalizer::kCanonicalizeForCreation)); |
| 9123 // In case the type is malformed, throw a dynamic type error after finishing | 9123 // In case the type is malformed, throw a dynamic type error after finishing |
| 9124 // parsing the instance creation expression. | 9124 // parsing the instance creation expression. |
| 9125 if (type.IsTypeParameter() || type.IsDynamicType()) { | 9125 if (type.IsTypeParameter() || type.IsDynamicType()) { |
| 9126 ASSERT(!type.IsMalformed()); | 9126 ASSERT(!type.IsMalformed()); |
| 9127 // Replace the type with a malformed type. | 9127 // Replace the type with a malformed type. |
| 9128 type = ClassFinalizer::NewFinalizedMalformedType( | 9128 type = ClassFinalizer::NewFinalizedMalformedType( |
| 9129 Error::Handle(), // No previous error. | 9129 Error::Handle(), // No previous error. |
| 9130 current_class(), | 9130 current_class(), |
| 9131 type_pos, | 9131 type_pos, |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9243 // Class finalization verifies that the factory class has identical type | 9243 // Class finalization verifies that the factory class has identical type |
| 9244 // parameters as the interface. | 9244 // parameters as the interface. |
| 9245 constructor_class_name = factory_class.Name(); | 9245 constructor_class_name = factory_class.Name(); |
| 9246 } | 9246 } |
| 9247 // Always change the result type of the constructor to the factory type. | 9247 // Always change the result type of the constructor to the factory type. |
| 9248 constructor_class = factory_class.raw(); | 9248 constructor_class = factory_class.raw(); |
| 9249 // The finalized type_arguments are still those of the interface type. | 9249 // The finalized type_arguments are still those of the interface type. |
| 9250 ASSERT(!constructor_class.is_interface()); | 9250 ASSERT(!constructor_class.is_interface()); |
| 9251 } | 9251 } |
| 9252 | 9252 |
| 9253 // An additional type check of the result of a redirecting factory may be | |
| 9254 // required. | |
| 9255 bool check_result_type = false; | |
| 9256 | |
| 9253 // Make sure that an appropriate constructor exists. | 9257 // Make sure that an appropriate constructor exists. |
| 9254 const String& constructor_name = | 9258 const String& constructor_name = |
| 9255 BuildConstructorName(constructor_class_name, named_constructor); | 9259 BuildConstructorName(constructor_class_name, named_constructor); |
| 9256 Function& constructor = Function::ZoneHandle( | 9260 Function& constructor = Function::ZoneHandle( |
| 9257 constructor_class.LookupConstructor(constructor_name)); | 9261 constructor_class.LookupConstructor(constructor_name)); |
| 9258 if (constructor.IsNull()) { | 9262 if (constructor.IsNull()) { |
| 9259 constructor = constructor_class.LookupFactory(constructor_name); | 9263 constructor = constructor_class.LookupFactory(constructor_name); |
| 9260 if (constructor.IsNull()) { | 9264 if (constructor.IsNull()) { |
| 9261 const String& external_constructor_name = | 9265 const String& external_constructor_name = |
| 9262 (named_constructor ? constructor_name : constructor_class_name); | 9266 (named_constructor ? constructor_name : constructor_class_name); |
| 9263 // Replace the type with a malformed type and compile a throw or report a | 9267 // Replace the type with a malformed type and compile a throw or report a |
| 9264 // compile-time error if the constructor is const. | 9268 // compile-time error if the constructor is const. |
| 9265 type = ClassFinalizer::NewFinalizedMalformedType( | 9269 type = ClassFinalizer::NewFinalizedMalformedType( |
| 9266 Error::Handle(), // No previous error. | 9270 Error::Handle(), // No previous error. |
| 9267 current_class(), | 9271 current_class(), |
| 9268 call_pos, | 9272 call_pos, |
| 9269 ClassFinalizer::kTryResolve, // No compile-time error. | 9273 ClassFinalizer::kTryResolve, // No compile-time error. |
| 9270 "class '%s' has no constructor or factory named '%s'", | 9274 "class '%s' has no constructor or factory named '%s'", |
| 9271 String::Handle(constructor_class.Name()).ToCString(), | 9275 String::Handle(constructor_class.Name()).ToCString(), |
| 9272 external_constructor_name.ToCString()); | 9276 external_constructor_name.ToCString()); |
| 9273 if (is_const) { | 9277 if (is_const) { |
| 9274 const Error& error = Error::Handle(type.malformed_error()); | 9278 const Error& error = Error::Handle(type.malformed_error()); |
| 9275 ErrorMsg(error); | 9279 ErrorMsg(error); |
| 9276 } | 9280 } |
| 9277 return ThrowNoSuchMethodError(call_pos, external_constructor_name); | 9281 return ThrowNoSuchMethodError(call_pos, external_constructor_name); |
| 9278 } else if (constructor.IsRedirectingFactory()) { | 9282 } else if (constructor.IsRedirectingFactory()) { |
| 9279 type = constructor.RedirectionType(); | 9283 Type& redirect_type = Type::Handle(constructor.RedirectionType()); |
| 9280 if (type.IsMalformed()) { | 9284 if (!redirect_type.IsMalformed() && !redirect_type.IsInstantiated()) { |
| 9285 // The type arguments of the redirection type are instantiated from the | |
| 9286 // type arguments of the parsed type of the 'new' or 'const' expression. | |
| 9287 redirect_type ^= redirect_type.InstantiateFrom(type_arguments); | |
| 9288 } | |
| 9289 if (redirect_type.IsMalformed()) { | |
| 9281 if (is_const) { | 9290 if (is_const) { |
| 9282 const Error& error = Error::Handle(type.malformed_error()); | 9291 const Error& error = Error::Handle(redirect_type.malformed_error()); |
| 9283 ErrorMsg(error); | 9292 ErrorMsg(error); |
| 9284 } | 9293 } |
| 9285 return ThrowTypeError(type.token_pos(), type); | 9294 return ThrowTypeError(redirect_type.token_pos(), redirect_type); |
| 9286 } | 9295 } |
| 9296 check_result_type = | |
| 9297 FLAG_enable_type_checks && !redirect_type.IsSubtypeOf(type, NULL); | |
| 9298 type = redirect_type.raw(); | |
| 9299 type_class = type.type_class(); | |
| 9300 type_arguments = type.arguments(); | |
| 9287 constructor = constructor.RedirectionTarget(); | 9301 constructor = constructor.RedirectionTarget(); |
| 9288 ASSERT(!constructor.IsNull()); | 9302 ASSERT(!constructor.IsNull()); |
| 9289 type_class = type.type_class(); | |
| 9290 type_arguments = type.arguments(); | |
| 9291 constructor_class = constructor.Owner(); | 9303 constructor_class = constructor.Owner(); |
| 9292 ASSERT(type_class.raw() == constructor_class.raw()); | 9304 ASSERT(type_class.raw() == constructor_class.raw()); |
| 9293 } | 9305 } |
| 9294 if (constructor.IsFactory()) { | 9306 if (constructor.IsFactory()) { |
| 9295 // A factory does not have the implicit 'phase' parameter. | 9307 // A factory does not have the implicit 'phase' parameter. |
| 9296 arguments_length -= 1; | 9308 arguments_length -= 1; |
| 9297 } | 9309 } |
| 9298 } | 9310 } |
| 9299 | 9311 |
| 9300 // It is ok to call a factory method of an abstract class, but it is | 9312 // It is ok to call a factory method of an abstract class, but it is |
| 9301 // a dynamic error to instantiate an abstract class. | 9313 // a dynamic error to instantiate an abstract class. |
| 9302 ASSERT(!constructor.IsNull()); | 9314 ASSERT(!constructor.IsNull()); |
| 9303 if (constructor_class.is_abstract() && | 9315 if (constructor_class.is_abstract() && !constructor.IsFactory()) { |
| 9304 !constructor.IsFactory()) { | |
| 9305 ArgumentListNode* arguments = new ArgumentListNode(type_pos); | 9316 ArgumentListNode* arguments = new ArgumentListNode(type_pos); |
| 9306 arguments->Add(new LiteralNode( | 9317 arguments->Add(new LiteralNode( |
| 9307 TokenPos(), Integer::ZoneHandle(Integer::New(type_pos)))); | 9318 TokenPos(), Integer::ZoneHandle(Integer::New(type_pos)))); |
| 9308 arguments->Add(new LiteralNode( | 9319 arguments->Add(new LiteralNode( |
| 9309 TokenPos(), String::ZoneHandle(constructor_class_name.raw()))); | 9320 TokenPos(), String::ZoneHandle(constructor_class_name.raw()))); |
| 9310 const String& cls_name = | 9321 const String& cls_name = |
| 9311 String::Handle(Symbols::AbstractClassInstantiationError()); | 9322 String::Handle(Symbols::AbstractClassInstantiationError()); |
| 9312 const String& func_name = String::Handle(Symbols::ThrowNew()); | 9323 const String& func_name = String::Handle(Symbols::ThrowNew()); |
| 9313 return MakeStaticCall(cls_name, func_name, arguments); | 9324 return MakeStaticCall(cls_name, func_name, arguments); |
| 9314 } | 9325 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9392 EvaluateConstConstructorCall(constructor_class, | 9403 EvaluateConstConstructorCall(constructor_class, |
| 9393 type_arguments, | 9404 type_arguments, |
| 9394 constructor, | 9405 constructor, |
| 9395 arguments)); | 9406 arguments)); |
| 9396 if (constructor_result.IsUnhandledException()) { | 9407 if (constructor_result.IsUnhandledException()) { |
| 9397 new_object = GenerateRethrow(new_pos, constructor_result); | 9408 new_object = GenerateRethrow(new_pos, constructor_result); |
| 9398 } else { | 9409 } else { |
| 9399 const Instance& const_instance = Instance::Cast(constructor_result); | 9410 const Instance& const_instance = Instance::Cast(constructor_result); |
| 9400 new_object = new LiteralNode(new_pos, | 9411 new_object = new LiteralNode(new_pos, |
| 9401 Instance::ZoneHandle(const_instance.raw())); | 9412 Instance::ZoneHandle(const_instance.raw())); |
| 9413 if (check_result_type) { | |
| 9414 ASSERT(!type.IsMalformed()); | |
| 9415 Error& malformed_error = Error::Handle(); | |
| 9416 if (!const_instance.IsInstanceOf(type, | |
| 9417 TypeArguments::Handle(), | |
| 9418 &malformed_error)) { | |
| 9419 type = ClassFinalizer::NewFinalizedMalformedType( | |
| 9420 malformed_error, | |
| 9421 current_class(), | |
| 9422 new_pos, | |
| 9423 ClassFinalizer::kTryResolve, // No compile-time error. | |
| 9424 "const factory result is not an instance of '%s'", | |
| 9425 String::Handle(type.UserVisibleName()).ToCString()); | |
| 9426 new_object = ThrowTypeError(new_pos, type); | |
| 9427 } | |
| 9428 check_result_type = false; | |
| 9429 } | |
| 9402 } | 9430 } |
| 9403 } else { | 9431 } else { |
| 9404 CheckFunctionIsCallable(new_pos, constructor); | 9432 CheckFunctionIsCallable(new_pos, constructor); |
| 9405 CheckConstructorCallTypeArguments(new_pos, constructor, type_arguments); | 9433 CheckConstructorCallTypeArguments(new_pos, constructor, type_arguments); |
| 9406 if (!type_arguments.IsNull() && | 9434 if (!type_arguments.IsNull() && |
| 9407 !type_arguments.IsInstantiated() && | 9435 !type_arguments.IsInstantiated() && |
| 9408 (current_block_->scope->function_level() > 0)) { | 9436 (current_block_->scope->function_level() > 0)) { |
| 9409 // Make sure that the instantiator is captured. | 9437 // Make sure that the instantiator is captured. |
| 9410 CaptureInstantiator(); | 9438 CaptureInstantiator(); |
| 9411 } | 9439 } |
| 9412 // If the type argument vector is not instantiated, we verify in checked | 9440 // If the type argument vector is not instantiated, we verify in checked |
| 9413 // mode at runtime that it is within its declared bounds. | 9441 // mode at runtime that it is within its declared bounds. |
| 9414 new_object = CreateConstructorCallNode( | 9442 new_object = CreateConstructorCallNode( |
| 9415 new_pos, type_arguments, constructor, arguments); | 9443 new_pos, type_arguments, constructor, arguments); |
| 9416 } | 9444 } |
| 9445 if (check_result_type) { | |
| 9446 const String& dst_name = String::ZoneHandle(Symbols::New("factory result")); | |
|
hausner
2012/11/13 19:06:37
Would it make sense to add this string to the symb
regis
2012/11/13 19:29:26
I'll do it in a following cl. Thanks.
| |
| 9447 new_object = new AssignableNode(new_pos, new_object, type, dst_name); | |
| 9448 } | |
| 9417 return new_object; | 9449 return new_object; |
| 9418 } | 9450 } |
| 9419 | 9451 |
| 9420 | 9452 |
| 9421 String& Parser::Interpolate(ArrayNode* values) { | 9453 String& Parser::Interpolate(ArrayNode* values) { |
| 9422 const String& class_name = String::Handle(Symbols::StringBase()); | 9454 const String& class_name = String::Handle(Symbols::StringBase()); |
| 9423 const Class& cls = Class::Handle(LookupCoreClass(class_name)); | 9455 const Class& cls = Class::Handle(LookupCoreClass(class_name)); |
| 9424 ASSERT(!cls.IsNull()); | 9456 ASSERT(!cls.IsNull()); |
| 9425 const String& func_name = String::Handle(Symbols::Interpolate()); | 9457 const String& func_name = String::Handle(Symbols::Interpolate()); |
| 9426 const Function& func = | 9458 const Function& func = |
| (...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10016 void Parser::SkipQualIdent() { | 10048 void Parser::SkipQualIdent() { |
| 10017 ASSERT(IsIdentifier()); | 10049 ASSERT(IsIdentifier()); |
| 10018 ConsumeToken(); | 10050 ConsumeToken(); |
| 10019 if (CurrentToken() == Token::kPERIOD) { | 10051 if (CurrentToken() == Token::kPERIOD) { |
| 10020 ConsumeToken(); // Consume the kPERIOD token. | 10052 ConsumeToken(); // Consume the kPERIOD token. |
| 10021 ExpectIdentifier("identifier expected after '.'"); | 10053 ExpectIdentifier("identifier expected after '.'"); |
| 10022 } | 10054 } |
| 10023 } | 10055 } |
| 10024 | 10056 |
| 10025 } // namespace dart | 10057 } // namespace dart |
| OLD | NEW |