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 register = self.next_register() - 1;
let set_local = Instruction::from(SetLocal { let set_local = Instruction::from(SetLocal {
register, register_index: register,
local_index, local_index,
}); });

View File

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

View File

@ -1,5 +1,7 @@
use crate::{Instruction, Operation}; use crate::{Instruction, Operation};
use super::InstructionOptions;
pub struct Close { pub struct Close {
pub from: u16, pub from: u16,
pub to: u16, pub to: u16,
@ -8,16 +10,20 @@ pub struct Close {
impl From<&Instruction> for Close { impl From<&Instruction> for Close {
fn from(instruction: &Instruction) -> Self { fn from(instruction: &Instruction) -> Self {
Close { Close {
from: instruction.b(), from: instruction.b,
to: instruction.c(), to: instruction.c,
} }
} }
} }
impl From<Close> for Instruction { impl From<Close> for Instruction {
fn from(r#move: Close) -> Self { fn from(close: Close) -> Self {
*Instruction::new(Operation::Close) Instruction {
.set_b(r#move.from) operation: Operation::CLOSE,
.set_c(r#move.to) 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 { impl From<&Instruction> for Divide {
fn from(instruction: &Instruction) -> Self { fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() { let destination = instruction.a_as_destination();
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let (left, right) = instruction.b_and_c_as_arguments(); let (left, right) = instruction.b_and_c_as_arguments();
Divide { Divide {
@ -25,19 +21,16 @@ impl From<&Instruction> for Divide {
impl From<Divide> for Instruction { impl From<Divide> for Instruction {
fn from(divide: Divide) -> Self { fn from(divide: Divide) -> Self {
let (a, a_is_local) = match divide.destination { let (a, a_options) = divide.destination.as_index_and_a_options();
Destination::Local(local) => (local, true), let (b, b_options) = divide.left.as_index_and_b_options();
Destination::Register(register) => (register, false), let (c, c_options) = divide.right.as_index_and_c_options();
};
*Instruction::new(Operation::Divide) Instruction {
.set_a(a) operation: Operation::DIVIDE,
.set_a_is_local(a_is_local) options: a_options | b_options | c_options,
.set_b(divide.left.index()) a,
.set_b_is_constant(divide.left.is_constant()) b,
.set_b_is_local(divide.left.is_local()) c,
.set_c(divide.right.index()) }
.set_c_is_constant(divide.right.is_constant())
.set_c_is_local(divide.right.is_local())
} }
} }

View File

@ -1,6 +1,9 @@
use crate::{Argument, Instruction, Operation}; use crate::{Argument, Destination, Instruction, Operation};
use super::InstructionOptions;
pub struct Equal { pub struct Equal {
pub destination: Destination,
pub value: bool, pub value: bool,
pub left: Argument, pub left: Argument,
pub right: Argument, pub right: Argument,
@ -8,10 +11,13 @@ pub struct Equal {
impl From<&Instruction> for Equal { impl From<&Instruction> for Equal {
fn from(instruction: &Instruction) -> Self { 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(); let (left, right) = instruction.b_and_c_as_arguments();
Equal { Equal {
value: instruction.a_as_boolean(), destination,
value,
left, left,
right, right,
} }
@ -20,13 +26,21 @@ impl From<&Instruction> for Equal {
impl From<Equal> for Instruction { impl From<Equal> for Instruction {
fn from(equal: Equal) -> Self { fn from(equal: Equal) -> Self {
*Instruction::new(Operation::Equal) let (a, a_options) = equal.destination.as_index_and_a_options();
.set_a_to_boolean(equal.value) let (b, b_options) = equal.left.as_index_and_b_options();
.set_b(equal.left.index()) let (c, c_options) = equal.right.as_index_and_c_options();
.set_b_is_constant(equal.left.is_constant()) let d_options = if equal.value {
.set_b_is_local(equal.left.is_local()) InstructionOptions::D_IS_TRUE
.set_c(equal.right.index()) } else {
.set_c_is_constant(equal.right.is_constant()) InstructionOptions::empty()
.set_c_is_local(equal.right.is_local()) };
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 { impl From<&Instruction> for GetLocal {
fn from(instruction: &Instruction) -> Self { fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() { let destination = instruction.a_as_destination();
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
GetLocal { GetLocal {
destination, destination,
local_index: instruction.b(), local_index: instruction.b,
} }
} }
} }
impl From<GetLocal> for Instruction { impl From<GetLocal> for Instruction {
fn from(get_local: GetLocal) -> Self { fn from(get_local: GetLocal) -> Self {
let (a, a_is_local) = match get_local.destination { let (a, a_options) = get_local.destination.as_index_and_a_options();
Destination::Local(local) => (local, true),
Destination::Register(register) => (register, false),
};
*Instruction::new(Operation::GetLocal) Instruction {
.set_a(a) operation: Operation::GET_LOCAL,
.set_a_is_local(a_is_local) options: a_options,
.set_b(get_local.local_index) a,
b: get_local.local_index,
c: 0,
}
} }
} }

View File

@ -1,5 +1,7 @@
use crate::{Instruction, Operation}; use crate::{Instruction, Operation};
use super::InstructionOptions;
pub struct Jump { pub struct Jump {
pub offset: u16, pub offset: u16,
pub is_positive: bool, pub is_positive: bool,
@ -8,16 +10,20 @@ pub struct Jump {
impl From<&Instruction> for Jump { impl From<&Instruction> for Jump {
fn from(instruction: &Instruction) -> Self { fn from(instruction: &Instruction) -> Self {
Jump { Jump {
offset: instruction.b(), offset: instruction.b,
is_positive: instruction.c_as_boolean(), is_positive: instruction.c != 0,
} }
} }
} }
impl From<Jump> for Instruction { impl From<Jump> for Instruction {
fn from(jump: Jump) -> Self { fn from(jump: Jump) -> Self {
*Instruction::new(Operation::Jump) Instruction {
.set_b(jump.offset) operation: Operation::JUMP,
.set_c_to_boolean(jump.is_positive) 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 struct Less {
pub destination: Destination,
pub value: bool, pub value: bool,
pub left: Argument, pub left: Argument,
pub right: Argument, pub right: Argument,
@ -8,10 +11,13 @@ pub struct Less {
impl From<&Instruction> for Less { impl From<&Instruction> for Less {
fn from(instruction: &Instruction) -> Self { 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(); let (left, right) = instruction.b_and_c_as_arguments();
Less { Less {
value: instruction.a_as_boolean(), destination,
value,
left, left,
right, right,
} }
@ -20,13 +26,21 @@ impl From<&Instruction> for Less {
impl From<Less> for Instruction { impl From<Less> for Instruction {
fn from(less: Less) -> Self { fn from(less: Less) -> Self {
*Instruction::new(Operation::Less) let (a, a_options) = less.destination.as_index_and_a_options();
.set_a_to_boolean(less.value) let (b, b_options) = less.left.as_index_and_b_options();
.set_b(less.left.index()) let (c, c_options) = less.right.as_index_and_c_options();
.set_b_is_constant(less.left.is_constant()) let d_options = if less.value {
.set_b_is_local(less.left.is_local()) InstructionOptions::D_IS_TRUE
.set_c(less.right.index()) } else {
.set_c_is_constant(less.right.is_constant()) InstructionOptions::empty()
.set_c_is_local(less.right.is_local()) };
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 struct LessEqual {
pub destination: Destination,
pub value: bool, pub value: bool,
pub left: Argument, pub left: Argument,
pub right: Argument, pub right: Argument,
@ -8,10 +11,13 @@ pub struct LessEqual {
impl From<&Instruction> for LessEqual { impl From<&Instruction> for LessEqual {
fn from(instruction: &Instruction) -> Self { 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(); let (left, right) = instruction.b_and_c_as_arguments();
LessEqual { LessEqual {
value: instruction.a_as_boolean(), destination,
value,
left, left,
right, right,
} }
@ -20,13 +26,21 @@ impl From<&Instruction> for LessEqual {
impl From<LessEqual> for Instruction { impl From<LessEqual> for Instruction {
fn from(less_equal: LessEqual) -> Self { fn from(less_equal: LessEqual) -> Self {
*Instruction::new(Operation::LessEqual) let (a, a_options) = less_equal.destination.as_index_and_a_options();
.set_a_to_boolean(less_equal.value) let (b, b_options) = less_equal.left.as_index_and_b_options();
.set_b(less_equal.left.index()) let (c, c_options) = less_equal.right.as_index_and_c_options();
.set_b_is_constant(less_equal.left.is_constant()) let d_options = if less_equal.value {
.set_b_is_local(less_equal.left.is_local()) InstructionOptions::D_IS_TRUE
.set_c(less_equal.right.index()) } else {
.set_c_is_constant(less_equal.right.is_constant()) InstructionOptions::empty()
.set_c_is_local(less_equal.right.is_local()) };
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 { impl From<&Instruction> for LoadBoolean {
fn from(instruction: &Instruction) -> Self { fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() { let destination = instruction.a_as_destination();
Destination::Local(instruction.a()) let value = instruction.b != 0;
} else { let jump_next = instruction.c != 0;
Destination::Register(instruction.a())
};
LoadBoolean { LoadBoolean {
destination, destination,
value: instruction.b_as_boolean(), value,
jump_next: instruction.c_as_boolean(), jump_next,
} }
} }
} }
impl From<LoadBoolean> for Instruction { impl From<LoadBoolean> for Instruction {
fn from(load_boolean: LoadBoolean) -> Self { fn from(load_boolean: LoadBoolean) -> Self {
let (a, a_is_local) = match load_boolean.destination { let (a, options) = load_boolean.destination.as_index_and_a_options();
Destination::Local(local) => (local, true), let b = load_boolean.value as u16;
Destination::Register(register) => (register, false), let c = load_boolean.jump_next as u16;
};
*Instruction::new(Operation::LoadBoolean) Instruction {
.set_a(a) operation: Operation::LOAD_BOOLEAN,
.set_a_is_local(a_is_local) options,
.set_b_to_boolean(load_boolean.value) a,
.set_c_to_boolean(load_boolean.jump_next) b,
c,
}
} }
} }

View File

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

View File

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

View File

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

View File

@ -1,18 +1,20 @@
//! An operation and its arguments for the Dust virtual machine. //! 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 //! Bit | Description
//! ----- | ----------- //! ----- | -----------
//! 0-8 | The operation code. //! 0-8 | Operation code
//! 9 | Boolean flag indicating whether the B argument is a constant. //! 9 | Flag for whether A is a local
//! 10 | Boolean flag indicating whether the C argument is a constant. //! 10 | Flag for whether B argument is a constant
//! 11 | Boolean flag indicating whether the A argument is a local. //! 11 | Flag for whether C argument is a local
//! 12 | Boolean flag indicating whether the B argument is a local. //! 12 | Flag for whether B argument is a constant
//! 13 | Boolean flag indicating whether the C argument is a local. //! 13 | Flag for whether C argument is a local
//! 17-32 | The A argument, //! 14 | D Argument
//! 33-48 | The B argument. //! 15-16 | Unused
//! 49-63 | The C argument. //! 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 //! 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 //! 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;
mod call_native; mod call_native;
mod close; mod close;
mod define_local;
mod divide; mod divide;
mod equal; mod equal;
mod get_local; mod get_local;
@ -79,13 +80,10 @@ mod subtract;
mod test; mod test;
mod test_set; mod test_set;
use std::fmt::{self, Debug, Display, Formatter};
pub use add::Add; pub use add::Add;
pub use call::Call; pub use call::Call;
pub use call_native::CallNative; pub use call_native::CallNative;
pub use close::Close; pub use close::Close;
pub use define_local::DefineLocal;
pub use divide::Divide; pub use divide::Divide;
pub use equal::Equal; pub use equal::Equal;
pub use get_local::GetLocal; pub use get_local::GetLocal;
@ -110,6 +108,7 @@ pub use test::Test;
pub use test_set::TestSet; pub use test_set::TestSet;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::{self, Debug, Display, Formatter};
use crate::NativeFunction; use crate::NativeFunction;
@ -165,14 +164,6 @@ impl Instruction {
Instruction::from(LoadSelf { destination }) 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 { pub fn get_local(destination: Destination, local_index: u16) -> Instruction {
Instruction::from(GetLocal { Instruction::from(GetLocal {
destination, destination,
@ -183,7 +174,7 @@ impl Instruction {
pub fn set_local(register: u16, local_index: u16) -> Instruction { pub fn set_local(register: u16, local_index: u16) -> Instruction {
Instruction::from(SetLocal { Instruction::from(SetLocal {
local_index, local_index,
register, register_index: register,
}) })
} }
@ -242,16 +233,46 @@ impl Instruction {
}) })
} }
pub fn equal(value: bool, left: Argument, right: Argument) -> Instruction { pub fn equal(
Instruction::from(Equal { value, left, right }) 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 { pub fn less(
Instruction::from(Less { value, left, right }) 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 { pub fn less_equal(
Instruction::from(LessEqual { value, left, right }) destination: Destination,
value: bool,
left: Argument,
right: Argument,
) -> Instruction {
Instruction::from(LessEqual {
destination,
value,
left,
right,
})
} }
pub fn negate(destination: Destination, argument: Argument) -> Instruction { pub fn negate(destination: Destination, argument: Argument) -> Instruction {
@ -460,7 +481,7 @@ impl Instruction {
} }
Operation::SET_LOCAL => { Operation::SET_LOCAL => {
let SetLocal { let SetLocal {
register, register_index: register,
local_index, local_index,
} = SetLocal::from(self); } = SetLocal::from(self);
@ -531,22 +552,37 @@ impl Instruction {
format!("if {bang}{argument} {{ JUMP +1 }} else {{ {destination} = {argument} }}") format!("if {bang}{argument} {{ JUMP +1 }} else {{ {destination} = {argument} }}")
} }
Operation::EQUAL => { 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 { "!=" }; let comparison_symbol = if value { "==" } else { "!=" };
format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}") format!("{destination} = {left} {comparison_symbol} {right}")
} }
Operation::LESS => { 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 { ">=" }; let comparison_symbol = if value { "<" } else { ">=" };
format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}") format!("{destination} {left} {comparison_symbol} {right}")
} }
Operation::LESS_EQUAL => { 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 { ">" }; let comparison_symbol = if value { "<=" } else { ">" };
format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}") format!("{destination} {left} {comparison_symbol} {right}")
} }
Operation::NEGATE => { Operation::NEGATE => {
let Negate { let Negate {

View File

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

View File

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

View File

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

View File

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

View File

@ -12,7 +12,7 @@ bitflags! {
const C_IS_CONSTANT = 0b00001000; const C_IS_CONSTANT = 0b00001000;
const C_IS_LOCAL = 0b00010000; 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 { 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 crate::{Instruction, Operation};
use super::InstructionOptions;
pub struct Return { pub struct Return {
pub should_return_value: bool, pub should_return_value: bool,
} }
impl From<&Instruction> for Return { impl From<&Instruction> for Return {
fn from(instruction: &Instruction) -> Self { fn from(instruction: &Instruction) -> Self {
let should_return_value = instruction.b != 0;
Return { Return {
should_return_value: instruction.b_as_boolean(), should_return_value,
} }
} }
} }
impl From<Return> for Instruction { impl From<Return> for Instruction {
fn from(r#return: Return) -> Self { 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 crate::{Instruction, Operation};
use super::InstructionOptions;
pub struct SetLocal { pub struct SetLocal {
pub register: u16, pub register_index: u16,
pub local_index: u16, pub local_index: u16,
} }
impl From<&Instruction> for SetLocal { impl From<&Instruction> for SetLocal {
fn from(instruction: &Instruction) -> Self { fn from(instruction: &Instruction) -> Self {
let register_index = instruction.b;
let local_index = instruction.c;
SetLocal { SetLocal {
register: instruction.a(), register_index,
local_index: instruction.b(), local_index,
} }
} }
} }
impl From<SetLocal> for Instruction { impl From<SetLocal> for Instruction {
fn from(set_local: SetLocal) -> Self { fn from(set_local: SetLocal) -> Self {
*Instruction::new(Operation::SetLocal) let b = set_local.register_index;
.set_a(set_local.register) let c = set_local.local_index;
.set_b(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 struct Subtract {
pub destination: Destination, pub destination: Destination,
@ -8,11 +8,7 @@ pub struct Subtract {
impl From<&Instruction> for Subtract { impl From<&Instruction> for Subtract {
fn from(instruction: &Instruction) -> Self { fn from(instruction: &Instruction) -> Self {
let destination = if instruction.a_is_local() { let destination = instruction.a_as_destination();
Destination::Local(instruction.a())
} else {
Destination::Register(instruction.a())
};
let (left, right) = instruction.b_and_c_as_arguments(); let (left, right) = instruction.b_and_c_as_arguments();
Subtract { Subtract {
@ -25,19 +21,16 @@ impl From<&Instruction> for Subtract {
impl From<Subtract> for Instruction { impl From<Subtract> for Instruction {
fn from(subtract: Subtract) -> Self { fn from(subtract: Subtract) -> Self {
let (a, a_is_local) = match subtract.destination { let (a, a_options) = subtract.destination.as_index_and_a_options();
Destination::Local(local) => (local, true), let (b, b_options) = subtract.left.as_index_and_b_options();
Destination::Register(register) => (register, false), let (c, c_options) = subtract.right.as_index_and_c_options();
};
*Instruction::new(crate::Operation::Subtract) Instruction {
.set_a(a) operation: Operation::SUBTRACT,
.set_a_is_local(a_is_local) options: a_options | b_options | c_options,
.set_b(subtract.left.index()) a,
.set_b_is_constant(subtract.left.is_constant()) b,
.set_b_is_local(subtract.left.is_local()) c,
.set_c(subtract.right.index()) }
.set_c_is_constant(subtract.right.is_constant())
.set_c_is_local(subtract.right.is_local())
} }
} }

View File

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

View File

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

View File

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