@@ -2846,29 +2846,33 @@ Statement* Parser::DesugarLetBindingsInForStatement(
2846
2846
//
2847
2847
// We rewrite a for statement of the form
2848
2848
//
2849
- // for (let x = i; cond; next) body
2849
+ // labels: for (let x = i; cond; next) body
2850
2850
//
2851
2851
// into
2852
2852
//
2853
2853
// {
2854
- // let x = i;
2855
- // temp_x = x;
2856
- // flag = 1;
2857
- // for (;;) {
2858
- // let x = temp_x;
2859
- // if (flag == 1) {
2860
- // flag = 0;
2861
- // } else {
2862
- // next;
2863
- // }
2854
+ // let x = i;
2855
+ // temp_x = x;
2856
+ // first = 1;
2857
+ // outer: for (;;) {
2858
+ // let x = temp_x;
2859
+ // if (first == 1) {
2860
+ // first = 0;
2861
+ // } else {
2862
+ // next;
2863
+ // }
2864
+ // flag = 1;
2865
+ // labels: for (; flag == 1; flag = 0, temp_x = x) {
2864
2866
// if (cond) {
2865
- // <empty>
2867
+ // body
2866
2868
// } else {
2867
- // break;
2869
+ // break outer ;
2868
2870
// }
2869
- // b
2870
- // temp_x = x;
2871
- // }
2871
+ // }
2872
+ // if (flag == 1) {
2873
+ // break;
2874
+ // }
2875
+ // }
2872
2876
// }
2873
2877
2874
2878
DCHECK (names->length () > 0 );
@@ -2896,24 +2900,33 @@ Statement* Parser::DesugarLetBindingsInForStatement(
2896
2900
temps.Add (temp, zone ());
2897
2901
}
2898
2902
2899
- Variable* flag = scope_->DeclarationScope ()->NewTemporary (temp_name);
2900
- // Make statement: flag = 1.
2901
- {
2902
- VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag);
2903
+ Variable* first = NULL ;
2904
+ // Make statement: first = 1.
2905
+ if (next) {
2906
+ first = scope_->DeclarationScope ()->NewTemporary (temp_name);
2907
+ VariableProxy* first_proxy = factory ()->NewVariableProxy (first);
2903
2908
Expression* const1 = factory ()->NewSmiLiteral (1 , RelocInfo::kNoPosition );
2904
2909
Assignment* assignment = factory ()->NewAssignment (
2905
- Token::ASSIGN, flag_proxy , const1, RelocInfo::kNoPosition );
2906
- Statement* assignment_statement = factory ()-> NewExpressionStatement (
2907
- assignment, RelocInfo::kNoPosition );
2910
+ Token::ASSIGN, first_proxy , const1, RelocInfo::kNoPosition );
2911
+ Statement* assignment_statement =
2912
+ factory ()-> NewExpressionStatement ( assignment, RelocInfo::kNoPosition );
2908
2913
outer_block->AddStatement (assignment_statement, zone ());
2909
2914
}
2910
2915
2911
- outer_block->AddStatement (loop, zone ());
2916
+ // Make statement: outer: for (;;)
2917
+ // Note that we don't actually create the label, or set this loop up as an
2918
+ // explicit break target, instead handing it directly to those nodes that
2919
+ // need to know about it. This should be safe because we don't run any code
2920
+ // in this function that looks up break targets.
2921
+ ForStatement* outer_loop =
2922
+ factory ()->NewForStatement (NULL , RelocInfo::kNoPosition );
2923
+ outer_block->AddStatement (outer_loop, zone ());
2924
+
2912
2925
outer_block->set_scope (for_scope);
2913
2926
scope_ = inner_scope;
2914
2927
2915
- Block* inner_block = factory ()->NewBlock (NULL , 2 * names->length () + 3 ,
2916
- false , RelocInfo::kNoPosition );
2928
+ Block* inner_block = factory ()->NewBlock (NULL , names->length () + 4 , false ,
2929
+ RelocInfo::kNoPosition );
2917
2930
int pos = scanner ()->location ().beg_pos ;
2918
2931
ZoneList<Variable*> inner_vars (names->length (), zone ());
2919
2932
@@ -2935,61 +2948,118 @@ Statement* Parser::DesugarLetBindingsInForStatement(
2935
2948
inner_block->AddStatement (assignment_statement, zone ());
2936
2949
}
2937
2950
2938
- // Make statement: if (flag == 1) { flag = 0; } else { next; }.
2951
+ // Make statement: if (first == 1) { first = 0; } else { next; }
2939
2952
if (next) {
2953
+ DCHECK (first);
2940
2954
Expression* compare = NULL ;
2941
- // Make compare expresion: flag == 1.
2955
+ // Make compare expression: first == 1.
2942
2956
{
2943
2957
Expression* const1 = factory ()->NewSmiLiteral (1 , RelocInfo::kNoPosition );
2944
- VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag );
2945
- compare = factory ()-> NewCompareOperation (
2946
- Token::EQ, flag_proxy , const1, pos);
2958
+ VariableProxy* first_proxy = factory ()->NewVariableProxy (first );
2959
+ compare =
2960
+ factory ()-> NewCompareOperation ( Token::EQ, first_proxy , const1, pos);
2947
2961
}
2948
- Statement* clear_flag = NULL ;
2949
- // Make statement: flag = 0.
2962
+ Statement* clear_first = NULL ;
2963
+ // Make statement: first = 0.
2950
2964
{
2951
- VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag );
2965
+ VariableProxy* first_proxy = factory ()->NewVariableProxy (first );
2952
2966
Expression* const0 = factory ()->NewSmiLiteral (0 , RelocInfo::kNoPosition );
2953
2967
Assignment* assignment = factory ()->NewAssignment (
2954
- Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition );
2955
- clear_flag = factory ()->NewExpressionStatement (assignment, pos);
2968
+ Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition );
2969
+ clear_first =
2970
+ factory ()->NewExpressionStatement (assignment, RelocInfo::kNoPosition );
2956
2971
}
2957
- Statement* clear_flag_or_next = factory ()->NewIfStatement (
2958
- compare, clear_flag , next, RelocInfo::kNoPosition );
2959
- inner_block->AddStatement (clear_flag_or_next , zone ());
2972
+ Statement* clear_first_or_next = factory ()->NewIfStatement (
2973
+ compare, clear_first , next, RelocInfo::kNoPosition );
2974
+ inner_block->AddStatement (clear_first_or_next , zone ());
2960
2975
}
2961
2976
2977
+ Variable* flag = scope_->DeclarationScope ()->NewTemporary (temp_name);
2978
+ // Make statement: flag = 1.
2979
+ {
2980
+ VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag);
2981
+ Expression* const1 = factory ()->NewSmiLiteral (1 , RelocInfo::kNoPosition );
2982
+ Assignment* assignment = factory ()->NewAssignment (
2983
+ Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition );
2984
+ Statement* assignment_statement =
2985
+ factory ()->NewExpressionStatement (assignment, RelocInfo::kNoPosition );
2986
+ inner_block->AddStatement (assignment_statement, zone ());
2987
+ }
2988
+
2989
+ // Make cond expression for main loop: flag == 1.
2990
+ Expression* flag_cond = NULL ;
2991
+ {
2992
+ Expression* const1 = factory ()->NewSmiLiteral (1 , RelocInfo::kNoPosition );
2993
+ VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag);
2994
+ flag_cond =
2995
+ factory ()->NewCompareOperation (Token::EQ, flag_proxy, const1, pos);
2996
+ }
2962
2997
2963
- // Make statement: if (cond) { } else { break; }.
2998
+ // Create chain of expressions "flag = 0, temp_x = x, ..."
2999
+ Statement* compound_next_statement = NULL ;
3000
+ {
3001
+ Expression* compound_next = NULL ;
3002
+ // Make expression: flag = 0.
3003
+ {
3004
+ VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag);
3005
+ Expression* const0 = factory ()->NewSmiLiteral (0 , RelocInfo::kNoPosition );
3006
+ compound_next = factory ()->NewAssignment (Token::ASSIGN, flag_proxy,
3007
+ const0, RelocInfo::kNoPosition );
3008
+ }
3009
+
3010
+ // Make the comma-separated list of temp_x = x assignments.
3011
+ for (int i = 0 ; i < names->length (); i++) {
3012
+ VariableProxy* temp_proxy = factory ()->NewVariableProxy (temps.at (i));
3013
+ VariableProxy* proxy = factory ()->NewVariableProxy (inner_vars.at (i), pos);
3014
+ Assignment* assignment = factory ()->NewAssignment (
3015
+ Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition );
3016
+ compound_next = factory ()->NewBinaryOperation (
3017
+ Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition );
3018
+ }
3019
+
3020
+ compound_next_statement = factory ()->NewExpressionStatement (
3021
+ compound_next, RelocInfo::kNoPosition );
3022
+ }
3023
+
3024
+ // Make statement: if (cond) { body; } else { break outer; }
3025
+ Statement* body_or_stop = body;
2964
3026
if (cond) {
2965
- Statement* empty = factory ()->NewEmptyStatement (RelocInfo::kNoPosition );
2966
- BreakableStatement* t = LookupBreakTarget (NULL , CHECK_OK);
2967
- Statement* stop = factory ()->NewBreakStatement (t, RelocInfo::kNoPosition );
2968
- Statement* if_not_cond_break = factory ()->NewIfStatement (
2969
- cond, empty, stop, cond->position ());
2970
- inner_block->AddStatement (if_not_cond_break, zone ());
3027
+ Statement* stop =
3028
+ factory ()->NewBreakStatement (outer_loop, RelocInfo::kNoPosition );
3029
+ body_or_stop =
3030
+ factory ()->NewIfStatement (cond, body, stop, cond->position ());
2971
3031
}
2972
3032
2973
- inner_block->AddStatement (body, zone ());
3033
+ // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
3034
+ // Note that we re-use the original loop node, which retains it labels
3035
+ // and ensures that any break or continue statements in body point to
3036
+ // the right place.
3037
+ loop->Initialize (NULL , flag_cond, compound_next_statement, body_or_stop);
3038
+ inner_block->AddStatement (loop, zone ());
2974
3039
2975
- // For each let variable x:
2976
- // make statement: temp_x = x;
2977
- for (int i = 0 ; i < names->length (); i++) {
2978
- VariableProxy* temp_proxy = factory ()->NewVariableProxy (temps.at (i));
2979
- int pos = scanner ()->location ().end_pos ;
2980
- VariableProxy* proxy = factory ()->NewVariableProxy (inner_vars.at (i), pos);
2981
- Assignment* assignment = factory ()->NewAssignment (
2982
- Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition );
2983
- Statement* assignment_statement = factory ()->NewExpressionStatement (
2984
- assignment, RelocInfo::kNoPosition );
2985
- inner_block->AddStatement (assignment_statement, zone ());
3040
+ // Make statement: if (flag == 1) { break; }
3041
+ {
3042
+ Expression* compare = NULL ;
3043
+ // Make compare expresion: flag == 1.
3044
+ {
3045
+ Expression* const1 = factory ()->NewSmiLiteral (1 , RelocInfo::kNoPosition );
3046
+ VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag);
3047
+ compare =
3048
+ factory ()->NewCompareOperation (Token::EQ, flag_proxy, const1, pos);
3049
+ }
3050
+ Statement* stop =
3051
+ factory ()->NewBreakStatement (outer_loop, RelocInfo::kNoPosition );
3052
+ Statement* empty = factory ()->NewEmptyStatement (RelocInfo::kNoPosition );
3053
+ Statement* if_flag_break =
3054
+ factory ()->NewIfStatement (compare, stop, empty, RelocInfo::kNoPosition );
3055
+ inner_block->AddStatement (if_flag_break, zone ());
2986
3056
}
2987
3057
2988
3058
inner_scope->set_end_position (scanner ()->location ().end_pos );
2989
3059
inner_block->set_scope (inner_scope);
2990
3060
scope_ = for_scope;
2991
3061
2992
- loop ->Initialize (NULL , NULL , NULL , inner_block);
3062
+ outer_loop ->Initialize (NULL , NULL , NULL , inner_block);
2993
3063
return outer_block;
2994
3064
}
2995
3065
0 commit comments