| 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 "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
| 9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 2833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2844 ConsumeToken(); | 2844 ConsumeToken(); |
| 2845 ParseStatementSequence(); | 2845 ParseStatementSequence(); |
| 2846 ExpectToken(Token::kRBRACE); | 2846 ExpectToken(Token::kRBRACE); |
| 2847 } else if (CurrentToken() == Token::kARROW) { | 2847 } else if (CurrentToken() == Token::kARROW) { |
| 2848 ErrorMsg("constructors may not return a value"); | 2848 ErrorMsg("constructors may not return a value"); |
| 2849 } else if (IsLiteral("native")) { | 2849 } else if (IsLiteral("native")) { |
| 2850 ErrorMsg("native constructors not supported"); | 2850 ErrorMsg("native constructors not supported"); |
| 2851 } else if (CurrentToken() == Token::kSEMICOLON) { | 2851 } else if (CurrentToken() == Token::kSEMICOLON) { |
| 2852 // Some constructors have no function body. | 2852 // Some constructors have no function body. |
| 2853 ConsumeToken(); | 2853 ConsumeToken(); |
| 2854 if (func.is_external()) { |
| 2855 // Body of an external method contains a single throw. |
| 2856 const String& function_name = String::ZoneHandle(func.name()); |
| 2857 current_block_->statements->Add( |
| 2858 ThrowNoSuchMethodError(TokenPos(), |
| 2859 cls, |
| 2860 function_name, |
| 2861 NULL, // No arguments. |
| 2862 InvocationMirror::kStatic, |
| 2863 InvocationMirror::kMethod, |
| 2864 NULL)); // No existing function. |
| 2865 } |
| 2854 } else { | 2866 } else { |
| 2855 UnexpectedToken(); | 2867 UnexpectedToken(); |
| 2856 } | 2868 } |
| 2857 | 2869 |
| 2858 SequenceNode* ctor_block = CloseBlock(); | 2870 SequenceNode* ctor_block = CloseBlock(); |
| 2859 if (ctor_block->length() > 0) { | 2871 if (ctor_block->length() > 0) { |
| 2860 // Generate guard around the constructor body code. | 2872 // Generate guard around the constructor body code. |
| 2861 LocalVariable* phase_param = LookupPhaseParameter(); | 2873 LocalVariable* phase_param = LookupPhaseParameter(); |
| 2862 AstNode* phase_value = | 2874 AstNode* phase_value = |
| 2863 new LoadLocalNode(Scanner::kNoSourcePos, phase_param); | 2875 new LoadLocalNode(Scanner::kNoSourcePos, phase_param); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3013 } | 3025 } |
| 3014 } | 3026 } |
| 3015 ParseNativeFunctionBlock(¶ms, func); | 3027 ParseNativeFunctionBlock(¶ms, func); |
| 3016 end_token_pos = TokenPos(); | 3028 end_token_pos = TokenPos(); |
| 3017 ExpectSemicolon(); | 3029 ExpectSemicolon(); |
| 3018 } else if (func.is_external()) { | 3030 } else if (func.is_external()) { |
| 3019 // Body of an external method contains a single throw. | 3031 // Body of an external method contains a single throw. |
| 3020 const String& function_name = String::ZoneHandle(I, func.name()); | 3032 const String& function_name = String::ZoneHandle(I, func.name()); |
| 3021 current_block_->statements->Add( | 3033 current_block_->statements->Add( |
| 3022 ThrowNoSuchMethodError(TokenPos(), | 3034 ThrowNoSuchMethodError(TokenPos(), |
| 3023 current_class(), | 3035 Class::Handle(func.Owner()), |
| 3024 function_name, | 3036 function_name, |
| 3025 NULL, // Ignore arguments. | 3037 NULL, // Ignore arguments. |
| 3026 func.is_static() ? | 3038 func.is_static() ? |
| 3027 InvocationMirror::kStatic : | 3039 InvocationMirror::kStatic : |
| 3028 InvocationMirror::kDynamic, | 3040 InvocationMirror::kDynamic, |
| 3029 InvocationMirror::kMethod, | 3041 InvocationMirror::kMethod, |
| 3030 &func)); // Unpatched external function. | 3042 &func)); // Unpatched external function. |
| 3031 end_token_pos = TokenPos(); | 3043 end_token_pos = TokenPos(); |
| 3032 } else { | 3044 } else { |
| 3033 UnexpectedToken(); | 3045 UnexpectedToken(); |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3260 Type& redirection_type = Type::Handle(isolate()); | 3272 Type& redirection_type = Type::Handle(isolate()); |
| 3261 String& redirection_identifier = String::Handle(isolate()); | 3273 String& redirection_identifier = String::Handle(isolate()); |
| 3262 bool is_redirecting = false; | 3274 bool is_redirecting = false; |
| 3263 if (method->IsFactory() && (CurrentToken() == Token::kASSIGN)) { | 3275 if (method->IsFactory() && (CurrentToken() == Token::kASSIGN)) { |
| 3264 // Default parameter values are disallowed in redirecting factories. | 3276 // Default parameter values are disallowed in redirecting factories. |
| 3265 if (method->params.has_explicit_default_values) { | 3277 if (method->params.has_explicit_default_values) { |
| 3266 ErrorMsg("redirecting factory '%s' may not specify default values " | 3278 ErrorMsg("redirecting factory '%s' may not specify default values " |
| 3267 "for optional parameters", | 3279 "for optional parameters", |
| 3268 method->name->ToCString()); | 3280 method->name->ToCString()); |
| 3269 } | 3281 } |
| 3282 if (method->has_external) { |
| 3283 ErrorMsg(TokenPos(), |
| 3284 "external factory constructor '%s' may not have redirection", |
| 3285 method->name->ToCString()); |
| 3286 } |
| 3270 ConsumeToken(); | 3287 ConsumeToken(); |
| 3271 const intptr_t type_pos = TokenPos(); | 3288 const intptr_t type_pos = TokenPos(); |
| 3272 is_redirecting = true; | 3289 is_redirecting = true; |
| 3273 const AbstractType& type = AbstractType::Handle(isolate(), | 3290 const AbstractType& type = AbstractType::Handle(isolate(), |
| 3274 ParseType(ClassFinalizer::kResolveTypeParameters)); | 3291 ParseType(ClassFinalizer::kResolveTypeParameters)); |
| 3275 if (!type.IsMalformed() && type.IsTypeParameter()) { | 3292 if (!type.IsMalformed() && type.IsTypeParameter()) { |
| 3276 // Replace the type with a malformed type and compile a throw when called. | 3293 // Replace the type with a malformed type and compile a throw when called. |
| 3277 redirection_type = ClassFinalizer::NewFinalizedMalformedType( | 3294 redirection_type = ClassFinalizer::NewFinalizedMalformedType( |
| 3278 Error::Handle(isolate()), // No previous error. | 3295 Error::Handle(isolate()), // No previous error. |
| 3279 script_, | 3296 script_, |
| 3280 type_pos, | 3297 type_pos, |
| 3281 "factory '%s' may not redirect to type parameter '%s'", | 3298 "factory '%s' may not redirect to type parameter '%s'", |
| 3282 method->name->ToCString(), | 3299 method->name->ToCString(), |
| 3283 String::Handle(isolate(), type.UserVisibleName()).ToCString()); | 3300 String::Handle(isolate(), type.UserVisibleName()).ToCString()); |
| 3284 } else { | 3301 } else { |
| 3285 // We handle malformed and malbounded redirection type at run time. | 3302 // We handle malformed and malbounded redirection type at run time. |
| 3286 redirection_type ^= type.raw(); | 3303 redirection_type ^= type.raw(); |
| 3287 } | 3304 } |
| 3288 if (CurrentToken() == Token::kPERIOD) { | 3305 if (CurrentToken() == Token::kPERIOD) { |
| 3289 // Named constructor or factory. | 3306 // Named constructor or factory. |
| 3290 ConsumeToken(); | 3307 ConsumeToken(); |
| 3291 redirection_identifier = ExpectIdentifier("identifier expected")->raw(); | 3308 redirection_identifier = ExpectIdentifier("identifier expected")->raw(); |
| 3292 } | 3309 } |
| 3293 } else if (CurrentToken() == Token::kCOLON) { | 3310 } else if (CurrentToken() == Token::kCOLON) { |
| 3294 // Parse initializers. | 3311 // Parse initializers. |
| 3295 if (!method->IsConstructor()) { | 3312 if (!method->IsConstructor()) { |
| 3296 ErrorMsg("initializers only allowed on constructors"); | 3313 ErrorMsg("initializers only allowed on constructors"); |
| 3297 } | 3314 } |
| 3315 if (method->has_external) { |
| 3316 ErrorMsg(TokenPos(), |
| 3317 "external constructor '%s' may not have initializers", |
| 3318 method->name->ToCString()); |
| 3319 } |
| 3298 if ((LookaheadToken(1) == Token::kTHIS) && | 3320 if ((LookaheadToken(1) == Token::kTHIS) && |
| 3299 ((LookaheadToken(2) == Token::kLPAREN) || | 3321 ((LookaheadToken(2) == Token::kLPAREN) || |
| 3300 LookaheadToken(4) == Token::kLPAREN)) { | 3322 LookaheadToken(4) == Token::kLPAREN)) { |
| 3301 // Redirected constructor: either this(...) or this.xxx(...). | 3323 // Redirected constructor: either this(...) or this.xxx(...). |
| 3302 is_redirecting = true; | 3324 is_redirecting = true; |
| 3303 if (method->params.has_field_initializer) { | 3325 if (method->params.has_field_initializer) { |
| 3304 // Constructors that redirect to another constructor must not | 3326 // Constructors that redirect to another constructor must not |
| 3305 // initialize any fields using field initializer parameters. | 3327 // initialize any fields using field initializer parameters. |
| 3306 ErrorMsg(formal_param_pos, "Redirecting constructor " | 3328 ErrorMsg(formal_param_pos, "Redirecting constructor " |
| 3307 "may not use field initializer parameters"); | 3329 "may not use field initializer parameters"); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3319 CheckToken(Token::kLPAREN); | 3341 CheckToken(Token::kLPAREN); |
| 3320 SkipToMatchingParenthesis(); | 3342 SkipToMatchingParenthesis(); |
| 3321 } else { | 3343 } else { |
| 3322 SkipInitializers(); | 3344 SkipInitializers(); |
| 3323 } | 3345 } |
| 3324 } | 3346 } |
| 3325 | 3347 |
| 3326 // Only constructors can redirect to another method. | 3348 // Only constructors can redirect to another method. |
| 3327 ASSERT((method->redirect_name == NULL) || method->IsConstructor()); | 3349 ASSERT((method->redirect_name == NULL) || method->IsConstructor()); |
| 3328 | 3350 |
| 3351 if (method->IsConstructor() && |
| 3352 method->has_external && |
| 3353 method->params.has_field_initializer) { |
| 3354 ErrorMsg(method->name_pos, |
| 3355 "external constructor '%s' may not have field initializers", |
| 3356 method->name->ToCString()); |
| 3357 } |
| 3358 |
| 3329 intptr_t method_end_pos = TokenPos(); | 3359 intptr_t method_end_pos = TokenPos(); |
| 3330 if ((CurrentToken() == Token::kLBRACE) || | 3360 if ((CurrentToken() == Token::kLBRACE) || |
| 3331 (CurrentToken() == Token::kARROW)) { | 3361 (CurrentToken() == Token::kARROW)) { |
| 3332 if (method->has_abstract) { | 3362 if (method->has_abstract) { |
| 3333 ErrorMsg(method->name_pos, | 3363 ErrorMsg(TokenPos(), |
| 3334 "abstract method '%s' may not have a function body", | 3364 "abstract method '%s' may not have a function body", |
| 3335 method->name->ToCString()); | 3365 method->name->ToCString()); |
| 3336 } else if (method->has_external) { | 3366 } else if (method->has_external) { |
| 3337 ErrorMsg(method->name_pos, | 3367 ErrorMsg(TokenPos(), |
| 3338 "external method '%s' may not have a function body", | 3368 "external %s '%s' may not have a function body", |
| 3369 method->IsFactoryOrConstructor() ? "constructor" : "method", |
| 3339 method->name->ToCString()); | 3370 method->name->ToCString()); |
| 3340 } else if (method->IsConstructor() && method->has_const) { | 3371 } else if (method->IsConstructor() && method->has_const) { |
| 3341 ErrorMsg(method->name_pos, | 3372 ErrorMsg(TokenPos(), |
| 3342 "const constructor '%s' may not have a function body", | 3373 "const constructor '%s' may not have a function body", |
| 3343 method->name->ToCString()); | 3374 method->name->ToCString()); |
| 3344 } else if (method->IsFactory() && method->has_const) { | 3375 } else if (method->IsFactory() && method->has_const) { |
| 3345 ErrorMsg(method->name_pos, | 3376 ErrorMsg(TokenPos(), |
| 3346 "const factory '%s' may not have a function body", | 3377 "const factory '%s' may not have a function body", |
| 3347 method->name->ToCString()); | 3378 method->name->ToCString()); |
| 3348 } | 3379 } |
| 3349 if (method->redirect_name != NULL) { | 3380 if (method->redirect_name != NULL) { |
| 3350 ErrorMsg(method->name_pos, | 3381 ErrorMsg(method->name_pos, |
| 3351 "Constructor with redirection may not have a function body"); | 3382 "Constructor with redirection may not have a function body"); |
| 3352 } | 3383 } |
| 3353 if (CurrentToken() == Token::kLBRACE) { | 3384 if (CurrentToken() == Token::kLBRACE) { |
| 3354 SkipBlock(); | 3385 SkipBlock(); |
| 3355 method_end_pos = TokenPos(); | 3386 method_end_pos = TokenPos(); |
| (...skipping 7679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11035 void Parser::SkipQualIdent() { | 11066 void Parser::SkipQualIdent() { |
| 11036 ASSERT(IsIdentifier()); | 11067 ASSERT(IsIdentifier()); |
| 11037 ConsumeToken(); | 11068 ConsumeToken(); |
| 11038 if (CurrentToken() == Token::kPERIOD) { | 11069 if (CurrentToken() == Token::kPERIOD) { |
| 11039 ConsumeToken(); // Consume the kPERIOD token. | 11070 ConsumeToken(); // Consume the kPERIOD token. |
| 11040 ExpectIdentifier("identifier expected after '.'"); | 11071 ExpectIdentifier("identifier expected after '.'"); |
| 11041 } | 11072 } |
| 11042 } | 11073 } |
| 11043 | 11074 |
| 11044 } // namespace dart | 11075 } // namespace dart |
| OLD | NEW |