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 "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "api.h" | 7 #include "api.h" |
| 8 #include "ast.h" | 8 #include "ast.h" |
| 9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
| 10 #include "char-predicates-inl.h" | 10 #include "char-predicates-inl.h" |
| (...skipping 2819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2830 } | 2830 } |
| 2831 | 2831 |
| 2832 for_of->Initialize(each, subject, body, | 2832 for_of->Initialize(each, subject, body, |
| 2833 assign_iterator, next_result, result_done, assign_each); | 2833 assign_iterator, next_result, result_done, assign_each); |
| 2834 } else { | 2834 } else { |
| 2835 stmt->Initialize(each, subject, body); | 2835 stmt->Initialize(each, subject, body); |
| 2836 } | 2836 } |
| 2837 } | 2837 } |
| 2838 | 2838 |
| 2839 | 2839 |
| 2840 Statement* Parser::Assign(Token::Value op, | |
| 2841 VariableProxy* dst, | |
| 2842 Expression* src, | |
| 2843 int pos) { | |
| 2844 Assignment* x = factory()->NewAssignment(op, dst, src, pos); | |
| 2845 return factory()->NewExpressionStatement(x, pos); | |
| 2846 } | |
| 2847 | |
| 2848 | |
| 2849 Variable* Parser::Temporary(Handle<String> name) { | |
| 2850 return scope_->DeclarationScope()->NewTemporary(name); | |
| 2851 } | |
| 2852 | |
| 2853 Statement* Parser::DesugarLetBindingsInForStatement( | |
| 2854 Scope* inner_scope, ZoneStringList* names, ForStatement* loop, | |
| 2855 Statement* init, Expression* cond, Statement* next, bool* ok) { | |
| 2856 // ES6 13.6.3.4 specifies that on each loop iteration the let variables are | |
| 2857 // copied into a new environment. After copying, the "next" statement of the | |
| 2858 // loop is executed to update the loop variables. The the loop condition is | |
|
rossberg
2014/05/22 12:55:44
Nit: "The the"
ulan
2014/05/23 14:29:03
Done.
| |
| 2859 // checked and the loop body is executed. | |
| 2860 // | |
| 2861 // We rewrite a for statement of the form | |
| 2862 // | |
| 2863 // for (let x = i; cond; next) body | |
| 2864 // | |
| 2865 // into | |
| 2866 // | |
| 2867 // { | |
| 2868 // let x = i; | |
| 2869 // temp_x = x; | |
| 2870 // flag = 1; | |
| 2871 // for (;;) { | |
| 2872 // let x = temp_x; | |
| 2873 // if (flag == 1) { | |
| 2874 // flag = 0; | |
| 2875 // } else { | |
| 2876 // next; | |
| 2877 // } | |
| 2878 // if (cond) { | |
| 2879 // <empty> | |
| 2880 // } else { | |
| 2881 // break; | |
| 2882 // } | |
| 2883 // b | |
| 2884 // temp_x = x; | |
| 2885 // } | |
| 2886 // } | |
|
rossberg
2014/05/22 12:55:44
So, eventually, there should be a comment here alo
ulan
2014/05/23 14:29:03
As discussed offline, only lets and consts are all
| |
| 2887 | |
| 2888 ASSERT(names->length() > 0); | |
| 2889 Scope* for_scope = scope_; | |
| 2890 ZoneList<Variable*> temps(names->length(), zone()); | |
| 2891 | |
| 2892 Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false, | |
| 2893 RelocInfo::kNoPosition); | |
| 2894 outer_block->AddStatement(init, zone()); | |
| 2895 | |
| 2896 Handle<String> temp_name = isolate()->factory()->dot_for_string(); | |
| 2897 Handle<Smi> smi0 = handle(Smi::FromInt(0), isolate()); | |
| 2898 Handle<Smi> smi1 = handle(Smi::FromInt(1), isolate()); | |
| 2899 | |
| 2900 | |
| 2901 // For each let variable x: | |
| 2902 // make statement: temp_x = x. | |
| 2903 for (int i = 0; i < names->length(); i++) { | |
| 2904 VariableProxy* proxy = | |
| 2905 NewUnresolved(names->at(i), LET, Interface::NewValue()); | |
| 2906 Variable* temp = Temporary(temp_name); | |
| 2907 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | |
| 2908 Statement* assignment = Assign(Token::ASSIGN, temp_proxy, proxy); | |
| 2909 outer_block->AddStatement(assignment, zone()); | |
| 2910 temps.Add(temp, zone()); | |
| 2911 } | |
| 2912 | |
| 2913 Variable* flag = Temporary(temp_name); | |
| 2914 // Make statement: flag = 1. | |
| 2915 { | |
| 2916 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | |
| 2917 Expression* const1 = factory()->NewLiteral(smi1, RelocInfo::kNoPosition); | |
| 2918 Statement* assignment = Assign(Token::ASSIGN, flag_proxy, const1); | |
| 2919 outer_block->AddStatement(assignment, zone()); | |
| 2920 } | |
| 2921 | |
| 2922 outer_block->AddStatement(loop, zone()); | |
| 2923 outer_block->set_scope(for_scope); | |
| 2924 scope_ = inner_scope; | |
| 2925 | |
| 2926 Statement* body = ParseStatement(NULL, CHECK_OK); | |
|
rossberg
2014/05/22 12:55:44
It's somewhat inappropriate to do actual parsing i
ulan
2014/05/23 14:29:03
Done.
| |
| 2927 | |
| 2928 Block* inner_block = factory()->NewBlock(NULL, 2 * names->length() + 3, | |
| 2929 false, RelocInfo::kNoPosition); | |
| 2930 int pos = scanner()->location().beg_pos; | |
| 2931 ZoneList<Variable*> inner_vars(names->length(), zone()); | |
| 2932 | |
| 2933 // For each let variable x: | |
| 2934 // make statement: let x = temp_x. | |
| 2935 for (int i = 0; i < names->length(); i++) { | |
| 2936 VariableProxy* proxy = | |
| 2937 NewUnresolved(names->at(i), LET, Interface::NewValue()); | |
| 2938 Declaration* declaration = | |
| 2939 factory()->NewVariableDeclaration(proxy, LET, scope_, pos); | |
| 2940 Declare(declaration, true, CHECK_OK); | |
| 2941 inner_vars.Add(declaration->proxy()->var(), zone()); | |
| 2942 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | |
| 2943 Statement* statement = Assign(Token::INIT_LET, proxy, temp_proxy, pos); | |
| 2944 proxy->var()->set_initializer_position(pos); | |
| 2945 inner_block->AddStatement(statement, zone()); | |
| 2946 } | |
| 2947 | |
| 2948 // Make statement: if (flag == 1) { flag = 0; } else { next; }. | |
| 2949 { | |
| 2950 Expression* compare = NULL; | |
| 2951 // Make compare expresion: flag == 1. | |
| 2952 { | |
| 2953 Expression* const1 = factory()->NewLiteral(smi1, RelocInfo::kNoPosition); | |
| 2954 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | |
| 2955 compare = factory()->NewCompareOperation( | |
| 2956 Token::EQ, flag_proxy, const1, RelocInfo::kNoPosition); | |
| 2957 } | |
| 2958 Statement* clear_flag = NULL; | |
| 2959 // Make statement: flag = 0. | |
| 2960 { | |
| 2961 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | |
| 2962 Expression* const0 = factory()->NewLiteral(smi0, RelocInfo::kNoPosition); | |
| 2963 clear_flag = Assign(Token::ASSIGN, flag_proxy, const0); | |
| 2964 } | |
| 2965 Statement* clear_flag_or_next = factory()->NewIfStatement( | |
| 2966 compare, clear_flag, next, RelocInfo::kNoPosition); | |
| 2967 inner_block->AddStatement(clear_flag_or_next, zone()); | |
| 2968 } | |
| 2969 | |
| 2970 | |
| 2971 // Make statement: if (cond) { } else { break; }. | |
| 2972 { | |
| 2973 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | |
| 2974 BreakableStatement* t = LookupBreakTarget(Handle<String>(), CHECK_OK); | |
| 2975 Statement* stop = factory()->NewBreakStatement(t, RelocInfo::kNoPosition); | |
| 2976 Statement* if_not_cond_break = factory()->NewIfStatement( | |
| 2977 cond, empty, stop, RelocInfo::kNoPosition); | |
| 2978 inner_block->AddStatement(if_not_cond_break, zone()); | |
| 2979 } | |
| 2980 | |
| 2981 inner_block->AddStatement(body, zone()); | |
| 2982 | |
| 2983 // For each let variable x: | |
| 2984 // make statement: temp_x = x; | |
| 2985 for (int i = 0; i < names->length(); i++) { | |
| 2986 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | |
| 2987 int pos = scanner()->location().end_pos; | |
| 2988 VariableProxy* proxy = factory()->NewVariableProxy(inner_vars.at(i), pos); | |
| 2989 Statement* statement = Assign(Token::ASSIGN, temp_proxy, proxy); | |
| 2990 inner_block->AddStatement(statement, zone()); | |
| 2991 } | |
| 2992 | |
| 2993 inner_scope->set_end_position(scanner()->location().end_pos); | |
| 2994 inner_block->set_scope(inner_scope); | |
| 2995 scope_ = for_scope; | |
| 2996 | |
| 2997 loop->Initialize(NULL, NULL, NULL, inner_block); | |
| 2998 return outer_block; | |
| 2999 } | |
| 3000 | |
| 3001 | |
| 2840 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { | 3002 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
| 2841 // ForStatement :: | 3003 // ForStatement :: |
| 2842 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 3004 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| 2843 | 3005 |
| 2844 int pos = peek_position(); | 3006 int pos = peek_position(); |
| 2845 Statement* init = NULL; | 3007 Statement* init = NULL; |
| 3008 ZoneStringList let_bindings(1, zone()); | |
|
rossberg
2014/05/22 12:55:44
lexical_bindings
ulan
2014/05/23 14:29:03
Leaving as is.
| |
| 2846 | 3009 |
| 2847 // Create an in-between scope for let-bound iteration variables. | 3010 // Create an in-between scope for let-bound iteration variables. |
| 2848 Scope* saved_scope = scope_; | 3011 Scope* saved_scope = scope_; |
| 2849 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3012 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
| 2850 scope_ = for_scope; | 3013 scope_ = for_scope; |
| 2851 | 3014 |
| 2852 Expect(Token::FOR, CHECK_OK); | 3015 Expect(Token::FOR, CHECK_OK); |
| 2853 Expect(Token::LPAREN, CHECK_OK); | 3016 Expect(Token::LPAREN, CHECK_OK); |
| 2854 for_scope->set_start_position(scanner()->location().beg_pos); | 3017 for_scope->set_start_position(scanner()->location().beg_pos); |
| 2855 if (peek() != Token::SEMICOLON) { | 3018 if (peek() != Token::SEMICOLON) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2887 ASSERT(for_scope == NULL); | 3050 ASSERT(for_scope == NULL); |
| 2888 // Parsed for-in loop w/ variable/const declaration. | 3051 // Parsed for-in loop w/ variable/const declaration. |
| 2889 return result; | 3052 return result; |
| 2890 } else { | 3053 } else { |
| 2891 init = variable_statement; | 3054 init = variable_statement; |
| 2892 } | 3055 } |
| 2893 } else if (peek() == Token::LET) { | 3056 } else if (peek() == Token::LET) { |
| 2894 Handle<String> name; | 3057 Handle<String> name; |
| 2895 VariableDeclarationProperties decl_props = kHasNoInitializers; | 3058 VariableDeclarationProperties decl_props = kHasNoInitializers; |
| 2896 Block* variable_statement = | 3059 Block* variable_statement = |
| 2897 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, | 3060 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, |
| 2898 CHECK_OK); | 3061 &name, CHECK_OK); |
| 2899 bool accept_IN = !name.is_null() && decl_props != kHasInitializers; | 3062 bool accept_IN = !name.is_null() && decl_props != kHasInitializers; |
| 2900 bool accept_OF = decl_props == kHasNoInitializers; | 3063 bool accept_OF = decl_props == kHasNoInitializers; |
| 2901 ForEachStatement::VisitMode mode; | 3064 ForEachStatement::VisitMode mode; |
| 2902 | 3065 |
| 2903 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { | 3066 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { |
| 2904 // Rewrite a for-in statement of the form | 3067 // Rewrite a for-in statement of the form |
| 2905 // | 3068 // |
| 2906 // for (let x in e) b | 3069 // for (let x in e) b |
| 2907 // | 3070 // |
| 2908 // into | 3071 // into |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2991 } | 3154 } |
| 2992 } | 3155 } |
| 2993 | 3156 |
| 2994 // Standard 'for' loop | 3157 // Standard 'for' loop |
| 2995 ForStatement* loop = factory()->NewForStatement(labels, pos); | 3158 ForStatement* loop = factory()->NewForStatement(labels, pos); |
| 2996 Target target(&this->target_stack_, loop); | 3159 Target target(&this->target_stack_, loop); |
| 2997 | 3160 |
| 2998 // Parsed initializer at this point. | 3161 // Parsed initializer at this point. |
| 2999 Expect(Token::SEMICOLON, CHECK_OK); | 3162 Expect(Token::SEMICOLON, CHECK_OK); |
| 3000 | 3163 |
| 3164 // If there are let bindings, then condition and the next statement of the | |
|
rossberg
2014/05/22 12:55:44
"let bindings" -> "lexical declarations"
ulan
2014/05/23 14:29:03
Leaving as is.
| |
| 3165 // for loop must be parsed in a new scope. | |
| 3166 Scope* inner_scope = NULL; | |
| 3167 if (let_bindings.length() > 0) { | |
| 3168 inner_scope = NewScope(for_scope, BLOCK_SCOPE); | |
| 3169 inner_scope->set_start_position(scanner()->location().beg_pos); | |
| 3170 scope_ = inner_scope; | |
| 3171 } | |
| 3172 | |
| 3001 Expression* cond = NULL; | 3173 Expression* cond = NULL; |
| 3002 if (peek() != Token::SEMICOLON) { | 3174 if (peek() != Token::SEMICOLON) { |
| 3003 cond = ParseExpression(true, CHECK_OK); | 3175 cond = ParseExpression(true, CHECK_OK); |
| 3004 } | 3176 } |
| 3005 Expect(Token::SEMICOLON, CHECK_OK); | 3177 Expect(Token::SEMICOLON, CHECK_OK); |
| 3006 | 3178 |
| 3007 Statement* next = NULL; | 3179 Statement* next = NULL; |
| 3008 if (peek() != Token::RPAREN) { | 3180 if (peek() != Token::RPAREN) { |
| 3009 Expression* exp = ParseExpression(true, CHECK_OK); | 3181 Expression* exp = ParseExpression(true, CHECK_OK); |
| 3010 next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition); | 3182 next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition); |
| 3011 } | 3183 } |
| 3012 Expect(Token::RPAREN, CHECK_OK); | 3184 Expect(Token::RPAREN, CHECK_OK); |
| 3013 | 3185 |
| 3014 Statement* body = ParseStatement(NULL, CHECK_OK); | 3186 Statement* result = NULL; |
| 3015 scope_ = saved_scope; | 3187 if (let_bindings.length() > 0) { |
| 3016 for_scope->set_end_position(scanner()->location().end_pos); | 3188 scope_ = for_scope; |
| 3017 for_scope = for_scope->FinalizeBlockScope(); | 3189 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, |
| 3018 if (for_scope != NULL) { | 3190 init, cond, next, CHECK_OK); |
| 3019 // Rewrite a for statement of the form | 3191 scope_ = saved_scope; |
| 3020 // | 3192 for_scope->set_end_position(scanner()->location().end_pos); |
| 3021 // for (let x = i; c; n) b | |
| 3022 // | |
| 3023 // into | |
| 3024 // | |
| 3025 // { | |
| 3026 // let x = i; | |
| 3027 // for (; c; n) b | |
| 3028 // } | |
| 3029 ASSERT(init != NULL); | |
| 3030 Block* result = factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); | |
| 3031 result->AddStatement(init, zone()); | |
| 3032 result->AddStatement(loop, zone()); | |
| 3033 result->set_scope(for_scope); | |
| 3034 loop->Initialize(NULL, cond, next, body); | |
| 3035 return result; | |
| 3036 } else { | 3193 } else { |
| 3194 Statement* body = ParseStatement(NULL, CHECK_OK); | |
| 3037 loop->Initialize(init, cond, next, body); | 3195 loop->Initialize(init, cond, next, body); |
| 3038 return loop; | 3196 result = loop; |
| 3197 scope_ = saved_scope; | |
| 3198 for_scope->set_end_position(scanner()->location().end_pos); | |
| 3199 for_scope->FinalizeBlockScope(); | |
| 3039 } | 3200 } |
| 3201 return result; | |
| 3040 } | 3202 } |
| 3041 | 3203 |
| 3042 | 3204 |
| 3043 DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) { | 3205 DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) { |
| 3044 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | 3206 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser |
| 3045 // contexts this is used as a statement which invokes the debugger as i a | 3207 // contexts this is used as a statement which invokes the debugger as i a |
| 3046 // break point is present. | 3208 // break point is present. |
| 3047 // DebuggerStatement :: | 3209 // DebuggerStatement :: |
| 3048 // 'debugger' ';' | 3210 // 'debugger' ';' |
| 3049 | 3211 |
| (...skipping 1568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4618 ASSERT(info()->isolate()->has_pending_exception()); | 4780 ASSERT(info()->isolate()->has_pending_exception()); |
| 4619 } else { | 4781 } else { |
| 4620 result = ParseProgram(); | 4782 result = ParseProgram(); |
| 4621 } | 4783 } |
| 4622 } | 4784 } |
| 4623 info()->SetFunction(result); | 4785 info()->SetFunction(result); |
| 4624 return (result != NULL); | 4786 return (result != NULL); |
| 4625 } | 4787 } |
| 4626 | 4788 |
| 4627 } } // namespace v8::internal | 4789 } } // namespace v8::internal |
| OLD | NEW |