Add a constraint field to type_sig

This commit is contained in:
Ulf Norell 2019-09-09 10:18:45 +02:00
parent 6551690dff
commit 244ef6a6e2

View File

@ -81,7 +81,9 @@
-type type() :: aeso_syntax:type(). -type type() :: aeso_syntax:type().
-type name() :: string(). -type name() :: string().
-type qname() :: [string()]. -type qname() :: [string()].
-type typesig() :: {type_sig, aeso_syntax:ann(), [aeso_syntax:named_arg_t()], [type()], type()}. -type typesig() :: {type_sig, aeso_syntax:ann(), type_constraints(), [aeso_syntax:named_arg_t()], [type()], type()}.
-type type_constraints() :: none.
-type fun_info() :: {aeso_syntax:ann(), typesig() | type()}. -type fun_info() :: {aeso_syntax:ann(), typesig() | type()}.
-type type_info() :: {aeso_syntax:ann(), typedef()}. -type type_info() :: {aeso_syntax:ann(), typedef()}.
@ -206,7 +208,7 @@ bind_state(Env) ->
false -> Unit false -> Unit
end, end,
Env1 = bind_funs([{"state", State}, Env1 = bind_funs([{"state", State},
{"put", {type_sig, [stateful | Ann], [], [State], Unit}}], Env), {"put", {type_sig, [stateful | Ann], none, [], [State], Unit}}], Env),
case lookup_type(Env, {id, Ann, "event"}) of case lookup_type(Env, {id, Ann, "event"}) of
{E, _} -> {E, _} ->
@ -370,16 +372,16 @@ global_env() ->
Option = fun(T) -> {app_t, Ann, {id, Ann, "option"}, [T]} end, Option = fun(T) -> {app_t, Ann, {id, Ann, "option"}, [T]} end,
Map = fun(A, B) -> {app_t, Ann, {id, Ann, "map"}, [A, B]} end, Map = fun(A, B) -> {app_t, Ann, {id, Ann, "map"}, [A, B]} end,
Pair = fun(A, B) -> {tuple_t, Ann, [A, B]} end, Pair = fun(A, B) -> {tuple_t, Ann, [A, B]} end,
Fun = fun(Ts, T) -> {type_sig, Ann, [], Ts, T} end, Fun = fun(Ts, T) -> {type_sig, Ann, none, [], Ts, T} end,
Fun1 = fun(S, T) -> Fun([S], T) end, Fun1 = fun(S, T) -> Fun([S], T) end,
%% Lambda = fun(Ts, T) -> {fun_t, Ann, [], Ts, T} end, %% Lambda = fun(Ts, T) -> {fun_t, Ann, [], Ts, T} end,
%% Lambda1 = fun(S, T) -> Lambda([S], T) end, %% Lambda1 = fun(S, T) -> Lambda([S], T) end,
StateFun = fun(Ts, T) -> {type_sig, [stateful|Ann], [], Ts, T} end, StateFun = fun(Ts, T) -> {type_sig, [stateful|Ann], none, [], Ts, T} end,
TVar = fun(X) -> {tvar, Ann, "'" ++ X} end, TVar = fun(X) -> {tvar, Ann, "'" ++ X} end,
SignId = {id, Ann, "signature"}, SignId = {id, Ann, "signature"},
SignDef = {bytes, Ann, <<0:64/unit:8>>}, SignDef = {bytes, Ann, <<0:64/unit:8>>},
Signature = {named_arg_t, Ann, SignId, SignId, {typed, Ann, SignDef, SignId}}, Signature = {named_arg_t, Ann, SignId, SignId, {typed, Ann, SignDef, SignId}},
SignFun = fun(Ts, T) -> {type_sig, [stateful|Ann], [Signature], Ts, T} end, SignFun = fun(Ts, T) -> {type_sig, [stateful|Ann], none, [Signature], Ts, T} end,
TTL = {qid, Ann, ["Chain", "ttl"]}, TTL = {qid, Ann, ["Chain", "ttl"]},
Fee = Int, Fee = Int,
[A, Q, R, K, V] = lists:map(TVar, ["a", "q", "r", "k", "v"]), [A, Q, R, K, V] = lists:map(TVar, ["a", "q", "r", "k", "v"]),
@ -669,7 +671,7 @@ check_typedef_sccs(Env, TypeMap, [{acyclic, Name} | SCCs], Acc) ->
check_typedef_sccs(Env2, TypeMap, SCCs, Acc1); check_typedef_sccs(Env2, TypeMap, SCCs, Acc1);
{variant_t, Cons} -> {variant_t, Cons} ->
Target = check_type(Env1, app_t(Ann, D, Xs)), Target = check_type(Env1, app_t(Ann, D, Xs)),
ConType = fun([]) -> Target; (Args) -> {type_sig, Ann, [], Args, Target} end, ConType = fun([]) -> Target; (Args) -> {type_sig, Ann, none, [], Args, Target} end,
ConTypes = [ begin ConTypes = [ begin
{constr_t, _, {con, _, Con}, Args} = ConDef, {constr_t, _, {con, _, Con}, Args} = ConDef,
{Con, ConType(Args)} {Con, ConType(Args)}
@ -842,7 +844,7 @@ check_constructor_overlap(Env, Con = {con, Ann, Name}, NewType) ->
case lookup_env(Env, term, Ann, Name) of case lookup_env(Env, term, Ann, Name) of
false -> ok; false -> ok;
{_, {Ann, Type}} -> {_, {Ann, Type}} ->
OldType = case Type of {type_sig, _, _, _, T} -> T; OldType = case Type of {type_sig, _, _, _, _, T} -> T;
_ -> Type end, _ -> Type end,
OldCon = {con, Ann, Name}, OldCon = {con, Ann, Name},
type_error({repeated_constructor, [{OldCon, OldType}, {Con, NewType}]}) type_error({repeated_constructor, [{OldCon, OldType}, {Con, NewType}]})
@ -884,10 +886,10 @@ check_reserved_entrypoints(Funs) ->
-spec check_fundecl(env(), aeso_syntax:decl()) -> {{name(), typesig()}, aeso_syntax:decl()}. -spec check_fundecl(env(), aeso_syntax:decl()) -> {{name(), typesig()}, aeso_syntax:decl()}.
check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type = {fun_t, _, _, _, _}}) -> check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type = {fun_t, _, _, _, _}}) ->
Type1 = {fun_t, _, Named, Args, Ret} = check_type(Env, Type), Type1 = {fun_t, _, Named, Args, Ret} = check_type(Env, Type),
{{Name, {type_sig, Ann, Named, Args, Ret}}, {fun_decl, Ann, Id, Type1}}; {{Name, {type_sig, Ann, none, Named, Args, Ret}}, {fun_decl, Ann, Id, Type1}};
check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type}) -> check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type}) ->
type_error({fundecl_must_have_funtype, Ann, Id, Type}), type_error({fundecl_must_have_funtype, Ann, Id, Type}),
{{Name, {type_sig, Ann, [], [], Type}}, check_type(Env, Type)}. {{Name, {type_sig, Ann, none, [], [], Type}}, check_type(Env, Type)}.
infer_nonrec(Env, LetFun) -> infer_nonrec(Env, LetFun) ->
create_constraints(), create_constraints(),
@ -901,7 +903,7 @@ infer_nonrec(Env, LetFun) ->
%% Currenty only the init function. %% Currenty only the init function.
check_special_funs(Env, {{"init", Type}, _}) -> check_special_funs(Env, {{"init", Type}, _}) ->
{type_sig, Ann, _Named, _Args, Res} = Type, {type_sig, Ann, _Constr, _Named, _Args, Res} = Type,
State = State =
%% We might have implicit (no) state. %% We might have implicit (no) state.
case lookup_type(Env, {id, [], "state"}) of case lookup_type(Env, {id, [], "state"}) of
@ -911,7 +913,8 @@ check_special_funs(Env, {{"init", Type}, _}) ->
unify(Env, Res, State, {checking_init_type, Ann}); unify(Env, Res, State, {checking_init_type, Ann});
check_special_funs(_, _) -> ok. check_special_funs(_, _) -> ok.
typesig_to_fun_t({type_sig, Ann, Named, Args, Res}) -> {fun_t, Ann, Named, Args, Res}. typesig_to_fun_t({type_sig, Ann, _Constr, Named, Args, Res}) ->
{fun_t, Ann, Named, Args, Res}.
infer_letrec(Env, Defs) -> infer_letrec(Env, Defs) ->
create_constraints(), create_constraints(),
@ -945,7 +948,7 @@ infer_letfun(Env0, {letfun, Attrib, Fun = {id, NameAttrib, Name}, Args, What, Bo
NewArgs = [{arg, A1, {id, A2, ArgName}, T} NewArgs = [{arg, A1, {id, A2, ArgName}, T}
|| {{_, T}, {arg, A1, {id, A2, ArgName}, _}} <- lists:zip(ArgTypes, Args)], || {{_, T}, {arg, A1, {id, A2, ArgName}, _}} <- lists:zip(ArgTypes, Args)],
NamedArgs = [], NamedArgs = [],
TypeSig = {type_sig, Attrib, NamedArgs, [T || {arg, _, _, T} <- NewArgs], ResultType}, TypeSig = {type_sig, Attrib, none, NamedArgs, [T || {arg, _, _, T} <- NewArgs], ResultType},
{{Name, TypeSig}, {{Name, TypeSig},
{letfun, Attrib, {id, NameAttrib, Name}, NewArgs, ResultType, NewBody}}. {letfun, Attrib, {id, NameAttrib, Name}, NewArgs, ResultType, NewBody}}.
@ -981,14 +984,14 @@ lookup_name(Env, As, Id, Options) ->
Freshen = proplists:get_value(freshen, Options, false), Freshen = proplists:get_value(freshen, Options, false),
check_stateful(Env, Id, Ty), check_stateful(Env, Id, Ty),
Ty1 = case Ty of Ty1 = case Ty of
{type_sig, _, _, _, _} -> freshen_type(As, typesig_to_fun_t(Ty)); {type_sig, _, _, _, _, _} -> freshen_type_sig(As, Ty);
_ when Freshen -> freshen_type(As, Ty); _ when Freshen -> freshen_type(As, Ty);
_ -> Ty _ -> Ty
end, end,
{set_qname(QId, Id), Ty1} {set_qname(QId, Id), Ty1}
end. end.
check_stateful(#env{ stateful = false, current_function = Fun }, Id, Type = {type_sig, _, _, _, _}) -> check_stateful(#env{ stateful = false, current_function = Fun }, Id, Type = {type_sig, _, _, _, _, _}) ->
case aeso_syntax:get_ann(stateful, Type, false) of case aeso_syntax:get_ann(stateful, Type, false) of
false -> ok; false -> ok;
true -> true ->
@ -1803,8 +1806,8 @@ unfold_types(Env, {typed, Attr, E, Type}, Options) ->
{typed, Attr, unfold_types(Env, E, Options), unfold_types_in_type(Env, Type, Options)}; {typed, Attr, unfold_types(Env, E, Options), unfold_types_in_type(Env, Type, Options)};
unfold_types(Env, {arg, Attr, Id, Type}, Options) -> unfold_types(Env, {arg, Attr, Id, Type}, Options) ->
{arg, Attr, Id, unfold_types_in_type(Env, Type, Options)}; {arg, Attr, Id, unfold_types_in_type(Env, Type, Options)};
unfold_types(Env, {type_sig, Ann, NamedArgs, Args, Ret}, Options) -> unfold_types(Env, {type_sig, Ann, Constr, NamedArgs, Args, Ret}, Options) ->
{type_sig, Ann, {type_sig, Ann, Constr,
unfold_types_in_type(Env, NamedArgs, Options), unfold_types_in_type(Env, NamedArgs, Options),
unfold_types_in_type(Env, Args, Options), unfold_types_in_type(Env, Args, Options),
unfold_types_in_type(Env, Ret, Options)}; unfold_types_in_type(Env, Ret, Options)};
@ -2032,6 +2035,13 @@ freshen(Ann, [A | B]) ->
freshen(_, X) -> freshen(_, X) ->
X. X.
freshen_type_sig(Ann, TypeSig = {type_sig, _, Constr, _, _, _}) ->
FunT = freshen_type(Ann, typesig_to_fun_t(TypeSig)),
apply_typesig_constraint(Ann, Constr, FunT),
FunT.
apply_typesig_constraint(_Ann, none, _FunT) -> ok.
%% Dereferences all uvars and replaces the uninstantiated ones with a %% Dereferences all uvars and replaces the uninstantiated ones with a
%% succession of tvars. %% succession of tvars.
instantiate(E) -> instantiate(E) ->
@ -2443,7 +2453,7 @@ if_branches(If = {'if', Ann, _, Then, Else}) ->
end; end;
if_branches(E) -> [E]. if_branches(E) -> [E].
pp_typed(Label, E, T = {type_sig, _, _, _, _}) -> pp_typed(Label, E, typesig_to_fun_t(T)); pp_typed(Label, E, T = {type_sig, _, _, _, _, _}) -> pp_typed(Label, E, typesig_to_fun_t(T));
pp_typed(Label, {typed, _, Expr, _}, Type) -> pp_typed(Label, {typed, _, Expr, _}, Type) ->
pp_typed(Label, Expr, Type); pp_typed(Label, Expr, Type);
pp_typed(Label, Expr, Type) -> pp_typed(Label, Expr, Type) ->
@ -2475,7 +2485,7 @@ pp_loc(T) ->
plural(No, _Yes, [_]) -> No; plural(No, _Yes, [_]) -> No;
plural(_No, Yes, _) -> Yes. plural(_No, Yes, _) -> Yes.
pp(T = {type_sig, _, _, _, _}) -> pp(T = {type_sig, _, _, _, _, _}) ->
pp(typesig_to_fun_t(T)); pp(typesig_to_fun_t(T));
pp([]) -> pp([]) ->
""; "";