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

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

Issue 11299020: Make creation of list literal more resilient to changes in the underlying (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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 1340 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 const String& function_name, 1351 const String& function_name,
1352 const ArgumentListNode& function_args) { 1352 const ArgumentListNode& function_args) {
1353 const intptr_t args_pos = function_args.token_pos(); 1353 const intptr_t args_pos = function_args.token_pos();
1354 // Build arguments to the call to the static 1354 // Build arguments to the call to the static
1355 // InvocationMirror._allocateInvocationMirror method. 1355 // InvocationMirror._allocateInvocationMirror method.
1356 ArgumentListNode* arguments = new ArgumentListNode(args_pos); 1356 ArgumentListNode* arguments = new ArgumentListNode(args_pos);
1357 // The first argument is the original function name. 1357 // The first argument is the original function name.
1358 arguments->Add(new LiteralNode(args_pos, function_name)); 1358 arguments->Add(new LiteralNode(args_pos, function_name));
1359 // The second argument is an array containing the original function arguments. 1359 // The second argument is an array containing the original function arguments.
1360 ArrayNode* args_array = new ArrayNode( 1360 ArrayNode* args_array = new ArrayNode(
1361 args_pos, Type::ZoneHandle(Type::ListInterface())); 1361 args_pos, Type::ZoneHandle(Type::ArrayType()));
1362 for (intptr_t i = 1; i < function_args.length(); i++) { 1362 for (intptr_t i = 1; i < function_args.length(); i++) {
1363 args_array->AddElement(function_args.NodeAt(i)); 1363 args_array->AddElement(function_args.NodeAt(i));
1364 } 1364 }
1365 arguments->Add(args_array); 1365 arguments->Add(args_array);
1366 // Lookup the static InvocationMirror._allocateInvocationMirror method. 1366 // Lookup the static InvocationMirror._allocateInvocationMirror method.
1367 const Class& mirror_class = Class::Handle( 1367 const Class& mirror_class = Class::Handle(
1368 LookupCoreClass(String::Handle(Symbols::InvocationMirror()))); 1368 LookupCoreClass(String::Handle(Symbols::InvocationMirror())));
1369 ASSERT(!mirror_class.IsNull()); 1369 ASSERT(!mirror_class.IsNull());
1370 const String& allocation_function_name = 1370 const String& allocation_function_name =
1371 String::Handle(Symbols::AllocateInvocationMirror()); 1371 String::Handle(Symbols::AllocateInvocationMirror());
(...skipping 7328 matching lines...) Expand 10 before | Expand all | Expand 10 after
8700 "a list literal takes one type argument specifying " 8700 "a list literal takes one type argument specifying "
8701 "the element type"); 8701 "the element type");
8702 } 8702 }
8703 if (is_const && !element_type.IsInstantiated()) { 8703 if (is_const && !element_type.IsInstantiated()) {
8704 ErrorMsg(type_pos, 8704 ErrorMsg(type_pos,
8705 "the type argument of a constant list literal cannot include " 8705 "the type argument of a constant list literal cannot include "
8706 "a type variable"); 8706 "a type variable");
8707 } 8707 }
8708 } 8708 }
8709 ASSERT(type_arguments.IsNull() || (type_arguments.Length() == 1)); 8709 ASSERT(type_arguments.IsNull() || (type_arguments.Length() == 1));
8710 const Class& list_class = Class::Handle( 8710 const Class& array_class = Class::Handle(
8711 Type::Handle(Type::ListInterface()).type_class()); 8711 Type::Handle(Type::ArrayType()).type_class());
siva 2012/11/16 02:24:50 Why not just do const Class& array_class = Class::
regis 2012/11/20 19:37:33 The ListClass helper would be the wrong one here,
8712 Type& type = Type::ZoneHandle( 8712 Type& type = Type::ZoneHandle(
8713 Type::New(list_class, type_arguments, type_pos)); 8713 Type::New(array_class, type_arguments, type_pos));
8714 type ^= ClassFinalizer::FinalizeType( 8714 type ^= ClassFinalizer::FinalizeType(
8715 current_class(), type, ClassFinalizer::kCanonicalize); 8715 current_class(), type, ClassFinalizer::kCanonicalize);
8716 ArrayNode* list = new ArrayNode(TokenPos(), type); 8716 ArrayNode* list = new ArrayNode(TokenPos(), type);
8717 8717
8718 // Parse the list elements. Note: there may be an optional extra 8718 // Parse the list elements. Note: there may be an optional extra
8719 // comma after the last element. 8719 // comma after the last element.
8720 if (!is_empty_literal) { 8720 if (!is_empty_literal) {
8721 const bool saved_mode = SetAllowFunctionLiterals(true); 8721 const bool saved_mode = SetAllowFunctionLiterals(true);
8722 const String& dst_name = String::ZoneHandle(Symbols::ListLiteralElement()); 8722 const String& dst_name = String::ZoneHandle(Symbols::ListLiteralElement());
8723 while (CurrentToken() != Token::kRBRACK) { 8723 while (CurrentToken() != Token::kRBRACK) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
8769 String::Handle(element_type.UserVisibleName()).ToCString()); 8769 String::Handle(element_type.UserVisibleName()).ToCString());
8770 } 8770 }
8771 } 8771 }
8772 const_list.SetAt(i, elem->AsLiteralNode()->literal()); 8772 const_list.SetAt(i, elem->AsLiteralNode()->literal());
8773 } 8773 }
8774 const_list ^= const_list.Canonicalize(); 8774 const_list ^= const_list.Canonicalize();
8775 const_list.MakeImmutable(); 8775 const_list.MakeImmutable();
8776 return new LiteralNode(literal_pos, const_list); 8776 return new LiteralNode(literal_pos, const_list);
8777 } else { 8777 } else {
8778 // Factory call at runtime. 8778 // Factory call at runtime.
8779 String& list_class_name = String::Handle(Symbols::ListImplementation()); 8779 // TODO(regis): Once _ListImpl is removed, use Symbols::List() instead of
8780 const Class& list_class = Class::Handle(LookupCoreClass(list_class_name)); 8780 // Symbols::ListImplementation() on the following line.
8781 ASSERT(!list_class.IsNull()); 8781 String& factory_class_name = String::Handle(Symbols::ListImplementation());
8782 const String& list_literal_factory_name = 8782 const Class& factory_class =
8783 Class::Handle(LookupCoreClass(factory_class_name));
8784 ASSERT(!factory_class.IsNull());
8785 const String& factory_method_name =
8783 String::Handle(Symbols::ListLiteralFactory()); 8786 String::Handle(Symbols::ListLiteralFactory());
8784 const Function& list_literal_factory = Function::ZoneHandle( 8787 const Function& factory_method = Function::ZoneHandle(
8785 list_class.LookupFactory(list_literal_factory_name)); 8788 factory_class.LookupFactory(factory_method_name));
8786 ASSERT(!list_literal_factory.IsNull()); 8789 ASSERT(!factory_method.IsNull());
8787 if (!type_arguments.IsNull() && 8790 if (!type_arguments.IsNull() &&
8788 !type_arguments.IsInstantiated() && 8791 !type_arguments.IsInstantiated() &&
8789 (current_block_->scope->function_level() > 0)) { 8792 (current_block_->scope->function_level() > 0)) {
8790 // Make sure that the instantiator is captured. 8793 // Make sure that the instantiator is captured.
8791 CaptureInstantiator(); 8794 CaptureInstantiator();
8792 } 8795 }
8796 AbstractTypeArguments& factory_type_args =
8797 AbstractTypeArguments::ZoneHandle(type_arguments.raw());
8798 // If the factory class extends other parameterized classes, adjust the
8799 // type argument vector.
8800 if (!factory_type_args.IsNull() && (factory_class.NumTypeArguments() > 1)) {
8801 ASSERT(factory_type_args.Length() == 1);
8802 Type& factory_type = Type::Handle(Type::New(
8803 factory_class, factory_type_args, type_pos, Heap::kNew));
8804 factory_type ^= ClassFinalizer::FinalizeType(
8805 current_class(), factory_type, ClassFinalizer::kFinalize);
8806 factory_type_args = factory_type.arguments();
8807 ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments());
8808 }
8809 factory_type_args = factory_type_args.Canonicalize();
8793 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); 8810 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
8794 factory_param->Add(list); 8811 factory_param->Add(list);
8795 AbstractTypeArguments& canonical_type_arguments =
8796 AbstractTypeArguments::ZoneHandle(type_arguments.Canonicalize());
8797 return CreateConstructorCallNode(literal_pos, 8812 return CreateConstructorCallNode(literal_pos,
8798 canonical_type_arguments, 8813 factory_type_args,
8799 list_literal_factory, 8814 factory_method,
8800 factory_param); 8815 factory_param);
8801 } 8816 }
8802 } 8817 }
8803 8818
8804 8819
8805 ConstructorCallNode* Parser::CreateConstructorCallNode( 8820 ConstructorCallNode* Parser::CreateConstructorCallNode(
8806 intptr_t token_pos, 8821 intptr_t token_pos,
8807 const AbstractTypeArguments& type_arguments, 8822 const AbstractTypeArguments& type_arguments,
8808 const Function& constructor, 8823 const Function& constructor,
8809 ArgumentListNode* arguments) { 8824 ArgumentListNode* arguments) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
8890 ErrorMsg(type_pos, 8905 ErrorMsg(type_pos,
8891 "the type argument of a constant map literal cannot include " 8906 "the type argument of a constant map literal cannot include "
8892 "a type variable"); 8907 "a type variable");
8893 } 8908 }
8894 } 8909 }
8895 ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2)); 8910 ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2));
8896 map_type_arguments ^= map_type_arguments.Canonicalize(); 8911 map_type_arguments ^= map_type_arguments.Canonicalize();
8897 8912
8898 // The kv_pair array is temporary and of element type dynamic. It is passed 8913 // The kv_pair array is temporary and of element type dynamic. It is passed
8899 // to the factory to initialize a properly typed map. 8914 // to the factory to initialize a properly typed map.
8900 ArrayNode* kv_pairs = 8915 ArrayNode* kv_pairs = new ArrayNode(
8901 new ArrayNode(TokenPos(), Type::ZoneHandle(Type::ListInterface())); 8916 TokenPos(), Type::ZoneHandle(Type::ArrayType()));
8902 8917
8903 // Parse the map entries. Note: there may be an optional extra 8918 // Parse the map entries. Note: there may be an optional extra
8904 // comma after the last entry. 8919 // comma after the last entry.
8905 const String& dst_name = String::ZoneHandle(Symbols::ListLiteralElement()); 8920 const String& dst_name = String::ZoneHandle(Symbols::ListLiteralElement());
8906 while (CurrentToken() != Token::kRBRACE) { 8921 while (CurrentToken() != Token::kRBRACE) {
8907 AstNode* key = NULL; 8922 AstNode* key = NULL;
8908 if (CurrentToken() == Token::kSTRING) { 8923 if (CurrentToken() == Token::kSTRING) {
8909 key = ParseStringLiteral(); 8924 key = ParseStringLiteral();
8910 } 8925 }
8911 if (key == NULL) { 8926 if (key == NULL) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
8971 } 8986 }
8972 key_value_array ^= key_value_array.Canonicalize(); 8987 key_value_array ^= key_value_array.Canonicalize();
8973 key_value_array.MakeImmutable(); 8988 key_value_array.MakeImmutable();
8974 8989
8975 // Construct the map object. 8990 // Construct the map object.
8976 const String& immutable_map_class_name = 8991 const String& immutable_map_class_name =
8977 String::Handle(Symbols::ImmutableMap()); 8992 String::Handle(Symbols::ImmutableMap());
8978 const Class& immutable_map_class = 8993 const Class& immutable_map_class =
8979 Class::Handle(LookupCoreClass(immutable_map_class_name)); 8994 Class::Handle(LookupCoreClass(immutable_map_class_name));
8980 ASSERT(!immutable_map_class.IsNull()); 8995 ASSERT(!immutable_map_class.IsNull());
8996 // If the immutable map class extends other parameterized classes, we need
8997 // to adjust the type argument vector. This is currently not the case.
8998 ASSERT(immutable_map_class.NumTypeArguments() == 2);
8981 ArgumentListNode* constr_args = new ArgumentListNode(TokenPos()); 8999 ArgumentListNode* constr_args = new ArgumentListNode(TokenPos());
8982 constr_args->Add(new LiteralNode(literal_pos, key_value_array)); 9000 constr_args->Add(new LiteralNode(literal_pos, key_value_array));
8983 const String& constr_name = 9001 const String& constr_name =
8984 String::Handle(Symbols::ImmutableMapConstructor()); 9002 String::Handle(Symbols::ImmutableMapConstructor());
8985 const Function& map_constr = Function::ZoneHandle( 9003 const Function& map_constr = Function::ZoneHandle(
8986 immutable_map_class.LookupConstructor(constr_name)); 9004 immutable_map_class.LookupConstructor(constr_name));
8987 ASSERT(!map_constr.IsNull()); 9005 ASSERT(!map_constr.IsNull());
8988 const Object& constructor_result = Object::Handle( 9006 const Object& constructor_result = Object::Handle(
8989 EvaluateConstConstructorCall(immutable_map_class, 9007 EvaluateConstConstructorCall(immutable_map_class,
8990 map_type_arguments, 9008 map_type_arguments,
8991 map_constr, 9009 map_constr,
8992 constr_args)); 9010 constr_args));
8993 if (constructor_result.IsUnhandledException()) { 9011 if (constructor_result.IsUnhandledException()) {
8994 return GenerateRethrow(literal_pos, constructor_result); 9012 return GenerateRethrow(literal_pos, constructor_result);
8995 } else { 9013 } else {
8996 const Instance& const_instance = Instance::Cast(constructor_result); 9014 const Instance& const_instance = Instance::Cast(constructor_result);
8997 return new LiteralNode(literal_pos, 9015 return new LiteralNode(literal_pos,
8998 Instance::ZoneHandle(const_instance.raw())); 9016 Instance::ZoneHandle(const_instance.raw()));
8999 } 9017 }
9000 } else { 9018 } else {
9001 // Factory call at runtime. 9019 // Factory call at runtime.
9002 String& map_class_name = String::Handle(Symbols::MapImplementation()); 9020 String& factory_class_name = String::Handle(Symbols::MapImplementation());
9003 const Class& map_class = Class::Handle(LookupCoreClass(map_class_name)); 9021 const Class& factory_class =
9004 ASSERT(!map_class.IsNull()); 9022 Class::Handle(LookupCoreClass(factory_class_name));
9005 const String& map_literal_factory_name = 9023 ASSERT(!factory_class.IsNull());
9024 const String& factory_method_name =
9006 String::Handle(Symbols::MapLiteralFactory()); 9025 String::Handle(Symbols::MapLiteralFactory());
9007 const Function& map_literal_factory = Function::ZoneHandle( 9026 const Function& factory_method = Function::ZoneHandle(
9008 map_class.LookupFactory(map_literal_factory_name)); 9027 factory_class.LookupFactory(factory_method_name));
9009 ASSERT(!map_literal_factory.IsNull()); 9028 ASSERT(!factory_method.IsNull());
9010 if (!map_type_arguments.IsNull() && 9029 if (!map_type_arguments.IsNull() &&
9011 !map_type_arguments.IsInstantiated() && 9030 !map_type_arguments.IsInstantiated() &&
9012 (current_block_->scope->function_level() > 0)) { 9031 (current_block_->scope->function_level() > 0)) {
9013 // Make sure that the instantiator is captured. 9032 // Make sure that the instantiator is captured.
9014 CaptureInstantiator(); 9033 CaptureInstantiator();
9015 } 9034 }
9035 AbstractTypeArguments& factory_type_args =
9036 AbstractTypeArguments::ZoneHandle(map_type_arguments.raw());
9037 // If the factory class extends other parameterized classes, adjust the
9038 // type argument vector.
9039 if (!factory_type_args.IsNull() && (factory_class.NumTypeArguments() > 2)) {
9040 ASSERT(factory_type_args.Length() == 2);
9041 Type& factory_type = Type::Handle(Type::New(
9042 factory_class, factory_type_args, type_pos, Heap::kNew));
9043 factory_type ^= ClassFinalizer::FinalizeType(
9044 current_class(), factory_type, ClassFinalizer::kFinalize);
9045 factory_type_args = factory_type.arguments();
9046 ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments());
9047 }
9048 factory_type_args = factory_type_args.Canonicalize();
9016 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); 9049 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
9017 factory_param->Add(kv_pairs); 9050 factory_param->Add(kv_pairs);
9018 return CreateConstructorCallNode(literal_pos, 9051 return CreateConstructorCallNode(literal_pos,
9019 map_type_arguments, 9052 factory_type_args,
9020 map_literal_factory, 9053 factory_method,
9021 factory_param); 9054 factory_param);
9022 } 9055 }
9023 } 9056 }
9024 9057
9025 9058
9026 AstNode* Parser::ParseCompoundLiteral() { 9059 AstNode* Parser::ParseCompoundLiteral() {
9027 TRACE_PARSER("ParseCompoundLiteral"); 9060 TRACE_PARSER("ParseCompoundLiteral");
9028 bool is_const = false; 9061 bool is_const = false;
9029 if (CurrentToken() == Token::kCONST) { 9062 if (CurrentToken() == Token::kCONST) {
9030 is_const = true; 9063 is_const = true;
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
9462 if ((l1_token != Token::kSTRING) && 9495 if ((l1_token != Token::kSTRING) &&
9463 (l1_token != Token::kINTERPOL_VAR) && 9496 (l1_token != Token::kINTERPOL_VAR) &&
9464 (l1_token != Token::kINTERPOL_START)) { 9497 (l1_token != Token::kINTERPOL_START)) {
9465 // Common case: no interpolation. 9498 // Common case: no interpolation.
9466 primary = new LiteralNode(literal_start, *CurrentLiteral()); 9499 primary = new LiteralNode(literal_start, *CurrentLiteral());
9467 ConsumeToken(); 9500 ConsumeToken();
9468 return primary; 9501 return primary;
9469 } 9502 }
9470 // String interpolation needed. 9503 // String interpolation needed.
9471 bool is_compiletime_const = true; 9504 bool is_compiletime_const = true;
9472 ArrayNode* values = new ArrayNode(TokenPos(), 9505 ArrayNode* values = new ArrayNode(
9473 Type::ZoneHandle(Type::ListInterface())); 9506 TokenPos(), Type::ZoneHandle(Type::ArrayType()));
9474 while (CurrentToken() == Token::kSTRING) { 9507 while (CurrentToken() == Token::kSTRING) {
9475 values->AddElement(new LiteralNode(TokenPos(), *CurrentLiteral())); 9508 values->AddElement(new LiteralNode(TokenPos(), *CurrentLiteral()));
9476 ConsumeToken(); 9509 ConsumeToken();
9477 while ((CurrentToken() == Token::kINTERPOL_VAR) || 9510 while ((CurrentToken() == Token::kINTERPOL_VAR) ||
9478 (CurrentToken() == Token::kINTERPOL_START)) { 9511 (CurrentToken() == Token::kINTERPOL_START)) {
9479 AstNode* expr = NULL; 9512 AstNode* expr = NULL;
9480 const intptr_t expr_pos = TokenPos(); 9513 const intptr_t expr_pos = TokenPos();
9481 if (CurrentToken() == Token::kINTERPOL_VAR) { 9514 if (CurrentToken() == Token::kINTERPOL_VAR) {
9482 expr = ResolveIdent(TokenPos(), *CurrentLiteral(), true); 9515 expr = ResolveIdent(TokenPos(), *CurrentLiteral(), true);
9483 ConsumeToken(); 9516 ConsumeToken();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
9541 OS::SNPrint(name, 64, "%s_%"Pd"", 9574 OS::SNPrint(name, 64, "%s_%"Pd"",
9542 Symbols::Name(Symbols::kSavedArgDescVarPrefix), 9575 Symbols::Name(Symbols::kSavedArgDescVarPrefix),
9543 owner_function.token_pos()); 9576 owner_function.token_pos());
9544 const String& saved_args_desc_name = String::ZoneHandle(Symbols::New(name)); 9577 const String& saved_args_desc_name = String::ZoneHandle(Symbols::New(name));
9545 LocalVariable* saved_args_desc_var = LookupLocalScope(saved_args_desc_name); 9578 LocalVariable* saved_args_desc_var = LookupLocalScope(saved_args_desc_name);
9546 if (saved_args_desc_var == NULL) { 9579 if (saved_args_desc_var == NULL) {
9547 ASSERT(owner_scope != NULL); 9580 ASSERT(owner_scope != NULL);
9548 saved_args_desc_var = 9581 saved_args_desc_var =
9549 new LocalVariable(owner_function.token_pos(), 9582 new LocalVariable(owner_function.token_pos(),
9550 saved_args_desc_name, 9583 saved_args_desc_name,
9551 Type::ZoneHandle(Type::ListInterface())); 9584 Type::ZoneHandle(Type::ArrayType()));
9552 saved_args_desc_var->set_is_final(); 9585 saved_args_desc_var->set_is_final();
9553 // The saved arguments descriptor variable must be added just after the 9586 // The saved arguments descriptor variable must be added just after the
9554 // formal parameters. This simplifies the 2-step saving of a captured 9587 // formal parameters. This simplifies the 2-step saving of a captured
9555 // arguments descriptor. 9588 // arguments descriptor.
9556 // At this time, the owner scope should only contain formal parameters. 9589 // At this time, the owner scope should only contain formal parameters.
9557 ASSERT(owner_scope->num_variables() == owner_function.NumParameters()); 9590 ASSERT(owner_scope->num_variables() == owner_function.NumParameters());
9558 bool success = owner_scope->AddVariable(saved_args_desc_var); 9591 bool success = owner_scope->AddVariable(saved_args_desc_var);
9559 ASSERT(success); 9592 ASSERT(success);
9560 // Capture the saved argument descriptor variable if necessary. 9593 // Capture the saved argument descriptor variable if necessary.
9561 LocalVariable* local = LookupLocalScope(saved_args_desc_name); 9594 LocalVariable* local = LookupLocalScope(saved_args_desc_name);
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
10011 void Parser::SkipQualIdent() { 10044 void Parser::SkipQualIdent() {
10012 ASSERT(IsIdentifier()); 10045 ASSERT(IsIdentifier());
10013 ConsumeToken(); 10046 ConsumeToken();
10014 if (CurrentToken() == Token::kPERIOD) { 10047 if (CurrentToken() == Token::kPERIOD) {
10015 ConsumeToken(); // Consume the kPERIOD token. 10048 ConsumeToken(); // Consume the kPERIOD token.
10016 ExpectIdentifier("identifier expected after '.'"); 10049 ExpectIdentifier("identifier expected after '.'");
10017 } 10050 }
10018 } 10051 }
10019 10052
10020 } // namespace dart 10053 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698