From ac1d825f139cc917252de4f2f1040ceeb013f5d6 Mon Sep 17 00:00:00 2001 From: Derick Alangi Date: Wed, 16 Jun 2021 16:54:02 +0100 Subject: [PATCH 1/2] Add support for bitwise NOT (~) operator to pocketlang Like other bitwise operators like: &, ^, >>, << etc, add support for the bitwise NOT (~) operator. --- src/pk_core.c | 8 ++++++++ src/pk_core.h | 1 + src/pk_vm.c | 12 +++++++++++- tests/lang/basics.pk | 3 +++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/pk_core.c b/src/pk_core.c index ba150ed..a10f070 100644 --- a/src/pk_core.c +++ b/src/pk_core.c @@ -1217,6 +1217,14 @@ Var varBitRshift(PKVM* vm, Var v1, Var v2) { return VAR_NULL; } +Var varBitNot(PKVM* vm, Var v) { + int64_t i; + + if (isInteger(v, &i)) + return VAR_NUM((double)(~i)); + return VAR_NULL; +} + bool varGreater(Var v1, Var v2) { double d1, d2; diff --git a/src/pk_core.h b/src/pk_core.h index ff391ce..205ad37 100644 --- a/src/pk_core.h +++ b/src/pk_core.h @@ -41,6 +41,7 @@ Var varBitOr(PKVM* vm, Var v1, Var v2); // Returns v1 | v2. Var varBitXor(PKVM* vm, Var v1, Var v2); // Returns v1 ^ v2. Var varBitLshift(PKVM* vm, Var v1, Var v2); // Returns v1 << v2. Var varBitRshift(PKVM* vm, Var v1, Var v2); // Returns v1 >> v2. +Var varBitNot(PKVM* vm, Var v); // Returns ~v. bool varGreater(Var v1, Var v2); // Returns v1 > v2. bool varLesser(Var v1, Var v2); // Returns v1 < v2. diff --git a/src/pk_vm.c b/src/pk_vm.c index e2896c8..b21e349 100644 --- a/src/pk_vm.c +++ b/src/pk_vm.c @@ -1220,7 +1220,17 @@ static PkResult runFiber(PKVM* vm, Fiber* fiber) { } OPCODE(BIT_NOT): - TODO; + { + // Don't pop yet, we need the reference for gc. + Var val = POP(); + + Var result = varBitNot(vm, val); + DROP(); // val + PUSH(result); + + CHECK_ERROR(); + DISPATCH(); + } // Do not ever use PUSH(binaryOp(vm, POP(), POP())); // Function parameters are not evaluated in a defined order in C. diff --git a/tests/lang/basics.pk b/tests/lang/basics.pk index c197c4f..e92106a 100644 --- a/tests/lang/basics.pk +++ b/tests/lang/basics.pk @@ -73,6 +73,9 @@ assert(8 >> 1 == 0x4) assert(8 >> 2 == 0b10) assert(0xa >> 1 == 5) +assert(~8 == -9) +assert(~1 == -2) + x = 42 ; assert((x&=51) == 34) x = 123 ; assert((x&=324) == 64) for i in 0..1000 From fbcf6fc1a15eab6a10f39554aebe42692859e40c Mon Sep 17 00:00:00 2001 From: Derick Alangi Date: Wed, 16 Jun 2021 20:54:07 +0100 Subject: [PATCH 2/2] use PEEK() so we don't loose reference --- src/pk_core.c | 6 +++--- src/pk_vm.c | 2 +- tests/lang/basics.pk | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pk_core.c b/src/pk_core.c index a10f070..e963a48 100644 --- a/src/pk_core.c +++ b/src/pk_core.c @@ -1220,9 +1220,9 @@ Var varBitRshift(PKVM* vm, Var v1, Var v2) { Var varBitNot(PKVM* vm, Var v) { int64_t i; - if (isInteger(v, &i)) - return VAR_NUM((double)(~i)); - return VAR_NULL; + if (!validateInteger(vm, v, &i, "Unary operand")) return VAR_NULL; + + return VAR_NUM((double)(~i)); } bool varGreater(Var v1, Var v2) { diff --git a/src/pk_vm.c b/src/pk_vm.c index b21e349..1044440 100644 --- a/src/pk_vm.c +++ b/src/pk_vm.c @@ -1222,7 +1222,7 @@ static PkResult runFiber(PKVM* vm, Fiber* fiber) { OPCODE(BIT_NOT): { // Don't pop yet, we need the reference for gc. - Var val = POP(); + Var val = PEEK(-1); Var result = varBitNot(vm, val); DROP(); // val diff --git a/tests/lang/basics.pk b/tests/lang/basics.pk index e92106a..f14b3c8 100644 --- a/tests/lang/basics.pk +++ b/tests/lang/basics.pk @@ -75,6 +75,8 @@ assert(0xa >> 1 == 5) assert(~8 == -9) assert(~1 == -2) +assert(~0b0 == -1) +assert(~0x1 == -2) x = 42 ; assert((x&=51) == 34) x = 123 ; assert((x&=324) == 64)