From 29a7ce7dd5d75658d3044b42b7ab6d57b706f663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Sat, 12 Nov 2016 14:58:56 +0100 Subject: record_SUITE: Strengthen test of record access in guards --- .../record_SUITE_data/record_access_in_guards.erl | 63 +++++++++++++++------- 1 file changed, 43 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl b/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl index 9b72432246..dbd2419ad2 100644 --- a/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl +++ b/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl @@ -27,12 +27,12 @@ -record(r3, {a = fun(_) -> #r1{} end(1), b}). t() -> - foo = fun(A) when A#r1.a > A#r1.b -> foo end(#r1{b = 2}), - 0 = fun(A) when A#r2.a -> 0 end(#r2{a = true}), + foo = rec_call(fun(A) when A#r1.a > A#r1.b -> foo end, #r1{b = 2}), + 0 = rec_call(fun(A) when A#r2.a -> 0 end, #r2{a = true}), 1 = fun(A) when (#r1{a = A})#r1.a > 2 -> 1 end(3), 2 = fun(N) when ((#r2{a = #r{a = 4}, b = length([a,b,c])})#r2.a)#r.a > N -> - 2 end(2), - 3 = fun(A) when (A#r2.a)#r1.a =:= 3 -> 3 end(#r2{a = #r1{a = 3}}), + 2 end(2), + 3 = rec_call(fun(A) when (A#r2.a)#r1.a =:= 3 -> 3 end, #r2{a = #r1{a = 3}}), ok = fun() -> F = fun(A) when record(A#r.a, r1) -> 4; (A) when record(A#r1.a, r1) -> 5 @@ -41,9 +41,9 @@ t() -> 4 = F(#r{a = #r1{}}), ok end(), - 3 = fun(A) when record(A#r1.a, r), - (A#r1.a)#r.a > 3 -> 3 - end(#r1{a = #r{a = 4}}), + 3 = rec_call(fun(A) when record(A#r1.a, r), + (A#r1.a)#r.a > 3 -> 3 + end, #r1{a = #r{a = 4}}), 7 = fun(A) when record(A#r3.a, r1) -> 7 end(#r3{}), [#r1{a = 2,b = 1}] = fun() -> @@ -71,9 +71,10 @@ t() -> (_) -> p end(#r1{a = 2}), - 3 = fun(A) when A#r1.a > 3, - record(A, r1) -> 3 - end(#r1{a = 5}), + o = rec_call(fun(A) when (A#r1.a =:= 2) orelse (A#r2.a =:= 1) -> o end, #r1{a = 2}), + o = rec_call(fun(A) when A#r1.a =:= 2; A#r2.a =:= 1 -> o end, #r2{a = 1}), + + 3 = rec_call(fun(A) when A#r1.a > 3, record(A, r1) -> 3 end, #r1{a = 5}), ok = fun() -> F = fun(A) when (A#r2.a =:= 1) orelse (A#r2.a) -> 2; @@ -93,6 +94,8 @@ t() -> (_) -> b end(#r1{a = 1}), + a = rec_call(fun(A) when not (A#r.a =:= 1) or false -> a end, #r{a = 42}), + ok = fun() -> F = fun(A) when not (A#r.a =:= 1) -> yes; (_) -> no @@ -103,14 +106,14 @@ t() -> ok end(), - a = fun(A) when record(A, r), - A#r.a =:= 1, - A#r.b =:= 2 ->a - end(#r{a = 1, b = 2}), - a = fun(A) when erlang:is_record(A, r), - A#r.a =:= 1, - A#r.b =:= 2 -> a - end(#r{a = 1, b = 2}), + a = rec_call(fun(A) when record(A, r), + A#r.a =:= 1, + A#r.b =:= 2 -> a + end, #r{a = 1, b = 2}), + a = rec_call(fun(A) when erlang:is_record(A, r), + A#r.a =:= 1, + A#r.b =:= 2 -> a + end, #r{a = 1, b = 2}), a = fun(A) when is_record(A, r), A#r.a =:= 1, A#r.b =:= 2 -> a @@ -144,8 +147,7 @@ t() -> ok end(), - both = fun(A) when A#r.a, A#r.b -> both - end(#r{a = true, b = true}), + both = rec_call(fun(A) when A#r.a, A#r.b -> both end, #r{a = true, b = true}), ok = fun() -> F = fun(A, B) when ((A#r1.a) orelse (B#r2.a)) @@ -176,3 +178,24 @@ t() -> ok. +rec_call(F, Rec) -> + Corrupted1 = setelement(1, Rec, wrong), + Corrupted2 = erlang:append_element(Rec, extra), + Corrupted3 = erlang:append_element(Corrupted1, extra), + fc(F, Corrupted1), + fc(F, Corrupted2), + fc(F, Corrupted3), + F(Rec). + +fc(F, Term) -> + try + F(Term), + error(expected_to_fail) + catch + error:function_clause -> + ok; + error:{case_clause,_} -> + Comp = ?MODULE:module_info(compile), + {_,Opts} = lists:keyfind(options, 1, Comp), + true = lists:member(inline, Opts) + end. -- cgit v1.2.3 From cb4b1276acae0406344a24d4597c0d33a1d72ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Sat, 12 Nov 2016 09:28:28 +0100 Subject: sys_core_fold: Remove unnecessary calls to opt_bool_case/1 The fixpoint iteration added in 05130e48 makes those calls superfluous. --- lib/compiler/src/sys_core_fold.erl | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 5d7fd37270..d20159c140 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -1606,16 +1606,14 @@ opt_bool_clauses(Cs, true, true) -> [] end; opt_bool_clauses([#c_clause{pats=[#c_literal{val=Lit}], - guard=#c_literal{val=true}, - body=B}=C0|Cs], SeenT, SeenF) -> + guard=#c_literal{val=true}}=C|Cs], SeenT, SeenF) -> case is_boolean(Lit) of false -> %% Not a boolean - this clause can't match. - add_warning(C0, nomatch_clause_type), + add_warning(C, nomatch_clause_type), opt_bool_clauses(Cs, SeenT, SeenF); true -> %% This clause will match. - C = C0#c_clause{body=opt_bool_case(B)}, case {Lit,SeenT,SeenF} of {false,_,false} -> [C|opt_bool_clauses(Cs, SeenT, true)]; @@ -2386,9 +2384,7 @@ is_safe_bool_expr_list([], _, _) -> true. %% as a let or a sequence, move the original let body into the complex %% expression. -simplify_let(#c_let{arg=Arg0}=Let0, Sub) -> - Arg = opt_bool_case(Arg0), - Let = Let0#c_let{arg=Arg}, +simplify_let(#c_let{arg=Arg}=Let, Sub) -> move_let_into_expr(Let, Arg, Sub). move_let_into_expr(#c_let{vars=InnerVs0,body=InnerBody0}=Inner, -- cgit v1.2.3 From 348b5e6bee2f83d10642558d511cc904f5015ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 15 Sep 2016 16:33:57 +0200 Subject: v3_kernel: Generate optimized code for guards The compiler produces poor code for complex guard expressions with andalso/orelse. Here is an example from the filename module: -define(IS_DRIVELETTER(Letter),(((Letter >= $A) andalso (Letter =< $Z)) orelse ((Letter >= $a) andalso (Letter =< $z)))). skip_prefix(Name, false) -> Name; skip_prefix([L, DrvSep|Name], DrvSep) when ?IS_DRIVELETTER(L) -> Name; skip_prefix(Name, _) -> Name. beam_bool fails to simplify the code for the guard, leaving several 'bif' instructions: {function, skip_prefix, 2, 49}. {label,48}. {line,[{location,"filename.erl",187}]}. {func_info,{atom,filename},{atom,skip_prefix},2}. {label,49}. {test,is_ne_exact,{f,52},[{x,1},{atom,false}]}. {test,is_nonempty_list,{f,52},[{x,0}]}. {get_list,{x,0},{x,2},{x,3}}. {test,is_nonempty_list,{f,52},[{x,3}]}. {get_list,{x,3},{x,4},{x,5}}. {bif,'=:=',{f,52},[{x,1},{x,4}],{x,6}}. {test,is_ge,{f,50},[{x,2},{integer,65}]}. {bif,'=<',{f,52},[{x,2},{integer,90}],{x,7}}. {test,is_eq_exact,{f,51},[{x,7},{atom,false}]}. {test,is_ge,{f,50},[{x,2},{integer,97}]}. {bif,'=<',{f,52},[{x,2},{integer,122}],{x,7}}. {jump,{f,51}}. {label,50}. {move,{atom,false},{x,7}}. {label,51}. {bif,'=:=',{f,52},[{x,7},{atom,true}],{x,7}}. {test,is_eq_exact,{f,52},[{x,6},{atom,true}]}. {test,is_eq_exact,{f,52},[{x,7},{atom,true}]}. {move,{x,5},{x,0}}. return. {label,52}. return. We can add optimizations of guard tests to v3_kernel to achive a better result: {function, skip_prefix, 2, 49}. {label,48}. {line,[{location,"filename.erl",187}]}. {func_info,{atom,filename},{atom,skip_prefix},2}. {label,49}. {test,is_ne_exact,{f,51},[{x,1},{atom,false}]}. {test,is_nonempty_list,{f,51},[{x,0}]}. {get_list,{x,0},{x,2},{x,3}}. {test,is_nonempty_list,{f,51},[{x,3}]}. {get_list,{x,3},{x,4},{x,5}}. {test,is_eq_exact,{f,51},[{x,1},{x,4}]}. {test,is_ge,{f,51},[{x,2},{integer,65}]}. {test,is_lt,{f,50},[{integer,90},{x,2}]}. {test,is_ge,{f,51},[{x,2},{integer,97}]}. {test,is_ge,{f,51},[{integer,122},{x,2}]}. {label,50}. {move,{x,5},{x,0}}. return. {label,51}. return. Looking at the STDLIB application, there were 112 lines of BIF calls in guards that beam_bool failed to convert to test instructions. This commit eliminates all those BIF calls. Here is how I counted the instructions: $ PATH=$ERL_TOP/bin:$PATH erlc -I ../include -I ../../kernel/include -S *.erl $ grep "bif,'[=<>]" *.S | grep -v f,0 dets.S: {bif,'=:=',{f,547},[{x,4},{atom,read_write}],{x,4}}. dets.S: {bif,'=:=',{f,547},[{x,5},{atom,saved}],{x,5}}. dets.S: {bif,'=:=',{f,589},[{x,5},{atom,read}],{x,5}}. . . . $ grep "bif,'[=<>]" *.S | grep -v f,0 | wc 112 224 6765 $ --- lib/compiler/src/sys_core_fold.erl | 84 +--- lib/compiler/src/v3_codegen.erl | 20 +- lib/compiler/src/v3_kernel.erl | 474 ++++++++++++++++++++- lib/compiler/src/v3_kernel.hrl | 2 +- lib/compiler/src/v3_kernel_pp.erl | 9 +- lib/compiler/src/v3_life.erl | 4 +- lib/compiler/test/bs_match_SUITE.erl | 33 +- lib/compiler/test/core_SUITE.erl | 20 +- .../test/core_SUITE_data/cover_v3_kernel_1.core | 147 +++++++ .../test/core_SUITE_data/cover_v3_kernel_2.core | 98 +++++ .../test/core_SUITE_data/cover_v3_kernel_3.core | 98 +++++ .../test/core_SUITE_data/cover_v3_kernel_4.core | 82 ++++ .../test/core_SUITE_data/cover_v3_kernel_5.core | 98 +++++ 13 files changed, 1078 insertions(+), 91 deletions(-) create mode 100644 lib/compiler/test/core_SUITE_data/cover_v3_kernel_1.core create mode 100644 lib/compiler/test/core_SUITE_data/cover_v3_kernel_2.core create mode 100644 lib/compiler/test/core_SUITE_data/cover_v3_kernel_3.core create mode 100644 lib/compiler/test/core_SUITE_data/cover_v3_kernel_4.core create mode 100644 lib/compiler/test/core_SUITE_data/cover_v3_kernel_5.core (limited to 'lib') diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index d20159c140..50d28c0a5f 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -373,7 +373,7 @@ expr(#c_case{}=Case0, Ctxt, Sub) -> %% (in addition to any warnings that may have been emitted %% according to the rules above). %% - case opt_bool_case(Case0) of + case opt_bool_case(Case0, Sub) of #c_case{arg=Arg0,clauses=Cs0}=Case1 -> Arg1 = body(Arg0, value, Sub), LitExpr = cerl:is_literal(Arg1), @@ -1554,9 +1554,11 @@ will_match(E, [P]) -> will_match_1({false,_}) -> maybe; will_match_1({true,_}) -> yes. -%% opt_bool_case(CoreExpr) - CoreExpr'. -%% Do various optimizations to case statement that has a -%% boolean case expression. +%% opt_bool_case(CoreExpr, Sub) - CoreExpr'. +%% +%% In bodies, do various optimizations to case statements that have +%% boolean case expressions. We don't do the optimizations in guards, +%% because they would thwart the optimization in v3_kernel. %% %% We start with some simple optimizations and normalization %% to facilitate later optimizations. @@ -1565,7 +1567,7 @@ will_match_1({true,_}) -> yes. %% (or fail), we can remove any clause that cannot %% possibly match 'true' or 'false'. Also, any clause %% following both 'true' and 'false' clause can -%% be removed. If successful, we will end up this: +%% be removed. If successful, we will end up like this: %% %% case BoolExpr of case BoolExpr of %% true -> false -> @@ -1576,8 +1578,11 @@ will_match_1({true,_}) -> yes. %% %% We give up if there are clauses with guards, or if there %% is a variable clause that matches anything. -%% -opt_bool_case(#c_case{arg=Arg}=Case0) -> + +opt_bool_case(#c_case{}=Case, #sub{in_guard=true}) -> + %% v3_kernel does a better job without "help". + Case; +opt_bool_case(#c_case{arg=Arg}=Case0, #sub{in_guard=false}) -> case is_bool_expr(Arg) of false -> Case0; @@ -1589,8 +1594,7 @@ opt_bool_case(#c_case{arg=Arg}=Case0) -> impossible -> Case0 end - end; -opt_bool_case(Core) -> Core. + end. opt_bool_clauses(#c_case{clauses=Cs}=Case) -> Case#c_case{clauses=opt_bool_clauses(Cs, false, false)}. @@ -2236,14 +2240,14 @@ inverse_rel_op(_) -> no. %% opt_bool_case_in_let(LetExpr) -> Core -opt_bool_case_in_let(#c_let{vars=Vs,arg=Arg,body=B}=Let) -> - opt_bool_case_in_let_1(Vs, Arg, B, Let). +opt_bool_case_in_let(#c_let{vars=Vs,arg=Arg,body=B}=Let, Sub) -> + opt_bool_case_in_let_1(Vs, Arg, B, Let, Sub). opt_bool_case_in_let_1([#c_var{name=V}], Arg, - #c_case{arg=#c_var{name=V}}=Case0, Let) -> + #c_case{arg=#c_var{name=V}}=Case0, Let, Sub) -> case is_simple_case_arg(Arg) of true -> - Case = opt_bool_case(Case0#c_case{arg=Arg}), + Case = opt_bool_case(Case0#c_case{arg=Arg}, Sub), case core_lib:is_var_used(V, Case) of false -> Case; true -> Let @@ -2251,7 +2255,7 @@ opt_bool_case_in_let_1([#c_var{name=V}], Arg, false -> Let end; -opt_bool_case_in_let_1(_, _, _, Let) -> Let. +opt_bool_case_in_let_1(_, _, _, Let, _) -> Let. %% is_simple_case_arg(Expr) -> true|false %% Determine whether the Expr is simple enough to be worth @@ -2684,8 +2688,7 @@ opt_simple_let_2(Let0, Vs0, Arg0, Body, PrevBody, Ctxt, Sub) -> #c_seq{arg=Arg,body=Body}; true -> Let1 = Let0#c_let{vars=Vs,arg=Arg1,body=Body}, - Let2 = opt_bool_case_in_let(Let1), - opt_case_in_let_arg(Let2, Ctxt, Sub) + opt_bool_case_in_let(Let1, Sub) end end. @@ -2813,48 +2816,6 @@ move_case_into_arg(#c_case{arg=#c_seq{arg=OuterArg,body=InnerArg}=Outer, move_case_into_arg(_, _) -> impossible. -%% In guards only, rewrite a case in a let argument like -%% -%% let = case <> of -%% <> when AnyGuard -> Literal1; -%% <> when AnyGuard -> Literal2 -%% end -%% in LetBody -%% -%% to -%% -%% case <> of -%% <> when AnyGuard -> -%% let = Literal1 in LetBody -%% <> when 'true' -> -%% let = Literal2 in LetBody -%% end -%% -%% In the worst case, the size of the code could increase. -%% In practice, though, substituting the literals into -%% LetBody and doing constant folding will decrease the code -%% size. (Doing this transformation outside of guards could -%% lead to a substantational increase in code size.) -%% -opt_case_in_let_arg(#c_let{arg=#c_case{}=Case}=Let, Ctxt, - #sub{in_guard=true}=Sub) -> - opt_case_in_let_arg_1(Let, Case, Ctxt, Sub); -opt_case_in_let_arg(Let, _, _) -> Let. - -opt_case_in_let_arg_1(Let0, #c_case{arg=#c_values{es=[]}, - clauses=Cs}=Case0, _Ctxt, _Sub) -> - Let = mark_compiler_generated(Let0), - case Cs of - [#c_clause{body=#c_literal{}=BodyA}=Ca0, - #c_clause{body=#c_literal{}=BodyB}=Cb0] -> - Ca = Ca0#c_clause{body=Let#c_let{arg=BodyA}}, - Cb = Cb0#c_clause{body=Let#c_let{arg=BodyB}}, - Case0#c_case{clauses=[Ca,Cb]}; - _ -> - Let - end; -opt_case_in_let_arg_1(Let, _, _, _) -> Let. - is_any_var_used([#c_var{name=V}|Vs], Expr) -> case core_lib:is_var_used(V, Expr) of false -> is_any_var_used(Vs, Expr); @@ -3285,13 +3246,6 @@ bsm_problem(Where, What) -> %%% Handling of warnings. %%% -mark_compiler_generated(Term) -> - cerl_trees:map(fun mark_compiler_generated_1/1, Term). - -mark_compiler_generated_1(#c_call{anno=Anno}=Term) -> - Term#c_call{anno=[compiler_generated|Anno--[compiler_generated]]}; -mark_compiler_generated_1(Term) -> Term. - init_warnings() -> put({?MODULE,warnings}, []). diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl index c2e0c2bd1a..3627cdb7cd 100644 --- a/lib/compiler/src/v3_codegen.erl +++ b/lib/compiler/src/v3_codegen.erl @@ -363,7 +363,7 @@ bsm_rename_ctx(#l{ke={match,Ms0,Rs}}=L, Old, New, InProt) -> bsm_rename_ctx(#l{ke={guard_match,Ms0,Rs}}=L, Old, New, InProt) -> Ms = bsm_rename_ctx(Ms0, Old, New, InProt), L#l{ke={guard_match,Ms,Rs}}; -bsm_rename_ctx(#l{ke={test,_,_}}=L, _, _, _) -> L; +bsm_rename_ctx(#l{ke={test,_,_,_}}=L, _, _, _) -> L; bsm_rename_ctx(#l{ke={bif,_,_,_}}=L, _, _, _) -> L; bsm_rename_ctx(#l{ke={gc_bif,_,_,_}}=L, _, _, _) -> L; bsm_rename_ctx(#l{ke={set,_,_}}=L, _, _, _) -> L; @@ -1051,8 +1051,15 @@ guard_cg(#l{ke={protected,Ts,Rs},i=I,vdb=Pdb}, Fail, _Vdb, Bef, St) -> protected_cg(Ts, Rs, Fail, I, Pdb, Bef, St); guard_cg(#l{ke={block,Ts},i=I,vdb=Bdb}, Fail, _Vdb, Bef, St) -> guard_cg_list(Ts, Fail, I, Bdb, Bef, St); -guard_cg(#l{ke={test,Test,As},i=I,vdb=_Tdb}, Fail, Vdb, Bef, St) -> - test_cg(Test, As, Fail, I, Vdb, Bef, St); +guard_cg(#l{ke={test,Test,As,Inverted},i=I,vdb=_Tdb}, Fail, Vdb, Bef, St0) -> + case Inverted of + false -> + test_cg(Test, As, Fail, I, Vdb, Bef, St0); + true -> + {Psucc,St1} = new_label(St0), + {Is,Aft,St2} = test_cg(Test, As, Psucc, I, Vdb, Bef, St1), + {Is++[{jump,{f,Fail}},{label,Psucc}],Aft,St2} + end; guard_cg(G, _Fail, Vdb, Bef, St) -> %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{G,Fail,Vdb,Bef}]), {Gis,Aft,St1} = cg(G, Vdb, Bef, St), @@ -1103,6 +1110,13 @@ test_cg(is_map, [A], Fail, I, Vdb, Bef, St) -> Arg = cg_reg_arg_prefer_y(A, Bef), Aft = clear_dead(Bef, I, Vdb), {[{test,is_map,{f,Fail},[Arg]}],Aft,St}; +test_cg(is_boolean, [{atom,Val}], Fail, I, Vdb, Bef, St) -> + Aft = clear_dead(Bef, I, Vdb), + Is = case is_boolean(Val) of + true -> []; + false -> [{jump,{f,Fail}}] + end, + {Is,Aft,St}; test_cg(Test, As, Fail, I, Vdb, Bef, St) -> Args = cg_reg_args(As, Bef), Aft = clear_dead(Bef, I, Vdb), diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl index f8e99905b5..2bfa610628 100644 --- a/lib/compiler/src/v3_kernel.erl +++ b/lib/compiler/src/v3_kernel.erl @@ -82,7 +82,7 @@ -export([module/2,format_error/1]). -import(lists, [map/2,foldl/3,foldr/3,mapfoldl/3,splitwith/2,member/2, - keymember/3,keyfind/3,partition/2,droplast/1,last/1]). + keymember/3,keyfind/3,partition/2,droplast/1,last/1,sort/1]). -import(ordsets, [add_element/2,del_element/2,union/2,union/1,subtract/2]). -import(cerl, [c_tuple/1]). @@ -190,9 +190,479 @@ body(Ce, Sub, St0) -> guard(G0, Sub, St0) -> {G1,St1} = wrap_guard(G0, St0), {Ge0,Pre,St2} = expr(G1, Sub, St1), - {Ge,St} = gexpr_test(Ge0, St2), + {Ge1,St3} = gexpr_test(Ge0, St2), + {Ge,St} = guard_opt(Ge1, St3), {pre_seq(Pre, Ge),St}. +%% guard_opt(Kexpr, State) -> {Kexpr,State}. +%% Optimize the Kexpr for the guard. Instead of evaluating a boolean +%% expression comparing it to 'true' in a final #k_test{}, +%% replace BIF calls with #k_test{} in the expression. +%% +%% As an example, take the guard: +%% +%% when is_integer(V0), is_atom(V1) -> +%% +%% The unoptimized Kexpr translated to pseudo BEAM assembly +%% code would look like: +%% +%% bif is_integer V0 => Bool0 +%% bif is_atom V1 => Bool1 +%% bif and Bool0 Bool1 => Bool +%% test Bool =:= true else goto Fail +%% ... +%% Fail: +%% ... +%% +%% The optimized code would look like: +%% +%% test is_integer V0 else goto Fail +%% test is_atom V1 else goto Fail +%% ... +%% Fail: +%% ... +%% +%% An 'or' operation is only slightly more complicated: +%% +%% test is_integer V0 else goto NotFailedYet +%% goto Success +%% +%% NotFailedYet: +%% test is_atom V1 else goto Fail +%% +%% Success: +%% ... +%% Fail: +%% ... + +guard_opt(G, St0) -> + {Root,Forest0,St1} = make_forest(G, St0), + {Exprs,Forest,St} = rewrite_bool(Root, Forest0, false, St1), + E = forest_pre_seq(Exprs, Forest), + {G#k_try{arg=E},St}. + +%% rewrite_bool(Kexpr, Forest, Inv, St) -> {[Kexpr],Forest,St}. +%% Rewrite Kexpr to use #k_test{} operations instead of comparison +%% and type test BIFs. +%% +%% If Kexpr is a #k_test{} operation, the call will always +%% succeed. Otherwise, a 'not_possible' exception will be +%% thrown if Kexpr cannot be rewritten. + +rewrite_bool(#k_test{op=#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val='=:='}}, + args=[#k_var{}=V,#k_atom{val=true}]}=Test, Forest0, Inv, St0) -> + try rewrite_bool_var(V, Forest0, Inv, St0) of + {_,_,_}=Res -> + Res + catch + throw:not_possible -> + {[Test],Forest0,St0} + end; +rewrite_bool(#k_test{op=#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val='=:='}}, + args=[#k_var{}=V,#k_atom{val=false}]}=Test, Forest0, Inv, St0) -> + try rewrite_bool_var(V, Forest0, not Inv, St0) of + {_,_,_}=Res -> + Res + catch + throw:not_possible -> + {[Test],Forest0,St0} + end; +rewrite_bool(#k_test{op=#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val='=:='}}, + args=[#k_atom{val=V1},#k_atom{val=V2}]}, Forest0, false, St0) -> + case V1 =:= V2 of + true -> + {[make_test(is_boolean, [#k_atom{val=true}])],Forest0,St0}; + false -> + {[make_failing_test()],Forest0,St0} + end; +rewrite_bool(#k_test{}=Test, Forest, false, St) -> + {[Test],Forest,St}; +rewrite_bool(#k_try{vars=[#k_var{name=X}],body=#k_var{name=X}, + handler=#k_atom{val=false},ret=[]}=Prot, + Forest0, Inv, St0) -> + {Root,Forest1,St1} = make_forest(Prot, Forest0, St0), + {Exprs,Forest2,St} = rewrite_bool(Root, Forest1, Inv, St1), + InnerForest = maps:without(maps:keys(Forest0), Forest2), + Forest = maps:without(maps:keys(InnerForest), Forest2), + E = forest_pre_seq(Exprs, InnerForest), + {[Prot#k_try{arg=E}],Forest,St}; +rewrite_bool(#k_match{body=Body,ret=[]}, Forest, Inv, St) -> + rewrite_match(Body, Forest, Inv, St); +rewrite_bool(Other, Forest, Inv, St) -> + case extract_bif(Other) of + {Name,Args} -> + rewrite_bif(Name, Args, Forest, Inv, St); + error -> + throw(not_possible) + end. + +%% rewrite_bool_var(Var, Forest, Inv, St) -> {[Kexpr],Forest,St}. +%% Rewrite the boolean expression whose key in Forest is +%% given by Var. Throw a 'not_possible' expression if something +%% prevents the rewriting. + +rewrite_bool_var(Arg, Forest0, Inv, St) -> + {Expr,Forest} = forest_take_expr(Arg, Forest0), + rewrite_bool(Expr, Forest, Inv, St). + +%% rewrite_bool_args([Kexpr], Forest, Inv, St) -> {[[Kexpr]],Forest,St}. +%% Rewrite each Kexpr in the list. The input Kexpr should be variables +%% or boolean values. Throw a 'not_possible' expression if something +%% prevents the rewriting. +%% +%% This function is suitable for handling the arguments for both +%% 'and' and 'or'. + +rewrite_bool_args([#k_atom{val=B}=A|Vs], Forest0, false=Inv, St0) when is_boolean(B) -> + {Tail,Forest1,St1} = rewrite_bool_args(Vs, Forest0, Inv, St0), + Bif = make_bif('=:=', [A,#k_atom{val=true}]), + {Exprs,Forest,St} = rewrite_bool(Bif, Forest1, Inv, St1), + {[Exprs|Tail],Forest,St}; +rewrite_bool_args([#k_var{}=Var|Vs], Forest0, false=Inv, St0) -> + {Tail,Forest1,St1} = rewrite_bool_args(Vs, Forest0, Inv, St0), + {Exprs,Forest,St} = + case is_bool_expr(Var, Forest0) of + true -> + rewrite_bool_var(Var, Forest1, Inv, St1); + false -> + Bif = make_bif('=:=', [Var,#k_atom{val=true}]), + rewrite_bool(Bif, Forest1, Inv, St1) + end, + {[Exprs|Tail],Forest,St}; +rewrite_bool_args([_|_], _Forest, _Inv, _St) -> + throw(not_possible); +rewrite_bool_args([], Forest, _Inv, St) -> + {[],Forest,St}. + +%% rewrite_bif(Name, [Kexpr], Forest, Inv, St) -> {[Kexpr],Forest,St}. +%% Rewrite a BIF. Throw a 'not_possible' expression if something +%% prevents the rewriting. + +rewrite_bif('or', Args, Forest, true, St) -> + rewrite_not_args('and', Args, Forest, St); +rewrite_bif('and', Args, Forest, true, St) -> + rewrite_not_args('or', Args, Forest, St); +rewrite_bif('and', [#k_atom{val=Val},Arg], Forest0, Inv, St0) -> + false = Inv, %Assertion. + case Val of + true -> + %% The result only depends on Arg. + rewrite_bool_var(Arg, Forest0, Inv, St0); + _ -> + %% Will fail. There is no need to evalute the expression + %% represented by Arg. Take it out from the forest and + %% discard the expression. + Failing = make_failing_test(), + try rewrite_bool_var(Arg, Forest0, Inv, St0) of + {_,Forest,St} -> + {[Failing],Forest,St} + catch + throw:not_possible -> + try forest_take_expr(Arg, Forest0) of + {_,Forest} -> + {[Failing],Forest,St0} + catch + throw:not_possible -> + %% Arg is probably a variable bound in an + %% outer scope. + {[Failing],Forest0,St0} + end + end + end; +rewrite_bif('and', [Arg,#k_atom{}=Atom], Forest, Inv, St) -> + false = Inv, %Assertion. + rewrite_bif('and', [Atom,Arg], Forest, Inv, St); +rewrite_bif('and', Args, Forest0, Inv, St0) -> + false = Inv, %Assertion. + {[Es1,Es2],Forest,St} = rewrite_bool_args(Args, Forest0, Inv, St0), + {Es1 ++ Es2,Forest,St}; +rewrite_bif('or', Args, Forest0, Inv, St0) -> + false = Inv, %Assertion. + {[First,Then],Forest,St} = rewrite_bool_args(Args, Forest0, Inv, St0), + Alt = make_alt(First, Then), + {[Alt],Forest,St}; +rewrite_bif('xor', [_,_], _Forest, _Inv, _St) -> + %% Rewriting 'xor' is not practical. Fortunately, 'xor' is + %% almost never used in practice. + throw(not_possible); +rewrite_bif('not', [Arg], Forest0, Inv, St) -> + {Expr,Forest} = forest_take_expr(Arg, Forest0), + rewrite_bool(Expr, Forest, not Inv, St); +rewrite_bif(Op, Args, Forest, Inv, St) -> + case is_test(Op, Args) of + true -> + rewrite_bool(make_test(Op, Args, Inv), Forest, false, St); + false -> + throw(not_possible) + end. + +rewrite_not_args(Op, [A0,B0], Forest0, St0) -> + {A,Forest1,St1} = rewrite_not_args_1(A0, Forest0, St0), + {B,Forest2,St2} = rewrite_not_args_1(B0, Forest1, St1), + rewrite_bif(Op, [A,B], Forest2, false, St2). + +rewrite_not_args_1(Arg, Forest, St) -> + Not = make_bif('not', [Arg]), + forest_add_expr(Not, Forest, St). + +%% rewrite_match(Kvar, TypeClause, Forest, Inv, St) -> +%% {[Kexpr],Forest,St}. +%% Try to rewrite a #k_match{} originating from an 'andalso' or an 'orelse'. + +rewrite_match(#k_alt{first=First,then=Then}, Forest, Inv, St) -> + case {First,Then} of + {#k_select{var=#k_var{name=V}=Var,types=[TypeClause]},#k_var{name=V}} -> + rewrite_match_1(Var, TypeClause, Forest, Inv, St); + {_,_} -> + throw(not_possible) + end. + +rewrite_match_1(Var, #k_type_clause{values=Cs0}, Forest0, Inv, St0) -> + Cs = sort([{Val,B} || #k_val_clause{val=#k_atom{val=Val},body=B} <- Cs0]), + case Cs of + [{false,False},{true,True}] -> + rewrite_match_2(Var, False, True, Forest0, Inv, St0); + _ -> + throw(not_possible) + end. + +rewrite_match_2(Var, False, #k_atom{val=true}, Forest0, Inv, St0) -> + %% Originates from an 'orelse'. + case False of + #k_atom{val=NotBool} when not is_boolean(NotBool) -> + rewrite_bool(Var, Forest0, Inv, St0); + _ -> + {CodeVar,Forest1,St1} = add_protected_expr(False, Forest0, St0), + rewrite_bif('or', [Var,CodeVar], Forest1, Inv, St1) + end; +rewrite_match_2(Var, #k_atom{val=false}, True, Forest0, Inv, St0) -> + %% Originates from an 'andalso'. + {CodeVar,Forest1,St1} = add_protected_expr(True, Forest0, St0), + rewrite_bif('and', [Var,CodeVar], Forest1, Inv, St1); +rewrite_match_2(_V, _, _, _Forest, _Inv, _St) -> + throw(not_possible). + +%% is_bool_expr(#k_var{}, Forest) -> true|false. +%% Return true if the variable refers to a boolean expression +%% that does not need an explicit '=:= true' test. + +is_bool_expr(V, Forest) -> + case forest_peek_expr(V, Forest) of + error -> + %% Defined outside of the guard. We can't know. + false; + Expr -> + case extract_bif(Expr) of + {Name,Args} -> + is_test(Name, Args) orelse + erl_internal:bool_op(Name, length(Args)); + error -> + %% Not a BIF. Should be possible to rewrite + %% to a boolean. Definitely does not need + %% a '=:= true' test. + true + end + end. + +make_bif(Op, Args) -> + #k_bif{op=#k_remote{mod=#k_atom{val=erlang}, + name=#k_atom{val=Op}, + arity=length(Args)}, + args=Args}. + +extract_bif(#k_bif{op=#k_remote{mod=#k_atom{val=erlang}, + name=#k_atom{val=Name}}, + args=Args}) -> + {Name,Args}; +extract_bif(_) -> + error. + +%% make_alt(First, Then) -> KMatch. +%% Make a #k_alt{} within a #k_match{} to implement +%% 'or' or 'orelse'. + +make_alt(First0, Then0) -> + First1 = pre_seq(droplast(First0), last(First0)), + Then1 = pre_seq(droplast(Then0), last(Then0)), + First2 = make_protected(First1), + Then2 = make_protected(Then1), + Body = #k_atom{val=ignored}, + First3 = #k_guard_clause{guard=First2,body=Body}, + Then3 = #k_guard_clause{guard=Then2,body=Body}, + First = #k_guard{clauses=[First3]}, + Then = #k_guard{clauses=[Then3]}, + Alt = #k_alt{first=First,then=Then}, + #k_match{vars=[],body=Alt}. + +add_protected_expr(#k_atom{}=Atom, Forest, St) -> + {Atom,Forest,St}; +add_protected_expr(#k_var{}=Var, Forest, St) -> + {Var,Forest,St}; +add_protected_expr(E0, Forest, St) -> + E = make_protected(E0), + forest_add_expr(E, Forest, St). + +make_protected(#k_try{}=Try) -> + Try; +make_protected(B) -> + #k_try{arg=B,vars=[#k_var{name=''}],body=#k_var{name=''}, + handler=#k_atom{val=false}}. + +make_failing_test() -> + make_test(is_boolean, [#k_atom{val=fail}]). + +make_test(Op, Args) -> + make_test(Op, Args, false). + +make_test(Op, Args, Inv) -> + Remote = #k_remote{mod=#k_atom{val=erlang}, + name=#k_atom{val=Op}, + arity=length(Args)}, + #k_test{op=Remote,args=Args,inverted=Inv}. + +is_test(Op, Args) -> + A = length(Args), + erl_internal:new_type_test(Op, A) orelse erl_internal:comp_op(Op, A). + +%% make_forest(Kexpr, St) -> {RootKexpr,Forest,St}. +%% Build a forest out of Kexpr. RootKexpr is the final expression +%% nested inside Kexpr. + +make_forest(G, St) -> + make_forest_1(G, #{}, 0, St). + +%% make_forest(Kexpr, St) -> {RootKexpr,Forest,St}. +%% Add to Forest from Kexpr. RootKexpr is the final expression +%% nested inside Kexpr. + +make_forest(G, Forest0, St) -> + N = forest_next_index(Forest0), + make_forest_1(G, Forest0, N, St). + +make_forest_1(#k_try{arg=B}, Forest, I, St) -> + make_forest_1(B, Forest, I, St); +make_forest_1(#iset{vars=[]}=Iset0, Forest, I, St0) -> + {UnrefVar,St} = new_var(St0), + Iset = Iset0#iset{vars=[UnrefVar]}, + make_forest_1(Iset, Forest, I, St); +make_forest_1(#iset{vars=[#k_var{name=V}],arg=Arg,body=B}, Forest0, I, St) -> + Forest = Forest0#{V => {I,Arg}, {untaken,V} => true}, + make_forest_1(B, Forest, I+1, St); +make_forest_1(Innermost, Forest, _I, St) -> + {Innermost,Forest,St}. + +%% forest_take_expr(Kexpr, Forest) -> {Expr,Forest}. +%% If Kexpr is a variable, take out the expression corresponding +%% to variable in Forest. Expressions that have been taken out +%% of the forest will not be included the Kexpr returned +%% by forest_pre_seq/2. +%% +%% Throw a 'not_possible' exception if Kexpr is not a variable or +%% if the name of the variable is not a key in Forest. + +forest_take_expr(#k_var{name=V}, Forest0) -> + %% v3_core currently always generates guard expressions that can + %% be represented as a tree. Other code generators (such as LFE) + %% could generate guard expressions that can only be represented + %% as a DAG (i.e. some nodes are referenced more than once). To + %% handle DAGs, we must never remove a node from the forest, but + %% just remove the {untaken,V} marker. That will effectively convert + %% the DAG to a tree by duplicating the shared nodes and their + %% descendants. + + case maps:find(V, Forest0) of + {ok,{_,Expr}} -> + Forest = maps:remove({untaken,V}, Forest0), + {Expr,Forest}; + error -> + throw(not_possible) + end; +forest_take_expr(_, _) -> + throw(not_possible). + +%% forest_peek_expr(Kvar, Forest) -> Kexpr | error. +%% Return the expression corresponding to Kvar in Forest or +%% return 'error' if there is a corresponding expression. + +forest_peek_expr(#k_var{name=V}, Forest0) -> + case maps:find(V, Forest0) of + {ok,{_,Expr}} -> Expr; + error -> error + end. + +%% forest_add_expr(Kexpr, Forest, St) -> {Kvar,Forest,St}. +%% Add a new expression to Forest. + +forest_add_expr(Expr, Forest0, St0) -> + {#k_var{name=V}=Var,St} = new_var(St0), + N = forest_next_index(Forest0), + Forest = Forest0#{V => {N,Expr}}, + {Var,Forest,St}. + +forest_next_index(Forest) -> + 1 + lists:max([N || {N,_} <- maps:values(Forest), + is_integer(N)] ++ [0]). + +%% forest_pre_seq([Kexpr], Forest) -> Kexpr. +%% Package the list of Kexprs into a nested Kexpr, prepending all +%% expressions in Forest that have not been taken out using +%% forest_take_expr/2. + +forest_pre_seq(Exprs, Forest) -> + Es0 = [#k_var{name=V} || {untaken,V} <- maps:keys(Forest)], + Es = Es0 ++ Exprs, + Vs = extract_all_vars(Es, Forest, []), + Pre0 = sort([{maps:get(V, Forest),V} || V <- Vs]), + Pre = [#iset{vars=[#k_var{name=V}],arg=A} || + {{_,A},V} <- Pre0], + pre_seq(Pre++droplast(Exprs), last(Exprs)). + +extract_all_vars(Es, Forest, Acc0) -> + case extract_var_list(Es) of + [] -> + Acc0; + [_|_]=Vs0 -> + Vs = [V || V <- Vs0, maps:is_key(V, Forest)], + NewVs = ordsets:subtract(Vs, Acc0), + NewEs = [begin + {_,E} = maps:get(V, Forest), + E + end || V <- NewVs], + Acc = union(NewVs, Acc0), + extract_all_vars(NewEs, Forest, Acc) + end. + +extract_vars(#iset{arg=A,body=B}) -> + union(extract_vars(A), extract_vars(B)); +extract_vars(#k_bif{args=Args}) -> + ordsets:from_list(lit_list_vars(Args)); +extract_vars(#k_call{}) -> + []; +extract_vars(#k_test{args=Args}) -> + ordsets:from_list(lit_list_vars(Args)); +extract_vars(#k_match{body=Body}) -> + extract_vars(Body); +extract_vars(#k_alt{first=First,then=Then}) -> + union(extract_vars(First), extract_vars(Then)); +extract_vars(#k_guard{clauses=Cs}) -> + extract_var_list(Cs); +extract_vars(#k_guard_clause{guard=G}) -> + extract_vars(G); +extract_vars(#k_select{var=Var,types=Types}) -> + union(ordsets:from_list(lit_vars(Var)), + extract_var_list(Types)); +extract_vars(#k_type_clause{values=Values}) -> + extract_var_list(Values); +extract_vars(#k_val_clause{body=Body}) -> + extract_vars(Body); +extract_vars(#k_try{arg=Arg}) -> + extract_vars(Arg); +extract_vars(Lit) -> + ordsets:from_list(lit_vars(Lit)). + +extract_var_list(L) -> + union([extract_vars(E) || E <- L]). + %% Wrap the entire guard in a try/catch if needed. wrap_guard(#c_try{}=Try, St) -> {Try,St}; diff --git a/lib/compiler/src/v3_kernel.hrl b/lib/compiler/src/v3_kernel.hrl index 1169a69117..7cd30b25a8 100644 --- a/lib/compiler/src/v3_kernel.hrl +++ b/lib/compiler/src/v3_kernel.hrl @@ -58,7 +58,7 @@ -record(k_seq, {anno=[],arg,body}). -record(k_put, {anno=[],arg,ret=[]}). -record(k_bif, {anno=[],op,args,ret=[]}). --record(k_test, {anno=[],op,args}). +-record(k_test, {anno=[],op,args,inverted=false}). -record(k_call, {anno=[],op,args,ret=[]}). -record(k_enter, {anno=[],op,args}). -record(k_receive, {anno=[],var,body,timeout,action,ret=[]}). diff --git a/lib/compiler/src/v3_kernel_pp.erl b/lib/compiler/src/v3_kernel_pp.erl index 45065b7e11..d5f6ee19c9 100644 --- a/lib/compiler/src/v3_kernel_pp.erl +++ b/lib/compiler/src/v3_kernel_pp.erl @@ -235,8 +235,13 @@ format_1(#k_bif{op=Op,args=As,ret=Rs}, Ctxt) -> [Txt,format_args(As, Ctxt1), format_ret(Rs, Ctxt1) ]; -format_1(#k_test{op=Op,args=As}, Ctxt) -> - Txt = ["test (",format(Op, ctxt_bump_indent(Ctxt, 6)),$)], +format_1(#k_test{op=Op,args=As,inverted=Inverted}, Ctxt) -> + Txt = case Inverted of + false -> + ["test (",format(Op, ctxt_bump_indent(Ctxt, 6)),$)]; + true -> + ["inverted_test (",format(Op, ctxt_bump_indent(Ctxt, 6)),$)] + end, Ctxt1 = ctxt_bump_indent(Ctxt, 2), [Txt,format_args(As, Ctxt1)]; format_1(#k_put{arg=A,ret=Rs}, Ctxt) -> diff --git a/lib/compiler/src/v3_life.erl b/lib/compiler/src/v3_life.erl index 4337ec732c..0f2aeda87f 100644 --- a/lib/compiler/src/v3_life.erl +++ b/lib/compiler/src/v3_life.erl @@ -118,8 +118,8 @@ protected(#k_protected{anno=A,arg=Ts,ret=Rs}, I, Vdb) -> %% expr(Kexpr, I, Vdb) -> Expr. -expr(#k_test{anno=A,op=Op,args=As}, I, _Vdb) -> - #l{ke={test,test_op(Op),atomic_list(As)},i=I,a=A#k.a}; +expr(#k_test{anno=A,op=Op,args=As,inverted=Inverted}, I, _Vdb) -> + #l{ke={test,test_op(Op),atomic_list(As),Inverted},i=I,a=A#k.a}; expr(#k_call{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) -> #l{ke={call,call_op(Op),atomic_list(As),var_list(Rs)},i=I,a=A#k.a}; expr(#k_enter{anno=A,op=Op,args=As}, I, _Vdb) -> diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index 6742571b86..89f851ac3b 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -887,28 +887,41 @@ matching_and_andalso(Config) when is_list(Config) -> {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)), {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)), - {"abc",<<"xyz">>} = matching_and_andalso_2("abc", <<"-xyz">>), - {"abc",<<"">>} = matching_and_andalso_2("abc", <<($a-1)>>), - {"abc",<<"">>} = matching_and_andalso_2("abc", <<($z+1)>>), - {"abc",<<"">>} = matching_and_andalso_2("abc", <<($A-1)>>), - {"abc",<<"">>} = matching_and_andalso_2("abc", <<($Z+1)>>), - error = matching_and_andalso_2([], <<>>), - error = matching_and_andalso_2([], <<$A>>), - error = matching_and_andalso_2([], <<$Z>>), - error = matching_and_andalso_2([], <<$a>>), - error = matching_and_andalso_2([], <<$z>>), + {"abc",<<"xyz">>} = matching_and_andalso_23("abc", <<"-xyz">>), + {"abc",<<"">>} = matching_and_andalso_23("abc", <<($a-1)>>), + {"abc",<<"">>} = matching_and_andalso_23("abc", <<($z+1)>>), + {"abc",<<"">>} = matching_and_andalso_23("abc", <<($A-1)>>), + {"abc",<<"">>} = matching_and_andalso_23("abc", <<($Z+1)>>), + error = matching_and_andalso_23([], <<>>), + error = matching_and_andalso_23([], <<$A>>), + error = matching_and_andalso_23([], <<$Z>>), + error = matching_and_andalso_23([], <<$a>>), + error = matching_and_andalso_23([], <<$z>>), ok. matching_and_andalso_1(<>, K) when is_integer(K) andalso size(Bitmap) >= K andalso 0 < K -> ok. +matching_and_andalso_23(Datetime, Bin) -> + Res = matching_and_andalso_2(Datetime, Bin), + Res = matching_and_andalso_3(Datetime, Bin), + Res. + matching_and_andalso_2(Datetime, <>) when not ((H >= $a) andalso (H =< $z)) andalso not ((H >= $A) andalso (H =< $Z)) -> {Datetime,T}; matching_and_andalso_2(_, _) -> error. +%% Contrived example to ensure we cover the handling of 'call' instructions +%% in v3_codegen:bsm_rename_ctx/4. +matching_and_andalso_3(Datetime, <>) + when not ((abs(H) >= $a) andalso (abs(H) =< $z)) andalso + not ((abs(H) >= $A) andalso (abs(H) =< $Z)) -> + {Datetime,T}; +matching_and_andalso_3(_, _) -> error. + %% Thanks to Tomas Stejskal. otp_7188(Config) when is_list(Config) -> MP3 = <<84,65,71,68,117,154,105,232,107,121,0,0,0,0,0,0,0,0,0,0, diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl index b768f49e2c..f8839da42f 100644 --- a/lib/compiler/test/core_SUITE.erl +++ b/lib/compiler/test/core_SUITE.erl @@ -26,8 +26,9 @@ seq_in_guard/1,make_effect_seq/1,eval_is_boolean/1, unsafe_case/1,nomatch_shadow/1,reversed_annos/1, map_core_test/1,eval_case/1,bad_boolean_guard/1, - bs_shadowed_size_var/1 - ]). + bs_shadowed_size_var/1, + cover_v3_kernel_1/1,cover_v3_kernel_2/1,cover_v3_kernel_3/1, + cover_v3_kernel_4/1,cover_v3_kernel_5/1]). -include_lib("common_test/include/ct.hrl"). @@ -53,8 +54,10 @@ groups() -> [dehydrated_itracer,nested_tries,seq_in_guard,make_effect_seq, eval_is_boolean,unsafe_case,nomatch_shadow,reversed_annos, map_core_test,eval_case,bad_boolean_guard, - bs_shadowed_size_var - ]}]. + bs_shadowed_size_var, + cover_v3_kernel_1,cover_v3_kernel_2,cover_v3_kernel_3, + cover_v3_kernel_4,cover_v3_kernel_5 + ]}]. init_per_suite(Config) -> @@ -64,10 +67,10 @@ end_per_suite(_Config) -> ok. init_per_group(_GroupName, Config) -> - Config. + Config. end_per_group(_GroupName, Config) -> - Config. + Config. ?comp(dehydrated_itracer). @@ -82,6 +85,11 @@ end_per_group(_GroupName, Config) -> ?comp(eval_case). ?comp(bad_boolean_guard). ?comp(bs_shadowed_size_var). +?comp(cover_v3_kernel_1). +?comp(cover_v3_kernel_2). +?comp(cover_v3_kernel_3). +?comp(cover_v3_kernel_4). +?comp(cover_v3_kernel_5). try_it(Mod, Conf) -> diff --git a/lib/compiler/test/core_SUITE_data/cover_v3_kernel_1.core b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_1.core new file mode 100644 index 0000000000..9e5788796f --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_1.core @@ -0,0 +1,147 @@ +module 'cover_v3_kernel_1' ['cover_v3_kernel_1'/0, + 'module_info'/0, + 'module_info'/1] + attributes [] +'cover_v3_kernel_1'/0 = + %% Line 4 + fun () -> + case <> of + <> when 'true' -> + %% Line 5 + case apply 'bad_and_args'/1 + ('x') of + <'error'> when 'true' -> + %% Line 7 + case apply 'bad_and_args'/2 + (1, 2) of + <'error'> when 'true' -> + %% Line 8 + case apply 'bad_and_args'/2 + (1, 'true') of + <'error'> when 'true' -> + %% Line 9 + case apply 'bad_and_args'/2 + ('true', 42) of + <'error'> when 'true' -> + %% Line 10 + case apply 'bad_and_args'/2 + ('true', 'false') of + <'error'> when 'true' -> + %% Line 11 + case apply 'bad_and_args'/2 + ('false', 'true') of + <'error'> when 'true' -> + %% Line 12 + case apply 'bad_and_args'/2 + ('true', 'true') of + <'ok'> when 'true' -> + %% Line 14 + 'ok' + ( <_@c6> when 'true' -> + primop 'match_fail' + ({'badmatch',_@c6}) + -| ['compiler_generated'] ) + end + ( <_@c5> when 'true' -> + primop 'match_fail' + ({'badmatch',_@c5}) + -| ['compiler_generated'] ) + end + ( <_@c4> when 'true' -> + primop 'match_fail' + ({'badmatch',_@c4}) + -| ['compiler_generated'] ) + end + ( <_@c3> when 'true' -> + primop 'match_fail' + ({'badmatch',_@c3}) + -| ['compiler_generated'] ) + end + ( <_@c2> when 'true' -> + primop 'match_fail' + ({'badmatch',_@c2}) + -| ['compiler_generated'] ) + end + ( <_@c1> when 'true' -> + primop 'match_fail' + ({'badmatch',_@c1}) + -| ['compiler_generated'] ) + end + ( <_@c0> when 'true' -> + primop 'match_fail' + ({'badmatch',_@c0}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'cover_v3_kernel_1',0}}] ) + -| ['compiler_generated'] ) + end +'bad_and_args'/1 = + %% Line 16 + fun (_@c0) -> + case _@c0 of + + when try + call 'erlang':'and'(A, 42) + of -> + Try + catch -> + 'false' -> + 'ok' + %% Line 17 + <_@c4> when 'true' -> + 'error' + ( <_@c3> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_@c3}) + -| [{'function_name',{'bad_and_args',1}}] ) + -| ['compiler_generated'] ) + end +'bad_and_args'/2 = + %% Line 19 + fun (_@c1,_@c0) -> + case <_@c1,_@c0> of + + when try + call 'erlang':'and'(X, Y) + of -> + Try + catch -> + 'false' -> + 'ok' + %% Line 20 + <_@c6,_@c7> when 'true' -> + 'error' + ( <_@c5,_@c4> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_@c5,_@c4}) + -| [{'function_name',{'bad_and_args',2}}] ) + -| ['compiler_generated'] ) + end +'module_info'/0 = + fun () -> + case <> of + <> when 'true' -> + call 'erlang':'get_module_info' + ('cover_v3_kernel_1') + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'module_info',0}}] ) + -| ['compiler_generated'] ) + end +'module_info'/1 = + fun (_@c0) -> + case _@c0 of + when 'true' -> + call 'erlang':'get_module_info' + ('cover_v3_kernel_1', X) + ( <_@c1> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_@c1}) + -| [{'function_name',{'module_info',1}}] ) + -| ['compiler_generated'] ) + end +end diff --git a/lib/compiler/test/core_SUITE_data/cover_v3_kernel_2.core b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_2.core new file mode 100644 index 0000000000..165aacd691 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_2.core @@ -0,0 +1,98 @@ +module 'cover_v3_kernel_2' ['cover_v3_kernel_2'/0, + 'module_info'/0, + 'module_info'/1] + attributes [] +'cover_v3_kernel_2'/0 = + %% Line 4 + fun () -> + case <> of + <> when 'true' -> + %% Line 5 + case apply 'strange_case'/1 + ('a') of + <'ok'> when 'true' -> + %% Line 6 + case apply 'strange_case'/1 + ('b') of + <'ok'> when 'true' -> + %% Line 7 + case apply 'strange_case'/1 + ('c') of + <'error'> when 'true' -> + %% Line 8 + case apply 'strange_case'/1 + (42) of + <'error'> when 'true' -> + %% Line 9 + 'ok' + ( <_cor3> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor3}) + -| ['compiler_generated'] ) + end + ( <_cor2> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor2}) + -| ['compiler_generated'] ) + end + ( <_cor1> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor1}) + -| ['compiler_generated'] ) + end + ( <_cor0> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor0}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'cover_v3_kernel_2',0}}] ) + -| ['compiler_generated'] ) + end +'strange_case'/1 = + %% Line 12 + fun (_cor0) -> + case _cor0 of + when + case X of + <'a'> when 'true' -> 'true' + <'b'> when 'true' -> 'true' + when 'true' -> 'false' + end -> + 'ok' + %% Line 13 + <_cor4> when 'true' -> + 'error' + ( <_cor3> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor3}) + -| [{'function_name',{'strange_case',1}}] ) + -| ['compiler_generated'] ) + end +'module_info'/0 = + fun () -> + case <> of + <> when 'true' -> + call 'erlang':'get_module_info' + ('cover_v3_kernel_2') + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'module_info',0}}] ) + -| ['compiler_generated'] ) + end +'module_info'/1 = + fun (_cor0) -> + case _cor0 of + when 'true' -> + call 'erlang':'get_module_info' + ('cover_v3_kernel_2', X) + ( <_cor1> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor1}) + -| [{'function_name',{'module_info',1}}] ) + -| ['compiler_generated'] ) + end +end diff --git a/lib/compiler/test/core_SUITE_data/cover_v3_kernel_3.core b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_3.core new file mode 100644 index 0000000000..88a9edc354 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_3.core @@ -0,0 +1,98 @@ +module 'cover_v3_kernel_3' ['cover_v3_kernel_3'/0, + 'module_info'/0, + 'module_info'/1] + attributes [] +'cover_v3_kernel_3'/0 = + %% Line 4 + fun () -> + case <> of + <> when 'true' -> + %% Line 5 + case apply 'strange_case'/1 + (1) of + <'ok'> when 'true' -> + %% Line 6 + case apply 'strange_case'/1 + (2) of + <'ok'> when 'true' -> + %% Line 7 + case apply 'strange_case'/1 + (42) of + <'error'> when 'true' -> + %% Line 8 + case apply 'strange_case'/1 + ('atom') of + <'error'> when 'true' -> + %% Line 9 + 'ok' + ( <_cor3> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor3}) + -| ['compiler_generated'] ) + end + ( <_cor2> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor2}) + -| ['compiler_generated'] ) + end + ( <_cor1> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor1}) + -| ['compiler_generated'] ) + end + ( <_cor0> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor0}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'cover_v3_kernel_3',0}}] ) + -| ['compiler_generated'] ) + end +'strange_case'/1 = + %% Line 12 + fun (_cor0) -> + case _cor0 of + when + case X of + <1> when 'true' -> 'true' + <2> when 'true' -> 'true' + when 'true' -> 'false' + end -> + 'ok' + %% Line 13 + <_cor4> when 'true' -> + 'error' + ( <_cor3> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor3}) + -| [{'function_name',{'strange_case',1}}] ) + -| ['compiler_generated'] ) + end +'module_info'/0 = + fun () -> + case <> of + <> when 'true' -> + call 'erlang':'get_module_info' + ('cover_v3_kernel_3') + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'module_info',0}}] ) + -| ['compiler_generated'] ) + end +'module_info'/1 = + fun (_cor0) -> + case _cor0 of + when 'true' -> + call 'erlang':'get_module_info' + ('cover_v3_kernel_3', X) + ( <_cor1> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor1}) + -| [{'function_name',{'module_info',1}}] ) + -| ['compiler_generated'] ) + end +end diff --git a/lib/compiler/test/core_SUITE_data/cover_v3_kernel_4.core b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_4.core new file mode 100644 index 0000000000..905e236f26 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_4.core @@ -0,0 +1,82 @@ +module 'cover_v3_kernel_4' ['cover_v3_kernel_4'/0, + 'module_info'/0, + 'module_info'/1] + attributes [] +'cover_v3_kernel_4'/0 = + %% Line 4 + fun () -> + %% Line 5 + case apply 'turned_case'/1 + (20) of + <'ok'> when 'true' -> + %% Line 6 + case apply 'turned_case'/1 + (0) of + <'error'> when 'true' -> + %% Line 7 + 'ok' + ( <_@c1> when 'true' -> + primop 'match_fail' + ({'badmatch',_@c1}) + -| ['compiler_generated'] ) + end + ( <_@c0> when 'true' -> + primop 'match_fail' + ({'badmatch',_@c0}) + -| ['compiler_generated'] ) + end +'turned_case'/1 = + %% Line 9 + fun (_@c0) -> + let = + apply %% Line 10 + 'id'/1 + (%% Line 10 + 'true') + in %% Line 11 + case <> of + %% Line 12 + <> + when try + ( let <_@c4> = + case call 'erlang':'<' + (_@c0, 10) of + ( <( 'false' + -| ['compiler_generated'] )> when 'true' -> + True + -| ['compiler_generated'] ) + ( <( 'true' + -| ['compiler_generated'] )> when 'true' -> + 'false' + -| ['compiler_generated'] ) + ( <_@c2> when 'true' -> + _@c2 + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (( _@c4 + -| ['compiler_generated'] ), 'true') + -| ['compiler_generated'] ) + -| ['compiler_generated'] ) + of -> + Try + catch -> + 'false' -> + 'ok' + %% Line 13 + <> when 'true' -> + 'error' + end +'id'/1 = + %% Line 16 + fun (_@c0) -> + _@c0 +'module_info'/0 = + fun () -> + call 'erlang':'get_module_info' + ('cover_v3_kernel_4') +'module_info'/1 = + fun (_@c0) -> + call 'erlang':'get_module_info' + ('cover_v3_kernel_4', _@c0) +end \ No newline at end of file diff --git a/lib/compiler/test/core_SUITE_data/cover_v3_kernel_5.core b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_5.core new file mode 100644 index 0000000000..48c1bb84e6 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_5.core @@ -0,0 +1,98 @@ +module 'cover_v3_kernel_5' ['cover_v3_kernel_5'/0, + 'module_info'/0, + 'module_info'/1] + attributes [] +'cover_v3_kernel_5'/0 = + %% Line 4 + fun () -> + case <> of + <> when 'true' -> + %% Line 5 + case apply 'strange_case'/1 + (1) of + <'ok'> when 'true' -> + %% Line 6 + case apply 'strange_case'/1 + (2) of + <'ok'> when 'true' -> + %% Line 7 + case apply 'strange_case'/1 + (42) of + <'error'> when 'true' -> + %% Line 8 + case apply 'strange_case'/1 + ('atom') of + <'error'> when 'true' -> + %% Line 9 + 'ok' + ( <_cor3> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor3}) + -| ['compiler_generated'] ) + end + ( <_cor2> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor2}) + -| ['compiler_generated'] ) + end + ( <_cor1> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor1}) + -| ['compiler_generated'] ) + end + ( <_cor0> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor0}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'cover_v3_kernel_5',0}}] ) + -| ['compiler_generated'] ) + end +'strange_case'/1 = + %% Line 12 + fun (_cor0) -> + case _cor0 of + when + case X of + <1> when 'true' -> 'true' + <2> when 'true' -> 'true' + when 'true' -> X + end -> + 'ok' + %% Line 13 + <_cor4> when 'true' -> + 'error' + ( <_cor3> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor3}) + -| [{'function_name',{'strange_case',1}}] ) + -| ['compiler_generated'] ) + end +'module_info'/0 = + fun () -> + case <> of + <> when 'true' -> + call 'erlang':'get_module_info' + ('cover_v3_kernel_5') + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'module_info',0}}] ) + -| ['compiler_generated'] ) + end +'module_info'/1 = + fun (_cor0) -> + case _cor0 of + when 'true' -> + call 'erlang':'get_module_info' + ('cover_v3_kernel_5', X) + ( <_cor1> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor1}) + -| [{'function_name',{'module_info',1}}] ) + -| ['compiler_generated'] ) + end +end -- cgit v1.2.3 From 132d61e6f075f8e85da268e88953980c2f348987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 4 Oct 2016 11:00:51 +0200 Subject: Remove beam_bool The guard optimizations in v3_kernel has removed the need for beam_bool. --- lib/compiler/src/Makefile | 1 - lib/compiler/src/beam_bool.erl | 765 ---------------------------------- lib/compiler/src/beam_jump.erl | 32 +- lib/compiler/src/beam_utils.erl | 16 +- lib/compiler/src/compile.erl | 3 - lib/compiler/src/compiler.app.src | 1 - lib/compiler/test/Makefile | 3 - lib/compiler/test/beam_bool_SUITE.erl | 197 --------- lib/compiler/test/compile_SUITE.erl | 1 - lib/compiler/test/guard_SUITE.erl | 153 ++++++- lib/compiler/test/misc_SUITE.erl | 8 - 11 files changed, 153 insertions(+), 1027 deletions(-) delete mode 100644 lib/compiler/src/beam_bool.erl delete mode 100644 lib/compiler/test/beam_bool_SUITE.erl (limited to 'lib') diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index b5ca6c3c49..c37f731d8c 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -49,7 +49,6 @@ MODULES = \ beam_a \ beam_asm \ beam_block \ - beam_bool \ beam_bs \ beam_bsm \ beam_clean \ diff --git a/lib/compiler/src/beam_bool.erl b/lib/compiler/src/beam_bool.erl deleted file mode 100644 index 99e4ccb1e9..0000000000 --- a/lib/compiler/src/beam_bool.erl +++ /dev/null @@ -1,765 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% -%% Purpose: Optimizes booleans in guards. - --module(beam_bool). - --export([module/2]). - --import(lists, [reverse/1,reverse/2,foldl/3,mapfoldl/3,map/2]). - --record(st, - {next, %Next label number. - ll %Live regs at labels. - }). - -module({Mod,Exp,Attr,Fs0,Lc}, _Opts) -> - %%io:format("~p:\n", [Mod]), - {Fs,_} = mapfoldl(fun(Fn, Lbl) -> function(Fn, Lbl) end, 100000000, Fs0), - {ok,{Mod,Exp,Attr,Fs,Lc}}. - -function({function,Name,Arity,CLabel,Is0}, Lbl0) -> - try - {Is,#st{next=Lbl}} = bool_opt(Is0, Lbl0), - {{function,Name,Arity,CLabel,Is},Lbl} - catch - Class:Error -> - Stack = erlang:get_stacktrace(), - io:fwrite("Function: ~w/~w\n", [Name,Arity]), - erlang:raise(Class, Error, Stack) - end. - -%% -%% Optimize boolean expressions that use guard bifs. Rewrite to -%% use test instructions if possible. -%% - -bool_opt(Asm, Lbl) -> - LiveInfo = beam_utils:index_labels(Asm), - bopt(Asm, [], #st{next=Lbl,ll=LiveInfo}). - -bopt([{block,Bl0}=Block| - [{jump,{f,Succ}}, - {label,Fail}, - {block,[{set,[Dst],[{atom,false}],move}]}, - {label,Succ}|Is]=Is0], Acc0, St) -> - case split_block(Bl0, Dst, Fail, Acc0, true) of - failed -> - bopt(Is0, [Block|Acc0], St); - {Bl,PreBlock} -> - Acc1 = case PreBlock of - [] -> Acc0; - _ -> [{block,PreBlock}|Acc0] - end, - Acc = [{protected,[Dst],Bl,{Fail,Succ}}|Acc1], - bopt(Is, Acc, St) - end; -bopt([{test,is_eq_exact,{f,Fail},[Reg,{atom,true}]}=I|Is], [{block,_}|_]=Acc0, St0) -> - case bopt_block(Reg, Fail, Is, Acc0, St0) of - failed -> bopt(Is, [I|Acc0], St0); - {Acc,St} -> bopt(Is, Acc, St) - end; -bopt([I|Is], Acc, St) -> - bopt(Is, [I|Acc], St); -bopt([], Acc, St) -> - {bopt_reverse(Acc, []),St}. - -bopt_reverse([{protected,[Dst],Block,{Fail,Succ}}|Is], Acc0) -> - Acc = [{block,Block},{jump,{f,Succ}}, - {label,Fail}, - {block,[{set,[Dst],[{atom,false}],move}]}, - {label,Succ}|Acc0], - bopt_reverse(Is, Acc); -bopt_reverse([I|Is], Acc) -> - bopt_reverse(Is, [I|Acc]); -bopt_reverse([], Acc) -> Acc. - -%% bopt_block(Reg, Fail, OldIs, Accumulator, St) -> failed | {NewAcc,St} -%% Attempt to optimized a block of guard BIFs followed by a test -%% instruction. -bopt_block(Reg, Fail, OldIs, [{block,Bl0}|Acc0], St0) -> - case split_block(Bl0, Reg, Fail, Acc0, false) of - failed -> - %% Reason for failure: The block either contained no - %% guard BIFs with the failure label Fail, or the final - %% instruction in the block did not assign the Reg register. - - %%io:format("split ~p: ~P\n", [Reg,Bl0,20]), - failed; - {Bl1,BlPre} -> - %% The block has been splitted. Bl1 is a non-empty list - %% of guard BIF instructions having the failure label Fail. - %% BlPre is a (possibly empty list) of instructions preceeding - %% Bl1. - Acc1 = make_block(BlPre, Acc0), - {Bl,Acc} = extend_block(Bl1, Fail, Acc1), - try - {NewCode,St} = bopt_tree_cg(Bl, Fail, St0), - ensure_opt_safe(Bl, NewCode, OldIs, Fail, Acc, St), - {NewCode++Acc,St} - catch - %% Not possible to rewrite because a boolean value is - %% passed to another guard bif, e.g. 'abs(A > B)' - %% (in this case, obviously nonsense code). Rare in - %% practice. - throw:mixed -> - failed; - - %% There was a reference to a boolean expression - %% from inside a protected block (try/catch), to - %% a boolean expression outside. - throw:protected_barrier -> - failed; - - %% The 'xor' operator was used. We currently don't - %% find it worthwile to translate 'xor' operators - %% (the code would be clumsy). - throw:'xor' -> - failed; - - %% The block does not contain a boolean expression, - %% but only a call to a guard BIF. - %% For instance: ... when element(1, T) -> - throw:not_boolean_expr -> - failed; - - %% The optimization is not safe. (A register - %% used by the instructions following the - %% optimized code is either not assigned a - %% value at all or assigned a different value.) - throw:all_registers_not_killed -> - failed; - throw:registers_used -> - failed; - - %% A protected block refered to the value - %% returned by another protected block, - %% probably because the Core Erlang code - %% used nested try/catches in the guard. - %% (v3_core never produces nested try/catches - %% in guards, so it must have been another - %% Core Erlang translator.) - throw:protected_violation -> - failed; - - %% Failed to work out the live registers for a GC - %% BIF. For example, if the number of live registers - %% needed to be 4 because {x,3} was a source register, - %% but {x,2} was not known to be initialized, this - %% exception would be thrown. - throw:gc_bif_alloc_failure -> - failed - - end - end. - -%% ensure_opt_safe(OriginalCode, OptCode, FollowingCode, Fail, -%% ReversedPrecedingCode, State) -> ok -%% Comparing the original code to the optimized code, determine -%% whether the optimized code is guaranteed to work in the same -%% way as the original code. -%% -%% Throw an exception if the optimization is not safe. -%% -ensure_opt_safe(Bl, NewCode, OldIs, Fail, PrecedingCode, St) -> - %% Here are the conditions that must be true for the - %% optimization to be safe. - %% - %% 1. If a register is INITIALIZED by PrecedingCode, - %% then if that register assigned a value in the original - %% code, but not in the optimized code, it must be UNUSED or KILLED - %% in the code that follows. - %% - %% 2. If a register is not known to be INITIALIZED by PreccedingCode, - %% then if that register assigned a value in the original - %% code, but not in the optimized code, it must be KILLED - %% by the code that follows. - %% - %% 3. Any register that is assigned a value in the optimized - %% code must be UNUSED or KILLED in the following code, - %% unless we can be sure that it is always assigned the same - %% value. - - InitInPreceding = initialized_regs(PrecedingCode), - - PrevDst = dst_regs(Bl), - NewDst = dst_regs(NewCode), - NotSet = ordsets:subtract(PrevDst, NewDst), - MustBeKilled = ordsets:subtract(NotSet, InitInPreceding), - - case all_killed(MustBeKilled, OldIs, Fail, St) of - false -> throw(all_registers_not_killed); - true -> ok - end, - MustBeUnused = ordsets:subtract(ordsets:union(NotSet, NewDst), - MustBeKilled), - case none_used(MustBeUnused, OldIs, Fail, St) of - false -> throw(registers_used); - true -> ok - end, - ok. - -update_fail_label([{set,Ds,As,{bif,N,{f,_}}}|Is], Fail, Acc) -> - update_fail_label(Is, Fail, [{set,Ds,As,{bif,N,{f,Fail}}}|Acc]); -update_fail_label([{set,Ds,As,{alloc,Regs,{gc_bif,N,{f,_}}}}|Is], Fail, Acc) -> - update_fail_label(Is, Fail, - [{set,Ds,As,{alloc,Regs,{gc_bif,N,{f,Fail}}}}|Acc]); -update_fail_label([], _, Acc) -> reverse(Acc). - -make_block(Bl) -> - make_block(Bl, []). - -make_block([], Acc) -> Acc; -make_block(Bl, Acc) -> [{block,Bl}|Acc]. - -extend_block(BlAcc, Fail, [{protected,_,_,_}=Prot|OldAcc]) -> - extend_block([Prot|BlAcc], Fail, OldAcc); -extend_block(BlAcc0, Fail, [{block,Is0}|OldAcc]) -> - case extend_block_1(reverse(Is0), Fail, BlAcc0) of - {BlAcc,[]} -> extend_block(BlAcc, Fail, OldAcc); - {BlAcc,Is} -> {BlAcc,[{block,Is}|OldAcc]} - end; -extend_block(BlAcc, _, OldAcc) -> {BlAcc,OldAcc}. - -extend_block_1([{set,[{x,_}],_,{bif,_,{f,Fail}}}=I|Is], Fail, Acc) -> - extend_block_1(Is, Fail, [I|Acc]); -extend_block_1([{set,[{x,_}],As,{bif,Bif,_}}=I|Is]=Is0, Fail, Acc) -> - case safe_bool_op(Bif, length(As)) of - false -> {Acc,reverse(Is0)}; - true -> extend_block_1(Is, Fail, [I|Acc]) - end; -extend_block_1([_|_]=Is, _, Acc) -> {Acc,reverse(Is)}; -extend_block_1([], _, Acc) -> {Acc,[]}. - -%% split_block([Instruction], Destination, FailLabel, [PreInstruction], -%% ProhibitFailLabelInPreBlock) -> failed | {Block,PreBlock} -%% Split a sequence of instructions into two blocks - one containing -%% all guard bif instructions and a pre-block all instructions before -%% the guard BIFs. - -split_block(Is0, Dst, Fail, PreIs, ProhibitFailLabel) -> - case ProhibitFailLabel andalso beam_jump:is_label_used_in(Fail, PreIs) of - true -> - %% The failure label was used in one of the instructions (most - %% probably bit syntax construction) preceeding the block, - %% the caller might eliminate the label. - failed; - false -> - case reverse(Is0) of - [{set,[Dst],_,_}|_]=Is -> - split_block_1(Is, Fail, ProhibitFailLabel); - _ -> failed - end - end. - -split_block_1(Is, Fail, ProhibitFailLabel) -> - case split_block_2(Is, Fail, []) of - {[],_} -> failed; - {_,PreBlock}=Res -> - case ProhibitFailLabel andalso - split_block_label_used(PreBlock, Fail) of - true -> - %% The failure label was used in the pre-block; - %% not allowed, because the label may be removed. - failed; - false -> - Res - end - end. - -split_block_2([{set,[_],_,{bif,_,{f,Fail}}}=I|Is], Fail, Acc) -> - split_block_2(Is, Fail, [I|Acc]); -split_block_2([{set,[_],_,{alloc,_,{gc_bif,_,{f,Fail}}}}=I|Is], Fail, Acc) -> - split_block_2(Is, Fail, [I|Acc]); -split_block_2(Is0, _, Acc) -> - Is = reverse(Is0), - {Acc,Is}. - -split_block_label_used([{set,[_],_,{bif,_,{f,Fail}}}|_], Fail) -> - true; -split_block_label_used([{set,[_],_,{alloc,_,{gc_bif,_,{f,Fail}}}}|_], Fail) -> - true; -split_block_label_used([{set,[_],_,{alloc,_,{put_map,_,{f,Fail}}}}|_], Fail) -> - true; -split_block_label_used([_|Is], Fail) -> - split_block_label_used(Is, Fail); -split_block_label_used([], _) -> false. - -dst_regs(Is) -> - dst_regs(Is, []). - -dst_regs([{block,Bl}|Is], Acc) -> - dst_regs(Bl, dst_regs(Is, Acc)); -dst_regs([{set,[D],_,{bif,_,{f,_}}}|Is], Acc) -> - dst_regs(Is, [D|Acc]); -dst_regs([{set,[D],_,{alloc,_,{gc_bif,_,{f,_}}}}|Is], Acc) -> - dst_regs(Is, [D|Acc]); -dst_regs([{protected,_,Bl,_}|Is], Acc) -> - dst_regs(Bl, dst_regs(Is, Acc)); -dst_regs([_|Is], Acc) -> - dst_regs(Is, Acc); -dst_regs([], Acc) -> ordsets:from_list(Acc). - -all_killed([R|Rs], OldIs, Fail, St) -> - case is_killed(R, OldIs, Fail, St) of - false -> false; - true -> all_killed(Rs, OldIs, Fail, St) - end; -all_killed([], _, _, _) -> true. - -none_used([R|Rs], OldIs, Fail, St) -> - case is_not_used(R, OldIs, Fail, St) of - false -> false; - true -> none_used(Rs, OldIs, Fail, St) - end; -none_used([], _, _, _) -> true. - -bopt_tree_cg(Block0, Fail, St) -> - Free = free_variables(Block0), - Block = ssa_block(Block0), -%% io:format("~p\n", [Block0]), -%% io:format("~p\n", [Block]), -%% io:format("~p\n", [gb_trees:to_list(Free)]), - case bopt_tree(Block, Free, []) of - {Pre0,[{_,Tree}]} -> - Pre1 = update_fail_label(Pre0, Fail, []), - Regs0 = init_regs(gb_trees:keys(Free)), -%% io:format("~p\n", [dst_regs(Block0)]), -%% io:format("~p\n", [Pre1]), -%% io:format("~p\n", [Tree]), -%% io:nl(), - {Pre,Regs} = rename_regs(Pre1, Regs0), -%% io:format("~p\n", [Regs0]), -%% io:format("~p\n", [Pre]), - bopt_cg(Tree, Fail, Regs, make_block(Pre), St); - _Res -> - throw(not_boolean_expr) - end. - -bopt_tree([{set,[Dst],As0,{bif,'not',_}}|Is], Forest0, Pre) -> - {[Arg],Forest1} = bopt_bool_args(As0, Forest0), - Forest = gb_trees:enter(Dst, {'not',Arg}, Forest1), - bopt_tree(Is, Forest, Pre); -bopt_tree([{set,[Dst],As0,{bif,'and',_}}|Is], Forest0, Pre) -> - {As,Forest1} = bopt_bool_args(As0, Forest0), - Node = make_and_node(As), - Forest = gb_trees:enter(Dst, Node, Forest1), - bopt_tree(Is, Forest, Pre); -bopt_tree([{set,[Dst],As0,{bif,'or',_}}|Is], Forest0, Pre) -> - {As,Forest1} = bopt_bool_args(As0, Forest0), - Node = make_or_node(As), - Forest = gb_trees:enter(Dst, Node, Forest1), - bopt_tree(Is, Forest, Pre); -bopt_tree([{set,_,_,{bif,'xor',_}}|_], _, _) -> - throw('xor'); -bopt_tree([{protected,[Dst],Code,_}|Is], Forest0, Pre) -> - ProtForest0 = gb_trees:from_orddict([P || {_,any}=P <- gb_trees:to_list(Forest0)]), - case bopt_tree(Code, ProtForest0, []) of - {ProtPre,[{_,ProtTree}]} -> - Prot = {prot,ProtPre,ProtTree}, - Forest = gb_trees:enter(Dst, Prot, Forest0), - bopt_tree(Is, Forest, Pre); - _Res -> - throw(not_boolean_expr) - end; -bopt_tree([{set,[Dst],As,{bif,N,_}}=Bif|Is], Forest0, Pre) -> - Ar = length(As), - case safe_bool_op(N, Ar) of - false -> - bopt_good_args(As, Forest0), - Forest = gb_trees:enter(Dst, any, Forest0), - bopt_tree(Is, Forest, [Bif|Pre]); - true -> - bopt_good_args(As, Forest0), - Test = bif_to_test(Dst, N, As), - Forest = gb_trees:enter(Dst, Test, Forest0), - bopt_tree(Is, Forest, Pre) - end; -bopt_tree([{set,[Dst],As,{alloc,_,{gc_bif,_,_}}}=Bif|Is], Forest0, Pre) -> - bopt_good_args(As, Forest0), - Forest = gb_trees:enter(Dst, any, Forest0), - bopt_tree(Is, Forest, [Bif|Pre]); -bopt_tree([], Forest, Pre) -> - {reverse(Pre),[R || {_,V}=R <- gb_trees:to_list(Forest), V =/= any]}. - -safe_bool_op(N, Ar) -> - erl_internal:new_type_test(N, Ar) orelse erl_internal:comp_op(N, Ar). - -bopt_bool_args([V0,V0], Forest0) -> - {V,Forest} = bopt_bool_arg(V0, Forest0), - {[V,V],Forest}; -bopt_bool_args(As, Forest) -> - mapfoldl(fun bopt_bool_arg/2, Forest, As). - -bopt_bool_arg({T,_}=R, Forest) when T =:= x; T =:= y; T =:= tmp -> - Val = case gb_trees:lookup(R, Forest) of - {value,any} -> {test,is_eq_exact,fail,[R,{atom,true}]}; - {value,Val0} -> Val0; - none -> throw(mixed) - end, - {Val,gb_trees:delete(R, Forest)}; -bopt_bool_arg(Term, Forest) -> - {Term,Forest}. - -bopt_good_args([A|As], Regs) -> - bopt_good_arg(A, Regs), - bopt_good_args(As, Regs); -bopt_good_args([], _) -> ok. - -bopt_good_arg({Tag,_}=X, Regs) when Tag =:= x; Tag =:= tmp -> - case gb_trees:lookup(X, Regs) of - {value,any} -> ok; - {value,_} -> throw(mixed); - none -> throw(protected_barrier) - end; -bopt_good_arg(_, _) -> ok. - -bif_to_test(_, N, As) -> - beam_utils:bif_to_test(N, As, fail). - -make_and_node(Is) -> - AndList0 = make_and_list(Is), - case simplify_and_list(AndList0) of - [] -> {atom,true}; - [Op] -> Op; - AndList -> {'and',AndList} - end. - -make_and_list([{'and',As}|Is]) -> - make_and_list(As++Is); -make_and_list([I|Is]) -> - [I|make_and_list(Is)]; -make_and_list([]) -> []. - -simplify_and_list([{atom,true}|T]) -> - simplify_and_list(T); -simplify_and_list([{atom,false}=False|_]) -> - [False]; -simplify_and_list([H|T]) -> - [H|simplify_and_list(T)]; -simplify_and_list([]) -> []. - -make_or_node(Is) -> - OrList0 = make_or_list(Is), - case simplify_or_list(OrList0) of - [] -> {atom,false}; - [Op] -> Op; - OrList -> {'or',OrList} - end. - -make_or_list([{'or',As}|Is]) -> - make_or_list(As++Is); -make_or_list([I|Is]) -> - [I|make_or_list(Is)]; -make_or_list([]) -> []. - -simplify_or_list([{atom,false}|T]) -> - simplify_or_list(T); -simplify_or_list([{atom,true}=True|_]) -> - [True]; -simplify_or_list([H|T]) -> - [H|simplify_or_list(T)]; -simplify_or_list([]) -> []. - -%% Code generation for a boolean tree. - -bopt_cg({'not',Arg}, Fail, Rs, Acc, St) -> - I = bopt_cg_not(Arg), - bopt_cg(I, Fail, Rs, Acc, St); -bopt_cg({'and',As}, Fail, Rs, Acc, St) -> - bopt_cg_and(As, Fail, Rs, Acc, St); -bopt_cg({'or',As}, Fail, Rs, Acc, St0) -> - {Succ,St} = new_label(St0), - bopt_cg_or(As, Succ, Fail, Rs, Acc, St); -bopt_cg({test,N,fail,As0}, Fail, Rs, Acc, St) -> - As = rename_sources(As0, Rs), - Test = {test,N,{f,Fail},As}, - {[Test|Acc],St}; -bopt_cg({inverted_test,N,fail,As0}, Fail, Rs, Acc, St0) -> - As = rename_sources(As0, Rs), - {Lbl,St} = new_label(St0), - {[{label,Lbl},{jump,{f,Fail}},{test,N,{f,Lbl},As}|Acc],St}; -bopt_cg({prot,Pre0,Tree}, Fail, Rs0, Acc, St0) -> - Pre1 = update_fail_label(Pre0, Fail, []), - {Pre,Rs} = rename_regs(Pre1, Rs0), - bopt_cg(Tree, Fail, Rs, make_block(Pre, Acc), St0); -bopt_cg({atom,true}, _Fail, _Rs, Acc, St) -> - {Acc,St}; -bopt_cg({atom,false}, Fail, _Rs, Acc, St) -> - {[{jump,{f,Fail}}|Acc],St}; -bopt_cg(_, _, _, _, _) -> - throw(not_boolean_expr). - -bopt_cg_not({'and',As0}) -> - As = [bopt_cg_not(A) || A <- As0], - {'or',As}; -bopt_cg_not({'or',As0}) -> - As = [bopt_cg_not(A) || A <- As0], - {'and',As}; -bopt_cg_not({'not',Arg}) -> - bopt_cg_not_not(Arg); -bopt_cg_not({test,Test,Fail,As}) -> - {inverted_test,Test,Fail,As}; -bopt_cg_not({atom,Bool}) when is_boolean(Bool) -> - {atom,not Bool}; -bopt_cg_not(_) -> - throw(not_boolean_expr). - -bopt_cg_not_not({'and',As}) -> - {'and',[bopt_cg_not_not(A) || A <- As]}; -bopt_cg_not_not({'or',As}) -> - {'or',[bopt_cg_not_not(A) || A <- As]}; -bopt_cg_not_not({'not',Arg}) -> - bopt_cg_not(Arg); -bopt_cg_not_not(Leaf) -> Leaf. - -bopt_cg_and([I|Is], Fail, Rs, Acc0, St0) -> - {Acc,St} = bopt_cg(I, Fail, Rs, Acc0, St0), - bopt_cg_and(Is, Fail, Rs, Acc, St); -bopt_cg_and([], _, _, Acc, St) -> {Acc,St}. - -bopt_cg_or([I], Succ, Fail, Rs, Acc0, St0) -> - {Acc,St} = bopt_cg(I, Fail, Rs, Acc0, St0), - {[{label,Succ}|Acc],St}; -bopt_cg_or([I|Is], Succ, Fail, Rs, Acc0, St0) -> - {Lbl,St1} = new_label(St0), - {Acc,St} = bopt_cg(I, Lbl, Rs, Acc0, St1), - bopt_cg_or(Is, Succ, Fail, Rs, [{label,Lbl},{jump,{f,Succ}}|Acc], St). - -new_label(#st{next=LabelNum}=St) when is_integer(LabelNum) -> - {LabelNum,St#st{next=LabelNum+1}}. - -free_variables(Is) -> - E = gb_sets:empty(), - free_vars_1(Is, E, E, E). - -free_vars_1([{set,Ds,As,{bif,_,_}}|Is], F0, N0, A) -> - F = gb_sets:union(F0, gb_sets:difference(var_list(As), N0)), - N = gb_sets:union(N0, var_list(Ds)), - free_vars_1(Is, F, N, A); -free_vars_1([{set,Ds,As,{alloc,Regs,{gc_bif,_,_}}}|Is], F0, N0, A0) -> - A = gb_sets:union(A0, gb_sets:from_list(free_vars_regs(Regs))), - F = gb_sets:union(F0, gb_sets:difference(var_list(As), N0)), - N = gb_sets:union(N0, var_list(Ds)), - free_vars_1(Is, F, N, A); -free_vars_1([{protected,_,Pa,_}|Is], F, N, A) -> - free_vars_1(Pa++Is, F, N, A); -free_vars_1([], F0, N, A) -> - F = case gb_sets:is_empty(A) of - true -> - %% No GC BIFs. - {x,X} = gb_sets:smallest(N), - P = ordsets:from_list(free_vars_regs(X)), - ordsets:union(gb_sets:to_list(F0), P); - false -> - %% At least one GC BIF. - gb_sets:to_list(gb_sets:union(F0, gb_sets:difference(A, N))) - end, - gb_trees:from_orddict([{K,any} || K <- F]). - -var_list(Is) -> - var_list_1(Is, gb_sets:empty()). - -var_list_1([{Tag,_}=X|Is], D) when Tag =:= x; Tag =:= y -> - var_list_1(Is, gb_sets:add(X, D)); -var_list_1([_|Is], D) -> - var_list_1(Is, D); -var_list_1([], D) -> D. - -free_vars_regs(0) -> []; -free_vars_regs(X) -> [{x,X-1}|free_vars_regs(X-1)]. - -rename_regs(Is, Regs) -> - rename_regs(Is, Regs, []). - -rename_regs([{set,[Dst0],Ss0,{alloc,_,Info}}|Is], Regs0, Acc) -> - Live = live_regs(Regs0), - Ss = rename_sources(Ss0, Regs0), - Regs = put_reg(Dst0, Regs0), - Dst = fetch_reg(Dst0, Regs), - rename_regs(Is, Regs, [{set,[Dst],Ss,{alloc,Live,Info}}|Acc]); -rename_regs([{set,[Dst0],Ss0,Info}|Is], Regs0, Acc) -> - Ss = rename_sources(Ss0, Regs0), - Regs = put_reg(Dst0, Regs0), - Dst = fetch_reg(Dst0, Regs), - rename_regs(Is, Regs, [{set,[Dst],Ss,Info}|Acc]); -rename_regs([], Regs, Acc) -> {reverse(Acc),Regs}. - -rename_sources(Ss, Regs) -> - map(fun({x,_}=R) -> fetch_reg(R, Regs); - ({tmp,_}=R) -> fetch_reg(R, Regs); - (E) -> E - end, Ss). - -%%% -%%% Keeping track of register assignments. -%%% - -init_regs(Free) -> - init_regs_1(Free, 0). - -init_regs_1([{x,I}=V|T], I) -> - [{I,V}|init_regs_1(T, I+1)]; -init_regs_1([{x,X}|_]=T, I) when I < X -> - [{I,reserved}|init_regs_1(T, I+1)]; -init_regs_1([{y,_}|_], _) -> []; -init_regs_1([], _) -> []. - -put_reg(V, Rs) -> put_reg_1(V, Rs, 0). - -put_reg_1(V, [R|Rs], I) -> [R|put_reg_1(V, Rs, I+1)]; -put_reg_1(V, [], I) -> [{I,V}]. - -fetch_reg(V, [{I,V}|_]) -> {x,I}; -fetch_reg(V, [_|SRs]) -> fetch_reg(V, SRs). - -live_regs([{_,reserved}|_]) -> - %% We are not sure that this register is initialized, so we must - %% abort the optimization. - throw(gc_bif_alloc_failure); -live_regs([{I,_}]) -> - I+1; -live_regs([{_,_}|Regs]) -> - live_regs(Regs); -live_regs([]) -> - 0. - - -%%% -%%% Convert a block to Static Single Assignment (SSA) form. -%%% - --record(ssa, - {live=0, %Variable counter. - sub=gb_trees:empty(), %Substitution table. - prot=gb_sets:empty(), %Targets assigned by protecteds. - in_prot=false %Inside a protected. - }). - -ssa_block(Is0) -> - {Is,_} = ssa_block_1(Is0, #ssa{}, []), - Is. - -ssa_block_1([{protected,[_],Pa0,Pb}|Is], Sub0, Acc) -> - {Pa,Sub1} = ssa_block_1(Pa0, Sub0#ssa{in_prot=true}, []), - Dst = ssa_last_target(Pa), - Sub = Sub1#ssa{prot=gb_sets:insert(Dst, Sub1#ssa.prot), - in_prot=Sub0#ssa.in_prot}, - ssa_block_1(Is, Sub, [{protected,[Dst],Pa,Pb}|Acc]); -ssa_block_1([{set,[Dst],As,Bif}|Is], Sub0, Acc0) -> - Sub1 = ssa_in_use_list(As, Sub0), - Sub = ssa_assign(Dst, Sub1), - Acc = [{set,[ssa_sub(Dst, Sub)],ssa_sub_list(As, Sub0),Bif}|Acc0], - ssa_block_1(Is, Sub, Acc); -ssa_block_1([], Sub, Acc) -> {reverse(Acc),Sub}. - -ssa_in_use_list(As, Sub) -> - foldl(fun ssa_in_use/2, Sub, As). - -ssa_in_use({x,_}=R, #ssa{sub=Sub0}=Ssa) -> - case gb_trees:is_defined(R, Sub0) of - true -> Ssa; - false -> - Sub = gb_trees:insert(R, R, Sub0), - Ssa#ssa{sub=Sub} - end; -ssa_in_use(_, Ssa) -> Ssa. - -ssa_assign({x,_}=R, #ssa{sub=Sub0}=Ssa0) -> - {NewReg,Ssa} = ssa_new_reg(Ssa0), - case gb_trees:is_defined(R, Sub0) of - false -> - Sub = gb_trees:insert(R, NewReg, Sub0), - Ssa#ssa{sub=Sub}; - true -> - Sub1 = gb_trees:update(R, NewReg, Sub0), - Sub = gb_trees:insert(NewReg, NewReg, Sub1), - Ssa#ssa{sub=Sub} - end. - -ssa_sub_list(List, Sub) -> - [ssa_sub(E, Sub) || E <- List]. - -ssa_sub(R0, #ssa{sub=Sub,prot=Prot,in_prot=InProt}) -> - case gb_trees:lookup(R0, Sub) of - none -> R0; - {value,R} -> - case InProt andalso gb_sets:is_element(R, Prot) of - true -> - throw(protected_violation); - false -> - R - end - end. - -ssa_new_reg(#ssa{live=Reg}=Ssa) -> - {{tmp,Reg},Ssa#ssa{live=Reg+1}}. - -ssa_last_target([{set,[Dst],_,_}]) -> Dst; -ssa_last_target([_|Is]) -> ssa_last_target(Is). - -%% is_killed(Register, [Instruction], FailLabel, State) -> true|false -%% Determine whether a register is killed in the instruction sequence. -%% The state is used to allow us to determine the kill state -%% across branches. - -is_killed(R, Is, Label, #st{ll=Ll}) -> - beam_utils:is_killed(R, Is, Ll) andalso - beam_utils:is_killed_at(R, Label, Ll). - -%% is_not_used(Register, [Instruction], FailLabel, State) -> true|false -%% Determine whether a register is never used in the instruction sequence -%% (it could still referenced by an allocate instruction, meaning that -%% it MUST be initialized). -%% The state is used to allow us to determine the usage state -%% across branches. - -is_not_used(R, Is, Label, #st{ll=Ll}) -> - beam_utils:is_not_used(R, Is, Ll) andalso - beam_utils:is_not_used_at(R, Label, Ll). - -%% initialized_regs([Instruction]) -> [Register]) -%% Given a REVERSED instruction sequence, return a list of the registers -%% that are guaranteed to be initialized (not contain garbage). - -initialized_regs(Is) -> - initialized_regs(Is, ordsets:new()). - -initialized_regs([{set,Dst,_Src,{alloc,Live,_}}|_], Regs0) -> - Regs = add_init_regs(free_vars_regs(Live), Regs0), - add_init_regs(Dst, Regs); -initialized_regs([{set,Dst,Src,_}|Is], Regs) -> - initialized_regs(Is, add_init_regs(Dst, add_init_regs(Src, Regs))); -initialized_regs([{test,_,_,Src}|Is], Regs) -> - initialized_regs(Is, add_init_regs(Src, Regs)); -initialized_regs([{block,Bl}|Is], Regs) -> - initialized_regs(reverse(Bl, Is), Regs); -initialized_regs([{bs_context_to_binary,Src}|Is], Regs) -> - initialized_regs(Is, add_init_regs([Src], Regs)); -initialized_regs([{label,_},{func_info,_,_,Arity}|_], Regs) -> - InitRegs = free_vars_regs(Arity), - add_init_regs(InitRegs, Regs); -initialized_regs([_|_], Regs) -> Regs. - -add_init_regs([{x,_}=X|T], Regs) -> - add_init_regs(T, ordsets:add_element(X, Regs)); -add_init_regs([_|T], Regs) -> - add_init_regs(T, Regs); -add_init_regs([], Regs) -> Regs. diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl index 5311ce7379..e096270d8c 100644 --- a/lib/compiler/src/beam_jump.erl +++ b/lib/compiler/src/beam_jump.erl @@ -23,7 +23,7 @@ -export([module/2, is_unreachable_after/1,is_exit_instruction/1, - remove_unused_labels/1,is_label_used_in/2]). + remove_unused_labels/1]). %%% The following optimisations are done: %%% @@ -473,36 +473,6 @@ is_exit_instruction({try_case_end,_}) -> true; is_exit_instruction({badmatch,_}) -> true; is_exit_instruction(_) -> false. -%% is_label_used_in(LabelNumber, [Instruction]) -> boolean() -%% Check whether the label is used in the instruction sequence -%% (including inside blocks). - -is_label_used_in(Lbl, Is) -> - is_label_used_in_1(Is, Lbl, cerl_sets:new()). - -is_label_used_in_1([{block,Block}|Is], Lbl, Empty) -> - lists:any(fun(I) -> is_label_used_in_block(I, Lbl) end, Block) - orelse is_label_used_in_1(Is, Lbl, Empty); -is_label_used_in_1([I|Is], Lbl, Empty) -> - Used = ulbl(I, Empty), - cerl_sets:is_element(Lbl, Used) orelse is_label_used_in_1(Is, Lbl, Empty); -is_label_used_in_1([], _, _) -> false. - -is_label_used_in_block({set,_,_,Info}, Lbl) -> - case Info of - {bif,_,{f,F}} -> F =:= Lbl; - {alloc,_,{gc_bif,_,{f,F}}} -> F =:= Lbl; - {alloc,_,{put_map,_,{f,F}}} -> F =:= Lbl; - {get_map_elements,{f,F}} -> F =:= Lbl; - {try_catch,_,{f,F}} -> F =:= Lbl; - {alloc,_,_} -> false; - {put_tuple,_} -> false; - {get_tuple_element,_} -> false; - {set_tuple_element,_} -> false; - {line,_} -> false; - _ when is_atom(Info) -> false - end. - %% remove_unused_labels(Instructions0) -> Instructions %% Remove all unused labels. Also remove unreachable %% instructions following labels that are removed. diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index 564a62a7f2..74e3d7e38a 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -22,7 +22,7 @@ -module(beam_utils). -export([is_killed_block/2,is_killed/3,is_killed_at/3, - is_not_used/3,is_not_used_at/3, + is_not_used/3, empty_label_index/0,index_label/3,index_labels/1, code_at/2,bif_to_test/3,is_pure_test/1, live_opt/1,delete_live_annos/1,combine_heap_needs/2, @@ -96,20 +96,6 @@ is_not_used(R, Is, D) -> {_,_} -> true end. -%% is_not_used(Register, [Instruction], State) -> true|false -%% Determine whether a register is never used in the instruction sequence -%% (it could still be referenced by an allocate instruction, meaning that -%% it MUST be initialized, but that its value does not matter). -%% The state is used to allow us to determine the usage state -%% across branches. - -is_not_used_at(R, Lbl, D) -> - St = #live{lbl=D,res=gb_trees:empty()}, - case check_liveness_at(R, Lbl, St) of - {used,_} -> false; - {_,_} -> true - end. - %% index_labels(FunctionIs) -> State %% Index the instruction sequence so that we can quickly %% look up the instruction following a specific label. diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index e4fb703939..37da045d25 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -707,8 +707,6 @@ asm_passes() -> {iff,dexcept,{listing,"except"}}, {unless,no_bs_opt,{pass,beam_bs}}, {iff,dbs,{listing,"bs"}}, - {unless,no_bopt,{pass,beam_bool}}, - {iff,dbool,{listing,"bool"}}, {unless,no_topt,{pass,beam_type}}, {iff,dtype,{listing,"type"}}, {pass,beam_split}, @@ -1780,7 +1778,6 @@ pre_load() -> L = [beam_a, beam_asm, beam_block, - beam_bool, beam_bs, beam_bsm, beam_clean, diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src index 20195ac36f..3cb991687b 100644 --- a/lib/compiler/src/compiler.app.src +++ b/lib/compiler/src/compiler.app.src @@ -24,7 +24,6 @@ beam_a, beam_asm, beam_block, - beam_bool, beam_bs, beam_bsm, beam_clean, diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index de06e8760f..f2c68505fc 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -9,7 +9,6 @@ MODULES= \ andor_SUITE \ apply_SUITE \ beam_block_SUITE \ - beam_bool_SUITE \ beam_validator_SUITE \ beam_disasm_SUITE \ beam_except_SUITE \ @@ -49,7 +48,6 @@ NO_OPT= \ andor \ apply \ beam_block \ - beam_bool \ beam_except \ beam_jump \ beam_reorder \ @@ -76,7 +74,6 @@ INLINE= \ andor \ apply \ beam_block \ - beam_bool \ beam_utils \ bif \ bs_bincomp \ diff --git a/lib/compiler/test/beam_bool_SUITE.erl b/lib/compiler/test/beam_bool_SUITE.erl deleted file mode 100644 index e585eaedb5..0000000000 --- a/lib/compiler/test/beam_bool_SUITE.erl +++ /dev/null @@ -1,197 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2015-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% --module(beam_bool_SUITE). - --export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, - init_per_group/2,end_per_group/2, - before_and_inside_if/1, - scotland/1,y_registers/1,protected/1, - maps/1]). - -suite() -> - [{ct_hooks,[ts_install_cth]}]. - -all() -> - test_lib:recompile(?MODULE), - [{group,p}]. - -groups() -> - [{p,[parallel], - [before_and_inside_if, - scotland, - y_registers, - protected, - maps - ]}]. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - -before_and_inside_if(_Config) -> - no = before_and_inside_if([a], [b], delete), - no = before_and_inside_if([a], [b], x), - no = before_and_inside_if([a], [], delete), - no = before_and_inside_if([a], [], x), - no = before_and_inside_if([], [], delete), - yes = before_and_inside_if([], [], x), - yes = before_and_inside_if([], [b], delete), - yes = before_and_inside_if([], [b], x), - - {ch1,ch2} = before_and_inside_if_2([a], [b], blah), - {ch1,ch2} = before_and_inside_if_2([a], [b], xx), - {ch1,ch2} = before_and_inside_if_2([a], [], blah), - {ch1,ch2} = before_and_inside_if_2([a], [], xx), - {no,no} = before_and_inside_if_2([], [b], blah), - {no,no} = before_and_inside_if_2([], [b], xx), - {ch1,no} = before_and_inside_if_2([], [], blah), - {no,ch2} = before_and_inside_if_2([], [], xx), - ok. - -%% Thanks to Simon Cornish and Kostis Sagonas. -%% Used to crash beam_bool. -before_and_inside_if(XDo1, XDo2, Do3) -> - Do1 = (XDo1 =/= []), - Do2 = (XDo2 =/= []), - if - %% This expression occurs in a try/catch (protected) - %% block, which cannot refer to variables outside of - %% the block that are boolean expressions. - Do1 =:= true; - Do1 =:= false, Do2 =:= false, Do3 =:= delete -> - no; - true -> - yes - end. - -%% Thanks to Simon Cornish. -%% Used to generate code that would not set {y,0} on -%% all paths before its use (and therefore fail -%% validation by the beam_validator). -before_and_inside_if_2(XDo1, XDo2, Do3) -> - Do1 = (XDo1 =/= []), - Do2 = (XDo2 =/= []), - CH1 = if Do1 == true; - Do1 == false,Do2==false,Do3 == blah -> - ch1; - true -> - no - end, - CH2 = if Do1 == true; - Do1 == false,Do2==false,Do3 == xx -> - ch2; - true -> - no - end, - {CH1,CH2}. - - -%% beam_bool would remove the initialization of {y,0}. -%% (Thanks to Thomas Arts and QuickCheck.) - -scotland(_Config) -> - million = do_scotland(placed), - {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(false)), - {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(true)), - {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(echo)), - ok. - -do_scotland(Echo) -> - found(case Echo of - Echo when true; Echo, Echo, Echo -> - Echo; - echo -> - [] - end, - Echo = placed). - -found(_, _) -> million. - - -%% ERL-143: beam_bool could not handle Y registers as a destination. -y_registers(_Config) -> - {'EXIT',{badarith,[_|_]}} = (catch baker(valentine)), - {'EXIT',{badarith,[_|_]}} = (catch baker(clementine)), - - {not_ok,true} = potter([]), - {ok,false} = potter([{encoding,any}]), - - ok. - -%% Thanks to Quickcheck. -baker(Baker) -> - (valentine == Baker) + - case Baker of - Baker when Baker; Baker -> - Baker; - Baker -> - [] - end. - -%% Thanks to Jose Valim. -potter(Modes) -> - Raw = lists:keyfind(encoding, 1, Modes) == false, - Final = case Raw of - X when X == false; X == nil -> ok; - _ -> not_ok - end, - {Final,Raw}. - -protected(_Config) -> - {'EXIT',{if_clause,_}} = (catch photographs({1, surprise, true}, opinions)), - - {{true}} = welcome({perfect, true}), - {'EXIT',{if_clause,_}} = (catch welcome({perfect, false})), - ok. - -photographs({_Violation, surprise, Deep}, opinions) -> - {if - 0; "here", Deep -> - Deep = Deep - end}. - -welcome({perfect, Profit}) -> - if - Profit, Profit, Profit; 0 -> - {id({Profit})} - end. - -maps(_Config) -> - ok = evidence(#{0 => 42}). - -%% Cover handling of put_map in in split_block_label_used/2. -evidence(#{0 := Charge}) when 0; #{[] => Charge} == #{[] => 42} -> - ok. - - -%%% -%%% Common utilities. -%%% - -id(I) -> - I. diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 2953a901b5..d7e0b3498a 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -342,7 +342,6 @@ do_file_listings(DataDir, PrivDir, [File|Files]) -> do_listing(Simple, TargetDir, dblk, ".block"), do_listing(Simple, TargetDir, dexcept, ".except"), do_listing(Simple, TargetDir, dbs, ".bs"), - do_listing(Simple, TargetDir, dbool, ".bool"), do_listing(Simple, TargetDir, dtype, ".type"), do_listing(Simple, TargetDir, ddead, ".dead"), do_listing(Simple, TargetDir, djmp, ".jump"), diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl index 11d4038b06..a662d85272 100644 --- a/lib/compiler/test/guard_SUITE.erl +++ b/lib/compiler/test/guard_SUITE.erl @@ -35,7 +35,7 @@ basic_andalso_orelse/1,traverse_dcd/1, check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1, bad_constants/1,bad_guards/1, - guard_in_catch/1]). + guard_in_catch/1,beam_bool_SUITE/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -54,7 +54,7 @@ groups() -> rel_ops,rel_op_combinations, literal_type_tests,basic_andalso_orelse,traverse_dcd, check_qlc_hrl,andalso_semi,t_tuple_size,binary_part, - bad_constants,bad_guards,guard_in_catch]}]. + bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE]}]. init_per_suite(Config) -> Config. @@ -2050,6 +2050,155 @@ do_guard_in_catch_bin(From) -> saint end. +%%% +%%% The beam_bool pass has been eliminated. Here are the tests from +%%% beam_bool_SUITE. +%%% + +beam_bool_SUITE(_Config) -> + before_and_inside_if(), + scotland(), + y_registers(), + protected(), + maps(), + ok. + +before_and_inside_if() -> + no = before_and_inside_if([a], [b], delete), + no = before_and_inside_if([a], [b], x), + no = before_and_inside_if([a], [], delete), + no = before_and_inside_if([a], [], x), + no = before_and_inside_if([], [], delete), + yes = before_and_inside_if([], [], x), + yes = before_and_inside_if([], [b], delete), + yes = before_and_inside_if([], [b], x), + + {ch1,ch2} = before_and_inside_if_2([a], [b], blah), + {ch1,ch2} = before_and_inside_if_2([a], [b], xx), + {ch1,ch2} = before_and_inside_if_2([a], [], blah), + {ch1,ch2} = before_and_inside_if_2([a], [], xx), + {no,no} = before_and_inside_if_2([], [b], blah), + {no,no} = before_and_inside_if_2([], [b], xx), + {ch1,no} = before_and_inside_if_2([], [], blah), + {no,ch2} = before_and_inside_if_2([], [], xx), + ok. + +%% Thanks to Simon Cornish and Kostis Sagonas. +%% Used to crash beam_bool. +before_and_inside_if(XDo1, XDo2, Do3) -> + Do1 = (XDo1 =/= []), + Do2 = (XDo2 =/= []), + if + %% This expression occurs in a try/catch (protected) + %% block, which cannot refer to variables outside of + %% the block that are boolean expressions. + Do1 =:= true; + Do1 =:= false, Do2 =:= false, Do3 =:= delete -> + no; + true -> + yes + end. + +%% Thanks to Simon Cornish. +%% Used to generate code that would not set {y,0} on +%% all paths before its use (and therefore fail +%% validation by the beam_validator). +before_and_inside_if_2(XDo1, XDo2, Do3) -> + Do1 = (XDo1 =/= []), + Do2 = (XDo2 =/= []), + CH1 = if Do1 == true; + Do1 == false,Do2==false,Do3 == blah -> + ch1; + true -> + no + end, + CH2 = if Do1 == true; + Do1 == false,Do2==false,Do3 == xx -> + ch2; + true -> + no + end, + {CH1,CH2}. + + +%% beam_bool would remove the initialization of {y,0}. +%% (Thanks to Thomas Arts and QuickCheck.) + +scotland() -> + million = do_scotland(placed), + {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(false)), + {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(true)), + {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(echo)), + ok. + +do_scotland(Echo) -> + found(case Echo of + Echo when true; Echo, Echo, Echo -> + Echo; + echo -> + [] + end, + Echo = placed). + +found(_, _) -> million. + + +%% ERL-143: beam_bool could not handle Y registers as a destination. +y_registers() -> + {'EXIT',{badarith,[_|_]}} = (catch baker(valentine)), + {'EXIT',{badarith,[_|_]}} = (catch baker(clementine)), + + {not_ok,true} = potter([]), + {ok,false} = potter([{encoding,any}]), + + ok. + +%% Thanks to Quickcheck. +baker(Baker) -> + (valentine == Baker) + + case Baker of + Baker when Baker; Baker -> + Baker; + Baker -> + [] + end. + +%% Thanks to Jose Valim. +potter(Modes) -> + Raw = lists:keyfind(encoding, 1, Modes) == false, + Final = case Raw of + X when X == false; X == nil -> ok; + _ -> not_ok + end, + {Final,Raw}. + +protected() -> + {'EXIT',{if_clause,_}} = (catch photographs({1, surprise, true}, opinions)), + + {{true}} = welcome({perfect, true}), + {'EXIT',{if_clause,_}} = (catch welcome({perfect, false})), + ok. + +photographs({_Violation, surprise, Deep}, opinions) -> + {if + 0; "here", Deep -> + Deep = Deep + end}. + +welcome({perfect, Profit}) -> + if + Profit, Profit, Profit; 0 -> + {id({Profit})} + end. + +maps() -> + ok = evidence(#{0 => 42}). + +%% Cover handling of put_map in in split_block_label_used/2. +evidence(#{0 := Charge}) when 0; #{[] => Charge} == #{[] => 42} -> + ok. + + %% Call this function to turn off constant propagation. id(I) -> I. diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index f543f0d4de..621524114f 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -229,14 +229,6 @@ silly_coverage(Config) when is_list(Config) -> {label,2}|non_proper_list]}],99}, expect_error(fun() -> beam_except:module(ExceptInput, []) end), - %% beam_bool - BoolInput = {?MODULE,[{foo,0}],[], - [{function,foo,0,2, - [{label,1}, - {func_info,{atom,?MODULE},{atom,foo},0}, - {label,2}|non_proper_list]}],99}, - expect_error(fun() -> beam_bool:module(BoolInput, []) end), - %% beam_dead. This is tricky. Our function must look OK to %% beam_utils:clean_labels/1, but must crash beam_dead. DeadInput = {?MODULE,[{foo,0}],[], -- cgit v1.2.3 From 506f0982825f032b404425e777010459e974596f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 7 Oct 2016 12:46:50 +0200 Subject: Add test using LFE-generated Core Erlang modules Ensure that correct (not necessarily optimal) code is generated for Core Erlang code not originating from v3_core. --- lib/compiler/test/Makefile | 14 + lib/compiler/test/compile_SUITE.erl | 9 +- lib/compiler/test/lfe-core.patch | 97 + lib/compiler/test/lfe-source.patch | 117 ++ lib/compiler/test/lfe.readme | 31 + lib/compiler/test/lfe_andor_SUITE.core | 2014 +++++++++++++++++++ lib/compiler/test/lfe_guard_SUITE.core | 3438 ++++++++++++++++++++++++++++++++ 7 files changed, 5719 insertions(+), 1 deletion(-) create mode 100644 lib/compiler/test/lfe-core.patch create mode 100644 lib/compiler/test/lfe-source.patch create mode 100644 lib/compiler/test/lfe.readme create mode 100644 lib/compiler/test/lfe_andor_SUITE.core create mode 100644 lib/compiler/test/lfe_guard_SUITE.core (limited to 'lib') diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index f2c68505fc..e338dbb4e3 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -93,6 +93,10 @@ INLINE= \ receive \ record +CORE_MODULES = \ + lfe_andor_SUITE \ + lfe_guard_SUITE + NO_OPT_MODULES= $(NO_OPT:%=%_no_opt_SUITE) NO_OPT_ERL_FILES= $(NO_OPT_MODULES:%=%.erl) POST_OPT_MODULES= $(NO_OPT:%=%_post_opt_SUITE) @@ -101,6 +105,8 @@ INLINE_MODULES= $(INLINE:%=%_inline_SUITE) INLINE_ERL_FILES= $(INLINE_MODULES:%=%.erl) ERL_FILES= $(MODULES:%=%.erl) +CORE_FILES= $(CORE_MODULES:%=%.core) +ERL_DUMMY_FILES= $(CORE_MODULES:%=%.erl) ##TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) ##INSTALL_PROGS= $(TARGET_FILES) @@ -134,6 +140,8 @@ make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(INLINE_ERL_FILES) -o$(EBIN) $(POST_OPT_MODULES) >> $(EMAKEFILE) $(ERL_TOP)/make/make_emakefile +inline $(ERL_COMPILE_FLAGS) \ -o$(EBIN) $(INLINE_MODULES) >> $(EMAKEFILE) + $(ERL_TOP)/make/make_emakefile +from_core $(ERL_COMPILE_FLAGS) \ + -o$(EBIN) $(CORE_MODULES) >> $(EMAKEFILE) tests debug opt: make_emakefile erl $(ERL_MAKE_FLAGS) -make @@ -171,6 +179,12 @@ release_tests_spec: make_emakefile $(EMAKEFILE) $(ERL_FILES) "$(RELSYSDIR)" $(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \ $(INLINE_ERL_FILES) "$(RELSYSDIR)" + $(INSTALL_DATA) $(CORE_FILES) "$(RELSYSDIR)" + for file in $(ERL_DUMMY_FILES); do \ + module=`basename $$file .erl`; \ + echo "-module($$module). %% dummy .erl file" >$$file; \ + done + $(INSTALL_DATA) $(ERL_DUMMY_FILES) "$(RELSYSDIR)" chmod -R u+w "$(RELSYSDIR)" @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index d7e0b3498a..a2d3e2140b 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -1151,8 +1151,15 @@ get_unique_beam_files() -> get_unique_files(Ext) -> Wc = filename:join(filename:dirname(code:which(?MODULE)), "*"++Ext), - [F || F <- filelib:wildcard(Wc), not is_cloned(F, Ext)]. + [F || F <- filelib:wildcard(Wc), + not is_cloned(F, Ext), not is_lfe_module(F, Ext)]. is_cloned(File, Ext) -> Mod = list_to_atom(filename:basename(File, Ext)), test_lib:is_cloned_mod(Mod). + +is_lfe_module(File, Ext) -> + case filename:basename(File, Ext) of + "lfe_" ++ _ -> true; + _ -> false + end. diff --git a/lib/compiler/test/lfe-core.patch b/lib/compiler/test/lfe-core.patch new file mode 100644 index 0000000000..756d131e2c --- /dev/null +++ b/lib/compiler/test/lfe-core.patch @@ -0,0 +1,97 @@ +Date: Sun, 13 Nov 2016 10:11:11 +0100 +Subject: [PATCH] Fix invalid variable names + +--- + test/lfe_andor_SUITE.core | 16 ++++++++-------- + test/lfe_guard_SUITE.core | 14 +++++++------- + 2 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/test/lfe_andor_SUITE.core b/test/lfe_andor_SUITE.core +index 96ff765..df58b39 100644 +--- a/test/lfe_andor_SUITE.core ++++ b/test/lfe_andor_SUITE.core +@@ -288,19 +288,19 @@ module 'lfe_andor_SUITE' ['$handle_undefined_function'/2, + 'lc$^0'/1 = + fun (_2) -> + case <_2> of +- <[_x|_|-0-|]> when 'true' -> ++ <[_x|_lfe0]> when 'true' -> + letrec + 'lc$^1'/1 = + fun (_3) -> + case <_3> of +- <[_y|_|-1-|]> when 'true' -> ++ <[_y|_lfe1]> when 'true' -> + let <_4> = + apply 'lc$^1'/1 +- (_|-1-|) ++ (_lfe1) + in [{_x,_y}|_4] + <[]> when 'true' -> + apply 'lc$^0'/1 +- (_|-0-|) ++ (_lfe0) + ( <_5> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_5}) +@@ -455,19 +455,19 @@ module 'lfe_andor_SUITE' ['$handle_undefined_function'/2, + 'lc$^2'/1 = + fun (_2) -> + case <_2> of +- <[_x|_|-2-|]> when 'true' -> ++ <[_x|_lfe2]> when 'true' -> + letrec + 'lc$^3'/1 = + fun (_3) -> + case <_3> of +- <[_y|_|-3-|]> when 'true' -> ++ <[_y|_lfe3]> when 'true' -> + let <_4> = + apply 'lc$^3'/1 +- (_|-3-|) ++ (_lfe3) + in [{_x,_y}|_4] + <[]> when 'true' -> + apply 'lc$^2'/1 +- (_|-2-|) ++ (_lfe2) + ( <_5> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_5}) +diff --git a/test/lfe_guard_SUITE.core b/test/lfe_guard_SUITE.core +index 38f1d99..920be82 100644 +--- a/test/lfe_guard_SUITE.core ++++ b/test/lfe_guard_SUITE.core +@@ -2857,22 +2857,22 @@ module 'lfe_guard_SUITE' ['$handle_undefined_function'/2, + 'false' -> + case <_t> of + <{_a,_b,_c,_d}> when 'true' -> +- let <_|-0-|> = ++ let <_lfe0> = + <_a> +- in let <_|-1-|> = ++ in let <_lfe1> = + <_b> +- in let <_|-2-|> = ++ in let <_lfe2> = + <_c> +- in let <_|-3-|> = ++ in let <_lfe3> = + <_d> + in let <_4> = + let <_3> = + call 'erlang':'+' +- (_|-0-|, _|-1-|) ++ (_lfe0, _lfe1) + in call 'erlang':'+' +- (_3, _|-2-|) ++ (_3, _lfe2) + in call 'erlang':'+' +- (_4, _|-3-|) ++ (_4, _lfe3) + ( <_5> when 'true' -> + primop 'match_fail' + ({'badmatch',{_5}}) +-- +2.7.4 (Apple Git-66) + diff --git a/lib/compiler/test/lfe-source.patch b/lib/compiler/test/lfe-source.patch new file mode 100644 index 0000000000..cbd6748bc9 --- /dev/null +++ b/lib/compiler/test/lfe-source.patch @@ -0,0 +1,117 @@ +Date: Sun, 13 Nov 2016 09:40:36 +0100 +Subject: [PATCH] Rename and fix up LFE test suites + +--- + test/{andor_SUITE.lfe => lfe_andor_SUITE.lfe} | 16 ++++++++-------- + test/{guard_SUITE.lfe => lfe_guard_SUITE.lfe} | 8 ++++---- + 2 files changed, 12 insertions(+), 12 deletions(-) + rename test/{andor_SUITE.lfe => lfe_andor_SUITE.lfe} (97%) + rename test/{guard_SUITE.lfe => lfe_guard_SUITE.lfe} (99%) + +diff --git a/test/andor_SUITE.lfe b/test/lfe_andor_SUITE.lfe +similarity index 97% +rename from test/andor_SUITE.lfe +rename to test/lfe_andor_SUITE.lfe +index 64feddd..1802b3f 100644 +--- a/test/andor_SUITE.lfe ++++ b/test/lfe_andor_SUITE.lfe +@@ -26,14 +26,14 @@ + + (include-file "test_server.lfe") + +-(defmodule andor_SUITE ++(defmodule lfe_andor_SUITE + (export (all 0) (suite 0) (groups 0) (init_per_suite 1) (end_per_suite 1) + (init_per_group 2) (end_per_group 2) + (t_case 1) (t_and_or 1) (t_andalso 1) (t_orelse 1) (inside 1) + (overlap 1) (combined 1) (in_case 1) (before_and_inside_if 1) + )) + +-(defmacro MODULE () `'andor_SUITE) ++(defmacro MODULE () `'lfe_andor_SUITE) + + (defun all () + ;; (: test_lib recompile (MODULE)) +@@ -206,7 +206,7 @@ + + (defun t-andalso-1 + ([(tuple x y)] +- (: lfe_io format '"(andalso ~w ~w): " (list x y)) ++ (: io format '"(andalso ~w ~w): " (list x y)) + (let* ((v0 (andalso (echo x) (echo y))) + (v1 (when (=:= v0 v1)) + (eif (andalso x y) 'true 'true 'false))) +@@ -248,7 +248,7 @@ + + (defun t-orelse-1 + ([(tuple x y)] +- (: lfe_io format '"(orelse ~w ~w): " (list x y)) ++ (: io format '"(orelse ~w ~w): " (list x y)) + (let* ((v0 (orelse (echo x) (echo y))) + (v1 (when (=:= v0 v1)) + (eif (orelse x y) 'true 'true 'false))) +@@ -289,7 +289,7 @@ + (when (=:= r1 r2) (=:= xm xm2) (=:= ym ym2) (=:= x x2) + (=:= y y2) (=:= w w2) (=:= h h2)) + (inside-guard xm ym x y w h))) +- (: lfe_io fwrite ++ (: io fwrite + '"(andalso (=< ~p ~p) (< ~p ~p) (=< ~p ~p) (< ~p ~p)) ==> ~p\n" + (list x xm xm (+ x w) y ym ym (+ y h) r1))) + r1)) +@@ -499,12 +499,12 @@ + ;; Utilities + + (defun check (v1 v0) +- (eif (/= v1 v0) (progn (: lfe_io fwrite '"error: ~w.\n" (list v1)) ++ (eif (/= v1 v0) (progn (: io fwrite '"error: ~w.\n" (list v1)) + (exit 'suite_failed)) +- 'true (: lfe_io fwrite '"ok: ~w.\n" (list v1)))) ++ 'true (: io fwrite '"ok: ~w.\n" (list v1)))) + + (defun echo (x) +- (: lfe_io fwrite '"(eval ~w); " (list x)) ++ (: io fwrite '"(eval ~w); " (list x)) + x) + + ;; Call this function to turn off constant propagation. +diff --git a/test/guard_SUITE.lfe b/test/lfe_guard_SUITE.lfe +similarity index 99% +rename from test/guard_SUITE.lfe +rename to test/lfe_guard_SUITE.lfe +index 33b1344..2eeb1a6 100644 +--- a/test/guard_SUITE.lfe ++++ b/test/lfe_guard_SUITE.lfe +@@ -26,7 +26,7 @@ + + (include-file "test_server.lfe") + +-(defmodule guard_SUITE ++(defmodule lfe_guard_SUITE + (export (all 0) (suite 0) (groups 0) (init_per_suite 1) (end_per_suite 1) + (init_per_group 2) (end_per_group 2) + (misc 1) (const_cond 1) (basic_not 1) (complex_not 1) (nested_nots 1) +@@ -42,7 +42,7 @@ + (check_qlc_hrl 1) (andalso_semi 1) (t_tuple_size 1) (binary_part 1) + )) + +-(defmacro MODULE () `'guard_SUITE) ++(defmacro MODULE () `'lfe_guard_SUITE) + + (defun all () + ;; (: test_lib recompile (MODULE)) +@@ -764,9 +764,9 @@ + + (defun is_function_2 + ([config] (when (is_list config)) +- (line (test-pat 'true (is_function (id (function guard_SUITE all 1)) 1))) ++ (line (test-pat 'true (is_function (id (function lfe_guard_SUITE all 1)) 1))) + (line (test-pat 'true (is_function (id (lambda () 'ok)) 0))) +- (line (test-pat 'false (is_function (id (function guard_SUITE all 1)) 0))) ++ (line (test-pat 'false (is_function (id (function lfe_guard_SUITE all 1)) 0))) + (line (test-pat 'false (is_function (id (lambda () 'ok)) 1))) + + (let ((F (lambda (_) 'ok))) +-- +2.7.4 (Apple Git-66) + diff --git a/lib/compiler/test/lfe.readme b/lib/compiler/test/lfe.readme new file mode 100644 index 0000000000..2fc88e0252 --- /dev/null +++ b/lib/compiler/test/lfe.readme @@ -0,0 +1,31 @@ +Creating the LFE-derived test suites +==================================== + +Here is how to create `lfe_andor_SUITE.core` and `lfe_guard_SUITE.core` +files. + +First clone and build LFE. + + git clone https://github.com/rvirding/lfe.git + cd lfe + git checkout v1.2.0 + MAKEFLAGS='' make compile + export PATH=$(pwd)/bin:$PATH + +Apply the source patch to rename and fix up the LFE source code: + + cd test + git apply $ERL_TOP/lib/compiler/test/lfe-source.patch + git reset --hard HEAD + +Compile the modules to Core Erlang: + + lfec +to-core0 lfe*.lfe + +Apply the core patch to correct some invalid variable names: + + git apply $ERL_TOP/lib/compiler/test/lfe-core.patch + +Copy the patched .core file to the test suite: + + cp lfe*.core $ERL_TOP/lib/compiler/test diff --git a/lib/compiler/test/lfe_andor_SUITE.core b/lib/compiler/test/lfe_andor_SUITE.core new file mode 100644 index 0000000000..df58b39ae6 --- /dev/null +++ b/lib/compiler/test/lfe_andor_SUITE.core @@ -0,0 +1,2014 @@ +module 'lfe_andor_SUITE' ['$handle_undefined_function'/2, + 'LFE-EXPAND-EXPORTED-MACRO'/3, + 'all'/0, + 'before_and_inside_if'/1, + 'combined'/1, + 'end_per_group'/2, + 'end_per_suite'/1, + 'groups'/0, + 'in_case'/1, + 'init_per_group'/2, + 'init_per_suite'/1, + 'inside'/1, + 'module_info'/0, + 'module_info'/1, + 'overlap'/1, + 'suite'/0, + 't_and_or'/1, + 't_andalso'/1, + 't_case'/1, + 't_orelse'/1] + attributes [] +'all'/0 = + %% Line 38 + fun () -> + ['t_case'|['t_and_or'|['t_andalso'|['t_orelse'|['inside'|['overlap'|['combined'|['in_case'|['before_and_inside_if']]]]]]]]] +'suite'/0 = + %% Line 44 + fun () -> + [] +'groups'/0 = + %% Line 46 + fun () -> + [] +'init_per_suite'/1 = + %% Line 48 + fun (_config) -> + _config +'end_per_suite'/1 = + %% Line 50 + fun (_config) -> + 'ok' +'init_per_group'/2 = + %% Line 52 + fun (_name,_config) -> + _config +'end_per_group'/2 = + %% Line 54 + fun (_name,_config) -> + _config +'t_case'/1 = + %% Line 56 + fun (_0) -> + case <_0> of + <'suite'> when 'true' -> + [] + <'doc'> when 'true' -> + [84|[101|[115|[116|[32|[105|[110|[32|[99|[97|[115|[101|[46]]]]]]]]]]]]] + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_andor_SUITE',['test-pat'|[['quote'|['less']]|[['t-case-a'|[1|[2]]]]]]}) + let <_val> = + + in case <_val> of + <'less'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_25> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_25}) + -| [{'function_name',{'t_case',1}}] ) + -| ['compiler_generated'] ) + end +'t-case-a'/2 = + %% Line 94 + fun (_a,_b) -> + case call 'erlang':'<' + (_a, _b) of + <[_0|_1]> when 'true' -> + 'ok' + <'true'> when 'true' -> + 'less' + <'false'> when 'true' -> + 'not_less' + <{'a','b','c'}> when 'true' -> + 'ok' + <_2> when 'true' -> + 'ok' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'t-case-b'/2 = + %% Line 102 + fun (_a,_b) -> + case call 'erlang':'=:=' + (_a, _b) of + <'blurf'> when 'true' -> + 'ok' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'t-case-c'/2 = + %% Line 106 + fun (_a,_b) -> + case let <_0> = + call 'erlang':'=:=' + (_a, _b) + in call 'erlang':'not' + (_0) of + <'true'> when 'true' -> + 'ne' + <'false'> when 'true' -> + 'eq' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'t-case-d'/3 = + %% Line 111 + fun (_a,_b,_x) -> + case let <_0> = + call 'erlang':'=:=' + (_a, _b) + in call 'erlang':'and' + (_0, _x) of + <'true'> when 'true' -> + 't' + <'false'> when 'true' -> + 'f' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'t-case-e'/2 = + %% Line 116 + fun (_a,_b) -> + case call 'erlang':'=:=' + (_a, _b) of + <_bool> + when try + let <_0> = + call 'erlang':'is_tuple' + (_a) + in _0 + of -> + Try + catch -> + 'false' -> + apply 'id'/1 + (_bool) + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'t-case-xy'/3 = + %% Line 120 + fun (_x,_y,_z) -> + let <_r0> = + + in case of + <_res> + when try + let <_0> = + call 'erlang':'=:=' + (_res, _r0) + in _0 + of -> + Try + catch -> + 'false' -> + _res + ( <_1> when 'true' -> + primop 'match_fail' + ({'badmatch',{_1}}) + -| ['compiler_generated'] ) + end +'t-case-x'/3 = + %% Line 125 + fun (_x,_y,_z) -> + case let <_0> = + call 'erlang':'abs' + (_x) + in call 'erlang':'=:=' + (_0, 42) of + <'true'> when 'true' -> + call 'erlang':'=:=' + (_y, 100) + <'false'> when 'true' -> + call 'erlang':'=:=' + (_z, 700) + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'t-case-y'/3 = + %% Line 130 + fun (_x,_y,_z) -> + case let <_0> = + call 'erlang':'abs' + (_x) + in call 'erlang':'=:=' + (_0, 42) of + <'false'> when 'true' -> + call 'erlang':'=:=' + (_z, 700) + <'true'> when 'true' -> + call 'erlang':'=:=' + (_y, 100) + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'t_and_or'/1 = + %% Line 135 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_andor_SUITE',['test-pat'|[['quote'|['true']]|[['and'|[['quote'|['true']]|[['quote'|['true']]]]]]]]}) + let <_val> = + + in case <_val> of + <'true'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_42> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_42}) + -| [{'function_name',{'t_and_or',1}}] ) + -| ['compiler_generated'] ) + end +'t_andalso'/1 = + %% Line 172 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do let <_bs> = + <['true'|['false']]> + in let <_ps> = + + case <_2> of + <[_x|_lfe0]> when 'true' -> + letrec + 'lc$^1'/1 = + fun (_3) -> + case <_3> of + <[_y|_lfe1]> when 'true' -> + let <_4> = + apply 'lc$^1'/1 + (_lfe1) + in [{_x,_y}|_4] + <[]> when 'true' -> + apply 'lc$^0'/1 + (_lfe0) + ( <_5> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_5}) + -| [{'function_name',{'t_andalso',1}}] ) + -| ['compiler_generated'] ) + end + in apply 'lc$^1'/1 + (_bs) + <[]> when 'true' -> + [] + ( <_6> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_6}) + -| [{'function_name',{'t_andalso',1}}] ) + -| ['compiler_generated'] ) + end + in apply 'lc$^0'/1 + (_bs)> + in let <_7> = + fun (_p) -> + apply 't-andalso-1'/1 + (_p) + in call 'lists':'foreach' + (_7, _ps) + do call 'erlang':'put' + ('test_server_loc', {'lfe_andor_SUITE',['test-pat'|[['quote'|['true']]|[['andalso'|[['quote'|['true']]|[['quote'|['true']]]]]]]]}) + let <_val> = + when 'true' -> + 'true' + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end> + in case <_val> of + <'true'> when 'true' -> + _val + ( <_8> when 'true' -> + primop 'match_fail' + ({'badmatch',{_8}}) + -| ['compiler_generated'] ) + end + ( <_57> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_57}) + -| [{'function_name',{'t_andalso',1}}] ) + -| ['compiler_generated'] ) + end +'t-andalso-1'/1 = + %% Line 207 + fun (_0) -> + case <_0> of + <{_x,_y}> when 'true' -> + do call 'io':'format' + ([40|[97|[110|[100|[97|[108|[115|[111|[32|[126|[119|[32|[126|[119|[41|[58|[32]]]]]]]]]]]]]]]]], [_x,_y]) + let <_v0> = + when 'true' -> + apply 'echo'/1 + (_y) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end> + in case + when try + let <_3> = + let <_2> = + case _x of + <'true'> when 'true' -> + _y + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_2, 'true') + -| ['compiler_generated'] ) + in _3 + of -> + Try + catch -> + 'false' -> + 'true' + <_4> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <_v1> + when try + let <_5> = + call 'erlang':'=:=' + (_v0, _v1) + in _5 + of -> + Try + catch -> + 'false' -> + let <_6> = + call 'erlang':'and' + (_x, _y) + in apply 'check'/2 + (_v1, _6) + ( <_7> when 'true' -> + primop 'match_fail' + ({'badmatch',{_7}}) + -| ['compiler_generated'] ) + end + ( <_8> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_8}) + -| [{'function_name',{'t-andalso-1',1}}] ) + -| ['compiler_generated'] ) + end +'t_orelse'/1 = + %% Line 215 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do let <_bs> = + <['true'|['false']]> + in let <_ps> = + + case <_2> of + <[_x|_lfe2]> when 'true' -> + letrec + 'lc$^3'/1 = + fun (_3) -> + case <_3> of + <[_y|_lfe3]> when 'true' -> + let <_4> = + apply 'lc$^3'/1 + (_lfe3) + in [{_x,_y}|_4] + <[]> when 'true' -> + apply 'lc$^2'/1 + (_lfe2) + ( <_5> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_5}) + -| [{'function_name',{'t_orelse',1}}] ) + -| ['compiler_generated'] ) + end + in apply 'lc$^3'/1 + (_bs) + <[]> when 'true' -> + [] + ( <_6> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_6}) + -| [{'function_name',{'t_orelse',1}}] ) + -| ['compiler_generated'] ) + end + in apply 'lc$^2'/1 + (_bs)> + in let <_7> = + fun (_p) -> + apply 't-orelse-1'/1 + (_p) + in call 'lists':'foreach' + (_7, _ps) + do call 'erlang':'put' + ('test_server_loc', {'lfe_andor_SUITE',['test-pat'|[['quote'|['true']]|[['orelse'|[['quote'|['true']]|[['quote'|['true']]]]]]]]}) + let <_val> = + when 'true' -> + 'true' + <'false'> when 'true' -> + 'true' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end> + in case <_val> of + <'true'> when 'true' -> + _val + ( <_8> when 'true' -> + primop 'match_fail' + ({'badmatch',{_8}}) + -| ['compiler_generated'] ) + end + ( <_57> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_57}) + -| [{'function_name',{'t_orelse',1}}] ) + -| ['compiler_generated'] ) + end +'t-orelse-1'/1 = + %% Line 249 + fun (_0) -> + case <_0> of + <{_x,_y}> when 'true' -> + do call 'io':'format' + ([40|[111|[114|[101|[108|[115|[101|[32|[126|[119|[32|[126|[119|[41|[58|[32]]]]]]]]]]]]]]]], [_x,_y]) + let <_v0> = + when 'true' -> + 'true' + <'false'> when 'true' -> + apply 'echo'/1 + (_y) + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end> + in case + when try + let <_3> = + let <_2> = + case _x of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + _y + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_2, 'true') + -| ['compiler_generated'] ) + in _3 + of -> + Try + catch -> + 'false' -> + 'true' + <_4> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <_v1> + when try + let <_5> = + call 'erlang':'=:=' + (_v0, _v1) + in _5 + of -> + Try + catch -> + 'false' -> + let <_6> = + call 'erlang':'or' + (_x, _y) + in apply 'check'/2 + (_v1, _6) + ( <_7> when 'true' -> + primop 'match_fail' + ({'badmatch',{_7}}) + -| ['compiler_generated'] ) + end + ( <_8> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_8}) + -| [{'function_name',{'t-orelse-1',1}}] ) + -| ['compiler_generated'] ) + end +'inside'/1 = + %% Line 257 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_andor_SUITE',['test-pat'|[['quote'|['true']]|[['inside'|[-8|[1]]]]]]}) + let <_val> = + + in case <_val> of + <'true'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_12> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_12}) + -| [{'function_name',{'inside',1}}] ) + -| ['compiler_generated'] ) + end +'inside'/2 = + %% Line 272 + fun (_xm,_ym) -> + let <_x> = + <-1.00000000000000000000e+01> + in let <_y> = + <-2.00000000000000000000e+00> + in let <_w> = + <2.00000000000000000000e+01> + in let <_h> = + <4.00000000000000000000e+00> + in let <_r0> = + + in case + when try + let <_4> = + let <_3> = + case call 'erlang':'=<' + (_x, _xm) of + <'true'> when 'true' -> + case let <_1> = + call 'erlang':'+' + (_x, _w) + in call 'erlang':'<' + (_xm, _1) of + <'true'> when 'true' -> + case call 'erlang':'=<' + (_y, _ym) of + <'true'> when 'true' -> + let <_2> = + call 'erlang':'+' + (_y, _h) + in call 'erlang':'<' + (_ym, _2) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_3, 'true') + -| ['compiler_generated'] ) + in _4 + of -> + Try + catch -> + 'false' -> + 'true' + <_5> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <_r1> + when try + let <_6> = + call 'erlang':'=:=' + (_r0, _r1) + in _6 + of -> + Try + catch -> + 'false' -> + do case let <_7> = + apply 'id'/1 + (_r1) + in call 'erlang':'not' + (_7) of + <_o0> when 'true' -> + case + when try + let <_12> = + let <_11> = + case call 'erlang':'=<' + (_x, _xm) of + <'true'> when 'true' -> + case let <_9> = + call 'erlang':'+' + (_x, _w) + in call 'erlang':'<' + (_xm, _9) of + <'true'> when 'true' -> + case call 'erlang':'=<' + (_y, _ym) of + <'true'> when 'true' -> + let <_10> = + call 'erlang':'+' + (_y, _h) + in call 'erlang':'<' + (_ym, _10) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in call 'erlang':'not' + (_11) + in _12 + of -> + Try + catch -> + 'false' -> + 'true' + <_13> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <_o1> + when try + let <_14> = + call 'erlang':'=:=' + (_o0, _o1) + in _14 + of -> + Try + catch -> + 'false' -> + _o1 + ( <_15> when 'true' -> + primop 'match_fail' + ({'badmatch',{_15}}) + -| ['compiler_generated'] ) + end + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + do case of + <{_r2,_xm2,_ym2,_x2,_y2,_w2,_h2}> + when try + let <_16> = + call 'erlang':'=:=' + (_r1, _r2) + in let <_17> = + call 'erlang':'=:=' + (_xm, _xm2) + in let <_18> = + call 'erlang':'=:=' + (_ym, _ym2) + in let <_19> = + call 'erlang':'=:=' + (_x, _x2) + in let <_20> = + call 'erlang':'=:=' + (_y, _y2) + in let <_21> = + call 'erlang':'=:=' + (_w, _w2) + in let <_22> = + call 'erlang':'=:=' + (_h, _h2) + in let <_23> = + call 'erlang':'and' + (_16, _17) + in let <_24> = + call 'erlang':'and' + (_23, _18) + in let <_25> = + call 'erlang':'and' + (_24, _19) + in let <_26> = + call 'erlang':'and' + (_25, _20) + in let <_27> = + call 'erlang':'and' + (_26, _21) + in call 'erlang':'and' + (_27, _22) + of -> + Try + catch -> + 'false' -> + let <_30> = + let <_28> = + call 'erlang':'+' + (_x, _w) + in let <_29> = + call 'erlang':'+' + (_y, _h) + in [_x,_xm,_xm,_28,_y,_ym,_ym,_29,_r1] + in call 'io':'fwrite' + ([40|[97|[110|[100|[97|[108|[115|[111|[32|[40|[61|[60|[32|[126|[112|[32|[126|[112|[41|[32|[40|[60|[32|[126|[112|[32|[126|[112|[41|[32|[40|[61|[60|[32|[126|[112|[32|[126|[112|[41|[32|[40|[60|[32|[126|[112|[32|[126|[112|[41|[41|[32|[61|[61|[62|[32|[126|[112|[10]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]], _30) + ( <_31> when 'true' -> + primop 'match_fail' + ({'badmatch',{_31}}) + -| ['compiler_generated'] ) + end + _r1 + ( <_32> when 'true' -> + primop 'match_fail' + ({'badmatch',{_32}}) + -| ['compiler_generated'] ) + end +'inside'/6 = + %% Line 297 + fun (_xm,_ym,_x,_y,_w,_h) -> + case call 'erlang':'=<' + (_x, _xm) of + <'true'> when 'true' -> + case let <_0> = + call 'erlang':'+' + (_x, _w) + in call 'erlang':'<' + (_xm, _0) of + <'true'> when 'true' -> + case call 'erlang':'=<' + (_y, _ym) of + <'true'> when 'true' -> + let <_1> = + call 'erlang':'+' + (_y, _h) + in call 'erlang':'<' + (_ym, _1) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end +'inside-guard'/6 = + %% Line 300 + fun (_5,_4,_3,_2,_1,_0) -> + case <_5,_4,_3,_2,_1,_0> of + <_xm,_ym,_x,_y,_w,_h> + when try + let <_9> = + let <_8> = + case call 'erlang':'=<' + (_x, _xm) of + <'true'> when 'true' -> + case let <_6> = + call 'erlang':'+' + (_x, _w) + in call 'erlang':'<' + (_xm, _6) of + <'true'> when 'true' -> + case call 'erlang':'=<' + (_y, _ym) of + <'true'> when 'true' -> + let <_7> = + call 'erlang':'+' + (_y, _h) + in call 'erlang':'<' + (_ym, _7) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_8, 'true') + -| ['compiler_generated'] ) + in _9 + of -> + Try + catch -> + 'false' -> + {'true',_xm,_ym,_x,_y,_w,_h} + <_xm,_ym,_x,_y,_w,_h> when 'true' -> + {'false',_xm,_ym,_x,_y,_w,_h} + ( <_15,_14,_13,_12,_11,_10> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_15,_14,_13,_12,_11,_10}) + -| [{'function_name',{'inside-guard',6}}] ) + -| ['compiler_generated'] ) + end +'overlap'/1 = + %% Line 307 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_andor_SUITE',['test-pat'|[['quote'|['true']]|[['overlap'|[7.00000000000000000000e+00|[2.00000000000000000000e+00|[8.00000000000000000000e+00|[5.00000000000000000000e-01]]]]]]]]}) + let <_val> = + + in case <_val> of + <'true'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_10> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_10}) + -| [{'function_name',{'overlap',1}}] ) + -| ['compiler_generated'] ) + end +'overlap'/4 = + %% Line 321 + fun (_pos1,_len1,_pos2,_len2) -> + let <_r0> = + + when try + let <_3> = + let <_2> = + case case call 'erlang':'=<' + (_pos2, _pos1) of + <'true'> when 'true' -> + let <_0> = + call 'erlang':'+' + (_pos2, _len2) + in call 'erlang':'<' + (_pos1, _0) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + case call 'erlang':'=<' + (_pos1, _pos2) of + <'true'> when 'true' -> + let <_1> = + call 'erlang':'+' + (_pos1, _len1) + in call 'erlang':'<' + (_pos2, _1) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_2, 'true') + -| ['compiler_generated'] ) + in _3 + of -> + Try + catch -> + 'false' -> + 'true' + <_pos1> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> + in case when 'true' -> + let <_4> = + call 'erlang':'+' + (_pos2, _len2) + in call 'erlang':'<' + (_pos1, _4) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + case call 'erlang':'=<' + (_pos1, _pos2) of + <'true'> when 'true' -> + let <_5> = + call 'erlang':'+' + (_pos1, _len1) + in call 'erlang':'<' + (_pos2, _5) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end> of + <_r1> + when try + let <_6> = + call 'erlang':'=:=' + (_r0, _r1) + in _6 + of -> + Try + catch -> + 'false' -> + case + when try + let <_10> = + let <_9> = + case case call 'erlang':'=<' + (_pos2, _pos1) of + <'true'> when 'true' -> + let <_7> = + call 'erlang':'+' + (_pos2, _len2) + in call 'erlang':'<' + (_pos1, _7) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + case call 'erlang':'=<' + (_pos1, _pos2) of + <'true'> when 'true' -> + let <_8> = + call 'erlang':'+' + (_pos1, _len1) + in call 'erlang':'<' + (_pos2, _8) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_9, 'true') + -| ['compiler_generated'] ) + in _10 + of -> + Try + catch -> + 'false' -> + 'true' + <_pos1> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <_r2> + when try + let <_11> = + call 'erlang':'=:=' + (_r2, _r1) + in _11 + of -> + Try + catch -> + 'false' -> + apply 'id'/1 + (_r2) + ( <_12> when 'true' -> + primop 'match_fail' + ({'badmatch',{_12}}) + -| ['compiler_generated'] ) + end + ( <_13> when 'true' -> + primop 'match_fail' + ({'badmatch',{_13}}) + -| ['compiler_generated'] ) + end +'combined'/1 = + %% Line 348 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_andor_SUITE',['test-pat'|[['quote'|['false']]|[['comb'|[['quote'|['false']]|[['quote'|['false']]|[['quote'|['false']]]]]]]]]}) + let <_val> = + + in case <_val> of + <'false'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_26> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_26}) + -| [{'function_name',{'combined',1}}] ) + -| ['compiler_generated'] ) + end +'comb'/3 = + %% Line 383 + fun (_a,_b,_c) -> + let <_r0> = + when 'true' -> + _b + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + _c + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end> + in case + when try + let <_2> = + let <_1> = + case case _a of + <'true'> when 'true' -> + _b + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + _c + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_1, 'true') + -| ['compiler_generated'] ) + in _2 + of -> + Try + catch -> + 'false' -> + 'true' + <_3> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <_r1> + when try + let <_4> = + call 'erlang':'=:=' + (_r0, _r1) + in _4 + of -> + Try + catch -> + 'false' -> + let <_n0> = + + when try + let <_7> = + let <_6> = + case case _a of + <'true'> when 'true' -> + _b + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + _c + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in call 'erlang':'not' + (_6) + in _7 + of -> + Try + catch -> + 'false' -> + 'true' + <_8> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> + in case = + call 'erlang':'not' + (_r1) + in apply 'id'/1 + (_9)> of + <_n1> + when try + let <_10> = + call 'erlang':'=:=' + (_n0, _n1) + in _10 + of -> + Try + catch -> + 'false' -> + case when 'true' -> + _b + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + _c + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end> of + <_r2> + when try + let <_11> = + call 'erlang':'=:=' + (_r1, _r2) + in _11 + of -> + Try + catch -> + 'false' -> + case + when try + let <_14> = + let <_13> = + case case _a of + <'true'> when 'true' -> + _b + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + _c + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_13, 'true') + -| ['compiler_generated'] ) + in _14 + of -> + Try + catch -> + 'false' -> + 'true' + <_15> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <_r3> + when try + let <_16> = + call 'erlang':'=:=' + (_r2, _r3) + in _16 + of -> + Try + catch -> + 'false' -> + case = + call 'erlang':'not' + (_r3) + in apply 'id'/1 + (_17)> of + <_n2> + when try + let <_18> = + call 'erlang':'=:=' + (_n1, _n2) + in _18 + of -> + Try + catch -> + 'false' -> + case + when try + let <_21> = + let <_20> = + case case _a of + <'true'> when 'true' -> + _b + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + _c + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_20, 'true') + -| ['compiler_generated'] ) + in _21 + of -> + Try + catch -> + 'false' -> + 'true' + <_22> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <_r4> + when try + let <_23> = + call 'erlang':'=:=' + (_r3, _r4) + in _23 + of -> + Try + catch -> + 'false' -> + apply 'id'/1 + (_r4) + ( <_24> when 'true' -> + primop 'match_fail' + ({'badmatch',{_24}}) + -| ['compiler_generated'] ) + end + ( <_25> when 'true' -> + primop 'match_fail' + ({'badmatch',{_25}}) + -| ['compiler_generated'] ) + end + ( <_26> when 'true' -> + primop 'match_fail' + ({'badmatch',{_26}}) + -| ['compiler_generated'] ) + end + ( <_27> when 'true' -> + primop 'match_fail' + ({'badmatch',{_27}}) + -| ['compiler_generated'] ) + end + ( <_28> when 'true' -> + primop 'match_fail' + ({'badmatch',{_28}}) + -| ['compiler_generated'] ) + end + ( <_29> when 'true' -> + primop 'match_fail' + ({'badmatch',{_29}}) + -| ['compiler_generated'] ) + end +'in_case'/1 = + %% Line 402 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_andor_SUITE',['test-pat'|[['quote'|['edge_rings']]|[['in-case-1'|[1|[1|[1|[1|[1]]]]]]]]]}) + let <_val> = + + in case <_val> of + <'edge_rings'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_13> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_13}) + -| [{'function_name',{'in_case',1}}] ) + -| ['compiler_generated'] ) + end +'in-case-1'/5 = + %% Line 419 + fun (_lenup,_lendw,_lenn,_rot,_count) -> + let <_r0> = + + in case of + <_res> + when try + let <_0> = + call 'erlang':'=:=' + (_r0, _res) + in _0 + of -> + Try + catch -> + 'false' -> + _res + ( <_1> when 'true' -> + primop 'match_fail' + ({'badmatch',{_1}}) + -| ['compiler_generated'] ) + end +'in-case-1-body'/5 = + %% Line 425 + fun (_lenup,_lendw,_lenn,_rot,_count) -> + case let <_5> = + let <_2> = + let <_0> = + call 'erlang':'/' + (_lenup, _count) + in call 'erlang':'>' + (_0, 7.06999999999999961808e-01) + in let <_3> = + let <_1> = + call 'erlang':'/' + (_lenn, _count) + in call 'erlang':'>' + (_1, 7.06999999999999961808e-01) + in call 'erlang':'and' + (_2, _3) + in let <_6> = + let <_4> = + call 'erlang':'abs' + (_rot) + in call 'erlang':'>' + (_4, 7.06999999999999961808e-01) + in call 'erlang':'and' + (_5, _6) of + <'true'> when 'true' -> + 'edge_rings' + <'false'> when 'true' -> + case let <_11> = + let <_9> = + let <_7> = + call 'erlang':'>=' + (_lenup, 1) + in let <_8> = + call 'erlang':'>=' + (_lendw, 1) + in call 'erlang':'or' + (_7, _8) + in let <_10> = + call 'erlang':'=<' + (_lenn, 1) + in call 'erlang':'or' + (_9, _10) + in let <_12> = + call 'erlang':'>' + (_count, 4) + in call 'erlang':'or' + (_11, _12) of + <'true'> when 'true' -> + 'not_loop' + <'false'> when 'true' -> + 'loop' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'in-case-1-guard'/5 = + %% Line 435 + fun (_lenup,_lendw,_lenn,_rot,_count) -> + case case let <_0> = + call 'erlang':'/' + (_lenup, _count) + in call 'erlang':'>' + (_0, 7.06999999999999961808e-01) of + <'true'> when 'true' -> + case let <_1> = + call 'erlang':'/' + (_lenn, _count) + in call 'erlang':'>' + (_1, 7.06999999999999961808e-01) of + <'true'> when 'true' -> + let <_2> = + call 'erlang':'abs' + (_rot) + in call 'erlang':'>' + (_2, 7.06999999999999961808e-01) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ('if_clause') + -| ['compiler_generated'] ) + end of + <'true'> when 'true' -> + 'edge_rings' + <'false'> + when try + let <_4> = + let <_3> = + case call 'erlang':'>=' + (_lenup, 1) of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + case call 'erlang':'>=' + (_lendw, 1) of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + case call 'erlang':'=<' + (_lenn, 1) of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + call 'erlang':'<' + (_count, 4) + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_3, 'true') + -| ['compiler_generated'] ) + in _4 + of -> + Try + catch -> + 'false' -> + 'not_loop' + <'false'> when 'true' -> + 'loop' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'before_and_inside_if'/1 = + %% Line 443 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_andor_SUITE',['test-pat'|[['quote'|['no']]|[['before-and-inside-if'|[['quote'|[['a']]]|[['quote'|[['b']]]|[['quote'|['delete']]]]]]]]]}) + let <_val> = + + in case <_val> of + <'no'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_18> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_18}) + -| [{'function_name',{'before_and_inside_if',1}}] ) + -| ['compiler_generated'] ) + end +'before-and-inside-if'/3 = + %% Line 468 + fun (XDo1,XDo2,Do3) -> + let = + + in let = + + in case 1 of + <_0> + when try + let <_7> = + let <_5> = + call 'erlang':'=:=' + (Do1, 'true') + in let <_6> = + let <_3> = + let <_1> = + call 'erlang':'=:=' + (Do1, 'false') + in let <_2> = + call 'erlang':'=:=' + (Do2, 'false') + in call 'erlang':'and' + (_1, _2) + in let <_4> = + call 'erlang':'=:=' + (Do3, 'delete') + in call 'erlang':'and' + (_3, _4) + in call 'erlang':'or' + (_5, _6) + in _7 + of -> + Try + catch -> + 'false' -> + 'no' + <_8> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'yes' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'before-and-inside-if-2'/3 = + %% Line 484 + fun (XDo1,XDo2,Do3) -> + let = + + in let = + + in let = + + when try + let <_7> = + let <_5> = + call 'erlang':'==' + (Do1, 'true') + in let <_6> = + let <_3> = + let <_1> = + call 'erlang':'==' + (Do1, 'false') + in let <_2> = + call 'erlang':'==' + (Do2, 'false') + in call 'erlang':'and' + (_1, _2) + in let <_4> = + call 'erlang':'==' + (Do3, 'blah') + in call 'erlang':'and' + (_3, _4) + in call 'erlang':'or' + (_5, _6) + in _7 + of -> + Try + catch -> + 'false' -> + 'ch1' + <_8> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'no' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> + in let = + + when try + let <_16> = + let <_14> = + call 'erlang':'==' + (Do1, 'true') + in let <_15> = + let <_12> = + let <_10> = + call 'erlang':'==' + (Do1, 'false') + in let <_11> = + call 'erlang':'==' + (Do2, 'false') + in call 'erlang':'and' + (_10, _11) + in let <_13> = + call 'erlang':'==' + (Do3, 'xx') + in call 'erlang':'and' + (_12, _13) + in call 'erlang':'or' + (_14, _15) + in _16 + of -> + Try + catch -> + 'false' -> + 'ch2' + <_17> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'no' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> + in {CH1,CH2} +'check'/2 = + %% Line 501 + fun (_v1,_v0) -> + case 1 of + <_0> + when try + let <_1> = + call 'erlang':'/=' + (_v1, _v0) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'io':'fwrite' + ([101|[114|[114|[111|[114|[58|[32|[126|[119|[46|[10]]]]]]]]]]], [_v1]) + call 'erlang':'exit' + ('suite_failed') + <_2> + when try + 'true' + of -> + Try + catch -> + 'false' -> + call 'io':'fwrite' + ([111|[107|[58|[32|[126|[119|[46|[10]]]]]]]], [_v1]) + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'echo'/1 = + %% Line 506 + fun (_x) -> + do call 'io':'fwrite' + ([40|[101|[118|[97|[108|[32|[126|[119|[41|[59|[32]]]]]]]]]]], [_x]) + _x +'id'/1 = + %% Line 511 + fun (_i) -> + _i +'$handle_undefined_function'/2 = + %% Line 29 + fun (_f,_as) -> + case let <_0> = + call 'lfe_env':'new' + () + in apply 'LFE-EXPAND-EXPORTED-MACRO'/3 + (_f, _as, _0) of + <{'yes',_exp}> when 'true' -> + call 'lfe_eval':'expr' + (_exp) + <'no'> when 'true' -> + let <_a,_b> = + <_f,_as> + in call 'error_handler':'raise_undef_exception' + ('lfe_andor_SUITE', _a, _b) + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'LFE-EXPAND-EXPORTED-MACRO'/3 = + %% Line 29 + fun (_2,_1,_0) -> + 'no' +'module_info'/0 = + fun () -> + call 'erlang':'get_module_info' + ('lfe_andor_SUITE') +'module_info'/1 = + fun (_x) -> + call 'erlang':'get_module_info' + ('lfe_andor_SUITE', _x) +end diff --git a/lib/compiler/test/lfe_guard_SUITE.core b/lib/compiler/test/lfe_guard_SUITE.core new file mode 100644 index 0000000000..920be82f61 --- /dev/null +++ b/lib/compiler/test/lfe_guard_SUITE.core @@ -0,0 +1,3438 @@ +module 'lfe_guard_SUITE' ['$handle_undefined_function'/2, + 'LFE-EXPAND-EXPORTED-MACRO'/3, + 'all'/0, + 'and_guard'/1, + 'andalso_semi'/1, + 'basic_andalso_orelse'/1, + 'basic_not'/1, + 'binary_part'/1, + 'build_in_guard'/1, + 'check_qlc_hrl'/1, + 'comma'/1, + 'complex_not'/1, + 'complex_or_guards'/1, + 'complex_semicolon'/1, + 'const_cond'/1, + 'end_per_group'/2, + 'end_per_suite'/1, + 'gbif'/1, + 'groups'/0, + 'init_per_group'/2, + 'init_per_suite'/1, + 'is_function_2'/1, + 'literal_type_tests'/1, + 'misc'/1, + 'module_info'/0, + 'module_info'/1, + 'more_or_guards'/1, + 'more_xor_guards'/1, + 'nested_nots'/1, + 'old_guard_tests'/1, + 'or_guard'/1, + 'rel_ops'/1, + 'semicolon'/1, + 'suite'/0, + 't_is_boolean'/1, + 't_tuple_size'/1, + 'traverse_dcd'/1, + 'tricky'/1, + 'xor_guard'/1] + attributes [] +'all'/0 = + %% Line 47 + fun () -> + ['misc'|['const_cond'|['basic_not'|['complex_not'|['nested_nots'|['semicolon'|['complex_semicolon'|['comma'|['or_guard'|['more_or_guards'|['complex_or_guards'|['and_guard'|['xor_guard'|['more_xor_guards'|['build_in_guard'|['old_guard_tests'|['gbif'|['t_is_boolean'|['is_function_2'|['tricky'|['rel_ops'|['literal_type_tests'|['basic_andalso_orelse'|['traverse_dcd'|['check_qlc_hrl'|['andalso_semi'|['t_tuple_size'|['binary_part']]]]]]]]]]]]]]]]]]]]]]]]]]]] +'suite'/0 = + %% Line 58 + fun () -> + [] +'groups'/0 = + %% Line 60 + fun () -> + [] +'init_per_suite'/1 = + %% Line 62 + fun (_config) -> + _config +'end_per_suite'/1 = + %% Line 64 + fun (_config) -> + 'ok' +'init_per_group'/2 = + %% Line 66 + fun (_name,_config) -> + _config +'end_per_group'/2 = + %% Line 68 + fun (_name,_config) -> + _config +'misc'/1 = + %% Line 70 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[42|[['case'|[['id'|[42]]|[['x'|[['when'|[['-'|['x']]]]|[['quote'|['ok']]]]]|[['x'|['x']]]]]]]]]}) + let <_val> = + + when try + let <_3> = + let <_2> = + call 'erlang':'-' + (_x) + in ( call 'erlang':'=:=' + (_2, 'true') + -| ['compiler_generated'] ) + in _3 + of -> + Try + catch -> + 'false' -> + 'ok' + <_x> when 'true' -> + _x + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> + in case <_val> of + <42> when 'true' -> + _val + ( <_4> when 'true' -> + primop 'match_fail' + ({'badmatch',{_4}}) + -| ['compiler_generated'] ) + end + ( <_17> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_17}) + -| [{'function_name',{'misc',1}}] ) + -| ['compiler_generated'] ) + end +'misc-1'/1 = + %% Line 93 + fun (_0) -> + case <_0> of + <[{_w},{_x},{_y},{_z}]> when 'true' -> + case 1 of + <_1> + when try + let <_4> = + let <_3> = + case call 'erlang':'>' + (_x, _y) of + <'true'> when 'true' -> + let <_2> = + call 'erlang':'abs' + (_z) + in call 'erlang':'=:=' + (_2, 2) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_3, 'true') + -| ['compiler_generated'] ) + in _4 + of -> + Try + catch -> + 'false' -> + apply 'id'/1 + (_w) + <_5> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'none' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + ( <_6> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_6}) + -| [{'function_name',{'misc-1',1}}] ) + -| ['compiler_generated'] ) + end +'get-data'/3 = + %% Line 99 + fun (_2,_1,_0) -> + case <_2,_1,_0> of + <{'o',_active,_raw},_bytes,_buffer> + when try + let <_5> = + let <_3> = + call 'erlang':'=:=' + (_raw, 'raw') + in let <_4> = + call 'erlang':'=:=' + (_raw, 0) + in call 'erlang':'or' + (_3, _4) + in _5 + of -> + Try + catch -> + 'false' -> + case 1 of + <_6> + when try + let <_8> = + let <_7> = + case call 'erlang':'=/=' + (_active, 'false') of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + call 'erlang':'=:=' + (_bytes, 0) + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_7, 'true') + -| ['compiler_generated'] ) + in _8 + of -> + Try + catch -> + 'false' -> + {'ok',_buffer,#{}#} + <_9> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + ( <_12,_11,_10> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_12,_11,_10}) + -| [{'function_name',{'get-data',3}}] ) + -| ['compiler_generated'] ) + end +'const_cond'/1 = + %% Line 104 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[['quote'|['ok']]|[['const-cond'|[{}|[0]]]]]]}) + let <_val> = + + in case <_val> of + <'ok'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_7> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_7}) + -| [{'function_name',{'const_cond',1}}] ) + -| ['compiler_generated'] ) + end +'const-cond'/2 = + %% Line 113 + fun (_t,_sz) -> + case _t of + <_0> + when try + 'false' + of -> + Try + catch -> + 'false' -> + 'never' + <_1> + when try + let <_3> = + call 'erlang':'is_tuple' + (_t) + in let <_4> = + call 'erlang':'==' + ('eq', 'eq') + in let <_5> = + let <_2> = + call 'erlang':'tuple_size' + (_t) + in call 'erlang':'==' + (_2, _sz) + in let <_6> = + call 'erlang':'and' + (_3, _4) + in call 'erlang':'and' + (_6, _5) + of -> + Try + catch -> + 'false' -> + 'ok' + <_7> + when try + let <_9> = + call 'erlang':'is_tuple' + (_t) + in let <_10> = + call 'erlang':'==' + ('eq', 'leq') + in let <_11> = + let <_8> = + call 'erlang':'tuple_size' + (_t) + in call 'erlang':'==' + (_8, _sz) + in let <_12> = + call 'erlang':'and' + (_9, _10) + in call 'erlang':'and' + (_12, _11) + of -> + Try + catch -> + 'false' -> + 'ok' + <_13> when 'true' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'basic_not'/1 = + %% Line 120 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + let <_true> = + + in let <_false> = + + in let <_glurf> = + + in let <_a> = + + in let <_b> = + + in let <_c> = + + in let <_d> = + + in let <_atuple> = + <{_false,_true,_glurf}> + in do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['check'|[['lambda'|[[]|[['eif'|[['not'|[['quote'|['false']]]]|[['quote'|['ok']]|[['quote'|['true']]|[['quote'|['error']]]]]]]]]]|[['quote'|['ok']]]]]}) + let <_5> = + fun () -> + case 1 of + <_2> + when try + let <_3> = + call 'erlang':'not' + ('false') + in _3 + of -> + Try + catch -> + 'false' -> + 'ok' + <_4> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + in apply 'check'/2 + (_5, 'ok') + ( <_128> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_128}) + -| [{'function_name',{'basic_not',1}}] ) + -| ['compiler_generated'] ) + end +'complex_not'/1 = + %% Line 164 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + let <_atuple> = + + in do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['check'|[['lambda'|[[]|[['eif'|[['not'|[['element'|[1|['atuple']]]]]|[['quote'|['ok']]|[['quote'|['true']]|[['quote'|['error']]]]]]]]]]|[['quote'|['ok']]]]]}) + let <_6> = + fun () -> + case 1 of + <_2> + when try + let <_4> = + let <_3> = + call 'erlang':'element' + (1, _atuple) + in call 'erlang':'not' + (_3) + in _4 + of -> + Try + catch -> + 'false' -> + 'ok' + <_5> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + in apply 'check'/2 + (_6, 'ok') + ( <_50> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_50}) + -| [{'function_name',{'complex_not',1}}] ) + -| ['compiler_generated'] ) + end +'nested_nots'/1 = + %% Line 191 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[['quote'|['true']]|[['nested-not-1'|[0|[0]]]]]]}) + let <_val> = + + in case <_val> of + <'true'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_18> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_18}) + -| [{'function_name',{'nested_nots',1}}] ) + -| ['compiler_generated'] ) + end +'nested-not-1'/2 = + %% Line 213 + fun (_1,_0) -> + case <_1,_0> of + <_x,_y> + when try + let <_10> = + let <_9> = + let <_7> = + let <_3> = + call 'erlang':'>' + (_x, _y) + in let <_4> = + let <_2> = + call 'erlang':'is_atom' + (_x) + in call 'erlang':'not' + (_2) + in call 'erlang':'or' + (_3, _4) + in let <_8> = + let <_5> = + call 'erlang':'is_atom' + (_y) + in let <_6> = + call 'erlang':'==' + (_x, 3.39999999999999991118e+00) + in call 'erlang':'or' + (_5, _6) + in call 'erlang':'and' + (_7, _8) + in call 'erlang':'not' + (_9) + in _10 + of -> + Try + catch -> + 'false' -> + 'true' + <_11,_12> when 'true' -> + 'false' + ( <_14,_13> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_14,_13}) + -| [{'function_name',{'nested-not-1',2}}] ) + -| ['compiler_generated'] ) + end +'nested-not-2'/3 = + %% Line 219 + fun (_x,_y,_z) -> + apply 'nested-not-2'/4 + (_x, _y, _z, 'true') +'nested-not-2'/4 = + %% Line 222 + fun (_3,_2,_1,_0) -> + case <_3,_2,_1,_0> of + <_x,_y,_z,_true> + when try + let <_12> = + let <_11> = + let <_10> = + let <_9> = + let <_7> = + let <_4> = + call 'erlang':'not' + (_x) + in let <_5> = + call 'erlang':'not' + (_y) + in call 'erlang':'and' + (_4, _5) + in let <_8> = + let <_6> = + call 'erlang':'is_atom' + (_z) + in call 'erlang':'not' + (_6) + in call 'erlang':'or' + (_7, _8) + in call 'erlang':'not' + (_9) + in call 'erlang':'and' + (_true, _10) + in call 'erlang':'not' + (_11) + in _12 + of -> + Try + catch -> + 'false' -> + 'true' + <_13,_14,_15,_16> when 'true' -> + 'false' + ( <_20,_19,_18,_17> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_20,_19,_18,_17}) + -| [{'function_name',{'nested-not-2',4}}] ) + -| ['compiler_generated'] ) + end +'semicolon'/1 = + %% Line 228 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_2> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_2}) + -| [{'function_name',{'semicolon',1}}] ) + -| ['compiler_generated'] ) + end +'complex_semicolon'/1 = + %% Line 233 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_2> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_2}) + -| [{'function_name',{'complex_semicolon',1}}] ) + -| ['compiler_generated'] ) + end +'comma'/1 = + %% Line 239 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['check'|[['lambda'|[[]|[['eif'|[['progn'|[['quote'|['true']]|[['quote'|['false']]]]]|[['quote'|['ok']]|[['quote'|['true']]|[['quote'|['error']]]]]]]]]]|[['quote'|['error']]]]]}) + let <_6> = + fun () -> + case 1 of + <_2> + when try + let <_4> = + let <_3> = + call 'erlang':'and' + ('true', 'false') + in ( call 'erlang':'=:=' + (_3, 'true') + -| ['compiler_generated'] ) + in _4 + of -> + Try + catch -> + 'false' -> + 'ok' + <_5> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + in apply 'check'/2 + (_6, 'error') + ( <_181> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_181}) + -| [{'function_name',{'comma',1}}] ) + -| ['compiler_generated'] ) + end +'or_guard'/1 = + %% Line 305 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do let <_true,_false,_glurf> = + + in do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['check'|[['lambda'|[[]|[['eif'|[['or'|[['quote'|['true']]|[['quote'|['false']]]]]|[['quote'|['ok']]]]]]]]|[['quote'|['ok']]]]]}) + let <_4> = + fun () -> + case 1 of + <_2> + when try + let <_3> = + call 'erlang':'or' + ('true', 'false') + in _3 + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + in apply 'check'/2 + (_4, 'ok') + 'ok' + ( <_64> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_64}) + -| [{'function_name',{'or_guard',1}}] ) + -| ['compiler_generated'] ) + end +'more_or_guards'/1 = + %% Line 346 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do let <_true> = + + in let <_false> = + + in let <_atuple> = + + in do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['check'|[['lambda'|[[]|[['eif'|[['or'|[['element'|[42|['atuple']]]|['false']]]|[['quote'|['ok']]|[['quote'|['true']]|[['quote'|['error']]]]]]]]]]|[['quote'|['error']]]]]}) + let <_6> = + fun () -> + case 1 of + <_2> + when try + let <_4> = + let <_3> = + call 'erlang':'element' + (42, _atuple) + in call 'erlang':'or' + (_3, _false) + in _4 + of -> + Try + catch -> + 'false' -> + 'ok' + <_5> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + in apply 'check'/2 + (_6, 'error') + 'ok' + ( <_68> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_68}) + -| [{'function_name',{'more_or_guards',1}}] ) + -| ['compiler_generated'] ) + end +'complex_or_guards'/1 = + %% Line 409 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[['quote'|['ok']]|[['complex-or-1'|[{'a','b','c','d'}|[{1,2,3}]]]]]]}) + let <_val> = + + in case <_val> of + <'ok'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_55> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_55}) + -| [{'function_name',{'complex_or_guards',1}}] ) + -| ['compiler_generated'] ) + end +'complex-or-1'/2 = + %% Line 487 + fun (_a,_b) -> + case 1 of + <_0> + when try + let <_11> = + let <_9> = + let <_3> = + let <_1> = + call 'erlang':'tuple_size' + (_a) + in call 'erlang':'<' + (3, _1) + in let <_4> = + let <_2> = + call 'erlang':'tuple_size' + (_a) + in call 'erlang':'<' + (_2, 9) + in call 'erlang':'and' + (_3, _4) + in let <_10> = + let <_7> = + let <_5> = + call 'erlang':'tuple_size' + (_b) + in call 'erlang':'<' + (2, _5) + in let <_8> = + let <_6> = + call 'erlang':'tuple_size' + (_b) + in call 'erlang':'<' + (_6, 7) + in call 'erlang':'and' + (_7, _8) + in call 'erlang':'or' + (_9, _10) + in _11 + of -> + Try + catch -> + 'false' -> + 'ok' + <_12> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'complex-or-2'/1 = + %% Line 492 + fun (_tuple) -> + case 1 of + <_0> + when try + let <_6> = + let <_4> = + call 'erlang':'element' + (1, _tuple) + in let <_5> = + let <_3> = + let <_2> = + let <_1> = + call 'erlang':'element' + (2, _tuple) + in call 'erlang':'tuple_size' + (_1) + in call 'erlang':'>' + (_2, 3) + in call 'erlang':'not' + (_3) + in call 'erlang':'or' + (_4, _5) + in _6 + of -> + Try + catch -> + 'false' -> + 'ok' + <_7> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'complex-or-3'/2 = + %% Line 496 + fun (_a,_b) -> + case 1 of + <_0> + when try + let <_5> = + let <_3> = + let <_2> = + let <_1> = + call 'erlang':'size' + (_b) + in call 'erlang':'>' + (_1, 3) + in call 'erlang':'not' + (_2) + in let <_4> = + call 'erlang':'element' + (1, _a) + in call 'erlang':'or' + (_3, _4) + in _5 + of -> + Try + catch -> + 'false' -> + 'ok' + <_6> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'complex-or-4'/2 = + %% Line 499 + fun (_a,_b) -> + case 1 of + <_0> + when try + let <_7> = + let <_5> = + let <_4> = + let <_2> = + call 'erlang':'is_tuple' + (_a) + in let <_3> = + let <_1> = + call 'erlang':'size' + (_a) + in call 'erlang':'>' + (_1, 3) + in call 'erlang':'and' + (_2, _3) + in call 'erlang':'not' + (_4) + in let <_6> = + call 'erlang':'element' + (1, _b) + in call 'erlang':'or' + (_5, _6) + in _7 + of -> + Try + catch -> + 'false' -> + 'ok' + <_8> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'complex-or-5'/2 = + %% Line 503 + fun (_a,_b) -> + case 1 of + <_0> + when try + let <_8> = + let <_6> = + let <_4> = + let <_2> = + call 'erlang':'is_tuple' + (_a) + in let <_3> = + let <_1> = + call 'erlang':'size' + (_a) + in call 'erlang':'>' + (_1, 3) + in call 'erlang':'and' + (_2, _3) + in call 'erlang':'not' + (_4) + in let <_7> = + let <_5> = + call 'erlang':'element' + (1, _b) + in call 'erlang':'not' + (_5) + in call 'erlang':'or' + (_6, _7) + in _8 + of -> + Try + catch -> + 'false' -> + 'ok' + <_9> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'complex-or-6'/2 = + %% Line 507 + fun (_a,_b) -> + case 1 of + <_0> + when try + let <_11> = + let <_9> = + let <_5> = + let <_3> = + let <_1> = + call 'erlang':'element' + (1, _a) + in call 'erlang':'not' + (_1) + in let <_4> = + let <_2> = + call 'erlang':'element' + (2, _a) + in call 'erlang':'not' + (_2) + in call 'erlang':'and' + (_3, _4) + in call 'erlang':'not' + (_5) + in let <_10> = + let <_8> = + let <_7> = + let <_6> = + call 'erlang':'size' + (_b) + in call 'erlang':'>' + (_6, 3) + in call 'erlang':'not' + (_7) + in call 'erlang':'not' + (_8) + in call 'erlang':'or' + (_9, _10) + in _11 + of -> + Try + catch -> + 'false' -> + 'ok' + <_12> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'and_guard'/1 = + %% Line 512 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['check'|[['lambda'|[[]|[['eif'|[['and'|[['quote'|['true']]|[['quote'|['false']]]]]|[['quote'|['ok']]|[['quote'|['true']]|[['quote'|['error']]]]]]]]]]|[['quote'|['error']]]]]}) + let <_5> = + fun () -> + case 1 of + <_2> + when try + let <_3> = + call 'erlang':'and' + ('true', 'false') + in _3 + of -> + Try + catch -> + 'false' -> + 'ok' + <_4> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + in apply 'check'/2 + (_5, 'error') + ( <_120> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_120}) + -| [{'function_name',{'and_guard',1}}] ) + -| ['compiler_generated'] ) + end +'relprod'/2 = + %% Line 588 + fun (_1,_0) -> + case <_1,_0> of + <_r1,_r2> + when try + let <_10> = + let <_4> = + let <_2> = + call 'erlang':'size' + (_r1) + in call 'erlang':'=:=' + (_2, 3) + in let <_5> = + let <_3> = + call 'erlang':'element' + (1, _r1) + in call 'erlang':'=:=' + (_3, 'Set') + in call 'erlang':'and' + (_4, _5) + in let <_11> = + let <_8> = + let <_6> = + call 'erlang':'size' + (_r2) + in call 'erlang':'=:=' + (_6, 3) + in let <_9> = + let <_7> = + call 'erlang':'element' + (1, _r2) + in call 'erlang':'=:=' + (_7, 'Set') + in call 'erlang':'and' + (_8, _9) + in call 'erlang':'and' + (_10, _11) + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_13,_12> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_13,_12}) + -| [{'function_name',{'relprod',2}}] ) + -| ['compiler_generated'] ) + end +'xor_guard'/1 = + %% Line 595 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['check'|[['lambda'|[[]|[['eif'|[['xor'|[['quote'|['true']]|[['quote'|['false']]]]]|[['quote'|['ok']]]]]]]]|[['quote'|['ok']]]]]}) + let <_4> = + fun () -> + case 1 of + <_2> + when try + let <_3> = + call 'erlang':'xor' + ('true', 'false') + in _3 + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + in apply 'check'/2 + (_4, 'ok') + ( <_54> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_54}) + -| [{'function_name',{'xor_guard',1}}] ) + -| ['compiler_generated'] ) + end +'more_xor_guards'/1 = + %% Line 636 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + let <_true,_false,_atuple> = + + in do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['check'|[['lambda'|[[]|[['eif'|[['xor'|[['element'|[42|['atuple']]]|['false']]]|[['quote'|['ok']]|[['quote'|['true']]|[['quote'|['error']]]]]]]]]]|[['quote'|['error']]]]]}) + let <_6> = + fun () -> + case 1 of + <_2> + when try + let <_4> = + let <_3> = + call 'erlang':'element' + (42, _atuple) + in call 'erlang':'xor' + (_3, _false) + in _4 + of -> + Try + catch -> + 'false' -> + 'ok' + <_5> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + in apply 'check'/2 + (_6, 'error') + ( <_29> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_29}) + -| [{'function_name',{'more_xor_guards',1}}] ) + -| ['compiler_generated'] ) + end +'build_in_guard'/1 = + %% Line 666 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + let <_subbin> = + <#{#<64>(8,1,'integer',['unsigned'|['big']]), + #<20>(8,1,'integer',['unsigned'|['big']]), + #<0>(8,1,'integer',['unsigned'|['big']]), + #<0>(8,1,'integer',['unsigned'|['big']]), + #<0>(8,1,'integer',['unsigned'|['big']]), + #<0>(8,1,'integer',['unsigned'|['big']]), + #<0>(8,1,'integer',['unsigned'|['big']]), + #<0>(8,1,'integer',['unsigned'|['big']])}#> + in let <_b> = + <#{#<1>(8,1,'integer',['unsigned'|['big']]), + #<_subbin>('all',8,'binary',['unsigned'|['big']]), + #<3.50000000000000000000e+00>(64,1,'float',['unsigned'|['big']])}#> + in do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[['quote'|['ok']]|[['eif'|[['=:='|['b'|[['binary'|[1|[['subbin'|['binary']]|[[3.50000000000000000000e+00|['float']]]]]]]]]|[['quote'|['ok']]]]]]]]}) + let <_val> = + + when try + let <_3> = + call 'erlang':'=:=' + (_b, #{#<1>(8,1,'integer',['unsigned'|['big']]), + #<_subbin>('all',8,'binary',['unsigned'|['big']]), + #<3.50000000000000000000e+00>(64,1,'float',['unsigned'|['big']])}#) + in _3 + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> + in case <_val> of + <'ok'> when 'true' -> + _val + ( <_4> when 'true' -> + primop 'match_fail' + ({'badmatch',{_4}}) + -| ['compiler_generated'] ) + end + ( <_5> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_5}) + -| [{'function_name',{'build_in_guard',1}}] ) + -| ['compiler_generated'] ) + end +'old_guard_tests'/1 = + %% Line 674 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_2> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_2}) + -| [{'function_name',{'old_guard_tests',1}}] ) + -| ['compiler_generated'] ) + end +'gbif'/1 = + %% Line 679 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[['quote'|['error']]|[['gbif-1'|[1|[{'false','true'}]]]]]]}) + let <_val> = + + in case <_val> of + <'error'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_4> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_4}) + -| [{'function_name',{'gbif',1}}] ) + -| ['compiler_generated'] ) + end +'gbif-1'/2 = + %% Line 685 + fun (_1,_0) -> + case <_1,_0> of + <_p,_t> + when try + let <_3> = + let <_2> = + call 'erlang':'element' + (_p, _t) + in ( call 'erlang':'=:=' + (_2, 'true') + -| ['compiler_generated'] ) + in _3 + of -> + Try + catch -> + 'false' -> + 'ok' + <_4,_5> when 'true' -> + 'error' + ( <_7,_6> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_7,_6}) + -| [{'function_name',{'gbif-1',2}}] ) + -| ['compiler_generated'] ) + end +'t_is_boolean'/1 = + %% Line 690 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[['quote'|['true']]|[['is_boolean'|[['quote'|['true']]]]]]]}) + let <_val> = + + in case <_val> of + <'true'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_70> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_70}) + -| [{'function_name',{'t_is_boolean',1}}] ) + -| ['compiler_generated'] ) + end +'bool'/1 = + %% Line 744 + fun (_0) -> + case <_0> of + <_x> + when try + let <_1> = + call 'erlang':'is_boolean' + (_x) + in _1 + of -> + Try + catch -> + 'false' -> + 'ok' + <_2> when 'true' -> + 'error' + ( <_3> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_3}) + -| [{'function_name',{'bool',1}}] ) + -| ['compiler_generated'] ) + end +'my-is-bool'/1 = + %% Line 748 + fun (_v) -> + let <_r0> = + + in case of + <_res> + when try + let <_0> = + call 'erlang':'=:=' + (_res, _r0) + in _0 + of -> + Try + catch -> + 'false' -> + _res + ( <_1> when 'true' -> + primop 'match_fail' + ({'badmatch',{_1}}) + -| ['compiler_generated'] ) + end +'my-is-bool-a'/1 = + %% Line 753 + fun (_v) -> + case _v of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + 'true' + <_0> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'my-is-bool-b'/1 = + %% Line 759 + fun (_v) -> + case _v of + <'false'> when 'true' -> + 'true' + <'true'> when 'true' -> + 'true' + <_0> when 'true' -> + 'false' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'is_function_2'/1 = + %% Line 765 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[['quote'|['true']]|[['is_function'|[['id'|[['function'|['lfe_guard_SUITE'|['all'|[1]]]]]]|[1]]]]]]}) + let <_val> = + = + let <_2> = + call 'erlang':'make_fun' + ('lfe_guard_SUITE', 'all', 1) + in apply 'id'/1 + (_2) + in call 'erlang':'is_function' + (_3, 1)> + in case <_val> of + <'true'> when 'true' -> + _val + ( <_4> when 'true' -> + primop 'match_fail' + ({'badmatch',{_4}}) + -| ['compiler_generated'] ) + end + ( <_17> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_17}) + -| [{'function_name',{'is_function_2',1}}] ) + -| ['compiler_generated'] ) + end +'tricky'/1 = + %% Line 775 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[['quote'|['not_ok']]|[['tricky-1'|[1|[2]]]]]]}) + let <_val> = + + in case <_val> of + <'not_ok'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_12> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_12}) + -| [{'function_name',{'tricky',1}}] ) + -| ['compiler_generated'] ) + end +'tricky-1'/2 = + %% Line 791 + fun (_1,_0) -> + case <_1,_0> of + <_x,_y> + when try + let <_6> = + let <_5> = + let <_4> = + let <_2> = + call 'erlang':'==' + (_x, 1) + in let <_3> = + call 'erlang':'==' + (_y, 2) + in call 'erlang':'or' + (_2, _3) + in call 'erlang':'abs' + (_4) + in ( call 'erlang':'=:=' + (_5, 'true') + -| ['compiler_generated'] ) + in _6 + of -> + Try + catch -> + 'false' -> + 'ok' + <_7,_8> when 'true' -> + 'not_ok' + ( <_10,_9> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_10,_9}) + -| [{'function_name',{'tricky-1',2}}] ) + -| ['compiler_generated'] ) + end +'tricky-2'/1 = + %% Line 795 + fun (_0) -> + case <_0> of + <_x> + when try + let <_3> = + let <_1> = + call 'erlang':'float' + (_x) + in let <_2> = + call 'erlang':'float' + (_x) + in call 'erlang':'or' + (_1, _2) + in _3 + of -> + Try + catch -> + 'false' -> + 'ok' + <_4> when 'true' -> + 'error' + ( <_5> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_5}) + -| [{'function_name',{'tricky-2',1}}] ) + -| ['compiler_generated'] ) + end +'rb'/3 = + %% Line 801 + fun (_2,_1,_0) -> + case <_2,_1,_0> of + <_size,_toread,_sofar> + when try + let <_6> = + let <_4> = + let <_3> = + call 'erlang':'+' + (_sofar, _size) + in call 'erlang':'<' + (_3, 81920) + in let <_5> = + call 'erlang':'==' + (_toread, []) + in call 'erlang':'or' + (_4, _5) + in _6 + of -> + Try + catch -> + 'false' -> + 'true' + <_7,_8,_9> when 'true' -> + 'false' + ( <_12,_11,_10> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_12,_11,_10}) + -| [{'function_name',{'rb',3}}] ) + -| ['compiler_generated'] ) + end +'rel_ops'/1 = + %% Line 830 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['T'|['=/='|[1|[1.00000000000000000000e+00]]]]}) + case + when try + let <_3> = + call 'erlang':'=/=' + (1, 1.00000000000000000000e+00) + in _3 + of -> + Try + catch -> + 'false' -> + 'ok' + <_4> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <'ok'> when 'true' -> + case + when try + let <_7> = + let <_6> = + call 'erlang':'=/=' + (1, 1.00000000000000000000e+00) + in call 'erlang':'not' + (_6) + in _7 + of -> + Try + catch -> + 'false' -> + 'error' + <_8> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <'ok'> when 'true' -> + let <_x,_y,_true,_false> = + + in case + when try + let <_10> = + call 'erlang':'=/=' + (_x, _y) + in _10 + of -> + Try + catch -> + 'false' -> + 'ok' + <_11> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <'ok'> when 'true' -> + case + when try + let <_15> = + let <_14> = + let <_13> = + call 'erlang':'=/=' + (_x, _y) + in call 'erlang':'or' + (_false, _13) + in call 'erlang':'or' + (_14, _false) + in _15 + of -> + Try + catch -> + 'false' -> + 'ok' + <_16> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <'ok'> when 'true' -> + case + when try + let <_19> = + let <_18> = + call 'erlang':'=/=' + (_x, _y) + in call 'erlang':'and' + (_18, _true) + in _19 + of -> + Try + catch -> + 'false' -> + 'ok' + <_20> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <'ok'> when 'true' -> + case + when try + let <_23> = + let <_22> = + call 'erlang':'=/=' + (_x, _y) + in call 'erlang':'not' + (_22) + in _23 + of -> + Try + catch -> + 'false' -> + 'error' + <_24> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <'ok'> when 'true' -> + case + when try + let <_29> = + let <_28> = + let <_27> = + let <_26> = + call 'erlang':'=/=' + (_x, _y) + in call 'erlang':'not' + (_26) + in call 'erlang':'or' + (_false, _27) + in call 'erlang':'or' + (_28, _false) + in _29 + of -> + Try + catch -> + 'false' -> + 'error' + <_30> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> of + <'ok'> when 'true' -> + 'ok' + ( <_31> when 'true' -> + primop 'match_fail' + ({'badmatch',{_31}}) + -| ['compiler_generated'] ) + end + ( <_32> when 'true' -> + primop 'match_fail' + ({'badmatch',{_32}}) + -| ['compiler_generated'] ) + end + ( <_33> when 'true' -> + primop 'match_fail' + ({'badmatch',{_33}}) + -| ['compiler_generated'] ) + end + ( <_34> when 'true' -> + primop 'match_fail' + ({'badmatch',{_34}}) + -| ['compiler_generated'] ) + end + ( <_35> when 'true' -> + primop 'match_fail' + ({'badmatch',{_35}}) + -| ['compiler_generated'] ) + end + ( <_36> when 'true' -> + primop 'match_fail' + ({'badmatch',{_36}}) + -| ['compiler_generated'] ) + end + ( <_37> when 'true' -> + primop 'match_fail' + ({'badmatch',{_37}}) + -| ['compiler_generated'] ) + end + ( <_769> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_769}) + -| [{'function_name',{'rel_ops',1}}] ) + -| ['compiler_generated'] ) + end +'literal_type_tests'/1 = + %% Line 873 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + case 'guard_suite' of + <'guard_suite'> when 'true' -> + apply 'literal-type-tests-1'/1 + (_config) + <_2> when 'true' -> + {'skip',[69|[110|[111|[117|[103|[104|[32|[116|[111|[32|[114|[117|[110|[32|[116|[104|[105|[115|[32|[99|[97|[115|[101|[32|[111|[110|[99|[101|[46]]]]]]]]]]]]]]]]]]]]]]]]]]]]]} + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + ( <_3> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_3}) + -| [{'function_name',{'literal_type_tests',1}}] ) + -| ['compiler_generated'] ) + end +'literal-type-tests-1'/1 = + %% Line 879 + fun (_config) -> + 'ok' +'basic_andalso_orelse'/1 = + %% Line 967 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + let <_t> = + + in do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[65|[['eif'|[['andalso'|[['=:='|[['element'|[1|['t']]]|[['quote'|['type']]]]]|[['=:='|[['tuple_size'|['t']]|[4]]]|[['=:='|[['element'|[2|['t']]]|[['quote'|['integers']]]]]]]]]|[['+'|[['element'|[3|['t']]]|[['element'|[4|['t']]]]]]|[['quote'|['true']]|[['quote'|['error']]]]]]]]]]}) + let <_val> = + + when try + let <_7> = + let <_6> = + case let <_3> = + call 'erlang':'element' + (1, _t) + in call 'erlang':'=:=' + (_3, 'type') of + <'true'> when 'true' -> + case let <_4> = + call 'erlang':'tuple_size' + (_t) + in call 'erlang':'=:=' + (_4, 4) of + <'true'> when 'true' -> + let <_5> = + call 'erlang':'element' + (2, _t) + in call 'erlang':'=:=' + (_5, 'integers') + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_6, 'true') + -| ['compiler_generated'] ) + in _7 + of -> + Try + catch -> + 'false' -> + let <_8> = + call 'erlang':'element' + (3, _t) + in let <_9> = + call 'erlang':'element' + (4, _t) + in call 'erlang':'+' + (_8, _9) + <_10> + when try + 'true' + of -> + Try + catch -> + 'false' -> + 'error' + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end> + in case <_val> of + <65> when 'true' -> + _val + ( <_11> when 'true' -> + primop 'match_fail' + ({'badmatch',{_11}}) + -| ['compiler_generated'] ) + end + ( <_47> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_47}) + -| [{'function_name',{'basic_andalso_orelse',1}}] ) + -| ['compiler_generated'] ) + end +'basic-rt'/1 = + %% Line 1020 + fun (_0) -> + case <_0> of + <_t> + when try + let <_5> = + let <_4> = + case call 'erlang':'is_tuple' + (_t) of + <'true'> when 'true' -> + case let <_1> = + call 'erlang':'tuple_size' + (_t) + in call 'erlang':'=:=' + (_1, 4) of + <'true'> when 'true' -> + case let <_2> = + call 'erlang':'element' + (1, _t) + in call 'erlang':'=:=' + (_2, 'type') of + <'true'> when 'true' -> + let <_3> = + call 'erlang':'element' + (2, _t) + in call 'erlang':'==' + (_3, 'integers') + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_4, 'true') + -| ['compiler_generated'] ) + in _5 + of -> + Try + catch -> + 'false' -> + let <_6> = + call 'erlang':'element' + (3, _t) + in let <_7> = + call 'erlang':'element' + (4, _t) + in call 'erlang':'+' + (_6, _7) + <_t> + when try + let <_11> = + let <_10> = + case call 'erlang':'is_tuple' + (_t) of + <'true'> when 'true' -> + case let <_8> = + call 'erlang':'tuple_size' + (_t) + in call 'erlang':'=:=' + (_8, 2) of + <'true'> when 'true' -> + let <_9> = + call 'erlang':'element' + (1, _t) + in call 'erlang':'=:=' + (_9, 'vector') + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_10, 'true') + -| ['compiler_generated'] ) + in _11 + of -> + Try + catch -> + 'false' -> + case of + <{_x,_y}> when 'true' -> + case 1 of + <_12> + when try + let <_16> = + let <_15> = + let <_13> = + call 'erlang':'is_float' + (_x) + in let <_14> = + call 'erlang':'is_float' + (_y) + in call 'erlang':'and' + (_13, _14) + in ( call 'erlang':'=:=' + (_15, 'true') + -| ['compiler_generated'] ) + in _16 + of -> + Try + catch -> + 'false' -> + let <_19> = + let <_17> = + call 'erlang':'*' + (_x, _x) + in let <_18> = + call 'erlang':'*' + (_y, _y) + in call 'erlang':'+' + (_17, _18) + in call 'math':'sqrt' + (_19) + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end + ( <_20> when 'true' -> + primop 'match_fail' + ({'badmatch',{_20}}) + -| ['compiler_generated'] ) + end + <['+',_a,_b]> when 'true' -> + let <_22> = + let <_21> = + call 'erlang':'+' + (_a, _b) + in apply 'id'/1 + (_21) + in call 'erlang':'*' + (_22, 2) + <{_r1,_r2}> + when try + let <_28> = + let <_27> = + case let <_23> = + call 'erlang':'size' + (_r1) + in call 'erlang':'=:=' + (_23, 3) of + <'true'> when 'true' -> + case let <_24> = + call 'erlang':'element' + (1, _r1) + in call 'erlang':'=:=' + (_24, 'Set') of + <'true'> when 'true' -> + case let <_25> = + call 'erlang':'size' + (_r2) + in call 'erlang':'=:=' + (_25, 3) of + <'true'> when 'true' -> + let <_26> = + call 'erlang':'element' + (1, _r2) + in call 'erlang':'=:=' + (_26, 'Set') + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_27, 'true') + -| ['compiler_generated'] ) + in _28 + of -> + Try + catch -> + 'false' -> + let <_r1> = + + in let <_r2> = + + in _r1 + <_t> + when try + let <_32> = + let <_31> = + case call 'erlang':'is_tuple' + (_t) of + <'true'> when 'true' -> + case let <_29> = + call 'erlang':'tuple_size' + (_t) + in call 'erlang':'=:=' + (_29, 2) of + <'true'> when 'true' -> + let <_30> = + call 'erlang':'element' + (1, _t) + in call 'erlang':'=:=' + (_30, 'klurf') + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_31, 'true') + -| ['compiler_generated'] ) + in _32 + of -> + Try + catch -> + 'false' -> + let <_34> = + let <_33> = + call 'erlang':'element' + (2, _t) + in apply 'id'/1 + (_33) + in call 'erlang':'*' + (3, _34) + <_35> when 'true' -> + 'error' + ( <_36> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_36}) + -| [{'function_name',{'basic-rt',1}}] ) + -| ['compiler_generated'] ) + end +'traverse_dcd'/1 = + %% Line 1043 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + let <_l0> = + <[{'log_header','dcd_log',[49|[46|[48]]],'a','b','c'}|[{'log_header','dcd_log',[50|[46|[48]]],'a','b','c'}|[{'log_header','dcd_log',[48|[46|[48]]],'a','b','c'}|['blurf']]]]> + in case of + <{'cont',[{'log_header','dcd_log',[48|[46|[48]]],'a','b','c'}|['blurf']],'log','funny'}> when 'true' -> + let <_l1> = + <[{'log_header','dcd_log',[49|[46|[48]]]}]> + in case of + <{'cont',_l1,'log','funny'}> when 'true' -> + let <_l2> = + <[{'a','tuple'}]> + in case of + <{'cont',_l2,'log','funny'}> when 'true' -> + 'ok' + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_3> when 'true' -> + primop 'match_fail' + ({'badmatch',{_3}}) + -| ['compiler_generated'] ) + end + ( <_4> when 'true' -> + primop 'match_fail' + ({'badmatch',{_4}}) + -| ['compiler_generated'] ) + end + ( <_5> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_5}) + -| [{'function_name',{'traverse_dcd',1}}] ) + -| ['compiler_generated'] ) + end +'traverse-dcd'/3 = + %% Line 1066 + fun (_2,_1,_0) -> + case <_2,_1,_0> of + <{_cont,[_logh|_rest]},_log,_fun> + when try + let <_11> = + let <_6> = + case call 'erlang':'is_tuple' + (_logh) of + <'true'> when 'true' -> + case let <_3> = + call 'erlang':'tuple_size' + (_logh) + in call 'erlang':'=:=' + (_3, 6) of + <'true'> when 'true' -> + case let <_4> = + call 'erlang':'element' + (1, _logh) + in call 'erlang':'=:=' + (_4, 'log_header') of + <'true'> when 'true' -> + let <_5> = + call 'erlang':'element' + (2, _logh) + in call 'erlang':'==' + (_5, 'dcd_log') + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_6, 'true') + -| ['compiler_generated'] ) + in let <_12> = + let <_10> = + case call 'erlang':'is_tuple' + (_logh) of + <'true'> when 'true' -> + case let <_7> = + call 'erlang':'tuple_size' + (_logh) + in call 'erlang':'=:=' + (_7, 6) of + <'true'> when 'true' -> + case let <_8> = + call 'erlang':'element' + (1, _logh) + in call 'erlang':'=:=' + (_8, 'log_header') of + <'true'> when 'true' -> + let <_9> = + call 'erlang':'element' + (3, _logh) + in call 'erlang':'>=' + (_9, [49|[46|[48]]]) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in ( call 'erlang':'=:=' + (_10, 'true') + -| ['compiler_generated'] ) + in call 'erlang':'and' + (_11, _12) + of -> + Try + catch -> + 'false' -> + apply 'traverse-dcd'/3 + ({_cont,_rest}, _log, _fun) + <{_cont,_recs},_log,_fun> when 'true' -> + {_cont,_recs,_log,_fun} + ( <_15,_14,_13> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_15,_14,_13}) + -| [{'function_name',{'traverse-dcd',3}}] ) + -| ['compiler_generated'] ) + end +'check_qlc_hrl'/1 = + %% Line 1078 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + let <_st> = + <{'r1','false','dum'}> + in do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[['quote'|['foo']]|[['cqlc'|[['quote'|['qlc']]|[['quote'|['q']]|[['quote'|[[{'lc',1,2,3}]]]|['st']]]]]]]]}) + let <_val> = + + in case <_val> of + <'foo'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_5> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_5}) + -| [{'function_name',{'check_qlc_hrl',1}}] ) + -| ['compiler_generated'] ) + end +'cqlc'/4 = + %% Line 1094 + fun (_m,_f,_as,_st) -> + let <_arity> = + + in case _as of + <[{'lc',_0,_1,_2}|_3]> + when try + let <_11> = + call 'erlang':'=:=' + (_m, 'qlc') + in let <_12> = + call 'erlang':'=:=' + (_f, 'q') + in let <_13> = + call 'erlang':'<' + (_arity, 3) + in let <_14> = + let <_10> = + let <_8> = + case let <_4> = + call 'erlang':'element' + (1, _st) + in call 'erlang':'=:=' + (_4, 'r1') of + <'true'> when 'true' -> + 'true' + <'false'> when 'true' -> + 'fail' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in let <_9> = + let <_6> = + let <_5> = + call 'erlang':'tuple_size' + (_st) + in call 'erlang':'=:=' + (_5, 3) + in let <_7> = + call 'erlang':'element' + (2, _st) + in call 'erlang':'and' + (_6, _7) + in call 'erlang':'and' + (_8, _9) + in call 'erlang':'not' + (_10) + in let <_15> = + call 'erlang':'and' + (_11, _12) + in let <_16> = + call 'erlang':'and' + (_15, _13) + in call 'erlang':'and' + (_16, _14) + of -> + Try + catch -> + 'false' -> + 'foo' + <_17> when 'true' -> + _st + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'andalso_semi'/1 = + %% Line 1106 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[['quote'|['ok']]|[['andalso-semi-foo'|[0]]]]]}) + let <_val> = + + in case <_val> of + <'ok'> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_8> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_8}) + -| [{'function_name',{'andalso_semi',1}}] ) + -| ['compiler_generated'] ) + end +'andalso-semi-foo'/1 = + %% Line 1117 + fun (_0) -> + case <_0> of + <_bar> + when try + let <_3> = + let <_1> = + case call 'erlang':'is_integer' + (_bar) of + <'true'> when 'true' -> + call 'erlang':'=:=' + (_bar, 0) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in let <_2> = + call 'erlang':'=:=' + (_bar, 1) + in call 'erlang':'or' + (_1, _2) + in _3 + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_4> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_4}) + -| [{'function_name',{'andalso-semi-foo',1}}] ) + -| ['compiler_generated'] ) + end +'andalso-semi-bar'/1 = + %% Line 1121 + fun (_0) -> + case <_0> of + <_bar> + when try + let <_4> = + let <_2> = + case call 'erlang':'is_list' + (_bar) of + <'true'> when 'true' -> + let <_1> = + call 'erlang':'length' + (_bar) + in call 'erlang':'=:=' + (_1, 3) + <'false'> when 'true' -> + 'false' + ( <_omega> when 'true' -> + _omega + -| ['compiler_generated'] ) + end + in let <_3> = + call 'erlang':'=:=' + (_bar, 1) + in call 'erlang':'or' + (_2, _3) + in _4 + of -> + Try + catch -> + 'false' -> + 'ok' + ( <_5> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_5}) + -| [{'function_name',{'andalso-semi-bar',1}}] ) + -| ['compiler_generated'] ) + end +'t_tuple_size'/1 = + %% Line 1125 + fun (_0) -> + case <_0> of + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat'|[10|[['do-tuple-size'|[{1,2,3,4}]]]]]}) + let <_val> = + + in case <_val> of + <10> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_7> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_7}) + -| [{'function_name',{'t_tuple_size',1}}] ) + -| ['compiler_generated'] ) + end +'do-tuple-size'/1 = + %% Line 1139 + fun (_0) -> + case <_0> of + <_t> + when try + let <_2> = + let <_1> = + call 'erlang':'tuple_size' + (_t) + in call 'erlang':'=:=' + (_1, 4) + in _2 + of -> + Try + catch -> + 'false' -> + case <_t> of + <{_a,_b,_c,_d}> when 'true' -> + let <_lfe0> = + <_a> + in let <_lfe1> = + <_b> + in let <_lfe2> = + <_c> + in let <_lfe3> = + <_d> + in let <_4> = + let <_3> = + call 'erlang':'+' + (_lfe0, _lfe1) + in call 'erlang':'+' + (_3, _lfe2) + in call 'erlang':'+' + (_4, _lfe3) + ( <_5> when 'true' -> + primop 'match_fail' + ({'badmatch',{_5}}) + -| ['compiler_generated'] ) + end + ( <_6> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_6}) + -| [{'function_name',{'do-tuple-size',1}}] ) + -| ['compiler_generated'] ) + end +'ludicrous-tuple-size'/1 = + %% Line 1144 + fun (_0) -> + case <_0> of + <_t> + when try + let <_2> = + let <_1> = + call 'erlang':'tuple_size' + (_t) + in call 'erlang':'=:=' + (_1, 40652400101488115101757819767848575661943) + in _2 + of -> + Try + catch -> + 'false' -> + 'ok' + <_t> + when try + let <_4> = + let <_3> = + call 'erlang':'tuple_size' + (_t) + in call 'erlang':'=:=' + (_3, 18446744073709551616) + in _4 + of -> + Try + catch -> + 'false' -> + 'ok' + <_t> + when try + let <_8> = + let <_6> = + call 'erlang':'tuple_size' + (_t) + in let <_7> = + let <_5> = + call 'erlang':'bsl' + (1, 64) + in call 'erlang':'-' + (_5, 1) + in call 'erlang':'=:=' + (_6, _7) + in _8 + of -> + Try + catch -> + 'false' -> + 'ok' + <_t> + when try + let <_10> = + let <_9> = + call 'erlang':'tuple_size' + (_t) + in call 'erlang':'=:=' + (_9, 18446744073709551615) + in _10 + of -> + Try + catch -> + 'false' -> + 'ok' + <_11> when 'true' -> + 'error' + ( <_12> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_12}) + -| [{'function_name',{'ludicrous-tuple-size',1}}] ) + -| ['compiler_generated'] ) + end +'mask-error'/1 = + %% Line 1152 + fun (_0) -> + case <_0> of + <{'EXIT',{_err,_1}}> when 'true' -> + _err + <_else> when 'true' -> + _else + ( <_2> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_2}) + -| [{'function_name',{'mask-error',1}}] ) + -| ['compiler_generated'] ) + end +'binary_part'/1 = + %% Line 1156 + fun (_0) -> + case <_0> of + <'doc'> when 'true' -> + [84|[101|[115|[116|[115|[32|[116|[104|[101|[32|[98|[105|[110|[97|[114|[121|[95|[112|[97|[114|[116|[47|[50|[44|[51|[32|[103|[117|[97|[114|[100|[32|[40|[71|[67|[41|[32|[98|[105|[102|[39|[115]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] + <_config> + when try + let <_1> = + call 'erlang':'is_list' + (_config) + in _1 + of -> + Try + catch -> + 'false' -> + do call 'erlang':'put' + ('test_server_loc', {'lfe_guard_SUITE',['test-pat',1,['bp-test',#{#<1>(8,1,'integer',['unsigned'|['big']]), + #<2>(8,1,'integer',['unsigned'|['big']]), + #<3>(8,1,'integer',['unsigned'|['big']])}#]]}) + let <_val> = + (8,1,'integer',['unsigned'|['big']]), + #<2>(8,1,'integer',['unsigned'|['big']]), + #<3>(8,1,'integer',['unsigned'|['big']])}#)> + in case <_val> of + <1> when 'true' -> + _val + ( <_2> when 'true' -> + primop 'match_fail' + ({'badmatch',{_2}}) + -| ['compiler_generated'] ) + end + ( <_53> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_53}) + -| [{'function_name',{'binary_part',1}}] ) + -| ['compiler_generated'] ) + end +'bp-test'/1 = + %% Line 1225 + fun (_0) -> + case <_0> of + <_b> + when try + let <_2> = + let <_1> = + call 'erlang':'length' + (_b) + in call 'erlang':'=:=' + (_1, 137) + in _2 + of -> + Try + catch -> + 'false' -> + 1 + <_b> + when try + let <_4> = + let <_3> = + call 'erlang':'binary_part' + (_b, {1,1}) + in call 'erlang':'=:=' + (_3, #{#<2>(8,1,'integer',['unsigned'|['big']])}#) + in _4 + of -> + Try + catch -> + 'false' -> + 1 + <_b> + when try + let <_6> = + let <_5> = + call 'erlang':'binary_part' + (_b, 1, 1) + in call 'erlang':'=:=' + (_5, #{#<1>(8,1,'integer',['unsigned'|['big']])}#) + in _6 + of -> + Try + catch -> + 'false' -> + 2 + <_b> + when try + let <_8> = + let <_7> = + call 'erlang':'binary_part' + (_b, {1,2}) + in call 'erlang':'=:=' + (_7, #{#<3>(8,1,'integer',['unsigned'|['big']]), + #<3>(8,1,'integer',['unsigned'|['big']])}#) + in _8 + of -> + Try + catch -> + 'false' -> + 3 + <_9> when 'true' -> + 'error' + ( <_10> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_10}) + -| [{'function_name',{'bp-test',1}}] ) + -| ['compiler_generated'] ) + end +'bp-test'/2 = + %% Line 1232 + fun (_1,_0) -> + case <_1,_0> of + <_b,_a> + when try + let <_3> = + let <_2> = + call 'erlang':'length' + (_b) + in call 'erlang':'=:=' + (_2, _a) + in _3 + of -> + Try + catch -> + 'false' -> + 1 + <_b,_a> + when try + let <_5> = + let <_4> = + call 'erlang':'binary_part' + (_b, {_a,1}) + in call 'erlang':'=:=' + (_4, #{#<2>(8,1,'integer',['unsigned'|['big']])}#) + in _5 + of -> + Try + catch -> + 'false' -> + 1 + <_b,_a> + when try + let <_7> = + let <_6> = + call 'erlang':'binary_part' + (_b, _a, 1) + in call 'erlang':'=:=' + (_6, #{#<1>(8,1,'integer',['unsigned'|['big']])}#) + in _7 + of -> + Try + catch -> + 'false' -> + 2 + <_b,_a> + when try + let <_9> = + let <_8> = + call 'erlang':'binary_part' + (_b, {_a,2}) + in call 'erlang':'=:=' + (_8, #{#<3>(8,1,'integer',['unsigned'|['big']]), + #<3>(8,1,'integer',['unsigned'|['big']])}#) + in _9 + of -> + Try + catch -> + 'false' -> + 3 + <_10,_11> when 'true' -> + 'error' + ( <_13,_12> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_13,_12}) + -| [{'function_name',{'bp-test',2}}] ) + -| ['compiler_generated'] ) + end +'bp-test-x'/2 = + %% Line 1239 + fun (_1,_0) -> + case <_1,_0> of + <_b,_a> + when try + let <_3> = + let <_2> = + call 'erlang':'length' + (_b) + in call 'erlang':'=:=' + (_2, _a) + in _3 + of -> + Try + catch -> + 'false' -> + 1 + <_b,_a> + when try + let <_5> = + let <_4> = + call 'erlang':'binary_part' + (_b, _a) + in call 'erlang':'=:=' + (_4, #{#<2>(8,1,'integer',['unsigned'|['big']])}#) + in _5 + of -> + Try + catch -> + 'false' -> + 1 + <_b,_a> + when try + let <_7> = + let <_6> = + call 'erlang':'binary_part' + (_b, _a) + in call 'erlang':'=:=' + (_6, #{#<1>(8,1,'integer',['unsigned'|['big']])}#) + in _7 + of -> + Try + catch -> + 'false' -> + 2 + <_b,_a> + when try + let <_9> = + let <_8> = + call 'erlang':'binary_part' + (_b, _a) + in call 'erlang':'=:=' + (_8, #{#<3>(8,1,'integer',['unsigned'|['big']]), + #<3>(8,1,'integer',['unsigned'|['big']])}#) + in _9 + of -> + Try + catch -> + 'false' -> + 3 + <_10,_11> when 'true' -> + 'error' + ( <_13,_12> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_13,_12}) + -| [{'function_name',{'bp-test-x',2}}] ) + -| ['compiler_generated'] ) + end +'bp-test-y'/2 = + %% Line 1246 + fun (_1,_0) -> + case <_1,_0> of + <_b,_a> + when try + let <_3> = + let <_2> = + call 'erlang':'length' + (_b) + in call 'erlang':'=:=' + (_2, _a) + in _3 + of -> + Try + catch -> + 'false' -> + 1 + <_b,_a> + when try + let <_5> = + let <_4> = + call 'erlang':'binary_part' + (_b, {1,_a}) + in call 'erlang':'=:=' + (_4, #{#<2>(8,1,'integer',['unsigned'|['big']])}#) + in _5 + of -> + Try + catch -> + 'false' -> + 1 + <_b,_a> + when try + let <_7> = + let <_6> = + call 'erlang':'binary_part' + (_b, 1, _a) + in call 'erlang':'=:=' + (_6, #{#<1>(8,1,'integer',['unsigned'|['big']])}#) + in _7 + of -> + Try + catch -> + 'false' -> + 2 + <_b,_a> + when try + let <_9> = + let <_8> = + call 'erlang':'binary_part' + (_b, {1,_a}) + in call 'erlang':'=:=' + (_8, #{#<3>(8,1,'integer',['unsigned'|['big']]), + #<3>(8,1,'integer',['unsigned'|['big']])}#) + in _9 + of -> + Try + catch -> + 'false' -> + 3 + <_10,_11> when 'true' -> + 'error' + ( <_13,_12> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_13,_12}) + -| [{'function_name',{'bp-test-y',2}}] ) + -| ['compiler_generated'] ) + end +'bp-test'/3 = + %% Line 1253 + fun (_2,_1,_0) -> + case <_2,_1,_0> of + <_b,_a,_3> + when try + let <_5> = + let <_4> = + call 'erlang':'length' + (_b) + in call 'erlang':'=:=' + (_4, _a) + in _5 + of -> + Try + catch -> + 'false' -> + 1 + <_b,_a,_c> + when try + let <_7> = + let <_6> = + call 'erlang':'binary_part' + (_b, {_a,_c}) + in call 'erlang':'=:=' + (_6, #{#<2>(8,1,'integer',['unsigned'|['big']])}#) + in _7 + of -> + Try + catch -> + 'false' -> + 1 + <_b,_a,_c> + when try + let <_9> = + let <_8> = + call 'erlang':'binary_part' + (_b, _a, _c) + in call 'erlang':'=:=' + (_8, #{#<1>(8,1,'integer',['unsigned'|['big']])}#) + in _9 + of -> + Try + catch -> + 'false' -> + 2 + <_b,_a,_c> + when try + let <_11> = + let <_10> = + call 'erlang':'binary_part' + (_b, {_a,_c}) + in call 'erlang':'=:=' + (_10, #{#<3>(8,1,'integer',['unsigned'|['big']]), + #<3>(8,1,'integer',['unsigned'|['big']])}#) + in _11 + of -> + Try + catch -> + 'false' -> + 3 + <_12,_13,_14> when 'true' -> + 'error' + ( <_17,_16,_15> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_17,_16,_15}) + -| [{'function_name',{'bp-test',3}}] ) + -| ['compiler_generated'] ) + end +'id'/1 = + %% Line 1262 + fun (_i) -> + _i +'check'/2 = + %% Line 1264 + fun (_f,_result) -> + case apply _f + () of + <_r> + when try + let <_0> = + call 'erlang':'=:=' + (_r, _result) + in _0 + of -> + Try + catch -> + 'false' -> + 'ok' + <_other> when 'true' -> + do call 'lfe_io':'format' + ([69|[120|[112|[101|[99|[116|[101|[100|[58|[32|[126|[112|[10]]]]]]]]]]]]], [_result]) + do call 'lfe_io':'format' + ([32|[32|[32|[32|[32|[71|[111|[116|[58|[32|[126|[112|[10]]]]]]]]]]]]], [_other]) + call 'test_server':'fail' + () + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'fc'/1 = + %% Line 1272 + fun (_0) -> + case <_0> of + <{'EXIT',{'function_clause'}}> when 'true' -> + 'ok' + <{'EXIT',{{'case_clause',_1},_2}}> when 'true' -> + 'ok' + ( <_3> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_3}) + -| [{'function_name',{'fc',1}}] ) + -| ['compiler_generated'] ) + end +'$handle_undefined_function'/2 = + %% Line 29 + fun (_f,_as) -> + case let <_0> = + call 'lfe_env':'new' + () + in apply 'LFE-EXPAND-EXPORTED-MACRO'/3 + (_f, _as, _0) of + <{'yes',_exp}> when 'true' -> + call 'lfe_eval':'expr' + (_exp) + <'no'> when 'true' -> + let <_a,_b> = + <_f,_as> + in call 'error_handler':'raise_undef_exception' + ('lfe_guard_SUITE', _a, _b) + ( <_omega> when 'true' -> + primop 'match_fail' + ({'case_clause',_omega}) + -| ['compiler_generated'] ) + end +'LFE-EXPAND-EXPORTED-MACRO'/3 = + %% Line 29 + fun (_2,_1,_0) -> + 'no' +'module_info'/0 = + fun () -> + call 'erlang':'get_module_info' + ('lfe_guard_SUITE') +'module_info'/1 = + fun (_x) -> + call 'erlang':'get_module_info' + ('lfe_guard_SUITE', _x) +end -- cgit v1.2.3 From 9f3c69458c1258c21e44c35d487eceb2394fab74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 11 Oct 2016 08:51:11 +0200 Subject: beam_dead: Remove redundant 'bif' instructions A 'bif' or 'gc_bif' instruction is redundant if it has the same failure label as a 'jump' instruction immediately following it. There is no need to test for liveness of the destination register, because the code at the failure label cannot safely assume that the destination register is initialized. See the comments in the code for further details. In practice, this optimization will only apply to contrived guards that are almost never used in real applications. The only reason we add this optimization is to help approach the goal of zero tolerance for 'bif' instructions instead of 'test' instructions in guards. --- lib/compiler/src/beam_dead.erl | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index 3606af9d75..8ea949425e 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -266,12 +266,30 @@ backward([{jump,{f,To0}},{move,Src,Reg}=Move|Is], D, Acc) -> false -> backward([Move|Is], D, [Jump|Acc]); true -> backward([Jump|Is], D, Acc) end; -backward([{jump,{f,To}}=J|[{bif,Op,_,Ops,Reg}|Is]=Is0], D, Acc) -> +backward([{jump,{f,To}}=J|[{bif,Op,{f,BifFail},Ops,Reg}|Is]=Is0], D, Acc) -> try replace_comp_op(To, Reg, Op, Ops, D) of I -> backward(Is, D, I++Acc) catch - throw:not_possible -> backward(Is0, D, [J|Acc]) + throw:not_possible -> + case To =:= BifFail of + true -> + %% The bif instruction is redundant. See the comment + %% in the next clause for why there is no need to + %% test for liveness of Reg at label To. + backward([J|Is], D, Acc); + false -> + backward(Is0, D, [J|Acc]) + end end; +backward([{jump,{f,To}}=J|[{gc_bif,_,{f,To},_,_,_Dst}|Is]], D, Acc) -> + %% The gc_bif instruction is redundant, since either the gc_bif + %% instruction itself or the jump instruction will transfer control + %% to label To. Note that a gc_bif instruction does not assign its + %% destination register if the failure branch is taken; therefore, + %% the code at label To is not allowed to assume that the destination + %% register is initialized, and it is therefore no need to test + %% for liveness of the destination register at label To. + backward([J|Is], D, Acc); backward([{test,bs_start_match2,F,Live,[R,_]=Args,Ctxt}|Is], D, [{test,bs_match_string,F,[Ctxt,Bs]}, {test,bs_test_tail2,F,[Ctxt,0]}|Acc0]=Acc) -> -- cgit v1.2.3 From 4c76ea1116faa3efd797c39539131b9262b6fa36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Sat, 12 Nov 2016 12:31:31 +0100 Subject: beam_dead: Remove redundant 'or' instruction In practice, this optimization will only apply to contrived guards that are almost never used in real applications. The only reason we add this optimization is to help approach the goal of zero tolerance for 'bif' instructions instead of 'test' instructions in guards. --- lib/compiler/src/beam_dead.erl | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib') diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index 8ea949425e..9087586b58 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -379,6 +379,14 @@ backward([{kill,_}=I|Is], D, [{line,_},Exit|_]=Acc) -> false -> backward(Is, D, [I|Acc]); true -> backward(Is, D, Acc) end; +backward([{bif,'or',{f,To0},[Dst,{atom,false}],Dst}=I|Is], D, + [{test,is_eq_exact,{f,To},[Dst,{atom,true}]}|_]=Acc) -> + case shortcut_label(To0, D) of + To -> + backward(Is, D, Acc); + _ -> + backward(Is, D, [I|Acc]) + end; backward([I|Is], D, Acc) -> backward(Is, D, [I|Acc]); backward([], _D, Acc) -> Acc. @@ -397,6 +405,8 @@ shortcut_select_list([Lit,{f,To0}|T], Reg, D, Acc) -> shortcut_select_list(T, Reg, D, [{f,To},Lit|Acc]); shortcut_select_list([], _, _, Acc) -> reverse(Acc). +shortcut_label(0, _) -> + 0; shortcut_label(To0, D) -> case beam_utils:code_at(To0, D) of [{jump,{f,To}}|_] -> shortcut_label(To, D); -- cgit v1.2.3 From 09f170e35cf9df8438ae42d48b51becff167b5b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 12 Oct 2016 08:00:22 +0200 Subject: compile_SUITE: Make sure that guards are optimized Guards should use the more efficient 'test' instructions, not 'bif' instructions. Add a test to make sure that the optimizations don't degrade. We do have to keep an exception list for functions where we can't replace all 'bif' calls with 'test' instructions. We try to keep that list a short as practically possible. --- lib/compiler/test/compile_SUITE.erl | 94 ++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index a2d3e2140b..e2988b18dc 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -32,7 +32,7 @@ other_output/1, kernel_listing/1, encrypted_abstr/1, strict_record/1, cover/1, env/1, core/1, - core_roundtrip/1, asm/1, + core_roundtrip/1, asm/1, optimized_guards/1, sys_pre_attributes/1, dialyzer/1, warnings/1, pre_load_check/1, env_compiler_options/1 ]). @@ -49,7 +49,7 @@ all() -> binary, makedep, cond_and_ifdef, listings, listings_big, other_output, kernel_listing, encrypted_abstr, strict_record, - cover, env, core, core_roundtrip, asm, + cover, env, core, core_roundtrip, asm, optimized_guards, sys_pre_attributes, dialyzer, warnings, pre_load_check, env_compiler_options]. @@ -926,6 +926,96 @@ do_asm(Beam, Outdir) -> error end. +%% Make sure that guards are fully optimized. Guards should +%% should use 'test' instructions, not 'bif' instructions. + +optimized_guards(_Config) -> + TestBeams = get_unique_beam_files(), + test_lib:p_run(fun(F) -> do_opt_guards(F) end, TestBeams). + +do_opt_guards(Beam) -> + {ok,{M,[{abstract_code,{raw_abstract_v1,A}}]}} = + beam_lib:chunks(Beam, [abstract_code]), + try + {ok,M,Asm} = compile:forms(A, ['S']), + do_opt_guards_mod(Asm) + catch Class:Error -> + io:format("~p: ~p ~p\n~p\n", + [M,Class,Error,erlang:get_stacktrace()]), + error + end. + +do_opt_guards_mod({Mod,_Exp,_Attr,Asm,_NumLabels}) -> + case do_opt_guards_fs(Mod, Asm) of + [] -> + ok; + [_|_]=Bifs -> + io:format("ERRORS FOR ~p:\n~p\n", [Mod,Bifs]), + error + end. + +do_opt_guards_fs(Mod, [{function,Name,Arity,_,Is}|Fs]) -> + Bifs0 = do_opt_guards_fun(Is), + + %% The compiler does not attempt to optimize 'xor'. + %% Therefore, ignore all functions that use 'xor' in + %% a guard. + Bifs = case lists:any(fun({bif,'xor',_,_,_}) -> true; + (_) -> false + end, Bifs0) of + true -> []; + false -> Bifs0 + end, + + %% Filter out the allowed exceptions. + FA = {Name,Arity}, + case {Bifs,is_exception(Mod, FA)} of + {[_|_],true} -> + io:format("~p:~p/~p IGNORED:\n~p\n", + [Mod,Name,Arity,Bifs]), + do_opt_guards_fs(Mod, Fs); + {[_|_],false} -> + [{FA,Bifs}|do_opt_guards_fs(Mod, Fs)]; + {[],false} -> + do_opt_guards_fs(Mod, Fs); + {[],true} -> + io:format("Redundant exception for ~p:~p/~p\n", + [Mod,Name,Arity]), + error(redundant) + end; +do_opt_guards_fs(_, []) -> []. + +do_opt_guards_fun([{bif,Name,{f,F},As,_}=I|Is]) when F =/= 0 -> + Arity = length(As), + case erl_internal:comp_op(Name, Arity) orelse + erl_internal:bool_op(Name, Arity) orelse + erl_internal:new_type_test(Name, Arity) of + true -> + [I|do_opt_guards_fun(Is)]; + false -> + do_opt_guards_fun(Is) + end; +do_opt_guards_fun([_|Is]) -> + do_opt_guards_fun(Is); +do_opt_guards_fun([]) -> []. + +is_exception(bs_match_SUITE, {matching_and_andalso_2,2}) -> true; +is_exception(bs_match_SUITE, {matching_and_andalso_3,2}) -> true; +is_exception(guard_SUITE, {'-complex_not/1-fun-4-',1}) -> true; +is_exception(guard_SUITE, {'-complex_not/1-fun-5-',1}) -> true; +is_exception(guard_SUITE, {basic_andalso_orelse,1}) -> true; +is_exception(guard_SUITE, {bad_guards,1}) -> true; +is_exception(guard_SUITE, {bad_guards_2,2}) -> true; +is_exception(guard_SUITE, {bad_guards_3,2}) -> true; +is_exception(guard_SUITE, {cqlc,4}) -> true; +is_exception(guard_SUITE, {csemi7,3}) -> true; +is_exception(guard_SUITE, {misc,1}) -> true; +is_exception(guard_SUITE, {nested_not_2b,4}) -> true; +is_exception(guard_SUITE, {tricky_1,2}) -> true; +is_exception(map_SUITE, {map_guard_update,2}) -> true; +is_exception(map_SUITE, {map_guard_update_variables,3}) -> true; +is_exception(_, _) -> false. + sys_pre_attributes(Config) -> DataDir = proplists:get_value(data_dir, Config), File = filename:join(DataDir, "attributes.erl"), -- cgit v1.2.3