OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/rewriter.h" | 5 #include "src/rewriter.h" |
6 | 6 |
7 #include "src/ast.h" | 7 #include "src/ast.h" |
8 #include "src/parser.h" | 8 #include "src/parser.h" |
9 #include "src/scopes.h" | 9 #include "src/scopes.h" |
10 | 10 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
42 bool is_set_; | 42 bool is_set_; |
43 | 43 |
44 AstNodeFactory factory_; | 44 AstNodeFactory factory_; |
45 | 45 |
46 Expression* SetResult(Expression* value) { | 46 Expression* SetResult(Expression* value) { |
47 VariableProxy* result_proxy = factory()->NewVariableProxy(result_); | 47 VariableProxy* result_proxy = factory()->NewVariableProxy(result_); |
48 return factory()->NewAssignment( | 48 return factory()->NewAssignment( |
49 Token::ASSIGN, result_proxy, value, RelocInfo::kNoPosition); | 49 Token::ASSIGN, result_proxy, value, RelocInfo::kNoPosition); |
50 } | 50 } |
51 | 51 |
52 // Inserts '.result = undefined' in front of the given statement. | |
53 Statement* AssignUndefinedBefore(Statement* s); | |
54 | |
52 // Node visitors. | 55 // Node visitors. |
53 #define DEF_VISIT(type) virtual void Visit##type(type* node) override; | 56 #define DEF_VISIT(type) virtual void Visit##type(type* node) override; |
54 AST_NODE_LIST(DEF_VISIT) | 57 AST_NODE_LIST(DEF_VISIT) |
55 #undef DEF_VISIT | 58 #undef DEF_VISIT |
56 | 59 |
57 void VisitIterationStatement(IterationStatement* stmt); | 60 void VisitIterationStatement(IterationStatement* stmt); |
58 | 61 |
59 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 62 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
60 }; | 63 }; |
61 | 64 |
62 | 65 |
66 Statement* Processor::AssignUndefinedBefore(Statement* s) { | |
67 Expression* result_proxy = factory()->NewVariableProxy(result_); | |
68 Expression* undef = factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); | |
69 Expression* assignment = factory()->NewAssignment( | |
70 Token::ASSIGN, result_proxy, undef, RelocInfo::kNoPosition); | |
71 Block* b = factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); | |
72 b->AddStatement( | |
73 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), | |
74 zone()); | |
75 b->AddStatement(s, zone()); | |
76 return b; | |
77 } | |
78 | |
79 | |
63 void Processor::Process(ZoneList<Statement*>* statements) { | 80 void Processor::Process(ZoneList<Statement*>* statements) { |
64 for (int i = statements->length() - 1; i >= 0; --i) { | 81 for (int i = statements->length() - 1; i >= 0; --i) { |
65 Visit(statements->at(i)); | 82 Visit(statements->at(i)); |
66 statements->Set(i, replacement_); | 83 statements->Set(i, replacement_); |
67 } | 84 } |
68 } | 85 } |
69 | 86 |
70 | 87 |
71 void Processor::VisitBlock(Block* node) { | 88 void Processor::VisitBlock(Block* node) { |
72 // An initializer block is the rewritten form of a variable declaration | 89 // An initializer block is the rewritten form of a variable declaration |
(...skipping 23 matching lines...) Expand all Loading... | |
96 // Rewrite both branches. | 113 // Rewrite both branches. |
97 bool set_after = is_set_; | 114 bool set_after = is_set_; |
98 Visit(node->then_statement()); | 115 Visit(node->then_statement()); |
99 node->set_then_statement(replacement_); | 116 node->set_then_statement(replacement_); |
100 bool set_in_then = is_set_; | 117 bool set_in_then = is_set_; |
101 is_set_ = set_after; | 118 is_set_ = set_after; |
102 Visit(node->else_statement()); | 119 Visit(node->else_statement()); |
103 node->set_else_statement(replacement_); | 120 node->set_else_statement(replacement_); |
104 is_set_ = is_set_ && set_in_then; | 121 is_set_ = is_set_ && set_in_then; |
105 replacement_ = node; | 122 replacement_ = node; |
123 | |
124 if (FLAG_harmony_completion && !is_set_) { | |
125 is_set_ = true; | |
rossberg
2015/09/28 14:09:22
Why not move this into AssignUndefinedBeforeNode?
neis
2015/10/05 10:57:28
I prefer the is_set_ logic to be explicit in the V
| |
126 replacement_ = AssignUndefinedBefore(node); | |
127 } | |
106 } | 128 } |
107 | 129 |
108 | 130 |
109 void Processor::VisitIterationStatement(IterationStatement* node) { | 131 void Processor::VisitIterationStatement(IterationStatement* node) { |
110 // Rewrite the body. | 132 // Rewrite the body. |
111 bool set_after = is_set_; | 133 bool set_after = is_set_; |
112 is_set_ = false; // We are in a loop, so we can't rely on [set_after]. | 134 is_set_ = false; // We are in a loop, so we can't rely on [set_after]. |
113 Visit(node->body()); | 135 Visit(node->body()); |
114 node->set_body(replacement_); | 136 node->set_body(replacement_); |
115 is_set_ = is_set_ && set_after; | 137 is_set_ = is_set_ && set_after; |
116 replacement_ = node; | 138 replacement_ = node; |
139 | |
140 if (FLAG_harmony_completion && !is_set_) { | |
141 is_set_ = true; | |
142 replacement_ = AssignUndefinedBefore(node); | |
143 } | |
117 } | 144 } |
118 | 145 |
119 | 146 |
120 void Processor::VisitDoWhileStatement(DoWhileStatement* node) { | 147 void Processor::VisitDoWhileStatement(DoWhileStatement* node) { |
121 VisitIterationStatement(node); | 148 VisitIterationStatement(node); |
122 } | 149 } |
123 | 150 |
124 | 151 |
125 void Processor::VisitWhileStatement(WhileStatement* node) { | 152 void Processor::VisitWhileStatement(WhileStatement* node) { |
126 VisitIterationStatement(node); | 153 VisitIterationStatement(node); |
(...skipping 19 matching lines...) Expand all Loading... | |
146 // Rewrite both try and catch block. | 173 // Rewrite both try and catch block. |
147 bool set_after = is_set_; | 174 bool set_after = is_set_; |
148 Visit(node->try_block()); | 175 Visit(node->try_block()); |
149 node->set_try_block(static_cast<Block*>(replacement_)); | 176 node->set_try_block(static_cast<Block*>(replacement_)); |
150 bool set_in_try = is_set_; | 177 bool set_in_try = is_set_; |
151 is_set_ = set_after; | 178 is_set_ = set_after; |
152 Visit(node->catch_block()); | 179 Visit(node->catch_block()); |
153 node->set_catch_block(static_cast<Block*>(replacement_)); | 180 node->set_catch_block(static_cast<Block*>(replacement_)); |
154 is_set_ = is_set_ && set_in_try; | 181 is_set_ = is_set_ && set_in_try; |
155 replacement_ = node; | 182 replacement_ = node; |
183 | |
184 if (FLAG_harmony_completion && !is_set_) { | |
185 is_set_ = true; | |
186 replacement_ = AssignUndefinedBefore(node); | |
187 } | |
156 } | 188 } |
157 | 189 |
158 | 190 |
159 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { | 191 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { |
160 // Rewrite both try and finally block (in reverse order). | 192 // Rewrite both try and finally block (in reverse order). |
161 Visit(node->finally_block()); | 193 Visit(node->finally_block()); |
162 node->set_finally_block(static_cast<Block*>(replacement_)); | 194 node->set_finally_block(static_cast<Block*>(replacement_)); |
163 Visit(node->try_block()); // Exception will not be caught. | 195 Visit(node->try_block()); // Exception will not be caught. |
164 node->set_try_block(static_cast<Block*>(replacement_)); | 196 node->set_try_block(static_cast<Block*>(replacement_)); |
165 replacement_ = node; | 197 replacement_ = node; |
198 | |
199 if (FLAG_harmony_completion && !is_set_) { | |
200 is_set_ = true; | |
201 replacement_ = AssignUndefinedBefore(node); | |
202 } | |
166 } | 203 } |
167 | 204 |
168 | 205 |
169 void Processor::VisitSwitchStatement(SwitchStatement* node) { | 206 void Processor::VisitSwitchStatement(SwitchStatement* node) { |
170 // Rewrite statements in all case clauses (in reverse order). | 207 // Rewrite statements in all case clauses (in reverse order). |
171 ZoneList<CaseClause*>* clauses = node->cases(); | 208 ZoneList<CaseClause*>* clauses = node->cases(); |
172 bool set_after = is_set_; | 209 bool set_after = is_set_; |
173 for (int i = clauses->length() - 1; i >= 0; --i) { | 210 for (int i = clauses->length() - 1; i >= 0; --i) { |
174 CaseClause* clause = clauses->at(i); | 211 CaseClause* clause = clauses->at(i); |
175 Process(clause->statements()); | 212 Process(clause->statements()); |
176 } | 213 } |
177 is_set_ = is_set_ && set_after; | 214 is_set_ = is_set_ && set_after; |
178 replacement_ = node; | 215 replacement_ = node; |
216 | |
217 if (FLAG_harmony_completion && !is_set_) { | |
218 is_set_ = true; | |
219 replacement_ = AssignUndefinedBefore(node); | |
220 } | |
179 } | 221 } |
180 | 222 |
181 | 223 |
182 void Processor::VisitContinueStatement(ContinueStatement* node) { | 224 void Processor::VisitContinueStatement(ContinueStatement* node) { |
183 is_set_ = false; | 225 is_set_ = false; |
184 replacement_ = node; | 226 replacement_ = node; |
185 } | 227 } |
186 | 228 |
187 | 229 |
188 void Processor::VisitBreakStatement(BreakStatement* node) { | 230 void Processor::VisitBreakStatement(BreakStatement* node) { |
189 is_set_ = false; | 231 is_set_ = false; |
190 replacement_ = node; | 232 replacement_ = node; |
191 } | 233 } |
192 | 234 |
193 | 235 |
194 void Processor::VisitWithStatement(WithStatement* node) { | 236 void Processor::VisitWithStatement(WithStatement* node) { |
195 Visit(node->statement()); | 237 Visit(node->statement()); |
196 node->set_statement(replacement_); | 238 node->set_statement(replacement_); |
197 replacement_ = node; | 239 replacement_ = node; |
240 | |
241 if (FLAG_harmony_completion && !is_set_) { | |
242 is_set_ = true; | |
243 replacement_ = AssignUndefinedBefore(node); | |
244 } | |
198 } | 245 } |
199 | 246 |
200 | 247 |
201 void Processor::VisitSloppyBlockFunctionStatement( | 248 void Processor::VisitSloppyBlockFunctionStatement( |
202 SloppyBlockFunctionStatement* node) { | 249 SloppyBlockFunctionStatement* node) { |
203 Visit(node->statement()); | 250 Visit(node->statement()); |
204 node->set_statement(replacement_); | 251 node->set_statement(replacement_); |
205 replacement_ = node; | 252 replacement_ = node; |
206 } | 253 } |
207 | 254 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
269 processor.factory()->NewReturnStatement(result_proxy, pos); | 316 processor.factory()->NewReturnStatement(result_proxy, pos); |
270 body->Add(result_statement, info->zone()); | 317 body->Add(result_statement, info->zone()); |
271 } | 318 } |
272 | 319 |
273 return true; | 320 return true; |
274 } | 321 } |
275 | 322 |
276 | 323 |
277 } // namespace internal | 324 } // namespace internal |
278 } // namespace v8 | 325 } // namespace v8 |
OLD | NEW |