diff --git a/src/core/inttypes.c b/src/core/inttypes.c index c576e89d..f6f07c13 100644 --- a/src/core/inttypes.c +++ b/src/core/inttypes.c @@ -440,6 +440,14 @@ static Janet cfun_it_##type##_##name##i(int32_t argc, Janet *argv) { \ return janet_wrap_abstract(box); \ } \ +#define UNARYMETHOD(T, type, name, oper) \ +static Janet cfun_it_##type##_##name(int32_t argc, Janet *argv) { \ + janet_fixarity(argc, 1); \ + T *box = janet_abstract(&janet_##type##_type, sizeof(T)); \ + *box = oper(janet_unwrap_##type(argv[0])); \ + return janet_wrap_abstract(box); \ +} \ + #define DIVZERO(name) DIVZERO_##name #define DIVZERO_div janet_panic("division by zero") #define DIVZERO_rem janet_panic("division by zero") @@ -556,6 +564,7 @@ DIVMETHODINVERT_SIGNED(int64_t, s64, rem, %) OPMETHOD(int64_t, s64, and, &) OPMETHOD(int64_t, s64, or, |) OPMETHOD(int64_t, s64, xor, ^) +UNARYMETHOD(int64_t, s64, not, ~) OPMETHOD(int64_t, s64, lshift, <<) OPMETHOD(int64_t, s64, rshift, >>) OPMETHOD(uint64_t, u64, add, +) @@ -571,6 +580,7 @@ DIVMETHODINVERT(uint64_t, u64, mod, %) OPMETHOD(uint64_t, u64, and, &) OPMETHOD(uint64_t, u64, or, |) OPMETHOD(uint64_t, u64, xor, ^) +UNARYMETHOD(int64_t, u64, not, ~) OPMETHOD(uint64_t, u64, lshift, <<) OPMETHOD(uint64_t, u64, rshift, >>) @@ -600,6 +610,7 @@ static JanetMethod it_s64_methods[] = { {"r|", cfun_it_s64_or}, {"^", cfun_it_s64_xor}, {"r^", cfun_it_s64_xor}, + {"~", cfun_it_s64_not}, {"<<", cfun_it_s64_lshift}, {">>", cfun_it_s64_rshift}, {"compare", cfun_it_s64_compare}, @@ -627,6 +638,7 @@ static JanetMethod it_u64_methods[] = { {"r|", cfun_it_u64_or}, {"^", cfun_it_u64_xor}, {"r^", cfun_it_u64_xor}, + {"~", cfun_it_u64_not}, {"<<", cfun_it_u64_lshift}, {">>", cfun_it_u64_rshift}, {"compare", cfun_it_u64_compare}, diff --git a/src/core/vm.c b/src/core/vm.c index cdc932ce..00b9de04 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -301,6 +301,16 @@ static Janet janet_method_lookup(Janet x, const char *name) { return method_to_fun(janet_ckeywordv(name), x); } +static Janet janet_unary_call(const char *method, Janet arg) { + Janet m = janet_method_lookup(arg, method); + if (janet_checktype(m, JANET_NIL)) { + janet_panicf("could not find method :%s for %v", method, arg); + } else { + Janet argv[1] = { arg }; + return janet_method_invoke(m, 1, argv); + } +} + /* Call a method first on the righthand side, and then on the left hand side with a prefix */ static Janet janet_binop_call(const char *lmethod, const char *rmethod, Janet lhs, Janet rhs) { Janet lm = janet_method_lookup(lhs, lmethod); @@ -749,9 +759,14 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) { VM_OP(JOP_BNOT) { Janet op = stack[E]; - vm_assert_type(op, JANET_NUMBER); - stack[A] = janet_wrap_integer(~janet_unwrap_integer(op)); - vm_pcnext(); + if (janet_checktype(op, JANET_NUMBER)) { + stack[A] = janet_wrap_integer(~janet_unwrap_integer(op)); + vm_pcnext(); + } else { + vm_commit(); + stack[A] = janet_unary_call("~", op); + vm_checkgc_pcnext(); + } } VM_OP(JOP_SHIFT_RIGHT_UNSIGNED)