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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast.h" | 8 #include "src/ast.h" |
9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
11 #include "src/bootstrapper.h" | 11 #include "src/bootstrapper.h" |
12 #include "src/char-predicates-inl.h" | 12 #include "src/char-predicates-inl.h" |
13 #include "src/codegen.h" | 13 #include "src/codegen.h" |
14 #include "src/compiler.h" | 14 #include "src/compiler.h" |
15 #include "src/messages.h" | 15 #include "src/messages.h" |
16 #include "src/parser.h" | 16 #include "src/parser.h" |
17 #include "src/pattern-rewriter.h" | |
18 #include "src/preparser.h" | 17 #include "src/preparser.h" |
19 #include "src/runtime/runtime.h" | 18 #include "src/runtime/runtime.h" |
20 #include "src/scanner-character-streams.h" | 19 #include "src/scanner-character-streams.h" |
21 #include "src/scopeinfo.h" | 20 #include "src/scopeinfo.h" |
22 #include "src/string-stream.h" | 21 #include "src/string-stream.h" |
23 | 22 |
24 namespace v8 { | 23 namespace v8 { |
25 namespace internal { | 24 namespace internal { |
26 | 25 |
27 ScriptData::ScriptData(const byte* data, int length) | 26 ScriptData::ScriptData(const byte* data, int length) |
(...skipping 2250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2278 return body; | 2277 return body; |
2279 } | 2278 } |
2280 | 2279 |
2281 | 2280 |
2282 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, | 2281 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
2283 ZoneList<const AstRawString*>* names, | 2282 ZoneList<const AstRawString*>* names, |
2284 bool* ok) { | 2283 bool* ok) { |
2285 // VariableStatement :: | 2284 // VariableStatement :: |
2286 // VariableDeclarations ';' | 2285 // VariableDeclarations ';' |
2287 | 2286 |
2288 const AstRawString* ignore; | 2287 DeclarationParsingResult parsing_result; |
2289 Block* result = ParseVariableDeclarations( | 2288 ParseVariableDeclarations(var_context, &parsing_result, CHECK_OK); |
2290 var_context, nullptr, names, &ignore, nullptr, nullptr, CHECK_OK); | |
2291 ExpectSemicolon(CHECK_OK); | 2289 ExpectSemicolon(CHECK_OK); |
2290 Block* result = factory()->NewBlock(NULL, 1, true, parsing_result.decl.pos); | |
2291 for (auto decl : parsing_result.declarations) { | |
2292 decl.pattern.DeclareAndInitializeVariables( | |
2293 result, &parsing_result.decl, decl.initializer, names, CHECK_OK); | |
2294 } | |
2295 | |
2292 return result; | 2296 return result; |
2293 } | 2297 } |
2294 | 2298 |
2295 | 2299 |
2296 // If the variable declaration declares exactly one non-const | 2300 // If the variable declaration declares exactly one non-const |
2297 // variable, then *out is set to that variable. In all other cases, | 2301 // variable, then *out is set to that variable. In all other cases, |
2298 // *out is untouched; in particular, it is the caller's responsibility | 2302 // *out is untouched; in particular, it is the caller's responsibility |
2299 // to initialize it properly. This mechanism is used for the parsing | 2303 // to initialize it properly. This mechanism is used for the parsing |
2300 // of 'for-in' loops. | 2304 // of 'for-in' loops. |
2301 Block* Parser::ParseVariableDeclarations( | 2305 // TODO(dslomov): fix the comment |
2302 VariableDeclarationContext var_context, int* num_decl, | 2306 void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, |
2303 ZoneList<const AstRawString*>* names, const AstRawString** out, | 2307 DeclarationParsingResult* parsing_result, |
2304 Scanner::Location* first_initializer_loc, Scanner::Location* bindings_loc, | 2308 bool* ok) { |
2305 bool* ok) { | |
2306 // VariableDeclarations :: | 2309 // VariableDeclarations :: |
2307 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] | 2310 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] |
2308 // | 2311 // |
2309 // The ES6 Draft Rev3 specifies the following grammar for const declarations | 2312 // The ES6 Draft Rev3 specifies the following grammar for const declarations |
2310 // | 2313 // |
2311 // ConstDeclaration :: | 2314 // ConstDeclaration :: |
2312 // const ConstBinding (',' ConstBinding)* ';' | 2315 // const ConstBinding (',' ConstBinding)* ';' |
2313 // ConstBinding :: | 2316 // ConstBinding :: |
2314 // Identifier '=' AssignmentExpression | 2317 // Identifier '=' AssignmentExpression |
2315 // | 2318 // |
2316 // TODO(ES6): | 2319 // TODO(ES6): |
2317 // ConstBinding :: | 2320 // ConstBinding :: |
2318 // BindingPattern '=' AssignmentExpression | 2321 // BindingPattern '=' AssignmentExpression |
2319 | 2322 |
2320 PatternRewriter::DeclarationDescriptor decl; | 2323 parsing_result->decl.parser = this; |
2321 decl.parser = this; | 2324 parsing_result->decl.pos = peek_position(); |
2322 decl.pos = peek_position(); | 2325 parsing_result->decl.mode = VAR; |
2323 decl.mode = VAR; | |
2324 // True if the binding needs initialization. 'let' and 'const' declared | 2326 // True if the binding needs initialization. 'let' and 'const' declared |
2325 // bindings are created uninitialized by their declaration nodes and | 2327 // bindings are created uninitialized by their declaration nodes and |
2326 // need initialization. 'var' declared bindings are always initialized | 2328 // need initialization. 'var' declared bindings are always initialized |
2327 // immediately by their declaration nodes. | 2329 // immediately by their declaration nodes. |
2328 decl.needs_init = false; | 2330 parsing_result->decl.needs_init = false; |
2329 decl.is_const = false; | 2331 parsing_result->decl.is_const = false; |
2330 decl.init_op = Token::INIT_VAR; | 2332 parsing_result->decl.init_op = Token::INIT_VAR; |
2331 decl.names = names; | |
2332 if (peek() == Token::VAR) { | 2333 if (peek() == Token::VAR) { |
2333 if (is_strong(language_mode())) { | 2334 if (is_strong(language_mode())) { |
2334 Scanner::Location location = scanner()->peek_location(); | 2335 Scanner::Location location = scanner()->peek_location(); |
2335 ReportMessageAt(location, "strong_var"); | 2336 ReportMessageAt(location, "strong_var"); |
2336 *ok = false; | 2337 *ok = false; |
2337 return NULL; | 2338 return; |
2338 } | 2339 } |
2339 Consume(Token::VAR); | 2340 Consume(Token::VAR); |
2340 } else if (peek() == Token::CONST) { | 2341 } else if (peek() == Token::CONST) { |
2341 Consume(Token::CONST); | 2342 Consume(Token::CONST); |
2342 if (is_sloppy(language_mode())) { | 2343 if (is_sloppy(language_mode())) { |
2343 decl.mode = CONST_LEGACY; | 2344 parsing_result->decl.mode = CONST_LEGACY; |
2344 decl.init_op = Token::INIT_CONST_LEGACY; | 2345 parsing_result->decl.init_op = Token::INIT_CONST_LEGACY; |
2345 ++use_counts_[v8::Isolate::kLegacyConst]; | 2346 ++use_counts_[v8::Isolate::kLegacyConst]; |
2346 } else { | 2347 } else { |
2347 DCHECK(var_context != kStatement); | 2348 DCHECK(var_context != kStatement); |
2348 decl.mode = CONST; | 2349 parsing_result->decl.mode = CONST; |
2349 decl.init_op = Token::INIT_CONST; | 2350 parsing_result->decl.init_op = Token::INIT_CONST; |
2350 } | 2351 } |
2351 decl.is_const = true; | 2352 parsing_result->decl.is_const = true; |
2352 decl.needs_init = true; | 2353 parsing_result->decl.needs_init = true; |
2353 } else if (peek() == Token::LET && is_strict(language_mode())) { | 2354 } else if (peek() == Token::LET && is_strict(language_mode())) { |
2354 Consume(Token::LET); | 2355 Consume(Token::LET); |
2355 DCHECK(var_context != kStatement); | 2356 DCHECK(var_context != kStatement); |
2356 decl.mode = LET; | 2357 parsing_result->decl.mode = LET; |
2357 decl.needs_init = true; | 2358 parsing_result->decl.needs_init = true; |
2358 decl.init_op = Token::INIT_LET; | 2359 parsing_result->decl.init_op = Token::INIT_LET; |
2359 } else { | 2360 } else { |
2360 UNREACHABLE(); // by current callers | 2361 UNREACHABLE(); // by current callers |
2361 } | 2362 } |
2362 | 2363 |
2363 decl.declaration_scope = DeclarationScope(decl.mode); | 2364 parsing_result->decl.declaration_scope = |
2364 decl.scope = scope_; | 2365 DeclarationScope(parsing_result->decl.mode); |
2366 parsing_result->decl.scope = scope_; | |
2365 | 2367 |
2366 | 2368 |
2367 // The scope of a var/const declared variable anywhere inside a function | 2369 // The scope of a var/const declared variable anywhere inside a function |
2368 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can | 2370 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can |
2369 // transform a source-level var/const declaration into a (Function) | 2371 // transform a source-level var/const declaration into a (Function) |
2370 // Scope declaration, and rewrite the source-level initialization into an | 2372 // Scope declaration, and rewrite the source-level initialization into an |
2371 // assignment statement. We use a block to collect multiple assignments. | 2373 // assignment statement. We use a block to collect multiple assignments. |
2372 // | 2374 // |
2373 // We mark the block as initializer block because we don't want the | 2375 // We mark the block as initializer block because we don't want the |
2374 // rewriter to add a '.result' assignment to such a block (to get compliant | 2376 // rewriter to add a '.result' assignment to such a block (to get compliant |
2375 // behavior for code such as print(eval('var x = 7')), and for cosmetic | 2377 // behavior for code such as print(eval('var x = 7')), and for cosmetic |
2376 // reasons when pretty-printing. Also, unless an assignment (initialization) | 2378 // reasons when pretty-printing. Also, unless an assignment (initialization) |
2377 // is inside an initializer block, it is ignored. | 2379 // is inside an initializer block, it is ignored. |
2378 // | |
2379 // Create new block with one expected declaration. | |
2380 decl.block = factory()->NewBlock(NULL, 1, true, decl.pos); | |
2381 int nvars = 0; // the number of variables declared | 2380 int nvars = 0; // the number of variables declared |
2382 int bindings_start = peek_position(); | 2381 int bindings_start = peek_position(); |
2383 const AstRawString* first_name = NULL; | 2382 const AstRawString* first_name = NULL; |
2384 bool is_for_iteration_variable; | 2383 bool is_for_iteration_variable; |
2385 do { | 2384 do { |
2386 if (fni_ != NULL) fni_->Enter(); | 2385 if (fni_ != NULL) fni_->Enter(); |
2387 | 2386 |
2388 // Parse variable name. | 2387 // Parse name. |
2389 if (nvars > 0) Consume(Token::COMMA); | 2388 if (nvars > 0) Consume(Token::COMMA); |
2390 | 2389 |
2391 PatternRewriter pattern_rewriter; | 2390 PatternRewriter pattern_rewriter; |
2392 { | 2391 { |
2393 ExpressionClassifier pattern_classifier; | 2392 ExpressionClassifier pattern_classifier; |
2394 Token::Value next = peek(); | 2393 Token::Value next = peek(); |
2395 Expression* pattern = | 2394 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, ok); |
2396 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | 2395 if (!*ok) return; |
2397 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | 2396 ValidateBindingPattern(&pattern_classifier, ok); |
2398 pattern_rewriter = PatternRewriter(&decl, pattern); | 2397 if (!*ok) return; |
2398 pattern_rewriter = PatternRewriter(pattern); | |
2399 if (!allow_harmony_destructuring() && | 2399 if (!allow_harmony_destructuring() && |
2400 !pattern_rewriter.IsSingleVariableBinding()) { | 2400 !pattern_rewriter.IsSingleVariableBinding()) { |
2401 ReportUnexpectedToken(next); | 2401 ReportUnexpectedToken(next); |
2402 *ok = false; | 2402 *ok = false; |
2403 return nullptr; | 2403 return; |
2404 } | 2404 } |
2405 | |
2406 // TODO(dslomov): unify | |
2407 } | 2405 } |
2408 | 2406 |
2409 Scanner::Location variable_loc = scanner()->location(); | 2407 Scanner::Location variable_loc = scanner()->location(); |
2410 const bool single_name = pattern_rewriter.IsSingleVariableBinding(); | 2408 const bool single_name = pattern_rewriter.IsSingleVariableBinding(); |
2411 if (single_name) { | 2409 if (single_name) { |
2412 if (!first_name) first_name = pattern_rewriter.SingleName(); | 2410 if (!first_name) first_name = pattern_rewriter.SingleName(); |
2413 if (fni_ != NULL) fni_->PushVariableName(pattern_rewriter.SingleName()); | 2411 if (fni_ != NULL) fni_->PushVariableName(pattern_rewriter.SingleName()); |
2414 } | 2412 } |
2415 | 2413 |
2416 is_for_iteration_variable = | 2414 is_for_iteration_variable = |
2417 var_context == kForStatement && | 2415 var_context == kForStatement && |
2418 (peek() == Token::IN || PeekContextualKeyword(CStrVector("of"))); | 2416 (peek() == Token::IN || PeekContextualKeyword(CStrVector("of"))); |
2419 if (is_for_iteration_variable && decl.mode == CONST) { | 2417 if (is_for_iteration_variable && parsing_result->decl.mode == CONST) { |
2420 decl.needs_init = false; | 2418 parsing_result->decl.needs_init = false; |
2421 } | 2419 } |
2422 | 2420 |
2423 Expression* value = NULL; | 2421 Expression* value = NULL; |
2424 decl.pos = -1; | |
2425 decl.initializer_position = -1; | |
2426 // Harmony consts have non-optional initializers. | 2422 // Harmony consts have non-optional initializers. |
2427 if (peek() == Token::ASSIGN || | 2423 if (peek() == Token::ASSIGN || |
2428 (decl.mode == CONST && !is_for_iteration_variable)) { | 2424 (parsing_result->decl.mode == CONST && !is_for_iteration_variable)) { |
2429 Expect(Token::ASSIGN, CHECK_OK); | 2425 Expect(Token::ASSIGN, ok); |
arv (Not doing code reviews)
2015/05/13 16:29:29
Maybe add a macro for CHECK_OK_VOID?
Dmitry Lomov (no reviews)
2015/05/14 16:28:00
Considered this but decided against. Too many CHEC
| |
2430 decl.pos = position(); | 2426 if (!*ok) return; |
2427 parsing_result->decl.pos = position(); | |
2431 ExpressionClassifier classifier; | 2428 ExpressionClassifier classifier; |
2432 value = ParseAssignmentExpression(var_context != kForStatement, | 2429 value = ParseAssignmentExpression(var_context != kForStatement, |
2433 &classifier, CHECK_OK); | 2430 &classifier, ok); |
2434 ValidateExpression(&classifier, CHECK_OK); | 2431 if (!*ok) return; |
2432 ValidateExpression(&classifier, ok); | |
2433 if (!*ok) return; | |
2435 variable_loc.end_pos = scanner()->location().end_pos; | 2434 variable_loc.end_pos = scanner()->location().end_pos; |
2436 | 2435 |
2437 if (first_initializer_loc && !first_initializer_loc->IsValid()) { | 2436 if (!parsing_result->first_initializer_loc.IsValid()) { |
2438 *first_initializer_loc = variable_loc; | 2437 parsing_result->first_initializer_loc = variable_loc; |
2439 } | 2438 } |
2440 | 2439 |
2441 // Don't infer if it is "a = function(){...}();"-like expression. | 2440 // Don't infer if it is "a = function(){...}();"-like expression. |
2442 if (single_name) { | 2441 if (single_name) { |
2443 if (fni_ != NULL && value->AsCall() == NULL && | 2442 if (fni_ != NULL && value->AsCall() == NULL && |
2444 value->AsCallNew() == NULL) { | 2443 value->AsCallNew() == NULL) { |
2445 fni_->Infer(); | 2444 fni_->Infer(); |
2446 } else { | 2445 } else { |
2447 fni_->RemoveLastFunction(); | 2446 fni_->RemoveLastFunction(); |
2448 } | 2447 } |
2449 } | 2448 } |
2450 // End position of the initializer is after the assignment expression. | 2449 // End position of the initializer is after the assignment expression. |
2451 decl.initializer_position = scanner()->location().end_pos; | 2450 pattern_rewriter.set_initializer_position(scanner()->location().end_pos); |
2452 } else { | 2451 } else { |
2453 // End position of the initializer is after the variable. | 2452 // End position of the initializer is after the variable. |
2454 decl.initializer_position = position(); | 2453 pattern_rewriter.set_initializer_position(position()); |
2455 } | 2454 } |
2456 | 2455 |
2457 // Make sure that 'const x' and 'let x' initialize 'x' to undefined. | 2456 // Make sure that 'const x' and 'let x' initialize 'x' to undefined. |
2458 if (value == NULL && decl.needs_init) { | 2457 if (value == NULL && parsing_result->decl.needs_init) { |
2459 value = GetLiteralUndefined(position()); | 2458 value = GetLiteralUndefined(position()); |
2460 } | 2459 } |
2461 | 2460 |
2462 pattern_rewriter.DeclareAndInitializeVariables(value, &nvars, CHECK_OK); | |
2463 | |
2464 if (single_name && fni_ != NULL) fni_->Leave(); | 2461 if (single_name && fni_ != NULL) fni_->Leave(); |
2462 parsing_result->declarations.Add( | |
2463 DeclarationParsingResult::Declaration(pattern_rewriter, value)); | |
2464 nvars++; | |
2465 } while (peek() == Token::COMMA); | 2465 } while (peek() == Token::COMMA); |
2466 | 2466 |
2467 if (bindings_loc) { | 2467 parsing_result->bindings_loc = |
2468 *bindings_loc = | 2468 Scanner::Location(bindings_start, scanner()->location().end_pos); |
2469 Scanner::Location(bindings_start, scanner()->location().end_pos); | |
2470 } | |
2471 | 2469 |
2472 if (num_decl) *num_decl = nvars; | 2470 parsing_result->out = first_name; |
arv (Not doing code reviews)
2015/05/13 16:29:29
rename out?
Dmitry Lomov (no reviews)
2015/05/14 16:28:00
I did one better and removed it completely
| |
2473 *out = first_name; | |
2474 | |
2475 return decl.block; | |
2476 } | 2471 } |
2477 | 2472 |
2478 | 2473 |
2479 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, | 2474 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, |
2480 const AstRawString* label) { | 2475 const AstRawString* label) { |
2481 DCHECK(label != NULL); | 2476 DCHECK(label != NULL); |
2482 if (labels != NULL) { | 2477 if (labels != NULL) { |
2483 for (int i = labels->length(); i-- > 0; ) { | 2478 for (int i = labels->length(); i-- > 0; ) { |
2484 if (labels->at(i) == label) { | 2479 if (labels->at(i) == label) { |
2485 return true; | 2480 return true; |
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3232 ForStatement* outer_loop = | 3227 ForStatement* outer_loop = |
3233 factory()->NewForStatement(NULL, RelocInfo::kNoPosition); | 3228 factory()->NewForStatement(NULL, RelocInfo::kNoPosition); |
3234 outer_block->AddStatement(outer_loop, zone()); | 3229 outer_block->AddStatement(outer_loop, zone()); |
3235 | 3230 |
3236 outer_block->set_scope(for_scope); | 3231 outer_block->set_scope(for_scope); |
3237 scope_ = inner_scope; | 3232 scope_ = inner_scope; |
3238 | 3233 |
3239 Block* inner_block = factory()->NewBlock(NULL, names->length() + 4, false, | 3234 Block* inner_block = factory()->NewBlock(NULL, names->length() + 4, false, |
3240 RelocInfo::kNoPosition); | 3235 RelocInfo::kNoPosition); |
3241 ZoneList<Variable*> inner_vars(names->length(), zone()); | 3236 ZoneList<Variable*> inner_vars(names->length(), zone()); |
3242 | |
3243 // For each let variable x: | 3237 // For each let variable x: |
3244 // make statement: let/const x = temp_x. | 3238 // make statement: let/const x = temp_x. |
3245 VariableMode mode = is_const ? CONST : LET; | 3239 VariableMode mode = is_const ? CONST : LET; |
3246 for (int i = 0; i < names->length(); i++) { | 3240 for (int i = 0; i < names->length(); i++) { |
3247 VariableProxy* proxy = NewUnresolved(names->at(i), mode); | 3241 VariableProxy* proxy = NewUnresolved(names->at(i), mode); |
3248 Declaration* declaration = factory()->NewVariableDeclaration( | 3242 Declaration* declaration = factory()->NewVariableDeclaration( |
3249 proxy, mode, scope_, RelocInfo::kNoPosition); | 3243 proxy, mode, scope_, RelocInfo::kNoPosition); |
3250 Declare(declaration, true, CHECK_OK); | 3244 Declare(declaration, true, CHECK_OK); |
3251 inner_vars.Add(declaration->proxy()->var(), zone()); | 3245 inner_vars.Add(declaration->proxy()->var(), zone()); |
3252 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | 3246 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); |
3253 Assignment* assignment = | 3247 Assignment* assignment = |
3254 factory()->NewAssignment(is_const ? Token::INIT_CONST : Token::INIT_LET, | 3248 factory()->NewAssignment(is_const ? Token::INIT_CONST : Token::INIT_LET, |
3255 proxy, temp_proxy, RelocInfo::kNoPosition); | 3249 proxy, temp_proxy, RelocInfo::kNoPosition); |
3256 Statement* assignment_statement = | 3250 Statement* assignment_statement = |
3257 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | 3251 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
3252 DCHECK(init->position() != RelocInfo::kNoPosition); | |
3258 proxy->var()->set_initializer_position(init->position()); | 3253 proxy->var()->set_initializer_position(init->position()); |
3259 inner_block->AddStatement(assignment_statement, zone()); | 3254 inner_block->AddStatement(assignment_statement, zone()); |
3260 } | 3255 } |
3261 | 3256 |
3262 // Make statement: if (first == 1) { first = 0; } else { next; } | 3257 // Make statement: if (first == 1) { first = 0; } else { next; } |
3263 if (next) { | 3258 if (next) { |
3264 DCHECK(first); | 3259 DCHECK(first); |
3265 Expression* compare = NULL; | 3260 Expression* compare = NULL; |
3266 // Make compare expression: first == 1. | 3261 // Make compare expression: first == 1. |
3267 { | 3262 { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3384 | 3379 |
3385 int stmt_pos = peek_position(); | 3380 int stmt_pos = peek_position(); |
3386 bool is_const = false; | 3381 bool is_const = false; |
3387 Statement* init = NULL; | 3382 Statement* init = NULL; |
3388 ZoneList<const AstRawString*> lexical_bindings(1, zone()); | 3383 ZoneList<const AstRawString*> lexical_bindings(1, zone()); |
3389 | 3384 |
3390 // Create an in-between scope for let-bound iteration variables. | 3385 // Create an in-between scope for let-bound iteration variables. |
3391 Scope* saved_scope = scope_; | 3386 Scope* saved_scope = scope_; |
3392 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3387 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
3393 scope_ = for_scope; | 3388 scope_ = for_scope; |
3394 | |
3395 Expect(Token::FOR, CHECK_OK); | 3389 Expect(Token::FOR, CHECK_OK); |
3396 Expect(Token::LPAREN, CHECK_OK); | 3390 Expect(Token::LPAREN, CHECK_OK); |
3397 for_scope->set_start_position(scanner()->location().beg_pos); | 3391 for_scope->set_start_position(scanner()->location().beg_pos); |
3398 bool is_let_identifier_expression = false; | 3392 bool is_let_identifier_expression = false; |
3399 if (peek() != Token::SEMICOLON) { | 3393 if (peek() != Token::SEMICOLON) { |
3400 if (peek() == Token::VAR || | 3394 if (peek() == Token::VAR || |
3401 (peek() == Token::CONST && is_sloppy(language_mode()))) { | 3395 (peek() == Token::CONST && is_sloppy(language_mode()))) { |
3402 const AstRawString* name = NULL; | 3396 DeclarationParsingResult parsing_result; |
3403 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); | 3397 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); |
3404 Scanner::Location bindings_loc = Scanner::Location::invalid(); | 3398 Block* variable_statement = |
3405 int num_decl; | 3399 factory()->NewBlock(NULL, 1, true, parsing_result.decl.pos); |
3406 Block* variable_statement = ParseVariableDeclarations( | 3400 |
3407 kForStatement, &num_decl, nullptr, &name, &first_initializer_loc, | 3401 for (auto declaration : parsing_result.declarations) { |
3408 &bindings_loc, CHECK_OK); | 3402 declaration.pattern.DeclareAndInitializeVariables( |
3403 variable_statement, &parsing_result.decl, declaration.initializer, | |
3404 nullptr, CHECK_OK); | |
3405 } | |
3406 | |
3407 int num_decl = parsing_result.declarations.length(); | |
3409 bool accept_IN = num_decl >= 1; | 3408 bool accept_IN = num_decl >= 1; |
3410 bool accept_OF = true; | 3409 bool accept_OF = true; |
3411 ForEachStatement::VisitMode mode; | 3410 ForEachStatement::VisitMode mode; |
3412 int each_beg_pos = scanner()->location().beg_pos; | 3411 int each_beg_pos = scanner()->location().beg_pos; |
3413 int each_end_pos = scanner()->location().end_pos; | 3412 int each_end_pos = scanner()->location().end_pos; |
3414 | 3413 |
3415 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { | 3414 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { |
3416 if (!*ok) return nullptr; | 3415 if (!*ok) return nullptr; |
3417 if (num_decl != 1) { | 3416 if (num_decl != 1) { |
3418 const char* loop_type = | 3417 const char* loop_type = |
3419 mode == ForEachStatement::ITERATE ? "for-of" : "for-in"; | 3418 mode == ForEachStatement::ITERATE ? "for-of" : "for-in"; |
3420 ParserTraits::ReportMessageAt( | 3419 ParserTraits::ReportMessageAt(parsing_result.bindings_loc, |
3421 bindings_loc, "for_inof_loop_multi_bindings", loop_type); | 3420 "for_inof_loop_multi_bindings", |
3421 loop_type); | |
3422 *ok = false; | 3422 *ok = false; |
3423 return nullptr; | 3423 return nullptr; |
3424 } | 3424 } |
3425 if (first_initializer_loc.IsValid() && | 3425 if (parsing_result.first_initializer_loc.IsValid() && |
3426 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { | 3426 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { |
3427 if (mode == ForEachStatement::ITERATE) { | 3427 if (mode == ForEachStatement::ITERATE) { |
3428 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer"); | 3428 ReportMessageAt(parsing_result.first_initializer_loc, |
3429 "for_of_loop_initializer"); | |
3429 } else { | 3430 } else { |
3430 // TODO(caitp): This should be an error in sloppy mode too. | 3431 // TODO(caitp): This should be an error in sloppy mode too. |
3431 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer"); | 3432 ReportMessageAt(parsing_result.first_initializer_loc, |
3433 "for_in_loop_initializer"); | |
3432 } | 3434 } |
3433 *ok = false; | 3435 *ok = false; |
3434 return nullptr; | 3436 return nullptr; |
3435 } | 3437 } |
3436 ForEachStatement* loop = | 3438 ForEachStatement* loop = |
3437 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3439 factory()->NewForEachStatement(mode, labels, stmt_pos); |
3438 Target target(&this->target_stack_, loop); | 3440 Target target(&this->target_stack_, loop); |
3439 | 3441 |
3440 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3442 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3441 Expect(Token::RPAREN, CHECK_OK); | 3443 Expect(Token::RPAREN, CHECK_OK); |
3442 | 3444 |
3443 VariableProxy* each = scope_->NewUnresolved( | 3445 VariableProxy* each = |
3444 factory(), name, Variable::NORMAL, each_beg_pos, each_end_pos); | 3446 scope_->NewUnresolved(factory(), parsing_result.out, |
3447 Variable::NORMAL, each_beg_pos, each_end_pos); | |
3445 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3448 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
3446 InitializeForEachStatement(loop, each, enumerable, body); | 3449 InitializeForEachStatement(loop, each, enumerable, body); |
3447 Block* result = | 3450 Block* result = |
3448 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); | 3451 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); |
3449 result->AddStatement(variable_statement, zone()); | 3452 result->AddStatement(variable_statement, zone()); |
3450 result->AddStatement(loop, zone()); | 3453 result->AddStatement(loop, zone()); |
3451 scope_ = saved_scope; | 3454 scope_ = saved_scope; |
3452 for_scope->set_end_position(scanner()->location().end_pos); | 3455 for_scope->set_end_position(scanner()->location().end_pos); |
3453 for_scope = for_scope->FinalizeBlockScope(); | 3456 for_scope = for_scope->FinalizeBlockScope(); |
3454 DCHECK(for_scope == NULL); | 3457 DCHECK(for_scope == NULL); |
3455 // Parsed for-in loop w/ variable/const declaration. | 3458 // Parsed for-in loop w/ variable/const declaration. |
3456 return result; | 3459 return result; |
3457 } else { | 3460 } else { |
3458 init = variable_statement; | 3461 init = variable_statement; |
3459 } | 3462 } |
3460 } else if ((peek() == Token::LET || peek() == Token::CONST) && | 3463 } else if ((peek() == Token::LET || peek() == Token::CONST) && |
3461 is_strict(language_mode())) { | 3464 is_strict(language_mode())) { |
3462 is_const = peek() == Token::CONST; | 3465 is_const = peek() == Token::CONST; |
3463 const AstRawString* name = NULL; | 3466 DeclarationParsingResult parsing_result; |
3464 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); | 3467 |
3465 Scanner::Location bindings_loc = Scanner::Location::invalid(); | 3468 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); |
arv (Not doing code reviews)
2015/05/13 16:29:29
Can this code be shared with the sloppy branch?
Dmitry Lomov (no reviews)
2015/05/14 16:28:00
Maybe in the next CL; I shared some.
| |
3466 int num_decl; | 3469 Block* variable_statement = |
3467 Block* variable_statement = ParseVariableDeclarations( | 3470 factory()->NewBlock(NULL, 1, true, parsing_result.decl.pos); |
3468 kForStatement, &num_decl, &lexical_bindings, &name, | 3471 DCHECK(parsing_result.decl.pos != RelocInfo::kNoPosition); |
3469 &first_initializer_loc, &bindings_loc, CHECK_OK); | 3472 |
3473 for (auto declaration : parsing_result.declarations) { | |
3474 declaration.pattern.DeclareAndInitializeVariables( | |
3475 variable_statement, &parsing_result.decl, declaration.initializer, | |
3476 &lexical_bindings, CHECK_OK); | |
3477 } | |
3478 int num_decl = parsing_result.declarations.length(); | |
3470 bool accept_IN = num_decl >= 1; | 3479 bool accept_IN = num_decl >= 1; |
3471 bool accept_OF = true; | 3480 bool accept_OF = true; |
3472 ForEachStatement::VisitMode mode; | 3481 ForEachStatement::VisitMode mode; |
3473 int each_beg_pos = scanner()->location().beg_pos; | 3482 int each_beg_pos = scanner()->location().beg_pos; |
3474 int each_end_pos = scanner()->location().end_pos; | 3483 int each_end_pos = scanner()->location().end_pos; |
3475 | 3484 |
3476 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { | 3485 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { |
3477 if (!*ok) return nullptr; | 3486 if (!*ok) return nullptr; |
3478 if (num_decl != 1) { | 3487 if (num_decl != 1) { |
3479 const char* loop_type = | 3488 const char* loop_type = |
3480 mode == ForEachStatement::ITERATE ? "for-of" : "for-in"; | 3489 mode == ForEachStatement::ITERATE ? "for-of" : "for-in"; |
3481 ParserTraits::ReportMessageAt( | 3490 ParserTraits::ReportMessageAt(parsing_result.bindings_loc, |
3482 bindings_loc, "for_inof_loop_multi_bindings", loop_type); | 3491 "for_inof_loop_multi_bindings", |
3492 loop_type); | |
3483 *ok = false; | 3493 *ok = false; |
3484 return nullptr; | 3494 return nullptr; |
3485 } | 3495 } |
3486 if (first_initializer_loc.IsValid() && | 3496 if (parsing_result.first_initializer_loc.IsValid() && |
3487 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { | 3497 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { |
3488 if (mode == ForEachStatement::ITERATE) { | 3498 if (mode == ForEachStatement::ITERATE) { |
3489 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer"); | 3499 ReportMessageAt(parsing_result.first_initializer_loc, |
3500 "for_of_loop_initializer"); | |
3490 } else { | 3501 } else { |
3491 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer"); | 3502 ReportMessageAt(parsing_result.first_initializer_loc, |
3503 "for_in_loop_initializer"); | |
3492 } | 3504 } |
3493 *ok = false; | 3505 *ok = false; |
3494 return nullptr; | 3506 return nullptr; |
3495 } | 3507 } |
3496 // Rewrite a for-in statement of the form | 3508 // Rewrite a for-in statement of the form |
3497 // | 3509 // |
3498 // for (let/const x in e) b | 3510 // for (let/const x in e) b |
3499 // | 3511 // |
3500 // into | 3512 // into |
3501 // | 3513 // |
(...skipping 13 matching lines...) Expand all Loading... | |
3515 ForEachStatement* loop = | 3527 ForEachStatement* loop = |
3516 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3528 factory()->NewForEachStatement(mode, labels, stmt_pos); |
3517 Target target(&this->target_stack_, loop); | 3529 Target target(&this->target_stack_, loop); |
3518 | 3530 |
3519 // The expression does not see the loop variable. | 3531 // The expression does not see the loop variable. |
3520 scope_ = saved_scope; | 3532 scope_ = saved_scope; |
3521 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3533 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3522 scope_ = for_scope; | 3534 scope_ = for_scope; |
3523 Expect(Token::RPAREN, CHECK_OK); | 3535 Expect(Token::RPAREN, CHECK_OK); |
3524 | 3536 |
3525 VariableProxy* each = scope_->NewUnresolved( | 3537 VariableProxy* each = |
3526 factory(), name, Variable::NORMAL, each_beg_pos, each_end_pos); | 3538 scope_->NewUnresolved(factory(), parsing_result.out, |
3539 Variable::NORMAL, each_beg_pos, each_end_pos); | |
3527 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3540 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
3528 Block* body_block = | 3541 Block* body_block = |
3529 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); | 3542 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
3530 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; | 3543 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; |
3531 Assignment* assignment = factory()->NewAssignment( | 3544 Assignment* assignment = factory()->NewAssignment( |
3532 init_op, each, temp_proxy, RelocInfo::kNoPosition); | 3545 init_op, each, temp_proxy, RelocInfo::kNoPosition); |
3533 Statement* assignment_statement = factory()->NewExpressionStatement( | 3546 Statement* assignment_statement = factory()->NewExpressionStatement( |
3534 assignment, RelocInfo::kNoPosition); | 3547 assignment, RelocInfo::kNoPosition); |
3535 body_block->AddStatement(variable_statement, zone()); | 3548 body_block->AddStatement(variable_statement, zone()); |
3536 body_block->AddStatement(assignment_statement, zone()); | 3549 body_block->AddStatement(assignment_statement, zone()); |
(...skipping 2238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5775 | 5788 |
5776 Expression* Parser::SpreadCallNew(Expression* function, | 5789 Expression* Parser::SpreadCallNew(Expression* function, |
5777 ZoneList<v8::internal::Expression*>* args, | 5790 ZoneList<v8::internal::Expression*>* args, |
5778 int pos) { | 5791 int pos) { |
5779 args->InsertAt(0, function, zone()); | 5792 args->InsertAt(0, function, zone()); |
5780 | 5793 |
5781 return factory()->NewCallRuntime( | 5794 return factory()->NewCallRuntime( |
5782 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5795 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
5783 } | 5796 } |
5784 } } // namespace v8::internal | 5797 } } // namespace v8::internal |
OLD | NEW |