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

Side by Side Diff: src/pattern-matcher.cc

Issue 1130623004: [destructuring] Implement basic binding destructuring infrastructure (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/ast.h"
6 #include "src/parser.h"
7
8 namespace v8 {
9
arv (Not doing code reviews) 2015/05/08 19:09:49 Can I has .h file?
10 namespace internal {
11
12
13 bool Parser::PatternMatcher::IsSingleVariableBinding() const {
14 return pattern_->IsVariableProxy();
15 }
16
17
18 const AstRawString* Parser::PatternMatcher::SingleName() const {
19 DCHECK(IsSingleVariableBinding());
20 return pattern_->AsVariableProxy()->raw_name();
21 }
22
23
24 void Parser::PatternMatcher::DeclareAndInitializeVariables(Expression* value,
25 bool* ok) {
26 ok_ = ok;
27 RecurseIntoSubpattern(pattern_, value);
28 }
29
30
31 void Parser::PatternMatcher::VisitVariableProxy(VariableProxy* pattern) {
32 Expression* value = current_value_;
33 decl_->scope->RemoveUnresolved(pattern->AsVariableProxy());
34
35 // Declare variable.
36 // Note that we *always* must treat the initial value via a separate init
37 // assignment for variables and constants because the value must be assigned
38 // when the variable is encountered in the source. But the variable/constant
39 // is declared (and set to 'undefined') upon entering the function within
40 // which the variable or constant is declared. Only function variables have
41 // an initial value in the declaration (because they are initialized upon
42 // entering the function).
43 //
44 // If we have a const declaration, in an inner scope, the proxy is always
45 // bound to the declared variable (independent of possibly surrounding with
46 // statements).
47 // For let/const declarations in harmony mode, we can also immediately
48 // pre-resolve the proxy because it resides in the same scope as the
49 // declaration.
50 Parser* parser = decl_->parser;
51 const AstRawString* name = pattern->raw_name();
52 VariableProxy* proxy = parser->NewUnresolved(name, decl_->mode);
53 Declaration* declaration = factory()->NewVariableDeclaration(
54 proxy, decl_->mode, decl_->scope, decl_->pos);
55 Variable* var = parser->Declare(declaration, decl_->mode != VAR, ok_);
56 if (!*ok_) return;
57 DCHECK_NOT_NULL(var);
58 DCHECK(!proxy->is_resolved() || proxy->var() == var);
59 var->set_initializer_position(decl_->initializer_position);
60 (*decl_->nvars)++;
61 if (decl_->declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
62 parser->ReportMessage("too_many_variables");
63 *ok_ = false;
64 return;
65 }
66 if (decl_->names) {
67 decl_->names->Add(name, zone());
68 }
69
70
71 // Global variable declarations must be compiled in a specific
72 // way. When the script containing the global variable declaration
73 // is entered, the global variable must be declared, so that if it
74 // doesn't exist (on the global object itself, see ES5 errata) it
75 // gets created with an initial undefined value. This is handled
76 // by the declarations part of the function representing the
77 // top-level global code; see Runtime::DeclareGlobalVariable. If
78 // it already exists (in the object or in a prototype), it is
79 // *not* touched until the variable declaration statement is
80 // executed.
81 //
82 // Executing the variable declaration statement will always
83 // guarantee to give the global object an own property.
84 // This way, global variable declarations can shadow
85 // properties in the prototype chain, but only after the variable
86 // declaration statement has been executed. This is important in
87 // browsers where the global object (window) has lots of
88 // properties defined in prototype objects.
89 if (decl_->initialization_scope()->is_script_scope() &&
90 !IsLexicalVariableMode(decl_->mode)) {
91 // Compute the arguments for the runtime
92 // call.test-parsing/InitializedDeclarationsInStrictForOfError
93 ZoneList<Expression*>* arguments =
94 new (zone()) ZoneList<Expression*>(3, zone());
95 // We have at least 1 parameter.
96 arguments->Add(factory()->NewStringLiteral(name, decl_->pos), zone());
97 CallRuntime* initialize;
98
99 if (decl_->is_const) {
100 arguments->Add(value, zone());
101 value = NULL; // zap the value to avoid the unnecessary assignment
102
103 // Construct the call to Runtime_InitializeConstGlobal
104 // and add it to the initialization statement block.
105 // Note that the function does different things depending on
106 // the number of arguments (1 or 2).
107 initialize = factory()->NewCallRuntime(
108 ast_value_factory()->initialize_const_global_string(),
109 Runtime::FunctionForId(Runtime::kInitializeConstGlobal), arguments,
110 decl_->pos);
111 } else {
112 // Add language mode.
113 // We may want to pass singleton to avoid Literal allocations.
114 LanguageMode language_mode =
115 decl_->initialization_scope()->language_mode();
116 arguments->Add(factory()->NewNumberLiteral(language_mode, decl_->pos),
117 zone());
118
119 // Be careful not to assign a value to the global variable if
120 // we're in a with. The initialization value should not
121 // necessarily be stored in the global object in that case,
122 // which is why we need to generate a separate assignment node.
123 if (value != NULL && !decl_->inside_with()) {
124 arguments->Add(value, zone());
125 value = NULL; // zap the value to avoid the unnecessary assignment
126 // Construct the call to Runtime_InitializeVarGlobal
127 // and add it to the initialization statement block.
128 initialize = factory()->NewCallRuntime(
129 ast_value_factory()->initialize_var_global_string(),
130 Runtime::FunctionForId(Runtime::kInitializeVarGlobal), arguments,
131 decl_->pos);
132 } else {
133 initialize = NULL;
134 }
135 }
136
137 if (initialize != NULL) {
138 decl_->block->AddStatement(
139 factory()->NewExpressionStatement(initialize, RelocInfo::kNoPosition),
140 zone());
141 }
142 } else if (decl_->needs_init) {
143 // Constant initializations always assign to the declared constant which
144 // is always at the function scope level. This is only relevant for
145 // dynamically looked-up variables and constants (the
146 // stest-parsing/InitializedDeclarationsInStrictForOfError tart context for
arv (Not doing code reviews) 2015/05/08 19:09:49 typo
Dmitry Lomov (no reviews) 2015/05/11 11:07:28 Done.
147 // constant lookups is always the function context, while it is the top
148 // context for var declared variables). Sigh...
149 // For 'let' and 'const' declared variables in harmony mode the
150 // initialization also always assigns to the declared variable.
151 DCHECK(proxy != NULL);
arv (Not doing code reviews) 2015/05/08 19:09:49 DCHECK_NOT_NULL
Dmitry Lomov (no reviews) 2015/05/11 11:07:28 Done.
152 DCHECK(proxy->var() != NULL);
153 DCHECK(value != NULL);
154 Assignment* assignment =
155 factory()->NewAssignment(decl_->init_op, proxy, value, decl_->pos);
156 decl_->block->AddStatement(
157 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
158 zone());
159 value = NULL;
160 }
161
162 // Add an assignment node to the initialization statement block if we still
163 // have a pending initialization value.
164 if (value != NULL) {
165 DCHECK(decl_->mode == VAR);
166 // 'var' initializations are simply assignments (with all the consequences
167 // if they are inside a 'with' statement - they may change a 'with' object
168 // property).
169 VariableProxy* proxy =
170 decl_->initialization_scope()->NewUnresolved(factory(), name);
171 Assignment* assignment =
172 factory()->NewAssignment(decl_->init_op, proxy, value, decl_->pos);
173 decl_->block->AddStatement(
174 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
175 zone());
176 }
177 }
178
179
180 void Parser::PatternMatcher::VisitObjectLiteral(ObjectLiteral* pattern) {
181 auto temp = decl_->declaration_scope->NewTemporary(
182 ast_value_factory()->empty_string());
183 auto assignment =
184 factory()->NewAssignment(Token::ASSIGN, factory()->NewVariableProxy(temp),
185 current_value_, RelocInfo::kNoPosition);
186 decl_->block->AddStatement(
187 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
188 zone());
189 auto properties = pattern->properties();
190 for (auto i = properties->begin(); i != properties->end(); i++) {
arv (Not doing code reviews) 2015/05/08 19:09:49 Can we do? for (auto property : properties) {
Dmitry Lomov (no reviews) 2015/05/11 11:07:28 Done.
191 ObjectLiteralProperty* property = *i;
192
193 RecurseIntoSubpattern(
194 property->value(),
195 factory()->NewProperty(factory()->NewVariableProxy(temp),
196 property->key(), RelocInfo::kNoPosition));
arv (Not doing code reviews) 2015/05/08 19:09:49 TODO(dslomov): Computed property names
Dmitry Lomov (no reviews) 2015/05/11 11:07:28 Done.
197 }
198 }
199
200
201 void Parser::PatternMatcher::VisitArrayLiteral(ArrayLiteral* node) {
202 // TODO(dslomov): implement.
203 }
204
205
206 // =============== UNREACHABLE =============================
207 void Parser::PatternMatcher::VisitProperty(Property* node) { UNREACHABLE(); }
arv (Not doing code reviews) 2015/05/08 19:09:49 This is only unreachable in binding patterns: var
Dmitry Lomov (no reviews) 2015/05/11 11:07:28 I am not dealing with assignment patterns yet. As
208
209
210 void Parser::PatternMatcher::Visit(AstNode* node) { UNREACHABLE(); }
211
212
213 void Parser::PatternMatcher::VisitVariableDeclaration(
214 VariableDeclaration* node) {
215 UNREACHABLE();
216 }
217
218
219 void Parser::PatternMatcher::VisitExportDeclaration(ExportDeclaration* node) {
220 UNREACHABLE();
221 }
222
223
224 void Parser::PatternMatcher::VisitEmptyStatement(EmptyStatement* node) {
225 UNREACHABLE();
226 }
227
228
229 void Parser::PatternMatcher::VisitContinueStatement(ContinueStatement* node) {
230 UNREACHABLE();
231 }
232
233
234 void Parser::PatternMatcher::VisitBreakStatement(BreakStatement* node) {
235 UNREACHABLE();
236 }
237
238
239 void Parser::PatternMatcher::VisitDebuggerStatement(DebuggerStatement* node) {
240 UNREACHABLE();
241 }
242
243
244 void Parser::PatternMatcher::VisitNativeFunctionLiteral(
245 NativeFunctionLiteral* node) {
246 UNREACHABLE();
247 }
248
249
250 void Parser::PatternMatcher::VisitLiteral(Literal* node) { UNREACHABLE(); }
251
252
253 void Parser::PatternMatcher::VisitRegExpLiteral(RegExpLiteral* node) {
254 UNREACHABLE();
255 }
256
257
258 void Parser::PatternMatcher::VisitThisFunction(ThisFunction* node) {
259 UNREACHABLE();
260 }
261
262
263 void Parser::PatternMatcher::VisitSuperReference(
264 v8::internal::SuperReference* node) {
265 UNREACHABLE();
266 }
267
268
269 void Parser::PatternMatcher::VisitImportDeclaration(ImportDeclaration* node) {
270 UNREACHABLE();
271 }
272
273
274 void Parser::PatternMatcher::VisitExpressionStatement(
275 ExpressionStatement* node) {
276 UNREACHABLE();
277 }
278
279
280 void Parser::PatternMatcher::VisitReturnStatement(ReturnStatement* node) {
281 UNREACHABLE();
282 }
283
284
285 void Parser::PatternMatcher::VisitYield(Yield* node) { UNREACHABLE(); }
286
287
288 void Parser::PatternMatcher::VisitThrow(Throw* node) { UNREACHABLE(); }
289
290
291 void Parser::PatternMatcher::VisitUnaryOperation(UnaryOperation* node) {
292 UNREACHABLE();
293 }
294
295
296 void Parser::PatternMatcher::VisitCountOperation(CountOperation* node) {
297 UNREACHABLE();
298 }
299
300
301 void Parser::PatternMatcher::VisitBlock(Block* node) { UNREACHABLE(); }
302
303
304 void Parser::PatternMatcher::VisitFunctionDeclaration(
305 FunctionDeclaration* node) {
306 UNREACHABLE();
307 }
308
309
310 void Parser::PatternMatcher::VisitCallRuntime(CallRuntime* node) {
311 UNREACHABLE();
312 }
313
314
315 void Parser::PatternMatcher::VisitWithStatement(WithStatement* node) {
316 UNREACHABLE();
317 }
318
319
320 void Parser::PatternMatcher::VisitDoWhileStatement(DoWhileStatement* node) {
arv (Not doing code reviews) 2015/05/08 19:09:49 Maybe a macro for all of these?
Dmitry Lomov (no reviews) 2015/05/11 11:07:28 Done.
321 UNREACHABLE();
322 }
323
324
325 void Parser::PatternMatcher::VisitWhileStatement(WhileStatement* node) {
326 UNREACHABLE();
327 }
328
329
330 void Parser::PatternMatcher::VisitTryCatchStatement(TryCatchStatement* node) {
331 UNREACHABLE();
332 }
333
334
335 void Parser::PatternMatcher::VisitTryFinallyStatement(
336 TryFinallyStatement* node) {
337 UNREACHABLE();
338 }
339
340
341 void Parser::PatternMatcher::VisitAssignment(Assignment* node) {
arv (Not doing code reviews) 2015/05/08 19:09:49 TODO(dslomov): Implement var {x: y = 42} = {}; as
Dmitry Lomov (no reviews) 2015/05/11 11:07:28 Done.
342 UNREACHABLE();
343 }
344
345
346 void Parser::PatternMatcher::VisitBinaryOperation(BinaryOperation* node) {
347 UNREACHABLE();
348 }
349
350
351 void Parser::PatternMatcher::VisitCompareOperation(CompareOperation* node) {
352 UNREACHABLE();
353 }
354
355
356 void Parser::PatternMatcher::VisitSpread(Spread* node) { UNREACHABLE(); }
arv (Not doing code reviews) 2015/05/08 19:09:48 TODO(dslomov): Implement var [...xs] = []
Dmitry Lomov (no reviews) 2015/05/11 11:07:28 Done.
357
358
359 void Parser::PatternMatcher::VisitForInStatement(ForInStatement* node) {
360 UNREACHABLE();
361 }
362
363
364 void Parser::PatternMatcher::VisitForOfStatement(ForOfStatement* node) {
365 UNREACHABLE();
366 }
367
368
369 void Parser::PatternMatcher::VisitConditional(Conditional* node) {
370 UNREACHABLE();
371 }
372
373
374 void Parser::PatternMatcher::VisitIfStatement(IfStatement* node) {
375 UNREACHABLE();
376 }
377
378
379 void Parser::PatternMatcher::VisitSwitchStatement(SwitchStatement* node) {
380 UNREACHABLE();
381 }
382
383
384 void Parser::PatternMatcher::VisitCaseClause(CaseClause* node) {
385 UNREACHABLE();
386 }
387
388
389 void Parser::PatternMatcher::VisitForStatement(ForStatement* node) {
390 UNREACHABLE();
391 }
392
393
394 void Parser::PatternMatcher::VisitClassLiteral(ClassLiteral* node) {
395 UNREACHABLE();
396 }
397
398
399 void Parser::PatternMatcher::VisitCall(Call* node) { UNREACHABLE(); }
400
401
402 void Parser::PatternMatcher::VisitCallNew(CallNew* node) { UNREACHABLE(); }
403
404
405 void Parser::PatternMatcher::VisitFunctionLiteral(FunctionLiteral* node) {
406 UNREACHABLE();
407 }
408 }
409 } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698