File 1181-erts-Add-guard-BIF-erlang-is_integer-3.patch of Package erlang
From 64b2fde4e58e0f743cb910afff656e06fdd2312d Mon Sep 17 00:00:00 2001
From: Isabell Huang <isabell@erlang.org>
Date: Mon, 9 Jun 2025 10:51:57 +0200
Subject: [PATCH] erts: Add guard BIF `erlang:is_integer/3`
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add guard BIF `erlang:is_integer/3`, following the design of the
original EEP-16, only changing the name from `is_between` to
`is_integer`. This BIF takes in 3 parameters, `Term`, `LowerBound`,
and `UpperBound`.
It returns `true` if `Term`, `LowerBound`, and `UpperBound` are
all integers, and `LowerBound =< Term =< UpperBound`; otherwise,
it returns false.
Failure: `badarg` if `LowerBound` or `UpperBound` does not evaluate to
an integer.
Example:
````
1> is_integer(2, 1, 10).
true
2> is_integer(11, 1, 10).
false
3> is_integer(1, 1.0, 10.0).
** exception error: bad argument
in function is_integer/3
called as is_integer(1,1.0,10.0)
````
Co-authored-by: Björn Gustavsson <bjorn@erlang.org>
Co-authored-by: John Högberg <john@erlang.org>
---
erts/emulator/beam/bif.tab | 5 +
erts/emulator/beam/emu/ops.tab | 2 +
erts/emulator/beam/erl_bif_guard.c | 14 ++
erts/emulator/beam/erl_db_util.c | 6 +
erts/emulator/beam/jit/arm/ops.tab | 1 +
erts/emulator/beam/jit/x86/ops.tab | 1 +
erts/emulator/test/bif_SUITE.erl | 71 +++++++++-
erts/emulator/test/exception_SUITE.erl | 1 +
erts/preloaded/ebin/erlang.beam | Bin 40316 -> 40356 bytes
erts/preloaded/ebin/init.beam | Bin 27912 -> 27924 bytes
erts/preloaded/src/erlang.erl | 27 +++-
lib/compiler/src/beam_asm.erl | 3 +-
lib/compiler/src/beam_call_types.erl | 42 ++++--
lib/compiler/src/beam_disasm.erl | 4 +
lib/compiler/src/beam_ssa_codegen.erl | 1 +
lib/compiler/src/beam_ssa_opt.erl | 51 ++++++-
lib/compiler/src/beam_ssa_pre_codegen.erl | 1 +
lib/compiler/src/beam_ssa_type.erl | 29 ++++
lib/compiler/src/beam_validator.erl | 33 +++++
lib/compiler/src/erl_bifs.erl | 1 +
lib/compiler/src/genop.tab | 8 ++
lib/compiler/test/guard_SUITE.erl | 155 +++++++++++++++++++++-
lib/dialyzer/src/erl_bif_types.erl | 2 +
lib/kernel/src/erl_erts_errors.erl | 2 +
lib/stdlib/src/erl_internal.erl | 2 +
25 files changed, 438 insertions(+), 24 deletions(-)
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 95fcb0589f..e03f312443 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -834,3 +834,8 @@ bif erl_debugger:peek_xreg/3
#
bif erts_debug:unaligned_bitstring/2
bif re:import/1
+
+#
+# New in 29.
+#
+ubif erlang:is_integer/3
diff --git a/erts/emulator/beam/emu/ops.tab b/erts/emulator/beam/emu/ops.tab
index 68eebde0f2..265ca44b55 100644
--- a/erts/emulator/beam/emu/ops.tab
+++ b/erts/emulator/beam/emu/ops.tab
@@ -1001,6 +1001,8 @@ bif1 Fail=f Bif S1 Dst => i_bif1 S1 Fail Bif Dst
bif2 p Bif S1 S2 Dst => i_bif2_body S2 S1 Bif Dst
bif2 Fail=f Bif S1 S2 Dst => i_bif2 S2 S1 Fail Bif Dst
+bif3 p Bif S1 S2 S3 Dst => i_bif3_body S3 S2 S1 Bif Dst
+
i_get_hash c W d
i_get s d
diff --git a/erts/emulator/beam/erl_bif_guard.c b/erts/emulator/beam/erl_bif_guard.c
index 258e48a51e..5fc801179f 100644
--- a/erts/emulator/beam/erl_bif_guard.c
+++ b/erts/emulator/beam/erl_bif_guard.c
@@ -334,6 +334,20 @@ BIF_RETTYPE size_1(BIF_ALIST_1)
BIF_ERROR(BIF_P, BADARG);
}
+BIF_RETTYPE is_integer_3(BIF_ALIST_3)
+{
+ if(is_not_integer(BIF_ARG_2) ||
+ is_not_integer(BIF_ARG_3)) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+ if(is_not_integer(BIF_ARG_1)) {
+ BIF_RET(am_false);
+ }
+
+ BIF_RET((CMP_LE(BIF_ARG_2, BIF_ARG_1) && CMP_LE(BIF_ARG_1, BIF_ARG_3)) ?
+ am_true : am_false);
+}
+
/**********************************************************************/
/* returns the bitsize of a bitstring */
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index de67d804c0..1ffe59aa5e 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -588,6 +588,12 @@ static DMCGuardBif guard_tab[] =
1,
DBIF_ALL
},
+ {
+ am_is_integer,
+ &is_integer_3,
+ 3,
+ DBIF_ALL
+ },
{
am_is_list,
&is_list_1,
diff --git a/erts/emulator/beam/jit/arm/ops.tab b/erts/emulator/beam/jit/arm/ops.tab
index 6c0d1a1725..180c6925a5 100644
--- a/erts/emulator/beam/jit/arm/ops.tab
+++ b/erts/emulator/beam/jit/arm/ops.tab
@@ -814,6 +814,7 @@ bif2 _Fail Bif S1 S2 Dst | never_fails(Bif) => nofail_bif2 S1 S2 Bif Dst
bif1 Fail Bif S1 Dst => i_bif1 S1 Fail Bif Dst
bif2 Fail Bif S1 S2 Dst => i_bif2 S1 S2 Fail Bif Dst
+bif3 Fail Bif S1 S2 S3 Dst => i_bif3 S1 S2 S3 Fail Bif Dst
nofail_bif2 S1=d S2 Bif Dst | is_eq_exact_bif(Bif) => bif_is_eq_exact S1 S2 Dst
nofail_bif2 S1=d S2 Bif Dst | is_ne_exact_bif(Bif) => bif_is_ne_exact S1 S2 Dst
diff --git a/erts/emulator/beam/jit/x86/ops.tab b/erts/emulator/beam/jit/x86/ops.tab
index 2b0dfb2e4a..5bbbaf747e 100644
--- a/erts/emulator/beam/jit/x86/ops.tab
+++ b/erts/emulator/beam/jit/x86/ops.tab
@@ -745,6 +745,7 @@ bif2 _Fail Bif S1 S2 Dst | never_fails(Bif) => nofail_bif2 S1 S2 Bif Dst
bif1 Fail Bif S1 Dst => i_bif1 S1 Fail Bif Dst
bif2 Fail Bif S1 S2 Dst => i_bif2 S1 S2 Fail Bif Dst
+bif3 Fail Bif S1 S2 S3 Dst => i_bif3 S1 S2 S3 Fail Bif Dst
nofail_bif2 S1=d S2 Bif Dst | is_eq_exact_bif(Bif) => bif_is_eq_exact S1 S2 Dst
nofail_bif2 S1=d S2 Bif Dst | is_ne_exact_bif(Bif) => bif_is_ne_exact S1 S2 Dst
diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl
index 5b286b7f64..3d8782d9da 100644
--- a/erts/emulator/test/bif_SUITE.erl
+++ b/erts/emulator/test/bif_SUITE.erl
@@ -24,6 +24,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
+-include_lib("stdlib/include/assert.hrl").
-export([all/0, suite/0, init_per_testcase/2, end_per_testcase/2]).
@@ -46,7 +47,7 @@
test_length/1,
fixed_apply_badarg/1,
external_fun_apply3/1,
- node_1/1,doctests/1]).
+ node_1/1,doctests/1,is_integer_3_test/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -64,7 +65,7 @@ all() ->
is_process_alive, is_process_alive_signal_from,
process_info_blast, os_env_case_sensitivity,
verify_middle_queue_save, test_length,fixed_apply_badarg,
- external_fun_apply3, node_1, doctests].
+ external_fun_apply3, node_1, doctests, is_integer_3_test].
init_per_testcase(guard_bifs_in_erl_bif_types, Config) when is_list(Config) ->
skip_missing_erl_bif_types(Config);
@@ -1780,6 +1781,72 @@ node_error(E0) ->
doctests(_Config) ->
shell_docs:test(erlang, []).
+is_integer_3_test(_Config) ->
+ _ = [is_between_ten(X) || X <- lists:seq(-2, 12)],
+
+ false = is_between_ten(0),
+ true = is_between_ten(1),
+ true = is_between_ten(10),
+ false = is_between_ten(11),
+
+ false = is_between_ten(a),
+ false = is_between_ten(5.0),
+ false = is_between_ten(-7.0),
+ false = is_between_ten([1]),
+
+ _ = [begin
+ is_between_negative(X),
+ false = is_between_negative(-X)
+ end || X <- lists:seq(-100, -70)],
+
+ _ = [is_between_mixed(X) || X <- lists:seq(-10, 10)],
+
+ _ = [begin
+ is_between_bignum(X),
+ false = is_between_bignum(-X),
+ false = is_between_bignum(X - (1 bsl 64))
+ end || X <- lists:seq((1 bsl 64) - 3, (1 bsl 64) + 10)],
+
+ is_between_badarg(2, 1.5, 10.0),
+ is_between_badarg(2, 10.0, 1.5),
+ is_between_badarg(2, 1.5, 10),
+ is_between_badarg(2, 1, 10.0),
+ is_between_badarg(2, lower, upper),
+
+ ok.
+
+-define(IS_BETWEEN_TEST(Name, LB, UB),
+Name(X0) ->
+ F = id(is_integer),
+ Lower0 = LB,
+ Upper0 = UB,
+ Lower = id(Lower0),
+ Upper = id(Upper0),
+
+ X1 = id(X0),
+ Result = is_integer(X1, Lower0, Upper0),
+ Result = is_integer(X1, Lower, Upper),
+ Result = apply(erlang, F, id([X1, Lower, Upper])),
+ Result = erlang:F(X1, Lower, Upper),
+
+ false = is_integer(id(X1), Upper, Lower),
+
+ X = id(X1),
+ Result = is_integer(X) andalso Lower =< X andalso X =< Upper,
+ Result).
+
+?IS_BETWEEN_TEST(is_between_ten, 1, 10).
+?IS_BETWEEN_TEST(is_between_negative, -89, -77).
+?IS_BETWEEN_TEST(is_between_mixed, -7, 7).
+?IS_BETWEEN_TEST(is_between_bignum, 1 bsl 64, (1 bsl 64) + 7).
+
+is_between_badarg(X, A, B) ->
+ F = id(is_integer),
+
+ ?assertError(badarg, is_integer(id(X), id(A), id(B))),
+ ?assertError(badarg, erlang:F(X, A, B)),
+ ?assertError(badarg, apply(erlang, F, id([X, A, B]))).
+
%% helpers
wait_until(Fun) ->
diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl
index 6f88b0105b..db45d942cc 100644
--- a/erts/emulator/test/exception_SUITE.erl
+++ b/erts/emulator/test/exception_SUITE.erl
@@ -940,6 +940,7 @@ error_info(_Config) ->
{is_builtin, [1, 2, a]},
{is_function, [abc, bad_arity]},
{is_function, [abc, -1]},
+ {is_integer, [5, a, b]},
{is_map_key, [key, not_map]},
{is_process_alive, [abc]},
{is_record, [not_tuple,42]},
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index 8bab7acd94daf388755162e3dcee6dda010d0a27..f229bb4b043fd290cbdfe7335a3ed8306037417e 100644
GIT binary patch
delta 14696
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
delta 14557
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
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index a64afe58c65423743dce5e8689950d54182ef369..db659c843ca6a88c66f25d4863e3eb59097e2ba8 100644
GIT binary patch
delta 961
zcmYk5S!@kq7=~x&v{h3}X`+@?4kfYV5F{cra<qxq8oN?UEm5_UATG3x(^f;(?$D|&
zwxnK5qfQV@Vqe~%mWV{T!PSe1D-j9tk2As~-#qX4eBWgLxtQt}dvA-KJbL1kL6%kA
zrYU)@6A2@T9vFr`$iWzl!+1<UE+%6pW?>-~VK(MqF6N;Cg;;_j6r&6gl%oP0QH2_8
z#dhq*9z;=#I@IF;4&o?|<0Kkz8fS10jcCFJT*75s!woz_GhX2}-r+rjj}d&r7yQI8
zI!s_PyD@`7_Fzx;W?%MWhyyr~DQwGjOl3!=F`a`slp`5tHgh<JW0}i*&Sn7@a5-0V
z4cBo4D_F@RtYQtfavL{sGpl)!hq!~gxrh5%%X&5tj5P8*FYyX*@)jTRHt+Hd@9_ce
z^D&$GoNxG+pZJ;I`9roGC8?EMr6^S$l&-GouAnm2PXjbeVU1F@CTXgsYnt+uuLWAD
z#VXVat=2lNSBWZAsg0`AW>ss8YKCgNc4((|X`gCUr^7m;V>+ReY7o?<tGcfJs#mdA
zYL$v`3M;V+Yh#@gq8;r}>};o;UUpgZ>+s6frEX(rz56Is5-lBZ*e;27$;x%ZLjp;`
z&|14sX|ynFeBZL{Oe?d0XhWv^B=vkaJFPsBl31P>2)n%l7v1Kgd1;f<(u1CewPbzk
zX<M<U1#VKr&G=wh)<{#fsrf!F`;WJa<Gu6B&@uJbuP`xS)XO-nfWN=o^ohp5Fih~W
z@0Xfvo_Ct#bIb94Q6w&$$A(E>_6N&M_FnMJu$7m6KhO8443ka$Jy5<E&Hf?7)?SY9
zTV3Pc$}n_I`TJHE-$%TKlz#(zR(#;p8@Bn+n}5o?oSEj<)=U0@yx#k=I>UBe_WcZR
b#kBhj+k4sflYJjGO#SoC-XJz-$=Sr;X~A2?
delta 816
zcmX|<YfQ~y9LN9vbCfzEN=O@}+{Q7o^&)3xNxg6>hTKxLie$pD6g5O6m5wqgx4C^+
zu18)lm(BI-zQ&uzc!BNv0?iAr%sl6$o;|<k``!1m-=5#IJx9Cj>MlDZEo0F%%i3sN
z56N~^q#_n^@L&ScF%JunflMsK60AZt3Q&j~<YEohA`eB_fMRS$CH7(;s&D|+s6`!)
zpb<?thGv{VD^B7R&fx+sp$%7X71wbC9k_+txP$w6h&Sj&7e3-EzTrE5RNyCm(WZmJ
z4B-HdW*ieZmg6{)ZcgDeCUQE%IfM}$%3&PN7$z~9DNJP=(>agxxsa=w!#w756Sr|Y
zOSy+t+|RSDW-aSj&x1U~8lK{5Hn5RRY+*B7*~ZJPxWSve&AWWW$9%~re8#6FU+_8K
zvXk%miJ$qC-TcG93R19K3ezBkYp9|Wqfr{81dZ1eCCZ~z%~6^bD@)6@Oe?io`6|$Q
z6{$qqRH|Lttt#!;0afdeYIIn&Njjnid399B)vOabqq91%i@KyXT~>$g>493*s?FM>
zttv)4wqPrE_(t^eM%eMb_F=OV>@sh6@}AJ0t}E_R*9&*Kw`@kMUG9zc%=eaf=1we2
ziMQe>xp&9AUZq4<Iw!l!vz)VBV+UWG)!}-5Ix8|Wa(HZIqCKJ9_r>#jjPFBEXmAWm
zIxWkZY05U0`(G{F<P8N;J=iWbvD2~~?|Rg7`muLvA75{BhuN=<2Kjw}=l1cUo<7H0
zqy7Cp!0Y??3X_@Z9W6#f{XW1S^l~e@hg&0!hM5YC=k4z0w)x}!<ydBpfqob0k1gz-
af2lt*ywPa5-v@YRVU*Ln!?&)mJ?I~@R&VS8
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 8acce05852..bd76664c80 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -484,7 +484,7 @@ A list of binaries. This datatype is useful to use together with
-export([abs/1, append/2, element/2, get_module_info/2, hd/1,
is_atom/1, is_binary/1, is_bitstring/1, is_boolean/1,
- is_float/1, is_function/1, is_function/2, is_integer/1,
+ is_float/1, is_function/1, is_function/2, is_integer/1, is_integer/3,
is_list/1, is_map/1, is_number/1, is_pid/1, is_port/1, is_record/2,
is_record/3, is_reference/1, is_tuple/1, load_module/2,
load_nif/2, localtime_to_universaltime/2, make_fun/3,
@@ -7302,6 +7302,31 @@ false
is_tuple(_Term) ->
erlang:nif_error(undefined).
+%% Shadowed by erl_bif_types: erlang:is_integer/3
+-doc """
+Returns `true` if `Term`, `LB`, and `UB` all evaluate to integers, and `Term`
+is between `LB` and `UB` inclusive; otherwise, returns `false`.
+
+## Examples
+
+```erlang
+1> is_integer(15, 0, 1024).
+true
+2> is_integer(-1, 0, 1).
+false
+```
+
+Failure: `badarg` if `LB` or `UB` does not evaluate to an integer.
+""".
+-doc #{ category => terms }.
+-spec is_integer(Term, LB, UB) -> boolean() when
+ Term :: integer(),
+ LB :: integer(),
+ UB :: integer().
+is_integer(_Term, _LB, _UB) ->
+ erlang:nif_error(undefined).
+
+
-doc """
Loads `Module` described by the object code contained within `Binary`.
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index 3c2b364c5b..d830870603 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -508,7 +508,8 @@ bif_type(fsub, 2) -> {op,fsub};
bif_type(fmul, 2) -> {op,fmul};
bif_type(fdiv, 2) -> {op,fdiv};
bif_type(_, 1) -> bif1;
-bif_type(_, 2) -> bif2.
+bif_type(_, 2) -> bif2;
+bif_type(_, 3) -> bif3.
make_op({'%',_}, Dict) ->
{[],Dict};
diff --git a/lib/compiler/src/beam_call_types.erl b/lib/compiler/src/beam_call_types.erl
index 332be5ca06..0e375f4385 100644
--- a/lib/compiler/src/beam_call_types.erl
+++ b/lib/compiler/src/beam_call_types.erl
@@ -100,14 +100,15 @@ will_succeed(erlang, 'bsl'=Op, [LHS, RHS]=Args) ->
will_succeed(erlang, '++', [LHS, _RHS]) ->
succeeds_if_type(LHS, proper_list());
will_succeed(erlang, '--', [_, _] = Args) ->
- succeeds_if_types(Args, proper_list());
+ succeeds_if_types(Args, [proper_list(), proper_list()]);
will_succeed(erlang, BoolOp, [_, _] = Args) when BoolOp =:= 'and';
BoolOp =:= 'or' ->
- succeeds_if_types(Args, beam_types:make_boolean());
+ Bool = beam_types:make_boolean(),
+ succeeds_if_types(Args, [Bool, Bool]);
will_succeed(erlang, Op, [_, _] = Args) when Op =:= 'band';
Op =:= 'bor';
Op =:= 'bxor' ->
- succeeds_if_types(Args, #t_integer{});
+ succeeds_if_types(Args, [#t_integer{}, #t_integer{}]);
will_succeed(erlang, bit_size, [Arg]) ->
succeeds_if_type(Arg, #t_bs_matchable{});
will_succeed(erlang, byte_size, [Arg]) ->
@@ -144,13 +145,18 @@ will_succeed(erlang, map_size, [Arg]) ->
will_succeed(erlang, node, [Arg]) ->
succeeds_if_type(Arg, identifier);
will_succeed(erlang, 'and', [_, _]=Args) ->
- succeeds_if_types(Args, beam_types:make_boolean());
+ Bool = beam_types:make_boolean(),
+ succeeds_if_types(Args, [Bool, Bool]);
will_succeed(erlang, 'not', [Arg]) ->
succeeds_if_type(Arg, beam_types:make_boolean());
will_succeed(erlang, 'or', [_, _]=Args) ->
- succeeds_if_types(Args, beam_types:make_boolean());
+ Bool = beam_types:make_boolean(),
+ succeeds_if_types(Args, [Bool, Bool]);
will_succeed(erlang, 'xor', [_, _]=Args) ->
- succeeds_if_types(Args, beam_types:make_boolean());
+ Bool = beam_types:make_boolean(),
+ succeeds_if_types(Args, [Bool, Bool]);
+will_succeed(erlang, 'is_integer', [_, _, _]=Args) ->
+ succeeds_if_types(Args, [any, #t_integer{}, #t_integer{}]);
will_succeed(erlang, setelement, [Pos, Tuple0, _Value]=Args) ->
PosRange = #t_integer{elements={1,?MAX_TUPLE_SIZE}},
case {meet(Pos, PosRange), meet(Tuple0, #t_tuple{size=1})} of
@@ -231,14 +237,20 @@ fails_on_conflict_1([ArgType | Args], [Required | Types]) ->
fails_on_conflict_1([], []) ->
'maybe'.
-succeeds_if_types([LHS, RHS], Required) ->
- case {succeeds_if_type(LHS, Required),
- succeeds_if_type(RHS, Required)} of
- {yes, yes} -> yes;
- {no, _} -> no;
- {_, no} -> no;
- {_, _} -> 'maybe'
- end.
+succeeds_if_types(Ts, Rs) ->
+ succeeds_if_types_1(Ts, Rs, yes).
+
+succeeds_if_types_1([T | Ts], [R | Rs], Acc) ->
+ case succeeds_if_type(T, R) of
+ yes when Acc =:= yes ->
+ succeeds_if_types_1(Ts, Rs, Acc);
+ no ->
+ no;
+ _ ->
+ succeeds_if_types_1(Ts, Rs, 'maybe')
+ end;
+succeeds_if_types_1([], [], Acc) ->
+ Acc.
succeeds_if_type(ArgType, Required) ->
case meet(ArgType, Required) of
@@ -396,6 +408,8 @@ types(erlang, is_function, [Type]) ->
sub_unsafe_type_test(Type, #t_fun{});
types(erlang, is_integer, [Type]) ->
sub_unsafe_type_test(Type, #t_integer{});
+types(erlang, is_integer, [_Term, _LB, _UB]) ->
+ sub_unsafe(beam_types:make_boolean(), [any, #t_integer{}, #t_integer{}]);
types(erlang, is_list, [Type]) ->
sub_unsafe_type_test(Type, #t_list{});
types(erlang, is_map, [Type]) ->
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index e507e95db2..da37f0487e 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -820,6 +820,10 @@ resolve_inst({bif2,Args},Imports,_,_) ->
[F,Bif,A1,A2,Reg] = resolve_args(Args),
{extfunc,_Mod,BifName,_Arity} = lookup(Bif+1,Imports),
{bif,BifName,F,[A1,A2],Reg};
+resolve_inst({bif3,Args},Imports,_,_) ->
+ [F,Bif,A1,A2,A3,Reg] = resolve_args(Args),
+ {extfunc,_Mod,BifName,_Arity} = lookup(Bif+1,Imports),
+ {bif,BifName,F,[A1,A2,A3],Reg};
resolve_inst({allocate,[{u,X0},{u,X1}]},_,_,_) ->
{allocate,X0,X1};
resolve_inst({allocate_heap,[{u,X0},{u,X1},{u,X2}]},_,_,_) ->
diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl
index 5d7beee0e3..55b12e6187 100644
--- a/lib/compiler/src/beam_ssa_codegen.erl
+++ b/lib/compiler/src/beam_ssa_codegen.erl
@@ -2792,6 +2792,7 @@ is_gc_bif(node, [_]) -> false;
is_gc_bif(element, [_,_]) -> false;
is_gc_bif(get, [_]) -> false;
is_gc_bif(is_map_key, [_,_]) -> false;
+is_gc_bif(is_integer, [_,_,_]) -> false;
is_gc_bif(map_get, [_,_]) -> false;
is_gc_bif(tuple_size, [_]) -> false;
is_gc_bif(Bif, Args) ->
diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
index bb55a5deb8..dbf4ec96b2 100644
--- a/lib/compiler/src/beam_ssa_opt.erl
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -269,6 +269,7 @@ module_passes(Opts) ->
%% are repeated as required.
repeated_passes(Opts) ->
Ps = [?PASS(ssa_opt_live),
+ ?PASS(ssa_opt_is_between),
?PASS(ssa_opt_ne),
?PASS(ssa_opt_bs_create_bin),
?PASS(ssa_opt_dead),
@@ -549,7 +550,8 @@ merge_tuple_update_1([], Tuple) ->
%%%
ssa_opt_split_blocks({#opt_st{ssa=Blocks0,cnt=Count0}=St, FuncDb}) ->
- P = fun(#b_set{op={bif,element}}) -> true;
+ P = fun(#b_set{op={bif,is_integer},args=[_,_,_]}) -> true;
+ (#b_set{op={bif,element}}) -> true;
(#b_set{op=call}) -> true;
(#b_set{op=bs_init_writable}) -> true;
(#b_set{op=make_fun}) -> true;
@@ -559,6 +561,53 @@ ssa_opt_split_blocks({#opt_st{ssa=Blocks0,cnt=Count0}=St, FuncDb}) ->
{Blocks,Count} = beam_ssa:split_blocks_before(RPO, P, Blocks0, Count0),
{St#opt_st{ssa=Blocks,cnt=Count}, FuncDb}.
+%%%
+%%% BIF is_integer/3 tests whether a number is between a given range.
+%%% When the range is constant, rewrite it into 3 BIFs: is_integer/1 and two
+%%% =<'s to enable later optimization.
+%%%
+ssa_opt_is_between({#opt_st{ssa=Blocks0,cnt=Count0}=St, FuncDb}) ->
+ {Blocks1, Count1} = ssa_opt_is_between_1(Blocks0, Count0),
+ {St#opt_st{ssa=Blocks1,cnt=Count1}, FuncDb}.
+
+ssa_opt_is_between_1([{L,#b_blk{}=B}=Blk0|Ls0], Count0) ->
+ case B of
+ #b_blk{is=[#b_set{op={bif,is_integer},dst=Bool1,
+ args=[_,#b_literal{val=Min},
+ #b_literal{val=Max}]}],
+ last=#b_br{bool=Bool1}}=Blk when is_integer(Min),
+ is_integer(Max),
+ Min =< Max ->
+ {Blk1, Count1} = is_between_rewrite(Count0, L, Blk),
+ {Ls1, Count2} = ssa_opt_is_between_1(Ls0, Count1),
+ {Blk1++Ls1, Count2};
+ #b_blk{} ->
+ {Ls1, Count1} = ssa_opt_is_between_1(Ls0, Count0),
+ {[Blk0|Ls1], Count1}
+ end;
+ssa_opt_is_between_1([], Count0) ->
+ {[], Count0}.
+
+is_between_rewrite(Count0, L, Blk0) ->
+ LowerL = Count0,
+ UpperL = Count0 + 1,
+ LowerBool = #b_var{name=Count0},
+ UpperBool = #b_var{name=Count0 + 1},
+ Count = Count0 + 2,
+ #b_blk{is=[#b_set{dst=Bool1,args=[Term,LB,UB]}|_],
+ last=#b_br{fail=Fail}=Br0} = Blk0,
+ Blk1 = Blk0#b_blk{is=[#b_set{op={bif,is_integer},dst=Bool1,
+ args=[Term]}],
+ last=#b_br{bool=Bool1,succ=LowerL,fail=Fail}},
+ BlkLower = #b_blk{is=[#b_set{op={bif,'=<'},dst=LowerBool,
+ args=[LB,Term]}],
+ last=#b_br{bool=LowerBool,succ=UpperL,fail=Fail}},
+ BlkUpper = #b_blk{is=[#b_set{op={bif,'=<'},dst=UpperBool,
+ args=[Term,UB]}],
+ last=Br0#b_br{bool=UpperBool}},
+ Blocks = [{L, Blk1}, {LowerL, BlkLower}, {UpperL, BlkUpper}],
+ {Blocks, Count}.
+
%%%
%%% Coalesce phi nodes.
%%%
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
index 0ed15783be..23f5df6222 100644
--- a/lib/compiler/src/beam_ssa_pre_codegen.erl
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -2822,6 +2822,7 @@ use_zreg(wait_timeout) -> yes;
%% avoid using a z register if their result is used directly in a branch.
use_zreg(call) -> no;
use_zreg({bif,element}) -> no;
+use_zreg({bif,is_integer}) -> no;
use_zreg({bif,is_map_key}) -> no;
use_zreg({bif,is_record}) -> no;
use_zreg({bif,map_get}) -> no;
diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl
index 03f97565b6..4d40651df8 100644
--- a/lib/compiler/src/beam_ssa_type.erl
+++ b/lib/compiler/src/beam_ssa_type.erl
@@ -2721,6 +2721,15 @@ make_number({'-inf','+inf'}) ->
make_number({_,_}=R) ->
#t_number{elements=R}.
+make_integer({'-inf','+inf'}) ->
+ #t_integer{};
+make_integer({'-inf',_}=R) ->
+ #t_integer{elements=R};
+make_integer({Min,Max}=R) when is_integer(Min), Min =< Max ->
+ #t_integer{elements=R};
+make_integer(_) ->
+ #t_integer{}.
+
inv_relop({bif,Op}) -> inv_relop_1(Op);
inv_relop(_) -> none.
@@ -2736,6 +2745,14 @@ infer_get_range(#t_integer{elements=R}) -> R;
infer_get_range(#t_number{elements=R}) -> R;
infer_get_range(_) -> unknown.
+infer_integer_get_range(Arg, Ts) ->
+ case concrete_type(Arg, Ts) of
+ #t_integer{elements={_,_}=R} ->
+ R;
+ _ ->
+ {'-inf','+inf'}
+ end.
+
infer_br_value(_V, _Bool, none) ->
none;
infer_br_value(V, Bool, NewTs) ->
@@ -2814,6 +2831,18 @@ infer_type({bif,is_function}, [#b_var{}=Arg, Arity], _Ts, _Ds) ->
infer_type({bif,is_integer}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, #t_integer{}},
{[T], [T]};
+infer_type({bif,is_integer}, [#b_var{}=Arg,
+ #b_literal{val=Min},
+ #b_literal{val=Max}], _Ts, _Ds) when Min =< Max ->
+ T = {Arg, beam_types:make_integer(Min, Max)},
+ {[T], [T]};
+infer_type({bif,is_integer}, [#b_var{}=Arg,Min0,Max0], Ts, _Ds) ->
+ {Min,_} = infer_integer_get_range(Min0, Ts),
+ {_,Max} = infer_integer_get_range(Max0, Ts),
+ T = {Arg, make_integer({Min,Max})},
+ %% Conservatively never attempt to subtract the type; subtraction
+ %% will most likely be incorrect or useless.
+ {[T], []};
infer_type({bif,is_list}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, #t_list{}},
{[T], [T]};
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index c44091a408..0c5aec9b07 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -2288,6 +2288,22 @@ infer_types_1(#value{op={bif,is_function},args=[Src]}, Val, Op, Vst) ->
infer_type_test_bif(#t_fun{}, Src, Val, Op, Vst);
infer_types_1(#value{op={bif,is_integer},args=[Src]}, Val, Op, Vst) ->
infer_type_test_bif(#t_integer{}, Src, Val, Op, Vst);
+infer_types_1(#value{op={bif,is_integer},args=[Src,
+ {integer, Min},
+ {integer, Max}]}, Val, Op, Vst) ->
+ infer_type_test_bif(beam_types:make_integer(Min, Max), Src, Val, Op, Vst);
+infer_types_1(#value{op={bif,is_integer},args=[Src,Min0,Max0]}, Val, Op, Vst) ->
+ %% If there is at least one unknown bound, we cannot subtract
+ %% when 'false'.
+ {Min,_} = infer_integer_get_range(Min0, Vst),
+ {_,Max} = infer_integer_get_range(Max0, Vst),
+ Type = make_integer({Min, Max}),
+ case Val of
+ {atom, Bool} when Op =:= eq_exact, Bool; Op =:= ne_exact, not Bool ->
+ update_type(fun meet/2, Type, Src, Vst);
+ _ ->
+ Vst
+ end;
infer_types_1(#value{op={bif,is_list},args=[Src]}, Val, Op, Vst) ->
infer_type_test_bif(#t_list{}, Src, Val, Op, Vst);
infer_types_1(#value{op={bif,is_map},args=[Src]}, Val, Op, Vst) ->
@@ -2354,6 +2370,23 @@ invert_relop('=<') -> '>';
invert_relop('>=') -> '<';
invert_relop('>') -> '=<'.
+infer_integer_get_range(Arg, Vst) ->
+ case get_term_type(Arg, Vst) of
+ #t_integer{elements={_,_}=R} ->
+ R;
+ _ ->
+ {'-inf','+inf'}
+ end.
+
+make_integer({'-inf','+inf'}) ->
+ #t_integer{};
+make_integer({'-inf',_}=R) ->
+ #t_integer{elements=R};
+make_integer({Min,Max}=R) when is_integer(Min), Min =< Max ->
+ #t_integer{elements=R};
+make_integer(_) ->
+ #t_integer{}.
+
%%%
%%% Keeping track of types.
%%%
diff --git a/lib/compiler/src/erl_bifs.erl b/lib/compiler/src/erl_bifs.erl
index ee81d218a4..e3d137909d 100644
--- a/lib/compiler/src/erl_bifs.erl
+++ b/lib/compiler/src/erl_bifs.erl
@@ -114,6 +114,7 @@ is_pure(erlang, is_float, 1) -> true;
is_pure(erlang, is_function, 1) -> true;
is_pure(erlang, is_function, 2) -> true;
is_pure(erlang, is_integer, 1) -> true;
+is_pure(erlang, is_integer, 3) -> true;
is_pure(erlang, is_list, 1) -> true;
is_pure(erlang, is_map, 1) -> true;
is_pure(erlang, is_map_key, 2) -> true;
diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab
index 588ec5210e..d54edd0fef 100755
--- a/lib/compiler/src/genop.tab
+++ b/lib/compiler/src/genop.tab
@@ -710,3 +710,11 @@ BEAM_FORMAT_NUMBER=0
## * {atom,entry} - Function entry.
## * {atom,line} - Any other line in the function.
184: debug_line/4
+
+# OTP 29
+
+## @spec bif3 Lbl Bif Arg1 Arg2 Arg3 Reg
+## @doc Call the bif Bif with the arguments Arg1, Arg2, and Arg3,
+## and store the result in Reg.
+## On failure jump to Lbl.
+185: bif3/6
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 1d6ee3232b..3656672e36 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -26,6 +26,7 @@
-compile([nowarn_obsolete_guard]).
-include_lib("syntax_tools/include/merl.hrl").
+-include_lib("stdlib/include/assert.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -44,7 +45,7 @@
bad_constants/1,bad_guards/1,
guard_in_catch/1,beam_bool_SUITE/1,
repeated_type_tests/1,use_after_branch/1,
- body_in_guard/1]).
+ body_in_guard/1,is_integer_3_guard/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -63,12 +64,13 @@ groups() ->
basic_andalso_orelse,traverse_dcd,
check_qlc_hrl,andalso_semi,t_tuple_size,binary_part,
bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE,
- repeated_type_tests,use_after_branch,body_in_guard]},
+ repeated_type_tests,use_after_branch,body_in_guard,
+ is_integer_3_guard]},
{slow,[],[literal_type_tests,generated_combinations]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
- Config.
+ id(Config).
end_per_suite(_Config) ->
ok.
@@ -233,6 +235,26 @@ basic_not(Config) when is_list(Config) ->
check(fun() -> if not (False =:= true) -> ok; true -> error end end, ok),
check(fun() -> if not (Glurf =:= true) -> ok; true -> error end end, ok),
+ check(fun() -> if
+ not is_integer(7, Glurf, Glurf) -> ok;
+ true -> error
+ end
+ end, error),
+
+ check(fun() -> if
+ not is_integer(10, C, D) -> ok;
+ true -> error
+ end
+ end, ok),
+
+ check(fun() ->
+ X = id(20),
+ if
+ not is_integer(X, 1, 10) -> ok;
+ true -> error
+ end
+ end, ok),
+
ok.
complex_not(Config) when is_list(Config) ->
@@ -783,6 +805,24 @@ more_or_guards(Config) when is_list(Config) ->
element(19, ATuple) -> ok;
true -> error end
end, error),
+
+ check(fun() ->
+ Lower = id(a),
+ Upper = id(b),
+ if
+ true or is_integer(1, Lower, Upper) -> ok;
+ true -> error
+ end
+ end, error),
+
+ check(fun() ->
+ Lower = id(1),
+ Upper = id(10),
+ if
+ false or is_integer(1, Lower, Upper) -> ok;
+ true -> error
+ end
+ end, ok),
ok.
complex_or_guards(Config) when is_list(Config) ->
@@ -1561,7 +1601,8 @@ is_digit(N) ->
Bool = is_digit_8(N),
Bool = is_digit_9(42, N),
Bool = is_digit_10(N, 0),
- Bool = is_digit_11(N, 0).
+ Bool = is_digit_11(N, 0),
+ Bool = is_digit_12(N).
is_digit_1(X) when 16#0660 =< X, X =< 16#0669 -> true;
is_digit_1(X) when 16#0030 =< X, X =< 16#0039 -> true;
@@ -1622,6 +1663,12 @@ is_digit_11(X, _) when 16#0030 =< X, X =< 16#0039 -> true;
is_digit_11(X, _) when 16#06F0 =< X, X =< 16#06F9 -> true;
is_digit_11(_, _) -> false.
+is_digit_12(X) when is_integer(X, 16#0030, 16#0039);
+ is_integer(X, 16#06F0, 16#06F9);
+ is_integer(X, 16#0660, 16#0669) -> true;
+is_digit_12(16#0670) -> false;
+is_digit_12(_) -> false.
+
rel_op_combinations_2(0, _) ->
ok;
rel_op_combinations_2(N, Range) ->
@@ -1642,7 +1689,8 @@ broken_range(N) ->
Bool = broken_range_10(N),
Bool = broken_range_11(N),
Bool = broken_range_12(N),
- Bool = broken_range_13(N).
+ Bool = broken_range_13(N),
+ Bool = broken_range_14(N).
broken_range_1(X) when X >= 10, X =< 20, X =/= 13 -> true;
broken_range_1(X) when X >= 3, X =< 5 -> true;
@@ -1707,6 +1755,10 @@ broken_range_13(X) when X >= 10, X =< 20, 13 =/= X -> true;
broken_range_13(X) when X >= 3, X =< 5 -> true;
broken_range_13(_) -> false.
+broken_range_14(X) when is_integer(X, 10, 20), 13 =/= X -> true;
+broken_range_14(X) when is_integer(X, 3, 5) -> true;
+broken_range_14(_) -> false.
+
rel_op_combinations_3(0, _) ->
ok;
rel_op_combinations_3(N, Red) ->
@@ -3363,6 +3415,99 @@ body_in_guard(_Config) ->
demonitor(Mon)
end.
+is_integer_3_guard(_Config) ->
+ Lower = id(1),
+ Upper = id(10),
+ _ = [begin
+ Expected = Lower =< X andalso X =< Upper,
+ Expected = is_integer_3_guard_1(X, Lower, Upper),
+ false = is_integer_3_guard_1(float(X), Lower, Upper)
+ end || X <- lists:seq(-7, 17)],
+
+ ?assertError(badarg, is_integer_3_guard_1(2, 1.5, 10)),
+ ?assertError(badarg, is_integer_3_guard_1(2, true, 10)),
+ ?assertError(badarg, is_integer_3_guard_1(2, 10, b)),
+
+ false = is_integer_3_guard_2(id(0)),
+ true = is_integer_3_guard_2(id(1)),
+ true = is_integer_3_guard_2(id(32)),
+ true = is_integer_3_guard_2(id(1024)),
+ false = is_integer_3_guard_2(id(1025)),
+
+ true = is_integer_3_guard_3(id(0)),
+ false = is_integer_3_guard_3(id(1)),
+ false = is_integer_3_guard_3(id(32)),
+ false = is_integer_3_guard_3(id(1024)),
+ true = is_integer_3_guard_3(id(1025)),
+
+ 1 = is_integer_3_guard_4(id(1), id(0), id(5)),
+ false = is_integer_3_guard_4(id(1), id(-1), id(0)),
+
+ 2 = is_integer_3_guard_5(id(2), id(0), id(9)),
+ false = is_integer_3_guard_5(id(1024), id(0), id(9)),
+
+ false = is_integer_3_guard_6(id(0), id(1), id(-1)),
+ true = is_integer_3_guard_6(id(0), id(0), id(1)),
+
+ false = is_integer_3_guard_7(id(0), id(1), id(9)),
+ true = is_integer_3_guard_7(id(1), id(1), id(9)),
+
+ true = is_integer_3_guard_8(id(17), id(12), id(20)),
+ false = is_integer_3_guard_8(id(0), id(12), id(20)),
+ true = is_integer_3_guard_8(id(5), id(1), id(20)),
+
+ ok.
+
+is_integer_3_guard_1(X, LB, UB) when is_integer(X, LB, UB) ->
+ true = is_integer(X, LB, UB);
+is_integer_3_guard_1(X, LB, UB) ->
+ is_integer(X, LB, UB).
+
+is_integer_3_guard_2(X) when is_integer(X, 1, 1024) ->
+ true = is_integer(X, 1, 1024);
+is_integer_3_guard_2(X) ->
+ is_integer(X, 1, 1024).
+
+is_integer_3_guard_3(X) when not is_integer(X, 1, 1024) ->
+ true = not is_integer(X, 1, 1024);
+is_integer_3_guard_3(X) ->
+ not is_integer(X, 1, 1024).
+
+is_integer_3_guard_4(X, LB, UB) when 0 =< LB, UB < 10,
+ is_integer(X, LB, UB) ->
+ is_integer_3_guard_4_id(X);
+is_integer_3_guard_4(X, LB, UB) ->
+ is_integer(X, LB, UB).
+
+is_integer_3_guard_4_id(I) -> I.
+
+is_integer_3_guard_5(X, LB, UB) when 0 =< LB, is_integer(UB),
+ UB < 10, is_integer(X, LB, UB) ->
+ is_integer_3_guard_5_id(X);
+is_integer_3_guard_5(X, LB, UB) ->
+ is_integer(X, LB, UB).
+
+is_integer_3_guard_5_id(I) -> I.
+
+%% Test incorrect order of bounds.
+is_integer_3_guard_6(X, LB, UB) when 10 =< LB, UB < 0, is_integer(X, LB, UB) ->
+ is_integer(X, LB, UB);
+is_integer_3_guard_6(X, LB, UB) ->
+ is_integer(X, LB, UB).
+
+is_integer_3_guard_7(X, LB, UB) when is_number(UB), UB < 10, is_integer(X, LB, UB) ->
+ is_integer(X, LB, UB);
+is_integer_3_guard_7(X, LB, UB) ->
+ is_integer(X, LB, UB).
+
+is_integer_3_guard_8(X, LB, UB) when is_number(LB), LB > 10, is_integer(X, LB, UB) ->
+ is_integer_3_guard_8_id(X),
+ is_integer(X, LB, UB);
+is_integer_3_guard_8(X, LB, UB) ->
+ is_integer(X, LB, UB).
+
+is_integer_3_guard_8_id(I) -> I.
+
%% Call this function to turn off constant propagation.
id(I) -> I.
diff --git a/lib/dialyzer/src/erl_bif_types.erl b/lib/dialyzer/src/erl_bif_types.erl
index 311b4cfc9e..b54116ed4d 100644
--- a/lib/dialyzer/src/erl_bif_types.erl
+++ b/lib/dialyzer/src/erl_bif_types.erl
@@ -2243,6 +2243,8 @@ arg_types(erlang, is_function, 2) ->
[t_any(), t_arity()];
arg_types(erlang, is_integer, 1) ->
[t_any()];
+arg_types(erlang, is_integer, 3) ->
+ [t_any(),t_integer(), t_integer()];
arg_types(erlang, is_list, 1) ->
[t_any()];
arg_types(erlang, is_map, 1) ->
diff --git a/lib/kernel/src/erl_erts_errors.erl b/lib/kernel/src/erl_erts_errors.erl
index c4b8529874..c4e8283b7c 100644
--- a/lib/kernel/src/erl_erts_errors.erl
+++ b/lib/kernel/src/erl_erts_errors.erl
@@ -477,6 +477,8 @@ format_erlang_error(is_function, [_,Arity], _) ->
is_integer(Arity) -> range;
true -> not_integer
end];
+format_erlang_error(is_integer, [_,_,_], _) ->
+ [not_integer];
format_erlang_error(is_map_key, [_,_], _) ->
[[],not_map];
format_erlang_error(is_process_alive, [Arg], _) ->
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index 34d3b5c5c0..6ac0ccbee3 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -86,6 +86,7 @@ guard_bif(element, 2) -> true;
guard_bif(float, 1) -> true;
guard_bif(floor, 1) -> true;
guard_bif(hd, 1) -> true;
+guard_bif(is_integer, 3) -> true;
guard_bif(is_map_key, 2) -> true;
guard_bif(length, 1) -> true;
guard_bif(map_size, 1) -> true;
@@ -351,6 +352,7 @@ bif(is_float, 1) -> true;
bif(is_function, 1) -> true;
bif(is_function, 2) -> true;
bif(is_integer, 1) -> true;
+bif(is_integer, 3) -> true;
bif(is_list, 1) -> true;
bif(is_map, 1) -> true;
bif(is_map_key, 2) -> true;
--
2.51.0