OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/parser.h" | 5 #include "vm/parser.h" |
6 | 6 |
7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
8 #include "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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |