Generate type variables for polymorphic functions
This commit is contained in:
parent
ed3ed6ded6
commit
3b352d8093
@ -95,7 +95,7 @@
|
|||||||
| bits
|
| bits
|
||||||
| {variant, [[ftype()]]}
|
| {variant, [[ftype()]]}
|
||||||
| {function, [ftype()], ftype()}
|
| {function, [ftype()], ftype()}
|
||||||
| any.
|
| any | {tvar, var_name()}.
|
||||||
|
|
||||||
-type fun_def() :: #{ attrs := [attribute()],
|
-type fun_def() :: #{ attrs := [attribute()],
|
||||||
args := [{var_name(), ftype()}],
|
args := [{var_name(), ftype()}],
|
||||||
@ -318,7 +318,7 @@ type_to_fcode(Env, Sub, {record_t, Fields}) ->
|
|||||||
type_to_fcode(_Env, _Sub, {bytes_t, _, _N}) ->
|
type_to_fcode(_Env, _Sub, {bytes_t, _, _N}) ->
|
||||||
string; %% TODO: add bytes type to FATE?
|
string; %% TODO: add bytes type to FATE?
|
||||||
type_to_fcode(_Env, Sub, {tvar, _, X}) ->
|
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}) ->
|
type_to_fcode(Env, Sub, {fun_t, _, Named, Args, Res}) ->
|
||||||
FNamed = [type_to_fcode(Env, Sub, Arg) || {named_arg_t, _, _, Arg, _} <- Named],
|
FNamed = [type_to_fcode(Env, Sub, Arg) || {named_arg_t, _, _, Arg, _} <- Named],
|
||||||
FArgs = [type_to_fcode(Env, Sub, Arg) || Arg <- Args],
|
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(T) when is_atom(T) -> pp_text(T);
|
||||||
pp_ftype(any) -> pp_text("_");
|
pp_ftype(any) -> pp_text("_");
|
||||||
|
pp_ftype({tvar, X}) -> pp_text(X);
|
||||||
pp_ftype({tuple, Ts}) ->
|
pp_ftype({tuple, Ts}) ->
|
||||||
pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_ftype(T) || T <- Ts])));
|
pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_ftype(T) || T <- Ts])));
|
||||||
pp_ftype({list, T}) ->
|
pp_ftype({list, T}) ->
|
||||||
|
@ -138,16 +138,44 @@ functions_to_scode(ContractName, Functions, Options) ->
|
|||||||
return := Type}} <- maps:to_list(Functions)]).
|
return := Type}} <- maps:to_list(Functions)]).
|
||||||
|
|
||||||
function_to_scode(ContractName, Functions, _Name, Args, Body, ResType, _Options) ->
|
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),
|
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({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)};
|
||||||
type_to_scode({function, _Args, _Res}) -> {tuple, [string, any]};
|
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, []} ->
|
add_default_init_function(SFuns, StateType) when StateType /= {tuple, []} ->
|
||||||
%% Only add default if the type is unit.
|
%% Only add default if the type is unit.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user