diff options
author | Hans Bolinder <[email protected]> | 2016-05-31 14:14:27 +0200 |
---|---|---|
committer | Hans Bolinder <[email protected]> | 2016-06-09 11:28:00 +0200 |
commit | 42549165197b4f2622257b95a631f26a5a253d0a (patch) | |
tree | 8c1ff65111c26a80286f068d11fe4b8987a7e8dd | |
parent | e6595b12b525acb6842ba0f60eef8881fa9c658d (diff) | |
download | otp-42549165197b4f2622257b95a631f26a5a253d0a.tar.gz otp-42549165197b4f2622257b95a631f26a5a253d0a.tar.bz2 otp-42549165197b4f2622257b95a631f26a5a253d0a.zip |
dialyzer: Prepare erl_types:t_from_form() for a cache
No change of functionality.
-rw-r--r-- | lib/hipe/cerl/erl_types.erl | 526 |
1 files changed, 268 insertions, 258 deletions
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 7bfb44c06f..208f439388 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -4419,6 +4419,7 @@ mod_name(Mod, Name) -> -type mta() :: {module(), atom(), arity()}. -type mra() :: {module(), atom(), arity()}. -type site() :: {'type', mta()} | {'spec', mfa()} | {'record', mra()}. +-type cache() :: #{{module(), parse_form()} => erl_type()}. -spec t_from_form(parse_form(), sets:set(mfa()), site(), mod_records()) -> erl_type(). @@ -4482,15 +4483,28 @@ t_from_form_loop(Form, TypeNames, ET, Site, MR, V, D, L0) -> t_from_form_loop(Form, TypeNames, ET, Site, MR, V, D1, L1) end. +-record(from_form, {site :: site(), + xtypes :: sets:set(mfa()) | 'replace_by_none', + mrecs :: mod_records(), + vtab :: var_table(), + tnames :: type_names()}). + t_from_form2(Form, TypeNames, ET, Site, MR, V, D) -> L = ?EXPAND_LIMIT, - t_from_form(Form, TypeNames, ET, Site, MR, V, D, L). - --spec t_from_form(parse_form(), type_names(), - sets:set(mfa()) | 'replace_by_none', - site(), mod_records(), var_table(), - expand_depth(), expand_limit()) - -> {erl_type(), expand_limit()}. + State = #from_form{site = Site, + xtypes = ET, + mrecs = MR, + vtab = V, + tnames = TypeNames}, + C = #{}, + {T, L1, _C1} = from_form(Form, State, D, L, C), + {T, L1}. + +-spec from_form(parse_form(), + #from_form{}, + expand_depth(), + expand_limit(), + cache()) -> {erl_type(), expand_limit(), cache()}. %% If there is something wrong with parse_form() %% throw({error, io_lib:chars()} is called; @@ -4500,218 +4514,213 @@ t_from_form2(Form, TypeNames, ET, Site, MR, V, D) -> %% %% It is assumed that site_module(S) can be found in MR. -t_from_form(_, _TypeNames, _ET, _S, _MR, _V, D, L) when D =< 0 ; L =< 0 -> - {t_any(), L}; -t_from_form({var, _L, '_'}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_any(), L}; -t_from_form({var, _L, Name}, _TypeNames, _ET, _S, _MR, V, _D, L) -> +from_form(_, _S, D, L, C) when D =< 0 ; L =< 0 -> + {t_any(), L, C}; +from_form({var, _L, '_'}, _S, _D, L, C) -> + {t_any(), L, C}; +from_form({var, _L, Name}, S, _D, L, C) -> + V = S#from_form.vtab, case maps:find(Name, V) of - error -> {t_var(Name), L}; - {ok, Val} -> {Val, L} + error -> {t_var(Name), L, C}; + {ok, Val} -> {Val, L, C} end; -t_from_form({ann_type, _L, [_Var, Type]}, TypeNames, ET, S, MR, V, D, L) -> - t_from_form(Type, TypeNames, ET, S, MR, V, D, L); -t_from_form({paren_type, _L, [Type]}, TypeNames, ET, S, MR, V, D, L) -> - t_from_form(Type, TypeNames, ET, S, MR, V, D, L); -t_from_form({remote_type, _L, [{atom, _, Module}, {atom, _, Type}, Args]}, - TypeNames, ET, S, MR, V, D, L) -> - remote_from_form(Module, Type, Args, TypeNames, ET, S, MR, V, D, L); -t_from_form({atom, _L, Atom}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_atom(Atom), L}; -t_from_form({integer, _L, Int}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_integer(Int), L}; -t_from_form({op, _L, _Op, _Arg} = Op, _TypeNames, _ET, _S, _MR, _V, _D, L) -> +from_form({ann_type, _L, [_Var, Type]}, S, D, L, C) -> + from_form(Type, S, D, L, C); +from_form({paren_type, _L, [Type]}, S, D, L, C) -> + from_form(Type, S, D, L, C); +from_form({remote_type, _L, [{atom, _, Module}, {atom, _, Type}, Args]}, + S, D, L, C) -> + remote_from_form(Module, Type, Args, S, D, L, C); +from_form({atom, _L, Atom}, _S, _D, L, C) -> + {t_atom(Atom), L, C}; +from_form({integer, _L, Int}, _S, _D, L, C) -> + {t_integer(Int), L, C}; +from_form({op, _L, _Op, _Arg} = Op, _S, _D, L, C) -> case erl_eval:partial_eval(Op) of {integer, _, Val} -> - {t_integer(Val), L}; + {t_integer(Val), L, C}; _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Op])}) end; -t_from_form({op, _L, _Op, _Arg1, _Arg2} = Op, _TypeNames, - _ET, _S, _MR, _V, _D, L) -> +from_form({op, _L, _Op, _Arg1, _Arg2} = Op, _S, _D, L, C) -> case erl_eval:partial_eval(Op) of {integer, _, Val} -> - {t_integer(Val), L}; + {t_integer(Val), L, C}; _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Op])}) end; -t_from_form({type, _L, any, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_any(), L}; -t_from_form({type, _L, arity, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_arity(), L}; -t_from_form({type, _L, atom, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_atom(), L}; -t_from_form({type, _L, binary, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_binary(), L}; -t_from_form({type, _L, binary, [Base, Unit]} = Type, - _TypeNames, _ET, _S, _MR, _V, _D, L) -> +from_form({type, _L, any, []}, _S, _D, L, C) -> + {t_any(), L, C}; +from_form({type, _L, arity, []}, _S, _D, L, C) -> + {t_arity(), L, C}; +from_form({type, _L, atom, []}, _S, _D, L, C) -> + {t_atom(), L, C}; +from_form({type, _L, binary, []}, _S, _D, L, C) -> + {t_binary(), L, C}; +from_form({type, _L, binary, [Base, Unit]} = Type, _S, _D, L, C) -> case {erl_eval:partial_eval(Base), erl_eval:partial_eval(Unit)} of {{integer, _, B}, {integer, _, U}} when B >= 0, U >= 0 -> - {t_bitstr(U, B), L}; + {t_bitstr(U, B), L, C}; _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])}) end; -t_from_form({type, _L, bitstring, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_bitstr(), L}; -t_from_form({type, _L, bool, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_boolean(), L}; % XXX: Temporarily -t_from_form({type, _L, boolean, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_boolean(), L}; -t_from_form({type, _L, byte, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_byte(), L}; -t_from_form({type, _L, char, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_char(), L}; -t_from_form({type, _L, float, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_float(), L}; -t_from_form({type, _L, function, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_fun(), L}; -t_from_form({type, _L, 'fun', []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_fun(), L}; -t_from_form({type, _L, 'fun', [{type, _, any}, Range]}, TypeNames, - ET, S, MR, V, D, L) -> - {T, L1} = t_from_form(Range, TypeNames, ET, S, MR, V, D - 1, L - 1), - {t_fun(T), L1}; -t_from_form({type, _L, 'fun', [{type, _, product, Domain}, Range]}, - TypeNames, ET, S, MR, V, D, L) -> - {Dom1, L1} = list_from_form(Domain, TypeNames, ET, S, MR, V, D, L), - {Ran1, L2} = t_from_form(Range, TypeNames, ET, S, MR, V, D, L1), - {t_fun(Dom1, Ran1), L2}; -t_from_form({type, _L, identifier, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_identifier(), L}; -t_from_form({type, _L, integer, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_integer(), L}; -t_from_form({type, _L, iodata, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_iodata(), L}; -t_from_form({type, _L, iolist, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_iolist(), L}; -t_from_form({type, _L, list, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_list(), L}; -t_from_form({type, _L, list, [Type]}, TypeNames, ET, S, MR, V, D, L) -> - {T, L1} = t_from_form(Type, TypeNames, ET, S, MR, V, D - 1, L - 1), - {t_list(T), L1}; -t_from_form({type, _L, map, any}, TypeNames, ET, S, MR, V, D, L) -> - builtin_type(map, t_map(), TypeNames, ET, S, MR, V, D, L); -t_from_form({type, _L, map, List}, TypeNames, ET, S, MR, V, D, L) -> - {Pairs1, L5} = - fun PairsFromForm(_, L1) when L1 =< 0 -> {[{?any,?opt,?any}], L1}; - PairsFromForm([], L1) -> {[], L1}; - PairsFromForm([{type, _, Oper, [KF, VF]}|T], L1) -> - {Key, L2} = t_from_form(KF, TypeNames, ET, S, MR, V, D - 1, L1), - {Val, L3} = t_from_form(VF, TypeNames, ET, S, MR, V, D - 1, L2), - {Pairs0, L4} = PairsFromForm(T, L3 - 1), +from_form({type, _L, bitstring, []}, _S, _D, L, C) -> + {t_bitstr(), L, C}; +from_form({type, _L, bool, []}, _S, _D, L, C) -> + {t_boolean(), L, C}; % XXX: Temporarily +from_form({type, _L, boolean, []}, _S, _D, L, C) -> + {t_boolean(), L, C}; +from_form({type, _L, byte, []}, _S, _D, L, C) -> + {t_byte(), L, C}; +from_form({type, _L, char, []}, _S, _D, L, C) -> + {t_char(), L, C}; +from_form({type, _L, float, []}, _S, _D, L, C) -> + {t_float(), L, C}; +from_form({type, _L, function, []}, _S, _D, L, C) -> + {t_fun(), L, C}; +from_form({type, _L, 'fun', []}, _S, _D, L, C) -> + {t_fun(), L, C}; +from_form({type, _L, 'fun', [{type, _, any}, Range]}, S, D, L, C) -> + {T, L1} = from_form(Range, S, D - 1, L - 1, C), + {t_fun(T), L1, C}; +from_form({type, _L, 'fun', [{type, _, product, Domain}, Range]}, + S, D, L, C) -> + {Dom1, L1, C1} = list_from_form(Domain, S, D, L, C), + {Ran1, L2, C2} = from_form(Range, S, D, L1, C1), + {t_fun(Dom1, Ran1), L2, C2}; +from_form({type, _L, identifier, []}, _S, _D, L, C) -> + {t_identifier(), L, C}; +from_form({type, _L, integer, []}, _S, _D, L, C) -> + {t_integer(), L, C}; +from_form({type, _L, iodata, []}, _S, _D, L, C) -> + {t_iodata(), L, C}; +from_form({type, _L, iolist, []}, _S, _D, L, C) -> + {t_iolist(), L, C}; +from_form({type, _L, list, []}, _S, _D, L, C) -> + {t_list(), L, C}; +from_form({type, _L, list, [Type]}, S, D, L, C) -> + {T, L1, C1} = from_form(Type, S, D - 1, L - 1, C), + {t_list(T), L1, C1}; +from_form({type, _L, map, any}, S, D, L, C) -> + builtin_type(map, t_map(), S, D, L, C); +from_form({type, _L, map, List}, S, D0, L, C) -> + {Pairs1, L5, C5} = + fun PairsFromForm(_, L1, C1) when L1 =< 0 -> {[{?any,?opt,?any}], L1, C1}; + PairsFromForm([], L1, C1) -> {[], L1, C1}; + PairsFromForm([{type, _, Oper, [KF, VF]}|T], L1, C1) -> + D = D0 - 1, + {Key, L2, C2} = from_form(KF, S, D, L1, C1), + {Val, L3, C3} = from_form(VF, S, D, L2, C2), + {Pairs0, L4, C4} = PairsFromForm(T, L3 - 1, C3), case Oper of - map_field_assoc -> {[{Key,?opt, Val}|Pairs0], L4}; - map_field_exact -> {[{Key,?mand,Val}|Pairs0], L4} + map_field_assoc -> {[{Key,?opt, Val}|Pairs0], L4, C4}; + map_field_exact -> {[{Key,?mand,Val}|Pairs0], L4, C4} end - end(List, L), + end(List, L, C), try {Pairs, DefK, DefV} = map_from_form(Pairs1, [], [], [], ?none, ?none), - {t_map(Pairs, DefK, DefV), L5} - catch none -> {t_none(), L5} + {t_map(Pairs, DefK, DefV), L5, C5} + catch none -> {t_none(), L5, C5} end; -t_from_form({type, _L, mfa, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_mfa(), L}; -t_from_form({type, _L, module, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_module(), L}; -t_from_form({type, _L, nil, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_nil(), L}; -t_from_form({type, _L, neg_integer, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_neg_integer(), L}; -t_from_form({type, _L, non_neg_integer, []}, _TypeNames, _ET, _S, _MR, - _V, _D, L) -> - {t_non_neg_integer(), L}; -t_from_form({type, _L, no_return, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_unit(), L}; -t_from_form({type, _L, node, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_node(), L}; -t_from_form({type, _L, none, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_none(), L}; -t_from_form({type, _L, nonempty_list, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_nonempty_list(), L}; -t_from_form({type, _L, nonempty_list, [Type]}, TypeNames, ET, S, MR, V, D, L) -> - {T, L1} = t_from_form(Type, TypeNames, ET, S, MR, V, D, L - 1), - {t_nonempty_list(T), L1}; -t_from_form({type, _L, nonempty_improper_list, [Cont, Term]}, TypeNames, - ET, S, MR, V, D, L) -> - {T1, L1} = t_from_form(Cont, TypeNames, ET, S, MR, V, D, L - 1), - {T2, L2} = t_from_form(Term, TypeNames, ET, S, MR, V, D, L1), - {t_cons(T1, T2), L2}; -t_from_form({type, _L, nonempty_maybe_improper_list, []}, _TypeNames, - _ET, _S, _MR, _V, _D, L) -> - {t_cons(?any, ?any), L}; -t_from_form({type, _L, nonempty_maybe_improper_list, [Cont, Term]}, - TypeNames, ET, S, MR, V, D, L) -> - {T1, L1} = t_from_form(Cont, TypeNames, ET, S, MR, V, D, L - 1), - {T2, L2} = t_from_form(Term, TypeNames, ET, S, MR, V, D, L1), - {t_cons(T1, T2), L2}; -t_from_form({type, _L, nonempty_string, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_nonempty_string(), L}; -t_from_form({type, _L, number, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_number(), L}; -t_from_form({type, _L, pid, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_pid(), L}; -t_from_form({type, _L, port, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_port(), L}; -t_from_form({type, _L, pos_integer, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_pos_integer(), L}; -t_from_form({type, _L, maybe_improper_list, []}, _TypeNames, - _ET, _S, _MR, _V, _D, L) -> - {t_maybe_improper_list(), L}; -t_from_form({type, _L, maybe_improper_list, [Content, Termination]}, - TypeNames, ET, S, MR, V, D, L) -> - {T1, L1} = t_from_form(Content, TypeNames, ET, S, MR, V, D, L - 1), - {T2, L2} = t_from_form(Termination, TypeNames, ET, S, MR, V, D, L1), - {t_maybe_improper_list(T1, T2), L2}; -t_from_form({type, _L, product, Elements}, TypeNames, ET, S, MR, V, D, L) -> - {Lst, L1} = list_from_form(Elements, TypeNames, ET, S, MR, V, D - 1, L), - {t_product(Lst), L1}; -t_from_form({type, _L, range, [From, To]} = Type, - _TypeNames, _ET, _S, _MR, _V, _D, L) -> +from_form({type, _L, mfa, []}, _S, _D, L, C) -> + {t_mfa(), L, C}; +from_form({type, _L, module, []}, _S, _D, L, C) -> + {t_module(), L, C}; +from_form({type, _L, nil, []}, _S, _D, L, C) -> + {t_nil(), L, C}; +from_form({type, _L, neg_integer, []}, _S, _D, L, C) -> + {t_neg_integer(), L, C}; +from_form({type, _L, non_neg_integer, []}, _S, _D, L, C) -> + {t_non_neg_integer(), L, C}; +from_form({type, _L, no_return, []}, _S, _D, L, C) -> + {t_unit(), L, C}; +from_form({type, _L, node, []}, _S, _D, L, C) -> + {t_node(), L, C}; +from_form({type, _L, none, []}, _S, _D, L, C) -> + {t_none(), L, C}; +from_form({type, _L, nonempty_list, []}, _S, _D, L, C) -> + {t_nonempty_list(), L, C}; +from_form({type, _L, nonempty_list, [Type]}, S, D, L, C) -> + {T, L1, C1} = from_form(Type, S, D, L - 1, C), + {t_nonempty_list(T), L1, C1}; +from_form({type, _L, nonempty_improper_list, [Cont, Term]}, S, D, L, C) -> + {T1, L1, C1} = from_form(Cont, S, D, L - 1, C), + {T2, L2, C2} = from_form(Term, S, D, L1, C1), + {t_cons(T1, T2), L2, C2}; +from_form({type, _L, nonempty_maybe_improper_list, []}, _S, _D, L, C) -> + {t_cons(?any, ?any), L, C}; +from_form({type, _L, nonempty_maybe_improper_list, [Cont, Term]}, + S, D, L, C) -> + {T1, L1, C1} = from_form(Cont, S, D, L - 1, C), + {T2, L2, C2} = from_form(Term, S, D, L1, C1), + {t_cons(T1, T2), L2, C2}; +from_form({type, _L, nonempty_string, []}, _S, _D, L, C) -> + {t_nonempty_string(), L, C}; +from_form({type, _L, number, []}, _S, _D, L, C) -> + {t_number(), L, C}; +from_form({type, _L, pid, []}, _S, _D, L, C) -> + {t_pid(), L, C}; +from_form({type, _L, port, []}, _S, _D, L, C) -> + {t_port(), L, C}; +from_form({type, _L, pos_integer, []}, _S, _D, L, C) -> + {t_pos_integer(), L, C}; +from_form({type, _L, maybe_improper_list, []}, _S, _D, L, C) -> + {t_maybe_improper_list(), L, C}; +from_form({type, _L, maybe_improper_list, [Content, Termination]}, + S, D, L, C) -> + {T1, L1, C1} = from_form(Content, S, D, L - 1, C), + {T2, L2, C2} = from_form(Termination, S, D, L1, C1), + {t_maybe_improper_list(T1, T2), L2, C2}; +from_form({type, _L, product, Elements}, S, D, L, C) -> + {Lst, L1, C1} = list_from_form(Elements, S, D - 1, L, C), + {t_product(Lst), L1, C1}; +from_form({type, _L, range, [From, To]} = Type, _S, _D, L, C) -> case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of {{integer, _, FromVal}, {integer, _, ToVal}} -> - {t_from_range(FromVal, ToVal), L}; + {t_from_range(FromVal, ToVal), L, C}; _ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])}) end; -t_from_form({type, _L, record, [Name|Fields]}, TypeNames, ET, S, MR, V, D, L) -> - record_from_form(Name, Fields, TypeNames, ET, S, MR, V, D, L); -t_from_form({type, _L, reference, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_reference(), L}; -t_from_form({type, _L, string, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_string(), L}; -t_from_form({type, _L, term, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_any(), L}; -t_from_form({type, _L, timeout, []}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_timeout(), L}; -t_from_form({type, _L, tuple, any}, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {t_tuple(), L}; -t_from_form({type, _L, tuple, Args}, TypeNames, ET, S, MR, V, D, L) -> - {Lst, L1} = list_from_form(Args, TypeNames, ET, S, MR, V, D - 1, L), - {t_tuple(Lst), L1}; -t_from_form({type, _L, union, Args}, TypeNames, ET, S, MR, V, D, L) -> - {Lst, L1} = list_from_form(Args, TypeNames, ET, S, MR, V, D, L), - {t_sup(Lst), L1}; -t_from_form({user_type, _L, Name, Args}, TypeNames, ET, S, MR, V, D, L) -> - type_from_form(Name, Args, TypeNames, ET, S, MR, V, D, L); -t_from_form({type, _L, Name, Args}, TypeNames, ET, S, MR, V, D, L) -> +from_form({type, _L, record, [Name|Fields]}, S, D, L, C) -> + record_from_form(Name, Fields, S, D, L, C); +from_form({type, _L, reference, []}, _S, _D, L, C) -> + {t_reference(), L, C}; +from_form({type, _L, string, []}, _S, _D, L, C) -> + {t_string(), L, C}; +from_form({type, _L, term, []}, _S, _D, L, C) -> + {t_any(), L, C}; +from_form({type, _L, timeout, []}, _S, _D, L, C) -> + {t_timeout(), L, C}; +from_form({type, _L, tuple, any}, _S, _D, L, C) -> + {t_tuple(), L, C}; +from_form({type, _L, tuple, Args}, S, D, L, C) -> + {Lst, L1, C1} = list_from_form(Args, S, D - 1, L, C), + {t_tuple(Lst), L1, C1}; +from_form({type, _L, union, Args}, S, D, L, C) -> + {Lst, L1, C1} = list_from_form(Args, S, D, L, C), + {t_sup(Lst), L1, C1}; +from_form({user_type, _L, Name, Args}, S, D, L, C) -> + type_from_form(Name, Args, S, D, L, C); +from_form({type, _L, Name, Args}, S, D, L, C) -> %% Compatibility: modules compiled before Erlang/OTP 18.0. - type_from_form(Name, Args, TypeNames, ET, S, MR, V, D, L); -t_from_form({opaque, _L, Name, {Mod, Args, Rep}}, _TypeNames, - _ET, _S, _MR, _V, _D, L) -> + type_from_form(Name, Args, S, D, L, C); +from_form({opaque, _L, Name, {Mod, Args, Rep}}, _S, _D, L, C) -> %% XXX. To be removed. - {t_opaque(Mod, Name, Args, Rep), L}. + {t_opaque(Mod, Name, Args, Rep), L, C}. -builtin_type(Name, Type, TypeNames, ET, Site, MR, V, D, L) -> +builtin_type(Name, Type, S, D, L, C) -> + #from_form{site = Site, mrecs = MR} = S, M = site_module(Site), case dict:find(M, MR) of {ok, R} -> case lookup_type(Name, 0, R) of {_, {{_M, _FL, _F, _A}, _T}} -> - type_from_form(Name, [], TypeNames, ET, Site, MR, V, D, L); + type_from_form(Name, [], S, D, L, C); error -> - {Type, L} + {Type, L, C} end; error -> - {Type, L} + {Type, L, C} end. -type_from_form(Name, Args, TypeNames, ET, Site0, MR, V, D, L) -> +type_from_form(Name, Args, S, D, L, C) -> + #from_form{site = Site0, mrecs = MR, tnames = TypeNames} = S, ArgsLen = length(Args), Module = site_module(Site0), {ok, R} = dict:find(Module, MR), @@ -4721,26 +4730,26 @@ type_from_form(Name, Args, TypeNames, ET, Site0, MR, V, D, L) -> case can_unfold_more(TypeName, TypeNames) of true -> NewTypeNames = [TypeName|TypeNames], - {ArgTypes, L1} = - list_from_form(Args, TypeNames, ET, Site0, MR, V, D, L), + {ArgTypes, L1, C1} = list_from_form(Args, S, D, L, C), List = lists:zip(ArgNames, ArgTypes), TmpV = maps:from_list(List), - Site = TypeName, - t_from_form(Form, NewTypeNames, ET, Site, MR, TmpV, D, L1); + S1 = S#from_form{site = TypeName, + tnames = NewTypeNames, + vtab = TmpV}, + from_form(Form, S1, D, L1, C1); false -> - {t_any(), L} + {t_any(), L, C} end; {opaque, {{Module, _FileName, Form, ArgNames}, Type}} -> case can_unfold_more(TypeName, TypeNames) of true -> NewTypeNames = [TypeName|TypeNames], - {ArgTypes, L1} = - list_from_form(Args, NewTypeNames, ET, Site0, MR, V, D, L), + S1 = S#from_form{tnames = NewTypeNames}, + {ArgTypes, L1, C1} = list_from_form(Args, S1, D, L, C), List = lists:zip(ArgNames, ArgTypes), TmpV = maps:from_list(List), - Site = TypeName, - {Rep, L2} = - t_from_form(Form, NewTypeNames, ET, Site, MR, TmpV, D, L1), + S2 = S1#from_form{site = TypeName, vtab = TmpV}, + {Rep, L2, C2} = from_form(Form, S2, D, L1, C1), Rep1 = choose_opaque_type(Rep, Type), Rep2 = case cannot_have_opaque(Rep1, TypeName, TypeNames) of true -> Rep1; @@ -4748,25 +4757,26 @@ type_from_form(Name, Args, TypeNames, ET, Site0, MR, V, D, L) -> ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), t_opaque(Module, Name, ArgTypes2, Rep1) end, - {Rep2, L2}; - false -> {t_any(), L} + {Rep2, L2, C2}; + false -> {t_any(), L, C} end; error -> Msg = io_lib:format("Unable to find type ~w/~w\n", [Name, ArgsLen]), throw({error, Msg}) end. -remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> +remote_from_form(RemMod, Name, Args, S, D, L, C) -> + #from_form{xtypes = ET, mrecs = MR, tnames = TypeNames} = S, if ET =:= replace_by_none -> - {t_none(), L}; + {t_none(), L, C}; true -> ArgsLen = length(Args), MFA = {RemMod, Name, ArgsLen}, case dict:find(RemMod, MR) of error -> self() ! {self(), ext_types, MFA}, - {t_any(), L}; + {t_any(), L, C}; {ok, RemDict} -> RemType = {type, MFA}, case sets:is_element(MFA, ET) of @@ -4776,28 +4786,25 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> case can_unfold_more(RemType, TypeNames) of true -> NewTypeNames = [RemType|TypeNames], - {ArgTypes, L1} = list_from_form(Args, TypeNames, - ET, S, MR, V, D, L), + S1 = S#from_form{tnames = NewTypeNames}, + {ArgTypes, L1, C1} = list_from_form(Args, S1, D, L, C), List = lists:zip(ArgNames, ArgTypes), - TmpVarDict = maps:from_list(List), - Site = RemType, - t_from_form(Form, NewTypeNames, ET, - Site, MR, TmpVarDict, D, L1); + TmpVarTab = maps:from_list(List), + S2 = S1#from_form{site = RemType, vtab = TmpVarTab}, + from_form(Form, S2, D, L1, C1); false -> - {t_any(), L} + {t_any(), L, C} end; {opaque, {{Mod, _FileLine, Form, ArgNames}, Type}} -> case can_unfold_more(RemType, TypeNames) of true -> NewTypeNames = [RemType|TypeNames], - {ArgTypes, L1} = list_from_form(Args, NewTypeNames, - ET, S, MR, V, D, L), + S1 = S#from_form{tnames = NewTypeNames}, + {ArgTypes, L1, C1} = list_from_form(Args, S1, D, L, C), List = lists:zip(ArgNames, ArgTypes), - TmpVarDict = maps:from_list(List), - Site = RemType, - {NewRep, L2} = - t_from_form(Form, NewTypeNames, ET, Site, MR, - TmpVarDict, D, L1), + TmpVarTab = maps:from_list(List), + S2 = S1#from_form{site = RemType, vtab = TmpVarTab}, + {NewRep, L2, C2} = from_form(Form, S2, D, L1, C1), NewRep1 = choose_opaque_type(NewRep, Type), NewRep2 = case @@ -4808,9 +4815,9 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), t_opaque(Mod, Name, ArgTypes2, NewRep1) end, - {NewRep2, L2}; + {NewRep2, L2, C2}; false -> - {t_any(), L} + {t_any(), L, C} end; error -> Msg = io_lib:format("Unable to find remote type ~w:~w()\n", @@ -4819,7 +4826,7 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, S, MR, V, D, L) -> end; false -> self() ! {self(), ext_types, {RemMod, Name, ArgsLen}}, - {t_any(), L} + {t_any(), L, C} end end end. @@ -4846,63 +4853,62 @@ choose_opaque_type(Type, DeclType) -> false -> DeclType end. -record_from_form({atom, _, Name}, ModFields, TypeNames, ET, S, MR, V, D, L) -> +record_from_form({atom, _, Name}, ModFields, S, D, L, C) -> + #from_form{site = Site, mrecs = MR, tnames = TypeNames} = S, case can_unfold_more({record, Name}, TypeNames) of true -> - M = site_module(S), + M = site_module(Site), {ok, R} = dict:find(M, MR), case lookup_record(Name, R) of {ok, DeclFields} -> NewTypeNames = [{record, Name}|TypeNames], - S1 = {record, {M, Name, length(DeclFields)}}, - {GetModRec, L1} = get_mod_record(ModFields, DeclFields, - NewTypeNames, ET, S1, MR, V, D, L), + Site1 = {record, {M, Name, length(DeclFields)}}, + S1 = S#from_form{site = Site1, tnames = NewTypeNames}, + {GetModRec, L1, C1} = + get_mod_record(ModFields, DeclFields, S1, D, L, C), case GetModRec of {error, FieldName} -> throw({error, io_lib:format("Illegal declaration of #~w{~w}\n", [Name, FieldName])}); {ok, NewFields} -> - {NewFields1, L2} = - fields_from_form(NewFields, NewTypeNames, ET, S1, MR, - var_table__new(), D, L1), + S2 = S1#from_form{vtab = var_table__new()}, + {NewFields1, L2, C2} = + fields_from_form(NewFields, S2, D, L1, C1), Rec = t_tuple( [t_atom(Name)|[Type || {_FieldName, Type} <- NewFields1]]), - {Rec, L2} + {Rec, L2, C2} end; error -> throw({error, io_lib:format("Unknown record #~w{}\n", [Name])}) end; false -> - {t_any(), L} + {t_any(), L, C} end. -get_mod_record([], DeclFields, _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {{ok, DeclFields}, L}; -get_mod_record(ModFields, DeclFields, TypeNames, ET, S, MR, V, D, L) -> +get_mod_record([], DeclFields, _S, _D, L, C) -> + {{ok, DeclFields}, L, C}; +get_mod_record(ModFields, DeclFields, S, D, L, C) -> DeclFieldsDict = lists:keysort(1, DeclFields), - {ModFieldsDict, L1} = - build_field_dict(ModFields, TypeNames, ET, S, MR, V, D, L), + {ModFieldsDict, L1, C1} = build_field_dict(ModFields, S, D, L, C), case get_mod_record_types(DeclFieldsDict, ModFieldsDict, []) of - {error, _FieldName} = Error -> {Error, L1}; + {error, _FieldName} = Error -> {Error, L1, C1}; {ok, FinalKeyDict} -> Fields = [lists:keyfind(FieldName, 1, FinalKeyDict) || {FieldName, _, _} <- DeclFields], - {{ok, Fields}, L1} + {{ok, Fields}, L1, C1} end. -build_field_dict(FieldTypes, TypeNames, ET, S, MR, V, D, L) -> - build_field_dict(FieldTypes, TypeNames, ET, S, MR, V, D, L, []). +build_field_dict(FieldTypes, S, D, L, C) -> + build_field_dict(FieldTypes, S, D, L, C, []). build_field_dict([{type, _, field_type, [{atom, _, Name}, Type]}|Left], - TypeNames, ET, S, MR, V, D, L, Acc) -> - {T, L1} = t_from_form(Type, TypeNames, ET, S, MR, V, D, L - 1), + S, D, L, C, Acc) -> + {T, L1, C1} = from_form(Type, S, D, L - 1, C), NewAcc = [{Name, Type, T}|Acc], - {Dict, L2} = - build_field_dict(Left, TypeNames, ET, S, MR, V, D, L1, NewAcc), - {Dict, L2}; -build_field_dict([], _TypeNames, _ET, _S, _MR, _V, _D, L, Acc) -> - {lists:keysort(1, Acc), L}. + build_field_dict(Left, S, D, L1, C1, NewAcc); +build_field_dict([], _S, _D, L, C, Acc) -> + {lists:keysort(1, Acc), L, C}. get_mod_record_types([{FieldName, _Abstr, _DeclType}|Left1], [{FieldName, TypeForm, ModType}|Left2], @@ -4920,20 +4926,19 @@ get_mod_record_types(_, [{FieldName2, _FormType, _ModType}|_], _Acc) -> %% It is important to create a limited version of the record type %% since nested record types can otherwise easily result in huge %% terms. -fields_from_form([], _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {[], L}; -fields_from_form([{Name, Abstr, _Type}|Tail], TypeNames, ET, S, MR, - V, D, L) -> - {T, L1} = t_from_form(Abstr, TypeNames, ET, S, MR, V, D, L), - {F, L2} = fields_from_form(Tail, TypeNames, ET, S, MR, V, D, L1), - {[{Name, T}|F], L2}. - -list_from_form([], _TypeNames, _ET, _S, _MR, _V, _D, L) -> - {[], L}; -list_from_form([H|Tail], TypeNames, ET, S, MR, V, D, L) -> - {H1, L1} = t_from_form(H, TypeNames, ET, S, MR, V, D, L - 1), - {T1, L2} = list_from_form(Tail, TypeNames, ET, S, MR, V, D, L1), - {[H1|T1], L2}. +fields_from_form([], _S, _D, L, C) -> + {[], L, C}; +fields_from_form([{Name, Abstr, _Type}|Tail], S, D, L, C) -> + {T, L1, C1} = from_form(Abstr, S, D, L, C), + {F, L2, C2} = fields_from_form(Tail, S, D, L1, C1), + {[{Name, T}|F], L2, C2}. + +list_from_form([], _S, _D, L, C) -> + {[], L, C}; +list_from_form([H|Tail], S, D, L, C) -> + {H1, L1, C1} = from_form(H, S, D, L - 1, C), + {T1, L2, C2} = list_from_form(Tail, S, D, L1, C1), + {[H1|T1], L2, C2}. %% Sorts, combines non-singleton pairs, and applies precendence and %% mandatoriness rules. @@ -5151,10 +5156,15 @@ t_form_to_string({type, _L, Name, []} = T) -> M = mod, D0 = dict:new(), MR = dict:from_list([{M, D0}]), - S = {type, {M,Name,0}}, + Site = {type, {M,Name,0}}, V = #{}, - {T1, _} = - t_from_form(T, [], sets:new(), S, MR, V, _Deep=1000, _ALot=100000), + C = #{}, + State = #from_form{site = Site, + xtypes = sets:new(), + mrecs = MR, + vtab = V, + tnames = []}, + {T1, _, _} = from_form(T, State, _Deep=1000, _ALot=1000000, C), t_to_string(T1) catch throw:{error, _} -> atom_to_string(Name) ++ "()" end; |