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" |
(...skipping 2921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2932 ast_value_factory()->dot_result_string()); | 2932 ast_value_factory()->dot_result_string()); |
2933 | 2933 |
2934 Expression* assign_iterator; | 2934 Expression* assign_iterator; |
2935 Expression* next_result; | 2935 Expression* next_result; |
2936 Expression* result_done; | 2936 Expression* result_done; |
2937 Expression* assign_each; | 2937 Expression* assign_each; |
2938 | 2938 |
2939 // var iterator = subject[Symbol.iterator](); | 2939 // var iterator = subject[Symbol.iterator](); |
2940 assign_iterator = factory()->NewAssignment( | 2940 assign_iterator = factory()->NewAssignment( |
2941 Token::ASSIGN, factory()->NewVariableProxy(iterator), | 2941 Token::ASSIGN, factory()->NewVariableProxy(iterator), |
2942 GetIterator(subject, factory()), subject->position()); | 2942 GetIterator(subject, factory()), RelocInfo::kNoPosition); |
2943 | 2943 |
2944 // var result = iterator.next(); | 2944 // var result = iterator.next(); |
2945 { | 2945 { |
2946 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | 2946 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); |
2947 Expression* next_literal = factory()->NewStringLiteral( | 2947 Expression* next_literal = factory()->NewStringLiteral( |
2948 ast_value_factory()->next_string(), RelocInfo::kNoPosition); | 2948 ast_value_factory()->next_string(), RelocInfo::kNoPosition); |
2949 Expression* next_property = factory()->NewProperty( | 2949 Expression* next_property = factory()->NewProperty( |
2950 iterator_proxy, next_literal, RelocInfo::kNoPosition); | 2950 iterator_proxy, next_literal, RelocInfo::kNoPosition); |
2951 ZoneList<Expression*>* next_arguments = | 2951 ZoneList<Expression*>* next_arguments = |
2952 new(zone()) ZoneList<Expression*>(0, zone()); | 2952 new(zone()) ZoneList<Expression*>(0, zone()); |
2953 Expression* next_call = factory()->NewCall(next_property, next_arguments, | 2953 Expression* next_call = factory()->NewCall( |
2954 subject->position()); | 2954 next_property, next_arguments, RelocInfo::kNoPosition); |
2955 Expression* result_proxy = factory()->NewVariableProxy(result); | 2955 Expression* result_proxy = factory()->NewVariableProxy(result); |
2956 next_result = factory()->NewAssignment(Token::ASSIGN, result_proxy, | 2956 next_result = factory()->NewAssignment( |
2957 next_call, subject->position()); | 2957 Token::ASSIGN, result_proxy, next_call, RelocInfo::kNoPosition); |
2958 } | 2958 } |
2959 | 2959 |
2960 // result.done | 2960 // result.done |
2961 { | 2961 { |
2962 Expression* done_literal = factory()->NewStringLiteral( | 2962 Expression* done_literal = factory()->NewStringLiteral( |
2963 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | 2963 ast_value_factory()->done_string(), RelocInfo::kNoPosition); |
2964 Expression* result_proxy = factory()->NewVariableProxy(result); | 2964 Expression* result_proxy = factory()->NewVariableProxy(result); |
2965 result_done = factory()->NewProperty( | 2965 result_done = factory()->NewProperty( |
2966 result_proxy, done_literal, RelocInfo::kNoPosition); | 2966 result_proxy, done_literal, RelocInfo::kNoPosition); |
2967 } | 2967 } |
2968 | 2968 |
2969 // each = result.value | 2969 // each = result.value |
2970 { | 2970 { |
2971 Expression* value_literal = factory()->NewStringLiteral( | 2971 Expression* value_literal = factory()->NewStringLiteral( |
2972 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | 2972 ast_value_factory()->value_string(), RelocInfo::kNoPosition); |
2973 Expression* result_proxy = factory()->NewVariableProxy(result); | 2973 Expression* result_proxy = factory()->NewVariableProxy(result); |
2974 Expression* result_value = factory()->NewProperty( | 2974 Expression* result_value = factory()->NewProperty( |
2975 result_proxy, value_literal, RelocInfo::kNoPosition); | 2975 result_proxy, value_literal, RelocInfo::kNoPosition); |
2976 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, | 2976 assign_each = factory()->NewAssignment( |
2977 each->position()); | 2977 Token::ASSIGN, each, result_value, RelocInfo::kNoPosition); |
2978 } | 2978 } |
2979 | 2979 |
2980 for_of->Initialize(each, subject, body, | 2980 for_of->Initialize(each, subject, body, |
2981 assign_iterator, | 2981 assign_iterator, |
2982 next_result, | 2982 next_result, |
2983 result_done, | 2983 result_done, |
2984 assign_each); | 2984 assign_each); |
2985 } else { | 2985 } else { |
2986 stmt->Initialize(each, subject, body); | 2986 stmt->Initialize(each, subject, body); |
2987 } | 2987 } |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3145 loop->Initialize(NULL, NULL, NULL, inner_block); | 3145 loop->Initialize(NULL, NULL, NULL, inner_block); |
3146 return outer_block; | 3146 return outer_block; |
3147 } | 3147 } |
3148 | 3148 |
3149 | 3149 |
3150 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 3150 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
3151 bool* ok) { | 3151 bool* ok) { |
3152 // ForStatement :: | 3152 // ForStatement :: |
3153 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 3153 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
3154 | 3154 |
3155 int stmt_pos = peek_position(); | 3155 int pos = peek_position(); |
3156 Statement* init = NULL; | 3156 Statement* init = NULL; |
3157 ZoneList<const AstRawString*> let_bindings(1, zone()); | 3157 ZoneList<const AstRawString*> let_bindings(1, zone()); |
3158 | 3158 |
3159 // Create an in-between scope for let-bound iteration variables. | 3159 // Create an in-between scope for let-bound iteration variables. |
3160 Scope* saved_scope = scope_; | 3160 Scope* saved_scope = scope_; |
3161 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3161 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
3162 scope_ = for_scope; | 3162 scope_ = for_scope; |
3163 | 3163 |
3164 Expect(Token::FOR, CHECK_OK); | 3164 Expect(Token::FOR, CHECK_OK); |
3165 Expect(Token::LPAREN, CHECK_OK); | 3165 Expect(Token::LPAREN, CHECK_OK); |
3166 for_scope->set_start_position(scanner()->location().beg_pos); | 3166 for_scope->set_start_position(scanner()->location().beg_pos); |
3167 if (peek() != Token::SEMICOLON) { | 3167 if (peek() != Token::SEMICOLON) { |
3168 if (peek() == Token::VAR || | 3168 if (peek() == Token::VAR || |
3169 (peek() == Token::CONST && strict_mode() == SLOPPY)) { | 3169 (peek() == Token::CONST && strict_mode() == SLOPPY)) { |
3170 bool is_const = peek() == Token::CONST; | 3170 bool is_const = peek() == Token::CONST; |
3171 const AstRawString* name = NULL; | 3171 const AstRawString* name = NULL; |
3172 VariableDeclarationProperties decl_props = kHasNoInitializers; | 3172 VariableDeclarationProperties decl_props = kHasNoInitializers; |
3173 Block* variable_statement = | 3173 Block* variable_statement = |
3174 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, | 3174 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, |
3175 CHECK_OK); | 3175 CHECK_OK); |
3176 bool accept_OF = decl_props == kHasNoInitializers; | 3176 bool accept_OF = decl_props == kHasNoInitializers; |
3177 ForEachStatement::VisitMode mode; | 3177 ForEachStatement::VisitMode mode; |
3178 int each_pos = position(); | |
3179 | 3178 |
3180 if (name != NULL && CheckInOrOf(accept_OF, &mode)) { | 3179 if (name != NULL && CheckInOrOf(accept_OF, &mode)) { |
3181 Interface* interface = | 3180 Interface* interface = |
3182 is_const ? Interface::NewConst() : Interface::NewValue(); | 3181 is_const ? Interface::NewConst() : Interface::NewValue(); |
3183 ForEachStatement* loop = | 3182 ForEachStatement* loop = |
3184 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3183 factory()->NewForEachStatement(mode, labels, pos); |
3185 Target target(&this->target_stack_, loop); | 3184 Target target(&this->target_stack_, loop); |
3186 | 3185 |
3187 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3186 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3188 Expect(Token::RPAREN, CHECK_OK); | 3187 Expect(Token::RPAREN, CHECK_OK); |
3189 | 3188 |
3190 VariableProxy* each = | 3189 VariableProxy* each = |
3191 scope_->NewUnresolved(factory(), name, interface, each_pos); | 3190 scope_->NewUnresolved(factory(), name, interface); |
3192 Statement* body = ParseStatement(NULL, CHECK_OK); | 3191 Statement* body = ParseStatement(NULL, CHECK_OK); |
3193 InitializeForEachStatement(loop, each, enumerable, body); | 3192 InitializeForEachStatement(loop, each, enumerable, body); |
3194 Block* result = | 3193 Block* result = |
3195 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); | 3194 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); |
3196 result->AddStatement(variable_statement, zone()); | 3195 result->AddStatement(variable_statement, zone()); |
3197 result->AddStatement(loop, zone()); | 3196 result->AddStatement(loop, zone()); |
3198 scope_ = saved_scope; | 3197 scope_ = saved_scope; |
3199 for_scope->set_end_position(scanner()->location().end_pos); | 3198 for_scope->set_end_position(scanner()->location().end_pos); |
3200 for_scope = for_scope->FinalizeBlockScope(); | 3199 for_scope = for_scope->FinalizeBlockScope(); |
3201 DCHECK(for_scope == NULL); | 3200 DCHECK(for_scope == NULL); |
3202 // Parsed for-in loop w/ variable/const declaration. | 3201 // Parsed for-in loop w/ variable/const declaration. |
3203 return result; | 3202 return result; |
3204 } else { | 3203 } else { |
3205 init = variable_statement; | 3204 init = variable_statement; |
3206 } | 3205 } |
3207 } else if ((peek() == Token::LET || peek() == Token::CONST) && | 3206 } else if ((peek() == Token::LET || peek() == Token::CONST) && |
3208 strict_mode() == STRICT) { | 3207 strict_mode() == STRICT) { |
3209 bool is_const = peek() == Token::CONST; | 3208 bool is_const = peek() == Token::CONST; |
3210 const AstRawString* name = NULL; | 3209 const AstRawString* name = NULL; |
3211 VariableDeclarationProperties decl_props = kHasNoInitializers; | 3210 VariableDeclarationProperties decl_props = kHasNoInitializers; |
3212 Block* variable_statement = | 3211 Block* variable_statement = |
3213 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, | 3212 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, |
3214 &name, CHECK_OK); | 3213 &name, CHECK_OK); |
3215 bool accept_IN = name != NULL && decl_props != kHasInitializers; | 3214 bool accept_IN = name != NULL && decl_props != kHasInitializers; |
3216 bool accept_OF = decl_props == kHasNoInitializers; | 3215 bool accept_OF = decl_props == kHasNoInitializers; |
3217 ForEachStatement::VisitMode mode; | 3216 ForEachStatement::VisitMode mode; |
3218 int each_pos = position(); | |
3219 | 3217 |
3220 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { | 3218 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { |
3221 // Rewrite a for-in statement of the form | 3219 // Rewrite a for-in statement of the form |
3222 // | 3220 // |
3223 // for (let/const x in e) b | 3221 // for (let/const x in e) b |
3224 // | 3222 // |
3225 // into | 3223 // into |
3226 // | 3224 // |
3227 // <let x' be a temporary variable> | 3225 // <let x' be a temporary variable> |
3228 // for (x' in e) { | 3226 // for (x' in e) { |
3229 // let/const x; | 3227 // let/const x; |
3230 // x = x'; | 3228 // x = x'; |
3231 // b; | 3229 // b; |
3232 // } | 3230 // } |
3233 | 3231 |
3234 // TODO(keuchel): Move the temporary variable to the block scope, after | 3232 // TODO(keuchel): Move the temporary variable to the block scope, after |
3235 // implementing stack allocated block scoped variables. | 3233 // implementing stack allocated block scoped variables. |
3236 Variable* temp = scope_->DeclarationScope()->NewTemporary( | 3234 Variable* temp = scope_->DeclarationScope()->NewTemporary( |
3237 ast_value_factory()->dot_for_string()); | 3235 ast_value_factory()->dot_for_string()); |
3238 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 3236 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
3239 ForEachStatement* loop = | 3237 ForEachStatement* loop = |
3240 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3238 factory()->NewForEachStatement(mode, labels, pos); |
3241 Target target(&this->target_stack_, loop); | 3239 Target target(&this->target_stack_, loop); |
3242 | 3240 |
3243 // The expression does not see the loop variable. | 3241 // The expression does not see the loop variable. |
3244 scope_ = saved_scope; | 3242 scope_ = saved_scope; |
3245 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3243 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3246 scope_ = for_scope; | 3244 scope_ = for_scope; |
3247 Expect(Token::RPAREN, CHECK_OK); | 3245 Expect(Token::RPAREN, CHECK_OK); |
3248 | 3246 |
3249 VariableProxy* each = scope_->NewUnresolved( | 3247 VariableProxy* each = scope_->NewUnresolved(factory(), name); |
3250 factory(), name, Interface::NewValue(), each_pos); | |
3251 Statement* body = ParseStatement(NULL, CHECK_OK); | 3248 Statement* body = ParseStatement(NULL, CHECK_OK); |
3252 Block* body_block = | 3249 Block* body_block = |
3253 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); | 3250 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
3254 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; | 3251 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; |
3255 Assignment* assignment = factory()->NewAssignment( | 3252 Assignment* assignment = factory()->NewAssignment( |
3256 init_op, each, temp_proxy, RelocInfo::kNoPosition); | 3253 init_op, each, temp_proxy, RelocInfo::kNoPosition); |
3257 Statement* assignment_statement = factory()->NewExpressionStatement( | 3254 Statement* assignment_statement = factory()->NewExpressionStatement( |
3258 assignment, RelocInfo::kNoPosition); | 3255 assignment, RelocInfo::kNoPosition); |
3259 body_block->AddStatement(variable_statement, zone()); | 3256 body_block->AddStatement(variable_statement, zone()); |
3260 body_block->AddStatement(assignment_statement, zone()); | 3257 body_block->AddStatement(assignment_statement, zone()); |
(...skipping 13 matching lines...) Expand all Loading... |
3274 Scanner::Location lhs_location = scanner()->peek_location(); | 3271 Scanner::Location lhs_location = scanner()->peek_location(); |
3275 Expression* expression = ParseExpression(false, CHECK_OK); | 3272 Expression* expression = ParseExpression(false, CHECK_OK); |
3276 ForEachStatement::VisitMode mode; | 3273 ForEachStatement::VisitMode mode; |
3277 bool accept_OF = expression->IsVariableProxy(); | 3274 bool accept_OF = expression->IsVariableProxy(); |
3278 | 3275 |
3279 if (CheckInOrOf(accept_OF, &mode)) { | 3276 if (CheckInOrOf(accept_OF, &mode)) { |
3280 expression = this->CheckAndRewriteReferenceExpression( | 3277 expression = this->CheckAndRewriteReferenceExpression( |
3281 expression, lhs_location, "invalid_lhs_in_for", CHECK_OK); | 3278 expression, lhs_location, "invalid_lhs_in_for", CHECK_OK); |
3282 | 3279 |
3283 ForEachStatement* loop = | 3280 ForEachStatement* loop = |
3284 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3281 factory()->NewForEachStatement(mode, labels, pos); |
3285 Target target(&this->target_stack_, loop); | 3282 Target target(&this->target_stack_, loop); |
3286 | 3283 |
3287 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3284 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3288 Expect(Token::RPAREN, CHECK_OK); | 3285 Expect(Token::RPAREN, CHECK_OK); |
3289 | 3286 |
3290 Statement* body = ParseStatement(NULL, CHECK_OK); | 3287 Statement* body = ParseStatement(NULL, CHECK_OK); |
3291 InitializeForEachStatement(loop, expression, enumerable, body); | 3288 InitializeForEachStatement(loop, expression, enumerable, body); |
3292 scope_ = saved_scope; | 3289 scope_ = saved_scope; |
3293 for_scope->set_end_position(scanner()->location().end_pos); | 3290 for_scope->set_end_position(scanner()->location().end_pos); |
3294 for_scope = for_scope->FinalizeBlockScope(); | 3291 for_scope = for_scope->FinalizeBlockScope(); |
3295 DCHECK(for_scope == NULL); | 3292 DCHECK(for_scope == NULL); |
3296 // Parsed for-in loop. | 3293 // Parsed for-in loop. |
3297 return loop; | 3294 return loop; |
3298 | 3295 |
3299 } else { | 3296 } else { |
3300 init = factory()->NewExpressionStatement(expression, position()); | 3297 init = factory()->NewExpressionStatement( |
| 3298 expression, RelocInfo::kNoPosition); |
3301 } | 3299 } |
3302 } | 3300 } |
3303 } | 3301 } |
3304 | 3302 |
3305 // Standard 'for' loop | 3303 // Standard 'for' loop |
3306 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos); | 3304 ForStatement* loop = factory()->NewForStatement(labels, pos); |
3307 Target target(&this->target_stack_, loop); | 3305 Target target(&this->target_stack_, loop); |
3308 | 3306 |
3309 // Parsed initializer at this point. | 3307 // Parsed initializer at this point. |
3310 Expect(Token::SEMICOLON, CHECK_OK); | 3308 Expect(Token::SEMICOLON, CHECK_OK); |
3311 | 3309 |
3312 // If there are let bindings, then condition and the next statement of the | 3310 // If there are let bindings, then condition and the next statement of the |
3313 // for loop must be parsed in a new scope. | 3311 // for loop must be parsed in a new scope. |
3314 Scope* inner_scope = NULL; | 3312 Scope* inner_scope = NULL; |
3315 if (let_bindings.length() > 0) { | 3313 if (let_bindings.length() > 0) { |
3316 inner_scope = NewScope(for_scope, BLOCK_SCOPE); | 3314 inner_scope = NewScope(for_scope, BLOCK_SCOPE); |
3317 inner_scope->set_start_position(scanner()->location().beg_pos); | 3315 inner_scope->set_start_position(scanner()->location().beg_pos); |
3318 scope_ = inner_scope; | 3316 scope_ = inner_scope; |
3319 } | 3317 } |
3320 | 3318 |
3321 Expression* cond = NULL; | 3319 Expression* cond = NULL; |
3322 if (peek() != Token::SEMICOLON) { | 3320 if (peek() != Token::SEMICOLON) { |
3323 cond = ParseExpression(true, CHECK_OK); | 3321 cond = ParseExpression(true, CHECK_OK); |
3324 } | 3322 } |
3325 Expect(Token::SEMICOLON, CHECK_OK); | 3323 Expect(Token::SEMICOLON, CHECK_OK); |
3326 | 3324 |
3327 Statement* next = NULL; | 3325 Statement* next = NULL; |
3328 if (peek() != Token::RPAREN) { | 3326 if (peek() != Token::RPAREN) { |
3329 int next_pos = position(); | |
3330 Expression* exp = ParseExpression(true, CHECK_OK); | 3327 Expression* exp = ParseExpression(true, CHECK_OK); |
3331 next = factory()->NewExpressionStatement(exp, next_pos); | 3328 next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition); |
3332 } | 3329 } |
3333 Expect(Token::RPAREN, CHECK_OK); | 3330 Expect(Token::RPAREN, CHECK_OK); |
3334 | 3331 |
3335 Statement* body = ParseStatement(NULL, CHECK_OK); | 3332 Statement* body = ParseStatement(NULL, CHECK_OK); |
3336 | 3333 |
3337 Statement* result = NULL; | 3334 Statement* result = NULL; |
3338 if (let_bindings.length() > 0) { | 3335 if (let_bindings.length() > 0) { |
3339 scope_ = for_scope; | 3336 scope_ = for_scope; |
3340 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, | 3337 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, |
3341 init, cond, next, body, CHECK_OK); | 3338 init, cond, next, body, CHECK_OK); |
(...skipping 1684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5026 | 5023 |
5027 // We cannot internalize on a background thread; a foreground task will take | 5024 // We cannot internalize on a background thread; a foreground task will take |
5028 // care of calling Parser::Internalize just before compilation. | 5025 // care of calling Parser::Internalize just before compilation. |
5029 | 5026 |
5030 if (compile_options() == ScriptCompiler::kProduceParserCache) { | 5027 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
5031 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); | 5028 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); |
5032 log_ = NULL; | 5029 log_ = NULL; |
5033 } | 5030 } |
5034 } | 5031 } |
5035 } } // namespace v8::internal | 5032 } } // namespace v8::internal |
OLD | NEW |