Add DBG_DEF for switch pattern vars

This commit is contained in:
Gaith Hallak 2023-04-08 12:02:08 +03:00
parent f6730bd274
commit ccc6d98fe9
2 changed files with 30 additions and 30 deletions

View File

@ -87,7 +87,7 @@
| {lam, fann(), [var_name()], fexpr()}.
-type fsplit() :: {split, ftype(), var_name(), [fcase()]}
| {nosplit, fexpr()}.
| {nosplit, [rename()], fexpr()}. %% Renames are needed to add DBG_DEF for switch pattern vars
-type fcase() :: {'case', fsplit_pat(), fsplit()}.
@ -821,8 +821,8 @@ expr_to_fcode(_Env, Type, Expr) ->
-spec make_if(fexpr(), fexpr(), fexpr()) -> fexpr().
make_if({var, FAnn, X}, Then, Else) ->
{switch, FAnn, {split, boolean, X,
[{'case', {bool, false}, {nosplit, Else}},
{'case', {bool, true}, {nosplit, Then}}]}};
[{'case', {bool, false}, {nosplit, [], Else}},
{'case', {bool, true}, {nosplit, [], Then}}]}};
make_if(Cond, Then, Else) ->
X = fresh_name(),
FAnn = get_fann(Cond),
@ -831,7 +831,7 @@ make_if(Cond, Then, Else) ->
-spec make_if_no_else(fexpr(), fexpr()) -> fexpr().
make_if_no_else({var, FAnn, X}, Then) ->
{switch, FAnn, {split, boolean, X,
[{'case', {bool, true}, {nosplit, Then}}]}};
[{'case', {bool, true}, {nosplit, [], Then}}]}};
make_if_no_else(Cond, Then) ->
X = fresh_name(),
FAnn = get_fann(Cond),
@ -927,7 +927,7 @@ split_tree(Env, Vars, Alts = [{'case', Pats, Body} | _]) ->
Ys = [ Y || {var, Y} <- Pats ],
Ren = [ {Y, X} || {Y, X} <- lists:zip(Ys, Xs), X /= Y, Y /= "_" ],
%% TODO: Unreachable clauses error
{nosplit, rename(Ren, Body)};
{nosplit, Ren, rename(Ren, Body)};
I when is_integer(I) ->
{Vars0, [{X, Type} | Vars1]} = lists:split(I - 1, Vars),
Type1 = strip_singleton_tuples(Type),
@ -1123,8 +1123,8 @@ decision_tree_to_fcode({atom, B}) -> B;
decision_tree_to_fcode({'if', A, Then, Else}) ->
X = fresh_name(),
{'let', get_fann(A), X, A,
{switch, get_fann(A), {split, boolean, X, [{'case', {bool, false}, {nosplit, decision_tree_to_fcode(Else)}},
{'case', {bool, true}, {nosplit, decision_tree_to_fcode(Then)}}]}}}.
{switch, get_fann(A), {split, boolean, X, [{'case', {bool, false}, {nosplit, [], decision_tree_to_fcode(Else)}},
{'case', {bool, true}, {nosplit, [], decision_tree_to_fcode(Then)}}]}}}.
%% -- Statements --
@ -1262,7 +1262,7 @@ event_function(_Env = #{event_type := {variant_t, EventCons}}, EventType = {vari
end,
Indices = [ {var, [], V} || {indexed, V} <- IVars ],
Body = {builtin, [], chain_event, [Payload, Hash | Indices]},
{'case', {con, [], Arities, Tag, Vars}, {nosplit, Body}}
{'case', {con, [], Arities, Tag, Vars}, {nosplit, [], Body}}
end,
#{ attrs => [private],
args => [{"e", EventType}],
@ -1369,7 +1369,7 @@ lambda_lift_expr(Layout, Expr) ->
{get_state, _, _} -> Expr;
{switch, FAnn, S} -> {switch, FAnn, lambda_lift_expr(Layout, S)};
{split, Type, X, Alts} -> {split, Type, X, lambda_lift_exprs(Layout, Alts)};
{nosplit, A} -> {nosplit, lambda_lift_expr(Layout, A)};
{nosplit, Rens, A} -> {nosplit, Rens, lambda_lift_expr(Layout, A)};
{'case', P, S} -> {'case', P, lambda_lift_expr(Layout, S)}
end.
@ -1601,12 +1601,12 @@ add_catchalls(Alts, Catchalls) ->
end.
-spec nest_catchalls([fcase()]) -> fcase().
nest_catchalls([C = {'case', {var, _}, {nosplit, _}} | _]) -> C;
nest_catchalls([C = {'case', {var, _}, {nosplit, _, _}} | _]) -> C;
nest_catchalls([{'case', P = {var, _}, {split, Type, X, Alts}} | Catchalls]) ->
{'case', P, {split, Type, X, add_catchalls(Alts, Catchalls)}}.
-spec simpl_switch(expr_env(), fann(), [fcase()], fsplit()) -> fexpr() | nomatch.
simpl_switch(_Env, _FAnn, _, {nosplit, E}) -> E;
simpl_switch(_Env, _FAnn, _, {nosplit, _, E}) -> E;
simpl_switch(Env, FAnn, Catchalls, {split, Type, X, Alts}) ->
Alts1 = add_catchalls(Alts, Catchalls),
Stuck = {switch, FAnn, {split, Type, X, Alts1}},
@ -1708,7 +1708,7 @@ read_only({remote, _, _, _, _, _, _}) -> false;
read_only({builtin, _, _, _}) -> false; %% TODO: some builtins are
read_only({switch, _, Split}) -> read_only(Split);
read_only({split, _, _, Cases}) -> read_only(Cases);
read_only({nosplit, E}) -> read_only(E);
read_only({nosplit, _, E}) -> read_only(E);
read_only({'case', _, Split}) -> read_only(Split);
read_only({'let', _, _, A, B}) -> read_only([A, B]);
read_only({funcall, _, _, _}) -> false;
@ -1960,7 +1960,7 @@ free_vars(Expr) ->
{closure, _, _, A} -> free_vars(A);
{switch, _, A} -> free_vars(A);
{split, _, X, As} -> free_vars([{var, [], X} | As]);
{nosplit, A} -> free_vars(A);
{nosplit, _, A} -> free_vars(A);
{'case', P, A} -> free_vars(A) -- lists:sort(fsplit_pat_vars(P))
end.
@ -1992,7 +1992,7 @@ used_defs(Expr) ->
{closure, _, F, A} -> lists:umerge([F], used_defs(A));
{switch, _, A} -> used_defs(A);
{split, _, _, As} -> used_defs(As);
{nosplit, A} -> used_defs(A);
{nosplit, _, A} -> used_defs(A);
{'case', _, A} -> used_defs(A)
end.
@ -2040,7 +2040,7 @@ bottom_up(F, Env, Expr) ->
{'let', FAnn, X, E1, bottom_up(F, Env1, Body)}
end;
{split, Type, X, Cases} -> {split, Type, X, [bottom_up(F, Env, Case) || Case <- Cases]};
{nosplit, E} -> {nosplit, bottom_up(F, Env, E)};
{nosplit, Rens, E} -> {nosplit, Rens, bottom_up(F, Env, E)};
{'case', Pat, Split} -> {'case', Pat, bottom_up(F, Env, Split)}
end).
@ -2164,7 +2164,7 @@ rename_spat(Ren, {assign, X, P}) ->
-spec rename_split(rename(), fsplit()) -> fsplit().
rename_split(Ren, {split, Type, X, Cases}) ->
{split, Type, rename_var(Ren, X), [rename_case(Ren, C) || C <- Cases]};
rename_split(Ren, {nosplit, E}) -> {nosplit, rename(Ren, E)}.
rename_split(Ren, {nosplit, Rens, E}) -> {nosplit, Rens, rename(Ren, E)}.
-spec rename_case(rename(), fcase()) -> fcase().
rename_case(Ren, {'case', Pat, Split}) ->
@ -2406,7 +2406,7 @@ pp_ftype({variant, Cons}) ->
end || {I, Args} <- indexed(Cons)])).
-spec pp_split(fsplit()) -> prettypr:document().
pp_split({nosplit, E}) -> pp_fexpr(E);
pp_split({nosplit, _, E}) -> pp_fexpr(E);
pp_split({split, Type, X, Alts}) ->
pp_above([pp_beside([pp_text("switch("), pp_text(X), pp_text(" : "), pp_ftype(Type), pp_text(")")])] ++
[prettypr:nest(2, pp_case(Alt)) || Alt <- Alts]).

View File

@ -334,13 +334,13 @@ to_scode1(Env, {op, Ann, Op, Args}) ->
to_scode1(Env, {'let', Ann, X, {var, _, Y}, Body}) ->
Env1 = bind_var(X, lookup_var(Env, Y), Env),
[ dbg_loc(Env, Ann) | dbg_scoped_var(Env1, X, to_scode(Env1, Body)) ];
[ dbg_loc(Env, Ann) | dbg_scoped_vars(Env1, [X], to_scode(Env1, Body)) ];
to_scode1(Env, {'let', Ann, X, Expr, Body}) ->
{I, Env1} = bind_local(X, Env),
SCode = [ to_scode(notail(Env), Expr),
aeb_fate_ops:store({var, I}, {stack, 0}),
to_scode(Env1, Body) ],
[ dbg_loc(Env, Ann) | dbg_scoped_var(Env1, X, SCode) ];
[ dbg_loc(Env, Ann) | dbg_scoped_vars(Env1, [X], SCode) ];
to_scode1(Env = #env{ current_function = Fun, tailpos = true, debug_info = false }, {def, Ann, Fun, Args}) ->
%% Tail-call to current function, f(e0..en). Compile to
@ -409,8 +409,8 @@ to_scode1(Env, {switch, Ann, Case}) ->
local_call( Env = #env{debug_info = false}, Fun) when Env#env.tailpos -> aeb_fate_ops:call_t(Fun);
local_call(_Env, Fun) -> aeb_fate_ops:call(Fun).
split_to_scode(Env, {nosplit, Expr}) ->
[switch_body, to_scode(Env, Expr)];
split_to_scode(Env, {nosplit, Renames, Expr}) ->
[switch_body, dbg_scoped_vars(Env, Renames, to_scode(Env, Expr))];
split_to_scode(Env, {split, {tuple, _}, X, Alts}) ->
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
Arg = lookup_var(Env, X),
@ -760,20 +760,20 @@ dbg_scoped_vars(#env{debug_info = false}, _, SCode) ->
SCode;
dbg_scoped_vars(_Env, [], SCode) ->
SCode;
dbg_scoped_vars(Env, [Var | Rest], SCode) ->
dbg_scoped_vars(Env, Rest, dbg_scoped_var(Env, Var, SCode)).
dbg_scoped_vars(Env, [{SavedVarName, Var} | Rest], SCode) ->
dbg_scoped_vars(Env, Rest, dbg_scoped_var(Env, SavedVarName, Var, SCode));
dbg_scoped_vars(Env = #env{saved_fresh_names = SavedFreshNames}, [Var | Rest], SCode) ->
SavedVarName = maps:get(Var, SavedFreshNames, Var),
dbg_scoped_vars(Env, Rest, dbg_scoped_var(Env, SavedVarName, Var, SCode)).
dbg_scoped_var(#env{debug_info = false}, _, SCode) ->
SCode;
dbg_scoped_var(Env = #env{saved_fresh_names = SavedFreshNames}, Var, SCode) ->
VarName = maps:get(Var, SavedFreshNames, Var),
case VarName == "_" orelse is_fresh_name(VarName) of
dbg_scoped_var(Env, SavedVarName, Var, SCode) ->
case SavedVarName == "_" orelse is_fresh_name(SavedVarName) of
true ->
SCode;
false ->
Register = lookup_var(Env, Var),
Def = [{'DBG_DEF', {immediate, VarName}, Register}],
Undef = [{'DBG_UNDEF', {immediate, VarName}, Register}],
Def = [{'DBG_DEF', {immediate, SavedVarName}, Register}],
Undef = [{'DBG_UNDEF', {immediate, SavedVarName}, Register}],
Def ++ dbg_undef(Undef, SCode)
end.