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 13 matching lines...) Expand all Loading... |
24 | 24 |
25 DEFINE_FLAG(bool, constructor_name_check, false, | 25 DEFINE_FLAG(bool, constructor_name_check, false, |
26 "Named constructors may not clash with other members"); | 26 "Named constructors may not clash with other members"); |
27 DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements."); | 27 DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements."); |
28 DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks."); | 28 DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks."); |
29 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); | 29 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); |
30 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); | 30 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); |
31 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); | 31 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); |
32 DEFINE_FLAG(bool, warn_legacy_map_literal, false, | 32 DEFINE_FLAG(bool, warn_legacy_map_literal, false, |
33 "Warning on legacy map literal syntax (single type argument)"); | 33 "Warning on legacy map literal syntax (single type argument)"); |
| 34 DEFINE_FLAG(bool, warn_legacy_dynamic, false, |
| 35 "Warning on legacy type Dynamic)"); |
34 | 36 |
35 static void CheckedModeHandler(bool value) { | 37 static void CheckedModeHandler(bool value) { |
36 FLAG_enable_asserts = value; | 38 FLAG_enable_asserts = value; |
37 FLAG_enable_type_checks = value; | 39 FLAG_enable_type_checks = value; |
38 } | 40 } |
39 | 41 |
40 // --enable-checked-mode and --checked both enable checked mode which is | 42 // --enable-checked-mode and --checked both enable checked mode which is |
41 // equivalent to setting --enable-asserts and --enable-type-checks. | 43 // equivalent to setting --enable-asserts and --enable-type-checks. |
42 DEFINE_FLAG_HANDLER(CheckedModeHandler, | 44 DEFINE_FLAG_HANDLER(CheckedModeHandler, |
43 enable_checked_mode, | 45 enable_checked_mode, |
(...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1007 bool var_seen = false; | 1009 bool var_seen = false; |
1008 bool this_seen = false; | 1010 bool this_seen = false; |
1009 | 1011 |
1010 SkipMetadata(); | 1012 SkipMetadata(); |
1011 if (CurrentToken() == Token::kFINAL) { | 1013 if (CurrentToken() == Token::kFINAL) { |
1012 ConsumeToken(); | 1014 ConsumeToken(); |
1013 parameter.is_final = true; | 1015 parameter.is_final = true; |
1014 } else if (CurrentToken() == Token::kVAR) { | 1016 } else if (CurrentToken() == Token::kVAR) { |
1015 ConsumeToken(); | 1017 ConsumeToken(); |
1016 var_seen = true; | 1018 var_seen = true; |
1017 // The parameter type is the 'Dynamic' type. | 1019 // The parameter type is the 'dynamic' type. |
1018 parameter.type = &Type::ZoneHandle(Type::DynamicType()); | 1020 parameter.type = &Type::ZoneHandle(Type::DynamicType()); |
1019 } | 1021 } |
1020 if (CurrentToken() == Token::kTHIS) { | 1022 if (CurrentToken() == Token::kTHIS) { |
1021 ConsumeToken(); | 1023 ConsumeToken(); |
1022 ExpectToken(Token::kPERIOD); | 1024 ExpectToken(Token::kPERIOD); |
1023 this_seen = true; | 1025 this_seen = true; |
1024 parameter.is_field_initializer = true; | 1026 parameter.is_field_initializer = true; |
1025 } | 1027 } |
1026 if (params->implicitly_final) { | 1028 if (params->implicitly_final) { |
1027 parameter.is_final = true; | 1029 parameter.is_final = true; |
(...skipping 1837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2865 } | 2867 } |
2866 if (CurrentToken() == Token::kVAR) { | 2868 if (CurrentToken() == Token::kVAR) { |
2867 if (member.has_const) { | 2869 if (member.has_const) { |
2868 ErrorMsg("identifier expected after 'const'"); | 2870 ErrorMsg("identifier expected after 'const'"); |
2869 } | 2871 } |
2870 if (member.has_final) { | 2872 if (member.has_final) { |
2871 ErrorMsg("identifier expected after 'final'"); | 2873 ErrorMsg("identifier expected after 'final'"); |
2872 } | 2874 } |
2873 ConsumeToken(); | 2875 ConsumeToken(); |
2874 member.has_var = true; | 2876 member.has_var = true; |
2875 // The member type is the 'Dynamic' type. | 2877 // The member type is the 'dynamic' type. |
2876 member.type = &Type::ZoneHandle(Type::DynamicType()); | 2878 member.type = &Type::ZoneHandle(Type::DynamicType()); |
2877 } else if (CurrentToken() == Token::kFACTORY) { | 2879 } else if (CurrentToken() == Token::kFACTORY) { |
2878 ConsumeToken(); | 2880 ConsumeToken(); |
2879 if (member.has_static) { | 2881 if (member.has_static) { |
2880 ErrorMsg("factory method cannot be explicitly marked static"); | 2882 ErrorMsg("factory method cannot be explicitly marked static"); |
2881 } | 2883 } |
2882 member.has_factory = true; | 2884 member.has_factory = true; |
2883 member.has_static = true; | 2885 member.has_static = true; |
2884 // The result type depends on the name of the factory method. | 2886 // The result type depends on the name of the factory method. |
2885 } | 2887 } |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2989 (LookaheadToken(1) != Token::kCOMMA) && | 2991 (LookaheadToken(1) != Token::kCOMMA) && |
2990 (LookaheadToken(1) != Token::kSEMICOLON)) { | 2992 (LookaheadToken(1) != Token::kSEMICOLON)) { |
2991 ConsumeToken(); | 2993 ConsumeToken(); |
2992 member.kind = RawFunction::kSetterFunction; | 2994 member.kind = RawFunction::kSetterFunction; |
2993 member.name_pos = this->TokenPos(); | 2995 member.name_pos = this->TokenPos(); |
2994 member.name = ExpectIdentifier("identifier expected"); | 2996 member.name = ExpectIdentifier("identifier expected"); |
2995 if (CurrentToken() != Token::kLPAREN) { | 2997 if (CurrentToken() != Token::kLPAREN) { |
2996 ErrorMsg("'(' expected"); | 2998 ErrorMsg("'(' expected"); |
2997 } | 2999 } |
2998 // The grammar allows a return type, so member.type is not always NULL here. | 3000 // The grammar allows a return type, so member.type is not always NULL here. |
2999 // If no return type is specified, the return type of the setter is Dynamic. | 3001 // If no return type is specified, the return type of the setter is dynamic. |
3000 if (member.type == NULL) { | 3002 if (member.type == NULL) { |
3001 member.type = &Type::ZoneHandle(Type::DynamicType()); | 3003 member.type = &Type::ZoneHandle(Type::DynamicType()); |
3002 } | 3004 } |
3003 } else if ((CurrentToken() == Token::kOPERATOR) && !member.has_var && | 3005 } else if ((CurrentToken() == Token::kOPERATOR) && !member.has_var && |
3004 (LookaheadToken(1) != Token::kLPAREN) && | 3006 (LookaheadToken(1) != Token::kLPAREN) && |
3005 (LookaheadToken(1) != Token::kASSIGN) && | 3007 (LookaheadToken(1) != Token::kASSIGN) && |
3006 (LookaheadToken(1) != Token::kCOMMA) && | 3008 (LookaheadToken(1) != Token::kCOMMA) && |
3007 (LookaheadToken(1) != Token::kSEMICOLON)) { | 3009 (LookaheadToken(1) != Token::kSEMICOLON)) { |
3008 ConsumeToken(); | 3010 ConsumeToken(); |
3009 if (!Token::CanBeOverloaded(CurrentToken())) { | 3011 if (!Token::CanBeOverloaded(CurrentToken())) { |
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3666 const GrowableObjectArray& types = | 3668 const GrowableObjectArray& types = |
3667 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 3669 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
3668 AbstractType& type = AbstractType::Handle(); | 3670 AbstractType& type = AbstractType::Handle(); |
3669 do { | 3671 do { |
3670 ConsumeToken(); | 3672 ConsumeToken(); |
3671 type = ParseType(finalization); | 3673 type = ParseType(finalization); |
3672 // Only keep the error for the first malformed type argument. | 3674 // Only keep the error for the first malformed type argument. |
3673 if (malformed_error->IsNull() && type.IsMalformed()) { | 3675 if (malformed_error->IsNull() && type.IsMalformed()) { |
3674 *malformed_error = type.malformed_error(); | 3676 *malformed_error = type.malformed_error(); |
3675 } | 3677 } |
3676 // Map a malformed type argument to Dynamic, so that malformed types with | 3678 // Map a malformed type argument to dynamic, so that malformed types with |
3677 // a resolved type class are handled properly in production mode. | 3679 // a resolved type class are handled properly in production mode. |
3678 if (type.IsMalformed()) { | 3680 if (type.IsMalformed()) { |
3679 ASSERT(finalization != ClassFinalizer::kCanonicalizeWellFormed); | 3681 ASSERT(finalization != ClassFinalizer::kCanonicalizeWellFormed); |
3680 if (finalization == ClassFinalizer::kCanonicalizeForCreation) { | 3682 if (finalization == ClassFinalizer::kCanonicalizeForCreation) { |
3681 ErrorMsg(*malformed_error); | 3683 ErrorMsg(*malformed_error); |
3682 } | 3684 } |
3683 type = Type::DynamicType(); | 3685 type = Type::DynamicType(); |
3684 } | 3686 } |
3685 types.Add(type); | 3687 types.Add(type); |
3686 } while (CurrentToken() == Token::kCOMMA); | 3688 } while (CurrentToken() == Token::kCOMMA); |
(...skipping 1469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5156 } | 5158 } |
5157 if ((CurrentToken() != Token::kIDENT) && (CurrentToken() != Token::kCONST)) { | 5159 if ((CurrentToken() != Token::kIDENT) && (CurrentToken() != Token::kCONST)) { |
5158 // Not a legal type identifier or const keyword or metadata. | 5160 // Not a legal type identifier or const keyword or metadata. |
5159 return false; | 5161 return false; |
5160 } | 5162 } |
5161 const intptr_t saved_pos = TokenPos(); | 5163 const intptr_t saved_pos = TokenPos(); |
5162 bool is_var_decl = false; | 5164 bool is_var_decl = false; |
5163 bool have_type = false; | 5165 bool have_type = false; |
5164 if (CurrentToken() == Token::kCONST) { | 5166 if (CurrentToken() == Token::kCONST) { |
5165 ConsumeToken(); | 5167 ConsumeToken(); |
5166 have_type = true; // Type is Dynamic. | 5168 have_type = true; // Type is dynamic. |
5167 } | 5169 } |
5168 if (IsIdentifier()) { // Type or variable name. | 5170 if (IsIdentifier()) { // Type or variable name. |
5169 Token::Kind follower = LookaheadToken(1); | 5171 Token::Kind follower = LookaheadToken(1); |
5170 if ((follower == Token::kLT) || // Parameterized type. | 5172 if ((follower == Token::kLT) || // Parameterized type. |
5171 (follower == Token::kPERIOD) || // Qualified class name of type. | 5173 (follower == Token::kPERIOD) || // Qualified class name of type. |
5172 Token::IsIdentifier(follower)) { // Variable name following a type. | 5174 Token::IsIdentifier(follower)) { // Variable name following a type. |
5173 // We see the beginning of something that could be a type. | 5175 // We see the beginning of something that could be a type. |
5174 const intptr_t type_pos = TokenPos(); | 5176 const intptr_t type_pos = TokenPos(); |
5175 if (TryParseOptionalType()) { | 5177 if (TryParseOptionalType()) { |
5176 have_type = true; | 5178 have_type = true; |
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6071 exception_param.type = | 6073 exception_param.type = |
6072 &AbstractType::ZoneHandle(Type::DynamicType()); | 6074 &AbstractType::ZoneHandle(Type::DynamicType()); |
6073 } | 6075 } |
6074 if (CurrentToken() == Token::kCATCH) { | 6076 if (CurrentToken() == Token::kCATCH) { |
6075 ConsumeToken(); // Consume the 'catch'. | 6077 ConsumeToken(); // Consume the 'catch'. |
6076 ExpectToken(Token::kLPAREN); | 6078 ExpectToken(Token::kLPAREN); |
6077 exception_param.token_pos = TokenPos(); | 6079 exception_param.token_pos = TokenPos(); |
6078 exception_param.var = ExpectIdentifier("identifier expected"); | 6080 exception_param.var = ExpectIdentifier("identifier expected"); |
6079 if (CurrentToken() == Token::kCOMMA) { | 6081 if (CurrentToken() == Token::kCOMMA) { |
6080 ConsumeToken(); | 6082 ConsumeToken(); |
6081 // TODO(hausner): Make implicit type be StackTrace, not Dynamic. | 6083 // TODO(hausner): Make implicit type be StackTrace, not dynamic. |
6082 stack_trace_param.type = | 6084 stack_trace_param.type = |
6083 &AbstractType::ZoneHandle(Type::DynamicType()); | 6085 &AbstractType::ZoneHandle(Type::DynamicType()); |
6084 stack_trace_param.token_pos = TokenPos(); | 6086 stack_trace_param.token_pos = TokenPos(); |
6085 stack_trace_param.var = ExpectIdentifier("identifier expected"); | 6087 stack_trace_param.var = ExpectIdentifier("identifier expected"); |
6086 } | 6088 } |
6087 ExpectToken(Token::kRPAREN); | 6089 ExpectToken(Token::kRPAREN); |
6088 } | 6090 } |
6089 | 6091 |
6090 // If a generic "catch all" statement has already been seen then all | 6092 // If a generic "catch all" statement has already been seen then all |
6091 // subsequent catch statements are dead. We issue an error for now, | 6093 // subsequent catch statements are dead. We issue an error for now, |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6580 CurrentToken() == Token::kIDENT ? | 6582 CurrentToken() == Token::kIDENT ? |
6581 CurrentLiteral()->ToCString() : Token::Str(CurrentToken())); | 6583 CurrentLiteral()->ToCString() : Token::Str(CurrentToken())); |
6582 } | 6584 } |
6583 | 6585 |
6584 | 6586 |
6585 String* Parser::ExpectClassIdentifier(const char* msg) { | 6587 String* Parser::ExpectClassIdentifier(const char* msg) { |
6586 if (CurrentToken() != Token::kIDENT) { | 6588 if (CurrentToken() != Token::kIDENT) { |
6587 ErrorMsg("%s", msg); | 6589 ErrorMsg("%s", msg); |
6588 } | 6590 } |
6589 String* ident = CurrentLiteral(); | 6591 String* ident = CurrentLiteral(); |
6590 if (ident->Equals("Dynamic")) { | 6592 // TODO(hausner): Remove check for 'Dynamic' once support for upper-case |
| 6593 // type dynamic is gone. |
| 6594 if (ident->Equals("Dynamic") || ident->Equals("dynamic")) { |
6591 ErrorMsg("%s", msg); | 6595 ErrorMsg("%s", msg); |
6592 } | 6596 } |
6593 ConsumeToken(); | 6597 ConsumeToken(); |
6594 return ident; | 6598 return ident; |
6595 } | 6599 } |
6596 | 6600 |
6597 | 6601 |
6598 // Check whether current token is an identifier or a built-in identifier. | 6602 // Check whether current token is an identifier or a built-in identifier. |
6599 String* Parser::ExpectIdentifier(const char* msg) { | 6603 String* Parser::ExpectIdentifier(const char* msg) { |
6600 if (!IsIdentifier()) { | 6604 if (!IsIdentifier()) { |
(...skipping 1764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8365 ClassFinalizer::FinalizationKind finalization) { | 8369 ClassFinalizer::FinalizationKind finalization) { |
8366 TRACE_PARSER("ParseType"); | 8370 TRACE_PARSER("ParseType"); |
8367 if (CurrentToken() != Token::kIDENT) { | 8371 if (CurrentToken() != Token::kIDENT) { |
8368 ErrorMsg("type name expected"); | 8372 ErrorMsg("type name expected"); |
8369 } | 8373 } |
8370 QualIdent type_name; | 8374 QualIdent type_name; |
8371 if (finalization == ClassFinalizer::kIgnore) { | 8375 if (finalization == ClassFinalizer::kIgnore) { |
8372 SkipQualIdent(); | 8376 SkipQualIdent(); |
8373 } else { | 8377 } else { |
8374 ParseQualIdent(&type_name); | 8378 ParseQualIdent(&type_name); |
| 8379 // TODO(hausner): Remove this once support for legacy type 'Dynamic' |
| 8380 // is removed. |
| 8381 if ((type_name.lib_prefix == NULL) && type_name.ident->Equals("Dynamic")) { |
| 8382 if (FLAG_warn_legacy_dynamic) { |
| 8383 Warning(type_name.ident_pos, |
| 8384 "legacy type 'Dynamic' found; auto-converting to 'dynamic'"); |
| 8385 } |
| 8386 // Replace with lower-case 'dynamic'. |
| 8387 *type_name.ident ^= Symbols::Dynamic(); |
| 8388 } |
8375 // An identifier cannot be resolved in a local scope when top level parsing. | 8389 // An identifier cannot be resolved in a local scope when top level parsing. |
8376 if (!is_top_level_ && | 8390 if (!is_top_level_ && |
8377 (type_name.lib_prefix == NULL) && | 8391 (type_name.lib_prefix == NULL) && |
8378 ResolveIdentInLocalScope(type_name.ident_pos, *type_name.ident, NULL)) { | 8392 ResolveIdentInLocalScope(type_name.ident_pos, *type_name.ident, NULL)) { |
8379 ErrorMsg(type_name.ident_pos, "using '%s' in this context is invalid", | 8393 ErrorMsg(type_name.ident_pos, "using '%s' in this context is invalid", |
8380 type_name.ident->ToCString()); | 8394 type_name.ident->ToCString()); |
8381 } | 8395 } |
8382 } | 8396 } |
8383 Object& type_class = Object::Handle(); | 8397 Object& type_class = Object::Handle(); |
8384 // Leave type_class as null if type finalization mode is kIgnore. | 8398 // Leave type_class as null if type finalization mode is kIgnore. |
8385 if (finalization != ClassFinalizer::kIgnore) { | 8399 if (finalization != ClassFinalizer::kIgnore) { |
8386 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); | 8400 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); |
8387 if (type_name.lib_prefix != NULL) { | 8401 if (type_name.lib_prefix != NULL) { |
8388 lib_prefix = type_name.lib_prefix->raw(); | 8402 lib_prefix = type_name.lib_prefix->raw(); |
8389 } | 8403 } |
8390 type_class = UnresolvedClass::New(lib_prefix, | 8404 type_class = UnresolvedClass::New(lib_prefix, |
8391 *type_name.ident, | 8405 *type_name.ident, |
8392 type_name.ident_pos); | 8406 type_name.ident_pos); |
8393 } | 8407 } |
8394 Error& malformed_error = Error::Handle(); | 8408 Error& malformed_error = Error::Handle(); |
8395 AbstractTypeArguments& type_arguments = | 8409 AbstractTypeArguments& type_arguments = |
8396 AbstractTypeArguments::Handle(ParseTypeArguments(&malformed_error, | 8410 AbstractTypeArguments::Handle(ParseTypeArguments(&malformed_error, |
8397 finalization)); | 8411 finalization)); |
8398 if (finalization == ClassFinalizer::kIgnore) { | 8412 if (finalization == ClassFinalizer::kIgnore) { |
8399 return Type::DynamicType(); | 8413 return Type::DynamicType(); |
8400 } | 8414 } |
8401 AbstractType& type = AbstractType::Handle( | 8415 AbstractType& type = AbstractType::Handle( |
8402 Type::New(type_class, type_arguments, type_name.ident_pos)); | 8416 Type::New(type_class, type_arguments, type_name.ident_pos)); |
8403 // In production mode, malformed type arguments are mapped to Dynamic. | 8417 // In production mode, malformed type arguments are mapped to dynamic. |
8404 // In checked mode, a type with malformed type arguments is malformed. | 8418 // In checked mode, a type with malformed type arguments is malformed. |
8405 if (FLAG_enable_type_checks && !malformed_error.IsNull()) { | 8419 if (FLAG_enable_type_checks && !malformed_error.IsNull()) { |
8406 Type& parameterized_type = Type::Handle(); | 8420 Type& parameterized_type = Type::Handle(); |
8407 parameterized_type ^= type.raw(); | 8421 parameterized_type ^= type.raw(); |
8408 parameterized_type.set_type_class(Class::Handle(Object::dynamic_class())); | 8422 parameterized_type.set_type_class(Class::Handle(Object::dynamic_class())); |
8409 parameterized_type.set_arguments(AbstractTypeArguments::Handle()); | 8423 parameterized_type.set_arguments(AbstractTypeArguments::Handle()); |
8410 parameterized_type.set_malformed_error(malformed_error); | 8424 parameterized_type.set_malformed_error(malformed_error); |
8411 } | 8425 } |
8412 if (finalization >= ClassFinalizer::kTryResolve) { | 8426 if (finalization >= ClassFinalizer::kTryResolve) { |
8413 ResolveTypeFromClass(current_class(), finalization, &type); | 8427 ResolveTypeFromClass(current_class(), finalization, &type); |
(...skipping 30 matching lines...) Expand all Loading... |
8444 const AbstractTypeArguments& type_arguments) { | 8458 const AbstractTypeArguments& type_arguments) { |
8445 TRACE_PARSER("ParseListLiteral"); | 8459 TRACE_PARSER("ParseListLiteral"); |
8446 ASSERT(type_pos >= 0); | 8460 ASSERT(type_pos >= 0); |
8447 ASSERT(CurrentToken() == Token::kLBRACK || CurrentToken() == Token::kINDEX); | 8461 ASSERT(CurrentToken() == Token::kLBRACK || CurrentToken() == Token::kINDEX); |
8448 const intptr_t literal_pos = TokenPos(); | 8462 const intptr_t literal_pos = TokenPos(); |
8449 bool is_empty_literal = CurrentToken() == Token::kINDEX; | 8463 bool is_empty_literal = CurrentToken() == Token::kINDEX; |
8450 ConsumeToken(); | 8464 ConsumeToken(); |
8451 | 8465 |
8452 AbstractType& element_type = Type::ZoneHandle(Type::DynamicType()); | 8466 AbstractType& element_type = Type::ZoneHandle(Type::DynamicType()); |
8453 // If no type argument vector is provided, leave it as null, which is | 8467 // If no type argument vector is provided, leave it as null, which is |
8454 // equivalent to using Dynamic as the type argument for the element type. | 8468 // equivalent to using dynamic as the type argument for the element type. |
8455 if (!type_arguments.IsNull()) { | 8469 if (!type_arguments.IsNull()) { |
8456 ASSERT(type_arguments.Length() > 0); | 8470 ASSERT(type_arguments.Length() > 0); |
8457 // List literals take a single type argument. | 8471 // List literals take a single type argument. |
8458 element_type = type_arguments.TypeAt(0); | 8472 element_type = type_arguments.TypeAt(0); |
8459 if (type_arguments.Length() != 1) { | 8473 if (type_arguments.Length() != 1) { |
8460 ErrorMsg(type_pos, | 8474 ErrorMsg(type_pos, |
8461 "a list literal takes one type argument specifying " | 8475 "a list literal takes one type argument specifying " |
8462 "the element type"); | 8476 "the element type"); |
8463 } | 8477 } |
8464 if (is_const && !element_type.IsInstantiated()) { | 8478 if (is_const && !element_type.IsInstantiated()) { |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8614 TRACE_PARSER("ParseMapLiteral"); | 8628 TRACE_PARSER("ParseMapLiteral"); |
8615 ASSERT(type_pos >= 0); | 8629 ASSERT(type_pos >= 0); |
8616 ASSERT(CurrentToken() == Token::kLBRACE); | 8630 ASSERT(CurrentToken() == Token::kLBRACE); |
8617 const intptr_t literal_pos = TokenPos(); | 8631 const intptr_t literal_pos = TokenPos(); |
8618 ConsumeToken(); | 8632 ConsumeToken(); |
8619 | 8633 |
8620 AbstractType& value_type = Type::ZoneHandle(Type::DynamicType()); | 8634 AbstractType& value_type = Type::ZoneHandle(Type::DynamicType()); |
8621 AbstractTypeArguments& map_type_arguments = | 8635 AbstractTypeArguments& map_type_arguments = |
8622 AbstractTypeArguments::ZoneHandle(type_arguments.raw()); | 8636 AbstractTypeArguments::ZoneHandle(type_arguments.raw()); |
8623 // If no type argument vector is provided, leave it as null, which is | 8637 // If no type argument vector is provided, leave it as null, which is |
8624 // equivalent to using Dynamic as the type argument for the value type. | 8638 // equivalent to using dynamic as the type argument for the value type. |
8625 if (!map_type_arguments.IsNull()) { | 8639 if (!map_type_arguments.IsNull()) { |
8626 ASSERT(map_type_arguments.Length() > 0); | 8640 ASSERT(map_type_arguments.Length() > 0); |
8627 // Map literals take two type arguments. | 8641 // Map literals take two type arguments. |
8628 if (map_type_arguments.Length() < 2) { | 8642 if (map_type_arguments.Length() < 2) { |
8629 // TODO(hausner): Remove legacy syntax support. | 8643 // TODO(hausner): Remove legacy syntax support. |
8630 // We temporarily accept a single type argument. | 8644 // We temporarily accept a single type argument. |
8631 if (FLAG_warn_legacy_map_literal) { | 8645 if (FLAG_warn_legacy_map_literal) { |
8632 Warning(type_pos, | 8646 Warning(type_pos, |
8633 "a map literal takes two type arguments specifying " | 8647 "a map literal takes two type arguments specifying " |
8634 "the key type and the value type"); | 8648 "the key type and the value type"); |
(...skipping 16 matching lines...) Expand all Loading... |
8651 } | 8665 } |
8652 if (is_const && !value_type.IsInstantiated()) { | 8666 if (is_const && !value_type.IsInstantiated()) { |
8653 ErrorMsg(type_pos, | 8667 ErrorMsg(type_pos, |
8654 "the type argument of a constant map literal cannot include " | 8668 "the type argument of a constant map literal cannot include " |
8655 "a type variable"); | 8669 "a type variable"); |
8656 } | 8670 } |
8657 } | 8671 } |
8658 ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2)); | 8672 ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2)); |
8659 map_type_arguments ^= map_type_arguments.Canonicalize(); | 8673 map_type_arguments ^= map_type_arguments.Canonicalize(); |
8660 | 8674 |
8661 // The kv_pair array is temporary and of element type Dynamic. It is passed | 8675 // The kv_pair array is temporary and of element type dynamic. It is passed |
8662 // to the factory to initialize a properly typed map. | 8676 // to the factory to initialize a properly typed map. |
8663 ArrayNode* kv_pairs = | 8677 ArrayNode* kv_pairs = |
8664 new ArrayNode(TokenPos(), Type::ZoneHandle(Type::ListInterface())); | 8678 new ArrayNode(TokenPos(), Type::ZoneHandle(Type::ListInterface())); |
8665 | 8679 |
8666 // Parse the map entries. Note: there may be an optional extra | 8680 // Parse the map entries. Note: there may be an optional extra |
8667 // comma after the last entry. | 8681 // comma after the last entry. |
8668 const String& dst_name = String::ZoneHandle(Symbols::ListLiteralElement()); | 8682 const String& dst_name = String::ZoneHandle(Symbols::ListLiteralElement()); |
8669 while (CurrentToken() != Token::kRBRACE) { | 8683 while (CurrentToken() != Token::kRBRACE) { |
8670 AstNode* key = NULL; | 8684 AstNode* key = NULL; |
8671 if (CurrentToken() == Token::kSTRING) { | 8685 if (CurrentToken() == Token::kSTRING) { |
(...skipping 1050 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9722 void Parser::SkipQualIdent() { | 9736 void Parser::SkipQualIdent() { |
9723 ASSERT(IsIdentifier()); | 9737 ASSERT(IsIdentifier()); |
9724 ConsumeToken(); | 9738 ConsumeToken(); |
9725 if (CurrentToken() == Token::kPERIOD) { | 9739 if (CurrentToken() == Token::kPERIOD) { |
9726 ConsumeToken(); // Consume the kPERIOD token. | 9740 ConsumeToken(); // Consume the kPERIOD token. |
9727 ExpectIdentifier("identifier expected after '.'"); | 9741 ExpectIdentifier("identifier expected after '.'"); |
9728 } | 9742 } |
9729 } | 9743 } |
9730 | 9744 |
9731 } // namespace dart | 9745 } // namespace dart |
OLD | NEW |