Continue instruction rewrite
This commit is contained in:
parent
1fa958fd0b
commit
cc069df7ee
@ -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,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user