diff --git a/src/compiler/hxb/hxbReader.ml b/src/compiler/hxb/hxbReader.ml index 2848b4df5fe..e710c8033d0 100644 --- a/src/compiler/hxb/hxbReader.ml +++ b/src/compiler/hxb/hxbReader.ml @@ -1233,11 +1233,6 @@ class hxb_reader let e1 = loop () in let e2 = loop () in TWhile(e1,e2,DoWhile),(Some api#basic_types.tvoid) - | 86 -> - let v = declare_local () in - let e1 = loop () in - let e2 = loop () in - TFor(v,e1,e2),(Some api#basic_types.tvoid) (* control flow 90-99 *) | 90 -> diff --git a/src/compiler/hxb/hxbWriter.ml b/src/compiler/hxb/hxbWriter.ml index 619e7c499e9..8bd88f42bed 100644 --- a/src/compiler/hxb/hxbWriter.ml +++ b/src/compiler/hxb/hxbWriter.ml @@ -1488,12 +1488,6 @@ module HxbWriter = struct loop e1; loop e2; false; - | TFor(v,e1,e2) -> - Chunk.write_u8 writer.chunk 86; - declare_var v; - loop e1; - loop e2; - false; (* control flow 90-99 *) | TReturn None -> Chunk.write_u8 writer.chunk 90; diff --git a/src/context/display/diagnostics.ml b/src/context/display/diagnostics.ml index ceae6d3ffe1..b6a0cd0376b 100644 --- a/src/context/display/diagnostics.ml +++ b/src/context/display/diagnostics.ml @@ -77,7 +77,7 @@ let check_other_things com e = | TCall({eexpr = TField(e1,fa)},el) when not in_value && PurityState.is_pure_field_access fa -> compound "call" el e.epos | TNew _ | TCall _ | TBinop ((Ast.OpAssignOp _ | Ast.OpAssign),_,_) | TUnop ((Ast.Increment | Ast.Decrement),_,_) | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) - | TIf _ | TTry _ | TSwitch _ | TWhile _ | TFor _ -> + | TIf _ | TTry _ | TSwitch _ | TWhile _ -> had_effect := true; Type.iter (loop true) e | TParenthesis e1 | TMeta(_,e1) -> diff --git a/src/context/display/statistics.ml b/src/context/display/statistics.ml index 06216867a2a..4bac299939e 100644 --- a/src/context/display/statistics.ml +++ b/src/context/display/statistics.ml @@ -175,10 +175,6 @@ let collect_statistics ctx pos_filters with_expressions = | TVar(v,eo) -> Option.may loop eo; var_decl v; - | TFor(v,e1,e2) -> - var_decl v; - loop e1; - loop e2; | TFunction tf -> List.iter (fun (v,_) -> var_decl v) tf.tf_args; loop tf.tf_expr; diff --git a/src/core/json/genjson.ml b/src/core/json/genjson.ml index 6f5838c7c1c..c06bee22da1 100644 --- a/src/core/json/genjson.ml +++ b/src/core/json/genjson.ml @@ -420,12 +420,6 @@ and generate_texpr ctx e = | TBlock el -> let el = List.map (generate_texpr ctx) el in "TBlock",Some (jarray el) - | TFor(v,e1,e2) -> - "TFor",Some (jobject [ - "v",generate_tvar ctx v; - "expr1",generate_texpr ctx e1; - "expr2",generate_texpr ctx e2; - ]); | TIf(e1,e2,eo) -> "TIf",Some (jobject [ "eif",generate_texpr ctx e1; diff --git a/src/core/tOther.ml b/src/core/tOther.ml index 20be78d1968..d7331a625ac 100644 --- a/src/core/tOther.ml +++ b/src/core/tOther.ml @@ -143,9 +143,6 @@ module TExprToExpr = struct and eo = eopt eo in EVars ([mk_evar ~final ?t ?eo ~meta:v.v_meta (v.v_name,v.v_pos)]) | TBlock el -> EBlock (List.map convert_expr el) - | TFor (v,it,e) -> - let ein = (EBinop (OpIn,(EConst (Ident v.v_name),it.epos),convert_expr it),it.epos) in - EFor (ein,convert_expr e) | TIf (e,e1,e2) -> EIf (convert_expr e,convert_expr e1,eopt e2) | TWhile (e1,e2,flag) -> EWhile (convert_expr e1, convert_expr e2, flag) | TSwitch {switch_subject = e;switch_cases = cases;switch_default = def} -> diff --git a/src/core/tPrinting.ml b/src/core/tPrinting.ml index 47c3a772364..0d44f74ca2e 100644 --- a/src/core/tPrinting.ml +++ b/src/core/tPrinting.ml @@ -197,7 +197,6 @@ let s_expr_kind e = | TFunction _ -> "Function" | TVar _ -> "Vars" | TBlock _ -> "Block" - | TFor (_,_,_) -> "For" | TIf (_,_,_) -> "If" | TWhile (_,_,_) -> "While" | TSwitch _ -> "Switch" @@ -263,8 +262,6 @@ let rec s_expr_pretty print_var_ids tabs top_level s_type e = (match el with | [] -> "{}" | _ -> s ^ tabs ^ "}") - | TFor (v,econd,e) -> - sprintf "for (%s in %s) %s" (local v) (loop econd) (loop e) | TIf (e,e1,e2) -> sprintf "if (%s) %s%s" (loop e) (loop e1) (match e2 with None -> "" | Some e -> " else " ^ loop e) | TWhile (econd,e,flag) -> @@ -373,7 +370,6 @@ let rec s_expr_ast print_var_ids tabs s_type e = | TReturn (Some e1) -> tag "Return" [loop e1] | TWhile (e1,e2,NormalWhile) -> tag "While" [loop e1; loop e2] | TWhile (e1,e2,DoWhile) -> tag "Do" [loop e1; loop e2] - | TFor (v,e1,e2) -> tag "For" [local v None; loop e1; loop e2] | TTry (e1,catches) -> let sl = List.map (fun (v,e) -> sprintf "Catch %s%s" (local v None) (tag_args (tabs ^ "\t") [loop ~extra_tabs:"\t" e]); diff --git a/src/core/tType.ml b/src/core/tType.ml index e48e4330d7a..bf111332242 100644 --- a/src/core/tType.ml +++ b/src/core/tType.ml @@ -199,7 +199,6 @@ and texpr_expr = | TFunction of tfunc | TVar of tvar * texpr option | TBlock of texpr list - | TFor of tvar * texpr * texpr | TIf of texpr * texpr * texpr option | TWhile of texpr * texpr * Ast.while_flag | TSwitch of tswitch diff --git a/src/core/texpr.ml b/src/core/texpr.ml index 53c62f586d1..d3e6c655611 100644 --- a/src/core/texpr.ml +++ b/src/core/texpr.ml @@ -17,7 +17,6 @@ let iter f e = () | TArray (e1,e2) | TBinop (_,e1,e2) - | TFor (_,e1,e2) | TWhile (e1,e2,_) -> f e1; f e2; @@ -66,7 +65,7 @@ let check_expr predicate e = match e.eexpr with | TConst _ | TLocal _ | TBreak | TContinue | TTypeExpr _ | TIdent _ -> false - | TArray (e1,e2) | TBinop (_,e1,e2) | TFor (_,e1,e2) | TWhile (e1,e2,_) -> + | TArray (e1,e2) | TBinop (_,e1,e2) | TWhile (e1,e2,_) -> predicate e1 || predicate e2; | TThrow e | TField (e,_) | TEnumParameter (e,_,_) | TEnumIndex e | TParenthesis e | TCast (e,_) | TUnop (_,_,e) | TMeta(_,e) -> @@ -105,9 +104,6 @@ let map_expr f e = | TBinop (op,e1,e2) -> let e1 = f e1 in { e with eexpr = TBinop (op,e1,f e2) } - | TFor (v,e1,e2) -> - let e1 = f e1 in - { e with eexpr = TFor (v,e1,f e2) } | TWhile (e1,e2,flag) -> let e1 = f e1 in { e with eexpr = TWhile (e1,f e2,flag) } @@ -176,10 +172,6 @@ let map_expr_type f ft fv e = | TBinop (op,e1,e2) -> let e1 = f e1 in { e with eexpr = TBinop (op,e1,f e2); etype = ft e.etype } - | TFor (v,e1,e2) -> - let v = fv v in - let e1 = f e1 in - { e with eexpr = TFor (v,e1,f e2); etype = ft e.etype } | TWhile (e1,e2,flag) -> let e1 = f e1 in { e with eexpr = TWhile (e1,f e2,flag); etype = ft e.etype } @@ -301,7 +293,6 @@ let rec equal e1 e2 = match e1.eexpr,e2.eexpr with | TFunction tf1,TFunction tf2 -> tf1 == tf2 | TVar(v1,None),TVar(v2,None) -> v1 == v2 | TVar(v1,Some e1),TVar(v2,Some e2) -> v1 == v2 && equal e1 e2 - | TFor(v1,ec1,eb1),TFor(v2,ec2,eb2) -> v1 == v2 && equal ec1 ec2 && equal eb1 eb2 | TIf(e1,ethen1,None),TIf(e2,ethen2,None) -> equal e1 e2 && equal ethen1 ethen2 | TIf(e1,ethen1,Some eelse1),TIf(e2,ethen2,Some eelse2) -> equal e1 e2 && equal ethen1 ethen2 && equal eelse1 eelse2 | TWhile(e1,eb1,flag1),TWhile(e2,eb2,flag2) -> equal e1 e2 && equal eb2 eb2 && flag1 = flag2 @@ -337,9 +328,6 @@ let duplicate_tvars f_this e = | TVar (v,eo) -> let v2 = copy_var v in {e with eexpr = TVar(v2, Option.map build_expr eo)} - | TFor (v,e1,e2) -> - let v2 = copy_var v in - {e with eexpr = TFor(v2, build_expr e1, build_expr e2)} | TTry (e1,cl) -> let cl = List.map (fun (v,e) -> let v2 = copy_var v in @@ -407,10 +395,6 @@ let foldmap f acc e = let acc,e1 = f acc e1 in let acc,e2 = f acc e2 in acc,{ e with eexpr = TBinop (op,e1,e2) } - | TFor (v,e1,e2) -> - let acc,e1 = f acc e1 in - let acc,e2 = f acc e2 in - acc,{ e with eexpr = TFor (v,e1,e2) } | TWhile (e1,e2,flag) -> let acc,e1 = f acc e1 in let acc,e2 = f acc e2 in @@ -594,7 +578,7 @@ let rec constructor_side_effects e = true | TField (_,FEnum _) -> false - | TUnop _ | TArray _ | TField _ | TEnumParameter _ | TEnumIndex _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ -> + | TUnop _ | TArray _ | TField _ | TEnumParameter _ | TEnumIndex _ | TCall _ | TNew _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ -> true | TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _ | TFunction _ | TArrayDecl _ | TObjectDecl _ @@ -640,11 +624,11 @@ let rec type_constant_value basic (e,p) = let is_constant_value basic e = try (ignore (type_constant_value basic e); true) with Error {err_message = Custom _} -> false -let for_remap basic v e1 e2 p = - let v' = alloc_var v.v_kind v.v_name e1.etype e1.epos in - let ev' = mk (TLocal v') e1.etype e1.epos in - let t1 = (Abstract.follow_with_abstracts e1.etype) in - let ehasnext = mk (TField(ev',try quick_field t1 "hasNext" with Not_found -> raise_typing_error (s_type (print_context()) t1 ^ "has no field hasNext()") p)) (tfun [] basic.tbool) e1.epos in +let for_remap basic v etype e1 e2 p = + let v' = alloc_var v.v_kind v.v_name etype e1.epos in + let ev' = mk (TLocal v') etype e1.epos in + let t1 = (Abstract.follow_with_abstracts etype) in + let ehasnext = mk (TField(ev',try quick_field t1 "hasNext" with Not_found -> raise_typing_error (s_type (print_context()) t1 ^ " has no field hasNext()") p)) (tfun [] basic.tbool) e1.epos in let ehasnext = mk (TCall(ehasnext,[])) basic.tbool ehasnext.epos in let enext = mk (TField(ev',quick_field t1 "next")) (tfun [] v.v_type) e1.epos in let enext = mk (TCall(enext,[])) v.v_type e1.epos in @@ -760,10 +744,6 @@ let dump_with_pos tabs e = | TBlock el -> add "TBlock"; List.iter loop el - | TFor(v,e1,e2) -> - add ("TFor " ^ v.v_name); - loop e1; - loop e2; | TIf(e1,e2,eo) -> add "TIf"; loop e1; @@ -821,10 +801,6 @@ let collect_captured_vars e = | TVar(v,eo) -> Option.may loop eo; declare v - | TFor(v,e1,e2) -> - declare v; - loop e1; - loop e2; | TFunction tf -> List.iter (fun (v,_) -> declare v) tf.tf_args; loop tf.tf_expr @@ -942,8 +918,6 @@ module DeadEnd = struct Option.map_default (loop ) true switch.switch_default (* true because we know it's exhaustive *) in loop switch.switch_subject || check_exhaustive () - | TFor(_, e1, _) -> - loop e1 | TBinop(OpBoolAnd, e1, e2) -> loop e1 || is_true_expr e1 && loop e2 | TBinop(OpBoolOr, e1, e2) -> diff --git a/src/filters/capturedVars.ml b/src/filters/capturedVars.ml index 0bba9dc44b8..331443ad7fa 100644 --- a/src/filters/capturedVars.ml +++ b/src/filters/capturedVars.ml @@ -104,11 +104,6 @@ let captured_vars com e = { e with eexpr = TVar (v,ve) } | TLocal v when PMap.mem v.v_id used -> impl#mk_ref_access e v - | TFor (v,it,expr) when PMap.mem v.v_id used -> - let vtmp = mk_var v used in - let it = wrap used it in - let expr = wrap used expr in - mk (TFor (vtmp,it,Type.concat (impl#mk_init v vtmp e.epos) expr)) e.etype e.epos | TTry (expr,catchs) -> let catchs = List.map (fun (v,e) -> let e = wrap used e in @@ -194,7 +189,7 @@ let captured_vars com e = and out_loop e = match e.eexpr with - | TFor _ | TWhile _ -> + | TWhile _ -> (* collect variables that are declared in loop but used in subfunctions *) diff --git a/src/filters/filters.ml b/src/filters/filters.ml index 6f7f520b652..822e6545034 100644 --- a/src/filters/filters.ml +++ b/src/filters/filters.ml @@ -220,7 +220,7 @@ let mark_switch_break_loops e = let ret = Type.map_expr run e in num := old_num; ret - | TWhile _ | TFor _ -> + | TWhile _ -> let last_switch = !in_switch in let last_found = !did_found in let last_num = !cur_num in @@ -437,26 +437,6 @@ let iter_expressions fl mt = | _ -> () -module ForRemap = struct - let apply ctx e = - let rec loop e = match e.eexpr with - | TFor(v,e1,e2) -> - let e1 = loop e1 in - let e2 = loop e2 in - let iterator = ForLoop.IterationKind.of_texpr ctx e1 (ForLoop.get_unroll_params_t ctx e2) e.epos in - let restore = save_locals ctx in - let e = ForLoop.IterationKind.to_texpr ctx v iterator e2 e.epos in - restore(); - begin match e.eexpr with - | TFor _ -> for_remap ctx.com.basic v e1 e2 e.epos - | _ -> e - end - | _ -> - Type.map_expr loop e - in - loop e -end - open FilterContext let destruction tctx ectx detail_times main locals = @@ -707,7 +687,6 @@ let run tctx ectx main before_destruction = NullSafety.run com new_types; (* PASS 1: general expression filters *) let filters = [ - "ForRemap",ForRemap.apply; "handle_abstract_casts",AbstractCast.handle_abstract_casts; ] in List.iter (run_expression_filters tctx detail_times filters) new_types; diff --git a/src/filters/localUsage.ml b/src/filters/localUsage.ml index 28ea565b596..69263f2c877 100644 --- a/src/filters/localUsage.ml +++ b/src/filters/localUsage.ml @@ -47,12 +47,6 @@ let rec local_usage f e = f (Function cc) | TBlock l -> f (Block (fun f -> List.iter (local_usage f) l)) - | TFor (v,it,e) -> - local_usage f it; - f (Loop (fun f -> - f (Declare v); - local_usage f e; - )) | TWhile _ -> f (Loop (fun f -> iter (local_usage f) e diff --git a/src/filters/renameVars.ml b/src/filters/renameVars.ml index 1b96144c8c6..26264012d3d 100644 --- a/src/filters/renameVars.ml +++ b/src/filters/renameVars.ml @@ -337,19 +337,6 @@ let rec collect_vars ?(in_block=false) rc scope e = if flag = DoWhile then collect_vars scope condition; ) - (* - This only happens for `cross` target, because for real targets all loops are converted to `while` at this point - Idk if this works correctly. - *) - | TFor (v, iterator, body) -> - collect_loop scope (fun() -> - if rc.rc_hoisting then - declare_var rc scope v; - collect_vars scope iterator; - if not rc.rc_hoisting then - declare_var rc scope v; - collect_vars scope body - ) | _ -> iter (collect_vars scope) e diff --git a/src/filters/tre.ml b/src/filters/tre.ml index 1bbf18bfffe..3fb71515fb6 100644 --- a/src/filters/tre.ml +++ b/src/filters/tre.ml @@ -111,7 +111,7 @@ let rec transform_function ctx is_recursive_call fn = let rec transform_expr cancel_tre function_end e = match e.eexpr with (* cancel tre inside of loops bodies *) - | TWhile _ | TFor _ -> + | TWhile _ -> map_expr (transform_expr true false) e (* cancel tre inside of try blocks *) | TTry (e_try, catches) -> @@ -167,7 +167,7 @@ let rec transform_function ctx is_recursive_call fn = let rec has_tail_recursion is_recursive_call cancel_tre function_end e = match e.eexpr with (* cancel tre inside of loops bodies *) - | TFor _ | TWhile _ -> + | TWhile _ -> check_expr (has_tail_recursion is_recursive_call true false) e (* cancel tre inside of try blocks *) | TTry (e, catches) -> diff --git a/src/generators/cpp/cppRetyper.ml b/src/generators/cpp/cppRetyper.ml index 03a455b2946..be231104d4d 100644 --- a/src/generators/cpp/cppRetyper.ml +++ b/src/generators/cpp/cppRetyper.ml @@ -1081,13 +1081,6 @@ let expression ctx request_type function_args function_type expression_tree forI | Spread -> die ~p:expr.epos "Unexpected spread operator" __LOC__ in (reference, cpp_type_of expr.etype) - | TFor (v, init, block) -> - let old_declarations = Hashtbl.copy !declarations in - Hashtbl.add !declarations v.v_name (); - let init = retype (cpp_type_of v.v_type) init in - let block = retype TCppVoid (mk_block block) in - declarations := old_declarations; - (CppFor (v, init, block), TCppVoid) | TWhile (e1, e2, flag) -> let condition = retype (TCppScalar "bool") e1 in let close = begin_loop () in diff --git a/src/generators/cpp/gen/cppCppia.ml b/src/generators/cpp/gen/cppCppia.ml index 85468f61e64..ffd9ff33826 100644 --- a/src/generators/cpp/gen/cppCppia.ml +++ b/src/generators/cpp/gen/cppCppia.ml @@ -1230,12 +1230,6 @@ class script_writer ctx filename asciiOut = (this#op IaWhile ^ (if flag = NormalWhile then "1" else "0") ^ "\n"); this#gen_expression e1; this#gen_expression e2 - | TFor (tvar, init, loop) -> - this#writeOp IaFor; - this#writeVar tvar; - this#write "\n"; - this#gen_expression init; - this#gen_expression loop | TEnumParameter (expr, ef, i) -> let enum = match follow ef.ef_type with diff --git a/src/generators/genhl.ml b/src/generators/genhl.ml index 1a0106741cd..434339fef31 100644 --- a/src/generators/genhl.ml +++ b/src/generators/genhl.ml @@ -2868,8 +2868,6 @@ and eval_expr ctx e = die "" __LOC__) | TMeta (_,e) -> eval_expr ctx e - | TFor (v,it,loop) -> - eval_expr ctx (Texpr.for_remap ctx.com.basic v it loop e.epos) | TSwitch {switch_subject = en;switch_cases = cases;switch_default = def} -> let rt = to_type ctx e.etype in let r = alloc_tmp ctx rt in diff --git a/src/generators/genjs.ml b/src/generators/genjs.ml index d1cdb0aff88..3ba99abeae3 100644 --- a/src/generators/genjs.ml +++ b/src/generators/genjs.ml @@ -563,7 +563,7 @@ and gen_expr ctx e = spr ctx ")"; | TMeta ((Meta.LoopLabel,[(EConst(Int (n, _)),_)],_), e) -> (match e.eexpr with - | TWhile _ | TFor _ -> + | TWhile _ -> print ctx "_hx_loop%s: " n; gen_expr ctx e | TBreak -> @@ -676,30 +676,6 @@ and gen_expr ctx e = ) fields; spr ctx "}"; ctx.separator <- true - | TFor (v,it,e) -> - check_var_declaration v; - let old_in_loop = ctx.in_loop in - ctx.in_loop <- true; - let it = ident (match it.eexpr with - | TLocal v -> v.v_name - | _ -> - let id = ctx.id_counter in - ctx.id_counter <- ctx.id_counter + 1; - let name = "$it" ^ string_of_int id in - print ctx "%s %s = " (var ctx) name; - gen_value ctx it; - newline ctx; - name - ) in - print ctx "while( %s.hasNext() ) {" it; - let bend = open_block ctx in - newline ctx; - print ctx "%s %s = %s.next()" (var ctx) (ident v.v_name) it; - gen_block_element ctx e; - bend(); - newline ctx; - spr ctx "}"; - ctx.in_loop <- old_in_loop | TTry (etry,[(v,ecatch)]) -> spr ctx "try "; gen_expr ctx etry; @@ -885,7 +861,6 @@ and gen_value ctx e = spr ctx (ctx.type_accessor t); spr ctx ")" | TVar _ - | TFor _ | TWhile _ | TThrow _ -> (* value is discarded anyway *) diff --git a/src/generators/genjvm.ml b/src/generators/genjvm.ml index ad6033244ba..d3b7702ac8c 100644 --- a/src/generators/genjvm.ml +++ b/src/generators/genjvm.ml @@ -2141,8 +2141,6 @@ class texpr_to_jvm if not (need_val ret) then code#pop; | TParenthesis e1 | TMeta(_,e1) -> self#texpr ret e1 - | TFor(v,e1,e2) -> - self#texpr ret (Texpr.for_remap gctx.gctx.basic v e1 e2 e.epos) | TEnumIndex e1 -> self#texpr rvalue_any e1; jm#invokevirtual java_enum_path "ordinal" (method_sig [] (Some TInt)) diff --git a/src/generators/genlua.ml b/src/generators/genlua.ml index 807bcf0c93c..745f5555d2d 100644 --- a/src/generators/genlua.ml +++ b/src/generators/genlua.ml @@ -553,7 +553,7 @@ and gen_call ctx e el = and has_continue e = let rec loop e = match e.eexpr with | TContinue -> raise Exit - | TWhile(e1,_,_) | TFor(_,e1,_) -> loop e1 (* in theory there could be a continue there. Note that we don't want to recurse into the loop body because we do not care about inner continue expressions *) + | TWhile(e1,_,_) -> loop e1 (* in theory there could be a continue there. Note that we don't want to recurse into the loop body because we do not care about inner continue expressions *) | _ -> Type.iter loop e in try @@ -982,8 +982,6 @@ and gen_expr ?(local=true) ctx e = begin concat ctx "," (fun ((f,_,_),e) -> print ctx "%s=" (anon_field f); gen_anon_value ctx e) fields; spr ctx "})"; ctx.separator <- true - | TFor (v,it,e2) -> - unsupported e.epos; | TTry (e,catchs) -> (* TODO: add temp variables *) let old_in_loop_try = ctx.in_loop_try in @@ -1229,7 +1227,6 @@ and gen_value ctx e = | TCast (e1, _) -> gen_value ctx e1 | TVar _ - | TFor _ | TWhile _ | TThrow _ -> (* value is discarded anyway *) diff --git a/src/generators/genneko.ml b/src/generators/genneko.ml index 13b7cd0cabe..217cbf941c4 100644 --- a/src/generators/genneko.ml +++ b/src/generators/genneko.ml @@ -305,20 +305,6 @@ and gen_expr ctx e = (EFunction (List.map arg_name f.tf_args, with_return e),p) | TBlock el -> (EBlock (List.map (gen_expr ctx) el), p) - | TFor (v, it, e) -> - let it = gen_expr ctx it in - let e = gen_expr ctx e in - let next = call p (field p (ident p "@tmp") "next") [] in - let next = (if has_var_flag v VCaptured then call p (builtin p "array") [next] else next) in - (EBlock - [(EVars ["@tmp", Some it],p); - (EWhile (call p (field p (ident p "@tmp") "hasNext") [], - (EBlock [ - (EVars [v.v_name, Some next],p); - e - ],p) - ,NormalWhile),p)] - ,p) | TIf (cond,e1,e2) -> (* if(e)-1 is parsed as if( e - 1 ) *) let parent e = mk (TParenthesis e) e.etype e.epos in diff --git a/src/generators/genphp7.ml b/src/generators/genphp7.ml index 2cd92e8f6b0..21dff91f866 100644 --- a/src/generators/genphp7.ml +++ b/src/generators/genphp7.ml @@ -1451,7 +1451,6 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name = | TIf (_, _, None) -> true | TTry _ -> true | TWhile _ -> true - | TFor _ -> true | TSwitch _ -> true | _ -> false in @@ -1673,7 +1672,6 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name = | TFunction fn -> self#write_expr_function fn | TVar (var, expr) -> self#write_expr_var var expr | TBlock exprs -> self#write_expr_block expr - | TFor (var, iterator, body) -> fail self#pos __LOC__ | TIf (condition, if_expr, else_expr) -> self#write_expr_if condition if_expr else_expr | TWhile (condition, expr, do_while) -> (match (reveal_expr_with_parenthesis condition).eexpr with @@ -1853,7 +1851,6 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name = | TIf (_, _, _) -> false | TWhile (_, _, _) -> false | TTry (_, _) -> false - | TFor (_, _, _) -> false | TFunction _ -> false | TBlock _ -> false | TSwitch _ -> false diff --git a/src/generators/genpy.ml b/src/generators/genpy.ml index e58d05dcc90..79cb5150eec 100644 --- a/src/generators/genpy.ml +++ b/src/generators/genpy.ml @@ -686,30 +686,6 @@ module Transformer = struct lift true [inc_assign] var_assign | (_,TVar(v,eo)) -> transform_var_expr ae eo v - | (_,TFor(v,e1,e2)) -> - let a1 = trans true [] e1 in - let a2 = to_expr (trans false [] e2) in - - let name = (ae.a_next_id ()) in - let t_var = alloc_var name e1.etype e1.epos in - - let ev = make_local t_var e1.epos in - let ehasnext = mk (TField(ev,quick_field e1.etype "hasNext")) (tfun [] (!t_bool) ) e1.epos in - let ehasnext = mk (TCall(ehasnext,[])) ehasnext.etype ehasnext.epos in - - let enext = mk (TField(ev,quick_field e1.etype "next")) (tfun [] v.v_type) e1.epos in - let enext = mk (TCall(enext,[])) v.v_type e1.epos in - - let var_assign = mk (TVar (v,Some enext)) v.v_type a_expr.epos in - - let ebody = Type.concat var_assign (a2) in - - let var_decl = mk (TVar (t_var,Some a1.a_expr)) (!t_void) e1.epos in - let twhile = mk (TWhile((mk (TParenthesis ehasnext) ehasnext.etype ehasnext.epos),ebody,NormalWhile)) (!t_void) e1.epos in - - let blocks = a1.a_blocks @ [var_decl] in - - lift_expr ae.a_next_id ~blocks: blocks twhile | (_,TReturn None) -> ae | (_,TReturn (Some ({eexpr = TFunction f} as ef))) -> @@ -1396,7 +1372,7 @@ module Printer = struct print_expr pctx e1 | TIdent s -> s - | TSwitch _ | TCast(_, Some _) | TFor _ | TUnop(_,Postfix,_) -> + | TSwitch _ | TCast(_, Some _) | TUnop(_,Postfix,_) -> die "" __LOC__ and print_if_else pctx econd eif eelse as_elif = diff --git a/src/generators/genswf.ml b/src/generators/genswf.ml index 772dc6e5dc1..8ab35db9221 100644 --- a/src/generators/genswf.ml +++ b/src/generators/genswf.ml @@ -127,10 +127,6 @@ let build_dependencies t = List.iter (fun (v,_) -> add_type v.v_type) f.tf_args; add_type f.tf_type; add_expr f.tf_expr; - | TFor (v,e1,e2) -> - add_type v.v_type; - add_expr e1; - add_expr e2; | TVar (v,eo) -> add_type v.v_type; begin match eo with diff --git a/src/generators/genswf9.ml b/src/generators/genswf9.ml index a414330b45b..709de1c9f8e 100644 --- a/src/generators/genswf9.ml +++ b/src/generators/genswf9.ml @@ -1263,31 +1263,6 @@ let rec gen_expr_content ctx retval e = List.iter (fun j -> j()) loops; branch(); jend() - | TFor (v,it,e) -> - gen_expr ctx true it; - let r = alloc_reg ctx KDynamic in - set_reg ctx r; - let branch = begin_branch ctx in - let b = open_block ctx retval in - define_local ctx v e.epos; - let end_loop = begin_loop ctx in - let continue_pos = ctx.infos.ipos in - let start = jump_back ctx in - write ctx (HReg r.rid); - write ctx (HCallProperty (ident "hasNext",0)); - let jend = jump ctx J3False in - let acc = gen_local_access ctx v e.epos Write in - write ctx (HReg r.rid); - write ctx (HCallProperty (ident "next",0)); - setvar ctx acc None; - gen_expr ctx false e; - start J3Always; - end_loop continue_pos; - jend(); - if retval then getvar ctx (gen_local_access ctx v e.epos Read); - b(); - branch(); - free_reg ctx r; | TBreak -> pop ctx (ctx.infos.istack - ctx.infos.iloop); ctx.breaks <- jump ctx J3Always :: ctx.breaks; @@ -1859,7 +1834,7 @@ and generate_function ctx fdata stat = | TReturn (Some e) -> let rec inner_loop e = match e.eexpr with - | TSwitch _ | TFor _ | TWhile _ | TTry _ -> false + | TSwitch _ | TWhile _ | TTry _ -> false | TIf _ -> loop e | TParenthesis e | TMeta(_,e) -> inner_loop e | _ -> true diff --git a/src/macro/eval/evalJit.ml b/src/macro/eval/evalJit.ml index 8d0dbd6c701..e9d15f030e6 100644 --- a/src/macro/eval/evalJit.ml +++ b/src/macro/eval/evalJit.ml @@ -304,7 +304,7 @@ and jit_expr jit return e = | TWhile(e1,e2,flag) -> let rec has_continue e = match e.eexpr with | TContinue -> true - | TWhile _ | TFor _ | TFunction _ -> false + | TWhile _ | TFunction _ -> false | _ -> check_expr has_continue e in let exec_cond = jit_expr jit false e1 in @@ -632,8 +632,6 @@ and jit_expr jit return e = | TUnop(op,flag,v1) -> unop jit op flag v1 e.epos (* rewrites/skips *) - | TFor(v,e1,e2) -> - loop (Texpr.for_remap (ctx.curapi.MacroApi.get_com()).Common.basic v e1 e2 e.epos) | TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) -> loop e1 | TIdent s -> @@ -650,7 +648,7 @@ and jit_expr jit return e = begin match e.eexpr with | TCall _ | TNew _ | TVar({v_kind = VUser _},_) - | TFor _ | TIf _ | TWhile _ | TSwitch _ | TTry _ + | TIf _ | TWhile _ | TSwitch _ | TTry _ | TReturn _ | TBreak | TContinue | TThrow _ | TCast(_,Some _) -> wrap() | TUnop((Increment | Decrement),_,e1) | TBinop((OpAssign | OpAssignOp _),e1,_) -> diff --git a/src/macro/macroApi.ml b/src/macro/macroApi.ml index 4beb000f24d..6424f147132 100644 --- a/src/macro/macroApi.ml +++ b/src/macro/macroApi.ml @@ -1380,7 +1380,6 @@ and encode_texpr e = | TFunction func -> 12,[encode_tfunc func] | TVar (v,eo) -> 13,[encode_tvar v;vopt encode_texpr eo] | TBlock el -> 14,[encode_texpr_list el] - | TFor(v,e1,e2) -> 15,[encode_tvar v;loop e1;loop e2] | TIf(eif,ethen,eelse) -> 16,[loop eif;loop ethen;vopt encode_texpr eelse] | TWhile(econd,e1,flag) -> 17,[loop econd;loop e1;vbool (flag = NormalWhile)] | TSwitch switch -> @@ -1530,7 +1529,7 @@ and decode_texpr v = | 12, [f] -> TFunction(decode_tfunc f) | 13, [v;eo] -> TVar(decode_tvar v,opt loop eo) | 14, [vl] -> TBlock(List.map loop (decode_array vl)) - | 15, [v;v1;v2] -> TFor(decode_tvar v,loop v1,loop v2) + (* 15 was TFor *) | 16, [vif;vthen;velse] -> TIf(loop vif,loop vthen,opt loop velse) | 17, [vcond;v1;b] -> TWhile(loop vcond,loop v1,if decode_bool b then NormalWhile else DoWhile) | 18, [v1;cl;vdef] -> diff --git a/src/optimization/analyzer.ml b/src/optimization/analyzer.ml index cb80af4e33a..9c8d2e3d7fb 100644 --- a/src/optimization/analyzer.ml +++ b/src/optimization/analyzer.ml @@ -649,7 +649,6 @@ module LocalDce = struct | TField(_,fa) when PurityState.is_explicitly_impure fa -> raise Exit | TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit - | TFor _ -> raise Exit | TArray _ | TEnumParameter _ | TEnumIndex _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TField _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TBlock _ | TObjectDecl _ | TVar _ -> Type.iter loop e in diff --git a/src/optimization/analyzerTexpr.ml b/src/optimization/analyzerTexpr.ml index cfd76fb9d9b..fb029f50a46 100644 --- a/src/optimization/analyzerTexpr.ml +++ b/src/optimization/analyzerTexpr.ml @@ -204,7 +204,6 @@ let dynarray_mapi f d = - Postfix increment/decrement operations are rewritten to a TBlock with OpAssign and OpAdd/OpSub - `do {} while(true)` is rewritten to `while(true) {}` - TWhile expressions are rewritten to `while (true)` with appropriate conditional TBreak - - TFor is rewritten to TWhile *) module TexprFilter = struct let apply com e = @@ -242,7 +241,7 @@ module TexprFilter = struct let rec map_continue e = match e.eexpr with | TContinue -> Texpr.duplicate_tvars e_identity (e_if (Some e)) - | TWhile _ | TFor _ -> + | TWhile _ -> e | _ -> Type.map_expr map_continue e @@ -253,9 +252,6 @@ module TexprFilter = struct let e_true = mk (TConst (TBool true)) com.basic.tbool p in let e = mk (TWhile(Texpr.Builder.mk_parent e_true,e_block,NormalWhile)) e.etype p in loop e - | TFor(v,e1,e2) -> - let e = Texpr.for_remap com.basic v e1 e2 e.epos in - loop e | _ -> Type.map_expr loop e in @@ -903,7 +899,7 @@ module Fusion = struct if !found then raise Exit; found := true; {e with eexpr = TUnop(op,Postfix,e)} - | TIf _ | TSwitch _ | TTry _ | TWhile _ | TFor _ -> + | TIf _ | TSwitch _ | TTry _ | TWhile _ -> raise Exit | _ -> Type.map_expr replace e diff --git a/src/optimization/analyzerTexprTransformer.ml b/src/optimization/analyzerTexprTransformer.ml index 888ded14df5..dbdacc1c4d2 100644 --- a/src/optimization/analyzerTexprTransformer.ml +++ b/src/optimization/analyzerTexprTransformer.ml @@ -187,7 +187,7 @@ let rec func ctx bb tf t p = | TThrow _ | TReturn _ | TBreak | TContinue -> let bb = block_element bb e in bb,mk (TConst TNull) t_dynamic e.epos - | TVar _ | TFor _ | TWhile _ | TIf _ -> + | TVar _ | TWhile _ | TIf _ -> Error.raise_typing_error "Cannot use this expression as value" e.epos and value bb e = let bb,e = value' bb e in @@ -631,7 +631,7 @@ let rec func ctx bb tf t p = block_el false bb el | TObjectDecl fl -> block_el false bb (List.map snd fl) - | TFor _ | TWhile(_,_,DoWhile) -> + | TWhile(_,_,DoWhile) -> die "" __LOC__ and block_el allow_void bb el = let block_element = if allow_void then diff --git a/src/optimization/inline.ml b/src/optimization/inline.ml index 37415c2762e..1f67d0a33e1 100644 --- a/src/optimization/inline.ml +++ b/src/optimization/inline.ml @@ -700,14 +700,6 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f | Some e -> state#set_return_value; map term false e) - | TFor (v,e1,e2) -> - let i = state#declare v in - let e1 = map false false e1 in - let old = !in_loop in - in_loop := true; - let e2 = map false false e2 in - in_loop := old; - { e with eexpr = TFor (i.i_subst,e1,e2) } | TWhile (cond,eloop,flag) -> let cond = map false false cond in let old = !in_loop in @@ -747,7 +739,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f let r = match e.eexpr with | TReturn _ -> true | TFunction _ -> false - | TIf (_,_,None) | TSwitch {switch_default = None} | TFor _ | TWhile (_,_,NormalWhile) -> false (* we might not enter this code at all *) + | TIf (_,_,None) | TSwitch {switch_default = None} | TWhile (_,_,NormalWhile) -> false (* we might not enter this code at all *) | TTry (a, catches) -> List.for_all has_term_return (a :: List.map snd catches) | TIf (cond,a,Some b) -> has_term_return cond || (has_term_return a && has_term_return b) | TSwitch ({switch_default = Some def} as switch) -> has_term_return switch.switch_subject || List.for_all has_term_return (def :: List.map (fun case -> case.case_expr) switch.switch_cases) diff --git a/src/optimization/optimizer.ml b/src/optimization/optimizer.ml index 47ed16d8f18..493d2aa2451 100644 --- a/src/optimization/optimizer.ml +++ b/src/optimization/optimizer.ml @@ -64,7 +64,7 @@ let rec need_parent e = | TConst _ | TLocal _ | TArray _ | TField _ | TEnumParameter _ | TEnumIndex _ | TParenthesis _ | TCall _ | TNew _ | TTypeExpr _ | TObjectDecl _ | TArrayDecl _ | TIdent _ -> false | TCast (e,None) | TMeta(_,e) -> need_parent e - | TCast _ | TThrow _ | TReturn _ | TTry _ | TSwitch _ | TFor _ | TIf _ | TWhile _ | TBinop _ | TContinue | TBreak + | TCast _ | TThrow _ | TReturn _ | TTry _ | TSwitch _ | TIf _ | TWhile _ | TBinop _ | TContinue | TBreak | TBlock _ | TVar _ | TFunction _ | TUnop _ -> true let sanitize_expr com e = @@ -82,7 +82,6 @@ let sanitize_expr com e = (* complex expressions are the one that once generated to source consists in several expressions *) match e.eexpr with | TVar _ (* needs to be put into blocks *) - | TFor _ (* a temp var is needed for holding iterator *) | TCall ({ eexpr = TIdent "__js__" },_) (* we never know *) -> block e | _ -> e @@ -92,7 +91,6 @@ let sanitize_expr com e = match e.eexpr with | TIf (_,_,None) -> true | TWhile (_,e,NormalWhile) -> has_if e - | TFor (_,_,e) -> has_if e | _ -> false in match e.eexpr with @@ -156,9 +154,6 @@ let sanitize_expr com e = let e1 = parent e1 in let e2 = complex e2 in { e with eexpr = TWhile (e1,e2,flag) } - | TFor (v,e1,e2) -> - let e2 = complex e2 in - { e with eexpr = TFor (v,e1,e2) } | TFunction f -> let f = (match f.tf_expr.eexpr with | TBlock exprs -> diff --git a/src/optimization/optimizerTexpr.ml b/src/optimization/optimizerTexpr.ml index cdf8079e745..e84e65a8998 100644 --- a/src/optimization/optimizerTexpr.ml +++ b/src/optimization/optimizerTexpr.ml @@ -13,7 +13,7 @@ let has_side_effect e = | TField(_,fa) when PurityState.is_explicitly_impure fa -> raise Exit | TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit - | TArray _ | TEnumParameter _ | TEnumIndex _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TFor _ + | TArray _ | TEnumParameter _ | TEnumIndex _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TField _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TBlock _ | TObjectDecl _ | TVar _ -> Type.iter loop e in try diff --git a/src/typing/forLoop.ml b/src/typing/forLoop.ml index 480a9aefeb2..3e0bc984b84 100644 --- a/src/typing/forLoop.ml +++ b/src/typing/forLoop.ml @@ -33,7 +33,7 @@ let optimize_for_loop_iterator ctx v e1 e2 p = get_class_and_params e1 in let _, _, fhasnext = (try raw_class_field (fun cf -> apply_params c.cl_params tl cf.cf_type) c tl "hasNext" with Not_found -> raise Exit) in - if fhasnext.cf_kind <> Method MethInline then raise Exit; + if not ctx.allow_inline || fhasnext.cf_kind <> Method MethInline then raise Exit; let it_type = TInst(c,tl) in let tmp = gen_local ctx it_type e1.epos in let eit = mk (TLocal tmp) it_type p in @@ -284,7 +284,7 @@ module IterationKind = struct { it_kind = it; it_type = pt; - it_expr = if not ctx.allow_transform then e else e1; + it_expr = e1; } let to_texpr ctx v iterator e2 p = @@ -339,8 +339,6 @@ module IterationKind = struct mk (TBlock el) t_void p in match iterator.it_kind with - | _ when not ctx.allow_transform -> - mk (TFor(v,e1,e2)) t_void p | IteratorIntUnroll(offset,length,ascending,unroll_params) -> check_loop_var_modification [v] e2; if not ascending then raise_typing_error "Cannot iterate backwards" p; @@ -413,8 +411,11 @@ module IterationKind = struct | IteratorCustom(f_next,f_length) -> gen_int_iter e1 pt f_next f_length | IteratorIterator -> - begin try optimize_for_loop_iterator ctx v e1 e2 p - with Exit -> mk (TFor(v,e1,e2)) t_void p end + begin try + optimize_for_loop_iterator ctx v e1 e2 p + with Exit -> + Texpr.for_remap ctx.t v (ctx.t.titerator pt) e1 e2 p + end | IteratorGenericStack c -> let tcell = (try (PMap.find "head" c.cl_fields).cf_type with Not_found -> die "" __LOC__) in let cell = gen_local ctx tcell p in @@ -442,7 +443,7 @@ module IterationKind = struct ewhile; ]) t_void p | IteratorDynamic -> - mk (TFor(v,e1,e2)) t_void p + mk (TBlock []) t_void p end let get_unroll_params ctx e2 = @@ -504,11 +505,7 @@ let type_for_loop ctx handle_display ik e1 e2 p = check_display (i,pi,dko); ctx.e.in_loop <- old_loop; old_locals(); - begin try - IterationKind.to_texpr ctx i iterator e2 p - with Exit -> - mk (TFor (i,iterator.it_expr,e2)) ctx.t.tvoid p - end + IterationKind.to_texpr ctx i iterator e2 p | IKKeyValue((ikey,pkey,dkokey),(ivalue,pvalue,dkovalue)) -> (match follow e1.etype with | TDynamic _ | TMono _ -> diff --git a/src/typing/nullSafety.ml b/src/typing/nullSafety.ml index fc4dffc87fb..5f4e08a1286 100644 --- a/src/typing/nullSafety.ml +++ b/src/typing/nullSafety.ml @@ -766,9 +766,8 @@ class local_safety (mode:safety_mode) = (* let scope = new safety_scope mode STLoop (Hashtbl.create 100) (Hashtbl.create 100) in *) scopes <- scope :: scopes; match e.eexpr with - | TFor (v, _, _) -> scope#declare_var v | TWhile _ -> () - | _ -> fail ~msg:"Expected TFor or TWhile." e.epos __POS__ + | _ -> fail ~msg:"Expected TWhile." e.epos __POS__ (** Should be called upon leaving local function declaration. *) @@ -1131,7 +1130,6 @@ class expr_checker mode immediate_execution report = | TFunction fn -> self#check_function fn | TVar (v, init_expr) -> self#check_var v init_expr e.epos | TBlock exprs -> self#check_block exprs e.epos - | TFor _ -> self#check_for e | TIf _ -> self#check_if e | TWhile _ -> self#check_while e | TSwitch switch -> self#check_switch switch e.epos @@ -1213,20 +1211,7 @@ class expr_checker mode immediate_execution report = ); local_safety#scope_closed | _ -> fail ~msg:"Expected TWhile." e.epos __POS__ - (** - Don't iterate on nullable values - *) - method private check_for e = - match e.eexpr with - | TFor (v, iterable, body) -> - if self#is_nullable_expr iterable then - self#error "Cannot iterate over nullable value." [iterable.epos; e.epos]; - self#check_expr iterable; - local_safety#declare_var v; - local_safety#loop_declared e; - self#check_loop_body None body; - local_safety#scope_closed - | _ -> fail ~msg:"Expected TFor." e.epos __POS__ + (** Handle safety inside of loops *) diff --git a/src/typing/typeloadCheck.ml b/src/typing/typeloadCheck.ml index 20d1b2fd8f5..54c81b319d2 100644 --- a/src/typing/typeloadCheck.ml +++ b/src/typing/typeloadCheck.ml @@ -306,7 +306,7 @@ let rec return_flow ctx e = (* a special case for "inifite" while loops that have no break *) let rec loop e = match e.eexpr with (* ignore nested loops to not accidentally get one of its breaks *) - | TWhile _ | TFor _ -> () + | TWhile _ -> () | TBreak -> error() | _ -> Type.iter loop e in diff --git a/tests/optimization/src/Test.hx b/tests/optimization/src/Test.hx index 6b2a2c3222e..12eccd1221b 100644 --- a/tests/optimization/src/Test.hx +++ b/tests/optimization/src/Test.hx @@ -116,9 +116,9 @@ class Test { } @:js(' - var _g_set_amount = 10; - var _g_current = 0; - while(_g_current++ < 10) { + var i_set_amount = 10; + var i_current = 0; + while(i_current++ < 10) { var i = null; } ') @@ -130,9 +130,9 @@ class Test { } @:js(' - var _g_set_amount = 10; - var _g_current = 0; - while(_g_current++ < 10) { + var i_set_amount = 10; + var i_current = 0; + while(i_current++ < 10) { var i = null; } ')