diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 78488ce..f73d7a8 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -41,6 +41,10 @@ | {tuple, [fexpr()]} | {proj, fexpr(), integer()} | {set_proj, fexpr(), integer(), fexpr()} %% tuple, field, new_value + | map_empty + | {map_set, fexpr(), fexpr(), fexpr()} % map, key, val + | {map_get, fexpr(), fexpr()} % map, key + | {map_get, fexpr(), fexpr(), fexpr()} % map, key, default | {op, binop(), fexpr(), fexpr()} | {op, unop(), fexpr()} | {'let', var_name(), fexpr(), fexpr()} @@ -376,6 +380,33 @@ expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) -> expr_to_fcode(Env, _Type, {app, _Ann, Fun, Args}) -> {funcall, expr_to_fcode(Env, Fun), [expr_to_fcode(Env, Arg) || Arg <- Args]}; +%% Maps +expr_to_fcode(_Env, _Type, {map, _, []}) -> + map_empty; +expr_to_fcode(Env, Type, {map, Ann, KVs}) -> + %% Cheaper to do incremental map_update than building the list and doing + %% map_from_list (I think). + 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), + lists:foldr(fun(Fld, M) -> + case Fld of + {field, _, [{map_get, _, K}], V} -> + {map_set, M, expr_to_fcode(Env, K), expr_to_fcode(Env, V)}; + {field_upd, _, [{map_get, _, K}], {typed, _, {lam, _, [{arg, _, {id, _, Z}, _}], V}, _}} -> + Y = fresh_name(), + {'let', Y, expr_to_fcode(Env, K), + {'let', Z, {map_get, Map1, {var, [Y]}}, + {map_set, M, {var, [Y]}, expr_to_fcode(Env, V)}}} + end end, Map1, KVs)}; +expr_to_fcode(Env, _Type, {map_get, _, Map, Key}) -> + {map_get, expr_to_fcode(Env, Map), expr_to_fcode(Env, Key)}; +expr_to_fcode(Env, _Type, {map_get, _, Map, Key, Def}) -> + {map_get, expr_to_fcode(Env, Map), expr_to_fcode(Env, Key), expr_to_fcode(Env, Def)}; + expr_to_fcode(_Env, Type, Expr) -> error({todo, {Expr, ':', Type}}). diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 089e5d1..d14b49b 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -249,6 +249,24 @@ to_scode(Env, {op, Op, A}) -> [ to_scode(notail(Env), A), unop_to_scode(Op) ]; +%% Maps +to_scode(_Env, map_empty) -> + [aeb_fate_code:map_empty(?a)]; +to_scode(Env, {map_set, Map, Key, Val}) -> + [to_scode(notail(Env), Val), + to_scode(notail(Env), Key), + to_scode(notail(Env), Map), + aeb_fate_code:map_update(?a, ?a, ?a, ?a)]; +to_scode(Env, {map_get, Map, Key}) -> + [to_scode(notail(Env), Key), + to_scode(notail(Env), Map), + aeb_fate_code:map_lookup(?a, ?a, ?a)]; +to_scode(Env, {map_get, Map, Key, Default}) -> + [to_scode(notail(Env), Default), + to_scode(notail(Env), Key), + to_scode(notail(Env), Map), + aeb_fate_code:map_lookup(?a, ?a, ?a, ?a)]; + to_scode(Env, {'let', X, {var, Y}, Body}) -> Env1 = bind_var(X, lookup_var(Env, Y), Env), to_scode(Env1, Body);