Skip to content

Commit 9a8c1f6

Browse files
committed
BIF: add missing is_function/2
is_function/2 BIF also checks arity. Signed-off-by: Davide Bettio <davide@uninstall.it>
1 parent 6928350 commit 9a8c1f6

File tree

4 files changed

+47
-0
lines changed

4 files changed

+47
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ with nodejs and emscripten)
1414
- Added memory info in `out_of_memory` crash logs to help developers fix memory issues.
1515
- Added documentation and function specs for uart driver
1616
- Added `uart:read/2` with a timeout parameter.
17+
- Missing `erlang:is_function/2` BIF
1718

1819
### Fixed
1920

src/libAtomVM/bif.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,50 @@ term bif_erlang_is_function_1(Context *ctx, uint32_t fail_label, term arg1)
148148
return term_is_function(arg1) ? TRUE_ATOM : FALSE_ATOM;
149149
}
150150

151+
term bif_erlang_is_function_2(Context *ctx, uint32_t fail_label, term arg1, term arg2)
152+
{
153+
VALIDATE_VALUE_BIF(fail_label, arg2, term_is_any_integer);
154+
155+
if (!term_is_integer(arg2)) {
156+
// function takes any positive integer, including big integers
157+
// but internally we use only small integers
158+
return FALSE_ATOM;
159+
}
160+
avm_int_t arity = term_to_int(arg2);
161+
if (arity < 0) {
162+
RAISE_ERROR_BIF(fail_label, BADARG_ATOM);
163+
}
164+
165+
if (!term_is_function(arg1)) {
166+
return FALSE_ATOM;
167+
}
168+
169+
// following part has been taken from opcodesswitch.h
170+
// TODO: factor this out
171+
const term *boxed_value = term_to_const_term_ptr(arg1);
172+
173+
Module *fun_module = (Module *) boxed_value[1];
174+
term index_or_module = boxed_value[2];
175+
176+
uint32_t fun_arity;
177+
178+
if (term_is_atom(index_or_module)) {
179+
fun_arity = term_to_int(boxed_value[3]);
180+
181+
} else {
182+
uint32_t fun_index = term_to_int32(index_or_module);
183+
184+
uint32_t fun_label;
185+
uint32_t fun_arity_and_freeze;
186+
uint32_t fun_n_freeze;
187+
188+
module_get_fun(fun_module, fun_index, &fun_label, &fun_arity_and_freeze, &fun_n_freeze);
189+
fun_arity = fun_arity_and_freeze - fun_n_freeze;
190+
}
191+
192+
return (arity == ((avm_int_t) fun_arity)) ? TRUE_ATOM : FALSE_ATOM;
193+
}
194+
151195
term bif_erlang_is_integer_1(Context *ctx, uint32_t fail_label, term arg1)
152196
{
153197
UNUSED(ctx);

src/libAtomVM/bif.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ term bif_erlang_is_binary_1(Context *ctx, uint32_t fail_label, term arg1);
5151
term bif_erlang_is_boolean_1(Context *ctx, uint32_t fail_label, term arg1);
5252
term bif_erlang_is_float_1(Context *ctx, uint32_t fail_label, term arg1);
5353
term bif_erlang_is_function_1(Context *ctx, uint32_t fail_label, term arg1);
54+
term bif_erlang_is_function_2(Context *ctx, uint32_t fail_label, term arg1, term arg2);
5455
term bif_erlang_is_integer_1(Context *ctx, uint32_t fail_label, term arg1);
5556
term bif_erlang_is_list_1(Context *ctx, uint32_t fail_label, term arg1);
5657
term bif_erlang_is_number_1(Context *ctx, uint32_t fail_label, term arg1);

src/libAtomVM/bifs.gperf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ erlang:is_binary/1, {.bif.base.type = BIFFunctionType, .bif.bif1_ptr = bif_erlan
4646
erlang:is_boolean/1, {.bif.base.type = BIFFunctionType, .bif.bif1_ptr = bif_erlang_is_boolean_1}
4747
erlang:is_float/1, {.bif.base.type = BIFFunctionType, .bif.bif1_ptr = bif_erlang_is_float_1}
4848
erlang:is_function/1, {.bif.base.type = BIFFunctionType, .bif.bif1_ptr = bif_erlang_is_function_1}
49+
erlang:is_function/2, {.bif.base.type = BIFFunctionType, .bif.bif2_ptr = bif_erlang_is_function_2}
4950
erlang:is_integer/1, {.bif.base.type = BIFFunctionType, .bif.bif1_ptr = bif_erlang_is_integer_1}
5051
erlang:is_list/1, {.bif.base.type = BIFFunctionType, .bif.bif1_ptr = bif_erlang_is_list_1}
5152
erlang:is_number/1, {.bif.base.type = BIFFunctionType, .bif.bif1_ptr = bif_erlang_is_number_1}

0 commit comments

Comments
 (0)