Skip to content

Commit 75dfd2d

Browse files
committed
CR
Signed-off-by: Mateusz Front <mateusz.front@swmansion.com>
1 parent 395f800 commit 75dfd2d

3 files changed

Lines changed: 138 additions & 102 deletions

File tree

src/libAtomVM/term.c

Lines changed: 87 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,92 @@ TermCompareResult term_compare(term t, term other, TermCompareOpts opts, GlobalC
819819
}
820820
}
821821
}
822+
case TERM_TYPE_INDEX_FUNCTION: {
823+
if (term_is_external_fun(t) && term_is_external_fun(other)) {
824+
const term *boxed_value = term_to_const_term_ptr(t);
825+
term module_atom = boxed_value[1];
826+
term function_atom = boxed_value[2];
827+
term arity = boxed_value[3];
828+
829+
const term *other_boxed_value = term_to_const_term_ptr(other);
830+
term other_module_atom = other_boxed_value[1];
831+
term other_function_atom = other_boxed_value[2];
832+
term other_arity = other_boxed_value[3];
833+
834+
if (temp_stack_push(&temp_stack, arity) != TempStackOk
835+
|| temp_stack_push(&temp_stack, other_arity) != TempStackOk
836+
|| temp_stack_push(&temp_stack, function_atom) != TempStackOk
837+
|| temp_stack_push(&temp_stack, other_function_atom) != TempStackOk) {
838+
return TermCompareMemoryAllocFail;
839+
}
840+
841+
t = module_atom;
842+
other = other_module_atom;
843+
} else if (!term_is_external_fun(t) && !term_is_external_fun(other)) {
844+
const term *boxed_value = term_to_const_term_ptr(t);
845+
Module *fun_module = (Module *) boxed_value[1];
846+
term module_name_atom = module_get_name(fun_module);
847+
atom_index_t module_atom_index = term_to_atom_index(module_name_atom);
848+
849+
const term *other_boxed_value = term_to_const_term_ptr(other);
850+
Module *other_fun_module = (Module *) other_boxed_value[1];
851+
term other_module_name_atom = module_get_name(other_fun_module);
852+
atom_index_t other_module_atom_index = term_to_atom_index(other_module_name_atom);
853+
854+
int module_cmp_result = atom_table_cmp_using_atom_index(
855+
global->atom_table, module_atom_index, other_module_atom_index);
856+
857+
if (module_cmp_result != 0) {
858+
result = (module_cmp_result > 0) ? TermGreaterThan : TermLessThan;
859+
goto unequal;
860+
}
861+
862+
uint32_t fun_index = term_to_int32(boxed_value[2]);
863+
uint32_t other_fun_index = term_to_int32(other_boxed_value[2]);
864+
865+
if (fun_index != other_fun_index) {
866+
result = (fun_index > other_fun_index) ? TermGreaterThan : TermLessThan;
867+
goto unequal;
868+
}
869+
870+
uint32_t arity, old_index, old_uniq;
871+
module_get_fun_arity_old_index_uniq(fun_module, fun_index, &arity, &old_index, &old_uniq);
872+
uint32_t other_arity, other_old_index, other_old_uniq;
873+
module_get_fun_arity_old_index_uniq(other_fun_module, other_fun_index, &other_arity, &other_old_index, &other_old_uniq);
874+
875+
if (old_uniq != other_old_uniq) {
876+
result = (old_uniq > other_old_uniq) ? TermGreaterThan : TermLessThan;
877+
goto unequal;
878+
}
879+
880+
uint32_t num_freeze = module_get_fun_freeze(fun_module, fun_index);
881+
uint32_t other_num_freeze = module_get_fun_freeze(other_fun_module, other_fun_index);
882+
883+
if (num_freeze != other_num_freeze) {
884+
result = (num_freeze > other_num_freeze) ? TermGreaterThan : TermLessThan;
885+
goto unequal;
886+
} else if (num_freeze == 0) {
887+
CMP_POP_AND_CONTINUE();
888+
} else {
889+
uint32_t freeze_base = 3;
890+
for (uint32_t i = num_freeze; i >= 1; i--) {
891+
if (temp_stack_push(&temp_stack, boxed_value[i + freeze_base]) != TempStackOk
892+
|| temp_stack_push(&temp_stack, other_boxed_value[i + freeze_base]) != TempStackOk) {
893+
return TermCompareMemoryAllocFail;
894+
}
895+
}
896+
897+
t = boxed_value[freeze_base];
898+
other = other_boxed_value[freeze_base];
899+
}
900+
901+
} else {
902+
result = term_is_external_fun(t) ? TermGreaterThan : TermLessThan;
903+
goto unequal;
904+
}
905+
906+
break;
907+
}
822908
case TERM_TYPE_INDEX_NON_EMPTY_LIST: {
823909
term t_tail = term_get_list_tail(t);
824910
term other_tail = term_get_list_tail(other);
@@ -1024,93 +1110,7 @@ TermCompareResult term_compare(term t, term other, TermCompareOpts opts, GlobalC
10241110
break;
10251111
}
10261112
}
1027-
case TERM_TYPE_INDEX_FUNCTION:
1028-
if (term_is_external_fun(t) && term_is_external_fun(other)) {
1029-
const term *boxed_value = term_to_const_term_ptr(t);
1030-
term module_atom = boxed_value[1];
1031-
term function_atom = boxed_value[2];
1032-
term arity = boxed_value[3];
1033-
1034-
const term *other_boxed_value = term_to_const_term_ptr(other);
1035-
term other_module_atom = other_boxed_value[1];
1036-
term other_function_atom = other_boxed_value[2];
1037-
term other_arity = other_boxed_value[3];
1038-
1039-
if (temp_stack_push(&temp_stack, arity) != TempStackOk
1040-
|| temp_stack_push(&temp_stack, other_arity) != TempStackOk
1041-
|| temp_stack_push(&temp_stack, function_atom) != TempStackOk
1042-
|| temp_stack_push(&temp_stack, other_function_atom) != TempStackOk) {
1043-
return TermCompareMemoryAllocFail;
1044-
}
1045-
1046-
t = module_atom;
1047-
other = other_module_atom;
1048-
} else if (!term_is_external_fun(t) && !term_is_external_fun(other)) {
1049-
const term *boxed_value = term_to_const_term_ptr(t);
1050-
Module *fun_module = (Module *) boxed_value[1];
1051-
term module_name_atom = module_get_name(fun_module);
1052-
atom_index_t module_atom_index = term_to_atom_index(module_name_atom);
1053-
1054-
const term *other_boxed_value = term_to_const_term_ptr(other);
1055-
Module *other_fun_module = (Module *) other_boxed_value[1];
1056-
term other_module_name_atom = module_get_name(other_fun_module);
1057-
atom_index_t other_module_atom_index = term_to_atom_index(other_module_name_atom);
1058-
1059-
int module_cmp_result = atom_table_cmp_using_atom_index(
1060-
global->atom_table, module_atom_index, other_module_atom_index);
1061-
1062-
if (module_cmp_result != 0) {
1063-
result = (module_cmp_result > 0) ? TermGreaterThan : TermLessThan;
1064-
goto unequal;
1065-
}
1066-
1067-
uint32_t fun_index = term_to_int32(boxed_value[2]);
1068-
uint32_t other_fun_index = term_to_int32(other_boxed_value[2]);
1069-
1070-
if (fun_index != other_fun_index) {
1071-
result = (fun_index > other_fun_index) ? TermGreaterThan : TermLessThan;
1072-
goto unequal;
1073-
}
1074-
1075-
uint32_t arity, old_index, old_uniq;
1076-
module_get_fun_arity_old_index_uniq(fun_module, fun_index, &arity, &old_index, &old_uniq);
1077-
uint32_t other_arity, other_old_index, other_old_uniq;
1078-
module_get_fun_arity_old_index_uniq(other_fun_module, other_fun_index, &other_arity, &other_old_index, &other_old_uniq);
1079-
1080-
if (old_uniq != other_old_uniq) {
1081-
result = (old_uniq > other_old_uniq) ? TermGreaterThan : TermLessThan;
1082-
goto unequal;
1083-
}
1084-
1085-
uint32_t num_freeze = module_get_fun_freeze(fun_module, fun_index);
1086-
uint32_t other_num_freeze = module_get_fun_freeze(other_fun_module, other_fun_index);
1087-
1088-
if (num_freeze != other_num_freeze) {
1089-
result = (num_freeze > other_num_freeze) ? TermGreaterThan : TermLessThan;
1090-
goto unequal;
1091-
} else if (num_freeze == 0) {
1092-
CMP_POP_AND_CONTINUE();
1093-
} else {
1094-
uint32_t freeze_base = 3;
1095-
for (uint32_t i = num_freeze; i >= 1; i--) {
1096-
if (temp_stack_push(&temp_stack, boxed_value[i + freeze_base]) != TempStackOk
1097-
|| temp_stack_push(&temp_stack, other_boxed_value[i + freeze_base]) != TempStackOk) {
1098-
return TermCompareMemoryAllocFail;
1099-
}
1100-
}
1101-
1102-
t = boxed_value[freeze_base];
1103-
other = other_boxed_value[freeze_base];
1104-
}
1105-
1106-
} else {
1107-
result = term_is_external_fun(t) ? TermGreaterThan : TermLessThan;
1108-
goto unequal;
1109-
}
1110-
1111-
break;
1112-
case TERM_TYPE_INDEX_NIL: // This would mean we compare two equal terms, we check for that earlier
1113-
case TERM_TYPE_INDEX_INVALID:
1113+
default:
11141114
UNREACHABLE();
11151115
}
11161116
} else if ((((type_t == TERM_TYPE_INDEX_FLOAT && type_other == TERM_TYPE_INDEX_INTEGER)

tests/erlang_tests/test_function_ordering.erl

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,51 @@
2020

2121
-module(test_function_ordering).
2222

23-
-export([start/0, sort/1, insert/2, check/2]).
23+
-export([start/0, id/1]).
2424

2525
start() ->
26+
Self = self(),
27+
Self2 = ?MODULE:id(self()),
28+
Five = ?MODULE:id(5),
2629
F1 = fun(X, Y) -> X + Y end,
27-
F2 = fun(X, Y) -> X - Y end,
28-
Sorted = sort([fun erlang:exit/1, F2, fun application:ensure_started/1, F1, fun erlang:apply/3]),
29-
check(Sorted, [F1, F2, fun application:ensure_started/1, fun erlang:apply/3, fun erlang:exit/1]) +
30-
bool_to_n(Sorted < [fun erlang:whereis/1]) * 2 +
31-
bool_to_n(Sorted > {fun erlang:whereis/1}) * 4.
30+
F2 = fun(X, Y) -> X + Y end,
31+
F3 = fun() -> Self ! hello end,
32+
F4 = fun() -> Self ! Self2 end,
33+
F5 = fun() -> Self ! Five end,
34+
F6 = fun(X) -> Self ! {X, Self} end,
35+
F7 = fun(X, Y) -> Self ! {X, Y, Self} end,
36+
37+
Funs = [
38+
F4,
39+
F2,
40+
fun erlang:exit/1,
41+
F3,
42+
F6,
43+
fun application:ensure_started/1,
44+
F5,
45+
F1,
46+
fun erlang:apply/3,
47+
F7
48+
],
49+
false = has_duplicates(Funs),
50+
true = ?MODULE:id(Funs) == ?MODULE:id(Funs),
51+
true = ?MODULE:id(Funs) =:= ?MODULE:id(Funs),
52+
Sorted = sort(Funs),
53+
Sorted = [
54+
F1,
55+
F2,
56+
F3,
57+
F4,
58+
F5,
59+
F6,
60+
F7,
61+
fun application:ensure_started/1,
62+
fun erlang:apply/3,
63+
fun erlang:exit/1
64+
],
65+
true = Sorted < [fun erlang:whereis/1],
66+
true = Sorted > {fun erlang:whereis/1},
67+
0.
3268

3369
sort(L) ->
3470
sort(L, []).
@@ -49,12 +85,12 @@ insert([H | T], HL, I) when I < H ->
4985
insert([H | T], HL, I) ->
5086
insert(T, HL ++ [H], I).
5187

52-
check(T, Expected) when T == Expected ->
53-
1;
54-
check(T, Expected) when T /= Expected ->
55-
0.
88+
has_duplicates([]) ->
89+
false;
90+
has_duplicates([H | T]) ->
91+
case lists:member(H, T) of
92+
true -> true;
93+
false -> has_duplicates(T)
94+
end.
5695

57-
bool_to_n(true) ->
58-
1;
59-
bool_to_n(false) ->
60-
0.
96+
id(X) -> X.

tests/test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ struct Test tests[] = {
397397
TEST_CASE_EXPECTED(test_bigintegers_ordering, 7),
398398
TEST_CASE_EXPECTED(test_refs_ordering, 7),
399399
TEST_CASE_EXPECTED(test_atom_ordering, 7),
400-
TEST_CASE_EXPECTED(test_function_ordering, 7),
400+
TEST_CASE(test_function_ordering),
401401
TEST_CASE_EXPECTED(test_pids_ordering, 7),
402402
TEST_CASE_EXPECTED(test_list_match, 31),
403403
TEST_CASE(test_match),

0 commit comments

Comments
 (0)