Remove ==, not==, and order[<,<=,>,>=].

This unifies equality and comparison checking. Before, we had
separate functions and vm opcodes for comparing general values vs.
for comparing numbers, where the numberic functions were polymorphic and
had special cases for handling NaNs. By unfiying them, abstract types
can now better integrate with other number types and behave as keys.

For now, the old functions are aliased but will eventually be removed.
This commit is contained in:
Calvin Rose 2019-12-28 15:57:36 -05:00
parent 5528bca7a9
commit 022be217a2
21 changed files with 181 additions and 166 deletions

View File

@ -2,6 +2,11 @@
All notable changes to this project will be documented in this file.
### Unreleased
- Remove `==`, `not==`, `order<`, `order>`, `order<=`, and `order>=`. Instead, use the normal
comparison and equality functions.
- Let abstract types define a hash function and comparison/equality semantics. This lets
abstract types much better represent value types. This adds more fields to abstract types, which
will generate warnings when compiled against other versions.
- Update documentation.
### 1.6.0 - 2019-12-22

View File

@ -72,14 +72,22 @@
(setdyn name* @{:ref @[init]})
nil)
# Aliases
(def == =)
(def not== ==)
(def order< <)
(def order<= <=)
(def order> >=)
(def order>= >=)
# Basic predicates
(defn nan? "Check if x is NaN" [x] (not= x x))
(defn even? "Check if x is even." [x] (== 0 (% x 2)))
(defn even? "Check if x is even." [x] (= 0 (% x 2)))
(defn odd? "Check if x is odd." [x] (not= 0 (% x 2)))
(defn zero? "Check if x is zero." [x] (== x 0))
(defn zero? "Check if x is zero." [x] (= x 0))
(defn pos? "Check if x is greater than 0." [x] (> x 0))
(defn neg? "Check if x is less than 0." [x] (< x 0))
(defn one? "Check if x is equal to 1." [x] (== x 1))
(defn one? "Check if x is equal to 1." [x] (= x 1))
(defn number? "Check if x is a number." [x] (= (type x) :number))
(defn fiber? "Check if x is a fiber." [x] (= (type x) :fiber))
(defn string? "Check if x is a string." [x] (= (type x) :string))
@ -554,12 +562,12 @@
(defn max-order
"Returns the maximum of the arguments according to a total
order over all values."
[& args] (extreme order> args))
[& args] (extreme > args))
(defn min-order
"Returns the minimum of the arguments according to a total
order over all values."
[& args] (extreme order< args))
[& args] (extreme < args))
(defn first
"Get the first element from an indexed data structure."
@ -605,11 +613,11 @@
a)
(fn sort [a &opt by]
(sort-help a 0 (- (length a) 1) (or by order<)))))
(sort-help a 0 (- (length a) 1) (or by <)))))
(defn sorted
"Returns a new sorted array without modifying the old one."
[ind by]
[ind &opt by]
(sort (array/slice ind) by))
(defn reduce
@ -1427,7 +1435,7 @@
(if-let [[path line col] sm]
(string " " path " on line " line ", column " col "\n") "")
(if (or d sm) "\n" "")
(if d (doc-format d) "no documentation found.")
(if d (doc-format d) " no documentation found.")
"\n\n"))))
# else

View File

@ -77,14 +77,12 @@ static const JanetInstructionDef janet_ops[] = {
{"divim", JOP_DIVIDE_IMMEDIATE},
{"eq", JOP_EQUALS},
{"eqim", JOP_EQUALS_IMMEDIATE},
{"eqn", JOP_NUMERIC_EQUAL},
{"err", JOP_ERROR},
{"get", JOP_GET},
{"geti", JOP_GET_INDEX},
{"gt", JOP_GREATER_THAN},
{"gten", JOP_NUMERIC_GREATER_THAN_EQUAL},
{"gte", JOP_GREATER_THAN_EQUAL},
{"gtim", JOP_GREATER_THAN_IMMEDIATE},
{"gtn", JOP_NUMERIC_GREATER_THAN},
{"in", JOP_IN},
{"jmp", JOP_JUMP},
{"jmpif", JOP_JUMP_IF},
@ -98,9 +96,8 @@ static const JanetInstructionDef janet_ops[] = {
{"ldu", JOP_LOAD_UPVALUE},
{"len", JOP_LENGTH},
{"lt", JOP_LESS_THAN},
{"lten", JOP_NUMERIC_LESS_THAN_EQUAL},
{"lte", JOP_LESS_THAN_EQUAL},
{"ltim", JOP_LESS_THAN_IMMEDIATE},
{"ltn", JOP_NUMERIC_LESS_THAN},
{"mkarr", JOP_MAKE_ARRAY},
{"mkbtp", JOP_MAKE_BRACKET_TUPLE},
{"mkbuf", JOP_MAKE_BUFFER},

View File

@ -93,11 +93,8 @@ enum JanetInstructionType janet_instructions[JOP_INSTRUCTION_COUNT] = {
JINT_S, /* JOP_MAKE_TABLE */
JINT_S, /* JOP_MAKE_TUPLE */
JINT_S, /* JOP_MAKE_BRACKET_TUPLE */
JINT_SSS, /* JOP_NUMERIC_LESS_THAN */
JINT_SSS, /* JOP_NUMERIC_LESS_THAN_EQUAL */
JINT_SSS, /* JOP_NUMERIC_GREATER_THAN */
JINT_SSS, /* JOP_NUMERIC_GREATER_THAN_EQUAL */
JINT_SSS /* JOP_NUMERIC_EQUAL */
JINT_SSS, /* JOP_GREATER_THAN_EQUAL */
JINT_SSS /* JOP_LESS_THAN_EQUAL */
};
/* Verify some bytecode */

View File

@ -235,41 +235,23 @@ static JanetSlot compreduce(
return t;
}
static JanetSlot do_order_gt(JanetFopts opts, JanetSlot *args) {
static JanetSlot do_gt(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_GREATER_THAN, 0);
}
static JanetSlot do_order_lt(JanetFopts opts, JanetSlot *args) {
static JanetSlot do_lt(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_LESS_THAN, 0);
}
static JanetSlot do_order_gte(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_LESS_THAN, 1);
}
static JanetSlot do_order_lte(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_GREATER_THAN, 1);
}
static JanetSlot do_order_eq(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_EQUALS, 0);
}
static JanetSlot do_order_neq(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_EQUALS, 1);
}
static JanetSlot do_gt(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_NUMERIC_GREATER_THAN, 0);
}
static JanetSlot do_lt(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_NUMERIC_LESS_THAN, 0);
}
static JanetSlot do_gte(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_NUMERIC_GREATER_THAN_EQUAL, 0);
return compreduce(opts, args, JOP_GREATER_THAN_EQUAL, 0);
}
static JanetSlot do_lte(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_NUMERIC_LESS_THAN_EQUAL, 0);
return compreduce(opts, args, JOP_LESS_THAN_EQUAL, 0);
}
static JanetSlot do_eq(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_NUMERIC_EQUAL, 0);
return compreduce(opts, args, JOP_EQUALS, 0);
}
static JanetSlot do_neq(JanetFopts opts, JanetSlot *args) {
return compreduce(opts, args, JOP_NUMERIC_EQUAL, 1);
return compreduce(opts, args, JOP_EQUALS, 1);
}
/* Arranged by tag */
@ -293,12 +275,6 @@ static const JanetFunOptimizer optimizers[] = {
{NULL, do_rshift},
{NULL, do_rshiftu},
{fixarity1, do_bnot},
{NULL, do_order_gt},
{NULL, do_order_lt},
{NULL, do_order_gte},
{NULL, do_order_lte},
{NULL, do_order_eq},
{NULL, do_order_neq},
{NULL, do_gt},
{NULL, do_lt},
{NULL, do_gte},

View File

@ -48,20 +48,14 @@
#define JANET_FUN_RSHIFT 17
#define JANET_FUN_RSHIFTU 18
#define JANET_FUN_BNOT 19
#define JANET_FUN_ORDER_GT 20
#define JANET_FUN_ORDER_LT 21
#define JANET_FUN_ORDER_GTE 22
#define JANET_FUN_ORDER_LTE 23
#define JANET_FUN_ORDER_EQ 24
#define JANET_FUN_ORDER_NEQ 25
#define JANET_FUN_GT 26
#define JANET_FUN_LT 27
#define JANET_FUN_GTE 28
#define JANET_FUN_LTE 29
#define JANET_FUN_EQ 30
#define JANET_FUN_NEQ 31
#define JANET_FUN_PROP 32
#define JANET_FUN_GET 33
#define JANET_FUN_GT 20
#define JANET_FUN_LT 21
#define JANET_FUN_GTE 22
#define JANET_FUN_LTE 23
#define JANET_FUN_EQ 24
#define JANET_FUN_NEQ 25
#define JANET_FUN_PROP 26
#define JANET_FUN_GET 27
/* Compiler typedefs */
typedef struct JanetCompiler JanetCompiler;

View File

@ -1090,45 +1090,23 @@ JanetTable *janet_core_env(JanetTable *replacements) {
"for positive shifts the return value will always be positive."));
/* Variadic comparators */
templatize_comparator(env, JANET_FUN_ORDER_GT, "order>", 0, JOP_GREATER_THAN,
JDOC("(order> & xs)\n\n"
"Check if xs is strictly descending according to a total order "
"over all values. Returns a boolean."));
templatize_comparator(env, JANET_FUN_ORDER_LT, "order<", 0, JOP_LESS_THAN,
JDOC("(order< & xs)\n\n"
"Check if xs is strictly increasing according to a total order "
"over all values. Returns a boolean."));
templatize_comparator(env, JANET_FUN_ORDER_GTE, "order>=", 1, JOP_LESS_THAN,
JDOC("(order>= & xs)\n\n"
"Check if xs is not increasing according to a total order "
"over all values. Returns a boolean."));
templatize_comparator(env, JANET_FUN_ORDER_LTE, "order<=", 1, JOP_GREATER_THAN,
JDOC("(order<= & xs)\n\n"
"Check if xs is not decreasing according to a total order "
"over all values. Returns a boolean."));
templatize_comparator(env, JANET_FUN_ORDER_EQ, "=", 0, JOP_EQUALS,
JDOC("(= & xs)\n\n"
"Returns true if all values in xs are the same, false otherwise."));
templatize_comparator(env, JANET_FUN_ORDER_NEQ, "not=", 1, JOP_EQUALS,
JDOC("(not= & xs)\n\n"
"Return true if any values in xs are not equal, otherwise false."));
templatize_comparator(env, JANET_FUN_GT, ">", 0, JOP_NUMERIC_GREATER_THAN,
templatize_comparator(env, JANET_FUN_GT, ">", 0, JOP_GREATER_THAN,
JDOC("(> & xs)\n\n"
"Check if xs is in numerically descending order. Returns a boolean."));
templatize_comparator(env, JANET_FUN_LT, "<", 0, JOP_NUMERIC_LESS_THAN,
templatize_comparator(env, JANET_FUN_LT, "<", 0, JOP_LESS_THAN,
JDOC("(< & xs)\n\n"
"Check if xs is in numerically ascending order. Returns a boolean."));
templatize_comparator(env, JANET_FUN_GTE, ">=", 0, JOP_NUMERIC_GREATER_THAN_EQUAL,
templatize_comparator(env, JANET_FUN_GTE, ">=", 0, JOP_GREATER_THAN_EQUAL,
JDOC("(>= & xs)\n\n"
"Check if xs is in numerically non-ascending order. Returns a boolean."));
templatize_comparator(env, JANET_FUN_LTE, "<=", 0, JOP_NUMERIC_LESS_THAN_EQUAL,
templatize_comparator(env, JANET_FUN_LTE, "<=", 0, JOP_LESS_THAN_EQUAL,
JDOC("(<= & xs)\n\n"
"Check if xs is in numerically non-descending order. Returns a boolean."));
templatize_comparator(env, JANET_FUN_EQ, "==", 0, JOP_NUMERIC_EQUAL,
JDOC("(== & xs)\n\n"
templatize_comparator(env, JANET_FUN_EQ, "=", 0, JOP_EQUALS,
JDOC("(= & xs)\n\n"
"Check if all values in xs are numerically equal (4.0 == 4). Returns a boolean."));
templatize_comparator(env, JANET_FUN_NEQ, "not==", 1, JOP_NUMERIC_EQUAL,
JDOC("(not== & xs)\n\n"
templatize_comparator(env, JANET_FUN_NEQ, "not=", 1, JOP_EQUALS,
JDOC("(not= & xs)\n\n"
"Check if any values in xs are not numerically equal (3.0 not== 4). Returns a boolean."));
/* Platform detection */

View File

@ -39,6 +39,24 @@
static int it_s64_get(void *p, Janet key, Janet *out);
static int it_u64_get(void *p, Janet key, Janet *out);
static int32_t janet_int64_hash(void *p1, size_t size) {
(void) size;
int32_t *words = p1;
return words[0] ^ words[1];
}
static int janet_int64_compare(void *p1, void *p2) {
int64_t x = *((int64_t *)p1);
int64_t y = *((int64_t *)p2);
return x == y ? 0 : x < y ? -1 : 1;
}
static int janet_uint64_compare(void *p1, void *p2) {
uint64_t x = *((uint64_t *)p1);
uint64_t y = *((uint64_t *)p2);
return x == y ? 0 : x < y ? -1 : 1;
}
static void int64_marshal(void *p, JanetMarshalContext *ctx) {
janet_marshal_abstract(ctx, p);
janet_marshal_int64(ctx, *((int64_t *)p));
@ -70,7 +88,9 @@ static const JanetAbstractType it_s64_type = {
NULL,
int64_marshal,
int64_unmarshal,
it_s64_tostring
it_s64_tostring,
janet_int64_compare,
janet_int64_hash
};
static const JanetAbstractType it_u64_type = {
@ -81,7 +101,9 @@ static const JanetAbstractType it_u64_type = {
NULL,
int64_marshal,
int64_unmarshal,
it_u64_tostring
it_u64_tostring,
janet_uint64_compare,
janet_int64_hash
};
int64_t janet_unwrap_s64(Janet x) {
@ -297,7 +319,7 @@ static JanetMethod it_s64_methods[] = {
{">", cfun_it_s64_gt},
{"<=", cfun_it_s64_le},
{">=", cfun_it_s64_ge},
{"==", cfun_it_s64_eq},
{"=", cfun_it_s64_eq},
{"!=", cfun_it_s64_ne},
{"&", cfun_it_s64_and},
{"|", cfun_it_s64_or},
@ -329,7 +351,7 @@ static JanetMethod it_u64_methods[] = {
{">", cfun_it_u64_gt},
{"<=", cfun_it_u64_le},
{">=", cfun_it_u64_ge},
{"==", cfun_it_u64_eq},
{"=", cfun_it_u64_eq},
{"!=", cfun_it_u64_ne},
{"&", cfun_it_u64_and},
{"|", cfun_it_u64_or},

View File

@ -49,6 +49,8 @@ JanetAbstractType cfun_io_filetype = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};

View File

@ -59,6 +59,8 @@ static JanetAbstractType JanetRNG_type = {
NULL,
janet_rng_marshal,
janet_rng_unmarshal,
NULL,
NULL,
NULL
};

View File

@ -740,6 +740,8 @@ static JanetAbstractType janet_parse_parsertype = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};

View File

@ -1203,6 +1203,8 @@ static const JanetAbstractType peg_type = {
NULL,
peg_marshal,
peg_unmarshal,
NULL,
NULL,
NULL
};

View File

@ -393,6 +393,8 @@ static JanetAbstractType Thread_AT = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};

View File

@ -118,6 +118,8 @@ static const JanetAbstractType ta_buffer_type = {
NULL,
ta_buffer_marshal,
ta_buffer_unmarshal,
NULL,
NULL,
NULL
};
@ -282,6 +284,8 @@ static const JanetAbstractType ta_view_type = {
ta_setter,
ta_view_marshal,
ta_view_unmarshal,
NULL,
NULL,
NULL
};

View File

@ -295,6 +295,8 @@ static const JanetAbstractType type_wrap = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};

View File

@ -28,6 +28,20 @@
* Define a number of functions that can be used internally on ANY Janet.
*/
/* Compare two abstract values */
static int janet_compare_abstract(JanetAbstract xx, JanetAbstract yy) {
if (xx == yy) return 0;
const JanetAbstractType *xt = janet_abstract_type(xx);
const JanetAbstractType *yt = janet_abstract_type(yy);
if (xt != yt) {
return xt > yt ? 1 : -1;
}
if (xt->compare == NULL) {
return xx > yy ? 1 : -1;
}
return xt->compare(xx, yy);
}
/* Check if two values are equal. This is strict equality with no conversion. */
int janet_equals(Janet x, Janet y) {
int result = 0;
@ -53,6 +67,9 @@ int janet_equals(Janet x, Janet y) {
case JANET_STRUCT:
result = janet_struct_equal(janet_unwrap_struct(x), janet_unwrap_struct(y));
break;
case JANET_ABSTRACT:
result = !janet_compare_abstract(janet_unwrap_abstract(x), janet_unwrap_abstract(y));
break;
default:
/* compare pointers */
result = (janet_unwrap_pointer(x) == janet_unwrap_pointer(y));
@ -83,6 +100,15 @@ int32_t janet_hash(Janet x) {
case JANET_STRUCT:
hash = janet_struct_hash(janet_unwrap_struct(x));
break;
case JANET_ABSTRACT: {
JanetAbstract xx = janet_unwrap_abstract(x);
const JanetAbstractType *at = janet_abstract_type(xx);
if (at->hash != NULL) {
hash = at->hash(xx, janet_abstract_size(xx));
break;
}
}
/* fallthrough */
default:
/* TODO - test performance with different hash functions */
if (sizeof(double) == sizeof(void *)) {
@ -104,7 +130,7 @@ int32_t janet_hash(Janet x) {
/* Compares x to y. If they are equal returns 0. If x is less, returns -1.
* If y is less, returns 1. All types are comparable
* and should have strict ordering. */
* and should have strict ordering, excepts NaNs. */
int janet_compare(Janet x, Janet y) {
if (janet_type(x) == janet_type(y)) {
switch (janet_type(x)) {
@ -112,20 +138,13 @@ int janet_compare(Janet x, Janet y) {
return 0;
case JANET_BOOLEAN:
return janet_unwrap_boolean(x) - janet_unwrap_boolean(y);
case JANET_NUMBER:
/* Check for NaNs to ensure total order */
if (janet_unwrap_number(x) != janet_unwrap_number(x))
return janet_unwrap_number(y) != janet_unwrap_number(y)
? 0
: -1;
if (janet_unwrap_number(y) != janet_unwrap_number(y))
return 1;
if (janet_unwrap_number(x) == janet_unwrap_number(y)) {
return 0;
} else {
return janet_unwrap_number(x) > janet_unwrap_number(y) ? 1 : -1;
}
case JANET_NUMBER: {
double xx = janet_unwrap_number(x);
double yy = janet_unwrap_number(y);
return xx == yy
? 0
: (xx < yy) ? -1 : 1;
}
case JANET_STRING:
case JANET_SYMBOL:
case JANET_KEYWORD:
@ -134,6 +153,8 @@ int janet_compare(Janet x, Janet y) {
return janet_tuple_compare(janet_unwrap_tuple(x), janet_unwrap_tuple(y));
case JANET_STRUCT:
return janet_struct_compare(janet_unwrap_struct(x), janet_unwrap_struct(y));
case JANET_ABSTRACT:
return janet_compare_abstract(janet_unwrap_abstract(x), janet_unwrap_abstract(y));
default:
if (janet_unwrap_string(x) == janet_unwrap_string(y)) {
return 0;

View File

@ -149,7 +149,6 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
stack[A] = janet_mcall(#op, 2, _argv);\
vm_pcnext();\
} else {\
vm_assert_type(op1, JANET_NUMBER);\
vm_assert_type(op2, JANET_NUMBER);\
double x1 = janet_unwrap_number(op1);\
double x2 = janet_unwrap_number(op2);\
@ -158,7 +157,6 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
}\
}
#define vm_binop(op) _vm_binop(op, janet_wrap_number)
#define vm_numcomp(op) _vm_binop(op, janet_wrap_boolean)
#define _vm_bitop(op, type1)\
{\
Janet op1 = stack[B];\
@ -172,6 +170,21 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
}
#define vm_bitop(op) _vm_bitop(op, int32_t)
#define vm_bitopu(op) _vm_bitop(op, uint32_t)
#define vm_compop(op) \
{\
Janet op1 = stack[B];\
Janet op2 = stack[C];\
if (!janet_checktype(op1, JANET_NUMBER) || !janet_checktype(op2, JANET_NUMBER)) {\
vm_commit();\
stack[A] = janet_wrap_boolean(janet_compare(op1, op2) op 0);\
vm_pcnext();\
} else {\
double x1 = janet_unwrap_number(op1);\
double x2 = janet_unwrap_number(op2);\
stack[A] = janet_wrap_boolean(x1 op x2);\
vm_pcnext();\
}\
}
/* Trace a function call */
static void vm_do_trace(JanetFunction *func) {
@ -288,11 +301,11 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
&&label_JOP_MAKE_TABLE,
&&label_JOP_MAKE_TUPLE,
&&label_JOP_MAKE_BRACKET_TUPLE,
&&label_JOP_NUMERIC_LESS_THAN,
&&label_JOP_NUMERIC_LESS_THAN_EQUAL,
&&label_JOP_NUMERIC_GREATER_THAN,
&&label_JOP_NUMERIC_GREATER_THAN_EQUAL,
&&label_JOP_NUMERIC_EQUAL,
&&label_JOP_GREATER_THAN_EQUAL,
&&label_JOP_LESS_THAN_EQUAL,
&&label_unknown_op,
&&label_unknown_op,
&&label_unknown_op,
&&label_unknown_op,
&&label_unknown_op,
&&label_unknown_op,
@ -557,21 +570,6 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
VM_OP(JOP_MULTIPLY)
vm_binop(*);
VM_OP(JOP_NUMERIC_LESS_THAN)
vm_numcomp( <);
VM_OP(JOP_NUMERIC_LESS_THAN_EQUAL)
vm_numcomp( <=);
VM_OP(JOP_NUMERIC_GREATER_THAN)
vm_numcomp( >);
VM_OP(JOP_NUMERIC_GREATER_THAN_EQUAL)
vm_numcomp( >=);
VM_OP(JOP_NUMERIC_EQUAL)
vm_numcomp( ==);
VM_OP(JOP_DIVIDE_IMMEDIATE)
vm_binop_immediate( /);
@ -641,16 +639,20 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
vm_next();
VM_OP(JOP_LESS_THAN)
stack[A] = janet_wrap_boolean(janet_compare(stack[B], stack[C]) < 0);
vm_pcnext();
vm_compop( <);
VM_OP(JOP_LESS_THAN_EQUAL)
vm_compop( <=);
VM_OP(JOP_LESS_THAN_IMMEDIATE)
stack[A] = janet_wrap_boolean(janet_unwrap_integer(stack[B]) < CS);
vm_pcnext();
VM_OP(JOP_GREATER_THAN)
stack[A] = janet_wrap_boolean(janet_compare(stack[B], stack[C]) > 0);
vm_pcnext();
vm_compop( >);
VM_OP(JOP_GREATER_THAN_EQUAL)
vm_compop( >=);
VM_OP(JOP_GREATER_THAN_IMMEDIATE)
stack[A] = janet_wrap_boolean(janet_unwrap_integer(stack[B]) > CS);

View File

@ -924,6 +924,8 @@ struct JanetAbstractType {
void (*marshal)(void *p, JanetMarshalContext *ctx);
void *(*unmarshal)(JanetMarshalContext *ctx);
void (*tostring)(void *p, JanetBuffer *buffer);
int (*compare)(void *lhs, void *rhs);
int32_t (*hash)(void *p, size_t len);
};
struct JanetReg {
@ -1075,11 +1077,8 @@ enum JanetOpCode {
JOP_MAKE_TABLE,
JOP_MAKE_TUPLE,
JOP_MAKE_BRACKET_TUPLE,
JOP_NUMERIC_LESS_THAN,
JOP_NUMERIC_LESS_THAN_EQUAL,
JOP_NUMERIC_GREATER_THAN,
JOP_NUMERIC_GREATER_THAN_EQUAL,
JOP_NUMERIC_EQUAL,
JOP_GREATER_THAN_EQUAL,
JOP_LESS_THAN_EQUAL,
JOP_INSTRUCTION_COUNT
};

View File

@ -37,18 +37,18 @@
(assert (= 7 (% 20 13)) "modulo 1")
(assert (= -7 (% -20 13)) "modulo 2")
(assert (order< 1.0 nil false true
(fiber/new (fn [] 1))
"hi"
(quote hello)
:hello
(array 1 2 3)
(tuple 1 2 3)
(table "a" "b" "c" "d")
(struct 1 2 3 4)
(buffer "hi")
(fn [x] (+ x x))
print) "type ordering")
(assert (< 1.0 nil false true
(fiber/new (fn [] 1))
"hi"
(quote hello)
:hello
(array 1 2 3)
(tuple 1 2 3)
(table "a" "b" "c" "d")
(struct 1 2 3 4)
(buffer "hi")
(fn [x] (+ x x))
print) "type ordering")
(assert (= (string (buffer "123" "456")) (string @"123456")) "buffer literal")
(assert (= (get {} 1) nil) "get nil from empty struct")

View File

@ -232,11 +232,11 @@
(assert (= 4 ((get closures 4))) "closure in loop 4")
# More numerical tests
(assert (== 1 1.0) "numerical equal 1")
(assert (== 0 0.0) "numerical equal 2")
(assert (== 0 -0.0) "numerical equal 3")
(assert (== 2_147_483_647 2_147_483_647.0) "numerical equal 4")
(assert (== -2_147_483_648 -2_147_483_648.0) "numerical equal 5")
(assert (= 1 1.0) "numerical equal 1")
(assert (= 0 0.0) "numerical equal 2")
(assert (= 0 -0.0) "numerical equal 3")
(assert (= 2_147_483_647 2_147_483_647.0) "numerical equal 4")
(assert (= -2_147_483_648 -2_147_483_648.0) "numerical equal 5")
# Array tests

View File

@ -62,8 +62,8 @@
# just to big
(def d (u64 "123456789123456789123456789"))))
(assert (:== (:/ (u64 "0xffff_ffff_ffff_ffff") 8 2) "0xfffffffffffffff") "bigint operations")
(assert (let [a (u64 0xff)] (:== (:+ a a a a) (:* a 2 2))) "bigint operations")
(assert (= (:/ (u64 "0xffff_ffff_ffff_ffff") 8 2) (u64 "0xfffffffffffffff")) "bigint operations 1")
(assert (let [a (u64 0xff)] (= (:+ a a a a) (:* a 2 2))) "bigint operations 2")
(assert (= (string (i64 -123)) "-123") "i64 prints reasonably")
(assert (= (string (u64 123)) "123") "u64 prints reasonably")
@ -73,7 +73,7 @@
(:/ (int/s64 "-0x8000_0000_0000_0000") -1))
# in place operators
(assert (let [a (u64 1e10)] (:+! a 1000000 "1000000" "0xffff") (:== a 10002065535)) "in place operators")
(assert (let [a (u64 1e10)] (:+! a 1000000 "1000000" "0xffff") (:= a 10002065535)) "in place operators")
# int64 typed arrays
(assert (let [t (tarray/new :int64 10)
@ -84,10 +84,10 @@
(set (t 3) (t 0))
(set (t 4) (u64 1000))
(and
(:== (t 0) (t 1))
(:== (t 1) (t 2))
(:== (t 2) (t 3))
(:== (t 3) (t 4))
(= (t 0) (t 1))
(= (t 1) (t 2))
(= (t 2) (t 3))
(= (t 3) (t 4))
))
"int64 typed arrays")