1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-28 19:19:53 +00:00

Restore lexicographic comparison of tuples.

This commit is contained in:
Calvin Rose 2020-04-24 16:48:31 -05:00
parent a87015598c
commit da438a93e0
2 changed files with 34 additions and 19 deletions

View File

@ -32,12 +32,12 @@ JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal = NULL;
JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal_top = NULL; JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal_top = NULL;
JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal_base = NULL; JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal_base = NULL;
static void push_traversal_node(void *lhs, void *rhs) { static void push_traversal_node(void *lhs, void *rhs, int32_t index2) {
JanetTraversalNode node; JanetTraversalNode node;
node.self = (JanetGCObject *) lhs; node.self = (JanetGCObject *) lhs;
node.other = (JanetGCObject *) rhs; node.other = (JanetGCObject *) rhs;
node.index = 0; node.index = 0;
node.index2 = 0; node.index2 = index2;
if (janet_vm_traversal + 1 >= janet_vm_traversal_top) { if (janet_vm_traversal + 1 >= janet_vm_traversal_top) {
size_t oldsize = janet_vm_traversal - janet_vm_traversal_base; size_t oldsize = janet_vm_traversal - janet_vm_traversal_base;
size_t newsize = 2 * oldsize + 1; size_t newsize = 2 * oldsize + 1;
@ -55,7 +55,14 @@ static void push_traversal_node(void *lhs, void *rhs) {
*(++janet_vm_traversal) = node; *(++janet_vm_traversal) = node;
} }
/* Used for travsersing structs and tuples without recursion */ /*
* Used for travsersing structs and tuples without recursion
* Returns:
* 0 - next node found
* 1 - early stop - lhs < rhs
* 2 - no next node found
* 3 - early stop - lhs > rhs
*/
static int traversal_next(Janet *x, Janet *y) { static int traversal_next(Janet *x, Janet *y) {
JanetTraversalNode *t = janet_vm_traversal; JanetTraversalNode *t = janet_vm_traversal;
while (t && t > janet_vm_traversal_base) { while (t && t > janet_vm_traversal_base) {
@ -67,12 +74,15 @@ static int traversal_next(Janet *x, Janet *y) {
JanetStructHead *sother = (JanetStructHead *)other; JanetStructHead *sother = (JanetStructHead *)other;
if ((self->flags & JANET_MEM_TYPEBITS) == JANET_MEMORY_TUPLE) { if ((self->flags & JANET_MEM_TYPEBITS) == JANET_MEMORY_TUPLE) {
/* Node is a tuple at index t->index */ /* Node is a tuple at index t->index */
if (t->index < tself->length) { if (t->index < tself->length && t->index < tother->length) {
int32_t index = t->index++; int32_t index = t->index++;
*x = tself->data[index]; *x = tself->data[index];
*y = tother->data[index]; *y = tother->data[index];
janet_vm_traversal = t; janet_vm_traversal = t;
return 1; return 0;
}
if (t->index2 && tself->length != tother->length) {
return tself->length > tother->length ? 3 : 1;
} }
} else { } else {
/* Node is a struct at index t->index: if t->index2 is true, we should return the values. */ /* Node is a struct at index t->index: if t->index2 is true, we should return the values. */
@ -82,20 +92,20 @@ static int traversal_next(Janet *x, Janet *y) {
*x = sself->data[index].value; *x = sself->data[index].value;
*y = sother->data[index].value; *y = sother->data[index].value;
janet_vm_traversal = t; janet_vm_traversal = t;
return 1; return 0;
} }
for (int32_t i = t->index; i < sself->capacity; i++) { for (int32_t i = t->index; i < sself->capacity; i++) {
t->index2 = 1; t->index2 = 1;
*x = sself->data[t->index].key; *x = sself->data[t->index].key;
*y = sother->data[t->index].key; *y = sother->data[t->index].key;
janet_vm_traversal = t; janet_vm_traversal = t;
return 1; return 0;
} }
} }
t--; t--;
} }
janet_vm_traversal = t; janet_vm_traversal = t;
return 0; return 2;
} }
/* /*
@ -211,7 +221,7 @@ int janet_equals(Janet x, Janet y) {
if (t1 == t2) break; if (t1 == t2) break;
if (janet_tuple_hash(t1) != janet_tuple_hash(t2)) return 0; if (janet_tuple_hash(t1) != janet_tuple_hash(t2)) return 0;
if (janet_tuple_length(t1) != janet_tuple_length(t2)) return 0; if (janet_tuple_length(t1) != janet_tuple_length(t2)) return 0;
push_traversal_node(janet_tuple_head(t1), janet_tuple_head(t2)); push_traversal_node(janet_tuple_head(t1), janet_tuple_head(t2), 0);
break; break;
} }
break; break;
@ -221,12 +231,12 @@ int janet_equals(Janet x, Janet y) {
if (s1 == s2) break; if (s1 == s2) break;
if (janet_struct_hash(s1) != janet_struct_hash(s2)) return 0; if (janet_struct_hash(s1) != janet_struct_hash(s2)) return 0;
if (janet_struct_length(s1) != janet_struct_length(s2)) return 0; if (janet_struct_length(s1) != janet_struct_length(s2)) return 0;
push_traversal_node(janet_struct_head(s1), janet_struct_head(s2)); push_traversal_node(janet_struct_head(s1), janet_struct_head(s2), 0);
break; break;
} }
break; break;
} }
} while (traversal_next(&x, &y)); } while (!traversal_next(&x, &y));
return 1; return 1;
} }
@ -284,6 +294,7 @@ int32_t janet_hash(Janet x) {
* and should have strict ordering, excepts NaNs. */ * and should have strict ordering, excepts NaNs. */
int janet_compare(Janet x, Janet y) { int janet_compare(Janet x, Janet y) {
janet_vm_traversal = janet_vm_traversal_base; janet_vm_traversal = janet_vm_traversal_base;
int status;
do { do {
JanetType tx = janet_type(x); JanetType tx = janet_type(x);
JanetType ty = janet_type(y); JanetType ty = janet_type(y);
@ -327,11 +338,7 @@ int janet_compare(Janet x, Janet y) {
case JANET_TUPLE: { case JANET_TUPLE: {
const Janet *lhs = janet_unwrap_tuple(x); const Janet *lhs = janet_unwrap_tuple(x);
const Janet *rhs = janet_unwrap_tuple(y); const Janet *rhs = janet_unwrap_tuple(y);
int32_t llen = janet_tuple_length(lhs); push_traversal_node(janet_tuple_head(lhs), janet_tuple_head(rhs), 1);
int32_t rlen = janet_tuple_length(rhs);
if (llen < rlen) return -1;
if (llen > rlen) return 1;
push_traversal_node(janet_tuple_head(lhs), janet_tuple_head(rhs));
break; break;
} }
case JANET_STRUCT: { case JANET_STRUCT: {
@ -345,12 +352,12 @@ int janet_compare(Janet x, Janet y) {
if (llen > rlen) return 1; if (llen > rlen) return 1;
if (lhash < rhash) return -1; if (lhash < rhash) return -1;
if (lhash > rhash) return 1; if (lhash > rhash) return 1;
push_traversal_node(janet_struct_head(lhs), janet_struct_head(rhs)); push_traversal_node(janet_struct_head(lhs), janet_struct_head(rhs), 0);
break; break;
} }
} }
} while (traversal_next(&x, &y)); } while (!(status = traversal_next(&x, &y)));
return 0; return status - 2;
} }
static int32_t getter_checkint(Janet key, int32_t max) { static int32_t getter_checkint(Janet key, int32_t max) {

View File

@ -244,4 +244,12 @@ neldb\0\0\0\xD8\x05printG\x01\0\xDE\xDE\xDE'\x03\0marshal_tes/\x02
# For undefined behavior sanitizer # For undefined behavior sanitizer
0xf&1fffFFFF 0xf&1fffFFFF
# Tuple comparison
(assert (< [1 2 3] [2 2 3]) "tuple comparison 1")
(assert (< [1 2 3] [2 2]) "tuple comparison 2")
(assert (< [1 2 3] [2 2 3 4]) "tuple comparison 3")
(assert (< [1 2 3] [1 2 3 4]) "tuple comparison 4")
(assert (< [1 2 3] [1 2 3 -1]) "tuple comparison 5")
(assert (> [1 2 3] [1 2]) "tuple comparison 6")
(end-suite) (end-suite)