Use SETELEMENT instruction
This commit is contained in:
parent
f896b84221
commit
ed60cd8ddc
@ -32,6 +32,7 @@
|
||||
| {var, var_name()}
|
||||
| {tuple, [fexpr()]}
|
||||
| {proj, fexpr(), integer()}
|
||||
| {set_proj, fexpr(), integer(), fexpr()} %% tuple, field, new_value
|
||||
| {binop, binop(), fexpr(), fexpr()}
|
||||
| {'let', var_name(), fexpr(), fexpr()}
|
||||
| {switch, fsplit()}.
|
||||
@ -236,17 +237,23 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, _Ann, Fields}) ->
|
||||
{tuple, lists:map(FVal, FieldTypes)};
|
||||
|
||||
expr_to_fcode(Env, {record_t, FieldTypes}, {record, _Ann, Rec, Fields}) ->
|
||||
%% TODO: update once we have a SETELEMENT instruction
|
||||
X = fresh_name(),
|
||||
Proj = fun(I) -> {proj, {var, X}, I - 1} end,
|
||||
Comp = fun(I, FT) ->
|
||||
case field_value(FT, Fields) of
|
||||
false -> Proj(I);
|
||||
{set, E} -> expr_to_fcode(Env, E);
|
||||
{upd, Z, E} -> {'let', Z, Proj(I), expr_to_fcode(Env, E)}
|
||||
end end,
|
||||
{'let', X, expr_to_fcode(Env, Rec),
|
||||
{tuple, [Comp(I, FT) || {I, FT} <- indexed(FieldTypes)]}};
|
||||
Comp = fun({I, false}) -> Proj(I);
|
||||
({_, {set, E}}) -> expr_to_fcode(Env, E);
|
||||
({I, {upd, Z, E}}) -> {'let', Z, Proj(I), expr_to_fcode(Env, E)}
|
||||
end,
|
||||
Set = fun({_, false}, R) -> R;
|
||||
({I, {set, E}}, R) -> {set_proj, R, I - 1, expr_to_fcode(Env, E)};
|
||||
({I, {upd, Z, E}}, R) -> {set_proj, R, I - 1, {'let', Z, Proj(I), expr_to_fcode(Env, E)}}
|
||||
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
|
||||
expr_to_fcode(Env, _Type, {list, _, Es}) ->
|
||||
@ -411,6 +418,7 @@ rename(Ren, Expr) ->
|
||||
{var, X} -> {var, rename_var(Ren, X)};
|
||||
{tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]};
|
||||
{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)};
|
||||
{'let', X, E, Body} ->
|
||||
{Z, Ren1} = rename_binding(Ren, X),
|
||||
|
@ -154,6 +154,11 @@ to_scode(Env, {proj, E, I}) ->
|
||||
[to_scode(Env, E),
|
||||
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(notail(Env), B),
|
||||
to_scode(Env, A),
|
||||
@ -425,6 +430,7 @@ attributes(I) ->
|
||||
{'NOT', A, B} -> Pure(A, B);
|
||||
{'TUPLE', _} -> Pure(?a, []);
|
||||
{'ELEMENT', A, B, C} -> Pure(A, [B, C]);
|
||||
{'SETELEMENT', A, B, C, D} -> Pure(A, [B, C, D]);
|
||||
{'MAP_EMPTY', A} -> Pure(A, []);
|
||||
{'MAP_LOOKUP', A, B, C} -> Pure(A, [B, C]);
|
||||
{'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, 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_view({'STORE', R, A}) ->
|
||||
{'STORE', R, [A]};
|
||||
op_view({'NIL', R}) ->
|
||||
{'NIL', R, []};
|
||||
op_view({Op, R, A, B, C}) when Op == 'SETELEMENT' ->
|
||||
{Op, R, [A, B, C]};
|
||||
op_view({Op, R}) when Op == 'NIL' ->
|
||||
{Op, R, []};
|
||||
op_view(_) ->
|
||||
false.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user