Chromium Code Reviews| 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 |