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