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 2853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2864 ast_value_factory()->dot_result_string()); | 2864 ast_value_factory()->dot_result_string()); |
2865 | 2865 |
2866 Expression* assign_iterator; | 2866 Expression* assign_iterator; |
2867 Expression* next_result; | 2867 Expression* next_result; |
2868 Expression* result_done; | 2868 Expression* result_done; |
2869 Expression* assign_each; | 2869 Expression* assign_each; |
2870 | 2870 |
2871 // var iterator = subject[Symbol.iterator](); | 2871 // var iterator = subject[Symbol.iterator](); |
2872 assign_iterator = factory()->NewAssignment( | 2872 assign_iterator = factory()->NewAssignment( |
2873 Token::ASSIGN, factory()->NewVariableProxy(iterator), | 2873 Token::ASSIGN, factory()->NewVariableProxy(iterator), |
2874 GetIterator(subject, factory()), RelocInfo::kNoPosition); | 2874 GetIterator(subject, factory()), subject->position()); |
2875 | 2875 |
2876 // var result = iterator.next(); | 2876 // var result = iterator.next(); |
2877 { | 2877 { |
2878 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | 2878 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); |
2879 Expression* next_literal = factory()->NewStringLiteral( | 2879 Expression* next_literal = factory()->NewStringLiteral( |
2880 ast_value_factory()->next_string(), RelocInfo::kNoPosition); | 2880 ast_value_factory()->next_string(), RelocInfo::kNoPosition); |
2881 Expression* next_property = factory()->NewProperty( | 2881 Expression* next_property = factory()->NewProperty( |
2882 iterator_proxy, next_literal, RelocInfo::kNoPosition); | 2882 iterator_proxy, next_literal, RelocInfo::kNoPosition); |
2883 ZoneList<Expression*>* next_arguments = | 2883 ZoneList<Expression*>* next_arguments = |
2884 new(zone()) ZoneList<Expression*>(0, zone()); | 2884 new(zone()) ZoneList<Expression*>(0, zone()); |
2885 Expression* next_call = factory()->NewCall( | 2885 Expression* next_call = factory()->NewCall(next_property, next_arguments, |
2886 next_property, next_arguments, RelocInfo::kNoPosition); | 2886 subject->position()); |
2887 Expression* result_proxy = factory()->NewVariableProxy(result); | 2887 Expression* result_proxy = factory()->NewVariableProxy(result); |
2888 next_result = factory()->NewAssignment( | 2888 next_result = factory()->NewAssignment(Token::ASSIGN, result_proxy, |
2889 Token::ASSIGN, result_proxy, next_call, RelocInfo::kNoPosition); | 2889 next_call, subject->position()); |
2890 } | 2890 } |
2891 | 2891 |
2892 // result.done | 2892 // result.done |
2893 { | 2893 { |
2894 Expression* done_literal = factory()->NewStringLiteral( | 2894 Expression* done_literal = factory()->NewStringLiteral( |
2895 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | 2895 ast_value_factory()->done_string(), RelocInfo::kNoPosition); |
2896 Expression* result_proxy = factory()->NewVariableProxy(result); | 2896 Expression* result_proxy = factory()->NewVariableProxy(result); |
2897 result_done = factory()->NewProperty( | 2897 result_done = factory()->NewProperty( |
2898 result_proxy, done_literal, RelocInfo::kNoPosition); | 2898 result_proxy, done_literal, RelocInfo::kNoPosition); |
2899 } | 2899 } |
2900 | 2900 |
2901 // each = result.value | 2901 // each = result.value |
2902 { | 2902 { |
2903 Expression* value_literal = factory()->NewStringLiteral( | 2903 Expression* value_literal = factory()->NewStringLiteral( |
2904 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | 2904 ast_value_factory()->value_string(), RelocInfo::kNoPosition); |
2905 Expression* result_proxy = factory()->NewVariableProxy(result); | 2905 Expression* result_proxy = factory()->NewVariableProxy(result); |
2906 Expression* result_value = factory()->NewProperty( | 2906 Expression* result_value = factory()->NewProperty( |
2907 result_proxy, value_literal, RelocInfo::kNoPosition); | 2907 result_proxy, value_literal, RelocInfo::kNoPosition); |
2908 assign_each = factory()->NewAssignment( | 2908 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, |
2909 Token::ASSIGN, each, result_value, RelocInfo::kNoPosition); | 2909 each->position()); |
2910 } | 2910 } |
2911 | 2911 |
2912 for_of->Initialize(each, subject, body, | 2912 for_of->Initialize(each, subject, body, |
2913 assign_iterator, | 2913 assign_iterator, |
2914 next_result, | 2914 next_result, |
2915 result_done, | 2915 result_done, |
2916 assign_each); | 2916 assign_each); |
2917 } else { | 2917 } else { |
2918 stmt->Initialize(each, subject, body); | 2918 stmt->Initialize(each, subject, body); |
2919 } | 2919 } |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3077 loop->Initialize(NULL, NULL, NULL, inner_block); | 3077 loop->Initialize(NULL, NULL, NULL, inner_block); |
3078 return outer_block; | 3078 return outer_block; |
3079 } | 3079 } |
3080 | 3080 |
3081 | 3081 |
3082 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 3082 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
3083 bool* ok) { | 3083 bool* ok) { |
3084 // ForStatement :: | 3084 // ForStatement :: |
3085 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 3085 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
3086 | 3086 |
3087 int pos = peek_position(); | 3087 int stmt_pos = peek_position(); |
3088 Statement* init = NULL; | 3088 Statement* init = NULL; |
3089 ZoneList<const AstRawString*> let_bindings(1, zone()); | 3089 ZoneList<const AstRawString*> let_bindings(1, zone()); |
3090 | 3090 |
3091 // Create an in-between scope for let-bound iteration variables. | 3091 // Create an in-between scope for let-bound iteration variables. |
3092 Scope* saved_scope = scope_; | 3092 Scope* saved_scope = scope_; |
3093 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3093 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
3094 scope_ = for_scope; | 3094 scope_ = for_scope; |
3095 | 3095 |
3096 Expect(Token::FOR, CHECK_OK); | 3096 Expect(Token::FOR, CHECK_OK); |
3097 Expect(Token::LPAREN, CHECK_OK); | 3097 Expect(Token::LPAREN, CHECK_OK); |
3098 for_scope->set_start_position(scanner()->location().beg_pos); | 3098 for_scope->set_start_position(scanner()->location().beg_pos); |
3099 if (peek() != Token::SEMICOLON) { | 3099 if (peek() != Token::SEMICOLON) { |
3100 if (peek() == Token::VAR || | 3100 if (peek() == Token::VAR || |
3101 (peek() == Token::CONST && strict_mode() == SLOPPY)) { | 3101 (peek() == Token::CONST && strict_mode() == SLOPPY)) { |
3102 bool is_const = peek() == Token::CONST; | 3102 bool is_const = peek() == Token::CONST; |
3103 const AstRawString* name = NULL; | 3103 const AstRawString* name = NULL; |
3104 VariableDeclarationProperties decl_props = kHasNoInitializers; | 3104 VariableDeclarationProperties decl_props = kHasNoInitializers; |
3105 Block* variable_statement = | 3105 Block* variable_statement = |
3106 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, | 3106 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, |
3107 CHECK_OK); | 3107 CHECK_OK); |
3108 bool accept_OF = decl_props == kHasNoInitializers; | 3108 bool accept_OF = decl_props == kHasNoInitializers; |
3109 ForEachStatement::VisitMode mode; | 3109 ForEachStatement::VisitMode mode; |
| 3110 int each_pos = position(); |
3110 | 3111 |
3111 if (name != NULL && CheckInOrOf(accept_OF, &mode)) { | 3112 if (name != NULL && CheckInOrOf(accept_OF, &mode)) { |
3112 Interface* interface = | 3113 Interface* interface = |
3113 is_const ? Interface::NewConst() : Interface::NewValue(); | 3114 is_const ? Interface::NewConst() : Interface::NewValue(); |
3114 ForEachStatement* loop = | 3115 ForEachStatement* loop = |
3115 factory()->NewForEachStatement(mode, labels, pos); | 3116 factory()->NewForEachStatement(mode, labels, stmt_pos); |
3116 Target target(&this->target_stack_, loop); | 3117 Target target(&this->target_stack_, loop); |
3117 | 3118 |
3118 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3119 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3119 Expect(Token::RPAREN, CHECK_OK); | 3120 Expect(Token::RPAREN, CHECK_OK); |
3120 | 3121 |
3121 VariableProxy* each = | 3122 VariableProxy* each = |
3122 scope_->NewUnresolved(factory(), name, interface); | 3123 scope_->NewUnresolved(factory(), name, interface, each_pos); |
3123 Statement* body = ParseStatement(NULL, CHECK_OK); | 3124 Statement* body = ParseStatement(NULL, CHECK_OK); |
3124 InitializeForEachStatement(loop, each, enumerable, body); | 3125 InitializeForEachStatement(loop, each, enumerable, body); |
3125 Block* result = | 3126 Block* result = |
3126 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); | 3127 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); |
3127 result->AddStatement(variable_statement, zone()); | 3128 result->AddStatement(variable_statement, zone()); |
3128 result->AddStatement(loop, zone()); | 3129 result->AddStatement(loop, zone()); |
3129 scope_ = saved_scope; | 3130 scope_ = saved_scope; |
3130 for_scope->set_end_position(scanner()->location().end_pos); | 3131 for_scope->set_end_position(scanner()->location().end_pos); |
3131 for_scope = for_scope->FinalizeBlockScope(); | 3132 for_scope = for_scope->FinalizeBlockScope(); |
3132 DCHECK(for_scope == NULL); | 3133 DCHECK(for_scope == NULL); |
3133 // Parsed for-in loop w/ variable/const declaration. | 3134 // Parsed for-in loop w/ variable/const declaration. |
3134 return result; | 3135 return result; |
3135 } else { | 3136 } else { |
3136 init = variable_statement; | 3137 init = variable_statement; |
3137 } | 3138 } |
3138 } else if ((peek() == Token::LET || peek() == Token::CONST) && | 3139 } else if ((peek() == Token::LET || peek() == Token::CONST) && |
3139 strict_mode() == STRICT) { | 3140 strict_mode() == STRICT) { |
3140 bool is_const = peek() == Token::CONST; | 3141 bool is_const = peek() == Token::CONST; |
3141 const AstRawString* name = NULL; | 3142 const AstRawString* name = NULL; |
3142 VariableDeclarationProperties decl_props = kHasNoInitializers; | 3143 VariableDeclarationProperties decl_props = kHasNoInitializers; |
3143 Block* variable_statement = | 3144 Block* variable_statement = |
3144 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, | 3145 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, |
3145 &name, CHECK_OK); | 3146 &name, CHECK_OK); |
3146 bool accept_IN = name != NULL && decl_props != kHasInitializers; | 3147 bool accept_IN = name != NULL && decl_props != kHasInitializers; |
3147 bool accept_OF = decl_props == kHasNoInitializers; | 3148 bool accept_OF = decl_props == kHasNoInitializers; |
3148 ForEachStatement::VisitMode mode; | 3149 ForEachStatement::VisitMode mode; |
| 3150 int each_pos = position(); |
3149 | 3151 |
3150 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { | 3152 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { |
3151 // Rewrite a for-in statement of the form | 3153 // Rewrite a for-in statement of the form |
3152 // | 3154 // |
3153 // for (let/const x in e) b | 3155 // for (let/const x in e) b |
3154 // | 3156 // |
3155 // into | 3157 // into |
3156 // | 3158 // |
3157 // <let x' be a temporary variable> | 3159 // <let x' be a temporary variable> |
3158 // for (x' in e) { | 3160 // for (x' in e) { |
3159 // let/const x; | 3161 // let/const x; |
3160 // x = x'; | 3162 // x = x'; |
3161 // b; | 3163 // b; |
3162 // } | 3164 // } |
3163 | 3165 |
3164 // TODO(keuchel): Move the temporary variable to the block scope, after | 3166 // TODO(keuchel): Move the temporary variable to the block scope, after |
3165 // implementing stack allocated block scoped variables. | 3167 // implementing stack allocated block scoped variables. |
3166 Variable* temp = scope_->DeclarationScope()->NewTemporary( | 3168 Variable* temp = scope_->DeclarationScope()->NewTemporary( |
3167 ast_value_factory()->dot_for_string()); | 3169 ast_value_factory()->dot_for_string()); |
3168 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 3170 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
3169 ForEachStatement* loop = | 3171 ForEachStatement* loop = |
3170 factory()->NewForEachStatement(mode, labels, pos); | 3172 factory()->NewForEachStatement(mode, labels, stmt_pos); |
3171 Target target(&this->target_stack_, loop); | 3173 Target target(&this->target_stack_, loop); |
3172 | 3174 |
3173 // The expression does not see the loop variable. | 3175 // The expression does not see the loop variable. |
3174 scope_ = saved_scope; | 3176 scope_ = saved_scope; |
3175 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3177 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3176 scope_ = for_scope; | 3178 scope_ = for_scope; |
3177 Expect(Token::RPAREN, CHECK_OK); | 3179 Expect(Token::RPAREN, CHECK_OK); |
3178 | 3180 |
3179 VariableProxy* each = scope_->NewUnresolved(factory(), name); | 3181 VariableProxy* each = scope_->NewUnresolved( |
| 3182 factory(), name, Interface::NewValue(), each_pos); |
3180 Statement* body = ParseStatement(NULL, CHECK_OK); | 3183 Statement* body = ParseStatement(NULL, CHECK_OK); |
3181 Block* body_block = | 3184 Block* body_block = |
3182 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); | 3185 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
3183 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; | 3186 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; |
3184 Assignment* assignment = factory()->NewAssignment( | 3187 Assignment* assignment = factory()->NewAssignment( |
3185 init_op, each, temp_proxy, RelocInfo::kNoPosition); | 3188 init_op, each, temp_proxy, RelocInfo::kNoPosition); |
3186 Statement* assignment_statement = factory()->NewExpressionStatement( | 3189 Statement* assignment_statement = factory()->NewExpressionStatement( |
3187 assignment, RelocInfo::kNoPosition); | 3190 assignment, RelocInfo::kNoPosition); |
3188 body_block->AddStatement(variable_statement, zone()); | 3191 body_block->AddStatement(variable_statement, zone()); |
3189 body_block->AddStatement(assignment_statement, zone()); | 3192 body_block->AddStatement(assignment_statement, zone()); |
(...skipping 13 matching lines...) Expand all Loading... |
3203 Scanner::Location lhs_location = scanner()->peek_location(); | 3206 Scanner::Location lhs_location = scanner()->peek_location(); |
3204 Expression* expression = ParseExpression(false, CHECK_OK); | 3207 Expression* expression = ParseExpression(false, CHECK_OK); |
3205 ForEachStatement::VisitMode mode; | 3208 ForEachStatement::VisitMode mode; |
3206 bool accept_OF = expression->IsVariableProxy(); | 3209 bool accept_OF = expression->IsVariableProxy(); |
3207 | 3210 |
3208 if (CheckInOrOf(accept_OF, &mode)) { | 3211 if (CheckInOrOf(accept_OF, &mode)) { |
3209 expression = this->CheckAndRewriteReferenceExpression( | 3212 expression = this->CheckAndRewriteReferenceExpression( |
3210 expression, lhs_location, "invalid_lhs_in_for", CHECK_OK); | 3213 expression, lhs_location, "invalid_lhs_in_for", CHECK_OK); |
3211 | 3214 |
3212 ForEachStatement* loop = | 3215 ForEachStatement* loop = |
3213 factory()->NewForEachStatement(mode, labels, pos); | 3216 factory()->NewForEachStatement(mode, labels, stmt_pos); |
3214 Target target(&this->target_stack_, loop); | 3217 Target target(&this->target_stack_, loop); |
3215 | 3218 |
3216 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3219 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3217 Expect(Token::RPAREN, CHECK_OK); | 3220 Expect(Token::RPAREN, CHECK_OK); |
3218 | 3221 |
3219 Statement* body = ParseStatement(NULL, CHECK_OK); | 3222 Statement* body = ParseStatement(NULL, CHECK_OK); |
3220 InitializeForEachStatement(loop, expression, enumerable, body); | 3223 InitializeForEachStatement(loop, expression, enumerable, body); |
3221 scope_ = saved_scope; | 3224 scope_ = saved_scope; |
3222 for_scope->set_end_position(scanner()->location().end_pos); | 3225 for_scope->set_end_position(scanner()->location().end_pos); |
3223 for_scope = for_scope->FinalizeBlockScope(); | 3226 for_scope = for_scope->FinalizeBlockScope(); |
3224 DCHECK(for_scope == NULL); | 3227 DCHECK(for_scope == NULL); |
3225 // Parsed for-in loop. | 3228 // Parsed for-in loop. |
3226 return loop; | 3229 return loop; |
3227 | 3230 |
3228 } else { | 3231 } else { |
3229 init = factory()->NewExpressionStatement( | 3232 init = factory()->NewExpressionStatement(expression, position()); |
3230 expression, RelocInfo::kNoPosition); | |
3231 } | 3233 } |
3232 } | 3234 } |
3233 } | 3235 } |
3234 | 3236 |
3235 // Standard 'for' loop | 3237 // Standard 'for' loop |
3236 ForStatement* loop = factory()->NewForStatement(labels, pos); | 3238 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos); |
3237 Target target(&this->target_stack_, loop); | 3239 Target target(&this->target_stack_, loop); |
3238 | 3240 |
3239 // Parsed initializer at this point. | 3241 // Parsed initializer at this point. |
3240 Expect(Token::SEMICOLON, CHECK_OK); | 3242 Expect(Token::SEMICOLON, CHECK_OK); |
3241 | 3243 |
3242 // If there are let bindings, then condition and the next statement of the | 3244 // If there are let bindings, then condition and the next statement of the |
3243 // for loop must be parsed in a new scope. | 3245 // for loop must be parsed in a new scope. |
3244 Scope* inner_scope = NULL; | 3246 Scope* inner_scope = NULL; |
3245 if (let_bindings.length() > 0) { | 3247 if (let_bindings.length() > 0) { |
3246 inner_scope = NewScope(for_scope, BLOCK_SCOPE); | 3248 inner_scope = NewScope(for_scope, BLOCK_SCOPE); |
3247 inner_scope->set_start_position(scanner()->location().beg_pos); | 3249 inner_scope->set_start_position(scanner()->location().beg_pos); |
3248 scope_ = inner_scope; | 3250 scope_ = inner_scope; |
3249 } | 3251 } |
3250 | 3252 |
3251 Expression* cond = NULL; | 3253 Expression* cond = NULL; |
3252 if (peek() != Token::SEMICOLON) { | 3254 if (peek() != Token::SEMICOLON) { |
3253 cond = ParseExpression(true, CHECK_OK); | 3255 cond = ParseExpression(true, CHECK_OK); |
3254 } | 3256 } |
3255 Expect(Token::SEMICOLON, CHECK_OK); | 3257 Expect(Token::SEMICOLON, CHECK_OK); |
3256 | 3258 |
3257 Statement* next = NULL; | 3259 Statement* next = NULL; |
3258 if (peek() != Token::RPAREN) { | 3260 if (peek() != Token::RPAREN) { |
| 3261 int next_pos = position(); |
3259 Expression* exp = ParseExpression(true, CHECK_OK); | 3262 Expression* exp = ParseExpression(true, CHECK_OK); |
3260 next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition); | 3263 next = factory()->NewExpressionStatement(exp, next_pos); |
3261 } | 3264 } |
3262 Expect(Token::RPAREN, CHECK_OK); | 3265 Expect(Token::RPAREN, CHECK_OK); |
3263 | 3266 |
3264 Statement* body = ParseStatement(NULL, CHECK_OK); | 3267 Statement* body = ParseStatement(NULL, CHECK_OK); |
3265 | 3268 |
3266 Statement* result = NULL; | 3269 Statement* result = NULL; |
3267 if (let_bindings.length() > 0) { | 3270 if (let_bindings.length() > 0) { |
3268 scope_ = for_scope; | 3271 scope_ = for_scope; |
3269 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, | 3272 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, |
3270 init, cond, next, body, CHECK_OK); | 3273 init, cond, next, body, CHECK_OK); |
(...skipping 1684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4955 | 4958 |
4956 // We cannot internalize on a background thread; a foreground task will take | 4959 // We cannot internalize on a background thread; a foreground task will take |
4957 // care of calling Parser::Internalize just before compilation. | 4960 // care of calling Parser::Internalize just before compilation. |
4958 | 4961 |
4959 if (compile_options() == ScriptCompiler::kProduceParserCache) { | 4962 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
4960 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); | 4963 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); |
4961 log_ = NULL; | 4964 log_ = NULL; |
4962 } | 4965 } |
4963 } | 4966 } |
4964 } } // namespace v8::internal | 4967 } } // namespace v8::internal |
OLD | NEW |