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

Side by Side Diff: src/parser.cc

Issue 977543002: [es6] Fix for-const loops (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
(...skipping 2987 matching lines...) Expand 10 before | Expand all | Expand 10 after
2998 assign_iterator, 2998 assign_iterator,
2999 next_result, 2999 next_result,
3000 result_done, 3000 result_done,
3001 assign_each); 3001 assign_each);
3002 } else { 3002 } else {
3003 stmt->Initialize(each, subject, body); 3003 stmt->Initialize(each, subject, body);
3004 } 3004 }
3005 } 3005 }
3006 3006
3007 3007
3008 Statement* Parser::DesugarLetBindingsInForStatement( 3008 Statement* Parser::DesugarLexicalBindingsInForStatement(
3009 Scope* inner_scope, ZoneList<const AstRawString*>* names, 3009 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names,
3010 ForStatement* loop, Statement* init, Expression* cond, Statement* next, 3010 ForStatement* loop, Statement* init, Expression* cond, Statement* next,
3011 Statement* body, bool* ok) { 3011 Statement* body, bool* ok) {
3012 // ES6 13.6.3.4 specifies that on each loop iteration the let variables are 3012 // ES6 13.6.3.4 specifies that on each loop iteration the let variables are
3013 // copied into a new environment. After copying, the "next" statement of the 3013 // copied into a new environment. After copying, the "next" statement of the
3014 // loop is executed to update the loop variables. The loop condition is 3014 // loop is executed to update the loop variables. The loop condition is
3015 // checked and the loop body is executed. 3015 // checked and the loop body is executed.
3016 // 3016 //
3017 // We rewrite a for statement of the form 3017 // We rewrite a for statement of the form
3018 // 3018 //
3019 // labels: for (let x = i; cond; next) body 3019 // labels: for (let/const x = i; cond; next) body
3020 // 3020 //
3021 // into 3021 // into
3022 // 3022 //
3023 // { 3023 // {
3024 // let x = i; 3024 // let/const x = i;
3025 // temp_x = x; 3025 // temp_x = x;
3026 // first = 1; 3026 // first = 1;
3027 // outer: for (;;) { 3027 // outer: for (;;) {
3028 // let x = temp_x; 3028 // let/const x = temp_x;
3029 // if (first == 1) { 3029 // if (first == 1) {
3030 // first = 0; 3030 // first = 0;
3031 // } else { 3031 // } else {
3032 // next; 3032 // next;
3033 // } 3033 // }
3034 // flag = 1; 3034 // flag = 1;
3035 // labels: for (; flag == 1; flag = 0, temp_x = x) { 3035 // labels: for (; flag == 1; flag = 0, temp_x = x) {
3036 // if (cond) { 3036 // if (cond) {
3037 // body 3037 // body
3038 // } else { 3038 // } else {
3039 // break outer; 3039 // break outer;
3040 // } 3040 // }
3041 // } 3041 // }
3042 // if (flag == 1) { 3042 // if (flag == 1) {
3043 // break; 3043 // break;
3044 // } 3044 // }
3045 // } 3045 // }
3046 // } 3046 // }
3047 3047
3048 DCHECK(names->length() > 0); 3048 DCHECK(names->length() > 0);
3049 Scope* for_scope = scope_; 3049 Scope* for_scope = scope_;
3050 ZoneList<Variable*> temps(names->length(), zone()); 3050 ZoneList<Variable*> temps(names->length(), zone());
3051 3051
3052 Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false, 3052 Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false,
3053 RelocInfo::kNoPosition); 3053 RelocInfo::kNoPosition);
3054 3054
3055 // Add statement: let x = i. 3055 // Add statement: let/const x = i.
3056 outer_block->AddStatement(init, zone()); 3056 outer_block->AddStatement(init, zone());
3057 3057
3058 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); 3058 const AstRawString* temp_name = ast_value_factory()->dot_for_string();
3059 3059
3060 // For each let variable x: 3060 // For each lexical variable x:
3061 // make statement: temp_x = x. 3061 // make statement: temp_x = x.
3062 for (int i = 0; i < names->length(); i++) { 3062 for (int i = 0; i < names->length(); i++) {
3063 VariableProxy* proxy = NewUnresolved(names->at(i), LET); 3063 VariableProxy* proxy = NewUnresolved(names->at(i), LET);
3064 Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name); 3064 Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name);
3065 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); 3065 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3066 Assignment* assignment = factory()->NewAssignment( 3066 Assignment* assignment = factory()->NewAssignment(
3067 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); 3067 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
3068 Statement* assignment_statement = factory()->NewExpressionStatement( 3068 Statement* assignment_statement = factory()->NewExpressionStatement(
3069 assignment, RelocInfo::kNoPosition); 3069 assignment, RelocInfo::kNoPosition);
3070 outer_block->AddStatement(assignment_statement, zone()); 3070 outer_block->AddStatement(assignment_statement, zone());
(...skipping 24 matching lines...) Expand all
3095 3095
3096 outer_block->set_scope(for_scope); 3096 outer_block->set_scope(for_scope);
3097 scope_ = inner_scope; 3097 scope_ = inner_scope;
3098 3098
3099 Block* inner_block = factory()->NewBlock(NULL, names->length() + 4, false, 3099 Block* inner_block = factory()->NewBlock(NULL, names->length() + 4, false,
3100 RelocInfo::kNoPosition); 3100 RelocInfo::kNoPosition);
3101 int pos = scanner()->location().beg_pos; 3101 int pos = scanner()->location().beg_pos;
3102 ZoneList<Variable*> inner_vars(names->length(), zone()); 3102 ZoneList<Variable*> inner_vars(names->length(), zone());
3103 3103
3104 // For each let variable x: 3104 // For each let variable x:
3105 // make statement: let x = temp_x. 3105 // make statement: let/const x = temp_x.
3106 VariableMode mode = is_const ? CONST : LET;
3106 for (int i = 0; i < names->length(); i++) { 3107 for (int i = 0; i < names->length(); i++) {
3107 VariableProxy* proxy = NewUnresolved(names->at(i), LET); 3108 VariableProxy* proxy = NewUnresolved(names->at(i), mode);
3108 Declaration* declaration = factory()->NewVariableDeclaration( 3109 Declaration* declaration = factory()->NewVariableDeclaration(
3109 proxy, LET, scope_, RelocInfo::kNoPosition); 3110 proxy, mode, scope_, RelocInfo::kNoPosition);
3110 Declare(declaration, true, CHECK_OK); 3111 Declare(declaration, true, CHECK_OK);
3111 inner_vars.Add(declaration->proxy()->var(), zone()); 3112 inner_vars.Add(declaration->proxy()->var(), zone());
3112 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); 3113 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
3113 Assignment* assignment = factory()->NewAssignment( 3114 Assignment* assignment = factory()->NewAssignment(
3114 Token::INIT_LET, proxy, temp_proxy, pos); 3115 is_const ? Token::INIT_CONST : Token::INIT_LET, proxy, temp_proxy, pos);
3115 Statement* assignment_statement = 3116 Statement* assignment_statement =
3116 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); 3117 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3117 proxy->var()->set_initializer_position(init->position()); 3118 proxy->var()->set_initializer_position(init->position());
3118 inner_block->AddStatement(assignment_statement, zone()); 3119 inner_block->AddStatement(assignment_statement, zone());
3119 } 3120 }
3120 3121
3121 // Make statement: if (first == 1) { first = 0; } else { next; } 3122 // Make statement: if (first == 1) { first = 0; } else { next; }
3122 if (next) { 3123 if (next) {
3123 DCHECK(first); 3124 DCHECK(first);
3124 Expression* compare = NULL; 3125 Expression* compare = NULL;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
3233 return outer_block; 3234 return outer_block;
3234 } 3235 }
3235 3236
3236 3237
3237 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, 3238 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
3238 bool* ok) { 3239 bool* ok) {
3239 // ForStatement :: 3240 // ForStatement ::
3240 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement 3241 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
3241 3242
3242 int stmt_pos = peek_position(); 3243 int stmt_pos = peek_position();
3244 bool is_const = false;
3243 Statement* init = NULL; 3245 Statement* init = NULL;
3244 ZoneList<const AstRawString*> let_bindings(1, zone()); 3246 ZoneList<const AstRawString*> lexical_bindings(1, zone());
3245 3247
3246 // Create an in-between scope for let-bound iteration variables. 3248 // Create an in-between scope for let-bound iteration variables.
3247 Scope* saved_scope = scope_; 3249 Scope* saved_scope = scope_;
3248 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); 3250 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
3249 scope_ = for_scope; 3251 scope_ = for_scope;
3250 3252
3251 Expect(Token::FOR, CHECK_OK); 3253 Expect(Token::FOR, CHECK_OK);
3252 Expect(Token::LPAREN, CHECK_OK); 3254 Expect(Token::LPAREN, CHECK_OK);
3253 for_scope->set_start_position(scanner()->location().beg_pos); 3255 for_scope->set_start_position(scanner()->location().beg_pos);
3254 bool is_let_identifier_expression = false; 3256 bool is_let_identifier_expression = false;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3286 for_scope->set_end_position(scanner()->location().end_pos); 3288 for_scope->set_end_position(scanner()->location().end_pos);
3287 for_scope = for_scope->FinalizeBlockScope(); 3289 for_scope = for_scope->FinalizeBlockScope();
3288 DCHECK(for_scope == NULL); 3290 DCHECK(for_scope == NULL);
3289 // Parsed for-in loop w/ variable/const declaration. 3291 // Parsed for-in loop w/ variable/const declaration.
3290 return result; 3292 return result;
3291 } else { 3293 } else {
3292 init = variable_statement; 3294 init = variable_statement;
3293 } 3295 }
3294 } else if ((peek() == Token::LET || peek() == Token::CONST) && 3296 } else if ((peek() == Token::LET || peek() == Token::CONST) &&
3295 is_strict(language_mode())) { 3297 is_strict(language_mode())) {
3296 bool is_const = peek() == Token::CONST; 3298 is_const = peek() == Token::CONST;
3297 const AstRawString* name = NULL; 3299 const AstRawString* name = NULL;
3298 VariableDeclarationProperties decl_props = kHasNoInitializers; 3300 VariableDeclarationProperties decl_props = kHasNoInitializers;
3299 Block* variable_statement = 3301 Block* variable_statement =
3300 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, 3302 ParseVariableDeclarations(kForStatement, &decl_props,
3301 &name, CHECK_OK); 3303 &lexical_bindings, &name, CHECK_OK);
3302 bool accept_IN = name != NULL && decl_props != kHasInitializers; 3304 bool accept_IN = name != NULL && decl_props != kHasInitializers;
3303 bool accept_OF = decl_props == kHasNoInitializers; 3305 bool accept_OF = decl_props == kHasNoInitializers;
3304 ForEachStatement::VisitMode mode; 3306 ForEachStatement::VisitMode mode;
3305 int each_beg_pos = scanner()->location().beg_pos; 3307 int each_beg_pos = scanner()->location().beg_pos;
3306 int each_end_pos = scanner()->location().end_pos; 3308 int each_end_pos = scanner()->location().end_pos;
3307 3309
3308 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { 3310 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
3309 if (!*ok) return nullptr; 3311 if (!*ok) return nullptr;
3310 3312
3311 // Rewrite a for-in statement of the form 3313 // Rewrite a for-in statement of the form
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
3408 is_let_identifier_expression) { 3410 is_let_identifier_expression) {
3409 ReportMessage("sloppy_lexical", NULL); 3411 ReportMessage("sloppy_lexical", NULL);
3410 *ok = false; 3412 *ok = false;
3411 return NULL; 3413 return NULL;
3412 } 3414 }
3413 Expect(Token::SEMICOLON, CHECK_OK); 3415 Expect(Token::SEMICOLON, CHECK_OK);
3414 3416
3415 // If there are let bindings, then condition and the next statement of the 3417 // If there are let bindings, then condition and the next statement of the
3416 // for loop must be parsed in a new scope. 3418 // for loop must be parsed in a new scope.
3417 Scope* inner_scope = NULL; 3419 Scope* inner_scope = NULL;
3418 if (let_bindings.length() > 0) { 3420 if (lexical_bindings.length() > 0) {
3419 inner_scope = NewScope(for_scope, BLOCK_SCOPE); 3421 inner_scope = NewScope(for_scope, BLOCK_SCOPE);
3420 inner_scope->set_start_position(scanner()->location().beg_pos); 3422 inner_scope->set_start_position(scanner()->location().beg_pos);
3421 scope_ = inner_scope; 3423 scope_ = inner_scope;
3422 } 3424 }
3423 3425
3424 Expression* cond = NULL; 3426 Expression* cond = NULL;
3425 if (peek() != Token::SEMICOLON) { 3427 if (peek() != Token::SEMICOLON) {
3426 cond = ParseExpression(true, CHECK_OK); 3428 cond = ParseExpression(true, CHECK_OK);
3427 } 3429 }
3428 Expect(Token::SEMICOLON, CHECK_OK); 3430 Expect(Token::SEMICOLON, CHECK_OK);
3429 3431
3430 Statement* next = NULL; 3432 Statement* next = NULL;
3431 if (peek() != Token::RPAREN) { 3433 if (peek() != Token::RPAREN) {
3432 int next_pos = position(); 3434 int next_pos = position();
3433 Expression* exp = ParseExpression(true, CHECK_OK); 3435 Expression* exp = ParseExpression(true, CHECK_OK);
3434 next = factory()->NewExpressionStatement(exp, next_pos); 3436 next = factory()->NewExpressionStatement(exp, next_pos);
3435 } 3437 }
3436 Expect(Token::RPAREN, CHECK_OK); 3438 Expect(Token::RPAREN, CHECK_OK);
3437 3439
3438 Statement* body = ParseSubStatement(NULL, CHECK_OK); 3440 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3439 3441
3440 Statement* result = NULL; 3442 Statement* result = NULL;
3441 if (let_bindings.length() > 0) { 3443 if (lexical_bindings.length() > 0) {
3442 scope_ = for_scope; 3444 scope_ = for_scope;
3443 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, 3445 result = DesugarLexicalBindingsInForStatement(
3444 init, cond, next, body, CHECK_OK); 3446 inner_scope, is_const, &lexical_bindings, loop, init, cond,
3447 next, body, CHECK_OK);
3445 scope_ = saved_scope; 3448 scope_ = saved_scope;
3446 for_scope->set_end_position(scanner()->location().end_pos); 3449 for_scope->set_end_position(scanner()->location().end_pos);
3447 } else { 3450 } else {
3448 scope_ = saved_scope; 3451 scope_ = saved_scope;
3449 for_scope->set_end_position(scanner()->location().end_pos); 3452 for_scope->set_end_position(scanner()->location().end_pos);
3450 for_scope = for_scope->FinalizeBlockScope(); 3453 for_scope = for_scope->FinalizeBlockScope();
3451 if (for_scope) { 3454 if (for_scope) {
3452 // Rewrite a for statement of the form 3455 // Rewrite a for statement of the form
3453 // for (const x = i; c; n) b 3456 // for (const x = i; c; n) b
3454 // 3457 //
(...skipping 1988 matching lines...) Expand 10 before | Expand all | Expand 10 after
5443 } else { 5446 } else {
5444 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); 5447 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5445 running_hash = StringHasher::ComputeRunningHash(running_hash, data, 5448 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5446 raw_string->length()); 5449 raw_string->length());
5447 } 5450 }
5448 } 5451 }
5449 5452
5450 return running_hash; 5453 return running_hash;
5451 } 5454 }
5452 } } // namespace v8::internal 5455 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698