erl_bif_types.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,807 行 · 第 1/5 页
ERL
1,807 行
%% -*- erlang-indent-level: 2 -*-%% =====================================================================%% Type information for Erlang Built-in functions (implemented in C)%%%% Copyright (C) 2002 Richard Carlsson%% Copyright (C) 2006 Richard Carlsson, Tobias Lindahl and Kostis Sagonas%%%% This library is free software; you can redistribute it and/or modify%% it under the terms of the GNU Lesser General Public License as%% published by the Free Software Foundation; either version 2 of the%% License, or (at your option) any later version.%%%% This library is distributed in the hope that it will be useful, but%% WITHOUT ANY WARRANTY; without even the implied warranty of%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU%% Lesser General Public License for more details.%%%% You should have received a copy of the GNU Lesser General Public%% License along with this library; if not, write to the Free Software%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307%% USA%%%% Author contact: richardc@it.uu.se, tobiasl@it.uu.se, kostis@it.uu.se%%%% $Id$%%%% =====================================================================-module(erl_bif_types).%-define(BITS, (hipe_rtl_arch:word_size() * 8) - ?TAG_IMMED1_SIZE).-define(BITS, 128). %This is only in bsl to convert answer to pos_inf/neg_inf.-define(TAG_IMMED1_SIZE, 4).-export([type/3, type/4, arg_types/1, arg_types/3, is_known/3, infinity_add/2]).-include("../icode/hipe_icode_primops.hrl").-import(erl_types, [ number_max/1, number_min/1, t_any/0, t_arity/0, t_atom/0, t_atom/1, t_atom_vals/1, t_binary/0, t_bool/0, t_byte/0, t_char/0, t_cons/0, t_cons/2, t_cons_hd/1, t_cons_tl/1, t_constant/0, t_fixnum/0, t_non_neg_fixnum/0, t_pos_fixnum/0, t_float/0, t_from_range/2, t_from_term/1, t_fun/0, t_fun/2, t_fun_args/1, t_fun_range/1, t_identifier/0, t_inf/2, t_integer/0, t_non_neg_integer/0, t_pos_integer/0, t_integers/1, t_is_any/1, t_is_atom/1, t_is_binary/1, t_is_bool/1, t_is_cons/1, t_is_constant/1, t_is_float/1, t_is_float/1, t_is_fun/1, t_is_integer/1, t_is_integer/1, t_is_nil/1, t_is_none/1, t_is_none_or_unit/1, t_is_number/1, t_is_pid/1, t_is_port/1, t_is_pos_improper_list/1, t_is_ref/1, t_is_string/1, t_is_subtype/2, t_is_tuple/1, t_list/0, t_list/1, t_list_elements/1, t_mfa/0, t_nil/0, t_none/0, t_nonempty_list/0, t_nonempty_list/1, t_number/0, t_number_vals/1, t_pid/0, t_port/0, t_pos_improper_list/0, t_pos_improper_list/2, t_ref/0, t_string/0, t_subtract/2, t_sup/1, t_sup/2, t_tuple/0, t_tuple/1, t_tuple_args/1, t_tuple_arity/1, t_tuple_subtypes/1, t_unit/0 ]).-ifdef(DO_ERL_BIF_TYPES_TEST).-export([test/0]).-endif.type(M, F, A) -> type(M, F, A, any_list(A)).%% Arguments should be checked for undefinedness, so we do not make%% unnecessary overapproximations.%%-- code ---------------------------------------------------------------------type(code, add_path, 1, Xs) -> strict(arg_types(code, add_path, 1), Xs, fun (_) -> t_sup(t_bool(), t_tuple([t_atom('error'), t_atom('bad_directory')])) end);type(code, add_patha, 1, Xs) -> type(code, add_path, 1, Xs);type(code, add_paths, 1, Xs) -> type(code, add_path, 1, Xs);type(code, add_pathsa, 1, Xs) -> type(code, add_path, 1, Xs);type(code, add_pathsz, 1, Xs) -> type(code, add_path, 1, Xs);type(code, add_pathz, 1, Xs) -> type(code, add_path, 1, Xs);type(code, all_loaded, 0, _) -> t_list(t_tuple([t_atom(), t_sup([t_string(), % filename t_atom('preloaded'), t_atom('cover_compiled')])]));type(code, compiler_dir, 0, _) -> t_string();type(code, del_path, 1, Xs) -> strict(arg_types(code, del_path, 1), Xs, fun (_) -> t_sup(t_bool(), t_tuple([t_atom('error'), t_atom('bad_name')])) end);type(code, delete, 1, Xs) -> strict(arg_types(code, delete, 1), Xs, fun (_) -> t_bool() end);type(code, ensure_loaded, 1, Xs) -> type(code, load_file, 1, Xs);type(code, get_chunk, 2, Xs) -> strict(arg_types(code, get_chunk, 2), Xs, fun (_) -> t_sup(t_binary(), t_atom('undefined')) end);type(code, get_object_code, 1, Xs) -> strict(arg_types(code, get_object_code, 1), Xs, fun (_) -> t_sup(t_tuple([t_atom(), t_binary(), t_string()]), t_atom('error')) end);type(code, get_path, 0, _) -> t_list(t_string());type(code, is_loaded, 1, Xs) -> strict(arg_types(code, is_loaded, 1), Xs, fun (_) -> t_sup([t_tuple([t_atom('file'), t_string()]), % filename t_tuple([t_atom('file'), t_atom('preloaded')]), t_tuple([t_atom('file'), t_atom('cover_compiled')]), t_atom('false')]) end);type(code, is_sticky, 1, Xs) -> strict(arg_types(code, is_sticky, 1), Xs, fun (_) -> t_bool() end);type(code, is_module_native, 1, Xs) -> strict(arg_types(code, is_module_native, 1), Xs, fun (_) -> t_sup(t_bool(), t_atom('undefined')) end);type(code, lib_dir, 0, _) -> t_string();type(code, lib_dir, 1, Xs) -> strict(arg_types(code, lib_dir, 1), Xs, fun (_) -> t_sup(t_string(), t_tuple([t_atom('error'), t_atom('bad_name')])) end);type(code, load_abs, 1, Xs) -> type(code, load_file, 1, Xs);type(code, load_abs, 2, Xs) -> strict(arg_types(code, load_abs, 2), Xs, fun ([_File,Mod]) -> t_sup(t_tuple([t_atom('module'), Mod]), t_tuple([t_atom('error'), t_load_module_error_rsn()])) end);type(code, load_binary, 3, Xs) -> strict(arg_types(code, load_binary, 3), Xs, fun ([Mod,_File,_Bin]) -> t_sup(t_tuple([t_atom('module'), Mod]), t_tuple([t_atom('error'), t_load_module_error_rsn()])) end);type(code, load_file, 1, Xs) -> strict(arg_types(code, load_file, 1), Xs, fun ([Mod]) -> t_sup(t_tuple([t_atom('module'), case t_is_atom(Mod) of true -> Mod; false -> t_atom() end]), t_tuple([t_atom('error'), t_load_module_error_rsn()])) end);type(code, load_native_partial, 2, Xs) -> strict(arg_types(code, load_native_partial, 2), Xs, fun ([Mod,_Bin]) -> t_sup(t_tuple([t_atom('module'), Mod]), t_tuple([t_atom('error'), t_load_module_error_rsn()])) end);type(code, load_native_sticky, 3, Xs) -> strict(arg_types(code, load_native_sticky, 3), Xs, fun ([Mod,_Bin,_]) -> t_sup(t_tuple([t_atom('module'), Mod]), t_tuple([t_atom('error'), t_load_module_error_rsn()])) end);type(code, module_md5, 1, Xs) -> strict(arg_types(code, module_md5, 1), Xs, fun (_) -> t_sup(t_binary(), t_atom('undefined')) end);type(code, make_stub_module, 3, Xs) -> strict(arg_types(code, make_stub_module, 3), Xs, fun ([Mod,_,_]) -> Mod end);type(code, priv_dir, 1, Xs) -> strict(arg_types(code, priv_dir, 1), Xs, fun (_) -> t_sup(t_string(), t_tuple([t_atom('error'), t_atom('bad_name')])) end);type(code, purge, 1, Xs) -> type(code, delete, 1, Xs);type(code, rehash, 0, _) -> t_atom('ok');type(code, replace_path, 2, Xs) -> strict(arg_types(code, replace_path, 2), Xs, fun (_) -> t_sup([t_atom('true'), t_tuple([t_atom('error'), t_atom('bad_name')]), t_tuple([t_atom('error'), t_atom('bad_directory')]), t_tuple([t_atom('error'), t_tuple([t_atom('badarg'), t_any()])])]) end);type(code, root_dir, 0, _) -> t_string();type(code, set_path, 1, Xs) -> strict(arg_types(code, set_path, 1), Xs, fun (_) -> t_sup([t_atom('true'), t_tuple([t_atom('error'), t_atom('bad_path')]), t_tuple([t_atom('error'), t_atom('bad_directory')])]) end);type(code, soft_purge, 1, Xs) -> type(code, delete, 1, Xs);type(code, stick_dir, 1, Xs) -> strict(arg_types(code, stick_dir, 1), Xs, fun (_) -> t_sup(t_atom('ok'), t_atom('error')) end);type(code, stick_mod, 1, Xs) -> strict(arg_types(code, stick_mod, 1), Xs, fun (_) -> t_atom('true') end);type(code, stop, 0, _) -> t_none();type(code, unstick_dir, 1, Xs) -> type(code, stick_dir, 1, Xs);type(code, unstick_mod, 1, Xs) -> type(code, stick_mod, 1, Xs);type(code, which, 1, Xs) -> strict(arg_types(code, which, 1), Xs, fun (_) -> t_sup([t_string(), t_atom('preloaded'), t_atom('cover_compiled'), t_atom('non_existing')]) end);%%-- erl_ddll -----------------------------------------------------------------type(erl_ddll, demonitor, 1, Xs) -> type(erlang, demonitor, 1, Xs);type(erl_ddll, format_error_int, 1, Xs) -> strict(arg_types(erl_ddll, format_error_int, 1), Xs, fun (_) -> t_string() end);type(erl_ddll, info, 2, Xs) -> strict(arg_types(erl_ddll, info, 2), Xs, fun (_) -> t_atom() end);type(erl_ddll, loaded_drivers, 0, _) -> t_tuple([t_atom('ok'), t_list(t_string())]);type(erl_ddll, monitor, 2, Xs) -> % return type is the same, though args are not type(erlang, monitor, 2, Xs);type(erl_ddll, try_load, 3, Xs) -> strict(arg_types(erl_ddll, try_load, 3), Xs, fun (_) -> t_sup([t_tuple([t_atom('ok'), t_atom('already_loaded')]), t_tuple([t_atom('ok'), t_atom('loaded')]), t_tuple([t_atom('ok'), t_atom('pending_driver'), t_ref()]), t_tuple([t_atom('error'), t_atom('inconsistent')]), t_tuple([t_atom('error'), t_atom('permanent')])]) end);type(erl_ddll, try_unload, 2, Xs) -> strict(arg_types(erl_ddll, try_unload, 2), Xs, fun (_) -> t_sup([t_tuple([t_atom('ok'), t_atom('pending_process')]), t_tuple([t_atom('ok'), t_atom('unloaded')]), t_tuple([t_atom('ok'), t_atom('pending_driver')]), t_tuple([t_atom('ok'), t_atom('pending_driver'), t_ref()]), t_tuple([t_atom('error'), t_atom('permanent')]), t_tuple([t_atom('error'), t_atom('not_loaded')]), t_tuple([t_atom('error'), t_atom('not_loaded_by_this_process')])]) end);%%-- erlang -------------------------------------------------------------------type(erlang, halt, 0, _) -> t_none();type(erlang, halt, 1, _) -> t_none();type(erlang, exit, 1, _) -> t_none();%% Note that exit/2 sends an exit signal to another process.type(erlang, exit, 2, _) -> t_atom(true);type(erlang, fault, 1, _) -> t_none();type(erlang, fault, 2, _) -> t_none();type(erlang, error, 1, _) -> t_none();type(erlang, error, 2, _) -> t_none();type(erlang, throw, 1, _) -> t_none();type(erlang, hibernate, 3, _) -> t_none();type(erlang, '==', 2, Xs = [X1, X2]) -> case t_is_atom(X1) andalso t_is_atom(X2) of true -> type(erlang, '=:=', 2, Xs); false -> case t_is_integer(X1) andalso t_is_integer(X2) of true -> type(erlang, '=:=', 2, Xs); false -> strict(Xs, t_bool()) end end;type(erlang, '/=', 2, Xs = [X1, X2]) -> case t_is_atom(X1) andalso t_is_atom(X2) of true -> type(erlang, '=/=', 2, Xs); false -> case t_is_integer(X1) andalso t_is_integer(X2) of true -> type(erlang, '=/=', 2, Xs); false -> strict(Xs, t_bool()) end end;type(erlang, '=:=', 2, Xs = [Lhs, Rhs]) -> Ans = case t_is_none(t_inf(Lhs, Rhs)) of true -> t_from_term(false); false -> case t_is_atom(Lhs) andalso t_is_atom(Rhs) of true -> case {t_atom_vals(Lhs), t_atom_vals(Rhs)} of {[X], [X]} -> t_from_term(true); {LhsVals, RhsVals} when LhsVals =/= any, RhsVals =/= any -> case lists:all(fun({X, Y}) -> X =/= Y end, [{X, Y} || X <- LhsVals, Y <- RhsVals]) of true -> t_from_term(false); false -> t_bool() end; _ -> t_bool() end;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?