| 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 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 if (i.CheckJavascriptIntegerOverflow()) { | 425 if (i.CheckJavascriptIntegerOverflow()) { |
| 426 ReportError(TokenPos(), | 426 ReportError(TokenPos(), |
| 427 "Integer literal does not fit in a Javascript integer: %s.", | 427 "Integer literal does not fit in a Javascript integer: %s.", |
| 428 i.ToCString()); | 428 i.ToCString()); |
| 429 } | 429 } |
| 430 } | 430 } |
| 431 return ri; | 431 return ri; |
| 432 } | 432 } |
| 433 | 433 |
| 434 | 434 |
| 435 // A QualIdent is an optionally qualified identifier. | |
| 436 struct QualIdent { | |
| 437 QualIdent() { | |
| 438 Clear(); | |
| 439 } | |
| 440 void Clear() { | |
| 441 lib_prefix = NULL; | |
| 442 ident_pos = 0; | |
| 443 ident = NULL; | |
| 444 } | |
| 445 LibraryPrefix* lib_prefix; | |
| 446 intptr_t ident_pos; | |
| 447 String* ident; | |
| 448 }; | |
| 449 | |
| 450 | |
| 451 struct ParamDesc { | 435 struct ParamDesc { |
| 452 ParamDesc() | 436 ParamDesc() |
| 453 : type(NULL), | 437 : type(NULL), |
| 454 name_pos(0), | 438 name_pos(0), |
| 455 name(NULL), | 439 name(NULL), |
| 456 default_value(NULL), | 440 default_value(NULL), |
| 457 metadata(NULL), | 441 metadata(NULL), |
| 458 var(NULL), | 442 var(NULL), |
| 459 is_final(false), | 443 is_final(false), |
| 460 is_field_initializer(false), | 444 is_field_initializer(false), |
| (...skipping 2662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3123 ExpectIdentifier("identifier expected"); | 3107 ExpectIdentifier("identifier expected"); |
| 3124 ExpectToken(Token::kASSIGN); | 3108 ExpectToken(Token::kASSIGN); |
| 3125 SetAllowFunctionLiterals(false); | 3109 SetAllowFunctionLiterals(false); |
| 3126 SkipExpr(); | 3110 SkipExpr(); |
| 3127 SetAllowFunctionLiterals(true); | 3111 SetAllowFunctionLiterals(true); |
| 3128 } | 3112 } |
| 3129 } while (CurrentToken() == Token::kCOMMA); | 3113 } while (CurrentToken() == Token::kCOMMA); |
| 3130 } | 3114 } |
| 3131 | 3115 |
| 3132 | 3116 |
| 3133 void Parser::ParseQualIdent(QualIdent* qual_ident) { | 3117 // If the current identifier is a library prefix followed by a period, |
| 3134 TRACE_PARSER("ParseQualIdent"); | 3118 // consume the identifier and period, and return the resolved library |
| 3119 // prefix. |
| 3120 RawLibraryPrefix* Parser::ParsePrefix() { |
| 3135 ASSERT(IsIdentifier()); | 3121 ASSERT(IsIdentifier()); |
| 3122 // A library prefix can never stand by itself. It must be followed by |
| 3123 // a period. |
| 3124 if (LookaheadToken(1) != Token::kPERIOD) { |
| 3125 return LibraryPrefix::null(); |
| 3126 } |
| 3127 const String& ident = *CurrentLiteral(); |
| 3128 |
| 3129 // It is relatively fast to look up a name in the library dictionary, |
| 3130 // compared to searching the nested local scopes. Look up the name |
| 3131 // in the library scope and return in the common case where ident is |
| 3132 // not a library prefix. |
| 3133 LibraryPrefix& prefix = |
| 3134 LibraryPrefix::Handle(I, library_.LookupLocalLibraryPrefix(ident)); |
| 3135 if (prefix.IsNull()) { |
| 3136 return LibraryPrefix::null(); |
| 3137 } |
| 3138 |
| 3139 // A library prefix with the name exists. Now check whether it is |
| 3140 // shadowed by a local definition. |
| 3141 if (!is_top_level_ && |
| 3142 ResolveIdentInLocalScope(TokenPos(), ident, NULL)) { |
| 3143 return LibraryPrefix::null(); |
| 3144 } |
| 3145 // Check whether the identifier is shadowed by a type parameter. |
| 3136 ASSERT(!current_class().IsNull()); | 3146 ASSERT(!current_class().IsNull()); |
| 3137 qual_ident->ident_pos = TokenPos(); | 3147 if (current_class().LookupTypeParameter(ident) != TypeParameter::null()) { |
| 3138 qual_ident->ident = CurrentLiteral(); | 3148 return LibraryPrefix::null(); |
| 3139 qual_ident->lib_prefix = NULL; | 3149 } |
| 3150 |
| 3151 // We have a name that is not shadowed, followed by a period. |
| 3152 // Consume the identifier and the period. |
| 3140 ConsumeToken(); | 3153 ConsumeToken(); |
| 3141 if (CurrentToken() == Token::kPERIOD) { | 3154 ASSERT(CurrentToken() == Token::kPERIOD); // We checked above. |
| 3142 // An identifier cannot be resolved in a local scope when top level parsing. | 3155 ConsumeToken(); |
| 3143 if (is_top_level_ || | 3156 return prefix.raw(); |
| 3144 !ResolveIdentInLocalScope(qual_ident->ident_pos, | |
| 3145 *(qual_ident->ident), | |
| 3146 NULL)) { | |
| 3147 LibraryPrefix& lib_prefix = LibraryPrefix::ZoneHandle(I); | |
| 3148 if (!current_class().IsMixinApplication()) { | |
| 3149 lib_prefix = current_class().LookupLibraryPrefix(*(qual_ident->ident)); | |
| 3150 } else { | |
| 3151 // TODO(hausner): Should we resolve the prefix via the library scope | |
| 3152 // rather than via the class? | |
| 3153 Class& cls = Class::Handle(I, parsed_function()->function().origin()); | |
| 3154 lib_prefix = cls.LookupLibraryPrefix(*(qual_ident->ident)); | |
| 3155 } | |
| 3156 if (!lib_prefix.IsNull()) { | |
| 3157 // We have a library prefix qualified identifier, unless the prefix is | |
| 3158 // shadowed by a type parameter in scope. | |
| 3159 if (current_class().IsNull() || | |
| 3160 (current_class().LookupTypeParameter(*(qual_ident->ident)) == | |
| 3161 TypeParameter::null())) { | |
| 3162 ConsumeToken(); // Consume the kPERIOD token. | |
| 3163 qual_ident->lib_prefix = &lib_prefix; | |
| 3164 qual_ident->ident_pos = TokenPos(); | |
| 3165 qual_ident->ident = | |
| 3166 ExpectIdentifier("identifier expected after '.'"); | |
| 3167 } | |
| 3168 } | |
| 3169 } | |
| 3170 } | |
| 3171 } | 3157 } |
| 3172 | 3158 |
| 3173 | 3159 |
| 3174 void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) { | 3160 void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) { |
| 3175 TRACE_PARSER("ParseMethodOrConstructor"); | 3161 TRACE_PARSER("ParseMethodOrConstructor"); |
| 3176 ASSERT(CurrentToken() == Token::kLPAREN || method->IsGetter()); | 3162 ASSERT(CurrentToken() == Token::kLPAREN || method->IsGetter()); |
| 3177 ASSERT(method->type != NULL); | 3163 ASSERT(method->type != NULL); |
| 3178 ASSERT(method->name_pos > 0); | 3164 ASSERT(method->name_pos > 0); |
| 3179 ASSERT(current_member_ == method); | 3165 ASSERT(current_member_ == method); |
| 3180 | 3166 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3278 method->name->ToCString()); | 3264 method->name->ToCString()); |
| 3279 } | 3265 } |
| 3280 if (method->has_external) { | 3266 if (method->has_external) { |
| 3281 ReportError(TokenPos(), | 3267 ReportError(TokenPos(), |
| 3282 "external factory constructor '%s' may not have redirection", | 3268 "external factory constructor '%s' may not have redirection", |
| 3283 method->name->ToCString()); | 3269 method->name->ToCString()); |
| 3284 } | 3270 } |
| 3285 ConsumeToken(); | 3271 ConsumeToken(); |
| 3286 const intptr_t type_pos = TokenPos(); | 3272 const intptr_t type_pos = TokenPos(); |
| 3287 is_redirecting = true; | 3273 is_redirecting = true; |
| 3274 const bool consume_unresolved_prefix = |
| 3275 (LookaheadToken(3) == Token::kLT) || |
| 3276 (LookaheadToken(3) == Token::kPERIOD); |
| 3288 const AbstractType& type = AbstractType::Handle(I, | 3277 const AbstractType& type = AbstractType::Handle(I, |
| 3289 ParseType(ClassFinalizer::kResolveTypeParameters)); | 3278 ParseType(ClassFinalizer::kResolveTypeParameters, |
| 3279 false, // Deferred types not allowed. |
| 3280 consume_unresolved_prefix)); |
| 3290 if (!type.IsMalformed() && type.IsTypeParameter()) { | 3281 if (!type.IsMalformed() && type.IsTypeParameter()) { |
| 3291 // Replace the type with a malformed type and compile a throw when called. | 3282 // Replace the type with a malformed type and compile a throw when called. |
| 3292 redirection_type = ClassFinalizer::NewFinalizedMalformedType( | 3283 redirection_type = ClassFinalizer::NewFinalizedMalformedType( |
| 3293 Error::Handle(I), // No previous error. | 3284 Error::Handle(I), // No previous error. |
| 3294 script_, | 3285 script_, |
| 3295 type_pos, | 3286 type_pos, |
| 3296 "factory '%s' may not redirect to type parameter '%s'", | 3287 "factory '%s' may not redirect to type parameter '%s'", |
| 3297 method->name->ToCString(), | 3288 method->name->ToCString(), |
| 3298 String::Handle(I, type.UserVisibleName()).ToCString()); | 3289 String::Handle(I, type.UserVisibleName()).ToCString()); |
| 3299 } else { | 3290 } else { |
| (...skipping 2763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6063 return false; | 6054 return false; |
| 6064 } | 6055 } |
| 6065 | 6056 |
| 6066 | 6057 |
| 6067 // Returns true if the current token is kIDENT or a pseudo-keyword. | 6058 // Returns true if the current token is kIDENT or a pseudo-keyword. |
| 6068 bool Parser::IsIdentifier() { | 6059 bool Parser::IsIdentifier() { |
| 6069 return Token::IsIdentifier(CurrentToken()); | 6060 return Token::IsIdentifier(CurrentToken()); |
| 6070 } | 6061 } |
| 6071 | 6062 |
| 6072 | 6063 |
| 6064 // Returns true if the next tokens can be parsed as a an optionally |
| 6065 // qualified identifier: [ident '.'] ident. |
| 6066 // Current token position is not restored. |
| 6067 bool Parser::TryParseQualIdent() { |
| 6068 if (CurrentToken() != Token::kIDENT) { |
| 6069 return false; |
| 6070 } |
| 6071 ConsumeToken(); |
| 6072 if (CurrentToken() == Token::kPERIOD) { |
| 6073 ConsumeToken(); |
| 6074 if (CurrentToken() != Token::kIDENT) { |
| 6075 return false; |
| 6076 } |
| 6077 ConsumeToken(); |
| 6078 } |
| 6079 return true; |
| 6080 } |
| 6081 |
| 6082 |
| 6073 // Returns true if the next tokens can be parsed as a type with optional | 6083 // Returns true if the next tokens can be parsed as a type with optional |
| 6074 // type parameters. Current token position is not restored. | 6084 // type parameters. Current token position is not restored. |
| 6075 bool Parser::TryParseOptionalType() { | 6085 bool Parser::TryParseOptionalType() { |
| 6076 if (CurrentToken() == Token::kIDENT) { | 6086 if (CurrentToken() == Token::kIDENT) { |
| 6077 QualIdent type_name; | 6087 if (!TryParseQualIdent()) { |
| 6078 ParseQualIdent(&type_name); | 6088 return false; |
| 6089 } |
| 6079 if ((CurrentToken() == Token::kLT) && !TryParseTypeParameters()) { | 6090 if ((CurrentToken() == Token::kLT) && !TryParseTypeParameters()) { |
| 6080 return false; | 6091 return false; |
| 6081 } | 6092 } |
| 6082 } | 6093 } |
| 6083 return true; | 6094 return true; |
| 6084 } | 6095 } |
| 6085 | 6096 |
| 6086 | 6097 |
| 6087 // Returns true if the next tokens can be parsed as a type with optional | 6098 // Returns true if the next tokens can be parsed as a type with optional |
| 6088 // type parameters, or keyword "void". | 6099 // type parameters, or keyword "void". |
| (...skipping 3397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9486 } | 9497 } |
| 9487 } | 9498 } |
| 9488 return resolved; | 9499 return resolved; |
| 9489 } | 9500 } |
| 9490 | 9501 |
| 9491 | 9502 |
| 9492 // Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and | 9503 // Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and |
| 9493 // finalize it according to the given type finalization mode. | 9504 // finalize it according to the given type finalization mode. |
| 9494 RawAbstractType* Parser::ParseType( | 9505 RawAbstractType* Parser::ParseType( |
| 9495 ClassFinalizer::FinalizationKind finalization, | 9506 ClassFinalizer::FinalizationKind finalization, |
| 9496 bool allow_deferred_type) { | 9507 bool allow_deferred_type, |
| 9508 bool consume_unresolved_prefix) { |
| 9497 TRACE_PARSER("ParseType"); | 9509 TRACE_PARSER("ParseType"); |
| 9498 CheckToken(Token::kIDENT, "type name expected"); | 9510 CheckToken(Token::kIDENT, "type name expected"); |
| 9499 QualIdent type_name; | 9511 intptr_t ident_pos = TokenPos(); |
| 9512 LibraryPrefix& prefix = LibraryPrefix::Handle(I); |
| 9513 String& type_name = String::Handle(I);; |
| 9514 |
| 9500 if (finalization == ClassFinalizer::kIgnore) { | 9515 if (finalization == ClassFinalizer::kIgnore) { |
| 9501 if (!is_top_level_ && (current_block_ != NULL)) { | 9516 if (!is_top_level_ && (current_block_ != NULL)) { |
| 9502 // Add the library prefix or type class name to the list of referenced | 9517 // Add the library prefix or type class name to the list of referenced |
| 9503 // names of this scope, even if the type is ignored. | 9518 // names of this scope, even if the type is ignored. |
| 9504 current_block_->scope->AddReferencedName(TokenPos(), *CurrentLiteral()); | 9519 current_block_->scope->AddReferencedName(TokenPos(), *CurrentLiteral()); |
| 9505 } | 9520 } |
| 9506 SkipQualIdent(); | 9521 SkipQualIdent(); |
| 9507 } else { | 9522 } else { |
| 9508 ParseQualIdent(&type_name); | 9523 prefix = ParsePrefix(); |
| 9509 // An identifier cannot be resolved in a local scope when top level parsing. | 9524 type_name = CurrentLiteral()->raw(); |
| 9510 if (!is_top_level_ && | 9525 ConsumeToken(); |
| 9511 (type_name.lib_prefix == NULL) && | 9526 |
| 9512 ResolveIdentInLocalScope(type_name.ident_pos, *type_name.ident, NULL)) { | 9527 // Check whether we have a malformed qualified type name if the caller |
| 9528 // requests to consume unresolved prefix names: |
| 9529 // If we didn't see a valid prefix but the identifier is followed by |
| 9530 // a period and another identifier, consume the qualified identifier |
| 9531 // and create a malformed type. |
| 9532 if (consume_unresolved_prefix && |
| 9533 prefix.IsNull() && |
| 9534 (CurrentToken() == Token::kPERIOD) && |
| 9535 (Token::IsIdentifier(LookaheadToken(1)))) { |
| 9536 if (!is_top_level_ && (current_block_ != NULL)) { |
| 9537 // Add the unresolved prefix name to the list of referenced |
| 9538 // names of this scope. |
| 9539 current_block_->scope->AddReferencedName(TokenPos(), type_name); |
| 9540 } |
| 9541 ConsumeToken(); // Period token. |
| 9542 ASSERT(IsIdentifier()); |
| 9543 String& qualified_name = String::Handle(I, type_name.raw()); |
| 9544 qualified_name = String::Concat(qualified_name, Symbols::Dot()); |
| 9545 qualified_name = String::Concat(qualified_name, *CurrentLiteral()); |
| 9546 ConsumeToken(); |
| 9513 // The type is malformed. Skip over its type arguments. | 9547 // The type is malformed. Skip over its type arguments. |
| 9514 ParseTypeArguments(ClassFinalizer::kIgnore); | 9548 ParseTypeArguments(ClassFinalizer::kIgnore); |
| 9515 return ClassFinalizer::NewFinalizedMalformedType( | 9549 return ClassFinalizer::NewFinalizedMalformedType( |
| 9516 Error::Handle(I), // No previous error. | 9550 Error::Handle(I), // No previous error. |
| 9517 script_, | 9551 script_, |
| 9518 type_name.ident_pos, | 9552 ident_pos, |
| 9519 "using '%s' in this context is invalid", | 9553 "qualified name '%s' does not refer to a type", |
| 9520 type_name.ident->ToCString()); | 9554 qualified_name.ToCString()); |
| 9521 } | 9555 } |
| 9522 if ((type_name.lib_prefix != NULL) && | 9556 |
| 9523 type_name.lib_prefix->is_deferred_load() && | 9557 // If parsing inside a local scope, check whether the type name |
| 9524 !allow_deferred_type) { | 9558 // is shadowed by a local declaration. |
| 9559 if (!is_top_level_ && |
| 9560 (prefix.IsNull()) && |
| 9561 ResolveIdentInLocalScope(ident_pos, type_name, NULL)) { |
| 9562 // The type is malformed. Skip over its type arguments. |
| 9525 ParseTypeArguments(ClassFinalizer::kIgnore); | 9563 ParseTypeArguments(ClassFinalizer::kIgnore); |
| 9526 return ClassFinalizer::NewFinalizedMalformedType( | 9564 return ClassFinalizer::NewFinalizedMalformedType( |
| 9527 Error::Handle(I), // No previous error. | 9565 Error::Handle(I), // No previous error. |
| 9528 script_, | 9566 script_, |
| 9529 type_name.ident_pos, | 9567 ident_pos, |
| 9568 "using '%s' in this context is invalid", |
| 9569 type_name.ToCString()); |
| 9570 } |
| 9571 if (!prefix.IsNull() && prefix.is_deferred_load() && !allow_deferred_type) { |
| 9572 ParseTypeArguments(ClassFinalizer::kIgnore); |
| 9573 return ClassFinalizer::NewFinalizedMalformedType( |
| 9574 Error::Handle(I), // No previous error. |
| 9575 script_, |
| 9576 ident_pos, |
| 9530 "using deferred type '%s.%s' is invalid", | 9577 "using deferred type '%s.%s' is invalid", |
| 9531 String::Handle(I, type_name.lib_prefix->name()).ToCString(), | 9578 String::Handle(I, prefix.name()).ToCString(), |
| 9532 type_name.ident->ToCString()); | 9579 type_name.ToCString()); |
| 9533 } | 9580 } |
| 9534 } | 9581 } |
| 9535 Object& type_class = Object::Handle(I); | 9582 Object& type_class = Object::Handle(I); |
| 9536 // Leave type_class as null if type finalization mode is kIgnore. | 9583 // Leave type_class as null if type finalization mode is kIgnore. |
| 9537 if (finalization != ClassFinalizer::kIgnore) { | 9584 if (finalization != ClassFinalizer::kIgnore) { |
| 9538 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(I); | 9585 type_class = UnresolvedClass::New(prefix, type_name, ident_pos); |
| 9539 if (type_name.lib_prefix != NULL) { | |
| 9540 lib_prefix = type_name.lib_prefix->raw(); | |
| 9541 } | |
| 9542 type_class = UnresolvedClass::New(lib_prefix, | |
| 9543 *type_name.ident, | |
| 9544 type_name.ident_pos); | |
| 9545 } | 9586 } |
| 9546 TypeArguments& type_arguments = TypeArguments::Handle( | 9587 TypeArguments& type_arguments = TypeArguments::Handle( |
| 9547 I, ParseTypeArguments(finalization)); | 9588 I, ParseTypeArguments(finalization)); |
| 9548 if (finalization == ClassFinalizer::kIgnore) { | 9589 if (finalization == ClassFinalizer::kIgnore) { |
| 9549 return Type::DynamicType(); | 9590 return Type::DynamicType(); |
| 9550 } | 9591 } |
| 9551 AbstractType& type = AbstractType::Handle( | 9592 AbstractType& type = AbstractType::Handle( |
| 9552 I, Type::New(type_class, type_arguments, type_name.ident_pos)); | 9593 I, Type::New(type_class, type_arguments, ident_pos)); |
| 9553 if (finalization >= ClassFinalizer::kResolveTypeParameters) { | 9594 if (finalization >= ClassFinalizer::kResolveTypeParameters) { |
| 9554 ResolveTypeFromClass(current_class(), finalization, &type); | 9595 ResolveTypeFromClass(current_class(), finalization, &type); |
| 9555 if (finalization >= ClassFinalizer::kCanonicalize) { | 9596 if (finalization >= ClassFinalizer::kCanonicalize) { |
| 9556 type ^= ClassFinalizer::FinalizeType(current_class(), type, finalization); | 9597 type ^= ClassFinalizer::FinalizeType(current_class(), type, finalization); |
| 9557 } | 9598 } |
| 9558 } | 9599 } |
| 9559 return type.raw(); | 9600 return type.raw(); |
| 9560 } | 9601 } |
| 9561 | 9602 |
| 9562 | 9603 |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10084 TRACE_PARSER("ParseNewOperator"); | 10125 TRACE_PARSER("ParseNewOperator"); |
| 10085 const intptr_t new_pos = TokenPos(); | 10126 const intptr_t new_pos = TokenPos(); |
| 10086 ASSERT((op_kind == Token::kNEW) || (op_kind == Token::kCONST)); | 10127 ASSERT((op_kind == Token::kNEW) || (op_kind == Token::kCONST)); |
| 10087 bool is_const = (op_kind == Token::kCONST); | 10128 bool is_const = (op_kind == Token::kCONST); |
| 10088 if (!IsIdentifier()) { | 10129 if (!IsIdentifier()) { |
| 10089 ReportError("type name expected"); | 10130 ReportError("type name expected"); |
| 10090 } | 10131 } |
| 10091 intptr_t type_pos = TokenPos(); | 10132 intptr_t type_pos = TokenPos(); |
| 10092 // Can't allocate const objects of a deferred type. | 10133 // Can't allocate const objects of a deferred type. |
| 10093 const bool allow_deferred_type = !is_const; | 10134 const bool allow_deferred_type = !is_const; |
| 10135 const bool consume_unresolved_prefix = (LookaheadToken(3) == Token::kLT) || |
| 10136 (LookaheadToken(3) == Token::kPERIOD); |
| 10094 AbstractType& type = AbstractType::Handle(I, | 10137 AbstractType& type = AbstractType::Handle(I, |
| 10095 ParseType(ClassFinalizer::kCanonicalizeWellFormed, allow_deferred_type)); | 10138 ParseType(ClassFinalizer::kCanonicalizeWellFormed, |
| 10139 allow_deferred_type, |
| 10140 consume_unresolved_prefix)); |
| 10096 // In case the type is malformed, throw a dynamic type error after finishing | 10141 // In case the type is malformed, throw a dynamic type error after finishing |
| 10097 // parsing the instance creation expression. | 10142 // parsing the instance creation expression. |
| 10098 if (!type.IsMalformed() && (type.IsTypeParameter() || type.IsDynamicType())) { | 10143 if (!type.IsMalformed() && (type.IsTypeParameter() || type.IsDynamicType())) { |
| 10099 // Replace the type with a malformed type. | 10144 // Replace the type with a malformed type. |
| 10100 type = ClassFinalizer::NewFinalizedMalformedType( | 10145 type = ClassFinalizer::NewFinalizedMalformedType( |
| 10101 Error::Handle(I), // No previous error. | 10146 Error::Handle(I), // No previous error. |
| 10102 script_, | 10147 script_, |
| 10103 type_pos, | 10148 type_pos, |
| 10104 "%s'%s' cannot be instantiated", | 10149 "%s'%s' cannot be instantiated", |
| 10105 type.IsTypeParameter() ? "type parameter " : "", | 10150 type.IsTypeParameter() ? "type parameter " : "", |
| 10106 type.IsTypeParameter() ? | 10151 type.IsTypeParameter() ? |
| 10107 String::Handle(I, type.UserVisibleName()).ToCString() : | 10152 String::Handle(I, type.UserVisibleName()).ToCString() : |
| 10108 "dynamic"); | 10153 "dynamic"); |
| 10109 } | 10154 } |
| 10110 | 10155 |
| 10111 // The grammar allows for an optional ('.' identifier)? after the type, which | 10156 // The grammar allows for an optional ('.' identifier)? after the type, which |
| 10112 // is a named constructor. Note that ParseType() above will not consume it as | 10157 // is a named constructor. Note that we tell ParseType() above not to |
| 10113 // part of a misinterpreted qualified identifier, because only a valid library | 10158 // consume it as part of a misinterpreted qualified identifier. Only a |
| 10114 // prefix is accepted as qualifier. | 10159 // valid library prefix is accepted as qualifier. |
| 10115 String* named_constructor = NULL; | 10160 String* named_constructor = NULL; |
| 10116 if (CurrentToken() == Token::kPERIOD) { | 10161 if (CurrentToken() == Token::kPERIOD) { |
| 10117 ConsumeToken(); | 10162 ConsumeToken(); |
| 10118 named_constructor = ExpectIdentifier("name of constructor expected"); | 10163 named_constructor = ExpectIdentifier("name of constructor expected"); |
| 10119 } | 10164 } |
| 10120 | 10165 |
| 10121 // Parse constructor parameters. | 10166 // Parse constructor parameters. |
| 10122 CheckToken(Token::kLPAREN); | 10167 CheckToken(Token::kLPAREN); |
| 10123 intptr_t call_pos = TokenPos(); | 10168 intptr_t call_pos = TokenPos(); |
| 10124 ArgumentListNode* arguments = ParseActualParameters(NULL, is_const); | 10169 ArgumentListNode* arguments = ParseActualParameters(NULL, is_const); |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10475 ASSERT(!is_top_level_); | 10520 ASSERT(!is_top_level_); |
| 10476 AstNode* primary = NULL; | 10521 AstNode* primary = NULL; |
| 10477 const Token::Kind token = CurrentToken(); | 10522 const Token::Kind token = CurrentToken(); |
| 10478 if (IsFunctionLiteral()) { | 10523 if (IsFunctionLiteral()) { |
| 10479 // The name of a literal function is visible from inside the function, but | 10524 // The name of a literal function is visible from inside the function, but |
| 10480 // must not collide with names in the scope declaring the literal. | 10525 // must not collide with names in the scope declaring the literal. |
| 10481 OpenBlock(); | 10526 OpenBlock(); |
| 10482 primary = ParseFunctionStatement(true); | 10527 primary = ParseFunctionStatement(true); |
| 10483 CloseBlock(); | 10528 CloseBlock(); |
| 10484 } else if (IsIdentifier()) { | 10529 } else if (IsIdentifier()) { |
| 10485 QualIdent qual_ident; | |
| 10486 intptr_t qual_ident_pos = TokenPos(); | 10530 intptr_t qual_ident_pos = TokenPos(); |
| 10487 ParseQualIdent(&qual_ident); | 10531 const LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(I, ParsePrefix()); |
| 10488 if (qual_ident.lib_prefix == NULL) { | 10532 String& ident = *CurrentLiteral(); |
| 10489 if (!ResolveIdentInLocalScope(qual_ident.ident_pos, | 10533 ConsumeToken(); |
| 10490 *qual_ident.ident, | 10534 if (prefix.IsNull()) { |
| 10491 &primary)) { | 10535 if (!ResolveIdentInLocalScope(qual_ident_pos, ident, &primary)) { |
| 10492 // Check whether the identifier is a type parameter. | 10536 // Check whether the identifier is a type parameter. |
| 10493 if (!current_class().IsNull()) { | 10537 if (!current_class().IsNull()) { |
| 10494 TypeParameter& type_param = TypeParameter::ZoneHandle(I, | 10538 TypeParameter& type_param = TypeParameter::ZoneHandle(I, |
| 10495 current_class().LookupTypeParameter(*(qual_ident.ident))); | 10539 current_class().LookupTypeParameter(ident)); |
| 10496 if (!type_param.IsNull()) { | 10540 if (!type_param.IsNull()) { |
| 10497 return new(I) PrimaryNode(qual_ident.ident_pos, type_param); | 10541 return new(I) PrimaryNode(qual_ident_pos, type_param); |
| 10498 } | 10542 } |
| 10499 } | 10543 } |
| 10500 // This is a non-local unqualified identifier so resolve the | 10544 // This is a non-local unqualified identifier so resolve the |
| 10501 // identifier locally in the main app library and all libraries | 10545 // identifier locally in the main app library and all libraries |
| 10502 // imported by it. | 10546 // imported by it. |
| 10503 primary = ResolveIdentInCurrentLibraryScope(qual_ident.ident_pos, | 10547 primary = ResolveIdentInCurrentLibraryScope(qual_ident_pos, ident); |
| 10504 *qual_ident.ident); | |
| 10505 } | 10548 } |
| 10506 } else { | 10549 } else { |
| 10507 // This is a qualified identifier with a library prefix so resolve | 10550 // This is a qualified identifier with a library prefix so resolve |
| 10508 // the identifier locally in that library (we do not include the | 10551 // the identifier locally in that library (we do not include the |
| 10509 // libraries imported by that library). | 10552 // libraries imported by that library). |
| 10510 primary = ResolveIdentInPrefixScope(qual_ident.ident_pos, | 10553 primary = ResolveIdentInPrefixScope(qual_ident_pos, prefix, ident); |
| 10511 *qual_ident.lib_prefix, | 10554 |
| 10512 *qual_ident.ident); | |
| 10513 // If the identifier could not be resolved, throw a NoSuchMethodError. | 10555 // If the identifier could not be resolved, throw a NoSuchMethodError. |
| 10514 // Note: unlike in the case of an unqualified identifier, do not | 10556 // Note: unlike in the case of an unqualified identifier, do not |
| 10515 // interpret the unresolved identifier as an instance method or | 10557 // interpret the unresolved identifier as an instance method or |
| 10516 // instance getter call when compiling an instance method. | 10558 // instance getter call when compiling an instance method. |
| 10517 if (primary == NULL) { | 10559 if (primary == NULL) { |
| 10518 if (qual_ident.lib_prefix->is_deferred_load() && | 10560 if (prefix.is_deferred_load() && |
| 10519 qual_ident.ident->Equals(Symbols::LoadLibrary())) { | 10561 ident.Equals(Symbols::LoadLibrary())) { |
| 10520 // Hack Alert: recognize special 'loadLibrary' call on the | 10562 // Hack Alert: recognize special 'loadLibrary' call on the |
| 10521 // prefix object. The prefix is the primary. Rewind parser and | 10563 // prefix object. The prefix is the primary. Rewind parser and |
| 10522 // let ParseSelectors() handle the loadLibrary call. | 10564 // let ParseSelectors() handle the loadLibrary call. |
| 10523 SetPosition(qual_ident_pos); | 10565 SetPosition(qual_ident_pos); |
| 10524 ConsumeToken(); // Prefix name. | 10566 ConsumeToken(); // Prefix name. |
| 10525 primary = new(I) LiteralNode(qual_ident_pos, *qual_ident.lib_prefix); | 10567 primary = new(I) LiteralNode(qual_ident_pos, prefix); |
| 10526 } else { | 10568 } else { |
| 10527 // TODO(hausner): Ideally we should generate the NoSuchMethodError | 10569 // TODO(hausner): Ideally we should generate the NoSuchMethodError |
| 10528 // later, when we know more about how the unresolved name is used. | 10570 // later, when we know more about how the unresolved name is used. |
| 10529 // For example, we don't know yet whether the unresolved name | 10571 // For example, we don't know yet whether the unresolved name |
| 10530 // refers to a getter or a setter. However, it is more awkward | 10572 // refers to a getter or a setter. However, it is more awkward |
| 10531 // to distinuish four NoSuchMethodError cases all over the place | 10573 // to distinuish four NoSuchMethodError cases all over the place |
| 10532 // in the parser. The four cases are: prefixed vs non-prefixed | 10574 // in the parser. The four cases are: prefixed vs non-prefixed |
| 10533 // name, static vs dynamic context in which the unresolved name | 10575 // name, static vs dynamic context in which the unresolved name |
| 10534 // is used. We cheat a little here by looking at the next token | 10576 // is used. We cheat a little here by looking at the next token |
| 10535 // to determine whether we have an unresolved method call or | 10577 // to determine whether we have an unresolved method call or |
| 10536 // field access. | 10578 // field access. |
| 10537 String& qualified_name = | 10579 String& qualified_name = String::ZoneHandle(I, prefix.name()); |
| 10538 String::ZoneHandle(I, qual_ident.lib_prefix->name()); | |
| 10539 qualified_name = String::Concat(qualified_name, Symbols::Dot()); | 10580 qualified_name = String::Concat(qualified_name, Symbols::Dot()); |
| 10540 qualified_name = String::Concat(qualified_name, *qual_ident.ident); | 10581 qualified_name = String::Concat(qualified_name, ident); |
| 10541 qualified_name = Symbols::New(qualified_name); | 10582 qualified_name = Symbols::New(qualified_name); |
| 10542 InvocationMirror::Type call_type = | 10583 InvocationMirror::Type call_type = |
| 10543 CurrentToken() == Token::kLPAREN ? | 10584 CurrentToken() == Token::kLPAREN ? |
| 10544 InvocationMirror::kMethod : InvocationMirror::kGetter; | 10585 InvocationMirror::kMethod : InvocationMirror::kGetter; |
| 10545 primary = ThrowNoSuchMethodError(qual_ident_pos, | 10586 primary = ThrowNoSuchMethodError(qual_ident_pos, |
| 10546 current_class(), | 10587 current_class(), |
| 10547 qualified_name, | 10588 qualified_name, |
| 10548 NULL, // No arguments. | 10589 NULL, // No arguments. |
| 10549 InvocationMirror::kTopLevel, | 10590 InvocationMirror::kTopLevel, |
| 10550 call_type, | 10591 call_type, |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11016 void Parser::SkipQualIdent() { | 11057 void Parser::SkipQualIdent() { |
| 11017 ASSERT(IsIdentifier()); | 11058 ASSERT(IsIdentifier()); |
| 11018 ConsumeToken(); | 11059 ConsumeToken(); |
| 11019 if (CurrentToken() == Token::kPERIOD) { | 11060 if (CurrentToken() == Token::kPERIOD) { |
| 11020 ConsumeToken(); // Consume the kPERIOD token. | 11061 ConsumeToken(); // Consume the kPERIOD token. |
| 11021 ExpectIdentifier("identifier expected after '.'"); | 11062 ExpectIdentifier("identifier expected after '.'"); |
| 11022 } | 11063 } |
| 11023 } | 11064 } |
| 11024 | 11065 |
| 11025 } // namespace dart | 11066 } // namespace dart |
| OLD | NEW |