diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index ce26e9a..2ee90d9 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -95,7 +95,7 @@ | bits | {variant, [[ftype()]]} | {function, [ftype()], ftype()} - | any. + | any | {tvar, var_name()}. -type fun_def() :: #{ attrs := [attribute()], args := [{var_name(), ftype()}], @@ -318,7 +318,7 @@ type_to_fcode(Env, Sub, {record_t, Fields}) -> type_to_fcode(_Env, _Sub, {bytes_t, _, _N}) -> string; %% TODO: add bytes type to FATE? type_to_fcode(_Env, Sub, {tvar, _, X}) -> - maps:get(X, Sub, any); + maps:get(X, Sub, {tvar, X}); type_to_fcode(Env, Sub, {fun_t, _, Named, Args, Res}) -> FNamed = [type_to_fcode(Env, Sub, Arg) || {named_arg_t, _, _, Arg, _} <- Named], FArgs = [type_to_fcode(Env, Sub, Arg) || Arg <- Args], @@ -1298,6 +1298,7 @@ pp_call(Fun, Args) -> pp_ftype(T) when is_atom(T) -> pp_text(T); pp_ftype(any) -> pp_text("_"); +pp_ftype({tvar, X}) -> pp_text(X); pp_ftype({tuple, Ts}) -> pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_ftype(T) || T <- Ts]))); pp_ftype({list, T}) -> diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 1e1cf31..3841fbe 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -138,16 +138,44 @@ functions_to_scode(ContractName, Functions, Options) -> return := Type}} <- maps:to_list(Functions)]). function_to_scode(ContractName, Functions, _Name, Args, Body, ResType, _Options) -> - ArgTypes = [ type_to_scode(T) || {_, T} <- Args ], + {ArgTypes, ResType1} = typesig_to_scode(Args, ResType), SCode = to_scode(init_env(ContractName, Functions, Args), Body), - {{ArgTypes, type_to_scode(ResType)}, SCode}. + {{ArgTypes, ResType1}, SCode}. +-define(tvars, '$tvars'). + +typesig_to_scode(Args, Res) -> + put(?tvars, {0, #{}}), + R = {[type_to_scode(T) || {_, T} <- Args], type_to_scode(Res)}, + erase(?tvars), + R. + +type_to_scode(integer) -> integer; +type_to_scode(boolean) -> boolean; +type_to_scode(string) -> string; +type_to_scode(address) -> address; +type_to_scode(hash) -> hash; +type_to_scode(signature) -> signature; +type_to_scode(contract) -> contract; +type_to_scode(oracle) -> oracle; +type_to_scode(oracle_query) -> oracle_query; +type_to_scode(name) -> name; +type_to_scode(channel) -> channel; +type_to_scode(bits) -> bits; +type_to_scode(any) -> any; 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)}; type_to_scode({function, _Args, _Res}) -> {tuple, [string, any]}; -type_to_scode(T) -> T. +type_to_scode({tvar, X}) -> + {I, Vars} = get(?tvars), + case maps:get(X, Vars, false) of + false -> + put(?tvars, {I + 1, Vars#{ X => I }}), + {tvar, I}; + J -> {tvar, J} + end. add_default_init_function(SFuns, StateType) when StateType /= {tuple, []} -> %% Only add default if the type is unit.