diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 2357079..f24795b 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -330,6 +330,19 @@ type_to_fcode(_Env, _Sub, Type) -> args_to_fcode(Env, 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(). expr_to_fcode(Env, {typed, _, Expr, Type}) -> expr_to_fcode(Env, Type, Expr); @@ -415,17 +428,9 @@ expr_to_fcode(Env, _Type, {list, _, Es}) -> %% Conditionals expr_to_fcode(Env, _Type, {'if', _, Cond, Then, Else}) -> - Switch = fun(X) -> - {switch, {split, boolean, X, - [{'case', {bool, false}, {nosplit, 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; + make_if(expr_to_fcode(Env, Cond), + expr_to_fcode(Env, Then), + expr_to_fcode(Env, Else)); %% Switch 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], expr_to_fcode(Env, Type, {map, Ann, {map, Ann, []}, Fields}); expr_to_fcode(Env, _Type, {map, _, Map, KVs}) -> - X = fresh_name(), - Map1 = {var, X}, - {'let', X, expr_to_fcode(Env, Map), + ?make_let(Map1, expr_to_fcode(Env, Map), lists:foldr(fun(Fld, M) -> case Fld of {field, _, [{map_get, _, K}], 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 -> - Y = fresh_name(), [map_get, _, K | Default] = tuple_to_list(MapGet), - GetExpr = - case Default of - [] -> {op, map_get, [Map1, {var, Y}]}; - [D] -> {op, map_get_d, [Map1, {var, Y}, expr_to_fcode(Env, D)]} - end, - {'let', Y, expr_to_fcode(Env, K), - {'let', Z, GetExpr, - {op, map_set, [M, {var, Y}, expr_to_fcode(bind_var(Env, Z), V)]}}} - end end, Map1, KVs)}; + ?make_let(Key, expr_to_fcode(Env, K), + begin + GetExpr = + case Default of + [] -> {op, map_get, [Map1, Key]}; + [D] -> {op, map_get_d, [Map1, Key, expr_to_fcode(Env, D)]} + end, + {'let', Z, GetExpr, + {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}) -> {op, map_get, [expr_to_fcode(Env, Map), expr_to_fcode(Env, Key)]}; 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) -> 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 -- -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_difference, int_to_str, address_to_str]. -builtin_to_fcode(map_lookup, [Key, Map]) -> - {op, map_get, [Map, Key]}; +builtin_to_fcode(map_member, [Key, Map]) -> + {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]) -> {op, map_get_d, [Map, Key, Def]}; builtin_to_fcode(Builtin, Args) -> diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index ac69592..a30dd1e 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -142,7 +142,7 @@ function_to_scode(ContractName, Functions, _Name, Args, Body, ResType, _Options) SCode = to_scode(init_env(ContractName, Functions, Args), Body), {{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({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)};