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 |