Remove fann() from fsplit_pat() and fpat()

This commit is contained in:
Gaith Hallak 2022-11-19 12:38:53 +03:00
parent 9ddd29d63a
commit a752fa5b48
2 changed files with 98 additions and 94 deletions

View File

@ -91,14 +91,14 @@
-type fcase() :: {'case', fsplit_pat(), fsplit()}. -type fcase() :: {'case', fsplit_pat(), fsplit()}.
-type fsplit_pat() :: {var, fann(), var_name()} -type fsplit_pat() :: {var, var_name()}
| {bool, false | true} | {bool, false | true}
| {int, integer()} | {int, integer()}
| {string, binary()} | {string, binary()}
| {nil, fann()} | nil
| {'::', var_name(), var_name()} | {'::', var_name(), var_name()}
| {con, fann(), arities(), tag(), [var_name()]} | {con, arities(), tag(), [var_name()]}
| {tuple, fann(), [var_name()]} | {tuple, [var_name()]}
| {assign, var_name(), var_name()}. | {assign, var_name(), var_name()}.
-type ftype() :: integer -type ftype() :: integer
@ -839,6 +839,10 @@ make_if_no_else(Cond, Then) ->
make_tuple([E]) -> E; make_tuple([E]) -> E;
make_tuple(Es) -> {tuple, [], Es}. make_tuple(Es) -> {tuple, [], Es}.
-spec make_tuple_fpat([fpat()]) -> fpat().
make_tuple_fpat([P]) -> P;
make_tuple_fpat(Ps) -> {tuple, Ps}.
-spec strip_singleton_tuples(ftype()) -> ftype(). -spec strip_singleton_tuples(ftype()) -> ftype().
strip_singleton_tuples({tuple, _, [T]}) -> strip_singleton_tuples(T); strip_singleton_tuples({tuple, _, [T]}) -> strip_singleton_tuples(T);
strip_singleton_tuples(T) -> T. strip_singleton_tuples(T) -> T.
@ -864,14 +868,14 @@ alts_to_fcode(Env, Type, X, Alts, Switch) ->
%% Intermediate format before case trees (fcase() and fsplit()). %% Intermediate format before case trees (fcase() and fsplit()).
-type falt() :: {'case', [fpat()], fexpr()}. -type falt() :: {'case', [fpat()], fexpr()}.
-type fpat() :: {var, fann(), var_name()} -type fpat() :: {var, var_name()}
| {bool, false | true} | {bool, false | true}
| {int, integer()} | {int, integer()}
| {string, binary()} | {string, binary()}
| {nil, fann()} | nil
| {'::', fpat(), fpat()} | {'::', fpat(), fpat()}
| {tuple, fann(), [fpat()]} | {tuple, [fpat()]}
| {con, fann(), arities(), tag(), [fpat()]} | {con, arities(), tag(), [fpat()]}
| {assign, fpat(), fpat()}. | {assign, fpat(), fpat()}.
-spec remove_guards(env(), [aeso_syntax:alt()], aeso_syntax:expr()) -> [falt()]. -spec remove_guards(env(), [aeso_syntax:alt()], aeso_syntax:expr()) -> [falt()].
@ -918,7 +922,7 @@ split_tree(Env, Vars, Alts = [{'case', Pats, Body} | _]) ->
case next_split(Pats) of case next_split(Pats) of
false -> false ->
Xs = [ X || {X, _} <- Vars ], Xs = [ X || {X, _} <- Vars ],
Ys = [ Y || {var, _, Y} <- Pats ], Ys = [ Y || {var, Y} <- Pats ],
Ren = [ {Y, X} || {Y, X} <- lists:zip(Ys, Xs), X /= Y, Y /= "_" ], Ren = [ {Y, X} || {Y, X} <- lists:zip(Ys, Xs), X /= Y, Y /= "_" ],
%% TODO: Unreachable clauses error %% TODO: Unreachable clauses error
{nosplit, rename(Ren, Body)}; {nosplit, rename(Ren, Body)};
@ -926,7 +930,7 @@ split_tree(Env, Vars, Alts = [{'case', Pats, Body} | _]) ->
{Vars0, [{X, Type} | Vars1]} = lists:split(I - 1, Vars), {Vars0, [{X, Type} | Vars1]} = lists:split(I - 1, Vars),
Type1 = strip_singleton_tuples(Type), Type1 = strip_singleton_tuples(Type),
SAlts = merge_alts(I, X, [ split_alt(I, A) || A <- Alts ]), SAlts = merge_alts(I, X, [ split_alt(I, A) || A <- Alts ]),
MakeCase = fun({var, FAnn, Z}, Split) -> {'case', {var, FAnn, "_"}, rename_split([{Z, X}], Split)}; MakeCase = fun({var, Z}, Split) -> {'case', {var, "_"}, rename_split([{Z, X}], Split)};
(SPat, Split) -> {'case', SPat, Split} end, (SPat, Split) -> {'case', SPat, Split} end,
Cases = [ MakeCase(SPat, split_tree(Env, Vars0 ++ split_vars(SPat, Type1) ++ Vars1, FAlts)) Cases = [ MakeCase(SPat, split_tree(Env, Vars0 ++ split_vars(SPat, Type1) ++ Vars1, FAlts))
|| {SPat, FAlts} <- SAlts ], || {SPat, FAlts} <- SAlts ],
@ -948,18 +952,18 @@ merge_alts(I, X, Alts, Alts1) ->
when Alts :: [{fsplit_pat(), [falt()]}]. when Alts :: [{fsplit_pat(), [falt()]}].
merge_alt(_, _, {P, A}, []) -> [{P, [A]}]; merge_alt(_, _, {P, A}, []) -> [{P, [A]}];
merge_alt(I, X, {P, A}, [{Q, As} | Rest]) -> merge_alt(I, X, {P, A}, [{Q, As} | Rest]) ->
Match = fun({var, _, _}, {var, _, _}) -> match; Match = fun({var, _}, {var, _}) -> match;
({tuple, _, _}, {tuple, _, _}) -> match; ({tuple, _}, {tuple, _}) -> match;
({bool, B}, {bool, B}) -> match; ({bool, B}, {bool, B}) -> match;
({int, N}, {int, N}) -> match; ({int, N}, {int, N}) -> match;
({string, S}, {string, S}) -> match; ({string, S}, {string, S}) -> match;
({nil, []}, {nil, []}) -> match; (nil, nil) -> match;
({'::', _, _}, {'::', _, _}) -> match; ({'::', _, _}, {'::', _, _}) -> match;
({con, _, _, C, _}, {con, _, _, C, _}) -> match; ({con, _, C, _}, {con, _, C, _}) -> match;
({con, _, _, _, _}, {con, _, _, _, _}) -> mismatch; ({con, _, _, _}, {con, _, _, _}) -> mismatch;
({var, _, _}, _) -> expand; ({var, _}, _) -> expand;
(_, {var, _, _}) -> insert; (_, {var, _}) -> insert;
(_, _) -> mismatch (_, _) -> mismatch
end, end,
case Match(P, Q) of case Match(P, Q) of
match -> [{Q, [A | As]} | Rest]; match -> [{Q, [A | As]} | Rest];
@ -972,18 +976,18 @@ merge_alt(I, X, {P, A}, [{Q, As} | Rest]) ->
-spec expand(integer(), var_name(), fsplit_pat(), fsplit_pat(), falt()) -> term(). -spec expand(integer(), var_name(), fsplit_pat(), fsplit_pat(), falt()) -> term().
expand(I, X, P, Q, Case = {'case', Ps, E}) -> expand(I, X, P, Q, Case = {'case', Ps, E}) ->
{Ps0, [{var, _, Y} | Ps1]} = lists:split(I - 1, Ps), {Ps0, [{var, Y} | Ps1]} = lists:split(I - 1, Ps),
{Ps0r, Ren1} = rename_fpats([{Y, X} || Y /= X], Ps0), {Ps0r, Ren1} = rename_fpats([{Y, X} || Y /= X], Ps0),
{Ps1r, Ren2} = rename_fpats(Ren1, Ps1), {Ps1r, Ren2} = rename_fpats(Ren1, Ps1),
E1 = rename(Ren2, E), E1 = rename(Ren2, E),
Splice = fun(N) -> Ps0r ++ lists:duplicate(N, {var, [], "_"}) ++ Ps1r end, Splice = fun(N) -> Ps0r ++ lists:duplicate(N, {var, "_"}) ++ Ps1r end,
Type = fun({tuple, _, Xs}) -> {tuple, length(Xs)}; Type = fun({tuple, Xs}) -> {tuple, length(Xs)};
({bool, _}) -> bool; ({bool, _}) -> bool;
({int, _}) -> int; ({int, _}) -> int;
({string, _}) -> string; ({string, _}) -> string;
({nil, _}) -> list; (nil) -> list;
({'::', _, _}) -> list; ({'::', _, _}) -> list;
({con, _, As, _, _}) -> {variant, As} ({con, As, _, _}) -> {variant, As}
end, end,
MkCase = fun(Pat, Vars) -> {Pat, {'case', Splice(Vars), E1}} end, MkCase = fun(Pat, Vars) -> {Pat, {'case', Splice(Vars), E1}} end,
case Type(Q) of case Type(Q) of
@ -991,8 +995,8 @@ expand(I, X, P, Q, Case = {'case', Ps, E}) ->
bool -> {[MkCase({bool, B}, 0) || B <- [false, true]], []}; bool -> {[MkCase({bool, B}, 0) || B <- [false, true]], []};
int -> {[MkCase(Q, 0)], [{P, Case}]}; int -> {[MkCase(Q, 0)], [{P, Case}]};
string -> {[MkCase(Q, 0)], [{P, Case}]}; string -> {[MkCase(Q, 0)], [{P, Case}]};
list -> {[MkCase({nil, []}, 0), MkCase({'::', fresh_name(), fresh_name()}, 2)], []}; list -> {[MkCase(nil, 0), MkCase({'::', fresh_name(), fresh_name()}, 2)], []};
{variant, As} -> {[MkCase({con, [], As, C - 1, [fresh_name() || _ <- lists:seq(1, Ar)]}, Ar) {variant, As} -> {[MkCase({con, As, C - 1, [fresh_name() || _ <- lists:seq(1, Ar)]}, Ar)
|| {C, Ar} <- indexed(As)], []} || {C, Ar} <- indexed(As)], []}
end. end.
@ -1003,37 +1007,37 @@ split_alt(I, {'case', Pats, Body}) ->
{SPat, {'case', Pats0 ++ InnerPats ++ Pats1, Body}}. {SPat, {'case', Pats0 ++ InnerPats ++ Pats1, Body}}.
-spec split_pat(fpat()) -> {fsplit_pat(), [fpat()]}. -spec split_pat(fpat()) -> {fsplit_pat(), [fpat()]}.
split_pat(P = {var, FAnn, _}) -> {{var, FAnn, fresh_name()}, [P]}; split_pat(P = {var, _}) -> {{var, fresh_name()}, [P]};
split_pat({bool, B}) -> {{bool, B}, []}; split_pat({bool, B}) -> {{bool, B}, []};
split_pat({int, N}) -> {{int, N}, []}; split_pat({int, N}) -> {{int, N}, []};
split_pat({string, N}) -> {{string, N}, []}; split_pat({string, N}) -> {{string, N}, []};
split_pat({nil, FAnn}) -> {{nil, FAnn}, []}; split_pat(nil) -> {nil, []};
split_pat({'::', P, Q}) -> {{'::', fresh_name(), fresh_name()}, [P, Q]}; split_pat({'::', P, Q}) -> {{'::', fresh_name(), fresh_name()}, [P, Q]};
split_pat({con, FAnn, As, I, Pats}) -> split_pat({con, As, I, Pats}) ->
Xs = [fresh_name() || _ <- Pats], Xs = [fresh_name() || _ <- Pats],
{{con, FAnn, As, I, Xs}, Pats}; {{con, As, I, Xs}, Pats};
split_pat({assign, X = {var, _, _}, P}) -> split_pat({assign, X = {var, _}, P}) ->
{{assign, fresh_name(), fresh_name()}, [X, P]}; {{assign, fresh_name(), fresh_name()}, [X, P]};
split_pat({tuple, FAnn, Pats}) -> split_pat({tuple, Pats}) ->
Xs = [fresh_name() || _ <- Pats], Xs = [fresh_name() || _ <- Pats],
{{tuple, FAnn, Xs}, Pats}. {{tuple, Xs}, Pats}.
-spec split_vars(fsplit_pat(), ftype()) -> [{var_name(), ftype()}]. -spec split_vars(fsplit_pat(), ftype()) -> [{var_name(), ftype()}].
split_vars({bool, _}, boolean) -> []; split_vars({bool, _}, boolean) -> [];
split_vars({int, _}, integer) -> []; split_vars({int, _}, integer) -> [];
split_vars({string, _}, string) -> []; split_vars({string, _}, string) -> [];
split_vars({nil, _}, {list, _}) -> []; split_vars(nil, {list, _}) -> [];
split_vars({'::', X, Xs}, {list, T}) -> [{X, T}, {Xs, {list, T}}]; split_vars({'::', X, Xs}, {list, T}) -> [{X, T}, {Xs, {list, T}}];
split_vars({assign, X, P}, T) -> [{X, T}, {P, T}]; split_vars({assign, X, P}, T) -> [{X, T}, {P, T}];
split_vars({con, _, _, I, Xs}, {variant, Cons}) -> split_vars({con, _, I, Xs}, {variant, Cons}) ->
lists:zip(Xs, lists:nth(I + 1, Cons)); lists:zip(Xs, lists:nth(I + 1, Cons));
split_vars({tuple, _, Xs}, {tuple, Ts}) -> split_vars({tuple, Xs}, {tuple, Ts}) ->
lists:zip(Xs, Ts); lists:zip(Xs, Ts);
split_vars({var, _, X}, T) -> [{X, T}]. split_vars({var, X}, T) -> [{X, T}].
-spec next_split([fpat()]) -> integer() | false. -spec next_split([fpat()]) -> integer() | false.
next_split(Pats) -> next_split(Pats) ->
IsVar = fun({var, _, _}) -> true; (_) -> false end, IsVar = fun({var, _}) -> true; (_) -> false end,
case [ I || {I, P} <- indexed(Pats), not IsVar(P) ] of case [ I || {I, P} <- indexed(Pats), not IsVar(P) ] of
[] -> false; [] -> false;
[I | _] -> I [I | _] -> I
@ -1052,15 +1056,15 @@ pat_to_fcode(Env, Pat) ->
pat_to_fcode(Env, no_type, Pat). pat_to_fcode(Env, no_type, Pat).
-spec pat_to_fcode(env(), aeso_syntax:type() | no_type, aeso_syntax:pat()) -> fpat(). -spec pat_to_fcode(env(), aeso_syntax:type() | no_type, aeso_syntax:pat()) -> fpat().
pat_to_fcode(_Env, _Type, {id, Ann, X}) -> {var, to_fann(Ann), X}; pat_to_fcode(_Env, _Type, {id, _, X}) -> {var, X};
pat_to_fcode(Env, _Type, {C, Ann, _} = Con) when C == con; C == qcon -> pat_to_fcode(Env, _Type, {C, _, _} = Con) when C == con; C == qcon ->
#con_tag{tag = I, arities = As} = lookup_con(Env, Con), #con_tag{tag = I, arities = As} = lookup_con(Env, Con),
{con, to_fann(Ann), As, I, []}; {con, As, I, []};
pat_to_fcode(Env, _Type, {app, _, {typed, _, {C, Ann, _} = Con, _}, Pats}) when C == con; C == qcon -> pat_to_fcode(Env, _Type, {app, _, {typed, _, {C, _, _} = Con, _}, Pats}) when C == con; C == qcon ->
#con_tag{tag = I, arities = As} = lookup_con(Env, Con), #con_tag{tag = I, arities = As} = lookup_con(Env, Con),
{con, to_fann(Ann), As, I, [pat_to_fcode(Env, Pat) || Pat <- Pats]}; {con, As, I, [pat_to_fcode(Env, Pat) || Pat <- Pats]};
pat_to_fcode(Env, _Type, {tuple, _, Pats}) -> pat_to_fcode(Env, _Type, {tuple, _, Pats}) ->
make_tuple([ pat_to_fcode(Env, Pat) || Pat <- Pats ]); make_tuple_fpat([ pat_to_fcode(Env, Pat) || Pat <- Pats ]);
pat_to_fcode(_Env, _Type, {bool, _, B}) -> {bool, B}; pat_to_fcode(_Env, _Type, {bool, _, B}) -> {bool, B};
pat_to_fcode(_Env, _Type, {int, _, N}) -> {int, N}; pat_to_fcode(_Env, _Type, {int, _, N}) -> {int, N};
pat_to_fcode(_Env, _Type, {char, _, N}) -> {int, N}; pat_to_fcode(_Env, _Type, {char, _, N}) -> {int, N};
@ -1068,7 +1072,7 @@ pat_to_fcode(_Env, _Type, {string, _, N}) -> {string, N};
pat_to_fcode(Env, _Type, {list, _, Ps}) -> pat_to_fcode(Env, _Type, {list, _, Ps}) ->
lists:foldr(fun(P, Qs) -> lists:foldr(fun(P, Qs) ->
{'::', pat_to_fcode(Env, P), Qs} {'::', pat_to_fcode(Env, P), Qs}
end, {nil, []}, Ps); end, nil, Ps);
pat_to_fcode(Env, _Type, {app, _, {'::', _}, [P, Q]}) -> pat_to_fcode(Env, _Type, {app, _, {'::', _}, [P, Q]}) ->
{'::', pat_to_fcode(Env, P), pat_to_fcode(Env, Q)}; {'::', pat_to_fcode(Env, P), pat_to_fcode(Env, Q)};
pat_to_fcode(Env, {record_t, Fields}, {record, _, FieldPats}) -> pat_to_fcode(Env, {record_t, Fields}, {record, _, FieldPats}) ->
@ -1078,7 +1082,7 @@ pat_to_fcode(Env, {record_t, Fields}, {record, _, FieldPats}) ->
{set, Pat} -> Pat {set, Pat} -> Pat
%% {upd, _, _} is impossible in patterns %% {upd, _, _} is impossible in patterns
end end, end end,
make_tuple([pat_to_fcode(Env, FieldPat(Field)) make_tuple_fpat([pat_to_fcode(Env, FieldPat(Field))
|| Field <- Fields]); || Field <- Fields]);
pat_to_fcode(Env, _Type, {letpat, _, Id = {typed, _, {id, _, _}, _}, Pattern}) -> pat_to_fcode(Env, _Type, {letpat, _, Id = {typed, _, {id, _, _}, _}, Pattern}) ->
{assign, pat_to_fcode(Env, Id), pat_to_fcode(Env, Pattern)}; {assign, pat_to_fcode(Env, Id), pat_to_fcode(Env, Pattern)};
@ -1590,7 +1594,7 @@ get_catchalls(Alts) ->
-spec add_catchalls([fcase()], [fcase()]) -> [fcase()]. -spec add_catchalls([fcase()], [fcase()]) -> [fcase()].
add_catchalls(Alts, []) -> Alts; add_catchalls(Alts, []) -> Alts;
add_catchalls(Alts, Catchalls) -> add_catchalls(Alts, Catchalls) ->
case lists:splitwith(fun({'case', {var, _, _}, _}) -> false; (_) -> true end, case lists:splitwith(fun({'case', {var, _}, _}) -> false; (_) -> true end,
Alts) of Alts) of
{Alts1, [C]} -> Alts1 ++ [nest_catchalls([C | Catchalls])]; {Alts1, [C]} -> Alts1 ++ [nest_catchalls([C | Catchalls])];
{_, []} -> Alts ++ [nest_catchalls(Catchalls)] {_, []} -> Alts ++ [nest_catchalls(Catchalls)]
@ -1598,8 +1602,8 @@ add_catchalls(Alts, Catchalls) ->
end. end.
-spec nest_catchalls([fcase()]) -> fcase(). -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]) -> nest_catchalls([{'case', P = {var, _}, {split, Type, X, Alts}} | Catchalls]) ->
{'case', P, {split, Type, X, add_catchalls(Alts, Catchalls)}}. {'case', P, {split, Type, X, add_catchalls(Alts, Catchalls)}}.
-spec simpl_switch(expr_env(), [fcase()], fsplit()) -> fexpr() | nomatch. -spec simpl_switch(expr_env(), [fcase()], fsplit()) -> fexpr() | nomatch.
@ -1626,14 +1630,14 @@ simpl_case(Env, E, [{'case', Pat, Body} | Alts]) ->
end. end.
-spec match_pat(fsplit_pat(), fexpr()) -> false | [{var_name(), fexpr()}]. -spec match_pat(fsplit_pat(), fexpr()) -> false | [{var_name(), fexpr()}].
match_pat({tuple, _, Xs}, {tuple, _, Es}) -> lists:zip(Xs, Es); match_pat({tuple, Xs}, {tuple, _, Es}) -> lists:zip(Xs, Es);
match_pat({con, _, _, C, Xs}, {con, _, _, C, Es}) -> lists:zip(Xs, Es); match_pat({con, _, C, Xs}, {con, _, _, C, Es}) -> lists:zip(Xs, Es);
match_pat(L, {lit, _, L}) -> []; match_pat(L, {lit, _, L}) -> [];
match_pat({nil, _}, {nil, _}) -> []; match_pat(nil, {nil, _}) -> [];
match_pat({'::', X, Y}, {op, _, '::', [A, B]}) -> [{X, A}, {Y, B}]; match_pat({'::', X, Y}, {op, _, '::', [A, B]}) -> [{X, A}, {Y, B}];
match_pat({var, _, X}, E) -> [{X, E}]; match_pat({var, X}, E) -> [{X, E}];
match_pat({assign, X, P}, E) -> [{X, E}, {P, E}]; match_pat({assign, X, P}, E) -> [{X, E}, {P, E}];
match_pat(_, _) -> false. match_pat(_, _) -> false.
-spec constructor_form(expr_env(), fexpr()) -> fexpr() | false. -spec constructor_form(expr_env(), fexpr()) -> fexpr() | false.
constructor_form(Env, Expr) -> constructor_form(Env, Expr) ->
@ -1907,26 +1911,26 @@ fresh_name(Prefix) ->
lists:concat([Prefix, N]). lists:concat([Prefix, N]).
-spec pat_vars(fpat()) -> [var_name()]. -spec pat_vars(fpat()) -> [var_name()].
pat_vars({var, _, X}) -> [X || X /= "_"]; pat_vars({var, X}) -> [X || X /= "_"];
pat_vars({bool, _}) -> []; pat_vars({bool, _}) -> [];
pat_vars({int, _}) -> []; pat_vars({int, _}) -> [];
pat_vars({string, _}) -> []; pat_vars({string, _}) -> [];
pat_vars({nil, _}) -> []; pat_vars(nil) -> [];
pat_vars({'::', P, Q}) -> pat_vars(P) ++ pat_vars(Q); pat_vars({'::', P, Q}) -> pat_vars(P) ++ pat_vars(Q);
pat_vars({tuple, _, Ps}) -> pat_vars(Ps); pat_vars({tuple, Ps}) -> pat_vars(Ps);
pat_vars({con, _, _, _, Ps}) -> pat_vars(Ps); pat_vars({con, _, _, Ps}) -> pat_vars(Ps);
pat_vars({assign, X, P}) -> pat_vars(X) ++ pat_vars(P); pat_vars({assign, X, P}) -> pat_vars(X) ++ pat_vars(P);
pat_vars(Ps) when is_list(Ps) -> [X || P <- Ps, X <- pat_vars(P)]. pat_vars(Ps) when is_list(Ps) -> [X || P <- Ps, X <- pat_vars(P)].
-spec fsplit_pat_vars(fsplit_pat()) -> [var_name()]. -spec fsplit_pat_vars(fsplit_pat()) -> [var_name()].
fsplit_pat_vars({var, _, X}) -> [X || X /= "_"]; fsplit_pat_vars({var, X}) -> [X || X /= "_"];
fsplit_pat_vars({bool, _}) -> []; fsplit_pat_vars({bool, _}) -> [];
fsplit_pat_vars({int, _}) -> []; fsplit_pat_vars({int, _}) -> [];
fsplit_pat_vars({string, _}) -> []; fsplit_pat_vars({string, _}) -> [];
fsplit_pat_vars({nil, _}) -> []; fsplit_pat_vars(nil) -> [];
fsplit_pat_vars({'::', P, Q}) -> [P, Q]; fsplit_pat_vars({'::', P, Q}) -> [P, Q];
fsplit_pat_vars({tuple, _, Ps}) -> Ps; fsplit_pat_vars({tuple, Ps}) -> Ps;
fsplit_pat_vars({con, _, _, _, Ps}) -> Ps. fsplit_pat_vars({con, _, _, Ps}) -> Ps.
-spec free_vars(fexpr() | [fexpr()]) -> [var_name()]. -spec free_vars(fexpr() | [fexpr()]) -> [var_name()].
free_vars(Xs) when is_list(Xs) -> free_vars(Xs) when is_list(Xs) ->
@ -2119,39 +2123,39 @@ rename_fpats(Ren, [P | Ps]) ->
rename_fpat(Ren, P = {bool, _}) -> {P, Ren}; rename_fpat(Ren, P = {bool, _}) -> {P, Ren};
rename_fpat(Ren, P = {int, _}) -> {P, Ren}; rename_fpat(Ren, P = {int, _}) -> {P, Ren};
rename_fpat(Ren, P = {string, _}) -> {P, Ren}; rename_fpat(Ren, P = {string, _}) -> {P, Ren};
rename_fpat(Ren, P = {nil, _}) -> {P, Ren}; rename_fpat(Ren, P = nil) -> {P, Ren};
rename_fpat(Ren, {'::', P, Q}) -> rename_fpat(Ren, {'::', P, Q}) ->
{P1, Ren1} = rename_fpat(Ren, P), {P1, Ren1} = rename_fpat(Ren, P),
{Q1, Ren2} = rename_fpat(Ren1, Q), {Q1, Ren2} = rename_fpat(Ren1, Q),
{{'::', P1, Q1}, Ren2}; {{'::', P1, Q1}, Ren2};
rename_fpat(Ren, {var, FAnn, X}) -> rename_fpat(Ren, {var, X}) ->
{Z, Ren1} = rename_binding(Ren, X), {Z, Ren1} = rename_binding(Ren, X),
{{var, FAnn, Z}, Ren1}; {{var, Z}, Ren1};
rename_fpat(Ren, {con, FAnn, Ar, C, Ps}) -> rename_fpat(Ren, {con, Ar, C, Ps}) ->
{Ps1, Ren1} = rename_fpats(Ren, Ps), {Ps1, Ren1} = rename_fpats(Ren, Ps),
{{con, FAnn, Ar, C, Ps1}, Ren1}; {{con, Ar, C, Ps1}, Ren1};
rename_fpat(Ren, {tuple, FAnn, Ps}) -> rename_fpat(Ren, {tuple, Ps}) ->
{Ps1, Ren1} = rename_fpats(Ren, Ps), {Ps1, Ren1} = rename_fpats(Ren, Ps),
{{tuple, FAnn, Ps1}, Ren1}. {{tuple, Ps1}, Ren1}.
-spec rename_spat(rename(), fsplit_pat()) -> {fsplit_pat(), rename()}. -spec rename_spat(rename(), fsplit_pat()) -> {fsplit_pat(), rename()}.
rename_spat(Ren, P = {bool, _}) -> {P, Ren}; rename_spat(Ren, P = {bool, _}) -> {P, Ren};
rename_spat(Ren, P = {int, _}) -> {P, Ren}; rename_spat(Ren, P = {int, _}) -> {P, Ren};
rename_spat(Ren, P = {string, _}) -> {P, Ren}; rename_spat(Ren, P = {string, _}) -> {P, Ren};
rename_spat(Ren, P = {nil, _}) -> {P, Ren}; rename_spat(Ren, P = nil) -> {P, Ren};
rename_spat(Ren, {'::', X, Y}) -> rename_spat(Ren, {'::', X, Y}) ->
{X1, Ren1} = rename_binding(Ren, X), {X1, Ren1} = rename_binding(Ren, X),
{Y1, Ren2} = rename_binding(Ren1, Y), {Y1, Ren2} = rename_binding(Ren1, Y),
{{'::', X1, Y1}, Ren2}; {{'::', X1, Y1}, Ren2};
rename_spat(Ren, {var, FAnn, X}) -> rename_spat(Ren, {var, X}) ->
{Z, Ren1} = rename_binding(Ren, X), {Z, Ren1} = rename_binding(Ren, X),
{{var, FAnn, Z}, Ren1}; {{var, Z}, Ren1};
rename_spat(Ren, {con, FAnn, Ar, C, Xs}) -> rename_spat(Ren, {con, Ar, C, Xs}) ->
{Zs, Ren1} = rename_bindings(Ren, Xs), {Zs, Ren1} = rename_bindings(Ren, Xs),
{{con, FAnn, Ar, C, Zs}, Ren1}; {{con, Ar, C, Zs}, Ren1};
rename_spat(Ren, {tuple, FAnn, Xs}) -> rename_spat(Ren, {tuple, Xs}) ->
{Zs, Ren1} = rename_bindings(Ren, Xs), {Zs, Ren1} = rename_bindings(Ren, Xs),
{{tuple, FAnn, Zs}, Ren1}; {{tuple, Zs}, Ren1};
rename_spat(Ren, {assign, X, P}) -> rename_spat(Ren, {assign, X, P}) ->
{X1, Ren1} = rename_binding(Ren, X), {X1, Ren1} = rename_binding(Ren, X),
{P1, Ren2} = rename_binding(Ren1, P), {P1, Ren2} = rename_binding(Ren1, P),
@ -2409,10 +2413,10 @@ pp_case({'case', Pat, Split}) ->
prettypr:nest(2, pp_split(Split))]). prettypr:nest(2, pp_split(Split))]).
-spec pp_pat(fsplit_pat()) -> prettypr:document(). -spec pp_pat(fsplit_pat()) -> prettypr:document().
pp_pat({tuple, FAnn, Xs}) -> pp_fexpr({tuple, FAnn, [{var, FAnn, X} || X <- Xs]}); pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [], [{var, X} || X <- Xs]});
pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs}]}); pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs}]});
pp_pat({con, FAnn, As, I, Xs}) -> pp_fexpr({con, FAnn, As, I, [{var, [], X} || X <- Xs]}); pp_pat({con, As, I, Xs}) -> pp_fexpr({con, [], As, I, [{var, [], X} || X <- Xs]});
pp_pat({var, FAnn, X}) -> pp_fexpr({var, FAnn, X}); pp_pat({var, X}) -> pp_fexpr({var, [], X});
pp_pat(P = {Tag, _}) when Tag == bool; Tag == int; Tag == string pp_pat(P = {Tag, _}) when Tag == bool; Tag == int; Tag == string
-> pp_fexpr({lit, [], P}); -> pp_fexpr({lit, [], P});
pp_pat(Pat) -> pp_fexpr(Pat). pp_pat(Pat) -> pp_fexpr(Pat).

View File

@ -507,7 +507,7 @@ split_to_scode(Env, {split, {list, _}, X, Alts}) ->
GetAlt = fun(P) -> GetAlt = fun(P) ->
case [C || C = {'case', Pat, _} <- Alts1, Pat == P orelse is_tuple(Pat) andalso element(1, Pat) == P] of case [C || C = {'case', Pat, _} <- Alts1, Pat == P orelse is_tuple(Pat) andalso element(1, Pat) == P] of
[] -> missing; [] -> missing;
[{'case', {nil, _}, S} | _] -> split_to_scode(Env, S); [{'case', nil, S} | _] -> split_to_scode(Env, S);
[{'case', {'::', Y, Z}, S} | _] -> [{'case', {'::', Y, Z}, S} | _] ->
{I, Env1} = bind_local(Y, Env), {I, Env1} = bind_local(Y, Env),
{J, Env2} = bind_local(Z, Env1), {J, Env2} = bind_local(Z, Env1),
@ -558,7 +558,7 @@ literal_split_to_scode(Env, Type, Arg, [{'case', Lit, Body} | Alts], Def) when T
catchall_to_scode(Env, X, Alts) -> catchall_to_scode(Env, X, Alts, []). catchall_to_scode(Env, X, Alts) -> catchall_to_scode(Env, X, Alts, []).
catchall_to_scode(Env, X, [{'case', {var, _, Y}, Split} | _], Acc) -> catchall_to_scode(Env, X, [{'case', {var, Y}, Split} | _], Acc) ->
Env1 = bind_var(Y, lookup_var(Env, X), Env), Env1 = bind_var(Y, lookup_var(Env, X), Env),
{split_to_scode(Env1, Split), lists:reverse(Acc)}; {split_to_scode(Env1, Split), lists:reverse(Acc)};
catchall_to_scode(Env, X, [Alt | Alts], Acc) -> catchall_to_scode(Env, X, [Alt | Alts], Acc) ->