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

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

Issue 14942010: Eliminate temporary locals for some expressions (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/scopes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/class_finalizer.h" 9 #include "vm/class_finalizer.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 } 109 }
110 110
111 111
112 LocalVariable* ParsedFunction::CreateExpressionTempVar(intptr_t token_pos) { 112 LocalVariable* ParsedFunction::CreateExpressionTempVar(intptr_t token_pos) {
113 return new LocalVariable(token_pos, 113 return new LocalVariable(token_pos,
114 Symbols::ExprTemp(), 114 Symbols::ExprTemp(),
115 Type::ZoneHandle(Type::DynamicType())); 115 Type::ZoneHandle(Type::DynamicType()));
116 } 116 }
117 117
118 118
119 LocalVariable* ParsedFunction::CreateArrayLiteralVar(intptr_t token_pos) {
120 return new LocalVariable(token_pos,
121 Symbols::ArrayLiteralVar(),
122 Type::ZoneHandle(Type::ArrayType()));
123 }
124
125
126 void ParsedFunction::SetNodeSequence(SequenceNode* node_sequence) { 119 void ParsedFunction::SetNodeSequence(SequenceNode* node_sequence) {
127 ASSERT(node_sequence_ == NULL); 120 ASSERT(node_sequence_ == NULL);
128 ASSERT(node_sequence != NULL); 121 ASSERT(node_sequence != NULL);
129 node_sequence_ = node_sequence; 122 node_sequence_ = node_sequence;
130 } 123 }
131 124
132 125
133 LocalVariable* ParsedFunction::GetSavedArgumentsDescriptorVar() const { 126 LocalVariable* ParsedFunction::GetSavedArgumentsDescriptorVar() const {
134 const int num_parameters = function().NumParameters(); 127 const int num_parameters = function().NumParameters();
135 LocalScope* scope = node_sequence()->scope(); 128 LocalScope* scope = node_sequence()->scope();
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 case RawFunction::kConstImplicitGetter: 774 case RawFunction::kConstImplicitGetter:
782 node_sequence = parser.ParseStaticConstGetter(func); 775 node_sequence = parser.ParseStaticConstGetter(func);
783 break; 776 break;
784 case RawFunction::kMethodExtractor: 777 case RawFunction::kMethodExtractor:
785 node_sequence = parser.ParseMethodExtractor(func); 778 node_sequence = parser.ParseMethodExtractor(func);
786 break; 779 break;
787 default: 780 default:
788 UNREACHABLE(); 781 UNREACHABLE();
789 } 782 }
790 783
791 parsed_function->set_array_literal_var(
792 ParsedFunction::CreateArrayLiteralVar(func.token_pos()));
793 node_sequence->scope()->AddVariable(parsed_function->array_literal_var());
794
795 if (!HasReturnNode(node_sequence)) { 784 if (!HasReturnNode(node_sequence)) {
796 // Add implicit return node. 785 // Add implicit return node.
797 node_sequence->Add(new ReturnNode(func.end_token_pos())); 786 node_sequence->Add(new ReturnNode(func.end_token_pos()));
798 } 787 }
799 if (parsed_function->has_expression_temp_var()) { 788 if (parsed_function->has_expression_temp_var()) {
800 node_sequence->scope()->AddVariable(parsed_function->expression_temp_var()); 789 node_sequence->scope()->AddVariable(parsed_function->expression_temp_var());
801 } 790 }
802 if (parsed_function->has_saved_current_context_var()) { 791 if (parsed_function->has_saved_current_context_var()) {
803 node_sequence->scope()->AddVariable( 792 node_sequence->scope()->AddVariable(
804 parsed_function->saved_current_context_var()); 793 parsed_function->saved_current_context_var());
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 } 1391 }
1403 1392
1404 1393
1405 static const String& PrivateCoreLibName(const String& str) { 1394 static const String& PrivateCoreLibName(const String& str) {
1406 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 1395 const Library& core_lib = Library::Handle(Library::CoreLibrary());
1407 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str)); 1396 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str));
1408 return private_name; 1397 return private_name;
1409 } 1398 }
1410 1399
1411 1400
1412 LocalVariable* Parser::BuildArrayTempLocal(intptr_t token_pos) {
1413 char name[64];
1414 OS::SNPrint(name, 64, ":arrlit%"Pd, token_pos);
1415 LocalVariable* temp =
1416 new LocalVariable(token_pos,
1417 String::ZoneHandle(Symbols::New(name)),
1418 Type::ZoneHandle(Type::ArrayType()));
1419 current_block_->scope->AddVariable(temp);
1420 return temp;
1421 }
1422
1423
1424 StaticCallNode* Parser::BuildInvocationMirrorAllocation( 1401 StaticCallNode* Parser::BuildInvocationMirrorAllocation(
1425 intptr_t call_pos, 1402 intptr_t call_pos,
1426 const String& function_name, 1403 const String& function_name,
1427 const ArgumentListNode& function_args) { 1404 const ArgumentListNode& function_args) {
1428 const intptr_t args_pos = function_args.token_pos(); 1405 const intptr_t args_pos = function_args.token_pos();
1429 // Build arguments to the call to the static 1406 // Build arguments to the call to the static
1430 // InvocationMirror._allocateInvocationMirror method. 1407 // InvocationMirror._allocateInvocationMirror method.
1431 ArgumentListNode* arguments = new ArgumentListNode(args_pos); 1408 ArgumentListNode* arguments = new ArgumentListNode(args_pos);
1432 // The first argument is the original function name. 1409 // The first argument is the original function name.
1433 arguments->Add(new LiteralNode(args_pos, function_name)); 1410 arguments->Add(new LiteralNode(args_pos, function_name));
1434 // The second argument is the arguments descriptor of the original function. 1411 // The second argument is the arguments descriptor of the original function.
1435 const Array& args_descriptor = 1412 const Array& args_descriptor =
1436 Array::ZoneHandle(ArgumentsDescriptor::New(function_args.length(), 1413 Array::ZoneHandle(ArgumentsDescriptor::New(function_args.length(),
1437 function_args.names())); 1414 function_args.names()));
1438 arguments->Add(new LiteralNode(args_pos, args_descriptor)); 1415 arguments->Add(new LiteralNode(args_pos, args_descriptor));
1439 // The third argument is an array containing the original function arguments, 1416 // The third argument is an array containing the original function arguments,
1440 // including the receiver. 1417 // including the receiver.
1441 ArrayNode* args_array = new ArrayNode( 1418 ArrayNode* args_array =
1442 args_pos, Type::ZoneHandle(Type::ArrayType()), 1419 new ArrayNode(args_pos, Type::ZoneHandle(Type::ArrayType()));
1443 *BuildArrayTempLocal(call_pos));
1444 for (intptr_t i = 0; i < function_args.length(); i++) { 1420 for (intptr_t i = 0; i < function_args.length(); i++) {
1445 args_array->AddElement(function_args.NodeAt(i)); 1421 args_array->AddElement(function_args.NodeAt(i));
1446 } 1422 }
1447 arguments->Add(args_array); 1423 arguments->Add(args_array);
1448 // Lookup the static InvocationMirror._allocateInvocationMirror method. 1424 // Lookup the static InvocationMirror._allocateInvocationMirror method.
1449 const Class& mirror_class = 1425 const Class& mirror_class =
1450 Class::Handle(LookupCoreClass(Symbols::InvocationMirror())); 1426 Class::Handle(LookupCoreClass(Symbols::InvocationMirror()));
1451 ASSERT(!mirror_class.IsNull()); 1427 ASSERT(!mirror_class.IsNull());
1452 const Function& allocation_function = Function::ZoneHandle( 1428 const Function& allocation_function = Function::ZoneHandle(
1453 mirror_class.LookupStaticFunction( 1429 mirror_class.LookupStaticFunction(
(...skipping 5567 matching lines...) Expand 10 before | Expand all | Expand 10 after
7021 if (expr->IsLiteralNode()) { 6997 if (expr->IsLiteralNode()) {
7022 return expr; 6998 return expr;
7023 } 6999 }
7024 if (expr->EvalConstExpr() == NULL) { 7000 if (expr->EvalConstExpr() == NULL) {
7025 ErrorMsg(expr_pos, "expression must be a compile-time constant"); 7001 ErrorMsg(expr_pos, "expression must be a compile-time constant");
7026 } 7002 }
7027 return new LiteralNode(expr_pos, EvaluateConstExpr(expr)); 7003 return new LiteralNode(expr_pos, EvaluateConstExpr(expr));
7028 } 7004 }
7029 7005
7030 7006
7031 // A compound assignment consists of a store and a load part. In order 7007 LetNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) {
7032 // to control inputs with potential side effects, the store part stores any
7033 // side effect creating inputs into locals. The load part reads then from
7034 // those locals. If expr may have side effects, it will be split into two new
7035 // left and right nodes. 'expr' becomes the right node, left node is returned as
7036 // result.
7037 AstNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) {
7038 AstNode* node = *expr; 7008 AstNode* node = *expr;
7009 intptr_t token_pos = node->token_pos();
7010 LetNode* result = new LetNode(token_pos);
7039 if (node->IsLoadIndexedNode()) { 7011 if (node->IsLoadIndexedNode()) {
7040 LoadIndexedNode* left_node = node->AsLoadIndexedNode(); 7012 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode();
7041 LoadIndexedNode* right_node = left_node; 7013 AstNode* array = load_indexed->array();
7042 intptr_t token_pos = node->token_pos(); 7014 AstNode* index = load_indexed->index_expr();
7043 node = NULL; // Do not use it. 7015 if (!IsSimpleLocalOrLiteralNode(load_indexed->array())) {
7044 if (!IsSimpleLocalOrLiteralNode(left_node->array())) { 7016 LocalVariable* t0 = result->AddInitializer(load_indexed->array());
7045 LocalVariable* temp = 7017 array = new LoadLocalNode(token_pos, t0);
7046 CreateTempConstVariable(token_pos, "lia");
7047 StoreLocalNode* save =
7048 new StoreLocalNode(token_pos, temp, left_node->array());
7049 left_node = new LoadIndexedNode(token_pos,
7050 save,
7051 left_node->index_expr(),
7052 left_node->super_class());
7053 right_node = new LoadIndexedNode(token_pos,
7054 new LoadLocalNode(token_pos, temp),
7055 right_node->index_expr(),
7056 right_node->super_class());
7057 } 7018 }
7058 if (!IsSimpleLocalOrLiteralNode(left_node->index_expr())) { 7019 if (!IsSimpleLocalOrLiteralNode(load_indexed->index_expr())) {
7059 LocalVariable* temp = 7020 LocalVariable* t1 = result->AddInitializer(
7060 CreateTempConstVariable(token_pos, "lix"); 7021 load_indexed->index_expr());
7061 StoreLocalNode* save = 7022 index = new LoadLocalNode(token_pos, t1);
7062 new StoreLocalNode(token_pos, temp, left_node->index_expr());
7063 left_node = new LoadIndexedNode(token_pos,
7064 left_node->array(),
7065 save,
7066 left_node->super_class());
7067 right_node = new LoadIndexedNode(token_pos,
7068 right_node->array(),
7069 new LoadLocalNode(token_pos, temp),
7070 right_node->super_class());
7071 } 7023 }
7072 *expr = right_node; 7024 *expr = new LoadIndexedNode(token_pos,
7073 return left_node; 7025 array,
7026 index,
7027 load_indexed->super_class());
7028 return result;
7074 } 7029 }
7075 if (node->IsInstanceGetterNode()) { 7030 if (node->IsInstanceGetterNode()) {
7076 InstanceGetterNode* left_node = node->AsInstanceGetterNode(); 7031 InstanceGetterNode* getter = node->AsInstanceGetterNode();
7077 InstanceGetterNode* right_node = left_node; 7032 AstNode* receiver = getter->receiver();
7078 intptr_t token_pos = node->token_pos(); 7033 if (!IsSimpleLocalOrLiteralNode(getter->receiver())) {
7079 node = NULL; // Do not use it. 7034 LocalVariable* t0 = result->AddInitializer(getter->receiver());
7080 if (!IsSimpleLocalOrLiteralNode(left_node->receiver())) { 7035 receiver = new LoadLocalNode(token_pos, t0);
7081 LocalVariable* temp =
7082 CreateTempConstVariable(token_pos, "igr");
7083 StoreLocalNode* save =
7084 new StoreLocalNode(token_pos, temp, left_node->receiver());
7085 left_node = new InstanceGetterNode(token_pos,
7086 save,
7087 left_node->field_name());
7088 right_node = new InstanceGetterNode(token_pos,
7089 new LoadLocalNode(token_pos, temp),
7090 right_node->field_name());
7091 } 7036 }
7092 *expr = right_node; 7037 *expr = new InstanceGetterNode(token_pos,
7093 return left_node; 7038 receiver,
7039 getter->field_name());
7040 return result;
7094 } 7041 }
7095 return *expr; 7042 return result;
7096 } 7043 }
7097 7044
7098 7045
7099 // Ensure that the expression temp is allocated for nodes that may need it. 7046 // Ensure that the expression temp is allocated for nodes that may need it.
7100 AstNode* Parser::CreateAssignmentNode(AstNode* original, AstNode* rhs) { 7047 AstNode* Parser::CreateAssignmentNode(AstNode* original, AstNode* rhs) {
7101 AstNode* result = original->MakeAssignmentNode(rhs); 7048 AstNode* result = original->MakeAssignmentNode(rhs);
7102 if ((result == NULL) && original->IsTypeNode()) { 7049 if ((result == NULL) && original->IsTypeNode()) {
7103 const String& type_name = String::ZoneHandle( 7050 const String& type_name = String::ZoneHandle(
7104 original->AsTypeNode()->type().ClassName()); 7051 original->AsTypeNode()->type().ClassName());
7105 // TODO(tball): determine whether NoSuchMethod should be called instead. 7052 // TODO(tball): determine whether NoSuchMethod should be called instead.
(...skipping 10 matching lines...) Expand all
7116 result->IsStoreStaticFieldNode() || 7063 result->IsStoreStaticFieldNode() ||
7117 result->IsStoreLocalNode())) { 7064 result->IsStoreLocalNode())) {
7118 EnsureExpressionTemp(); 7065 EnsureExpressionTemp();
7119 } 7066 }
7120 return result; 7067 return result;
7121 } 7068 }
7122 7069
7123 7070
7124 AstNode* Parser::ParseCascades(AstNode* expr) { 7071 AstNode* Parser::ParseCascades(AstNode* expr) {
7125 intptr_t cascade_pos = TokenPos(); 7072 intptr_t cascade_pos = TokenPos();
7126 LocalVariable* cascade_receiver_var = 7073 LetNode* result = new LetNode(cascade_pos);
7127 CreateTempConstVariable(cascade_pos, "casc"); 7074 LocalVariable* cascade_receiver_var = result->AddInitializer(expr);
7075 // TODO(fschneider): Make LetNode support more than one body node and
7076 // replace the SequenceNode here and CommaNode here and in postfix
7077 // expressions.
7128 SequenceNode* cascade = new SequenceNode(cascade_pos, NULL); 7078 SequenceNode* cascade = new SequenceNode(cascade_pos, NULL);
7129 StoreLocalNode* save_cascade =
7130 new StoreLocalNode(cascade_pos, cascade_receiver_var, expr);
7131 cascade->Add(save_cascade);
7132 while (CurrentToken() == Token::kCASCADE) { 7079 while (CurrentToken() == Token::kCASCADE) {
7133 cascade_pos = TokenPos(); 7080 cascade_pos = TokenPos();
7134 LoadLocalNode* load_cascade_receiver = 7081 LoadLocalNode* load_cascade_receiver =
7135 new LoadLocalNode(cascade_pos, cascade_receiver_var); 7082 new LoadLocalNode(cascade_pos, cascade_receiver_var);
7136 if (Token::IsIdentifier(LookaheadToken(1))) { 7083 if (Token::IsIdentifier(LookaheadToken(1))) {
7137 // Replace .. with . for ParseSelectors(). 7084 // Replace .. with . for ParseSelectors().
7138 token_kind_ = Token::kPERIOD; 7085 token_kind_ = Token::kPERIOD;
7139 } else if (LookaheadToken(1) == Token::kLBRACK) { 7086 } else if (LookaheadToken(1) == Token::kLBRACK) {
7140 ConsumeToken(); 7087 ConsumeToken();
7141 } else { 7088 } else {
7142 ErrorMsg("identifier or [ expected after .."); 7089 ErrorMsg("identifier or [ expected after ..");
7143 } 7090 }
7144 expr = ParseSelectors(load_cascade_receiver, true); 7091 expr = ParseSelectors(load_cascade_receiver, true);
7145 7092
7146 // Assignments after a cascade are part of the cascade. The 7093 // Assignments after a cascade are part of the cascade. The
7147 // assigned expression must not contain cascades. 7094 // assigned expression must not contain cascades.
7148 if (Token::IsAssignmentOperator(CurrentToken())) { 7095 if (Token::IsAssignmentOperator(CurrentToken())) {
7149 Token::Kind assignment_op = CurrentToken(); 7096 Token::Kind assignment_op = CurrentToken();
7150 const intptr_t assignment_pos = TokenPos(); 7097 const intptr_t assignment_pos = TokenPos();
7151 ConsumeToken(); 7098 ConsumeToken();
7152 AstNode* right_expr = ParseExpr(kAllowConst, kNoCascades); 7099 AstNode* right_expr = ParseExpr(kAllowConst, kNoCascades);
7153 AstNode* left_expr = expr;
7154 if (assignment_op != Token::kASSIGN) { 7100 if (assignment_op != Token::kASSIGN) {
7155 // Compound assignment: store inputs with side effects into 7101 // Compound assignment: store inputs with side effects into
7156 // temporary locals. 7102 // temporary locals.
7157 left_expr = PrepareCompoundAssignmentNodes(&expr); 7103 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
7104 right_expr =
7105 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
7106 AstNode* assign_expr = CreateAssignmentNode(expr, right_expr);
7107 if (assign_expr == NULL) {
7108 ErrorMsg(assignment_pos,
7109 "left hand side of '%s' is not assignable",
7110 Token::Str(assignment_op));
7111 }
7112 let_expr->set_body(assign_expr);
7113 expr = let_expr;
7114 } else {
7115 right_expr =
7116 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
7117 AstNode* assign_expr = CreateAssignmentNode(expr, right_expr);
7118 if (assign_expr == NULL) {
7119 ErrorMsg(assignment_pos,
7120 "left hand side of '%s' is not assignable",
7121 Token::Str(assignment_op));
7122 }
7123 expr = assign_expr;
7158 } 7124 }
7159 right_expr =
7160 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
7161 AstNode* assign_expr = CreateAssignmentNode(left_expr, right_expr);
7162 if (assign_expr == NULL) {
7163 ErrorMsg(assignment_pos,
7164 "left hand side of '%s' is not assignable",
7165 Token::Str(assignment_op));
7166 }
7167 expr = assign_expr;
7168 } 7125 }
7169 cascade->Add(expr); 7126 cascade->Add(expr);
7170 } 7127 }
7171 // The result is a pair of the (side effects of the) cascade sequence 7128 // The result is a pair of the (side effects of the) cascade sequence
7172 // followed by the (value of the) receiver temp variable load. 7129 // followed by the (value of the) receiver temp variable load.
7173 return new CommaNode( 7130 CommaNode* body = new CommaNode(
7174 cascade_pos, 7131 cascade_pos,
7175 cascade, 7132 cascade,
7176 new LoadLocalNode(cascade_pos, cascade_receiver_var)); 7133 new LoadLocalNode(cascade_pos, cascade_receiver_var));
7134 result->set_body(body);
7135 return result;
7177 } 7136 }
7178 7137
7179 7138
7180 AstNode* Parser::ParseExpr(bool require_compiletime_const, 7139 AstNode* Parser::ParseExpr(bool require_compiletime_const,
7181 bool consume_cascades) { 7140 bool consume_cascades) {
7182 TRACE_PARSER("ParseExpr"); 7141 TRACE_PARSER("ParseExpr");
7183 const intptr_t expr_pos = TokenPos(); 7142 const intptr_t expr_pos = TokenPos();
7184 7143
7185 if (CurrentToken() == Token::kTHROW) { 7144 if (CurrentToken() == Token::kTHROW) {
7186 ConsumeToken(); 7145 ConsumeToken();
(...skipping 13 matching lines...) Expand all
7200 } 7159 }
7201 // Assignment expressions. 7160 // Assignment expressions.
7202 Token::Kind assignment_op = CurrentToken(); 7161 Token::Kind assignment_op = CurrentToken();
7203 const intptr_t assignment_pos = TokenPos(); 7162 const intptr_t assignment_pos = TokenPos();
7204 ConsumeToken(); 7163 ConsumeToken();
7205 const intptr_t right_expr_pos = TokenPos(); 7164 const intptr_t right_expr_pos = TokenPos();
7206 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { 7165 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) {
7207 ErrorMsg(right_expr_pos, "expression must be a compile-time constant"); 7166 ErrorMsg(right_expr_pos, "expression must be a compile-time constant");
7208 } 7167 }
7209 AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades); 7168 AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades);
7210 AstNode* left_expr = expr;
7211 if (assignment_op != Token::kASSIGN) { 7169 if (assignment_op != Token::kASSIGN) {
7212 // Compound assignment: store inputs with side effects into temp. locals. 7170 // Compound assignment: store inputs with side effects into temp. locals.
7213 left_expr = PrepareCompoundAssignmentNodes(&expr); 7171 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
7172 AstNode* assigned_value =
7173 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
7174 AstNode* assign_expr = CreateAssignmentNode(expr, assigned_value);
7175 if (assign_expr == NULL) {
7176 ErrorMsg(assignment_pos,
7177 "left hand side of '%s' is not assignable",
7178 Token::Str(assignment_op));
7179 }
7180 let_expr->set_body(assign_expr);
7181 return let_expr;
7182 } else {
7183 AstNode* assigned_value =
7184 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
7185 AstNode* assign_expr = CreateAssignmentNode(expr, assigned_value);
7186 if (assign_expr == NULL) {
7187 ErrorMsg(assignment_pos,
7188 "left hand side of '%s' is not assignable",
7189 Token::Str(assignment_op));
7190 }
7191 return assign_expr;
7214 } 7192 }
7215 right_expr =
7216 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
7217 AstNode* assign_expr = CreateAssignmentNode(left_expr, right_expr);
7218 if (assign_expr == NULL) {
7219 ErrorMsg(assignment_pos,
7220 "left hand side of '%s' is not assignable",
7221 Token::Str(assignment_op));
7222 }
7223 return assign_expr;
7224 } 7193 }
7225 7194
7226 7195
7227 LiteralNode* Parser::ParseConstExpr() { 7196 LiteralNode* Parser::ParseConstExpr() {
7228 TRACE_PARSER("ParseConstExpr"); 7197 TRACE_PARSER("ParseConstExpr");
7229 AstNode* expr = ParseExpr(kRequireConst, kNoCascades); 7198 AstNode* expr = ParseExpr(kRequireConst, kNoCascades);
7230 ASSERT(expr->IsLiteralNode()); 7199 ASSERT(expr->IsLiteralNode());
7231 return expr->AsLiteralNode(); 7200 return expr->AsLiteralNode();
7232 } 7201 }
7233 7202
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
7271 expr = UnaryOpNode::UnaryOpOrLiteral(op_pos, unary_op, expr); 7240 expr = UnaryOpNode::UnaryOpOrLiteral(op_pos, unary_op, expr);
7272 } 7241 }
7273 } else if (IsIncrementOperator(CurrentToken())) { 7242 } else if (IsIncrementOperator(CurrentToken())) {
7274 Token::Kind incr_op = CurrentToken(); 7243 Token::Kind incr_op = CurrentToken();
7275 ConsumeToken(); 7244 ConsumeToken();
7276 expr = ParseUnaryExpr(); 7245 expr = ParseUnaryExpr();
7277 if (!IsAssignableExpr(expr)) { 7246 if (!IsAssignableExpr(expr)) {
7278 ErrorMsg("expression is not assignable"); 7247 ErrorMsg("expression is not assignable");
7279 } 7248 }
7280 // Is prefix. 7249 // Is prefix.
7281 AstNode* left_expr = PrepareCompoundAssignmentNodes(&expr); 7250 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
7282 Token::Kind binary_op = 7251 Token::Kind binary_op =
7283 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB; 7252 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
7284 BinaryOpNode* add = new BinaryOpNode( 7253 BinaryOpNode* add = new BinaryOpNode(
7285 op_pos, 7254 op_pos,
7286 binary_op, 7255 binary_op,
7287 expr, 7256 expr,
7288 new LiteralNode(op_pos, Smi::ZoneHandle(Smi::New(1)))); 7257 new LiteralNode(op_pos, Smi::ZoneHandle(Smi::New(1))));
7289 AstNode* store = CreateAssignmentNode(left_expr, add); 7258 AstNode* store = CreateAssignmentNode(expr, add);
7290 ASSERT(store != NULL); 7259 ASSERT(store != NULL);
7291 expr = store; 7260 let_expr->set_body(store);
7261 expr = let_expr;
7292 } else { 7262 } else {
7293 expr = ParsePostfixExpr(); 7263 expr = ParsePostfixExpr();
7294 } 7264 }
7295 return expr; 7265 return expr;
7296 } 7266 }
7297 7267
7298 7268
7299 ArgumentListNode* Parser::ParseActualParameters( 7269 ArgumentListNode* Parser::ParseActualParameters(
7300 ArgumentListNode* implicit_arguments, 7270 ArgumentListNode* implicit_arguments,
7301 bool require_const) { 7271 bool require_const) {
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
7763 AstNode* postfix_expr = ParsePrimary(); 7733 AstNode* postfix_expr = ParsePrimary();
7764 postfix_expr = ParseSelectors(postfix_expr, false); 7734 postfix_expr = ParseSelectors(postfix_expr, false);
7765 if (IsIncrementOperator(CurrentToken())) { 7735 if (IsIncrementOperator(CurrentToken())) {
7766 TRACE_PARSER("IncrementOperator"); 7736 TRACE_PARSER("IncrementOperator");
7767 Token::Kind incr_op = CurrentToken(); 7737 Token::Kind incr_op = CurrentToken();
7768 if (!IsAssignableExpr(postfix_expr)) { 7738 if (!IsAssignableExpr(postfix_expr)) {
7769 ErrorMsg("expression is not assignable"); 7739 ErrorMsg("expression is not assignable");
7770 } 7740 }
7771 ConsumeToken(); 7741 ConsumeToken();
7772 // Not prefix. 7742 // Not prefix.
7773 AstNode* left_expr = PrepareCompoundAssignmentNodes(&postfix_expr); 7743 LetNode* let_expr = PrepareCompoundAssignmentNodes(&postfix_expr);
7774 const LocalVariable* temp = GetIncrementTempLocal(); 7744 LocalVariable* temp = let_expr->AddInitializer(postfix_expr);
7775 AstNode* save =
7776 new StoreLocalNode(postfix_expr_pos, temp, postfix_expr);
7777 Token::Kind binary_op = 7745 Token::Kind binary_op =
7778 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB; 7746 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
7779 BinaryOpNode* add = new BinaryOpNode( 7747 BinaryOpNode* add = new BinaryOpNode(
7780 postfix_expr_pos, 7748 postfix_expr_pos,
7781 binary_op, 7749 binary_op,
7782 save, 7750 new LoadLocalNode(postfix_expr_pos, temp),
7783 new LiteralNode(postfix_expr_pos, Smi::ZoneHandle(Smi::New(1)))); 7751 new LiteralNode(postfix_expr_pos, Smi::ZoneHandle(Smi::New(1))));
7784 AstNode* store = CreateAssignmentNode(left_expr, add); 7752 AstNode* store = CreateAssignmentNode(postfix_expr, add);
7753 ASSERT(store != NULL);
7785 // The result is a pair of the (side effects of the) store followed by 7754 // The result is a pair of the (side effects of the) store followed by
7786 // the (value of the) initial value temp variable load. 7755 // the (value of the) initial value temp variable load.
7787 return new CommaNode( 7756 let_expr->set_body(new CommaNode(
7788 postfix_expr_pos, 7757 postfix_expr_pos,
7789 store, 7758 store,
7790 new LoadLocalNode(postfix_expr_pos, temp)); 7759 new LoadLocalNode(postfix_expr_pos, temp)));
7760 return let_expr;
7791 } 7761 }
7792 return postfix_expr; 7762 return postfix_expr;
7793 } 7763 }
7794 7764
7795 7765
7796 // Resolve the given type and its type arguments from the given scope class 7766 // Resolve the given type and its type arguments from the given scope class
7797 // according to the given type finalization mode. 7767 // according to the given type finalization mode.
7798 // If the given scope class is null, use the current library, but do not try to 7768 // If the given scope class is null, use the current library, but do not try to
7799 // resolve type parameters. 7769 // resolve type parameters.
7800 // Not all involved type classes may get resolved yet, but at least the type 7770 // Not all involved type classes may get resolved yet, but at least the type
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after
8855 } 8825 }
8856 factory_type_args = factory_type_args.Canonicalize(); 8826 factory_type_args = factory_type_args.Canonicalize();
8857 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); 8827 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
8858 if (element_list.length() == 0) { 8828 if (element_list.length() == 0) {
8859 // TODO(srdjan): Use Object::empty_array once issue 9871 has been fixed. 8829 // TODO(srdjan): Use Object::empty_array once issue 9871 has been fixed.
8860 Array& empty_array = Array::ZoneHandle(Object::empty_array().raw()); 8830 Array& empty_array = Array::ZoneHandle(Object::empty_array().raw());
8861 LiteralNode* empty_array_literal = 8831 LiteralNode* empty_array_literal =
8862 new LiteralNode(TokenPos(), empty_array); 8832 new LiteralNode(TokenPos(), empty_array);
8863 factory_param->Add(empty_array_literal); 8833 factory_param->Add(empty_array_literal);
8864 } else { 8834 } else {
8865 const LocalVariable& temp_local = *BuildArrayTempLocal(type_pos); 8835 ArrayNode* list = new ArrayNode(TokenPos(), type, element_list);
8866 ArrayNode* list =
8867 new ArrayNode(TokenPos(), type, temp_local, element_list);
8868 factory_param->Add(list); 8836 factory_param->Add(list);
8869 } 8837 }
8870 return CreateConstructorCallNode(literal_pos, 8838 return CreateConstructorCallNode(literal_pos,
8871 factory_type_args, 8839 factory_type_args,
8872 factory_method, 8840 factory_method,
8873 factory_param); 8841 factory_param);
8874 } 8842 }
8875 } 8843 }
8876 8844
8877 8845
8878 ConstructorCallNode* Parser::CreateConstructorCallNode( 8846 ConstructorCallNode* Parser::CreateConstructorCallNode(
8879 intptr_t token_pos, 8847 intptr_t token_pos,
8880 const AbstractTypeArguments& type_arguments, 8848 const AbstractTypeArguments& type_arguments,
8881 const Function& constructor, 8849 const Function& constructor,
8882 ArgumentListNode* arguments) { 8850 ArgumentListNode* arguments) {
8883 if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) { 8851 if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) {
8884 EnsureExpressionTemp(); 8852 EnsureExpressionTemp();
8885 } 8853 }
8886 LocalVariable* allocated =
8887 CreateTempConstVariable(token_pos, "alloc");
8888 return new ConstructorCallNode(token_pos, 8854 return new ConstructorCallNode(token_pos,
8889 type_arguments, 8855 type_arguments,
8890 constructor, 8856 constructor,
8891 arguments, 8857 arguments);
8892 allocated);
8893 } 8858 }
8894 8859
8895 8860
8896 static void AddKeyValuePair(GrowableArray<AstNode*>* pairs, 8861 static void AddKeyValuePair(GrowableArray<AstNode*>* pairs,
8897 bool is_const, 8862 bool is_const,
8898 AstNode* key, 8863 AstNode* key,
8899 AstNode* value) { 8864 AstNode* value) {
8900 if (is_const) { 8865 if (is_const) {
8901 ASSERT(key->IsLiteralNode()); 8866 ASSERT(key->IsLiteralNode());
8902 ASSERT(key->AsLiteralNode()->literal().IsString()); 8867 ASSERT(key->AsLiteralNode()->literal().IsString());
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
9080 factory_type_args = factory_type.arguments(); 9045 factory_type_args = factory_type.arguments();
9081 ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments()); 9046 ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments());
9082 } 9047 }
9083 factory_type_args = factory_type_args.Canonicalize(); 9048 factory_type_args = factory_type_args.Canonicalize();
9084 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); 9049 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
9085 // The kv_pair array is temporary and of element type dynamic. It is passed 9050 // The kv_pair array is temporary and of element type dynamic. It is passed
9086 // to the factory to initialize a properly typed map. 9051 // to the factory to initialize a properly typed map.
9087 ArrayNode* kv_pairs = new ArrayNode( 9052 ArrayNode* kv_pairs = new ArrayNode(
9088 TokenPos(), 9053 TokenPos(),
9089 Type::ZoneHandle(Type::ArrayType()), 9054 Type::ZoneHandle(Type::ArrayType()),
9090 *BuildArrayTempLocal(type_pos),
9091 kv_pairs_list); 9055 kv_pairs_list);
9092 factory_param->Add(kv_pairs); 9056 factory_param->Add(kv_pairs);
9093 return CreateConstructorCallNode(literal_pos, 9057 return CreateConstructorCallNode(literal_pos,
9094 factory_type_args, 9058 factory_type_args,
9095 factory_method, 9059 factory_method,
9096 factory_param); 9060 factory_param);
9097 } 9061 }
9098 } 9062 }
9099 9063
9100 9064
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
9467 values_list.Add(expr); 9431 values_list.Add(expr);
9468 } 9432 }
9469 } 9433 }
9470 if (is_compiletime_const) { 9434 if (is_compiletime_const) {
9471 primary = new LiteralNode(literal_start, Interpolate(values_list)); 9435 primary = new LiteralNode(literal_start, Interpolate(values_list));
9472 } else { 9436 } else {
9473 ArgumentListNode* interpolate_arg = new ArgumentListNode(TokenPos()); 9437 ArgumentListNode* interpolate_arg = new ArgumentListNode(TokenPos());
9474 ArrayNode* values = new ArrayNode( 9438 ArrayNode* values = new ArrayNode(
9475 TokenPos(), 9439 TokenPos(),
9476 Type::ZoneHandle(Type::ArrayType()), 9440 Type::ZoneHandle(Type::ArrayType()),
9477 *BuildArrayTempLocal(TokenPos()),
9478 values_list); 9441 values_list);
9479 interpolate_arg->Add(values); 9442 interpolate_arg->Add(values);
9480 primary = MakeStaticCall(Symbols::StringBase(), 9443 primary = MakeStaticCall(Symbols::StringBase(),
9481 PrivateCoreLibName(Symbols::Interpolate()), 9444 PrivateCoreLibName(Symbols::Interpolate()),
9482 interpolate_arg); 9445 interpolate_arg);
9483 } 9446 }
9484 return primary; 9447 return primary;
9485 } 9448 }
9486 9449
9487 9450
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
9988 void Parser::SkipQualIdent() { 9951 void Parser::SkipQualIdent() {
9989 ASSERT(IsIdentifier()); 9952 ASSERT(IsIdentifier());
9990 ConsumeToken(); 9953 ConsumeToken();
9991 if (CurrentToken() == Token::kPERIOD) { 9954 if (CurrentToken() == Token::kPERIOD) {
9992 ConsumeToken(); // Consume the kPERIOD token. 9955 ConsumeToken(); // Consume the kPERIOD token.
9993 ExpectIdentifier("identifier expected after '.'"); 9956 ExpectIdentifier("identifier expected after '.'");
9994 } 9957 }
9995 } 9958 }
9996 9959
9997 } // namespace dart 9960 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/scopes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698