diff options
Diffstat (limited to 'lib/hipe/cerl/erl_bif_types.erl')
-rw-r--r-- | lib/hipe/cerl/erl_bif_types.erl | 117 |
1 files changed, 89 insertions, 28 deletions
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 0b47c7b6e1..4163f2dae2 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -366,7 +366,7 @@ type(erlang, '>', 2, Xs = [Lhs, Rhs]) -> is_integer(LhsMax), is_integer(RhsMin), RhsMin >= LhsMax -> F; true -> t_boolean() end; - false -> t_boolean() + false -> compare('>', Lhs, Rhs) end, strict(Xs, Ans); type(erlang, '>=', 2, Xs = [Lhs, Rhs]) -> @@ -384,7 +384,7 @@ type(erlang, '>=', 2, Xs = [Lhs, Rhs]) -> is_integer(LhsMax), is_integer(RhsMin), RhsMin > LhsMax -> F; true -> t_boolean() end; - false -> t_boolean() + false -> compare('>=', Lhs, Rhs) end, strict(Xs, Ans); type(erlang, '<', 2, Xs = [Lhs, Rhs]) -> @@ -402,7 +402,7 @@ type(erlang, '<', 2, Xs = [Lhs, Rhs]) -> is_integer(LhsMin), is_integer(RhsMax), RhsMax =< LhsMin -> F; true -> t_boolean() end; - false -> t_boolean() + false -> compare('<', Lhs, Rhs) end, strict(Xs, Ans); type(erlang, '=<', 2, Xs = [Lhs, Rhs]) -> @@ -420,7 +420,7 @@ type(erlang, '=<', 2, Xs = [Lhs, Rhs]) -> is_integer(LhsMin), is_integer(RhsMax), RhsMax < LhsMin -> F; true -> t_boolean() end; - false -> t_boolean() + false -> compare('=<', Lhs, Rhs) end, strict(Xs, Ans); type(erlang, '+', 1, Xs) -> @@ -672,6 +672,9 @@ type(erlang, call_on_load_function, 1, Xs) -> type(erlang, cancel_timer, 1, Xs) -> strict(arg_types(erlang, cancel_timer, 1), Xs, fun (_) -> t_sup(t_integer(), t_atom('false')) end); +type(erlang, check_old_code, 1, Xs) -> + strict(arg_types(erlang, check_old_code, 1), Xs, + fun (_) -> t_boolean() end); type(erlang, check_process_code, 2, Xs) -> strict(arg_types(erlang, check_process_code, 2), Xs, fun (_) -> t_boolean() end); @@ -702,7 +705,7 @@ type(erlang, demonitor, 1, Xs) -> type(erlang, demonitor, 2, Xs) -> strict(arg_types(erlang, demonitor, 2), Xs, fun (_) -> t_boolean() end); type(erlang, disconnect_node, 1, Xs) -> - strict(arg_types(erlang, disconnect_node, 1), Xs, fun (_) -> t_boolean() end); + strict(arg_types(erlang, disconnect_node, 1), Xs, fun (_) -> t_sup([t_boolean(), t_atom('ignored')]) end); type(erlang, display, 1, _) -> t_atom('true'); type(erlang, display_string, 1, Xs) -> strict(arg_types(erlang, display_string, 1), Xs, fun(_) -> t_atom('true') end); @@ -736,6 +739,7 @@ type(erlang, element, 2, Xs) -> type(erlang, erase, 0, _) -> t_any(); type(erlang, erase, 1, _) -> t_any(); type(erlang, external_size, 1, _) -> t_integer(); +type(erlang, external_size, 2, _) -> t_integer(); type(erlang, finish_after_on_load, 2, Xs) -> %% Internal BIF used by on_load. strict(arg_types(erlang, finish_after_on_load, 2), Xs, @@ -1124,7 +1128,7 @@ type(erlang, nodes, 0, _) -> t_list(t_node()); type(erlang, nodes, 1, Xs) -> strict(arg_types(erlang, nodes, 1), Xs, fun (_) -> t_list(t_node()) end); type(erlang, now, 0, _) -> - t_time(); + t_timestamp(); type(erlang, open_port, 2, Xs) -> strict(arg_types(erlang, open_port, 2), Xs, fun (_) -> t_port() end); type(erlang, phash, 2, Xs) -> @@ -1199,6 +1203,7 @@ type(erlang, process_flag, 2, Xs) -> case t_atom_vals(Flag) of ['error_handler'] -> t_atom(); ['min_heap_size'] -> t_non_neg_integer(); + ['scheduler'] -> t_non_neg_integer(); ['monitor_nodes'] -> t_boolean(); ['priority'] -> t_process_priority_level(); ['save_calls'] -> t_non_neg_integer(); @@ -1585,8 +1590,7 @@ type(erlang, system_info, 1, Xs) -> ['multi_scheduling_blockers'] -> t_list(t_pid()); ['os_type'] -> - t_tuple([t_sup([t_atom('ose'), % XXX: undocumented - t_atom('unix'), + t_tuple([t_sup([t_atom('unix'), t_atom('vxworks'), t_atom('win32')]), t_atom()]); @@ -1900,7 +1904,7 @@ type(prim_file, internal_native2name, 1, Xs) -> fun (_) -> t_prim_file_name() end); type(prim_file, internal_normalize_utf8, 1, Xs) -> strict(arg_types(prim_file, internal_normalize_utf8, 1), Xs, - fun (_) -> t_binary() end); + fun (_) -> t_unicode_string() end); %%-- gen_tcp ------------------------------------------------------------------ %% NOTE: All type information for this module added to avoid loss of precision type(gen_tcp, accept, 1, Xs) -> @@ -2325,10 +2329,7 @@ type(lists, keyfind, 3, Xs) -> case t_tuple_subtypes(Tuple) of unknown -> Ret; List -> - Keys = [type(erlang, element, 2, [Y, S]) - || S <- List], - Infs = [t_inf(Key, X) || Key <- Keys], - case all_is_none(Infs) of + case key_comparisons_fail(X, Y, List) of true -> t_atom('false'); false -> Ret end @@ -2358,9 +2359,7 @@ type(lists, keymember, 3, Xs) -> case t_tuple_subtypes(Tuple) of unknown -> t_boolean(); List -> - Keys = [type(erlang, element, 2, [Y,S]) || S <- List], - Infs = [t_inf(Key, X) || Key <- Keys], - case all_is_none(Infs) of + case key_comparisons_fail(X, Y, List) of true -> t_atom('false'); false -> t_boolean() end @@ -2390,10 +2389,7 @@ type(lists, keysearch, 3, Xs) -> case t_tuple_subtypes(Tuple) of unknown -> Ret; List -> - Keys = [type(erlang, element, 2, [Y, S]) - || S <- List], - Infs = [t_inf(Key, X) || Key <- Keys], - case all_is_none(Infs) of + case key_comparisons_fail(X, Y, List) of true -> t_atom('false'); false -> Ret end @@ -2693,7 +2689,7 @@ type(os, getpid, 0, _) -> t_string(); type(os, putenv, 2, Xs) -> strict(arg_types(os, putenv, 2), Xs, fun (_) -> t_atom('true') end); type(os, timestamp, 0, _) -> - t_time(); + t_timestamp(); %%-- re ----------------------------------------------------------------------- type(re, compile, 1, Xs) -> strict(arg_types(re, compile, 1), Xs, @@ -2821,9 +2817,6 @@ list_replace(1, E, [_X | Xs]) -> any_is_none_or_unit(Ts) -> lists:any(fun erl_types:t_is_none_or_unit/1, Ts). -all_is_none(Ts) -> - lists:all(fun erl_types:t_is_none/1, Ts). - check_guard([X], Test, Type) -> check_guard_single(X, Test, Type). @@ -3176,6 +3169,59 @@ arith(Op, X1, X2) -> end. %%============================================================================= +%% Comparison of terms +%%============================================================================= + +compare(Op, Lhs, Rhs) -> + case t_is_none(t_inf(Lhs, Rhs)) of + false -> t_boolean(); + true -> + case Op of + '<' -> always_smaller(Lhs, Rhs); + '>' -> always_smaller(Rhs, Lhs); + '=<' -> always_smaller(Lhs, Rhs); + '>=' -> always_smaller(Rhs, Lhs) + end + end. + +always_smaller(Type1, Type2) -> + {Min1, Max1} = type_ranks(Type1), + {Min2, Max2} = type_ranks(Type2), + if Max1 < Min2 -> t_atom('true'); + Min1 > Max2 -> t_atom('false'); + true -> t_boolean() + end. + +type_ranks(Type) -> + type_ranks(Type, 1, 0, 0, type_order()). + +type_ranks(_Type, _I, Min, Max, []) -> {Min, Max}; +type_ranks(Type, I, Min, Max, [TypeClass|Rest]) -> + {NewMin, NewMax} = + case t_is_none(t_inf(Type, TypeClass)) of + true -> {Min, Max}; + false -> case Min of + 0 -> {I, I}; + _ -> {Min, I} + end + end, + type_ranks(Type, I+1, NewMin, NewMax, Rest). + +type_order() -> + [t_number(), t_atom(), t_reference(), t_fun(), t_port(), t_pid(), t_tuple(), + t_list(), t_binary()]. + +key_comparisons_fail(X0, KeyPos, TupleList) -> + X = case t_is_number(t_inf(X0, t_number())) of + false -> X0; + true -> t_number() + end, + lists:all(fun(Tuple) -> + Key = type(erlang, element, 2, [KeyPos, Tuple]), + t_is_none(t_inf(Key, X)) + end, TupleList). + +%%============================================================================= -spec arg_types(atom(), atom(), arity()) -> [erl_types:erl_type()] | 'unknown'. @@ -3396,6 +3442,8 @@ arg_types(erlang, call_on_load_function, 1) -> [t_atom()]; arg_types(erlang, cancel_timer, 1) -> [t_reference()]; +arg_types(erlang, check_old_code, 1) -> + [t_atom()]; arg_types(erlang, check_process_code, 2) -> [t_pid(), t_atom()]; arg_types(erlang, concat_binary, 1) -> @@ -3442,6 +3490,8 @@ arg_types(erlang, exit, 2) -> [t_sup(t_pid(), t_port()), t_any()]; arg_types(erlang, external_size, 1) -> [t_any()]; % takes any term as input +arg_types(erlang, external_size, 2) -> + [t_any(), t_list()]; % takes any term as input and a list of options arg_types(erlang, finish_after_on_load, 2) -> [t_atom(), t_boolean()]; arg_types(erlang, float, 1) -> @@ -3696,6 +3746,7 @@ arg_types(erlang, process_display, 2) -> arg_types(erlang, process_flag, 2) -> [t_sup([t_atom('trap_exit'), t_atom('error_handler'), t_atom('min_heap_size'), t_atom('priority'), t_atom('save_calls'), + t_atom('scheduler'), % undocumented t_atom('monitor_nodes'), % undocumented t_tuple([t_atom('monitor_nodes'), t_list()])]), % undocumented t_sup([t_boolean(), t_atom(), t_non_neg_integer()])]; @@ -3734,7 +3785,7 @@ arg_types(erlang, send, 3) -> arg_types(erlang, send_after, 3) -> [t_non_neg_integer(), t_sup(t_pid(), t_atom()), t_any()]; arg_types(erlang, seq_trace, 2) -> - [t_atom(), t_sup([t_boolean(), t_tuple([t_fixnum(), t_fixnum()]), t_nil()])]; + [t_atom(), t_sup([t_boolean(), t_tuple([t_fixnum(), t_fixnum()]), t_fixnum(), t_nil()])]; arg_types(erlang, seq_trace_info, 1) -> [t_seq_trace_info()]; arg_types(erlang, seq_trace_print, 1) -> @@ -3983,7 +4034,7 @@ arg_types(ets, match_object, 3) -> arg_types(ets, match_spec_compile, 1) -> [t_matchspecs()]; arg_types(ets, match_spec_run_r, 3) -> - [t_matchspecs(), t_any(), t_list()]; + [t_list(t_tuple()),t_matchspecs(), t_list()]; arg_types(ets, member, 2) -> [t_tab(), t_any()]; arg_types(ets, new, 2) -> @@ -4015,8 +4066,12 @@ arg_types(ets, select_reverse, 3) -> arg_types(ets, slot, 2) -> [t_tab(), t_non_neg_fixnum()]; % 2nd arg can be 0 arg_types(ets, setopts, 2) -> - Opt = t_sup(t_tuple([t_atom('heir'), t_pid(), t_any()]), - t_tuple([t_atom('heir'), t_atom('none')])), + Opt = t_sup([t_tuple([t_atom('heir'), t_pid(), t_any()]), + t_tuple([t_atom('heir'), t_atom('none')]), + t_tuple([t_atom('protection'), + t_sup([t_atom('protected'), + t_atom('private'), + t_atom('public')])])]), [t_tab(), t_sup(Opt, t_list(Opt))]; arg_types(ets, update_counter, 3) -> Int = t_integer(), @@ -4458,6 +4513,9 @@ t_date() -> t_time() -> t_tuple([t_non_neg_fixnum(), t_non_neg_fixnum(), t_non_neg_fixnum()]). +t_timestamp() -> + t_tuple([t_non_neg_fixnum(), t_non_neg_fixnum(), t_non_neg_fixnum()]). + t_packet() -> t_sup([t_binary(), t_iolist(), t_httppacket()]). @@ -4805,6 +4863,9 @@ t_ets_info_items() -> t_atom('owner'), t_atom('protection'), t_atom('size'), + t_atom('compressed'), + t_atom('heir'), + t_atom('stats'), t_atom('type')]). %% ===================================================================== |