OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1624 } | 1624 } |
1625 | 1625 |
1626 | 1626 |
1627 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, | 1627 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
1628 bool* ok) { | 1628 bool* ok) { |
1629 // VariableStatement :: | 1629 // VariableStatement :: |
1630 // VariableDeclarations ';' | 1630 // VariableDeclarations ';' |
1631 | 1631 |
1632 Handle<String> ignore; | 1632 Handle<String> ignore; |
1633 Block* result = ParseVariableDeclarations(var_context, | 1633 Block* result = ParseVariableDeclarations(var_context, |
1634 NULL, | |
1634 &ignore, | 1635 &ignore, |
1635 CHECK_OK); | 1636 CHECK_OK); |
1636 ExpectSemicolon(CHECK_OK); | 1637 ExpectSemicolon(CHECK_OK); |
1637 return result; | 1638 return result; |
1638 } | 1639 } |
1639 | 1640 |
1640 | 1641 |
1641 bool Parser::IsEvalOrArguments(Handle<String> string) { | 1642 bool Parser::IsEvalOrArguments(Handle<String> string) { |
1642 return string.is_identical_to(isolate()->factory()->eval_symbol()) || | 1643 return string.is_identical_to(isolate()->factory()->eval_symbol()) || |
1643 string.is_identical_to(isolate()->factory()->arguments_symbol()); | 1644 string.is_identical_to(isolate()->factory()->arguments_symbol()); |
1644 } | 1645 } |
1645 | 1646 |
1646 | 1647 |
1647 // If the variable declaration declares exactly one non-const | 1648 // If the variable declaration declares exactly one non-const |
1648 // variable, then *var is set to that variable. In all other cases, | 1649 // variable, then *var is set to that variable. In all other cases, |
1649 // *var is untouched; in particular, it is the caller's responsibility | 1650 // *var is untouched; in particular, it is the caller's responsibility |
1650 // to initialize it properly. This mechanism is used for the parsing | 1651 // to initialize it properly. This mechanism is used for the parsing |
1651 // of 'for-in' loops. | 1652 // of 'for-in' loops. |
1652 Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, | 1653 Block* Parser::ParseVariableDeclarations( |
1653 Handle<String>* out, | 1654 VariableDeclarationContext var_context, |
1654 bool* ok) { | 1655 VariableDeclarationProperties* decl_props, |
1656 Handle<String>* out, | |
1657 bool* ok) { | |
1655 // VariableDeclarations :: | 1658 // VariableDeclarations :: |
1656 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 1659 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
1657 | 1660 |
1658 VariableMode mode = VAR; | 1661 VariableMode mode = VAR; |
1659 // True if the binding needs initialization. 'let' and 'const' declared | 1662 // True if the binding needs initialization. 'let' and 'const' declared |
1660 // bindings are created uninitialized by their declaration nodes and | 1663 // bindings are created uninitialized by their declaration nodes and |
1661 // need initialization. 'var' declared bindings are always initialized | 1664 // need initialization. 'var' declared bindings are always initialized |
1662 // immediately by their declaration nodes. | 1665 // immediately by their declaration nodes. |
1663 bool needs_init = false; | 1666 bool needs_init = false; |
1664 bool is_const = false; | 1667 bool is_const = false; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1782 position = scanner().location().beg_pos; | 1785 position = scanner().location().beg_pos; |
1783 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); | 1786 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
1784 // Don't infer if it is "a = function(){...}();"-like expression. | 1787 // Don't infer if it is "a = function(){...}();"-like expression. |
1785 if (fni_ != NULL && | 1788 if (fni_ != NULL && |
1786 value->AsCall() == NULL && | 1789 value->AsCall() == NULL && |
1787 value->AsCallNew() == NULL) { | 1790 value->AsCallNew() == NULL) { |
1788 fni_->Infer(); | 1791 fni_->Infer(); |
1789 } else { | 1792 } else { |
1790 fni_->RemoveLastFunction(); | 1793 fni_->RemoveLastFunction(); |
1791 } | 1794 } |
1795 if (decl_props != NULL) *decl_props = kHasInitializers; | |
1792 } | 1796 } |
1793 | 1797 |
1794 // Make sure that 'const x' and 'let x' initialize 'x' to undefined. | 1798 // Make sure that 'const x' and 'let x' initialize 'x' to undefined. |
1795 if (value == NULL && needs_init) { | 1799 if (value == NULL && needs_init) { |
1796 value = GetLiteralUndefined(); | 1800 value = GetLiteralUndefined(); |
1797 } | 1801 } |
1798 | 1802 |
1799 // Global variable declarations must be compiled in a specific | 1803 // Global variable declarations must be compiled in a specific |
1800 // way. When the script containing the global variable declaration | 1804 // way. When the script containing the global variable declaration |
1801 // is entered, the global variable must be declared, so that if it | 1805 // is entered, the global variable must be declared, so that if it |
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2362 return loop; | 2366 return loop; |
2363 } | 2367 } |
2364 | 2368 |
2365 | 2369 |
2366 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { | 2370 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
2367 // ForStatement :: | 2371 // ForStatement :: |
2368 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 2372 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
2369 | 2373 |
2370 Statement* init = NULL; | 2374 Statement* init = NULL; |
2371 | 2375 |
2376 // Create an in-between scope for let-bound iteration variables. | |
2377 Scope* saved_scope = top_scope_; | |
2378 Scope* for_scope = NewScope(top_scope_, Scope::BLOCK_SCOPE); | |
2379 if (top_scope_->is_strict_mode()) { | |
2380 for_scope->EnableStrictMode(); | |
2381 } | |
2382 top_scope_ = for_scope; | |
2383 | |
2372 Expect(Token::FOR, CHECK_OK); | 2384 Expect(Token::FOR, CHECK_OK); |
2373 Expect(Token::LPAREN, CHECK_OK); | 2385 Expect(Token::LPAREN, CHECK_OK); |
2374 if (peek() != Token::SEMICOLON) { | 2386 if (peek() != Token::SEMICOLON) { |
2375 if (peek() == Token::VAR || peek() == Token::CONST) { | 2387 if (peek() == Token::VAR || peek() == Token::CONST) { |
2376 Handle<String> name; | 2388 Handle<String> name; |
2377 Block* variable_statement = | 2389 Block* variable_statement = |
2378 ParseVariableDeclarations(kForStatement, &name, CHECK_OK); | 2390 ParseVariableDeclarations(kForStatement, NULL, &name, CHECK_OK); |
2379 | 2391 |
2380 if (peek() == Token::IN && !name.is_null()) { | 2392 if (peek() == Token::IN && !name.is_null()) { |
2381 VariableProxy* each = top_scope_->NewUnresolved(name); | 2393 VariableProxy* each = top_scope_->NewUnresolved(name); |
2382 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels); | 2394 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels); |
2383 Target target(&this->target_stack_, loop); | 2395 Target target(&this->target_stack_, loop); |
2384 | 2396 |
2385 Expect(Token::IN, CHECK_OK); | 2397 Expect(Token::IN, CHECK_OK); |
2386 Expression* enumerable = ParseExpression(true, CHECK_OK); | 2398 Expression* enumerable = ParseExpression(true, CHECK_OK); |
2387 Expect(Token::RPAREN, CHECK_OK); | 2399 Expect(Token::RPAREN, CHECK_OK); |
2388 | 2400 |
2389 Statement* body = ParseStatement(NULL, CHECK_OK); | 2401 Statement* body = ParseStatement(NULL, CHECK_OK); |
2390 loop->Initialize(each, enumerable, body); | 2402 loop->Initialize(each, enumerable, body); |
2391 Block* result = new(zone()) Block(isolate(), NULL, 2, false); | 2403 Block* result = new(zone()) Block(isolate(), NULL, 2, false); |
2392 result->AddStatement(variable_statement); | 2404 result->AddStatement(variable_statement); |
2393 result->AddStatement(loop); | 2405 result->AddStatement(loop); |
2406 top_scope_ = saved_scope; | |
2407 for_scope = for_scope->FinalizeBlockScope(); | |
2408 ASSERT(for_scope == NULL); | |
2394 // Parsed for-in loop w/ variable/const declaration. | 2409 // Parsed for-in loop w/ variable/const declaration. |
2395 return result; | 2410 return result; |
2396 } else { | 2411 } else { |
2397 init = variable_statement; | 2412 init = variable_statement; |
2398 } | 2413 } |
2414 } else if (peek() == Token::LET) { | |
2415 Handle<String> name; | |
2416 VariableDeclarationProperties decl_props = kHasNoInitializers; | |
2417 Block* variable_statement = | |
2418 ParseVariableDeclarations(kForStatement, | |
2419 &decl_props, | |
2420 &name, | |
2421 CHECK_OK); | |
2422 bool accept_IN = !name.is_null() && decl_props != kHasInitializers; | |
2423 if (peek() == Token::IN && accept_IN) { | |
2424 // Rewrite a for-in statement of the form | |
2425 // | |
2426 // for (let x in e) b | |
2427 // | |
2428 // into | |
2429 // | |
2430 // <let x' be a temporary variable> | |
2431 // for (x' in e) { | |
2432 // let x; | |
2433 // x = x'; | |
2434 // b; | |
2435 // } | |
2399 | 2436 |
2437 // TODO(keuchel): move temporary variable to block scope | |
Lasse Reichstein
2011/10/17 11:49:40
What does this mean? Is the current code not corre
Steven
2011/10/17 12:18:29
This is an optimization. TEMPORARY variables are a
| |
2438 Variable* temp = top_scope_->DeclarationScope()->NewTemporary(name); | |
2439 VariableProxy* temp_proxy = new(zone()) VariableProxy(isolate(), temp); | |
2440 VariableProxy* each = top_scope_->NewUnresolved(name, inside_with()); | |
2441 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels); | |
2442 Target target(&this->target_stack_, loop); | |
2443 | |
2444 Expect(Token::IN, CHECK_OK); | |
2445 Expression* enumerable = ParseExpression(true, CHECK_OK); | |
2446 Expect(Token::RPAREN, CHECK_OK); | |
2447 | |
2448 Statement* body = ParseStatement(NULL, CHECK_OK); | |
2449 Block* body_block = new(zone()) Block(isolate(), NULL, 3, false); | |
2450 Assignment* assignment = new(zone()) Assignment(isolate(), | |
2451 Token::ASSIGN, | |
2452 each, | |
2453 temp_proxy, | |
2454 RelocInfo::kNoPosition); | |
2455 Statement* assignment_statement = | |
2456 new(zone()) ExpressionStatement(assignment); | |
2457 body_block->AddStatement(variable_statement); | |
2458 body_block->AddStatement(assignment_statement); | |
2459 body_block->AddStatement(body); | |
2460 loop->Initialize(temp_proxy, enumerable, body_block); | |
2461 top_scope_ = saved_scope; | |
2462 for_scope = for_scope->FinalizeBlockScope(); | |
2463 body_block->set_block_scope(for_scope); | |
2464 // Parsed for-in loop w/ let declaration. | |
2465 return loop; | |
2466 | |
2467 } else { | |
2468 init = variable_statement; | |
2469 } | |
2400 } else { | 2470 } else { |
2401 Expression* expression = ParseExpression(false, CHECK_OK); | 2471 Expression* expression = ParseExpression(false, CHECK_OK); |
2402 if (peek() == Token::IN) { | 2472 if (peek() == Token::IN) { |
2403 // Signal a reference error if the expression is an invalid | 2473 // Signal a reference error if the expression is an invalid |
2404 // left-hand side expression. We could report this as a syntax | 2474 // left-hand side expression. We could report this as a syntax |
2405 // error here but for compatibility with JSC we choose to report | 2475 // error here but for compatibility with JSC we choose to report |
2406 // the error at runtime. | 2476 // the error at runtime. |
2407 if (expression == NULL || !expression->IsValidLeftHandSide()) { | 2477 if (expression == NULL || !expression->IsValidLeftHandSide()) { |
2408 Handle<String> type = | 2478 Handle<String> type = |
2409 isolate()->factory()->invalid_lhs_in_for_in_symbol(); | 2479 isolate()->factory()->invalid_lhs_in_for_in_symbol(); |
2410 expression = NewThrowReferenceError(type); | 2480 expression = NewThrowReferenceError(type); |
2411 } | 2481 } |
2412 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels); | 2482 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels); |
2413 Target target(&this->target_stack_, loop); | 2483 Target target(&this->target_stack_, loop); |
2414 | 2484 |
2415 Expect(Token::IN, CHECK_OK); | 2485 Expect(Token::IN, CHECK_OK); |
2416 Expression* enumerable = ParseExpression(true, CHECK_OK); | 2486 Expression* enumerable = ParseExpression(true, CHECK_OK); |
2417 Expect(Token::RPAREN, CHECK_OK); | 2487 Expect(Token::RPAREN, CHECK_OK); |
2418 | 2488 |
2419 Statement* body = ParseStatement(NULL, CHECK_OK); | 2489 Statement* body = ParseStatement(NULL, CHECK_OK); |
2420 if (loop) loop->Initialize(expression, enumerable, body); | 2490 if (loop) loop->Initialize(expression, enumerable, body); |
2491 top_scope_ = saved_scope; | |
2492 for_scope = for_scope->FinalizeBlockScope(); | |
2493 ASSERT(for_scope == NULL); | |
2421 // Parsed for-in loop. | 2494 // Parsed for-in loop. |
2422 return loop; | 2495 return loop; |
2423 | 2496 |
2424 } else { | 2497 } else { |
2425 init = new(zone()) ExpressionStatement(expression); | 2498 init = new(zone()) ExpressionStatement(expression); |
2426 } | 2499 } |
2427 } | 2500 } |
2428 } | 2501 } |
2429 | 2502 |
2430 // Standard 'for' loop | 2503 // Standard 'for' loop |
(...skipping 10 matching lines...) Expand all Loading... | |
2441 Expect(Token::SEMICOLON, CHECK_OK); | 2514 Expect(Token::SEMICOLON, CHECK_OK); |
2442 | 2515 |
2443 Statement* next = NULL; | 2516 Statement* next = NULL; |
2444 if (peek() != Token::RPAREN) { | 2517 if (peek() != Token::RPAREN) { |
2445 Expression* exp = ParseExpression(true, CHECK_OK); | 2518 Expression* exp = ParseExpression(true, CHECK_OK); |
2446 next = new(zone()) ExpressionStatement(exp); | 2519 next = new(zone()) ExpressionStatement(exp); |
2447 } | 2520 } |
2448 Expect(Token::RPAREN, CHECK_OK); | 2521 Expect(Token::RPAREN, CHECK_OK); |
2449 | 2522 |
2450 Statement* body = ParseStatement(NULL, CHECK_OK); | 2523 Statement* body = ParseStatement(NULL, CHECK_OK); |
2451 if (loop) loop->Initialize(init, cond, next, body); | 2524 top_scope_ = saved_scope; |
2452 return loop; | 2525 for_scope = for_scope->FinalizeBlockScope(); |
2526 if (for_scope != NULL) { | |
2527 // Rewrite a for statement of the form | |
2528 // | |
2529 // for (let x = i; c; n) b | |
2530 // | |
2531 // into | |
2532 // | |
2533 // { | |
2534 // let x = i; | |
2535 // for (; c; n) b | |
2536 // } | |
2537 ASSERT(init != NULL); | |
2538 Block* result = new(zone()) Block(isolate(), NULL, 2, false); | |
2539 result->AddStatement(init); | |
2540 result->AddStatement(loop); | |
2541 result->set_block_scope(for_scope); | |
2542 if (loop) loop->Initialize(NULL, cond, next, body); | |
2543 return result; | |
2544 } else { | |
2545 if (loop) loop->Initialize(init, cond, next, body); | |
2546 return loop; | |
2547 } | |
2453 } | 2548 } |
2454 | 2549 |
2455 | 2550 |
2456 // Precedence = 1 | 2551 // Precedence = 1 |
2457 Expression* Parser::ParseExpression(bool accept_IN, bool* ok) { | 2552 Expression* Parser::ParseExpression(bool accept_IN, bool* ok) { |
2458 // Expression :: | 2553 // Expression :: |
2459 // AssignmentExpression | 2554 // AssignmentExpression |
2460 // Expression ',' AssignmentExpression | 2555 // Expression ',' AssignmentExpression |
2461 | 2556 |
2462 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK); | 2557 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK); |
(...skipping 2767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5230 result = parser.ParseProgram(source, | 5325 result = parser.ParseProgram(source, |
5231 info->is_global(), | 5326 info->is_global(), |
5232 info->StrictMode()); | 5327 info->StrictMode()); |
5233 } | 5328 } |
5234 } | 5329 } |
5235 info->SetFunction(result); | 5330 info->SetFunction(result); |
5236 return (result != NULL); | 5331 return (result != NULL); |
5237 } | 5332 } |
5238 | 5333 |
5239 } } // namespace v8::internal | 5334 } } // namespace v8::internal |
OLD | NEW |