Fix bug in compilation of Map.lookup
This commit is contained in:
parent
0532c54ca0
commit
e44a890292
@ -330,6 +330,19 @@ type_to_fcode(_Env, _Sub, Type) ->
|
|||||||
args_to_fcode(Env, Args) ->
|
args_to_fcode(Env, Args) ->
|
||||||
[ {Name, type_to_fcode(Env, Type)} || {arg, _, {id, _, Name}, Type} <- Args ].
|
[ {Name, type_to_fcode(Env, Type)} || {arg, _, {id, _, Name}, Type} <- Args ].
|
||||||
|
|
||||||
|
-define(make_let(X, Expr, Body),
|
||||||
|
make_let(Expr, fun(X) -> Body end)).
|
||||||
|
|
||||||
|
make_let(Expr, Body) ->
|
||||||
|
case Expr of
|
||||||
|
{var, _} -> Body(Expr);
|
||||||
|
{lit, {int, _}} -> Body(Expr);
|
||||||
|
{lit, {bool, _}} -> Body(Expr);
|
||||||
|
_ ->
|
||||||
|
X = fresh_name(),
|
||||||
|
{'let', X, Expr, Body({var, X})}
|
||||||
|
end.
|
||||||
|
|
||||||
-spec expr_to_fcode(env(), aeso_syntax:expr()) -> fexpr().
|
-spec expr_to_fcode(env(), aeso_syntax:expr()) -> fexpr().
|
||||||
expr_to_fcode(Env, {typed, _, Expr, Type}) ->
|
expr_to_fcode(Env, {typed, _, Expr, Type}) ->
|
||||||
expr_to_fcode(Env, Type, Expr);
|
expr_to_fcode(Env, Type, Expr);
|
||||||
@ -415,17 +428,9 @@ expr_to_fcode(Env, _Type, {list, _, Es}) ->
|
|||||||
|
|
||||||
%% Conditionals
|
%% Conditionals
|
||||||
expr_to_fcode(Env, _Type, {'if', _, Cond, Then, Else}) ->
|
expr_to_fcode(Env, _Type, {'if', _, Cond, Then, Else}) ->
|
||||||
Switch = fun(X) ->
|
make_if(expr_to_fcode(Env, Cond),
|
||||||
{switch, {split, boolean, X,
|
expr_to_fcode(Env, Then),
|
||||||
[{'case', {bool, false}, {nosplit, expr_to_fcode(Env, Else)}},
|
expr_to_fcode(Env, Else));
|
||||||
{'case', {bool, true}, {nosplit, expr_to_fcode(Env, Then)}}]}}
|
|
||||||
end,
|
|
||||||
case Cond of
|
|
||||||
{var, X} -> Switch(X);
|
|
||||||
_ ->
|
|
||||||
X = fresh_name(),
|
|
||||||
{'let', X, expr_to_fcode(Env, Cond), Switch(X)}
|
|
||||||
end;
|
|
||||||
|
|
||||||
%% Switch
|
%% Switch
|
||||||
expr_to_fcode(Env, _, {switch, _, Expr = {typed, _, E, Type}, Alts}) ->
|
expr_to_fcode(Env, _, {switch, _, Expr = {typed, _, E, Type}, Alts}) ->
|
||||||
@ -484,25 +489,24 @@ expr_to_fcode(Env, Type, {map, Ann, KVs}) ->
|
|||||||
Fields = [{field, Ann, [{map_get, Ann, K}], V} || {K, V} <- KVs],
|
Fields = [{field, Ann, [{map_get, Ann, K}], V} || {K, V} <- KVs],
|
||||||
expr_to_fcode(Env, Type, {map, Ann, {map, Ann, []}, Fields});
|
expr_to_fcode(Env, Type, {map, Ann, {map, Ann, []}, Fields});
|
||||||
expr_to_fcode(Env, _Type, {map, _, Map, KVs}) ->
|
expr_to_fcode(Env, _Type, {map, _, Map, KVs}) ->
|
||||||
X = fresh_name(),
|
?make_let(Map1, expr_to_fcode(Env, Map),
|
||||||
Map1 = {var, X},
|
|
||||||
{'let', X, expr_to_fcode(Env, Map),
|
|
||||||
lists:foldr(fun(Fld, M) ->
|
lists:foldr(fun(Fld, M) ->
|
||||||
case Fld of
|
case Fld of
|
||||||
{field, _, [{map_get, _, K}], V} ->
|
{field, _, [{map_get, _, K}], V} ->
|
||||||
{op, map_set, [M, expr_to_fcode(Env, K), expr_to_fcode(Env, V)]};
|
{op, map_set, [M, expr_to_fcode(Env, K), expr_to_fcode(Env, V)]};
|
||||||
{field_upd, _, [MapGet], {typed, _, {lam, _, [{arg, _, {id, _, Z}, _}], V}, _}} when element(1, MapGet) == map_get ->
|
{field_upd, _, [MapGet], {typed, _, {lam, _, [{arg, _, {id, _, Z}, _}], V}, _}} when element(1, MapGet) == map_get ->
|
||||||
Y = fresh_name(),
|
|
||||||
[map_get, _, K | Default] = tuple_to_list(MapGet),
|
[map_get, _, K | Default] = tuple_to_list(MapGet),
|
||||||
GetExpr =
|
?make_let(Key, expr_to_fcode(Env, K),
|
||||||
case Default of
|
begin
|
||||||
[] -> {op, map_get, [Map1, {var, Y}]};
|
GetExpr =
|
||||||
[D] -> {op, map_get_d, [Map1, {var, Y}, expr_to_fcode(Env, D)]}
|
case Default of
|
||||||
end,
|
[] -> {op, map_get, [Map1, Key]};
|
||||||
{'let', Y, expr_to_fcode(Env, K),
|
[D] -> {op, map_get_d, [Map1, Key, expr_to_fcode(Env, D)]}
|
||||||
{'let', Z, GetExpr,
|
end,
|
||||||
{op, map_set, [M, {var, Y}, expr_to_fcode(bind_var(Env, Z), V)]}}}
|
{'let', Z, GetExpr,
|
||||||
end end, Map1, KVs)};
|
{op, map_set, [M, Key, expr_to_fcode(bind_var(Env, Z), V)]}}
|
||||||
|
end)
|
||||||
|
end end, Map1, KVs));
|
||||||
expr_to_fcode(Env, _Type, {map_get, _, Map, Key}) ->
|
expr_to_fcode(Env, _Type, {map_get, _, Map, Key}) ->
|
||||||
{op, map_get, [expr_to_fcode(Env, Map), expr_to_fcode(Env, Key)]};
|
{op, map_get, [expr_to_fcode(Env, Map), expr_to_fcode(Env, Key)]};
|
||||||
expr_to_fcode(Env, _Type, {map_get, _, Map, Key, Def}) ->
|
expr_to_fcode(Env, _Type, {map_get, _, Map, Key, Def}) ->
|
||||||
@ -516,6 +520,14 @@ expr_to_fcode(Env, _Type, {lam, _, Args, Body}) ->
|
|||||||
expr_to_fcode(_Env, Type, Expr) ->
|
expr_to_fcode(_Env, Type, Expr) ->
|
||||||
error({todo, {Expr, ':', Type}}).
|
error({todo, {Expr, ':', Type}}).
|
||||||
|
|
||||||
|
make_if({var, X}, Then, Else) ->
|
||||||
|
{switch, {split, boolean, X,
|
||||||
|
[{'case', {bool, false}, {nosplit, Else}},
|
||||||
|
{'case', {bool, true}, {nosplit, Then}}]}};
|
||||||
|
make_if(Cond, Then, Else) ->
|
||||||
|
X = fresh_name(),
|
||||||
|
{'let', X, Cond, make_if({var, X}, Then, Else)}.
|
||||||
|
|
||||||
%% -- Pattern matching --
|
%% -- Pattern matching --
|
||||||
|
|
||||||
-spec alts_to_fcode(env(), ftype(), var_name(), [aeso_syntax:alt()]) -> fsplit().
|
-spec alts_to_fcode(env(), ftype(), var_name(), [aeso_syntax:alt()]) -> fsplit().
|
||||||
@ -744,8 +756,14 @@ op_builtins() ->
|
|||||||
bits_set, bits_clear, bits_test, bits_sum, bits_intersection, bits_union,
|
bits_set, bits_clear, bits_test, bits_sum, bits_intersection, bits_union,
|
||||||
bits_difference, int_to_str, address_to_str].
|
bits_difference, int_to_str, address_to_str].
|
||||||
|
|
||||||
builtin_to_fcode(map_lookup, [Key, Map]) ->
|
builtin_to_fcode(map_member, [Key, Map]) ->
|
||||||
{op, map_get, [Map, Key]};
|
{op, map_member, [Map, Key]};
|
||||||
|
builtin_to_fcode(map_lookup, [Key0, Map0]) ->
|
||||||
|
?make_let(Key, Key0,
|
||||||
|
?make_let(Map, Map0,
|
||||||
|
make_if({op, map_member, [Map, Key]},
|
||||||
|
{con, [0, 1], 1, [{op, map_get, [Map, Key]}]},
|
||||||
|
{con, [0, 1], 0, []})));
|
||||||
builtin_to_fcode(map_lookup_default, [Key, Map, Def]) ->
|
builtin_to_fcode(map_lookup_default, [Key, Map, Def]) ->
|
||||||
{op, map_get_d, [Map, Key, Def]};
|
{op, map_get_d, [Map, Key, Def]};
|
||||||
builtin_to_fcode(Builtin, Args) ->
|
builtin_to_fcode(Builtin, Args) ->
|
||||||
|
@ -142,7 +142,7 @@ function_to_scode(ContractName, Functions, _Name, Args, Body, ResType, _Options)
|
|||||||
SCode = to_scode(init_env(ContractName, Functions, Args), Body),
|
SCode = to_scode(init_env(ContractName, Functions, Args), Body),
|
||||||
{{ArgTypes, type_to_scode(ResType)}, SCode}.
|
{{ArgTypes, type_to_scode(ResType)}, SCode}.
|
||||||
|
|
||||||
type_to_scode({variant, Cons}) -> {variant, lists:map(fun length/1, Cons)};
|
type_to_scode({variant, Cons}) -> {variant, lists:map(fun(T) -> type_to_scode({tuple, T}) end, Cons)};
|
||||||
type_to_scode({list, Type}) -> {list, type_to_scode(Type)};
|
type_to_scode({list, Type}) -> {list, type_to_scode(Type)};
|
||||||
type_to_scode({tuple, Types}) -> {tuple, lists:map(fun type_to_scode/1, Types)};
|
type_to_scode({tuple, Types}) -> {tuple, lists:map(fun type_to_scode/1, Types)};
|
||||||
type_to_scode({map, Key, Val}) -> {map, type_to_scode(Key), type_to_scode(Val)};
|
type_to_scode({map, Key, Val}) -> {map, type_to_scode(Key), type_to_scode(Val)};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user