Add fann() to let
This commit is contained in:
parent
a027ac4f6a
commit
48136ef719
@ -71,7 +71,7 @@
|
|||||||
| {proj, fann(), fexpr(), integer()}
|
| {proj, fann(), fexpr(), integer()}
|
||||||
| {set_proj, fann(), fexpr(), integer(), fexpr()} %% tuple, field, new_value
|
| {set_proj, fann(), fexpr(), integer(), fexpr()} %% tuple, field, new_value
|
||||||
| {op, fann(), op(), [fexpr()]}
|
| {op, fann(), op(), [fexpr()]}
|
||||||
| {'let', var_name(), fexpr(), fexpr()}
|
| {'let', fann(), var_name(), fexpr(), fexpr()}
|
||||||
| {funcall, fann(), fexpr(), [fexpr()]} %% Call to unknown function
|
| {funcall, fann(), fexpr(), [fexpr()]} %% Call to unknown function
|
||||||
| {closure, fann(), fun_name(), fexpr()}
|
| {closure, fann(), fun_name(), fexpr()}
|
||||||
| {switch, fsplit()}
|
| {switch, fsplit()}
|
||||||
@ -524,11 +524,11 @@ make_let(Expr, Body) ->
|
|||||||
{lit, {bool, _}} -> Body(Expr);
|
{lit, {bool, _}} -> Body(Expr);
|
||||||
_ ->
|
_ ->
|
||||||
X = fresh_name(),
|
X = fresh_name(),
|
||||||
{'let', X, Expr, Body({var, X})}
|
{'let', get_fann(Expr), X, Expr, Body({var, X})}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
let_bind(X, {var, Y}, Body) -> rename([{X, Y}], Body);
|
let_bind(X, {var, Y}, Body) -> rename([{X, Y}], Body);
|
||||||
let_bind(X, Expr, Body) -> {'let', X, Expr, Body}.
|
let_bind(X, Expr, Body) -> {'let', get_fann(Expr), X, Expr, Body}.
|
||||||
|
|
||||||
let_bind(Binds, Body) ->
|
let_bind(Binds, Body) ->
|
||||||
lists:foldr(fun({X, E}, Rest) -> let_bind(X, E, Rest) end,
|
lists:foldr(fun({X, E}, Rest) -> let_bind(X, E, Rest) end,
|
||||||
@ -620,23 +620,24 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, _Ann, Fields}) ->
|
|||||||
end,
|
end,
|
||||||
make_tuple(lists:map(FVal, FieldTypes));
|
make_tuple(lists:map(FVal, FieldTypes));
|
||||||
|
|
||||||
expr_to_fcode(Env, {record_t, [FieldT]}, {record, _Ann, Rec, Fields}) ->
|
expr_to_fcode(Env, {record_t, [FieldT]}, {record, Ann, Rec, Fields}) ->
|
||||||
case field_value(FieldT, Fields) of
|
case field_value(FieldT, Fields) of
|
||||||
false -> expr_to_fcode(Env, Rec);
|
false -> expr_to_fcode(Env, Rec);
|
||||||
{set, E} -> expr_to_fcode(Env, E);
|
{set, E} -> expr_to_fcode(Env, E);
|
||||||
{upd, Z, E} -> {'let', Z, expr_to_fcode(Env, Rec), expr_to_fcode(bind_var(Env, Z), E)}
|
{upd, Z, E} -> {'let', to_fann(Ann), Z, expr_to_fcode(Env, Rec), expr_to_fcode(bind_var(Env, Z), E)}
|
||||||
end;
|
end;
|
||||||
expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) ->
|
expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) ->
|
||||||
X = fresh_name(),
|
X = fresh_name(),
|
||||||
Proj = fun(I) -> {proj, to_fann(Ann), {var, X}, I - 1} end,
|
FAnn = to_fann(Ann),
|
||||||
|
Proj = fun(I) -> {proj, FAnn, {var, X}, I - 1} end,
|
||||||
Comp = fun({I, false}) -> Proj(I);
|
Comp = fun({I, false}) -> Proj(I);
|
||||||
({_, {set, E}}) -> expr_to_fcode(Env, E);
|
({_, {set, E}}) -> expr_to_fcode(Env, E);
|
||||||
({I, {upd, Z, E}}) -> {'let', Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)}
|
({I, {upd, Z, E}}) -> {'let', FAnn, Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)}
|
||||||
end,
|
end,
|
||||||
Set = fun({_, false}, R) -> R;
|
Set = fun({_, false}, R) -> R;
|
||||||
({I, {set, E}}, R) -> {set_proj, to_fann(Ann), R, I - 1, expr_to_fcode(Env, E)};
|
({I, {set, E}}, R) -> {set_proj, FAnn, R, I - 1, expr_to_fcode(Env, E)};
|
||||||
({I, {upd, Z, E}}, R) -> {set_proj, to_fann(Ann), R, I - 1,
|
({I, {upd, Z, E}}, R) -> {set_proj, FAnn, R, I - 1,
|
||||||
{'let', Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)}}
|
{'let', FAnn, Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)}}
|
||||||
end,
|
end,
|
||||||
Expand = length(Fields) == length(FieldTypes),
|
Expand = length(Fields) == length(FieldTypes),
|
||||||
Updates = [ {I, field_value(FT, Fields)} || {I, FT} <- indexed(FieldTypes) ],
|
Updates = [ {I, field_value(FT, Fields)} || {I, FT} <- indexed(FieldTypes) ],
|
||||||
@ -644,7 +645,7 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) ->
|
|||||||
true -> {tuple, lists:map(Comp, Updates)};
|
true -> {tuple, lists:map(Comp, Updates)};
|
||||||
false -> lists:foldr(Set, {var, X}, Updates)
|
false -> lists:foldr(Set, {var, X}, Updates)
|
||||||
end,
|
end,
|
||||||
{'let', X, expr_to_fcode(Env, Rec), Body};
|
{'let', FAnn, X, expr_to_fcode(Env, Rec), Body};
|
||||||
|
|
||||||
%% Lists
|
%% Lists
|
||||||
expr_to_fcode(Env, _Type, {list, _, Es}) ->
|
expr_to_fcode(Env, _Type, {list, _, Es}) ->
|
||||||
@ -682,7 +683,7 @@ expr_to_fcode(Env, _Type, {'if', _, Cond, Then, Else}) ->
|
|||||||
expr_to_fcode(Env, Else));
|
expr_to_fcode(Env, Else));
|
||||||
|
|
||||||
%% Switch
|
%% Switch
|
||||||
expr_to_fcode(Env, _, S = {switch, _, Expr = {typed, _, E, Type}, Alts}) ->
|
expr_to_fcode(Env, _, S = {switch, Ann, Expr = {typed, _, E, Type}, Alts}) ->
|
||||||
Switch = fun(X) ->
|
Switch = fun(X) ->
|
||||||
{switch, alts_to_fcode(Env, type_to_fcode(Env, Type), X, Alts, S)}
|
{switch, alts_to_fcode(Env, type_to_fcode(Env, Type), X, Alts, S)}
|
||||||
end,
|
end,
|
||||||
@ -690,7 +691,7 @@ expr_to_fcode(Env, _, S = {switch, _, Expr = {typed, _, E, Type}, Alts}) ->
|
|||||||
{id, _, X} -> Switch(X);
|
{id, _, X} -> Switch(X);
|
||||||
_ ->
|
_ ->
|
||||||
X = fresh_name(),
|
X = fresh_name(),
|
||||||
{'let', X, expr_to_fcode(Env, Expr),
|
{'let', to_fann(Ann), X, expr_to_fcode(Env, Expr),
|
||||||
Switch(X)}
|
Switch(X)}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -748,7 +749,7 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A
|
|||||||
case FFun of
|
case FFun of
|
||||||
{var, X} -> Call(X);
|
{var, X} -> Call(X);
|
||||||
_ -> X = fresh_name(),
|
_ -> X = fresh_name(),
|
||||||
{'let', X, FFun, Call(X)}
|
{'let', FAnn, X, FFun, Call(X)}
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -778,7 +779,7 @@ expr_to_fcode(Env, _Type, {map, _, Map, KVs}) ->
|
|||||||
[] -> {op, FAnn, map_get, [Map1, Key]};
|
[] -> {op, FAnn, map_get, [Map1, Key]};
|
||||||
[D] -> {op, FAnn, map_get_d, [Map1, Key, expr_to_fcode(Env, D)]}
|
[D] -> {op, FAnn, map_get_d, [Map1, Key, expr_to_fcode(Env, D)]}
|
||||||
end,
|
end,
|
||||||
{'let', Z1, GetExpr,
|
{'let', FAnn, Z1, GetExpr,
|
||||||
{op, FAnn, map_set, [M, Key, rename([{Z, Z1}], expr_to_fcode(bind_var(Env, Z), V))]}}
|
{op, FAnn, map_set, [M, Key, rename([{Z, Z1}], expr_to_fcode(bind_var(Env, Z), V))]}}
|
||||||
end)
|
end)
|
||||||
end end, Map1, KVs));
|
end end, Map1, KVs));
|
||||||
@ -801,14 +802,14 @@ make_if({var, X}, Then, Else) ->
|
|||||||
{'case', {bool, true}, {nosplit, Then}}]}};
|
{'case', {bool, true}, {nosplit, Then}}]}};
|
||||||
make_if(Cond, Then, Else) ->
|
make_if(Cond, Then, Else) ->
|
||||||
X = fresh_name(),
|
X = fresh_name(),
|
||||||
{'let', X, Cond, make_if({var, X}, Then, Else)}.
|
{'let', get_fann(Cond), X, Cond, make_if({var, X}, Then, Else)}.
|
||||||
|
|
||||||
make_if_no_else({var, X}, Then) ->
|
make_if_no_else({var, X}, Then) ->
|
||||||
{switch, {split, boolean, X,
|
{switch, {split, boolean, X,
|
||||||
[{'case', {bool, true}, {nosplit, Then}}]}};
|
[{'case', {bool, true}, {nosplit, Then}}]}};
|
||||||
make_if_no_else(Cond, Then) ->
|
make_if_no_else(Cond, Then) ->
|
||||||
X = fresh_name(),
|
X = fresh_name(),
|
||||||
{'let', X, Cond, make_if_no_else({var, X}, Then)}.
|
{'let', get_fann(Cond), X, Cond, make_if_no_else({var, X}, Then)}.
|
||||||
|
|
||||||
-spec make_tuple([fexpr()]) -> fexpr().
|
-spec make_tuple([fexpr()]) -> fexpr().
|
||||||
make_tuple([E]) -> E;
|
make_tuple([E]) -> E;
|
||||||
@ -1073,15 +1074,15 @@ decision_tree_to_fcode(true) -> {lit, {bool, true}};
|
|||||||
decision_tree_to_fcode({atom, B}) -> B;
|
decision_tree_to_fcode({atom, B}) -> B;
|
||||||
decision_tree_to_fcode({'if', A, Then, Else}) ->
|
decision_tree_to_fcode({'if', A, Then, Else}) ->
|
||||||
X = fresh_name(),
|
X = fresh_name(),
|
||||||
{'let', X, A,
|
{'let', [], X, A,
|
||||||
{switch, {split, boolean, X, [{'case', {bool, false}, {nosplit, decision_tree_to_fcode(Else)}},
|
{switch, {split, boolean, X, [{'case', {bool, false}, {nosplit, decision_tree_to_fcode(Else)}},
|
||||||
{'case', {bool, true}, {nosplit, decision_tree_to_fcode(Then)}}]}}}.
|
{'case', {bool, true}, {nosplit, decision_tree_to_fcode(Then)}}]}}}.
|
||||||
|
|
||||||
%% -- Statements --
|
%% -- Statements --
|
||||||
|
|
||||||
-spec stmts_to_fcode(env(), [aeso_syntax:stmt()]) -> fexpr().
|
-spec stmts_to_fcode(env(), [aeso_syntax:stmt()]) -> fexpr().
|
||||||
stmts_to_fcode(Env, [{letval, _, {typed, _, {id, _, X}, _}, Expr} | Stmts]) ->
|
stmts_to_fcode(Env, [{letval, Ann, {typed, _, {id, _, X}, _}, Expr} | Stmts]) ->
|
||||||
{'let', X, expr_to_fcode(Env, Expr), stmts_to_fcode(bind_var(Env, X), Stmts)};
|
{'let', to_fann(Ann), X, expr_to_fcode(Env, Expr), stmts_to_fcode(bind_var(Env, X), Stmts)};
|
||||||
stmts_to_fcode(Env, [{letval, Ann, Pat, Expr} | Stmts]) ->
|
stmts_to_fcode(Env, [{letval, Ann, Pat, Expr} | Stmts]) ->
|
||||||
expr_to_fcode(Env, {switch, Ann, Expr, [{'case', Ann, Pat, [{guarded, Ann, [], {block, Ann, Stmts}}]}]});
|
expr_to_fcode(Env, {switch, Ann, Expr, [{'case', Ann, Pat, [{guarded, Ann, [], {block, Ann, Stmts}}]}]});
|
||||||
stmts_to_fcode(Env, [{letfun, Ann, {id, _, X}, Args, _Type, [{guarded, _, [], Expr}]} | Stmts]) ->
|
stmts_to_fcode(Env, [{letfun, Ann, {id, _, X}, Args, _Type, [{guarded, _, [], Expr}]} | Stmts]) ->
|
||||||
@ -1089,12 +1090,12 @@ stmts_to_fcode(Env, [{letfun, Ann, {id, _, X}, Args, _Type, [{guarded, _, [], Ex
|
|||||||
{typed, Ann1, Id, T} -> {arg, Ann1, Id, T};
|
{typed, Ann1, Id, T} -> {arg, Ann1, Id, T};
|
||||||
_ -> internal_error({bad_arg, Arg}) %% pattern matching has been desugared
|
_ -> internal_error({bad_arg, Arg}) %% pattern matching has been desugared
|
||||||
end || Arg <- Args ],
|
end || Arg <- Args ],
|
||||||
{'let', X, expr_to_fcode(Env, {lam, Ann, LamArgs, Expr}),
|
{'let', to_fann(Ann), X, expr_to_fcode(Env, {lam, Ann, LamArgs, Expr}),
|
||||||
stmts_to_fcode(bind_var(Env, X), Stmts)};
|
stmts_to_fcode(bind_var(Env, X), Stmts)};
|
||||||
stmts_to_fcode(Env, [Expr]) ->
|
stmts_to_fcode(Env, [Expr]) ->
|
||||||
expr_to_fcode(Env, Expr);
|
expr_to_fcode(Env, Expr);
|
||||||
stmts_to_fcode(Env, [Expr | Stmts]) ->
|
stmts_to_fcode(Env, [Expr | Stmts]) ->
|
||||||
{'let', "_", expr_to_fcode(Env, Expr), stmts_to_fcode(Env, Stmts)}.
|
{'let', to_fann(aeso_syntax:get_ann(Expr)), "_", expr_to_fcode(Env, Expr), stmts_to_fcode(Env, Stmts)}.
|
||||||
|
|
||||||
%% -- Builtins --
|
%% -- Builtins --
|
||||||
|
|
||||||
@ -1122,7 +1123,7 @@ set_state({reg, R}, Val) ->
|
|||||||
set_state({tuple, Ls}, Val) ->
|
set_state({tuple, Ls}, Val) ->
|
||||||
?make_let(X, Val,
|
?make_let(X, Val,
|
||||||
lists:foldr(fun({I, L}, Code) ->
|
lists:foldr(fun({I, L}, Code) ->
|
||||||
{'let', "_", set_state(L, {proj, get_fann(Val), X, I - 1}), Code}
|
{'let', [], "_", set_state(L, {proj, get_fann(Val), X, I - 1}), Code}
|
||||||
end, {tuple, []}, indexed(Ls))).
|
end, {tuple, []}, indexed(Ls))).
|
||||||
|
|
||||||
get_state({reg, R}) ->
|
get_state({reg, R}) ->
|
||||||
@ -1246,7 +1247,7 @@ lifted_fun([Z], Xs, Body) ->
|
|||||||
body => Body };
|
body => Body };
|
||||||
lifted_fun(FVs, Xs, Body) ->
|
lifted_fun(FVs, Xs, Body) ->
|
||||||
Z = "%env",
|
Z = "%env",
|
||||||
Proj = fun({I, Y}, E) -> {'let', Y, {proj, get_fann(Body), {var, Z}, I - 1}, E} end,
|
Proj = fun({I, Y}, E) -> {'let', get_fann(Body), Y, {proj, get_fann(Body), {var, Z}, I - 1}, E} end,
|
||||||
#{ attrs => [private],
|
#{ attrs => [private],
|
||||||
args => [{Z, any} | [{X, any} || X <- Xs]],
|
args => [{Z, any} | [{X, any} || X <- Xs]],
|
||||||
return => any,
|
return => any,
|
||||||
@ -1295,7 +1296,7 @@ lambda_lift_expr(Layout, Expr) ->
|
|||||||
{proj, Ann, A, I} -> {proj, Ann, lambda_lift_expr(Layout, A), I};
|
{proj, Ann, A, I} -> {proj, Ann, lambda_lift_expr(Layout, A), I};
|
||||||
{set_proj, Ann, A, I, B} -> {set_proj, Ann, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)};
|
{set_proj, Ann, A, I, B} -> {set_proj, Ann, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)};
|
||||||
{op, Ann, Op, As} -> {op, Ann, Op, lambda_lift_exprs(Layout, As)};
|
{op, Ann, Op, As} -> {op, Ann, Op, lambda_lift_exprs(Layout, As)};
|
||||||
{'let', X, A, B} -> {'let', X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)};
|
{'let', Ann, X, A, B} -> {'let', Ann, X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)};
|
||||||
{funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)};
|
{funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)};
|
||||||
{set_state, Ann, R, A} -> {set_state, Ann, R, lambda_lift_expr(Layout, A)};
|
{set_state, Ann, R, A} -> {set_state, Ann, R, lambda_lift_expr(Layout, A)};
|
||||||
{get_state, _} -> Expr;
|
{get_state, _} -> Expr;
|
||||||
@ -1392,8 +1393,8 @@ inline_local_functions(_, Expr) -> Expr.
|
|||||||
|
|
||||||
let_floating(Expr) -> bottom_up(fun let_float/2, Expr).
|
let_floating(Expr) -> bottom_up(fun let_float/2, Expr).
|
||||||
|
|
||||||
let_float(_, {'let', X, E, Body}) ->
|
let_float(_, {'let', Ann, X, E, Body}) ->
|
||||||
pull_out_let({'let', X, {here, E}, Body});
|
pull_out_let({'let', Ann, X, {here, E}, Body});
|
||||||
let_float(_, {proj, Ann, E, I}) ->
|
let_float(_, {proj, Ann, E, I}) ->
|
||||||
pull_out_let({proj, Ann, {here, E}, I});
|
pull_out_let({proj, Ann, {here, E}, I});
|
||||||
let_float(_, {set_proj, Ann, E, I, V}) ->
|
let_float(_, {set_proj, Ann, E, I, V}) ->
|
||||||
@ -1424,7 +1425,7 @@ pull_out_let(Es) when is_list(Es) ->
|
|||||||
%% Also renames the variables to fresh names
|
%% Also renames the variables to fresh names
|
||||||
let_view(E) -> let_view(E, [], []).
|
let_view(E) -> let_view(E, [], []).
|
||||||
|
|
||||||
let_view({'let', X, E, Rest}, Ren, Lets) ->
|
let_view({'let', _, X, E, Rest}, Ren, Lets) ->
|
||||||
Z = fresh_name(),
|
Z = fresh_name(),
|
||||||
let_view(Rest, [{X, Z} | Ren], [{Z, rename(Ren, E)} | Lets]);
|
let_view(Rest, [{X, Z} | Ren], [{Z, rename(Ren, E)} | Lets]);
|
||||||
let_view(E, Ren, Lets) ->
|
let_view(E, Ren, Lets) ->
|
||||||
@ -1440,7 +1441,7 @@ simplifier(Expr) ->
|
|||||||
|
|
||||||
%% (e₀, .., en).i ->
|
%% (e₀, .., en).i ->
|
||||||
%% let _ = e₀ in .. let x = ei in .. let _ = en in x
|
%% let _ = e₀ in .. let x = ei in .. let _ = en in x
|
||||||
simplify(_Env, {proj, _, {tuple, Es}, I}) ->
|
simplify(_Env, {proj, FAnn, {tuple, Es}, I}) ->
|
||||||
It = lists:nth(I + 1, Es),
|
It = lists:nth(I + 1, Es),
|
||||||
X = fresh_name(),
|
X = fresh_name(),
|
||||||
Dup = safe_to_duplicate(It),
|
Dup = safe_to_duplicate(It),
|
||||||
@ -1449,12 +1450,12 @@ simplify(_Env, {proj, _, {tuple, Es}, I}) ->
|
|||||||
fun({J, E}, Rest) when I == J ->
|
fun({J, E}, Rest) when I == J ->
|
||||||
case Dup of
|
case Dup of
|
||||||
true -> Rest;
|
true -> Rest;
|
||||||
false -> {'let', X, E, Rest}
|
false -> {'let', FAnn, X, E, Rest}
|
||||||
end;
|
end;
|
||||||
({_, E}, Rest) ->
|
({_, E}, Rest) ->
|
||||||
case read_only(E) of
|
case read_only(E) of
|
||||||
true -> Rest;
|
true -> Rest;
|
||||||
false -> {'let', "_", E, Rest}
|
false -> {'let', FAnn, "_", E, Rest}
|
||||||
end
|
end
|
||||||
end, Val, indexed(Es));
|
end, Val, indexed(Es));
|
||||||
|
|
||||||
@ -1579,10 +1580,10 @@ constructor_form(Env, Expr) ->
|
|||||||
|
|
||||||
drop_unused_lets(Expr) -> bottom_up(fun drop_unused_lets/2, Expr).
|
drop_unused_lets(Expr) -> bottom_up(fun drop_unused_lets/2, Expr).
|
||||||
|
|
||||||
drop_unused_lets(_, {'let', X, E, Body} = Expr) ->
|
drop_unused_lets(_, {'let', Ann, X, E, Body} = Expr) ->
|
||||||
case {read_only(E), not lists:member(X, free_vars(Body))} of
|
case {read_only(E), not lists:member(X, free_vars(Body))} of
|
||||||
{true, true} -> Body;
|
{true, true} -> Body;
|
||||||
{false, true} -> {'let', "_", E, Body};
|
{false, true} -> {'let', Ann, "_", E, Body};
|
||||||
_ -> Expr
|
_ -> Expr
|
||||||
end;
|
end;
|
||||||
drop_unused_lets(_, Expr) -> Expr.
|
drop_unused_lets(_, Expr) -> Expr.
|
||||||
@ -1618,7 +1619,7 @@ read_only({switch, Split}) -> read_only(Split);
|
|||||||
read_only({split, _, _, Cases}) -> read_only(Cases);
|
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({'case', _, Split}) -> read_only(Split);
|
||||||
read_only({'let', _, A, B}) -> read_only([A, B]);
|
read_only({'let', _, _, A, B}) -> read_only([A, B]);
|
||||||
read_only({funcall, _, _, _}) -> false;
|
read_only({funcall, _, _, _}) -> false;
|
||||||
read_only({closure, _, _, _}) -> internal_error(no_closures_here);
|
read_only({closure, _, _, _}) -> internal_error(no_closures_here);
|
||||||
read_only(Es) when is_list(Es) -> lists:all(fun read_only/1, Es).
|
read_only(Es) when is_list(Es) -> lists:all(fun read_only/1, Es).
|
||||||
@ -1846,7 +1847,7 @@ free_vars(Expr) ->
|
|||||||
{proj, _, A, _} -> free_vars(A);
|
{proj, _, A, _} -> free_vars(A);
|
||||||
{set_proj, _, A, _, B} -> free_vars([A, B]);
|
{set_proj, _, A, _, B} -> free_vars([A, B]);
|
||||||
{op, _, _, As} -> free_vars(As);
|
{op, _, _, As} -> free_vars(As);
|
||||||
{'let', X, A, B} -> free_vars([A, {lam, [X], B}]);
|
{'let', _, X, A, B} -> free_vars([A, {lam, [X], B}]);
|
||||||
{funcall, _, A, Bs} -> free_vars([A | Bs]);
|
{funcall, _, A, Bs} -> free_vars([A | Bs]);
|
||||||
{set_state, _, _, A} -> free_vars(A);
|
{set_state, _, _, A} -> free_vars(A);
|
||||||
{get_state, _} -> [];
|
{get_state, _} -> [];
|
||||||
@ -1877,7 +1878,7 @@ used_defs(Expr) ->
|
|||||||
{proj, _, A, _} -> used_defs(A);
|
{proj, _, A, _} -> used_defs(A);
|
||||||
{set_proj, _, A, _, B} -> used_defs([A, B]);
|
{set_proj, _, A, _, B} -> used_defs([A, B]);
|
||||||
{op, _, _, As} -> used_defs(As);
|
{op, _, _, As} -> used_defs(As);
|
||||||
{'let', _, A, B} -> used_defs([A, B]);
|
{'let', _, _, A, B} -> used_defs([A, B]);
|
||||||
{funcall, _, A, Bs} -> used_defs([A | Bs]);
|
{funcall, _, A, Bs} -> used_defs([A | Bs]);
|
||||||
{set_state, _, _, A} -> used_defs(A);
|
{set_state, _, _, A} -> used_defs(A);
|
||||||
{get_state, _} -> [];
|
{get_state, _} -> [];
|
||||||
@ -1914,7 +1915,7 @@ bottom_up(F, Env, Expr) ->
|
|||||||
{closure, Ann, F, CEnv} -> {closure, Ann, F, bottom_up(F, Env, CEnv)};
|
{closure, Ann, F, CEnv} -> {closure, Ann, F, bottom_up(F, Env, CEnv)};
|
||||||
{switch, Split} -> {switch, bottom_up(F, Env, Split)};
|
{switch, Split} -> {switch, bottom_up(F, Env, Split)};
|
||||||
{lam, Xs, B} -> {lam, Xs, bottom_up(F, Env, B)};
|
{lam, Xs, B} -> {lam, Xs, bottom_up(F, Env, B)};
|
||||||
{'let', X, E, Body} ->
|
{'let', Ann, X, E, Body} ->
|
||||||
E1 = bottom_up(F, Env, E),
|
E1 = bottom_up(F, Env, E),
|
||||||
%% Always freshen user variables to avoid shadowing issues.
|
%% Always freshen user variables to avoid shadowing issues.
|
||||||
ShouldFreshen = fun(Y = "%" ++ _) -> maps:is_key(Y, Env);
|
ShouldFreshen = fun(Y = "%" ++ _) -> maps:is_key(Y, Env);
|
||||||
@ -1923,10 +1924,10 @@ bottom_up(F, Env, Expr) ->
|
|||||||
true ->
|
true ->
|
||||||
Z = fresh_name_save(X),
|
Z = fresh_name_save(X),
|
||||||
Env1 = Env#{ Z => E1 },
|
Env1 = Env#{ Z => E1 },
|
||||||
{'let', Z, E1, bottom_up(F, Env1, rename([{X, Z}], Body))};
|
{'let', Ann, Z, E1, bottom_up(F, Env1, rename([{X, Z}], Body))};
|
||||||
false ->
|
false ->
|
||||||
Env1 = Env#{ X => E1 },
|
Env1 = Env#{ X => E1 },
|
||||||
{'let', X, E1, bottom_up(F, Env1, Body)}
|
{'let', Ann, X, E1, bottom_up(F, Env1, Body)}
|
||||||
end;
|
end;
|
||||||
{split, Type, X, Cases} -> {split, Type, X, [bottom_up(F, Env, Case) || Case <- Cases]};
|
{split, Type, X, Cases} -> {split, Type, X, [bottom_up(F, Env, Case) || Case <- Cases]};
|
||||||
{nosplit, E} -> {nosplit, bottom_up(F, Env, E)};
|
{nosplit, E} -> {nosplit, bottom_up(F, Env, E)};
|
||||||
@ -1974,9 +1975,9 @@ rename(Ren, Expr) ->
|
|||||||
{lam, Xs, B} ->
|
{lam, Xs, B} ->
|
||||||
{Zs, Ren1} = rename_bindings(Ren, Xs),
|
{Zs, Ren1} = rename_bindings(Ren, Xs),
|
||||||
{lam, Zs, rename(Ren1, B)};
|
{lam, Zs, rename(Ren1, B)};
|
||||||
{'let', X, E, Body} ->
|
{'let', Ann, X, E, Body} ->
|
||||||
{Z, Ren1} = rename_binding(Ren, X),
|
{Z, Ren1} = rename_binding(Ren, X),
|
||||||
{'let', Z, rename(Ren, E), rename(Ren1, Body)}
|
{'let', Ann, Z, rename(Ren, E), rename(Ren1, Body)}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
rename_var(Ren, X) -> proplists:get_value(X, Ren, X).
|
rename_var(Ren, X) -> proplists:get_value(X, Ren, X).
|
||||||
@ -2190,8 +2191,8 @@ pp_fexpr({op, _, Op, [A] = Args}) ->
|
|||||||
end;
|
end;
|
||||||
pp_fexpr({op, _, Op, As}) ->
|
pp_fexpr({op, _, Op, As}) ->
|
||||||
pp_beside(pp_text(Op), pp_fexpr({tuple, As}));
|
pp_beside(pp_text(Op), pp_fexpr({tuple, As}));
|
||||||
pp_fexpr({'let', _, _, _} = Expr) ->
|
pp_fexpr({'let', _, _, _, _} = Expr) ->
|
||||||
Lets = fun Lets({'let', Y, C, D}) ->
|
Lets = fun Lets({'let', _, Y, C, D}) ->
|
||||||
{Ls, E} = Lets(D),
|
{Ls, E} = Lets(D),
|
||||||
{[{Y, C} | Ls], E};
|
{[{Y, C} | Ls], E};
|
||||||
Lets(E) -> {[], E} end,
|
Lets(E) -> {[], E} end,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user