| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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/ast_transformer.h" | 5 #include "vm/ast_transformer.h" |
| 6 | 6 |
| 7 #include "vm/object_store.h" | 7 #include "vm/object_store.h" |
| 8 #include "vm/parser.h" | 8 #include "vm/parser.h" |
| 9 #include "vm/thread.h" | 9 #include "vm/thread.h" |
| 10 | 10 |
| 11 namespace dart { | 11 namespace dart { |
| 12 | 12 |
| 13 // Quick access to the current zone. | 13 // Quick access to the current zone. |
| 14 #define Z (thread()->zone()) | 14 #define Z (thread()->zone()) |
| 15 | 15 |
| 16 // Quick synthetic token position. |
| 17 #define ST(token_pos) Token::ToSynthetic(token_pos) |
| 18 |
| 16 // Nodes that are unreachable from already parsed expressions. | 19 // Nodes that are unreachable from already parsed expressions. |
| 17 #define FOR_EACH_UNREACHABLE_NODE(V) \ | 20 #define FOR_EACH_UNREACHABLE_NODE(V) \ |
| 18 V(AwaitMarker) \ | 21 V(AwaitMarker) \ |
| 19 V(Case) \ | 22 V(Case) \ |
| 20 V(CatchClause) \ | 23 V(CatchClause) \ |
| 21 V(CloneContext) \ | 24 V(CloneContext) \ |
| 22 V(ClosureCall) \ | 25 V(ClosureCall) \ |
| 23 V(DoWhile) \ | 26 V(DoWhile) \ |
| 24 V(If) \ | 27 V(If) \ |
| 25 V(InitStaticField) \ | 28 V(InitStaticField) \ |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 LocalVariable* AwaitTransformer::EnsureCurrentTempVar() { | 67 LocalVariable* AwaitTransformer::EnsureCurrentTempVar() { |
| 65 String& symbol = | 68 String& symbol = |
| 66 String::ZoneHandle(Z, Symbols::NewFormatted("%d", temp_cnt_)); | 69 String::ZoneHandle(Z, Symbols::NewFormatted("%d", temp_cnt_)); |
| 67 symbol = Symbols::FromConcat(Symbols::AwaitTempVarPrefix(), symbol); | 70 symbol = Symbols::FromConcat(Symbols::AwaitTempVarPrefix(), symbol); |
| 68 ASSERT(!symbol.IsNull()); | 71 ASSERT(!symbol.IsNull()); |
| 69 // Look up the variable in the scope used for async temp variables. | 72 // Look up the variable in the scope used for async temp variables. |
| 70 LocalVariable* await_tmp = async_temp_scope_->LocalLookupVariable(symbol); | 73 LocalVariable* await_tmp = async_temp_scope_->LocalLookupVariable(symbol); |
| 71 if (await_tmp == NULL) { | 74 if (await_tmp == NULL) { |
| 72 // We need a new temp variable; add it to the function's top scope. | 75 // We need a new temp variable; add it to the function's top scope. |
| 73 await_tmp = new (Z) LocalVariable( | 76 await_tmp = new (Z) LocalVariable( |
| 74 Scanner::kNoSourcePos, symbol, Object::dynamic_type()); | 77 Token::kNoSourcePos, symbol, Object::dynamic_type()); |
| 75 async_temp_scope_->AddVariable(await_tmp); | 78 async_temp_scope_->AddVariable(await_tmp); |
| 76 // After adding it to the top scope, we can look it up from the preamble. | 79 // After adding it to the top scope, we can look it up from the preamble. |
| 77 // The following call includes an ASSERT check. | 80 // The following call includes an ASSERT check. |
| 78 await_tmp = GetVariableInScope(preamble_->scope(), symbol); | 81 await_tmp = GetVariableInScope(preamble_->scope(), symbol); |
| 79 } | 82 } |
| 80 return await_tmp; | 83 return await_tmp; |
| 81 } | 84 } |
| 82 | 85 |
| 83 | 86 |
| 84 LocalVariable* AwaitTransformer::GetVariableInScope(LocalScope* scope, | 87 LocalVariable* AwaitTransformer::GetVariableInScope(LocalScope* scope, |
| 85 const String& symbol) { | 88 const String& symbol) { |
| 86 LocalVariable* var = scope->LookupVariable(symbol, false); | 89 LocalVariable* var = scope->LookupVariable(symbol, false); |
| 87 ASSERT(var != NULL); | 90 ASSERT(var != NULL); |
| 88 return var; | 91 return var; |
| 89 } | 92 } |
| 90 | 93 |
| 91 | 94 |
| 92 LocalVariable* AwaitTransformer::AddToPreambleNewTempVar(AstNode* node) { | 95 LocalVariable* AwaitTransformer::AddToPreambleNewTempVar(AstNode* node, |
| 96 intptr_t token_pos) { |
| 93 LocalVariable* tmp_var = EnsureCurrentTempVar(); | 97 LocalVariable* tmp_var = EnsureCurrentTempVar(); |
| 94 preamble_->Add(new(Z) StoreLocalNode(Scanner::kNoSourcePos, tmp_var, node)); | 98 ASSERT(Token::IsSynthetic(token_pos) || Token::IsNoSource(token_pos)); |
| 99 preamble_->Add(new(Z) StoreLocalNode(token_pos, tmp_var, node)); |
| 95 NextTempVar(); | 100 NextTempVar(); |
| 96 return tmp_var; | 101 return tmp_var; |
| 97 } | 102 } |
| 98 | 103 |
| 99 | 104 |
| 100 void AwaitTransformer::VisitLiteralNode(LiteralNode* node) { | 105 void AwaitTransformer::VisitLiteralNode(LiteralNode* node) { |
| 101 result_ = node; | 106 result_ = node; |
| 102 } | 107 } |
| 103 | 108 |
| 104 | 109 |
| 105 void AwaitTransformer::VisitTypeNode(TypeNode* node) { | 110 void AwaitTransformer::VisitTypeNode(TypeNode* node) { |
| 106 result_ = new(Z) TypeNode(node->token_pos(), node->type()); | 111 result_ = new(Z) TypeNode(node->token_pos(), node->type()); |
| 107 } | 112 } |
| 108 | 113 |
| 109 | 114 |
| 110 void AwaitTransformer::VisitAwaitNode(AwaitNode* node) { | 115 void AwaitTransformer::VisitAwaitNode(AwaitNode* node) { |
| 111 // Await transformation: | 116 // Await transformation: |
| 112 // | 117 // |
| 113 // :await_temp_var_X = <expr>; | 118 // :await_temp_var_X = <expr>; |
| 114 // AwaitMarker(kNewContinuationState); | 119 // AwaitMarker(kNewContinuationState); |
| 115 // :result_param = _awaitHelper( | 120 // :result_param = _awaitHelper( |
| 116 // :await_temp_var_X, :async_then_callback, :async_catch_error_callback); | 121 // :await_temp_var_X, :async_then_callback, :async_catch_error_callback); |
| 117 // return; // (return_type() == kContinuationTarget) | 122 // return; // (return_type() == kContinuationTarget) |
| 118 // | 123 // |
| 119 // :saved_try_ctx_var = :await_saved_try_ctx_var_y; | 124 // :saved_try_ctx_var = :await_saved_try_ctx_var_y; |
| 120 // :await_temp_var_(X+1) = :result_param; | 125 // :await_temp_var_(X+1) = :result_param; |
| 121 | 126 |
| 122 const intptr_t token_pos = node->token_pos(); | 127 const intptr_t token_pos = ST(node->token_pos()); |
| 123 LocalVariable* async_op = GetVariableInScope( | 128 LocalVariable* async_op = GetVariableInScope( |
| 124 preamble_->scope(), Symbols::AsyncOperation()); | 129 preamble_->scope(), Symbols::AsyncOperation()); |
| 125 LocalVariable* async_then_callback = GetVariableInScope( | 130 LocalVariable* async_then_callback = GetVariableInScope( |
| 126 preamble_->scope(), Symbols::AsyncThenCallback()); | 131 preamble_->scope(), Symbols::AsyncThenCallback()); |
| 127 LocalVariable* async_catch_error_callback = GetVariableInScope( | 132 LocalVariable* async_catch_error_callback = GetVariableInScope( |
| 128 preamble_->scope(), Symbols::AsyncCatchErrorCallback()); | 133 preamble_->scope(), Symbols::AsyncCatchErrorCallback()); |
| 129 LocalVariable* result_param = GetVariableInScope( | 134 LocalVariable* result_param = GetVariableInScope( |
| 130 preamble_->scope(), Symbols::AsyncOperationParam()); | 135 preamble_->scope(), Symbols::AsyncOperationParam()); |
| 131 LocalVariable* error_param = GetVariableInScope( | 136 LocalVariable* error_param = GetVariableInScope( |
| 132 preamble_->scope(), Symbols::AsyncOperationErrorParam()); | 137 preamble_->scope(), Symbols::AsyncOperationErrorParam()); |
| 133 LocalVariable* stack_trace_param = GetVariableInScope( | 138 LocalVariable* stack_trace_param = GetVariableInScope( |
| 134 preamble_->scope(), Symbols::AsyncOperationStackTraceParam()); | 139 preamble_->scope(), Symbols::AsyncOperationStackTraceParam()); |
| 135 | 140 |
| 136 AstNode* transformed_expr = Transform(node->expr()); | 141 AstNode* transformed_expr = Transform(node->expr()); |
| 137 LocalVariable* await_temp = AddToPreambleNewTempVar(transformed_expr); | 142 LocalVariable* await_temp = AddToPreambleNewTempVar(transformed_expr, |
| 143 ST(node->token_pos())); |
| 138 | 144 |
| 139 AwaitMarkerNode* await_marker = | 145 AwaitMarkerNode* await_marker = |
| 140 new (Z) AwaitMarkerNode(async_temp_scope_, node->scope(), token_pos); | 146 new (Z) AwaitMarkerNode(async_temp_scope_, node->scope(), token_pos); |
| 141 preamble_->Add(await_marker); | 147 preamble_->Add(await_marker); |
| 142 | 148 |
| 143 // :result_param = _awaitHelper( | 149 // :result_param = _awaitHelper( |
| 144 // :await_temp, :async_then_callback, :async_catch_error_callback) | 150 // :await_temp, :async_then_callback, :async_catch_error_callback) |
| 145 const Library& async_lib = Library::Handle(Library::AsyncLibrary()); | 151 const Library& async_lib = Library::Handle(Library::AsyncLibrary()); |
| 146 const Function& async_await_helper = Function::ZoneHandle( | 152 const Function& async_await_helper = Function::ZoneHandle( |
| 147 Z, async_lib.LookupFunctionAllowPrivate(Symbols::AsyncAwaitHelper())); | 153 Z, async_lib.LookupFunctionAllowPrivate(Symbols::AsyncAwaitHelper())); |
| 148 ASSERT(!async_await_helper.IsNull()); | 154 ASSERT(!async_await_helper.IsNull()); |
| 149 ArgumentListNode* async_await_helper_args = new (Z) ArgumentListNode( | 155 ArgumentListNode* async_await_helper_args = |
| 150 Scanner::kNoSourcePos); | 156 new (Z) ArgumentListNode(token_pos); |
| 151 async_await_helper_args->Add( | 157 async_await_helper_args->Add( |
| 152 new(Z) LoadLocalNode(Scanner::kNoSourcePos, await_temp)); | 158 new(Z) LoadLocalNode(token_pos, await_temp)); |
| 153 async_await_helper_args->Add( | 159 async_await_helper_args->Add( |
| 154 new(Z) LoadLocalNode(Scanner::kNoSourcePos, async_then_callback)); | 160 new(Z) LoadLocalNode(token_pos, async_then_callback)); |
| 155 async_await_helper_args->Add( | 161 async_await_helper_args->Add( |
| 156 new(Z) LoadLocalNode(Scanner::kNoSourcePos, async_catch_error_callback)); | 162 new(Z) LoadLocalNode(token_pos, async_catch_error_callback)); |
| 157 StaticCallNode* await_helper_call = new (Z) StaticCallNode( | 163 StaticCallNode* await_helper_call = new (Z) StaticCallNode( |
| 158 node->token_pos(), | 164 node->token_pos(), |
| 159 async_await_helper, | 165 async_await_helper, |
| 160 async_await_helper_args); | 166 async_await_helper_args); |
| 161 | 167 |
| 162 preamble_->Add(new(Z) StoreLocalNode( | 168 preamble_->Add(new(Z) StoreLocalNode( |
| 163 Scanner::kNoSourcePos, result_param, await_helper_call)); | 169 token_pos, result_param, await_helper_call)); |
| 164 | 170 |
| 165 ReturnNode* continuation_return = new(Z) ReturnNode(Scanner::kNoSourcePos); | 171 ReturnNode* continuation_return = new(Z) ReturnNode(token_pos); |
| 166 continuation_return->set_return_type(ReturnNode::kContinuationTarget); | 172 continuation_return->set_return_type(ReturnNode::kContinuationTarget); |
| 167 preamble_->Add(continuation_return); | 173 preamble_->Add(continuation_return); |
| 168 | 174 |
| 169 // If this expression is part of a try block, also append the code for | 175 // If this expression is part of a try block, also append the code for |
| 170 // restoring the saved try context that lives on the stack and possibly the | 176 // restoring the saved try context that lives on the stack and possibly the |
| 171 // saved try context of the outer try block. | 177 // saved try context of the outer try block. |
| 172 if (node->saved_try_ctx() != NULL) { | 178 if (node->saved_try_ctx() != NULL) { |
| 173 preamble_->Add(new (Z) StoreLocalNode( | 179 preamble_->Add(new (Z) StoreLocalNode( |
| 174 Scanner::kNoSourcePos, | 180 token_pos, |
| 175 node->saved_try_ctx(), | 181 node->saved_try_ctx(), |
| 176 new (Z) LoadLocalNode(Scanner::kNoSourcePos, | 182 new (Z) LoadLocalNode(token_pos, |
| 177 node->async_saved_try_ctx()))); | 183 node->async_saved_try_ctx()))); |
| 178 if (node->outer_saved_try_ctx() != NULL) { | 184 if (node->outer_saved_try_ctx() != NULL) { |
| 179 preamble_->Add(new (Z) StoreLocalNode( | 185 preamble_->Add(new (Z) StoreLocalNode( |
| 180 Scanner::kNoSourcePos, | 186 token_pos, |
| 181 node->outer_saved_try_ctx(), | 187 node->outer_saved_try_ctx(), |
| 182 new (Z) LoadLocalNode(Scanner::kNoSourcePos, | 188 new (Z) LoadLocalNode(token_pos, |
| 183 node->outer_async_saved_try_ctx()))); | 189 node->outer_async_saved_try_ctx()))); |
| 184 } | 190 } |
| 185 } else { | 191 } else { |
| 186 ASSERT(node->outer_saved_try_ctx() == NULL); | 192 ASSERT(node->outer_saved_try_ctx() == NULL); |
| 187 } | 193 } |
| 188 | 194 |
| 189 // Load the async_op variable. It is unused, but the observatory uses it | 195 // Load the async_op variable. It is unused, but the observatory uses it |
| 190 // to determine if a breakpoint is inside an asynchronous function. | 196 // to determine if a breakpoint is inside an asynchronous function. |
| 191 LoadLocalNode* load_async_op = new (Z) LoadLocalNode( | 197 LoadLocalNode* load_async_op = new (Z) LoadLocalNode(token_pos, async_op); |
| 192 Scanner::kNoSourcePos, async_op); | |
| 193 preamble_->Add(load_async_op); | 198 preamble_->Add(load_async_op); |
| 194 | 199 |
| 195 LoadLocalNode* load_error_param = new (Z) LoadLocalNode( | 200 LoadLocalNode* load_error_param = new (Z) LoadLocalNode( |
| 196 Scanner::kNoSourcePos, error_param); | 201 token_pos, error_param); |
| 197 LoadLocalNode* load_stack_trace_param = new (Z) LoadLocalNode( | 202 LoadLocalNode* load_stack_trace_param = new (Z) LoadLocalNode( |
| 198 Scanner::kNoSourcePos, stack_trace_param); | 203 token_pos, stack_trace_param); |
| 199 SequenceNode* error_ne_null_branch = new (Z) SequenceNode( | 204 SequenceNode* error_ne_null_branch = new (Z) SequenceNode( |
| 200 Scanner::kNoSourcePos, ChainNewScope(preamble_->scope())); | 205 token_pos, ChainNewScope(preamble_->scope())); |
| 201 error_ne_null_branch->Add(new (Z) ThrowNode( | 206 error_ne_null_branch->Add(new (Z) ThrowNode( |
| 202 Scanner::kNoSourcePos, | 207 token_pos, |
| 203 load_error_param, | 208 load_error_param, |
| 204 load_stack_trace_param)); | 209 load_stack_trace_param)); |
| 205 preamble_->Add(new (Z) IfNode( | 210 preamble_->Add(new (Z) IfNode( |
| 206 Scanner::kNoSourcePos, | 211 token_pos, |
| 207 new (Z) ComparisonNode( | 212 new (Z) ComparisonNode( |
| 208 Scanner::kNoSourcePos, | 213 token_pos, |
| 209 Token::kNE, | 214 Token::kNE, |
| 210 load_error_param, | 215 load_error_param, |
| 211 new (Z) LiteralNode(Scanner::kNoSourcePos, | 216 new (Z) LiteralNode(token_pos, |
| 212 Object::null_instance())), | 217 Object::null_instance())), |
| 213 error_ne_null_branch, | 218 error_ne_null_branch, |
| 214 NULL)); | 219 NULL)); |
| 215 | 220 |
| 216 LocalVariable* result = AddToPreambleNewTempVar(new(Z) LoadLocalNode( | 221 LocalVariable* result = AddToPreambleNewTempVar(new(Z) LoadLocalNode( |
| 217 Scanner::kNoSourcePos, result_param)); | 222 token_pos, result_param), ST(node->token_pos())); |
| 218 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 223 result_ = new(Z) LoadLocalNode(token_pos, result); |
| 219 } | 224 } |
| 220 | 225 |
| 221 | 226 |
| 222 // Transforms boolean expressions into a sequence of evaluatons that only lazily | 227 // Transforms boolean expressions into a sequence of evaluatons that only lazily |
| 223 // evaluate subexpressions. | 228 // evaluate subexpressions. |
| 224 // | 229 // |
| 225 // Example: | 230 // Example: |
| 226 // | 231 // |
| 227 // (a || b) only evaluates b if a is false | 232 // (a || b) only evaluates b if a is false |
| 228 // | 233 // |
| 229 // Transformation (roughly): | 234 // Transformation (roughly): |
| 230 // | 235 // |
| 231 // t_1 = a; | 236 // t_1 = a; |
| 232 // if (!t_1) { | 237 // if (!t_1) { |
| 233 // t_2 = b; | 238 // t_2 = b; |
| 234 // } | 239 // } |
| 235 // t_3 = t_1 || t_2; // Compiler takes care that lazy evaluation takes place | 240 // t_3 = t_1 || t_2; // Compiler takes care that lazy evaluation takes place |
| 236 // on this level. | 241 // on this level. |
| 237 AstNode* AwaitTransformer::LazyTransform(const Token::Kind logical_op, | 242 AstNode* AwaitTransformer::LazyTransform(const Token::Kind logical_op, |
| 238 AstNode* new_left, | 243 AstNode* new_left, |
| 239 AstNode* right) { | 244 AstNode* right) { |
| 240 ASSERT(logical_op == Token::kAND || logical_op == Token::kOR); | 245 ASSERT(logical_op == Token::kAND || logical_op == Token::kOR); |
| 241 AstNode* result = NULL; | 246 AstNode* result = NULL; |
| 242 const Token::Kind compare_logical_op = (logical_op == Token::kAND) ? | 247 const Token::Kind compare_logical_op = (logical_op == Token::kAND) ? |
| 243 Token::kEQ : Token::kNE; | 248 Token::kEQ : Token::kNE; |
| 244 SequenceNode* eval = new (Z) SequenceNode( | 249 SequenceNode* eval = new (Z) SequenceNode( |
| 245 Scanner::kNoSourcePos, ChainNewScope(preamble_->scope())); | 250 ST(new_left->token_pos()), ChainNewScope(preamble_->scope())); |
| 246 SequenceNode* saved_preamble = preamble_; | 251 SequenceNode* saved_preamble = preamble_; |
| 247 preamble_ = eval; | 252 preamble_ = eval; |
| 248 result = Transform(right); | 253 result = Transform(right); |
| 249 preamble_ = saved_preamble; | 254 preamble_ = saved_preamble; |
| 250 IfNode* right_body = new(Z) IfNode( | 255 IfNode* right_body = new(Z) IfNode( |
| 251 Scanner::kNoSourcePos, | 256 ST(new_left->token_pos()), |
| 252 new(Z) ComparisonNode( | 257 new(Z) ComparisonNode( |
| 253 Scanner::kNoSourcePos, | 258 ST(new_left->token_pos()), |
| 254 compare_logical_op, | 259 compare_logical_op, |
| 255 new_left, | 260 new_left, |
| 256 new(Z) LiteralNode(Scanner::kNoSourcePos, Bool::True())), | 261 new(Z) LiteralNode(ST(new_left->token_pos()), Bool::True())), |
| 257 eval, | 262 eval, |
| 258 NULL); | 263 NULL); |
| 259 preamble_->Add(right_body); | 264 preamble_->Add(right_body); |
| 260 return result; | 265 return result; |
| 261 } | 266 } |
| 262 | 267 |
| 263 | 268 |
| 264 LocalScope* AwaitTransformer::ChainNewScope(LocalScope* parent) { | 269 LocalScope* AwaitTransformer::ChainNewScope(LocalScope* parent) { |
| 265 return new (Z) LocalScope( | 270 return new (Z) LocalScope( |
| 266 parent, parent->function_level(), parent->loop_level()); | 271 parent, parent->function_level(), parent->loop_level()); |
| 267 } | 272 } |
| 268 | 273 |
| 269 | 274 |
| 270 void AwaitTransformer::VisitBinaryOpNode(BinaryOpNode* node) { | 275 void AwaitTransformer::VisitBinaryOpNode(BinaryOpNode* node) { |
| 271 AstNode* new_left = Transform(node->left()); | 276 AstNode* new_left = Transform(node->left()); |
| 272 AstNode* new_right = NULL; | 277 AstNode* new_right = NULL; |
| 273 // Preserve lazy evaluaton. | 278 // Preserve lazy evaluaton. |
| 274 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 279 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
| 275 new_right = LazyTransform(node->kind(), new_left, node->right()); | 280 new_right = LazyTransform(node->kind(), new_left, node->right()); |
| 276 } else { | 281 } else { |
| 277 new_right = Transform(node->right()); | 282 new_right = Transform(node->right()); |
| 278 } | 283 } |
| 279 LocalVariable* result = AddToPreambleNewTempVar( | 284 LocalVariable* result = AddToPreambleNewTempVar( |
| 280 new(Z) BinaryOpNode(node->token_pos(), | 285 new(Z) BinaryOpNode(node->token_pos(), |
| 281 node->kind(), | 286 node->kind(), |
| 282 new_left, | 287 new_left, |
| 283 new_right)); | 288 new_right), ST(node->token_pos())); |
| 284 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 289 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 285 } | 290 } |
| 286 | 291 |
| 287 | 292 |
| 288 void AwaitTransformer::VisitBinaryOpWithMask32Node( | 293 void AwaitTransformer::VisitBinaryOpWithMask32Node( |
| 289 BinaryOpWithMask32Node* node) { | 294 BinaryOpWithMask32Node* node) { |
| 290 ASSERT((node->kind() != Token::kAND) && (node->kind() != Token::kOR)); | 295 ASSERT((node->kind() != Token::kAND) && (node->kind() != Token::kOR)); |
| 291 AstNode* new_left = Transform(node->left()); | 296 AstNode* new_left = Transform(node->left()); |
| 292 AstNode* new_right = Transform(node->right()); | 297 AstNode* new_right = Transform(node->right()); |
| 293 LocalVariable* result = AddToPreambleNewTempVar( | 298 LocalVariable* result = AddToPreambleNewTempVar( |
| 294 new(Z) BinaryOpWithMask32Node(node->token_pos(), | 299 new(Z) BinaryOpWithMask32Node(node->token_pos(), |
| 295 node->kind(), | 300 node->kind(), |
| 296 new_left, | 301 new_left, |
| 297 new_right, | 302 new_right, |
| 298 node->mask32())); | 303 node->mask32()), ST(node->token_pos())); |
| 299 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 304 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 300 } | 305 } |
| 301 | 306 |
| 302 | 307 |
| 303 void AwaitTransformer::VisitComparisonNode(ComparisonNode* node) { | 308 void AwaitTransformer::VisitComparisonNode(ComparisonNode* node) { |
| 304 AstNode* new_left = Transform(node->left()); | 309 AstNode* new_left = Transform(node->left()); |
| 305 AstNode* new_right = Transform(node->right()); | 310 AstNode* new_right = Transform(node->right()); |
| 306 LocalVariable* result = AddToPreambleNewTempVar( | 311 LocalVariable* result = AddToPreambleNewTempVar( |
| 307 new(Z) ComparisonNode(node->token_pos(), | 312 new(Z) ComparisonNode(node->token_pos(), |
| 308 node->kind(), | 313 node->kind(), |
| 309 new_left, | 314 new_left, |
| 310 new_right)); | 315 new_right), ST(node->token_pos())); |
| 311 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 316 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 312 } | 317 } |
| 313 | 318 |
| 314 | 319 |
| 315 void AwaitTransformer::VisitUnaryOpNode(UnaryOpNode* node) { | 320 void AwaitTransformer::VisitUnaryOpNode(UnaryOpNode* node) { |
| 316 AstNode* new_operand = Transform(node->operand()); | 321 AstNode* new_operand = Transform(node->operand()); |
| 317 LocalVariable* result = AddToPreambleNewTempVar( | 322 LocalVariable* result = AddToPreambleNewTempVar( |
| 318 new(Z) UnaryOpNode(node->token_pos(), node->kind(), new_operand)); | 323 new(Z) UnaryOpNode(node->token_pos(), node->kind(), new_operand), |
| 319 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 324 ST(node->token_pos())); |
| 325 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 320 } | 326 } |
| 321 | 327 |
| 322 | 328 |
| 323 // ::= (<condition>) ? <true-branch> : <false-branch> | 329 // ::= (<condition>) ? <true-branch> : <false-branch> |
| 324 // | 330 // |
| 325 void AwaitTransformer::VisitConditionalExprNode(ConditionalExprNode* node) { | 331 void AwaitTransformer::VisitConditionalExprNode(ConditionalExprNode* node) { |
| 326 AstNode* new_condition = Transform(node->condition()); | 332 AstNode* new_condition = Transform(node->condition()); |
| 327 SequenceNode* new_true = new (Z) SequenceNode( | 333 SequenceNode* new_true = new (Z) SequenceNode( |
| 328 Scanner::kNoSourcePos, ChainNewScope(preamble_->scope())); | 334 ST(node->true_expr()->token_pos()), ChainNewScope(preamble_->scope())); |
| 329 SequenceNode* saved_preamble = preamble_; | 335 SequenceNode* saved_preamble = preamble_; |
| 330 preamble_ = new_true; | 336 preamble_ = new_true; |
| 331 AstNode* new_true_result = Transform(node->true_expr()); | 337 AstNode* new_true_result = Transform(node->true_expr()); |
| 332 SequenceNode* new_false = new (Z) SequenceNode( | 338 SequenceNode* new_false = new (Z) SequenceNode( |
| 333 Scanner::kNoSourcePos, ChainNewScope(preamble_->scope())); | 339 ST(node->false_expr()->token_pos()), ChainNewScope(preamble_->scope())); |
| 334 preamble_ = new_false; | 340 preamble_ = new_false; |
| 335 AstNode* new_false_result = Transform(node->false_expr()); | 341 AstNode* new_false_result = Transform(node->false_expr()); |
| 336 preamble_ = saved_preamble; | 342 preamble_ = saved_preamble; |
| 337 IfNode* new_if = new(Z) IfNode(Scanner::kNoSourcePos, | 343 IfNode* new_if = new(Z) IfNode(ST(node->token_pos()), |
| 338 new_condition, | 344 new_condition, |
| 339 new_true, | 345 new_true, |
| 340 new_false); | 346 new_false); |
| 341 preamble_->Add(new_if); | 347 preamble_->Add(new_if); |
| 342 LocalVariable* result = AddToPreambleNewTempVar( | 348 LocalVariable* result = AddToPreambleNewTempVar( |
| 343 new(Z) ConditionalExprNode(Scanner::kNoSourcePos, | 349 new(Z) ConditionalExprNode(ST(node->token_pos()), |
| 344 new_condition, | 350 new_condition, |
| 345 new_true_result, | 351 new_true_result, |
| 346 new_false_result)); | 352 new_false_result), ST(node->token_pos())); |
| 347 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 353 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 348 } | 354 } |
| 349 | 355 |
| 350 | 356 |
| 351 void AwaitTransformer::VisitArgumentListNode(ArgumentListNode* node) { | 357 void AwaitTransformer::VisitArgumentListNode(ArgumentListNode* node) { |
| 352 ArgumentListNode* new_args = new(Z) ArgumentListNode(node->token_pos()); | 358 ArgumentListNode* new_args = new(Z) ArgumentListNode(node->token_pos()); |
| 353 for (intptr_t i = 0; i < node->length(); i++) { | 359 for (intptr_t i = 0; i < node->length(); i++) { |
| 354 new_args->Add(Transform(node->NodeAt(i))); | 360 new_args->Add(Transform(node->NodeAt(i))); |
| 355 } | 361 } |
| 356 new_args->set_names(node->names()); | 362 new_args->set_names(node->names()); |
| 357 result_ = new_args; | 363 result_ = new_args; |
| 358 } | 364 } |
| 359 | 365 |
| 360 | 366 |
| 361 void AwaitTransformer::VisitArrayNode(ArrayNode* node) { | 367 void AwaitTransformer::VisitArrayNode(ArrayNode* node) { |
| 362 GrowableArray<AstNode*> new_elements; | 368 GrowableArray<AstNode*> new_elements; |
| 363 for (intptr_t i = 0; i < node->length(); i++) { | 369 for (intptr_t i = 0; i < node->length(); i++) { |
| 364 new_elements.Add(Transform(node->ElementAt(i))); | 370 new_elements.Add(Transform(node->ElementAt(i))); |
| 365 } | 371 } |
| 366 result_ = new(Z) ArrayNode(node->token_pos(), node->type(), new_elements); | 372 result_ = new(Z) ArrayNode(node->token_pos(), node->type(), new_elements); |
| 367 } | 373 } |
| 368 | 374 |
| 369 | 375 |
| 370 void AwaitTransformer::VisitStringInterpolateNode(StringInterpolateNode* node) { | 376 void AwaitTransformer::VisitStringInterpolateNode(StringInterpolateNode* node) { |
| 371 ArrayNode* new_value = Transform(node->value())->AsArrayNode(); | 377 ArrayNode* new_value = Transform(node->value())->AsArrayNode(); |
| 372 LocalVariable* result = AddToPreambleNewTempVar( | 378 LocalVariable* result = AddToPreambleNewTempVar( |
| 373 new(Z) StringInterpolateNode(node->token_pos(), | 379 new(Z) StringInterpolateNode(node->token_pos(), |
| 374 new_value)); | 380 new_value), ST(node->token_pos())); |
| 375 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 381 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 376 } | 382 } |
| 377 | 383 |
| 378 | 384 |
| 379 void AwaitTransformer::VisitClosureNode(ClosureNode* node) { | 385 void AwaitTransformer::VisitClosureNode(ClosureNode* node) { |
| 380 AstNode* new_receiver = node->receiver(); | 386 AstNode* new_receiver = node->receiver(); |
| 381 if (new_receiver != NULL) { | 387 if (new_receiver != NULL) { |
| 382 new_receiver = Transform(new_receiver); | 388 new_receiver = Transform(new_receiver); |
| 383 } | 389 } |
| 384 LocalVariable* result = AddToPreambleNewTempVar( | 390 LocalVariable* result = AddToPreambleNewTempVar( |
| 385 new(Z) ClosureNode(node->token_pos(), | 391 new(Z) ClosureNode(node->token_pos(), |
| 386 node->function(), | 392 node->function(), |
| 387 new_receiver, | 393 new_receiver, |
| 388 node->scope())); | 394 node->scope()), ST(node->token_pos())); |
| 389 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 395 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 390 } | 396 } |
| 391 | 397 |
| 392 | 398 |
| 393 void AwaitTransformer::VisitInstanceCallNode(InstanceCallNode* node) { | 399 void AwaitTransformer::VisitInstanceCallNode(InstanceCallNode* node) { |
| 394 AstNode* new_receiver = Transform(node->receiver()); | 400 AstNode* new_receiver = Transform(node->receiver()); |
| 395 ArgumentListNode* new_args = | 401 ArgumentListNode* new_args = |
| 396 Transform(node->arguments())->AsArgumentListNode(); | 402 Transform(node->arguments())->AsArgumentListNode(); |
| 397 LocalVariable* result = AddToPreambleNewTempVar( | 403 LocalVariable* result = AddToPreambleNewTempVar( |
| 398 new(Z) InstanceCallNode(node->token_pos(), | 404 new(Z) InstanceCallNode(node->token_pos(), |
| 399 new_receiver, | 405 new_receiver, |
| 400 node->function_name(), | 406 node->function_name(), |
| 401 new_args, | 407 new_args, |
| 402 node->is_conditional())); | 408 node->is_conditional()), ST(node->token_pos())); |
| 403 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 409 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 404 } | 410 } |
| 405 | 411 |
| 406 | 412 |
| 407 void AwaitTransformer::VisitStaticCallNode(StaticCallNode* node) { | 413 void AwaitTransformer::VisitStaticCallNode(StaticCallNode* node) { |
| 408 ArgumentListNode* new_args = | 414 ArgumentListNode* new_args = |
| 409 Transform(node->arguments())->AsArgumentListNode(); | 415 Transform(node->arguments())->AsArgumentListNode(); |
| 410 LocalVariable* result = AddToPreambleNewTempVar( | 416 LocalVariable* result = AddToPreambleNewTempVar( |
| 411 new(Z) StaticCallNode(node->token_pos(), | 417 new(Z) StaticCallNode(node->token_pos(), |
| 412 node->function(), | 418 node->function(), |
| 413 new_args)); | 419 new_args), ST(node->token_pos())); |
| 414 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 420 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 415 } | 421 } |
| 416 | 422 |
| 417 | 423 |
| 418 void AwaitTransformer::VisitConstructorCallNode(ConstructorCallNode* node) { | 424 void AwaitTransformer::VisitConstructorCallNode(ConstructorCallNode* node) { |
| 419 ArgumentListNode* new_args = | 425 ArgumentListNode* new_args = |
| 420 Transform(node->arguments())->AsArgumentListNode(); | 426 Transform(node->arguments())->AsArgumentListNode(); |
| 421 LocalVariable* result = AddToPreambleNewTempVar( | 427 LocalVariable* result = AddToPreambleNewTempVar( |
| 422 new(Z) ConstructorCallNode(node->token_pos(), | 428 new(Z) ConstructorCallNode(node->token_pos(), |
| 423 node->type_arguments(), | 429 node->type_arguments(), |
| 424 node->constructor(), | 430 node->constructor(), |
| 425 new_args)); | 431 new_args), ST(node->token_pos())); |
| 426 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 432 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 427 } | 433 } |
| 428 | 434 |
| 429 | 435 |
| 430 void AwaitTransformer::VisitInstanceGetterNode(InstanceGetterNode* node) { | 436 void AwaitTransformer::VisitInstanceGetterNode(InstanceGetterNode* node) { |
| 431 AstNode* new_receiver = Transform(node->receiver()); | 437 AstNode* new_receiver = Transform(node->receiver()); |
| 432 LocalVariable* result = AddToPreambleNewTempVar( | 438 LocalVariable* result = AddToPreambleNewTempVar( |
| 433 new(Z) InstanceGetterNode(node->token_pos(), | 439 new(Z) InstanceGetterNode(node->token_pos(), |
| 434 new_receiver, | 440 new_receiver, |
| 435 node->field_name(), | 441 node->field_name(), |
| 436 node->is_conditional())); | 442 node->is_conditional()), ST(node->token_pos())); |
| 437 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 443 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 438 } | 444 } |
| 439 | 445 |
| 440 | 446 |
| 441 void AwaitTransformer::VisitInstanceSetterNode(InstanceSetterNode* node) { | 447 void AwaitTransformer::VisitInstanceSetterNode(InstanceSetterNode* node) { |
| 442 AstNode* new_receiver = node->receiver(); | 448 AstNode* new_receiver = node->receiver(); |
| 443 if (new_receiver != NULL) { | 449 if (new_receiver != NULL) { |
| 444 new_receiver = Transform(new_receiver); | 450 new_receiver = Transform(new_receiver); |
| 445 } | 451 } |
| 446 AstNode* new_value = Transform(node->value()); | 452 AstNode* new_value = Transform(node->value()); |
| 447 LocalVariable* result = AddToPreambleNewTempVar( | 453 LocalVariable* result = AddToPreambleNewTempVar( |
| 448 new(Z) InstanceSetterNode(node->token_pos(), | 454 new(Z) InstanceSetterNode(node->token_pos(), |
| 449 new_receiver, | 455 new_receiver, |
| 450 node->field_name(), | 456 node->field_name(), |
| 451 new_value, | 457 new_value, |
| 452 node->is_conditional())); | 458 node->is_conditional()), ST(node->token_pos())); |
| 453 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 459 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 454 } | 460 } |
| 455 | 461 |
| 456 | 462 |
| 457 void AwaitTransformer::VisitStaticGetterNode(StaticGetterNode* node) { | 463 void AwaitTransformer::VisitStaticGetterNode(StaticGetterNode* node) { |
| 458 AstNode* new_receiver = node->receiver(); | 464 AstNode* new_receiver = node->receiver(); |
| 459 if (new_receiver != NULL) { | 465 if (new_receiver != NULL) { |
| 460 new_receiver = Transform(new_receiver); | 466 new_receiver = Transform(new_receiver); |
| 461 } | 467 } |
| 462 StaticGetterNode* new_getter = | 468 StaticGetterNode* new_getter = |
| 463 new(Z) StaticGetterNode(node->token_pos(), | 469 new(Z) StaticGetterNode(node->token_pos(), |
| 464 new_receiver, | 470 new_receiver, |
| 465 node->cls(), | 471 node->cls(), |
| 466 node->field_name()); | 472 node->field_name()); |
| 467 new_getter->set_owner(node->owner()); | 473 new_getter->set_owner(node->owner()); |
| 468 LocalVariable* result = AddToPreambleNewTempVar(new_getter); | 474 LocalVariable* result = |
| 469 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 475 AddToPreambleNewTempVar(new_getter, ST(node->token_pos())); |
| 476 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 470 } | 477 } |
| 471 | 478 |
| 472 | 479 |
| 473 void AwaitTransformer::VisitStaticSetterNode(StaticSetterNode* node) { | 480 void AwaitTransformer::VisitStaticSetterNode(StaticSetterNode* node) { |
| 474 AstNode* new_receiver = node->receiver(); | 481 AstNode* new_receiver = node->receiver(); |
| 475 if (new_receiver != NULL) { | 482 if (new_receiver != NULL) { |
| 476 new_receiver = Transform(new_receiver); | 483 new_receiver = Transform(new_receiver); |
| 477 } | 484 } |
| 478 AstNode* new_value = Transform(node->value()); | 485 AstNode* new_value = Transform(node->value()); |
| 479 StaticSetterNode* new_setter = | 486 StaticSetterNode* new_setter = |
| 480 node->function().IsNull() | 487 node->function().IsNull() |
| 481 ? new(Z) StaticSetterNode(node->token_pos(), | 488 ? new(Z) StaticSetterNode(node->token_pos(), |
| 482 new_receiver, | 489 new_receiver, |
| 483 node->cls(), | 490 node->cls(), |
| 484 node->field_name(), | 491 node->field_name(), |
| 485 new_value) | 492 new_value) |
| 486 : new(Z) StaticSetterNode(node->token_pos(), | 493 : new(Z) StaticSetterNode(node->token_pos(), |
| 487 new_receiver, | 494 new_receiver, |
| 488 node->field_name(), | 495 node->field_name(), |
| 489 node->function(), | 496 node->function(), |
| 490 new_value); | 497 new_value); |
| 491 | 498 |
| 492 LocalVariable* result = AddToPreambleNewTempVar(new_setter); | 499 LocalVariable* result = |
| 493 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 500 AddToPreambleNewTempVar(new_setter, ST(node->token_pos())); |
| 501 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 494 } | 502 } |
| 495 | 503 |
| 496 | 504 |
| 497 void AwaitTransformer::VisitLoadLocalNode(LoadLocalNode* node) { | 505 void AwaitTransformer::VisitLoadLocalNode(LoadLocalNode* node) { |
| 498 result_ = node; | 506 result_ = node; |
| 499 } | 507 } |
| 500 | 508 |
| 501 | 509 |
| 502 void AwaitTransformer::VisitStoreLocalNode(StoreLocalNode* node) { | 510 void AwaitTransformer::VisitStoreLocalNode(StoreLocalNode* node) { |
| 503 AstNode* new_value = Transform(node->value()); | 511 AstNode* new_value = Transform(node->value()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 518 } | 526 } |
| 519 | 527 |
| 520 | 528 |
| 521 void AwaitTransformer::VisitLoadIndexedNode(LoadIndexedNode* node) { | 529 void AwaitTransformer::VisitLoadIndexedNode(LoadIndexedNode* node) { |
| 522 AstNode* new_array = Transform(node->array()); | 530 AstNode* new_array = Transform(node->array()); |
| 523 AstNode* new_index = Transform(node->index_expr()); | 531 AstNode* new_index = Transform(node->index_expr()); |
| 524 LocalVariable* result = AddToPreambleNewTempVar( | 532 LocalVariable* result = AddToPreambleNewTempVar( |
| 525 new(Z) LoadIndexedNode(node->token_pos(), | 533 new(Z) LoadIndexedNode(node->token_pos(), |
| 526 new_array, | 534 new_array, |
| 527 new_index, | 535 new_index, |
| 528 node->super_class())); | 536 node->super_class()), ST(node->token_pos())); |
| 529 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 537 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 530 } | 538 } |
| 531 | 539 |
| 532 | 540 |
| 533 void AwaitTransformer::VisitStoreIndexedNode(StoreIndexedNode* node) { | 541 void AwaitTransformer::VisitStoreIndexedNode(StoreIndexedNode* node) { |
| 534 AstNode* new_array = Transform(node->array()); | 542 AstNode* new_array = Transform(node->array()); |
| 535 AstNode* new_index = Transform(node->index_expr()); | 543 AstNode* new_index = Transform(node->index_expr()); |
| 536 AstNode* new_value = Transform(node->value()); | 544 AstNode* new_value = Transform(node->value()); |
| 537 LocalVariable* result = AddToPreambleNewTempVar( | 545 LocalVariable* result = AddToPreambleNewTempVar( |
| 538 new(Z) StoreIndexedNode(node->token_pos(), | 546 new(Z) StoreIndexedNode(node->token_pos(), |
| 539 new_array, | 547 new_array, |
| 540 new_index, | 548 new_index, |
| 541 new_value, | 549 new_value, |
| 542 node->super_class())); | 550 node->super_class()), ST(node->token_pos())); |
| 543 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 551 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 544 } | 552 } |
| 545 | 553 |
| 546 | 554 |
| 547 void AwaitTransformer::VisitAssignableNode(AssignableNode* node) { | 555 void AwaitTransformer::VisitAssignableNode(AssignableNode* node) { |
| 548 AstNode* new_expr = Transform(node->expr()); | 556 AstNode* new_expr = Transform(node->expr()); |
| 549 LocalVariable* result = AddToPreambleNewTempVar( | 557 LocalVariable* result = AddToPreambleNewTempVar( |
| 550 new(Z) AssignableNode(node->token_pos(), | 558 new(Z) AssignableNode(node->token_pos(), |
| 551 new_expr, | 559 new_expr, |
| 552 node->type(), | 560 node->type(), |
| 553 node->dst_name())); | 561 node->dst_name()), ST(node->token_pos())); |
| 554 result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result); | 562 result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result); |
| 555 } | 563 } |
| 556 | 564 |
| 557 | 565 |
| 558 void AwaitTransformer::VisitLetNode(LetNode* node) { | 566 void AwaitTransformer::VisitLetNode(LetNode* node) { |
| 559 // Add all the initializer nodes to the preamble and the | 567 // Add all the initializer nodes to the preamble and the |
| 560 // temporary variables to the scope for async temporary variables. | 568 // temporary variables to the scope for async temporary variables. |
| 561 // The temporary variables will be captured as a side effect of being | 569 // The temporary variables will be captured as a side effect of being |
| 562 // added to a scope, and the subsequent nodes that are added to the | 570 // added to a scope, and the subsequent nodes that are added to the |
| 563 // preample can access them. | 571 // preample can access them. |
| 564 for (intptr_t i = 0; i < node->num_temps(); i++) { | 572 for (intptr_t i = 0; i < node->num_temps(); i++) { |
| 565 async_temp_scope_->AddVariable(node->TempAt(i)); | 573 async_temp_scope_->AddVariable(node->TempAt(i)); |
| 566 AstNode* new_init_val = Transform(node->InitializerAt(i)); | 574 AstNode* new_init_val = Transform(node->InitializerAt(i)); |
| 567 preamble_->Add(new(Z) StoreLocalNode(node->token_pos(), | 575 preamble_->Add(new(Z) StoreLocalNode(node->token_pos(), |
| 568 node->TempAt(i), | 576 node->TempAt(i), |
| 569 new_init_val)); | 577 new_init_val)); |
| 570 } | 578 } |
| 571 | 579 |
| 572 // Add all expressions but the last to the preamble. We must do | 580 // Add all expressions but the last to the preamble. We must do |
| 573 // this because subexpressions of the awaitable expression we | 581 // this because subexpressions of the awaitable expression we |
| 574 // are currently transforming may depend on each other, | 582 // are currently transforming may depend on each other, |
| 575 // e.g. await foo(a++, a++). Thus we must preserve the order of the | 583 // e.g. await foo(a++, a++). Thus we must preserve the order of the |
| 576 // transformed subexpressions. | 584 // transformed subexpressions. |
| 577 for (intptr_t i = 0; i < node->nodes().length() - 1; i++) { | 585 for (intptr_t i = 0; i < node->nodes().length() - 1; i++) { |
| 578 preamble_->Add(Transform(node->nodes()[i])); | 586 preamble_->Add(Transform(node->nodes()[i])); |
| 579 } | 587 } |
| 580 | 588 |
| 581 // The last expression in the let node is the value of the node. | 589 // The last expression in the let node is the value of the node. |
| 582 // The result of the transformed let node is this expression. | 590 // The result of the transformed let node is this expression. |
| 583 ASSERT(node->nodes().length() > 0); | 591 ASSERT(node->nodes().length() > 0); |
| 584 const intptr_t last_node_index = node->nodes().length() - 1; | 592 const intptr_t last_node_index = node->nodes().length() - 1; |
| 585 result_ = Transform(node->nodes()[last_node_index]); | 593 result_ = Transform(node->nodes()[last_node_index]); |
| 586 } | 594 } |
| 587 | 595 |
| 588 | 596 |
| 589 void AwaitTransformer::VisitThrowNode(ThrowNode* node) { | 597 void AwaitTransformer::VisitThrowNode(ThrowNode* node) { |
| 590 AstNode* new_exception = Transform(node->exception()); | 598 AstNode* new_exception = Transform(node->exception()); |
| 591 result_ = new(Z) ThrowNode(node->token_pos(), | 599 result_ = new(Z) ThrowNode(node->token_pos(), |
| 592 new_exception, | 600 new_exception, |
| 593 node->stacktrace()); | 601 node->stacktrace()); |
| 594 } | 602 } |
| 595 | 603 |
| 596 } // namespace dart | 604 } // namespace dart |
| OLD | NEW |