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

Side by Side Diff: src/parser.cc

Issue 672193002: Revert "harmony-scoping: Allow 'const' iteration variables in strict mode." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/preparser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2138 matching lines...) Expand 10 before | Expand all | Expand 10 after
2149 // We mark the block as initializer block because we don't want the 2149 // We mark the block as initializer block because we don't want the
2150 // rewriter to add a '.result' assignment to such a block (to get compliant 2150 // rewriter to add a '.result' assignment to such a block (to get compliant
2151 // behavior for code such as print(eval('var x = 7')), and for cosmetic 2151 // behavior for code such as print(eval('var x = 7')), and for cosmetic
2152 // reasons when pretty-printing. Also, unless an assignment (initialization) 2152 // reasons when pretty-printing. Also, unless an assignment (initialization)
2153 // is inside an initializer block, it is ignored. 2153 // is inside an initializer block, it is ignored.
2154 // 2154 //
2155 // Create new block with one expected declaration. 2155 // Create new block with one expected declaration.
2156 Block* block = factory()->NewBlock(NULL, 1, true, pos); 2156 Block* block = factory()->NewBlock(NULL, 1, true, pos);
2157 int nvars = 0; // the number of variables declared 2157 int nvars = 0; // the number of variables declared
2158 const AstRawString* name = NULL; 2158 const AstRawString* name = NULL;
2159 bool is_for_iteration_variable;
2160 do { 2159 do {
2161 if (fni_ != NULL) fni_->Enter(); 2160 if (fni_ != NULL) fni_->Enter();
2162 2161
2163 // Parse variable name. 2162 // Parse variable name.
2164 if (nvars > 0) Consume(Token::COMMA); 2163 if (nvars > 0) Consume(Token::COMMA);
2165 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 2164 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
2166 if (fni_ != NULL) fni_->PushVariableName(name); 2165 if (fni_ != NULL) fni_->PushVariableName(name);
2167 2166
2168 // Declare variable. 2167 // Declare variable.
2169 // Note that we *always* must treat the initial value via a separate init 2168 // Note that we *always* must treat the initial value via a separate init
2170 // assignment for variables and constants because the value must be assigned 2169 // assignment for variables and constants because the value must be assigned
2171 // when the variable is encountered in the source. But the variable/constant 2170 // when the variable is encountered in the source. But the variable/constant
2172 // is declared (and set to 'undefined') upon entering the function within 2171 // is declared (and set to 'undefined') upon entering the function within
2173 // which the variable or constant is declared. Only function variables have 2172 // which the variable or constant is declared. Only function variables have
2174 // an initial value in the declaration (because they are initialized upon 2173 // an initial value in the declaration (because they are initialized upon
2175 // entering the function). 2174 // entering the function).
2176 // 2175 //
2177 // If we have a const declaration, in an inner scope, the proxy is always 2176 // If we have a const declaration, in an inner scope, the proxy is always
2178 // bound to the declared variable (independent of possibly surrounding with 2177 // bound to the declared variable (independent of possibly surrounding with
2179 // statements). 2178 // statements).
2180 // For let/const declarations in harmony mode, we can also immediately 2179 // For let/const declarations in harmony mode, we can also immediately
2181 // pre-resolve the proxy because it resides in the same scope as the 2180 // pre-resolve the proxy because it resides in the same scope as the
2182 // declaration. 2181 // declaration.
2183 is_for_iteration_variable =
2184 var_context == kForStatement &&
2185 (peek() == Token::IN || PeekContextualKeyword(CStrVector("of")));
2186 if (is_for_iteration_variable && mode == CONST) {
2187 needs_init = false;
2188 }
2189
2190 Interface* interface = 2182 Interface* interface =
2191 is_const ? Interface::NewConst() : Interface::NewValue(); 2183 is_const ? Interface::NewConst() : Interface::NewValue();
2192 VariableProxy* proxy = NewUnresolved(name, mode, interface); 2184 VariableProxy* proxy = NewUnresolved(name, mode, interface);
2193 Declaration* declaration = 2185 Declaration* declaration =
2194 factory()->NewVariableDeclaration(proxy, mode, scope_, pos); 2186 factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
2195 Declare(declaration, mode != VAR, CHECK_OK); 2187 Declare(declaration, mode != VAR, CHECK_OK);
2196 nvars++; 2188 nvars++;
2197 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) { 2189 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
2198 ReportMessage("too_many_variables"); 2190 ReportMessage("too_many_variables");
2199 *ok = false; 2191 *ok = false;
(...skipping 25 matching lines...) Expand all
2225 // const c; c = x; 2217 // const c; c = x;
2226 // 2218 //
2227 // The "variable" c initialized to x is the same as the declared 2219 // The "variable" c initialized to x is the same as the declared
2228 // one - there is no re-lookup (see the last parameter of the 2220 // one - there is no re-lookup (see the last parameter of the
2229 // Declare() call above). 2221 // Declare() call above).
2230 2222
2231 Scope* initialization_scope = is_const ? declaration_scope : scope_; 2223 Scope* initialization_scope = is_const ? declaration_scope : scope_;
2232 Expression* value = NULL; 2224 Expression* value = NULL;
2233 int pos = -1; 2225 int pos = -1;
2234 // Harmony consts have non-optional initializers. 2226 // Harmony consts have non-optional initializers.
2235 if (peek() == Token::ASSIGN || 2227 if (peek() == Token::ASSIGN || mode == CONST) {
2236 (mode == CONST && !is_for_iteration_variable)) {
2237 Expect(Token::ASSIGN, CHECK_OK); 2228 Expect(Token::ASSIGN, CHECK_OK);
2238 pos = position(); 2229 pos = position();
2239 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); 2230 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
2240 // Don't infer if it is "a = function(){...}();"-like expression. 2231 // Don't infer if it is "a = function(){...}();"-like expression.
2241 if (fni_ != NULL && 2232 if (fni_ != NULL &&
2242 value->AsCall() == NULL && 2233 value->AsCall() == NULL &&
2243 value->AsCallNew() == NULL) { 2234 value->AsCallNew() == NULL) {
2244 fni_->Infer(); 2235 fni_->Infer();
2245 } else { 2236 } else {
2246 fni_->RemoveLastFunction(); 2237 fni_->RemoveLastFunction();
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
2359 block->AddStatement( 2350 block->AddStatement(
2360 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), 2351 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
2361 zone()); 2352 zone());
2362 } 2353 }
2363 2354
2364 if (fni_ != NULL) fni_->Leave(); 2355 if (fni_ != NULL) fni_->Leave();
2365 } while (peek() == Token::COMMA); 2356 } while (peek() == Token::COMMA);
2366 2357
2367 // If there was a single non-const declaration, return it in the output 2358 // If there was a single non-const declaration, return it in the output
2368 // parameter for possible use by for/in. 2359 // parameter for possible use by for/in.
2369 if (nvars == 1 && (!is_const || is_for_iteration_variable)) { 2360 if (nvars == 1 && !is_const) {
2370 *out = name; 2361 *out = name;
2371 } 2362 }
2372 2363
2373 return block; 2364 return block;
2374 } 2365 }
2375 2366
2376 2367
2377 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, 2368 static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
2378 const AstRawString* label) { 2369 const AstRawString* label) {
2379 DCHECK(label != NULL); 2370 DCHECK(label != NULL);
(...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after
3096 3087
3097 // Create an in-between scope for let-bound iteration variables. 3088 // Create an in-between scope for let-bound iteration variables.
3098 Scope* saved_scope = scope_; 3089 Scope* saved_scope = scope_;
3099 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); 3090 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
3100 scope_ = for_scope; 3091 scope_ = for_scope;
3101 3092
3102 Expect(Token::FOR, CHECK_OK); 3093 Expect(Token::FOR, CHECK_OK);
3103 Expect(Token::LPAREN, CHECK_OK); 3094 Expect(Token::LPAREN, CHECK_OK);
3104 for_scope->set_start_position(scanner()->location().beg_pos); 3095 for_scope->set_start_position(scanner()->location().beg_pos);
3105 if (peek() != Token::SEMICOLON) { 3096 if (peek() != Token::SEMICOLON) {
3106 if (peek() == Token::VAR || 3097 if (peek() == Token::VAR || peek() == Token::CONST) {
3107 (peek() == Token::CONST && strict_mode() == SLOPPY)) {
3108 bool is_const = peek() == Token::CONST; 3098 bool is_const = peek() == Token::CONST;
3109 const AstRawString* name = NULL; 3099 const AstRawString* name = NULL;
3110 VariableDeclarationProperties decl_props = kHasNoInitializers; 3100 VariableDeclarationProperties decl_props = kHasNoInitializers;
3111 Block* variable_statement = 3101 Block* variable_statement =
3112 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, 3102 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
3113 CHECK_OK); 3103 CHECK_OK);
3114 bool accept_OF = decl_props == kHasNoInitializers; 3104 bool accept_OF = decl_props == kHasNoInitializers;
3115 ForEachStatement::VisitMode mode; 3105 ForEachStatement::VisitMode mode;
3116 3106
3117 if (name != NULL && CheckInOrOf(accept_OF, &mode)) { 3107 if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
(...skipping 16 matching lines...) Expand all
3134 result->AddStatement(loop, zone()); 3124 result->AddStatement(loop, zone());
3135 scope_ = saved_scope; 3125 scope_ = saved_scope;
3136 for_scope->set_end_position(scanner()->location().end_pos); 3126 for_scope->set_end_position(scanner()->location().end_pos);
3137 for_scope = for_scope->FinalizeBlockScope(); 3127 for_scope = for_scope->FinalizeBlockScope();
3138 DCHECK(for_scope == NULL); 3128 DCHECK(for_scope == NULL);
3139 // Parsed for-in loop w/ variable/const declaration. 3129 // Parsed for-in loop w/ variable/const declaration.
3140 return result; 3130 return result;
3141 } else { 3131 } else {
3142 init = variable_statement; 3132 init = variable_statement;
3143 } 3133 }
3144 } else if ((peek() == Token::LET || peek() == Token::CONST) && 3134 } else if (peek() == Token::LET && strict_mode() == STRICT) {
3145 strict_mode() == STRICT) {
3146 DCHECK(allow_harmony_scoping()); 3135 DCHECK(allow_harmony_scoping());
3147 bool is_const = peek() == Token::CONST;
3148 const AstRawString* name = NULL; 3136 const AstRawString* name = NULL;
3149 VariableDeclarationProperties decl_props = kHasNoInitializers; 3137 VariableDeclarationProperties decl_props = kHasNoInitializers;
3150 Block* variable_statement = 3138 Block* variable_statement =
3151 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, 3139 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
3152 &name, CHECK_OK); 3140 &name, CHECK_OK);
3153 bool accept_IN = name != NULL && decl_props != kHasInitializers; 3141 bool accept_IN = name != NULL && decl_props != kHasInitializers;
3154 bool accept_OF = decl_props == kHasNoInitializers; 3142 bool accept_OF = decl_props == kHasNoInitializers;
3155 ForEachStatement::VisitMode mode; 3143 ForEachStatement::VisitMode mode;
3156 3144
3157 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { 3145 if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
3158 // Rewrite a for-in statement of the form 3146 // Rewrite a for-in statement of the form
3159 // 3147 //
3160 // for (let/const x in e) b 3148 // for (let x in e) b
3161 // 3149 //
3162 // into 3150 // into
3163 // 3151 //
3164 // <let x' be a temporary variable> 3152 // <let x' be a temporary variable>
3165 // for (x' in e) { 3153 // for (x' in e) {
3166 // let/const x; 3154 // let x;
3167 // x = x'; 3155 // x = x';
3168 // b; 3156 // b;
3169 // } 3157 // }
3170 3158
3171 // TODO(keuchel): Move the temporary variable to the block scope, after 3159 // TODO(keuchel): Move the temporary variable to the block scope, after
3172 // implementing stack allocated block scoped variables. 3160 // implementing stack allocated block scoped variables.
3173 Variable* temp = scope_->DeclarationScope()->NewTemporary( 3161 Variable* temp = scope_->DeclarationScope()->NewTemporary(
3174 ast_value_factory()->dot_for_string()); 3162 ast_value_factory()->dot_for_string());
3175 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); 3163 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3176 ForEachStatement* loop = 3164 ForEachStatement* loop =
3177 factory()->NewForEachStatement(mode, labels, pos); 3165 factory()->NewForEachStatement(mode, labels, pos);
3178 Target target(&this->target_stack_, loop); 3166 Target target(&this->target_stack_, loop);
3179 3167
3180 // The expression does not see the loop variable. 3168 // The expression does not see the loop variable.
3181 scope_ = saved_scope; 3169 scope_ = saved_scope;
3182 Expression* enumerable = ParseExpression(true, CHECK_OK); 3170 Expression* enumerable = ParseExpression(true, CHECK_OK);
3183 scope_ = for_scope; 3171 scope_ = for_scope;
3184 Expect(Token::RPAREN, CHECK_OK); 3172 Expect(Token::RPAREN, CHECK_OK);
3185 3173
3186 VariableProxy* each = scope_->NewUnresolved(factory(), name); 3174 VariableProxy* each =
3175 scope_->NewUnresolved(factory(), name, Interface::NewValue());
3187 Statement* body = ParseStatement(NULL, CHECK_OK); 3176 Statement* body = ParseStatement(NULL, CHECK_OK);
3188 Block* body_block = 3177 Block* body_block =
3189 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); 3178 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3190 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN;
3191 Assignment* assignment = factory()->NewAssignment( 3179 Assignment* assignment = factory()->NewAssignment(
3192 init_op, each, temp_proxy, RelocInfo::kNoPosition); 3180 Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
3193 Statement* assignment_statement = factory()->NewExpressionStatement( 3181 Statement* assignment_statement = factory()->NewExpressionStatement(
3194 assignment, RelocInfo::kNoPosition); 3182 assignment, RelocInfo::kNoPosition);
3195 body_block->AddStatement(variable_statement, zone()); 3183 body_block->AddStatement(variable_statement, zone());
3196 body_block->AddStatement(assignment_statement, zone()); 3184 body_block->AddStatement(assignment_statement, zone());
3197 body_block->AddStatement(body, zone()); 3185 body_block->AddStatement(body, zone());
3198 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block); 3186 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
3199 scope_ = saved_scope; 3187 scope_ = saved_scope;
3200 for_scope->set_end_position(scanner()->location().end_pos); 3188 for_scope->set_end_position(scanner()->location().end_pos);
3201 for_scope = for_scope->FinalizeBlockScope(); 3189 for_scope = for_scope->FinalizeBlockScope();
3202 body_block->set_scope(for_scope); 3190 body_block->set_scope(for_scope);
(...skipping 1759 matching lines...) Expand 10 before | Expand all | Expand 10 after
4962 4950
4963 // We cannot internalize on a background thread; a foreground task will take 4951 // We cannot internalize on a background thread; a foreground task will take
4964 // care of calling Parser::Internalize just before compilation. 4952 // care of calling Parser::Internalize just before compilation.
4965 4953
4966 if (compile_options() == ScriptCompiler::kProduceParserCache) { 4954 if (compile_options() == ScriptCompiler::kProduceParserCache) {
4967 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); 4955 if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
4968 log_ = NULL; 4956 log_ = NULL;
4969 } 4957 }
4970 } 4958 }
4971 } } // namespace v8::internal 4959 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698