1
0

Continue instruction rewrite

This commit is contained in:
Jeff 2024-12-08 08:01:15 -05:00
parent 1fa958fd0b
commit cc069df7ee
27 changed files with 387 additions and 338 deletions

View File

@ -994,7 +994,7 @@ impl<'src> Compiler<'src> {
let register = self.next_register() - 1;
let set_local = Instruction::from(SetLocal {
register,
register_index: register,
local_index,
});

View File

@ -8,31 +8,28 @@ pub struct CallNative {
impl From<&Instruction> for CallNative {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let function = NativeFunction::from(instruction.b);
CallNative {
destination,
function: NativeFunction::from(instruction.b()),
argument_count: instruction.c(),
function,
argument_count: instruction.c,
}
}
}
impl From<CallNative> for Instruction {
fn from(call_native: CallNative) -> Self {
let (a, a_is_local) = match call_native.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, a_options) = call_native.destination.as_index_and_a_options();
let b = call_native.function as u16;
*Instruction::new(Operation::CallNative)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(call_native.function as u16)
.set_c(call_native.argument_count)
Instruction {
operation: Operation::CALL_NATIVE,
options: a_options,
a,
b,
c: call_native.argument_count,
}
}
}

View File

@ -1,5 +1,7 @@
use crate::{Instruction, Operation};
use super::InstructionOptions;
pub struct Close {
pub from: u16,
pub to: u16,
@ -8,16 +10,20 @@ pub struct Close {
impl From<&Instruction> for Close {
fn from(instruction: &Instruction) -> Self {
Close {
from: instruction.b(),
to: instruction.c(),
from: instruction.b,
to: instruction.c,
}
}
}
impl From<Close> for Instruction {
fn from(r#move: Close) -> Self {
*Instruction::new(Operation::Close)
.set_b(r#move.from)
.set_c(r#move.to)
fn from(close: Close) -> Self {
Instruction {
operation: Operation::CLOSE,
options: InstructionOptions::empty(),
a: 0,
b: close.from,
c: close.to,
}
}
}

View File

@ -1,26 +0,0 @@
use crate::{Instruction, Operation};
pub struct DefineLocal {
pub register: u16,
pub local_index: u16,
pub is_mutable: bool,
}
impl From<&Instruction> for DefineLocal {
fn from(instruction: &Instruction) -> Self {
DefineLocal {
register: instruction.a(),
local_index: instruction.b(),
is_mutable: instruction.c_as_boolean(),
}
}
}
impl From<DefineLocal> for Instruction {
fn from(define_local: DefineLocal) -> Self {
*Instruction::new(Operation::DefineLocal)
.set_a(define_local.register)
.set_b(define_local.local_index)
.set_c_to_boolean(define_local.is_mutable)
}
}

View File

@ -8,11 +8,7 @@ pub struct Divide {
impl From<&Instruction> for Divide {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let (left, right) = instruction.b_and_c_as_arguments();
Divide {
@ -25,19 +21,16 @@ impl From<&Instruction> for Divide {
impl From<Divide> for Instruction {
fn from(divide: Divide) -> Self {
let (a, a_is_local) = match divide.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, a_options) = divide.destination.as_index_and_a_options();
let (b, b_options) = divide.left.as_index_and_b_options();
let (c, c_options) = divide.right.as_index_and_c_options();
*Instruction::new(Operation::Divide)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(divide.left.index())
.set_b_is_constant(divide.left.is_constant())
.set_b_is_local(divide.left.is_local())
.set_c(divide.right.index())
.set_c_is_constant(divide.right.is_constant())
.set_c_is_local(divide.right.is_local())
Instruction {
operation: Operation::DIVIDE,
options: a_options | b_options | c_options,
a,
b,
c,
}
}
}

View File

@ -1,6 +1,9 @@
use crate::{Argument, Instruction, Operation};
use crate::{Argument, Destination, Instruction, Operation};
use super::InstructionOptions;
pub struct Equal {
pub destination: Destination,
pub value: bool,
pub left: Argument,
pub right: Argument,
@ -8,10 +11,13 @@ pub struct Equal {
impl From<&Instruction> for Equal {
fn from(instruction: &Instruction) -> Self {
let destination = instruction.a_as_destination();
let value = instruction.options.d();
let (left, right) = instruction.b_and_c_as_arguments();
Equal {
value: instruction.a_as_boolean(),
destination,
value,
left,
right,
}
@ -20,13 +26,21 @@ impl From<&Instruction> for Equal {
impl From<Equal> for Instruction {
fn from(equal: Equal) -> Self {
*Instruction::new(Operation::Equal)
.set_a_to_boolean(equal.value)
.set_b(equal.left.index())
.set_b_is_constant(equal.left.is_constant())
.set_b_is_local(equal.left.is_local())
.set_c(equal.right.index())
.set_c_is_constant(equal.right.is_constant())
.set_c_is_local(equal.right.is_local())
let (a, a_options) = equal.destination.as_index_and_a_options();
let (b, b_options) = equal.left.as_index_and_b_options();
let (c, c_options) = equal.right.as_index_and_c_options();
let d_options = if equal.value {
InstructionOptions::D_IS_TRUE
} else {
InstructionOptions::empty()
};
Instruction {
operation: Operation::EQUAL,
options: a_options | b_options | c_options | d_options,
a,
b,
c,
}
}
}

View File

@ -7,29 +7,25 @@ pub struct GetLocal {
impl From<&Instruction> for GetLocal {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
GetLocal {
destination,
local_index: instruction.b(),
local_index: instruction.b,
}
}
}
impl From<GetLocal> for Instruction {
fn from(get_local: GetLocal) -> Self {
let (a, a_is_local) = match get_local.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, a_options) = get_local.destination.as_index_and_a_options();
*Instruction::new(Operation::GetLocal)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(get_local.local_index)
Instruction {
operation: Operation::GET_LOCAL,
options: a_options,
a,
b: get_local.local_index,
c: 0,
}
}
}

View File

@ -1,5 +1,7 @@
use crate::{Instruction, Operation};
use super::InstructionOptions;
pub struct Jump {
pub offset: u16,
pub is_positive: bool,
@ -8,16 +10,20 @@ pub struct Jump {
impl From<&Instruction> for Jump {
fn from(instruction: &Instruction) -> Self {
Jump {
offset: instruction.b(),
is_positive: instruction.c_as_boolean(),
offset: instruction.b,
is_positive: instruction.c != 0,
}
}
}
impl From<Jump> for Instruction {
fn from(jump: Jump) -> Self {
*Instruction::new(Operation::Jump)
.set_b(jump.offset)
.set_c_to_boolean(jump.is_positive)
Instruction {
operation: Operation::JUMP,
options: InstructionOptions::empty(),
a: 0,
b: jump.offset,
c: jump.is_positive as u16,
}
}
}

View File

@ -1,6 +1,9 @@
use crate::{Argument, Instruction, Operation};
use crate::{Argument, Destination, Instruction, Operation};
use super::InstructionOptions;
pub struct Less {
pub destination: Destination,
pub value: bool,
pub left: Argument,
pub right: Argument,
@ -8,10 +11,13 @@ pub struct Less {
impl From<&Instruction> for Less {
fn from(instruction: &Instruction) -> Self {
let destination = instruction.a_as_destination();
let value = instruction.options.d();
let (left, right) = instruction.b_and_c_as_arguments();
Less {
value: instruction.a_as_boolean(),
destination,
value,
left,
right,
}
@ -20,13 +26,21 @@ impl From<&Instruction> for Less {
impl From<Less> for Instruction {
fn from(less: Less) -> Self {
*Instruction::new(Operation::Less)
.set_a_to_boolean(less.value)
.set_b(less.left.index())
.set_b_is_constant(less.left.is_constant())
.set_b_is_local(less.left.is_local())
.set_c(less.right.index())
.set_c_is_constant(less.right.is_constant())
.set_c_is_local(less.right.is_local())
let (a, a_options) = less.destination.as_index_and_a_options();
let (b, b_options) = less.left.as_index_and_b_options();
let (c, c_options) = less.right.as_index_and_c_options();
let d_options = if less.value {
InstructionOptions::D_IS_TRUE
} else {
InstructionOptions::empty()
};
Instruction {
operation: Operation::LESS,
options: a_options | b_options | c_options | d_options,
a,
b,
c,
}
}
}

View File

@ -1,6 +1,9 @@
use crate::{Argument, Instruction, Operation};
use crate::{Argument, Destination, Instruction, Operation};
use super::InstructionOptions;
pub struct LessEqual {
pub destination: Destination,
pub value: bool,
pub left: Argument,
pub right: Argument,
@ -8,10 +11,13 @@ pub struct LessEqual {
impl From<&Instruction> for LessEqual {
fn from(instruction: &Instruction) -> Self {
let destination = instruction.a_as_destination();
let value = instruction.options.d();
let (left, right) = instruction.b_and_c_as_arguments();
LessEqual {
value: instruction.a_as_boolean(),
destination,
value,
left,
right,
}
@ -20,13 +26,21 @@ impl From<&Instruction> for LessEqual {
impl From<LessEqual> for Instruction {
fn from(less_equal: LessEqual) -> Self {
*Instruction::new(Operation::LessEqual)
.set_a_to_boolean(less_equal.value)
.set_b(less_equal.left.index())
.set_b_is_constant(less_equal.left.is_constant())
.set_b_is_local(less_equal.left.is_local())
.set_c(less_equal.right.index())
.set_c_is_constant(less_equal.right.is_constant())
.set_c_is_local(less_equal.right.is_local())
let (a, a_options) = less_equal.destination.as_index_and_a_options();
let (b, b_options) = less_equal.left.as_index_and_b_options();
let (c, c_options) = less_equal.right.as_index_and_c_options();
let d_options = if less_equal.value {
InstructionOptions::D_IS_TRUE
} else {
InstructionOptions::empty()
};
Instruction {
operation: Operation::LESS_EQUAL,
options: a_options | b_options | c_options | d_options,
a,
b,
c,
}
}
}

View File

@ -8,31 +8,30 @@ pub struct LoadBoolean {
impl From<&Instruction> for LoadBoolean {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let value = instruction.b != 0;
let jump_next = instruction.c != 0;
LoadBoolean {
destination,
value: instruction.b_as_boolean(),
jump_next: instruction.c_as_boolean(),
value,
jump_next,
}
}
}
impl From<LoadBoolean> for Instruction {
fn from(load_boolean: LoadBoolean) -> Self {
let (a, a_is_local) = match load_boolean.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, options) = load_boolean.destination.as_index_and_a_options();
let b = load_boolean.value as u16;
let c = load_boolean.jump_next as u16;
*Instruction::new(Operation::LoadBoolean)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b_to_boolean(load_boolean.value)
.set_c_to_boolean(load_boolean.jump_next)
Instruction {
operation: Operation::LOAD_BOOLEAN,
options,
a,
b,
c,
}
}
}

View File

@ -8,31 +8,30 @@ pub struct LoadConstant {
impl From<&Instruction> for LoadConstant {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let constant_index = instruction.b;
let jump_next = instruction.c != 0;
LoadConstant {
destination,
constant_index: instruction.b(),
jump_next: instruction.c_as_boolean(),
constant_index,
jump_next,
}
}
}
impl From<LoadConstant> for Instruction {
fn from(load_constant: LoadConstant) -> Self {
let (a, a_is_local) = match load_constant.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, options) = load_constant.destination.as_index_and_a_options();
let b = load_constant.constant_index;
let c = load_constant.jump_next as u16;
*Instruction::new(Operation::LoadConstant)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(load_constant.constant_index)
.set_c_to_boolean(load_constant.jump_next)
Instruction {
operation: Operation::LOAD_CONSTANT,
options,
a,
b,
c,
}
}
}

View File

@ -7,29 +7,27 @@ pub struct LoadList {
impl From<&Instruction> for LoadList {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let start_register = instruction.b;
LoadList {
destination,
start_register: instruction.b(),
start_register,
}
}
}
impl From<LoadList> for Instruction {
fn from(load_list: LoadList) -> Self {
let (a, a_is_local) = match load_list.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, options) = load_list.destination.as_index_and_a_options();
let b = load_list.start_register;
*Instruction::new(Operation::LoadList)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(load_list.start_register)
Instruction {
operation: Operation::LOAD_LIST,
options,
a,
b,
c: 0,
}
}
}

View File

@ -6,11 +6,7 @@ pub struct LoadSelf {
impl From<&Instruction> for LoadSelf {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
LoadSelf { destination }
}
@ -18,13 +14,14 @@ impl From<&Instruction> for LoadSelf {
impl From<LoadSelf> for Instruction {
fn from(load_self: LoadSelf) -> Self {
let (a, a_is_local) = match load_self.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, options) = load_self.destination.as_index_and_a_options();
*Instruction::new(Operation::LoadSelf)
.set_a(a)
.set_a_is_local(a_is_local)
Instruction {
operation: Operation::LOAD_SELF,
options,
a,
b: 0,
c: 0,
}
}
}

View File

@ -1,18 +1,20 @@
//! An operation and its arguments for the Dust virtual machine.
//!
//! Each instruction is a 64-bit unsigned integer that is divided into nine fields:
//! Each instruction is 64 bits and holds ten distinct fields:
//!
//! Bit | Description
//! ----- | -----------
//! 0-8 | The operation code.
//! 9 | Boolean flag indicating whether the B argument is a constant.
//! 10 | Boolean flag indicating whether the C argument is a constant.
//! 11 | Boolean flag indicating whether the A argument is a local.
//! 12 | Boolean flag indicating whether the B argument is a local.
//! 13 | Boolean flag indicating whether the C argument is a local.
//! 17-32 | The A argument,
//! 33-48 | The B argument.
//! 49-63 | The C argument.
//! 0-8 | Operation code
//! 9 | Flag for whether A is a local
//! 10 | Flag for whether B argument is a constant
//! 11 | Flag for whether C argument is a local
//! 12 | Flag for whether B argument is a constant
//! 13 | Flag for whether C argument is a local
//! 14 | D Argument
//! 15-16 | Unused
//! 17-32 | A argument
//! 33-48 | B argument
//! 49-63 | C argument
//!
//! Be careful when working with instructions directly. When modifying an instruction, be sure to
//! account for the fact that setting the A, B, or C arguments to 0 will have no effect. It is
@ -55,7 +57,6 @@ mod add;
mod call;
mod call_native;
mod close;
mod define_local;
mod divide;
mod equal;
mod get_local;
@ -79,13 +80,10 @@ mod subtract;
mod test;
mod test_set;
use std::fmt::{self, Debug, Display, Formatter};
pub use add::Add;
pub use call::Call;
pub use call_native::CallNative;
pub use close::Close;
pub use define_local::DefineLocal;
pub use divide::Divide;
pub use equal::Equal;
pub use get_local::GetLocal;
@ -110,6 +108,7 @@ pub use test::Test;
pub use test_set::TestSet;
use serde::{Deserialize, Serialize};
use std::fmt::{self, Debug, Display, Formatter};
use crate::NativeFunction;
@ -165,14 +164,6 @@ impl Instruction {
Instruction::from(LoadSelf { destination })
}
pub fn define_local(register: u16, local_index: u16, is_mutable: bool) -> Instruction {
Instruction::from(DefineLocal {
local_index,
register,
is_mutable,
})
}
pub fn get_local(destination: Destination, local_index: u16) -> Instruction {
Instruction::from(GetLocal {
destination,
@ -183,7 +174,7 @@ impl Instruction {
pub fn set_local(register: u16, local_index: u16) -> Instruction {
Instruction::from(SetLocal {
local_index,
register,
register_index: register,
})
}
@ -242,16 +233,46 @@ impl Instruction {
})
}
pub fn equal(value: bool, left: Argument, right: Argument) -> Instruction {
Instruction::from(Equal { value, left, right })
pub fn equal(
destination: Destination,
value: bool,
left: Argument,
right: Argument,
) -> Instruction {
Instruction::from(Equal {
destination,
value,
left,
right,
})
}
pub fn less(value: bool, left: Argument, right: Argument) -> Instruction {
Instruction::from(Less { value, left, right })
pub fn less(
destination: Destination,
value: bool,
left: Argument,
right: Argument,
) -> Instruction {
Instruction::from(Less {
destination,
value,
left,
right,
})
}
pub fn less_equal(value: bool, left: Argument, right: Argument) -> Instruction {
Instruction::from(LessEqual { value, left, right })
pub fn less_equal(
destination: Destination,
value: bool,
left: Argument,
right: Argument,
) -> Instruction {
Instruction::from(LessEqual {
destination,
value,
left,
right,
})
}
pub fn negate(destination: Destination, argument: Argument) -> Instruction {
@ -460,7 +481,7 @@ impl Instruction {
}
Operation::SET_LOCAL => {
let SetLocal {
register,
register_index: register,
local_index,
} = SetLocal::from(self);
@ -531,22 +552,37 @@ impl Instruction {
format!("if {bang}{argument} {{ JUMP +1 }} else {{ {destination} = {argument} }}")
}
Operation::EQUAL => {
let Equal { value, left, right } = Equal::from(self);
let Equal {
destination,
value,
left,
right,
} = Equal::from(self);
let comparison_symbol = if value { "==" } else { "!=" };
format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}")
format!("{destination} = {left} {comparison_symbol} {right}")
}
Operation::LESS => {
let Less { value, left, right } = Less::from(self);
let Less {
destination,
value,
left,
right,
} = Less::from(self);
let comparison_symbol = if value { "<" } else { ">=" };
format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}")
format!("{destination} {left} {comparison_symbol} {right}")
}
Operation::LESS_EQUAL => {
let LessEqual { value, left, right } = LessEqual::from(self);
let LessEqual {
destination,
value,
left,
right,
} = LessEqual::from(self);
let comparison_symbol = if value { "<=" } else { ">" };
format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}")
format!("{destination} {left} {comparison_symbol} {right}")
}
Operation::NEGATE => {
let Negate {

View File

@ -8,11 +8,7 @@ pub struct Modulo {
impl From<&Instruction> for Modulo {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let (left, right) = instruction.b_and_c_as_arguments();
Modulo {
@ -25,19 +21,16 @@ impl From<&Instruction> for Modulo {
impl From<Modulo> for Instruction {
fn from(modulo: Modulo) -> Self {
let (a, a_is_local) = match modulo.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, a_options) = modulo.destination.as_index_and_a_options();
let (b, b_options) = modulo.left.as_index_and_b_options();
let (c, c_options) = modulo.right.as_index_and_c_options();
*Instruction::new(Operation::Modulo)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(modulo.left.index())
.set_b_is_constant(modulo.left.is_constant())
.set_b_is_local(modulo.left.is_local())
.set_c(modulo.right.index())
.set_c_is_constant(modulo.right.is_constant())
.set_c_is_local(modulo.right.is_local())
Instruction {
operation: Operation::MODULO,
options: a_options | b_options | c_options,
a,
b,
c,
}
}
}

View File

@ -1,5 +1,7 @@
use crate::{Instruction, Operation};
use super::InstructionOptions;
pub struct Move {
pub from: u16,
pub to: u16,
@ -8,16 +10,20 @@ pub struct Move {
impl From<&Instruction> for Move {
fn from(instruction: &Instruction) -> Self {
Move {
from: instruction.b(),
to: instruction.a(),
from: instruction.b,
to: instruction.c,
}
}
}
impl From<Move> for Instruction {
fn from(r#move: Move) -> Self {
*Instruction::new(Operation::Move)
.set_b(r#move.from)
.set_c(r#move.to)
Instruction {
operation: Operation::MOVE,
options: InstructionOptions::empty(),
a: 0,
b: r#move.from,
c: r#move.to,
}
}
}

View File

@ -8,11 +8,7 @@ pub struct Multiply {
impl From<&Instruction> for Multiply {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let (left, right) = instruction.b_and_c_as_arguments();
Multiply {
@ -25,19 +21,16 @@ impl From<&Instruction> for Multiply {
impl From<Multiply> for Instruction {
fn from(multiply: Multiply) -> Self {
let (a, a_is_local) = match multiply.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, a_options) = multiply.destination.as_index_and_a_options();
let (b, b_options) = multiply.left.as_index_and_b_options();
let (c, c_options) = multiply.right.as_index_and_c_options();
*Instruction::new(Operation::Multiply)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(multiply.left.index())
.set_b_is_constant(multiply.left.is_constant())
.set_b_is_local(multiply.left.is_local())
.set_c(multiply.right.index())
.set_c_is_constant(multiply.right.is_constant())
.set_c_is_local(multiply.right.is_local())
Instruction {
operation: Operation::MULTIPLY,
options: a_options | b_options | c_options,
a,
b,
c,
}
}
}

View File

@ -7,31 +7,27 @@ pub struct Negate {
impl From<&Instruction> for Negate {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let argument = instruction.b_as_argument();
Negate {
destination,
argument: instruction.b_as_argument(),
argument,
}
}
}
impl From<Negate> for Instruction {
fn from(negate: Negate) -> Self {
let (a, a_is_local) = match negate.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, a_options) = negate.destination.as_index_and_a_options();
let (b, b_options) = negate.argument.as_index_and_b_options();
*Instruction::new(Operation::Negate)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(negate.argument.index())
.set_b_is_constant(negate.argument.is_constant())
.set_b_is_local(negate.argument.is_local())
Instruction {
operation: Operation::NEGATE,
options: a_options | b_options,
a,
b,
c: 0,
}
}
}

View File

@ -7,31 +7,27 @@ pub struct Not {
impl From<&Instruction> for Not {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let argument = instruction.b_as_argument();
Not {
destination,
argument: instruction.b_as_argument(),
argument,
}
}
}
impl From<Not> for Instruction {
fn from(not: Not) -> Self {
let (a, a_is_local) = match not.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, a_options) = not.destination.as_index_and_a_options();
let (b, b_options) = not.argument.as_index_and_b_options();
*Instruction::new(Operation::Not)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(not.argument.index())
.set_b_is_constant(not.argument.is_constant())
.set_b_is_local(not.argument.is_local())
Instruction {
operation: Operation::NOT,
options: a_options | b_options,
a,
b,
c: 0,
}
}
}

View File

@ -12,7 +12,7 @@ bitflags! {
const C_IS_CONSTANT = 0b00001000;
const C_IS_LOCAL = 0b00010000;
const D_FIELD = 0b00100000;
const D_IS_TRUE = 0b00100000;
}
}
@ -38,6 +38,6 @@ impl InstructionOptions {
}
pub fn d(self) -> bool {
self.contains(Self::D_FIELD)
self.contains(Self::D_IS_TRUE)
}
}

View File

@ -1,19 +1,31 @@
use crate::{Instruction, Operation};
use super::InstructionOptions;
pub struct Return {
pub should_return_value: bool,
}
impl From<&Instruction> for Return {
fn from(instruction: &Instruction) -> Self {
let should_return_value = instruction.b != 0;
Return {
should_return_value: instruction.b_as_boolean(),
should_return_value,
}
}
}
impl From<Return> for Instruction {
fn from(r#return: Return) -> Self {
*Instruction::new(Operation::Return).set_b_to_boolean(r#return.should_return_value)
let b = r#return.should_return_value as u16;
Instruction {
operation: Operation::RETURN,
options: InstructionOptions::empty(),
a: 0,
b,
c: 0,
}
}
}

View File

@ -1,23 +1,35 @@
use crate::{Instruction, Operation};
use super::InstructionOptions;
pub struct SetLocal {
pub register: u16,
pub register_index: u16,
pub local_index: u16,
}
impl From<&Instruction> for SetLocal {
fn from(instruction: &Instruction) -> Self {
let register_index = instruction.b;
let local_index = instruction.c;
SetLocal {
register: instruction.a(),
local_index: instruction.b(),
register_index,
local_index,
}
}
}
impl From<SetLocal> for Instruction {
fn from(set_local: SetLocal) -> Self {
*Instruction::new(Operation::SetLocal)
.set_a(set_local.register)
.set_b(set_local.local_index)
let b = set_local.register_index;
let c = set_local.local_index;
Instruction {
operation: Operation::SET_LOCAL,
options: InstructionOptions::empty(),
a: 0,
b,
c,
}
}
}

View File

@ -1,4 +1,4 @@
use crate::{Argument, Destination, Instruction};
use crate::{Argument, Destination, Instruction, Operation};
pub struct Subtract {
pub destination: Destination,
@ -8,11 +8,7 @@ pub struct Subtract {
impl From<&Instruction> for Subtract {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let (left, right) = instruction.b_and_c_as_arguments();
Subtract {
@ -25,19 +21,16 @@ impl From<&Instruction> for Subtract {
impl From<Subtract> for Instruction {
fn from(subtract: Subtract) -> Self {
let (a, a_is_local) = match subtract.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, a_options) = subtract.destination.as_index_and_a_options();
let (b, b_options) = subtract.left.as_index_and_b_options();
let (c, c_options) = subtract.right.as_index_and_c_options();
*Instruction::new(crate::Operation::Subtract)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(subtract.left.index())
.set_b_is_constant(subtract.left.is_constant())
.set_b_is_local(subtract.left.is_local())
.set_c(subtract.right.index())
.set_c_is_constant(subtract.right.is_constant())
.set_c_is_local(subtract.right.is_local())
Instruction {
operation: Operation::SUBTRACT,
options: a_options | b_options | c_options,
a,
b,
c,
}
}
}

View File

@ -7,19 +7,27 @@ pub struct Test {
impl From<&Instruction> for Test {
fn from(instruction: &Instruction) -> Self {
let argument = instruction.b_as_argument();
let test_value = instruction.c != 0;
Test {
argument: instruction.b_as_argument(),
test_value: instruction.c_as_boolean(),
argument,
test_value,
}
}
}
impl From<Test> for Instruction {
fn from(test: Test) -> Self {
*Instruction::new(Operation::Test)
.set_b(test.argument.index())
.set_b_is_constant(test.argument.is_constant())
.set_b_is_local(test.argument.is_local())
.set_c_to_boolean(test.test_value)
let (b, options) = test.argument.as_index_and_b_options();
let c = test.test_value as u16;
Instruction {
operation: Operation::TEST,
options,
a: 0,
b,
c,
}
}
}

View File

@ -8,33 +8,30 @@ pub struct TestSet {
impl From<&Instruction> for TestSet {
fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() {
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let destination = instruction.a_as_destination();
let argument = instruction.b_as_argument();
let test_value = instruction.c != 0;
TestSet {
destination,
argument: instruction.b_as_argument(),
test_value: instruction.c_as_boolean(),
argument,
test_value,
}
}
}
impl From<TestSet> for Instruction {
fn from(test_set: TestSet) -> Self {
let (a, a_is_local) = match test_set.destination {
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
let (a, a_options) = test_set.destination.as_index_and_a_options();
let (b, b_options) = test_set.argument.as_index_and_b_options();
let c = test_set.test_value as u16;
*Instruction::new(Operation::TestSet)
.set_a(a)
.set_a_is_local(a_is_local)
.set_b(test_set.argument.index())
.set_b_is_constant(test_set.argument.is_constant())
.set_b_is_local(test_set.argument.is_local())
.set_c_to_boolean(test_set.test_value)
Instruction {
operation: Operation::TEST_SET,
options: a_options | b_options,
a,
b,
c,
}
}
}

View File

@ -182,7 +182,7 @@ impl<'a> Vm<'a> {
}
Operation::SetLocal => {
let SetLocal {
register,
register_index: register,
local_index,
} = SetLocal::from(&instruction);