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