Skip to content

Commit

Permalink
Add support for bitwise NOT
Browse files Browse the repository at this point in the history
This adds Int.not which performs a bitwise NOT of the receiver.

Changelog: added
  • Loading branch information
yorickpeterse committed Oct 10, 2022
1 parent 28706b5 commit 758497f
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 0 deletions.
5 changes: 5 additions & 0 deletions bytecode/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ pub enum Opcode {
Push,
Pop,
FuturePoll,
IntBitNot,
}

impl Opcode {
Expand Down Expand Up @@ -260,6 +261,7 @@ impl Opcode {
105 => Opcode::Push,
106 => Opcode::Pop,
107 => Opcode::FuturePoll,
108 => Opcode::IntBitNot,
_ => return Err(format!("The opcode {} is invalid", byte)),
};

Expand Down Expand Up @@ -377,6 +379,7 @@ impl Opcode {
Opcode::Push => 105,
Opcode::Pop => 106,
Opcode::FuturePoll => 107,
Opcode::IntBitNot => 108,
}
}

Expand Down Expand Up @@ -490,6 +493,7 @@ impl Opcode {
Opcode::Push => "push",
Opcode::Pop => "pop",
Opcode::FuturePoll => "future_poll",
Opcode::IntBitNot => "int_bit_not",
}
}

Expand Down Expand Up @@ -621,6 +625,7 @@ impl Opcode {
Opcode::Push => 1,
Opcode::Pop => 1,
Opcode::FuturePoll => 2,
Opcode::IntBitNot => 1,
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/src/type_check/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,7 @@ pub(crate) fn define_builtin_functions(state: &mut State) -> bool {
(Opcode::IsUndefined, boolean),
(Opcode::ProcessSuspend, nil),
(Opcode::FuturePoll, any),
(Opcode::IntBitNot, int),
];

let macros = vec![
Expand Down
12 changes: 12 additions & 0 deletions libstd/src/std/int.inko
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,18 @@ class builtin Int {
bytes.reverse
ByteArray.from_array(bytes).into_string
}

# Returns the result of performing a bitwise `NOT` on `self`.
#
# As Inko doesn't support unary operators besides `not` (which only supports
# booleans), this is just a regular method.
#
# # Examples
#
# 12.not # => -13
fn pub not -> Int {
_INKO.int_bit_not(self)
}
}

impl ToInt for Int {
Expand Down
9 changes: 9 additions & 0 deletions libstd/test/std/test_int.inko
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import helpers::(fmt, hash)
import std::cmp::Ordering
import std::int::(MIN, MAX)
import std::test::Tests

fn pub tests(t: mut Tests) {
Expand Down Expand Up @@ -233,4 +234,12 @@ fn pub tests(t: mut Tests) {
t.equal(3.nearest_power_of_two, 4)
t.equal(9.nearest_power_of_two, 16)
}

t.test('Int.not') fn (t) {
t.equal(0.not, -1)
t.equal(12.not, -13)
t.equal(-13.not, 12)
t.equal(MAX.not, MIN)
t.equal(MIN.not, MAX)
}
}
7 changes: 7 additions & 0 deletions vm/src/instructions/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ pub(crate) fn xor(state: &State, left: Pointer, right: Pointer) -> Pointer {
Int::alloc(state.permanent_space.int_class(), value)
}

#[inline(always)]
pub(crate) fn not(state: &State, ptr: Pointer) -> Pointer {
let value = unsafe { !Int::read(ptr) };

Int::alloc(state.permanent_space.int_class(), value)
}

#[inline(always)]
pub(crate) fn shl(
state: &State,
Expand Down
7 changes: 7 additions & 0 deletions vm/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,13 @@ impl<'a> Machine<'a> {

state.context.set_register(reg, res);
}
Opcode::IntBitNot => {
let reg = ins.arg(0);
let val = state.context.get_register(ins.arg(1));
let res = integer::not(self.state, val);

state.context.set_register(reg, res);
}
Opcode::IntShl => {
let reg = ins.arg(0);
let a = state.context.get_register(ins.arg(1));
Expand Down

0 comments on commit 758497f

Please sign in to comment.