Use SETELEMENT instruction

This commit is contained in:
Ulf Norell 2019-04-23 12:36:14 +02:00
parent f896b84221
commit ed60cd8ddc
2 changed files with 28 additions and 14 deletions

View File

@ -32,6 +32,7 @@
| {var, var_name()} | {var, var_name()}
| {tuple, [fexpr()]} | {tuple, [fexpr()]}
| {proj, fexpr(), integer()} | {proj, fexpr(), integer()}
| {set_proj, fexpr(), integer(), fexpr()} %% tuple, field, new_value
| {binop, binop(), fexpr(), fexpr()} | {binop, binop(), fexpr(), fexpr()}
| {'let', var_name(), fexpr(), fexpr()} | {'let', var_name(), fexpr(), fexpr()}
| {switch, fsplit()}. | {switch, fsplit()}.
@ -236,17 +237,23 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, _Ann, Fields}) ->
{tuple, lists:map(FVal, FieldTypes)}; {tuple, lists:map(FVal, FieldTypes)};
expr_to_fcode(Env, {record_t, FieldTypes}, {record, _Ann, Rec, Fields}) -> expr_to_fcode(Env, {record_t, FieldTypes}, {record, _Ann, Rec, Fields}) ->
%% TODO: update once we have a SETELEMENT instruction
X = fresh_name(), X = fresh_name(),
Proj = fun(I) -> {proj, {var, X}, I - 1} end, Proj = fun(I) -> {proj, {var, X}, I - 1} end,
Comp = fun(I, FT) -> Comp = fun({I, false}) -> Proj(I);
case field_value(FT, Fields) of ({_, {set, E}}) -> expr_to_fcode(Env, E);
false -> Proj(I); ({I, {upd, Z, E}}) -> {'let', Z, Proj(I), expr_to_fcode(Env, E)}
{set, E} -> expr_to_fcode(Env, E); end,
{upd, Z, E} -> {'let', Z, Proj(I), expr_to_fcode(Env, E)} Set = fun({_, false}, R) -> R;
end end, ({I, {set, E}}, R) -> {set_proj, R, I - 1, expr_to_fcode(Env, E)};
{'let', X, expr_to_fcode(Env, Rec), ({I, {upd, Z, E}}, R) -> {set_proj, R, I - 1, {'let', Z, Proj(I), expr_to_fcode(Env, E)}}
{tuple, [Comp(I, FT) || {I, FT} <- indexed(FieldTypes)]}}; end,
Expand = length(Fields) == length(FieldTypes),
Updates = [ {I, field_value(FT, Fields)} || {I, FT} <- indexed(FieldTypes) ],
Body = case Expand of
true -> {tuple, lists:map(Comp, Updates)};
false -> lists:foldr(Set, {var, X}, Updates)
end,
{'let', X, expr_to_fcode(Env, Rec), Body};
%% Lists %% Lists
expr_to_fcode(Env, _Type, {list, _, Es}) -> expr_to_fcode(Env, _Type, {list, _, Es}) ->
@ -411,6 +418,7 @@ rename(Ren, Expr) ->
{var, X} -> {var, rename_var(Ren, X)}; {var, X} -> {var, rename_var(Ren, X)};
{tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]};
{proj, E, I} -> {proj, rename(Ren, E), I}; {proj, E, I} -> {proj, rename(Ren, E), I};
{set_proj, R, I, E} -> {set_proj, rename(Ren, R), I, rename(Ren, E)};
{binop, Op, E1, E2} -> {binop, Op, rename(Ren, E1), rename(Ren, E2)}; {binop, Op, E1, E2} -> {binop, Op, rename(Ren, E1), rename(Ren, E2)};
{'let', X, E, Body} -> {'let', X, E, Body} ->
{Z, Ren1} = rename_binding(Ren, X), {Z, Ren1} = rename_binding(Ren, X),

View File

@ -154,6 +154,11 @@ to_scode(Env, {proj, E, I}) ->
[to_scode(Env, E), [to_scode(Env, E),
aeb_fate_code:element_op(?a, ?i(I), ?a)]; aeb_fate_code:element_op(?a, ?i(I), ?a)];
to_scode(Env, {set_proj, R, I, E}) ->
[to_scode(Env, E),
to_scode(Env, R),
aeb_fate_code:setelement(?a, ?i(I), ?a, ?a)];
to_scode(Env, {binop, Op, A, B}) -> to_scode(Env, {binop, Op, A, B}) ->
[ to_scode(notail(Env), B), [ to_scode(notail(Env), B),
to_scode(Env, A), to_scode(Env, A),
@ -425,6 +430,7 @@ attributes(I) ->
{'NOT', A, B} -> Pure(A, B); {'NOT', A, B} -> Pure(A, B);
{'TUPLE', _} -> Pure(?a, []); {'TUPLE', _} -> Pure(?a, []);
{'ELEMENT', A, B, C} -> Pure(A, [B, C]); {'ELEMENT', A, B, C} -> Pure(A, [B, C]);
{'SETELEMENT', A, B, C, D} -> Pure(A, [B, C, D]);
{'MAP_EMPTY', A} -> Pure(A, []); {'MAP_EMPTY', A} -> Pure(A, []);
{'MAP_LOOKUP', A, B, C} -> Pure(A, [B, C]); {'MAP_LOOKUP', A, B, C} -> Pure(A, [B, C]);
{'MAP_LOOKUPD', A, B, C, D} -> Pure(A, [B, C, D]); {'MAP_LOOKUPD', A, B, C, D} -> Pure(A, [B, C, D]);
@ -732,12 +738,12 @@ r_write_to_dead_var(_, _) -> false.
op_view({Op, R, A, B}) when ?IsBinOp(Op) -> op_view({Op, R, A, B}) when ?IsBinOp(Op) ->
{Op, R, [A, B]}; {Op, R, [A, B]};
op_view({Op, R, A}) when ?IsUnOp(Op) -> op_view({Op, R, A}) when ?IsUnOp(Op); Op == 'STORE' ->
{Op, R, [A]}; {Op, R, [A]};
op_view({'STORE', R, A}) -> op_view({Op, R, A, B, C}) when Op == 'SETELEMENT' ->
{'STORE', R, [A]}; {Op, R, [A, B, C]};
op_view({'NIL', R}) -> op_view({Op, R}) when Op == 'NIL' ->
{'NIL', R, []}; {Op, R, []};
op_view(_) -> op_view(_) ->
false. false.