From cc069df7eed0f3cbd48dc1c38905020d4c745978 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 8 Dec 2024 08:01:15 -0500 Subject: [PATCH] Continue instruction rewrite --- dust-lang/src/compiler.rs | 2 +- dust-lang/src/instruction/call_native.rs | 29 +++--- dust-lang/src/instruction/close.rs | 18 ++-- dust-lang/src/instruction/define_local.rs | 26 ----- dust-lang/src/instruction/divide.rs | 29 +++--- dust-lang/src/instruction/equal.rs | 34 +++++-- dust-lang/src/instruction/get_local.rs | 24 ++--- dust-lang/src/instruction/jump.rs | 16 ++- dust-lang/src/instruction/less.rs | 34 +++++-- dust-lang/src/instruction/less_equal.rs | 34 +++++-- dust-lang/src/instruction/load_boolean.rs | 31 +++--- dust-lang/src/instruction/load_constant.rs | 31 +++--- dust-lang/src/instruction/load_list.rs | 26 +++-- dust-lang/src/instruction/load_self.rs | 21 ++-- dust-lang/src/instruction/mod.rs | 108 ++++++++++++++------- dust-lang/src/instruction/modulo.rs | 29 +++--- dust-lang/src/instruction/move.rs | 16 ++- dust-lang/src/instruction/multiply.rs | 29 +++--- dust-lang/src/instruction/negate.rs | 28 +++--- dust-lang/src/instruction/not.rs | 28 +++--- dust-lang/src/instruction/options.rs | 4 +- dust-lang/src/instruction/return.rs | 16 ++- dust-lang/src/instruction/set_local.rs | 24 +++-- dust-lang/src/instruction/subtract.rs | 31 +++--- dust-lang/src/instruction/test.rs | 22 +++-- dust-lang/src/instruction/test_set.rs | 33 +++---- dust-lang/src/vm.rs | 2 +- 27 files changed, 387 insertions(+), 338 deletions(-) delete mode 100644 dust-lang/src/instruction/define_local.rs diff --git a/dust-lang/src/compiler.rs b/dust-lang/src/compiler.rs index 811e403..57ece13 100644 --- a/dust-lang/src/compiler.rs +++ b/dust-lang/src/compiler.rs @@ -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, }); diff --git a/dust-lang/src/instruction/call_native.rs b/dust-lang/src/instruction/call_native.rs index e35266b..93b2412 100644 --- a/dust-lang/src/instruction/call_native.rs +++ b/dust-lang/src/instruction/call_native.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/close.rs b/dust-lang/src/instruction/close.rs index 7428a1b..ecb5e2d 100644 --- a/dust-lang/src/instruction/close.rs +++ b/dust-lang/src/instruction/close.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/define_local.rs b/dust-lang/src/instruction/define_local.rs deleted file mode 100644 index 021fae9..0000000 --- a/dust-lang/src/instruction/define_local.rs +++ /dev/null @@ -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 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) - } -} diff --git a/dust-lang/src/instruction/divide.rs b/dust-lang/src/instruction/divide.rs index 85243a4..39ff33e 100644 --- a/dust-lang/src/instruction/divide.rs +++ b/dust-lang/src/instruction/divide.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/equal.rs b/dust-lang/src/instruction/equal.rs index 2400d87..8c1c023 100644 --- a/dust-lang/src/instruction/equal.rs +++ b/dust-lang/src/instruction/equal.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/get_local.rs b/dust-lang/src/instruction/get_local.rs index a2fc817..01e358a 100644 --- a/dust-lang/src/instruction/get_local.rs +++ b/dust-lang/src/instruction/get_local.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/jump.rs b/dust-lang/src/instruction/jump.rs index 0bd866c..085034d 100644 --- a/dust-lang/src/instruction/jump.rs +++ b/dust-lang/src/instruction/jump.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/less.rs b/dust-lang/src/instruction/less.rs index d2e5463..04df91b 100644 --- a/dust-lang/src/instruction/less.rs +++ b/dust-lang/src/instruction/less.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/less_equal.rs b/dust-lang/src/instruction/less_equal.rs index 698ef5d..1191575 100644 --- a/dust-lang/src/instruction/less_equal.rs +++ b/dust-lang/src/instruction/less_equal.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/load_boolean.rs b/dust-lang/src/instruction/load_boolean.rs index e3675de..9c24599 100644 --- a/dust-lang/src/instruction/load_boolean.rs +++ b/dust-lang/src/instruction/load_boolean.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/load_constant.rs b/dust-lang/src/instruction/load_constant.rs index b6f0f2d..b91da50 100644 --- a/dust-lang/src/instruction/load_constant.rs +++ b/dust-lang/src/instruction/load_constant.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/load_list.rs b/dust-lang/src/instruction/load_list.rs index 3e6b987..095579e 100644 --- a/dust-lang/src/instruction/load_list.rs +++ b/dust-lang/src/instruction/load_list.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/load_self.rs b/dust-lang/src/instruction/load_self.rs index 66cf872..5c81f81 100644 --- a/dust-lang/src/instruction/load_self.rs +++ b/dust-lang/src/instruction/load_self.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/mod.rs b/dust-lang/src/instruction/mod.rs index 05ce6f4..f9ad42f 100644 --- a/dust-lang/src/instruction/mod.rs +++ b/dust-lang/src/instruction/mod.rs @@ -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 { diff --git a/dust-lang/src/instruction/modulo.rs b/dust-lang/src/instruction/modulo.rs index c50205d..f187a60 100644 --- a/dust-lang/src/instruction/modulo.rs +++ b/dust-lang/src/instruction/modulo.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/move.rs b/dust-lang/src/instruction/move.rs index fe00943..6be4cc4 100644 --- a/dust-lang/src/instruction/move.rs +++ b/dust-lang/src/instruction/move.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/multiply.rs b/dust-lang/src/instruction/multiply.rs index 023a4d3..e00ae0b 100644 --- a/dust-lang/src/instruction/multiply.rs +++ b/dust-lang/src/instruction/multiply.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/negate.rs b/dust-lang/src/instruction/negate.rs index 1340c9a..1979b6a 100644 --- a/dust-lang/src/instruction/negate.rs +++ b/dust-lang/src/instruction/negate.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/not.rs b/dust-lang/src/instruction/not.rs index 805e7d1..b67f3bc 100644 --- a/dust-lang/src/instruction/not.rs +++ b/dust-lang/src/instruction/not.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/options.rs b/dust-lang/src/instruction/options.rs index 01858fe..f3f2b19 100644 --- a/dust-lang/src/instruction/options.rs +++ b/dust-lang/src/instruction/options.rs @@ -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) } } diff --git a/dust-lang/src/instruction/return.rs b/dust-lang/src/instruction/return.rs index 557d045..d38dc4e 100644 --- a/dust-lang/src/instruction/return.rs +++ b/dust-lang/src/instruction/return.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/set_local.rs b/dust-lang/src/instruction/set_local.rs index 6f1c747..1c2f8a3 100644 --- a/dust-lang/src/instruction/set_local.rs +++ b/dust-lang/src/instruction/set_local.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/subtract.rs b/dust-lang/src/instruction/subtract.rs index 482ce66..e441a18 100644 --- a/dust-lang/src/instruction/subtract.rs +++ b/dust-lang/src/instruction/subtract.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/test.rs b/dust-lang/src/instruction/test.rs index 08bf025..420d2d5 100644 --- a/dust-lang/src/instruction/test.rs +++ b/dust-lang/src/instruction/test.rs @@ -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 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, + } } } diff --git a/dust-lang/src/instruction/test_set.rs b/dust-lang/src/instruction/test_set.rs index a9a6faa..81fa8d2 100644 --- a/dust-lang/src/instruction/test_set.rs +++ b/dust-lang/src/instruction/test_set.rs @@ -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 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, + } } } diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 08ec5cc..7e49ed2 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -182,7 +182,7 @@ impl<'a> Vm<'a> { } Operation::SetLocal => { let SetLocal { - register, + register_index: register, local_index, } = SetLocal::from(&instruction);