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

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

Issue 40683002: It's a compile-time error if a const constructor call fails (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 months 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 "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/bootstrap.h" 9 #include "vm/bootstrap.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 for (int i = 0; i < objs.Length(); i++) { 90 for (int i = 0; i < objs.Length(); i++) {
91 type ^= objs.At(i); 91 type ^= objs.At(i);
92 a.SetTypeAt(i, type); 92 a.SetTypeAt(i, type);
93 } 93 }
94 // Cannot canonicalize TypeArgument yet as its types may not have been 94 // Cannot canonicalize TypeArgument yet as its types may not have been
95 // finalized yet. 95 // finalized yet.
96 return a.raw(); 96 return a.raw();
97 } 97 }
98 98
99 99
100 static ThrowNode* GenerateRethrow(intptr_t token_pos, const Object& obj) {
101 const UnhandledException& excp = UnhandledException::Cast(obj);
102 Instance& exception = Instance::ZoneHandle(excp.exception());
103 if (exception.IsNew()) {
104 exception ^= Object::Clone(exception, Heap::kOld);
105 }
106 Instance& stack_trace = Instance::ZoneHandle(excp.stacktrace());
107 if (stack_trace.IsNew()) {
108 stack_trace ^= Object::Clone(stack_trace, Heap::kOld);
srdjan 2013/10/24 17:03:32 Why not Canonicalize instead of Clone?
hausner 2013/10/24 17:09:32 This code goes away, but I don't think canonicaliz
109 }
110 return new ThrowNode(token_pos,
111 new LiteralNode(token_pos, exception),
112 new LiteralNode(token_pos, stack_trace));
113 }
114
115
116 LocalVariable* ParsedFunction::EnsureExpressionTemp() { 100 LocalVariable* ParsedFunction::EnsureExpressionTemp() {
117 if (!has_expression_temp_var()) { 101 if (!has_expression_temp_var()) {
118 LocalVariable* temp = 102 LocalVariable* temp =
119 new LocalVariable(function_.token_pos(), 103 new LocalVariable(function_.token_pos(),
120 Symbols::ExprTemp(), 104 Symbols::ExprTemp(),
121 Type::ZoneHandle(Type::DynamicType())); 105 Type::ZoneHandle(Type::DynamicType()));
122 ASSERT(temp != NULL); 106 ASSERT(temp != NULL);
123 set_expression_temp_var(temp); 107 set_expression_temp_var(temp);
124 } 108 }
125 ASSERT(has_expression_temp_var()); 109 ASSERT(has_expression_temp_var());
(...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 ((LookaheadToken(1) == Token::kPERIOD) && 874 ((LookaheadToken(1) == Token::kPERIOD) &&
891 (LookaheadToken(3) == Token::kPERIOD) && 875 (LookaheadToken(3) == Token::kPERIOD) &&
892 (LookaheadToken(5) == Token::kLPAREN))) { 876 (LookaheadToken(5) == Token::kLPAREN))) {
893 expr = ParseNewOperator(Token::kCONST); 877 expr = ParseNewOperator(Token::kCONST);
894 } else { 878 } else {
895 expr = ParsePrimary(); 879 expr = ParsePrimary();
896 } 880 }
897 if (expr->EvalConstExpr() == NULL) { 881 if (expr->EvalConstExpr() == NULL) {
898 ErrorMsg(expr_pos, "expression must be a compile-time constant"); 882 ErrorMsg(expr_pos, "expression must be a compile-time constant");
899 } 883 }
900 const Instance& val = EvaluateConstExpr(expr); 884 const Instance& val = EvaluateConstExpr(expr_pos, expr);
901 meta_values.Add(val); 885 meta_values.Add(val);
902 } 886 }
903 return Array::MakeArray(meta_values); 887 return Array::MakeArray(meta_values);
904 } 888 }
905 889
906 890
907 SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) { 891 SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) {
908 TRACE_PARSER("ParseStaticFinalGetter"); 892 TRACE_PARSER("ParseStaticFinalGetter");
909 ParamList params; 893 ParamList params;
910 ASSERT(func.num_fixed_parameters() == 0); // static. 894 ASSERT(func.num_fixed_parameters() == 0); // static.
(...skipping 1210 matching lines...) Expand 10 before | Expand all | Expand 10 after
2121 const intptr_t saved_token_pos = TokenPos(); 2105 const intptr_t saved_token_pos = TokenPos();
2122 2106
2123 set_current_class(Class::Handle(field.origin())); 2107 set_current_class(Class::Handle(field.origin()));
2124 set_library(Library::Handle(current_class().library())); 2108 set_library(Library::Handle(current_class().library()));
2125 SetScript(Script::Handle(current_class().script()), field.token_pos()); 2109 SetScript(Script::Handle(current_class().script()), field.token_pos());
2126 2110
2127 ASSERT(IsIdentifier()); 2111 ASSERT(IsIdentifier());
2128 ConsumeToken(); 2112 ConsumeToken();
2129 ExpectToken(Token::kASSIGN); 2113 ExpectToken(Token::kASSIGN);
2130 AstNode* init_expr = NULL; 2114 AstNode* init_expr = NULL;
2115 intptr_t expr_pos = TokenPos();
2131 if (field.is_const()) { 2116 if (field.is_const()) {
2132 init_expr = ParseConstExpr(); 2117 init_expr = ParseConstExpr();
2133 } else { 2118 } else {
2134 init_expr = ParseExpr(kAllowConst, kConsumeCascades); 2119 init_expr = ParseExpr(kAllowConst, kConsumeCascades);
2135 if (init_expr->EvalConstExpr() != NULL) { 2120 if (init_expr->EvalConstExpr() != NULL) {
2136 init_expr = 2121 init_expr =
2137 new LiteralNode(field.token_pos(), EvaluateConstExpr(init_expr)); 2122 new LiteralNode(field.token_pos(),
2123 EvaluateConstExpr(expr_pos, init_expr));
2138 } 2124 }
2139 } 2125 }
2140 set_current_class(saved_class); 2126 set_current_class(saved_class);
2141 set_library(saved_library); 2127 set_library(saved_library);
2142 SetScript(saved_script, saved_token_pos); 2128 SetScript(saved_script, saved_token_pos);
2143 return init_expr; 2129 return init_expr;
2144 } 2130 }
2145 2131
2146 2132
2147 void Parser::ParseInitializedInstanceFields(const Class& cls, 2133 void Parser::ParseInitializedInstanceFields(const Class& cls,
(...skipping 18 matching lines...) Expand all
2166 if (current_class().raw() != field.origin()) { 2152 if (current_class().raw() != field.origin()) {
2167 init_expr = ParseExternalInitializedField(field); 2153 init_expr = ParseExternalInitializedField(field);
2168 } else { 2154 } else {
2169 SetPosition(field.token_pos()); 2155 SetPosition(field.token_pos());
2170 ASSERT(IsIdentifier()); 2156 ASSERT(IsIdentifier());
2171 ConsumeToken(); 2157 ConsumeToken();
2172 ExpectToken(Token::kASSIGN); 2158 ExpectToken(Token::kASSIGN);
2173 if (field.is_const()) { 2159 if (field.is_const()) {
2174 init_expr = ParseConstExpr(); 2160 init_expr = ParseConstExpr();
2175 } else { 2161 } else {
2162 intptr_t expr_pos = TokenPos();
2176 init_expr = ParseExpr(kAllowConst, kConsumeCascades); 2163 init_expr = ParseExpr(kAllowConst, kConsumeCascades);
2177 if (init_expr->EvalConstExpr() != NULL) { 2164 if (init_expr->EvalConstExpr() != NULL) {
2178 init_expr = new LiteralNode(field.token_pos(), 2165 init_expr = new LiteralNode(field.token_pos(),
2179 EvaluateConstExpr(init_expr)); 2166 EvaluateConstExpr(expr_pos, init_expr));
2180 } 2167 }
2181 } 2168 }
2182 } 2169 }
2183 ASSERT(init_expr != NULL); 2170 ASSERT(init_expr != NULL);
2184 AstNode* instance = new LoadLocalNode(field.token_pos(), receiver); 2171 AstNode* instance = new LoadLocalNode(field.token_pos(), receiver);
2185 EnsureExpressionTemp(); 2172 EnsureExpressionTemp();
2186 AstNode* field_init = 2173 AstNode* field_init =
2187 new StoreInstanceFieldNode(field.token_pos(), 2174 new StoreInstanceFieldNode(field.token_pos(),
2188 instance, 2175 instance,
2189 field, 2176 field,
(...skipping 5452 matching lines...) Expand 10 before | Expand all | Expand 10 after
7642 7629
7643 // Evaluates the value of the compile time constant expression 7630 // Evaluates the value of the compile time constant expression
7644 // and returns a literal node for the value. 7631 // and returns a literal node for the value.
7645 AstNode* Parser::FoldConstExpr(intptr_t expr_pos, AstNode* expr) { 7632 AstNode* Parser::FoldConstExpr(intptr_t expr_pos, AstNode* expr) {
7646 if (expr->IsLiteralNode()) { 7633 if (expr->IsLiteralNode()) {
7647 return expr; 7634 return expr;
7648 } 7635 }
7649 if (expr->EvalConstExpr() == NULL) { 7636 if (expr->EvalConstExpr() == NULL) {
7650 ErrorMsg(expr_pos, "expression is not a valid compile-time constant"); 7637 ErrorMsg(expr_pos, "expression is not a valid compile-time constant");
7651 } 7638 }
7652 return new LiteralNode(expr_pos, EvaluateConstExpr(expr)); 7639 return new LiteralNode(expr_pos, EvaluateConstExpr(expr_pos, expr));
7653 } 7640 }
7654 7641
7655 7642
7656 LetNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) { 7643 LetNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) {
7657 AstNode* node = *expr; 7644 AstNode* node = *expr;
7658 intptr_t token_pos = node->token_pos(); 7645 intptr_t token_pos = node->token_pos();
7659 LetNode* result = new LetNode(token_pos); 7646 LetNode* result = new LetNode(token_pos);
7660 if (node->IsLoadIndexedNode()) { 7647 if (node->IsLoadIndexedNode()) {
7661 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode(); 7648 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode();
7662 AstNode* array = load_indexed->array(); 7649 AstNode* array = load_indexed->array();
(...skipping 1902 matching lines...) Expand 10 before | Expand all | Expand 10 after
9565 const Function& map_constr = 9552 const Function& map_constr =
9566 Function::ZoneHandle(immutable_map_class.LookupConstructor( 9553 Function::ZoneHandle(immutable_map_class.LookupConstructor(
9567 Library::PrivateCoreLibName(Symbols::ImmutableMapConstructor()))); 9554 Library::PrivateCoreLibName(Symbols::ImmutableMapConstructor())));
9568 ASSERT(!map_constr.IsNull()); 9555 ASSERT(!map_constr.IsNull());
9569 const Object& constructor_result = Object::Handle( 9556 const Object& constructor_result = Object::Handle(
9570 EvaluateConstConstructorCall(immutable_map_class, 9557 EvaluateConstConstructorCall(immutable_map_class,
9571 map_type_arguments, 9558 map_type_arguments,
9572 map_constr, 9559 map_constr,
9573 constr_args)); 9560 constr_args));
9574 if (constructor_result.IsUnhandledException()) { 9561 if (constructor_result.IsUnhandledException()) {
9575 return GenerateRethrow(literal_pos, constructor_result); 9562 AppendErrorMsg(Error::Cast(constructor_result),
9563 literal_pos,
9564 "error executing const Map constructor");
9576 } else { 9565 } else {
9577 const Instance& const_instance = Instance::Cast(constructor_result); 9566 const Instance& const_instance = Instance::Cast(constructor_result);
9578 return new LiteralNode(literal_pos, 9567 return new LiteralNode(literal_pos,
9579 Instance::ZoneHandle(const_instance.raw())); 9568 Instance::ZoneHandle(const_instance.raw()));
9580 } 9569 }
9581 } else { 9570 } else {
9582 // Factory call at runtime. 9571 // Factory call at runtime.
9583 const Class& factory_class = 9572 const Class& factory_class =
9584 Class::Handle(Library::LookupCoreClass(Symbols::Map())); 9573 Class::Handle(Library::LookupCoreClass(Symbols::Map()));
9585 ASSERT(!factory_class.IsNull()); 9574 ASSERT(!factory_class.IsNull());
(...skipping 27 matching lines...) Expand all
9613 ArrayNode* kv_pairs = new ArrayNode( 9602 ArrayNode* kv_pairs = new ArrayNode(
9614 TokenPos(), 9603 TokenPos(),
9615 Type::ZoneHandle(Type::ArrayType()), 9604 Type::ZoneHandle(Type::ArrayType()),
9616 kv_pairs_list); 9605 kv_pairs_list);
9617 factory_param->Add(kv_pairs); 9606 factory_param->Add(kv_pairs);
9618 return CreateConstructorCallNode(literal_pos, 9607 return CreateConstructorCallNode(literal_pos,
9619 factory_type_args, 9608 factory_type_args,
9620 factory_method, 9609 factory_method,
9621 factory_param); 9610 factory_param);
9622 } 9611 }
9612 UNREACHABLE();
9613 return NULL;
9623 } 9614 }
9624 9615
9625 9616
9626 AstNode* Parser::ParseCompoundLiteral() { 9617 AstNode* Parser::ParseCompoundLiteral() {
9627 TRACE_PARSER("ParseCompoundLiteral"); 9618 TRACE_PARSER("ParseCompoundLiteral");
9628 bool is_const = false; 9619 bool is_const = false;
9629 if (CurrentToken() == Token::kCONST) { 9620 if (CurrentToken() == Token::kCONST) {
9630 is_const = true; 9621 is_const = true;
9631 ConsumeToken(); 9622 ConsumeToken();
9632 } 9623 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
9678 symbol_pos, String::ZoneHandle(Symbols::New(symbol)))); 9669 symbol_pos, String::ZoneHandle(Symbols::New(symbol))));
9679 const Function& constr = Function::ZoneHandle( 9670 const Function& constr = Function::ZoneHandle(
9680 symbol_class.LookupConstructor(Symbols::SymbolCtor())); 9671 symbol_class.LookupConstructor(Symbols::SymbolCtor()));
9681 ASSERT(!constr.IsNull()); 9672 ASSERT(!constr.IsNull());
9682 const Object& result = Object::Handle( 9673 const Object& result = Object::Handle(
9683 EvaluateConstConstructorCall(symbol_class, 9674 EvaluateConstConstructorCall(symbol_class,
9684 TypeArguments::Handle(), 9675 TypeArguments::Handle(),
9685 constr, 9676 constr,
9686 constr_args)); 9677 constr_args));
9687 if (result.IsUnhandledException()) { 9678 if (result.IsUnhandledException()) {
9688 return GenerateRethrow(symbol_pos, result); 9679 AppendErrorMsg(Error::Cast(result),
9680 symbol_pos,
9681 "error executing const Symbol constructor");
9689 } 9682 }
9690 const Instance& instance = Instance::Cast(result); 9683 const Instance& instance = Instance::Cast(result);
9691 return new LiteralNode(symbol_pos, Instance::ZoneHandle(instance.raw())); 9684 return new LiteralNode(symbol_pos, Instance::ZoneHandle(instance.raw()));
9692 } 9685 }
9693 9686
9694 9687
9695 static String& BuildConstructorName(const String& type_class_name, 9688 static String& BuildConstructorName(const String& type_class_name,
9696 const String* named_constructor) { 9689 const String* named_constructor) {
9697 // By convention, the static function implementing a named constructor 'C' 9690 // By convention, the static function implementing a named constructor 'C'
9698 // for class 'A' is labeled 'A.C', and the static function implementing the 9691 // for class 'A' is labeled 'A.C', and the static function implementing the
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
9916 ErrorMsg("non-const constructor '%s' cannot be used in " 9909 ErrorMsg("non-const constructor '%s' cannot be used in "
9917 "const object creation", 9910 "const object creation",
9918 external_constructor_name.ToCString()); 9911 external_constructor_name.ToCString());
9919 } 9912 }
9920 const Object& constructor_result = Object::Handle( 9913 const Object& constructor_result = Object::Handle(
9921 EvaluateConstConstructorCall(type_class, 9914 EvaluateConstConstructorCall(type_class,
9922 type_arguments, 9915 type_arguments,
9923 constructor, 9916 constructor,
9924 arguments)); 9917 arguments));
9925 if (constructor_result.IsUnhandledException()) { 9918 if (constructor_result.IsUnhandledException()) {
9926 new_object = GenerateRethrow(new_pos, constructor_result); 9919 // It's a compile-time error if invocation of a const constructor
9920 // call fails.
9921 AppendErrorMsg(Error::Cast(constructor_result),
9922 new_pos,
9923 "error while evaluating const constructor");
9927 } else { 9924 } else {
9928 const Instance& const_instance = Instance::Cast(constructor_result); 9925 const Instance& const_instance = Instance::Cast(constructor_result);
9929 new_object = new LiteralNode(new_pos, 9926 new_object = new LiteralNode(new_pos,
9930 Instance::ZoneHandle(const_instance.raw())); 9927 Instance::ZoneHandle(const_instance.raw()));
9931 if (!type_bound.IsNull()) { 9928 if (!type_bound.IsNull()) {
9932 ASSERT(!type_bound.IsMalformed()); 9929 ASSERT(!type_bound.IsMalformed());
9933 Error& malformed_error = Error::Handle(); 9930 Error& malformed_error = Error::Handle();
9934 ASSERT(!is_top_level_); // We cannot check unresolved types. 9931 ASSERT(!is_top_level_); // We cannot check unresolved types.
9935 if (!const_instance.IsInstanceOf(type_bound, 9932 if (!const_instance.IsInstanceOf(type_bound,
9936 TypeArguments::Handle(), 9933 TypeArguments::Handle(),
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
10053 // a constant or not. Only strings, numbers, booleans and null values 10050 // a constant or not. Only strings, numbers, booleans and null values
10054 // are allowed in compile time const interpolations. 10051 // are allowed in compile time const interpolations.
10055 if (is_compiletime_const) { 10052 if (is_compiletime_const) {
10056 const Object* const_expr = expr->EvalConstExpr(); 10053 const Object* const_expr = expr->EvalConstExpr();
10057 if ((const_expr != NULL) && 10054 if ((const_expr != NULL) &&
10058 (const_expr->IsNumber() || 10055 (const_expr->IsNumber() ||
10059 const_expr->IsString() || 10056 const_expr->IsString() ||
10060 const_expr->IsBool() || 10057 const_expr->IsBool() ||
10061 const_expr->IsNull())) { 10058 const_expr->IsNull())) {
10062 // Change expr into a literal. 10059 // Change expr into a literal.
10063 expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr)); 10060 expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr_pos, expr));
10064 } else { 10061 } else {
10065 is_compiletime_const = false; 10062 is_compiletime_const = false;
10066 } 10063 }
10067 } 10064 }
10068 values_list.Add(expr); 10065 values_list.Add(expr);
10069 } 10066 }
10070 } 10067 }
10071 if (is_compiletime_const) { 10068 if (is_compiletime_const) {
10072 if (has_interpolation) { 10069 if (has_interpolation) {
10073 primary = new LiteralNode(literal_start, Interpolate(values_list)); 10070 primary = new LiteralNode(literal_start, Interpolate(values_list));
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
10251 } 10248 }
10252 } else { 10249 } else {
10253 UnexpectedToken(); 10250 UnexpectedToken();
10254 } 10251 }
10255 return primary; 10252 return primary;
10256 } 10253 }
10257 10254
10258 10255
10259 // Evaluate expression in expr and return the value. The expression must 10256 // Evaluate expression in expr and return the value. The expression must
10260 // be a compile time constant. 10257 // be a compile time constant.
10261 const Instance& Parser::EvaluateConstExpr(AstNode* expr) { 10258 const Instance& Parser::EvaluateConstExpr(intptr_t expr_pos, AstNode* expr) {
10262 if (expr->IsLiteralNode()) { 10259 if (expr->IsLiteralNode()) {
10263 return expr->AsLiteralNode()->literal(); 10260 return expr->AsLiteralNode()->literal();
10264 } else if (expr->IsLoadLocalNode() && 10261 } else if (expr->IsLoadLocalNode() &&
10265 expr->AsLoadLocalNode()->local().IsConst()) { 10262 expr->AsLoadLocalNode()->local().IsConst()) {
10266 return *expr->AsLoadLocalNode()->local().ConstValue(); 10263 return *expr->AsLoadLocalNode()->local().ConstValue();
10267 } else { 10264 } else {
10268 ASSERT(expr->EvalConstExpr() != NULL); 10265 ASSERT(expr->EvalConstExpr() != NULL);
10269 ReturnNode* ret = new ReturnNode(expr->token_pos(), expr); 10266 ReturnNode* ret = new ReturnNode(expr->token_pos(), expr);
10270 // Compile time constant expressions cannot reference anything from a 10267 // Compile time constant expressions cannot reference anything from a
10271 // local scope. 10268 // local scope.
10272 LocalScope* empty_scope = new LocalScope(NULL, 0, 0); 10269 LocalScope* empty_scope = new LocalScope(NULL, 0, 0);
10273 SequenceNode* seq = new SequenceNode(expr->token_pos(), empty_scope); 10270 SequenceNode* seq = new SequenceNode(expr->token_pos(), empty_scope);
10274 seq->Add(ret); 10271 seq->Add(ret);
10275 10272
10276 Object& result = Object::Handle(Compiler::ExecuteOnce(seq)); 10273 Object& result = Object::Handle(Compiler::ExecuteOnce(seq));
10277 if (result.IsError()) { 10274 if (result.IsError()) {
10278 // Propagate the compilation error. 10275 AppendErrorMsg(Error::Cast(result),
10279 isolate()->long_jump_base()->Jump(1, Error::Cast(result)); 10276 expr_pos,
10280 UNREACHABLE(); 10277 "error evaluating constant expression");
10281 } 10278 }
10282 ASSERT(result.IsInstance()); 10279 ASSERT(result.IsInstance());
10283 Instance& value = Instance::ZoneHandle(); 10280 Instance& value = Instance::ZoneHandle();
10284 value ^= result.raw(); 10281 value ^= result.raw();
10285 value = TryCanonicalize(value, TokenPos()); 10282 value = TryCanonicalize(value, TokenPos());
10286 return value; 10283 return value;
10287 } 10284 }
10288 } 10285 }
10289 10286
10290 10287
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
10611 void Parser::SkipQualIdent() { 10608 void Parser::SkipQualIdent() {
10612 ASSERT(IsIdentifier()); 10609 ASSERT(IsIdentifier());
10613 ConsumeToken(); 10610 ConsumeToken();
10614 if (CurrentToken() == Token::kPERIOD) { 10611 if (CurrentToken() == Token::kPERIOD) {
10615 ConsumeToken(); // Consume the kPERIOD token. 10612 ConsumeToken(); // Consume the kPERIOD token.
10616 ExpectIdentifier("identifier expected after '.'"); 10613 ExpectIdentifier("identifier expected after '.'");
10617 } 10614 }
10618 } 10615 }
10619 10616
10620 } // namespace dart 10617 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-co19.status » ('j') | tests/co19/co19-co19.status » ('J')

Powered by Google App Engine
This is Rietveld 408576698