diff --git a/Cargo.lock b/Cargo.lock index b9433d2..e689604 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,6 +85,15 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -189,6 +198,7 @@ name = "dust-lang" version = "0.5.0" dependencies = [ "annotate-snippets", + "bitflags", "colored", "env_logger", "getrandom", diff --git a/dust-lang/Cargo.toml b/dust-lang/Cargo.toml index 0edf1b0..8cdc91d 100644 --- a/dust-lang/Cargo.toml +++ b/dust-lang/Cargo.toml @@ -22,6 +22,7 @@ smallvec = { version = "1.13.2", features = ["serde"] } smartstring = { version = "1.0.1", features = [ "serde", ], default-features = false } +bitflags = { version = "2.6.0", features = ["serde"] } [dev-dependencies] env_logger = "0.11.5" diff --git a/dust-lang/src/instruction/add.rs b/dust-lang/src/instruction/add.rs index f6da751..d77d562 100644 --- a/dust-lang/src/instruction/add.rs +++ b/dust-lang/src/instruction/add.rs @@ -8,11 +8,7 @@ pub struct Add { impl From<&Instruction> for Add { 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(); Add { @@ -25,19 +21,16 @@ impl From<&Instruction> for Add { impl From for Instruction { fn from(add: Add) -> Self { - let (a, a_is_local) = match add.destination { - Destination::Local(local) => (local, true), - Destination::Register(register) => (register, false), - }; + let (a, a_options) = add.destination.as_index_and_a_options(); + let (b, b_options) = add.left.as_index_and_b_options(); + let (c, c_options) = add.right.as_index_and_c_options(); - *Instruction::new(Operation::Add) - .set_a(a) - .set_a_is_local(a_is_local) - .set_b(add.left.index()) - .set_b_is_constant(add.left.is_constant()) - .set_b_is_local(add.left.is_local()) - .set_c(add.right.index()) - .set_c_is_constant(add.right.is_constant()) - .set_c_is_local(add.right.is_local()) + Instruction { + operation: Operation::ADD, + options: a_options | b_options | c_options, + a, + b, + c, + } } } diff --git a/dust-lang/src/instruction/call.rs b/dust-lang/src/instruction/call.rs index 7fa1247..6145e9e 100644 --- a/dust-lang/src/instruction/call.rs +++ b/dust-lang/src/instruction/call.rs @@ -8,33 +8,25 @@ pub struct Call { impl From<&Instruction> for Call { fn from(instruction: &Instruction) -> Self { - let destination = if instruction.a_is_local() { - Destination::Local(instruction.a()) - } else { - Destination::Register(instruction.a()) - }; - Call { - destination, + destination: instruction.a_as_destination(), function: instruction.b_as_argument(), - argument_count: instruction.c(), + argument_count: instruction.c, } } } impl From for Instruction { fn from(call: Call) -> Self { - let (a, a_is_local) = match call.destination { - Destination::Local(local) => (local, true), - Destination::Register(register) => (register, false), - }; + let (a, a_options) = call.destination.as_index_and_a_options(); + let (b, b_options) = call.function.as_index_and_b_options(); - *Instruction::new(Operation::Call) - .set_a(a) - .set_a_is_local(a_is_local) - .set_b(call.function.index()) - .set_b_is_constant(call.function.is_constant()) - .set_b_is_local(call.function.is_local()) - .set_c(call.argument_count) + Instruction { + operation: Operation::CALL, + options: a_options | b_options, + a, + b, + c: call.argument_count, + } } } diff --git a/dust-lang/src/instruction/mod.rs b/dust-lang/src/instruction/mod.rs index 600d1a9..05ce6f4 100644 --- a/dust-lang/src/instruction/mod.rs +++ b/dust-lang/src/instruction/mod.rs @@ -71,6 +71,8 @@ mod r#move; mod multiply; mod negate; mod not; +mod operation; +mod options; mod r#return; mod set_local; mod subtract; @@ -98,6 +100,8 @@ pub use modulo::Modulo; pub use multiply::Multiply; pub use negate::Negate; pub use not::Not; +pub use operation::Operation; +pub use options::InstructionOptions; pub use r#move::Move; pub use r#return::Return; pub use set_local::SetLocal; @@ -107,19 +111,21 @@ pub use test_set::TestSet; use serde::{Deserialize, Serialize}; -use crate::{NativeFunction, Operation}; +use crate::NativeFunction; /// An operation and its arguments for the Dust virtual machine. /// /// See the [module-level documentation](index.html) for more information. -#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -pub struct Instruction(u64); +#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct Instruction { + operation: Operation, + options: InstructionOptions, + a: u16, + b: u16, + c: u16, +} impl Instruction { - pub fn new(operation: Operation) -> Instruction { - Instruction(operation as u64) - } - pub fn r#move(from: u16, to: u16) -> Instruction { Instruction::from(Move { from, to }) } @@ -296,215 +302,115 @@ impl Instruction { } pub fn destination_as_argument(&self) -> Option { - match self.operation() { - Operation::LoadConstant => Some(Argument::Constant(self.b())), - Operation::GetLocal => Some(Argument::Local(self.b())), - Operation::LoadBoolean - | Operation::LoadList - | Operation::LoadSelf - | Operation::Add - | Operation::Subtract - | Operation::Multiply - | Operation::Divide - | Operation::Modulo - | Operation::Negate - | Operation::Not - | Operation::Call - | Operation::CallNative => Some(Argument::Register(self.a())), + match self.operation { + Operation::LOAD_CONSTANT => Some(Argument::Constant(self.b)), + Operation::GET_LOCAL => Some(Argument::Local(self.b)), + Operation::LOAD_BOOLEAN + | Operation::LOAD_LIST + | Operation::LOAD_SELF + | Operation::ADD + | Operation::SUBTRACT + | Operation::MULTIPLY + | Operation::DIVIDE + | Operation::MODULO + | Operation::NEGATE + | Operation::NOT + | Operation::CALL + | Operation::CALL_NATIVE => Some(Argument::Register(self.a)), _ => None, } } - pub fn b_as_argument(&self) -> Argument { - if self.b_is_constant() { - Argument::Constant(self.b()) - } else if self.b_is_local() { - Argument::Local(self.b()) + pub fn a_as_destination(&self) -> Destination { + if self.options.a_is_local() { + Destination::Local(self.a) } else { - Argument::Register(self.b()) + Destination::Register(self.a) + } + } + + pub fn b_as_argument(&self) -> Argument { + if self.options.b_is_constant() { + Argument::Constant(self.b) + } else if self.options.b_is_local() { + Argument::Local(self.b) + } else { + Argument::Register(self.b) } } pub fn b_and_c_as_arguments(&self) -> (Argument, Argument) { - let left = if self.b_is_constant() { - Argument::Constant(self.b()) - } else if self.b_is_local() { - Argument::Local(self.b()) + let left = if self.options.b_is_constant() { + Argument::Constant(self.b) + } else if self.options.b_is_local() { + Argument::Local(self.b) } else { - Argument::Register(self.b()) + Argument::Register(self.b) }; - let right = if self.c_is_constant() { - Argument::Constant(self.c()) - } else if self.c_is_local() { - Argument::Local(self.c()) + let right = if self.options.c_is_constant() { + Argument::Constant(self.c) + } else if self.options.c_is_local() { + Argument::Local(self.c) } else { - Argument::Register(self.c()) + Argument::Register(self.c) }; (left, right) } - pub fn operation(&self) -> Operation { - Operation::from((self.0 & 0b11111111) as u8) - } - - pub fn set_b_is_constant(&mut self, boolean: bool) -> &mut Self { - self.0 = (self.0 & !(1 << 9)) | ((boolean as u64) << 9); - - self - } - - pub fn set_c_is_constant(&mut self, boolean: bool) -> &mut Self { - self.0 = (self.0 & !(1 << 10)) | ((boolean as u64) << 10); - - self - } - - pub fn set_a_is_local(&mut self, boolean: bool) -> &mut Self { - self.0 = (self.0 & !(1 << 11)) | ((boolean as u64) << 11); - - self - } - - pub fn set_b_is_local(&mut self, boolean: bool) -> &mut Self { - self.0 = (self.0 & !(1 << 12)) | ((boolean as u64) << 12); - - self - } - - pub fn set_c_is_local(&mut self, boolean: bool) -> &mut Self { - self.0 = (self.0 & !(1 << 13)) | ((boolean as u64) << 13); - - self - } - - pub fn a(&self) -> u16 { - ((self.0 >> 16) & 0b1111111111111111) as u16 - } - - pub fn a_as_boolean(&self) -> bool { - self.a() != 0 - } - - pub fn set_a(&mut self, a: u16) -> &mut Self { - self.0 = (self.0 & !(0b1111111111111111 << 16)) | ((a as u64) << 16); - - self - } - - pub fn set_a_to_boolean(&mut self, boolean: bool) -> &mut Self { - self.0 = (self.0 & !(0b1111111111111111 << 16)) | ((boolean as u64) << 16); - - self - } - - pub fn b(&self) -> u16 { - ((self.0 >> 32) & 0b1111111111111111) as u16 - } - - pub fn b_as_boolean(&self) -> bool { - self.b() != 0 - } - - pub fn set_b(&mut self, b: u16) -> &mut Self { - self.0 = (self.0 & !(0b1111111111111111 << 32)) | ((b as u64) << 32); - - self - } - - pub fn set_b_to_boolean(&mut self, boolean: bool) -> &mut Self { - self.0 = (self.0 & !(0b1111111111111111 << 32)) | ((boolean as u64) << 32); - - self - } - - pub fn c(&self) -> u16 { - ((self.0 >> 48) & 0b1111111111111111) as u16 - } - - pub fn c_as_boolean(&self) -> bool { - self.c() != 0 - } - - pub fn set_c(&mut self, c: u16) -> &mut Self { - self.0 = (self.0 & !(0b1111111111111111 << 48)) | ((c as u64) << 48); - - self - } - - pub fn set_c_to_boolean(&mut self, boolean: bool) -> &mut Self { - self.0 = (self.0 & !(0b1111111111111111 << 48)) | ((boolean as u64) << 48); - - self - } - - pub fn b_is_constant(&self) -> bool { - (self.0 >> 9) & 1 == 1 - } - - pub fn c_is_constant(&self) -> bool { - (self.0 >> 10) & 1 == 1 - } - - pub fn a_is_local(&self) -> bool { - (self.0 >> 11) & 1 == 1 - } - - pub fn b_is_local(&self) -> bool { - (self.0 >> 12) & 1 == 1 - } - - pub fn c_is_local(&self) -> bool { - (self.0 >> 13) & 1 == 1 - } - pub fn yields_value(&self) -> bool { - match self.operation() { - Operation::LoadBoolean - | Operation::LoadConstant - | Operation::LoadList - | Operation::LoadSelf - | Operation::GetLocal - | Operation::Add - | Operation::Subtract - | Operation::Multiply - | Operation::Divide - | Operation::Modulo - | Operation::Negate - | Operation::Not - | Operation::Call => true, - Operation::Move - | Operation::Close - | Operation::DefineLocal - | Operation::SetLocal - | Operation::Equal - | Operation::Less - | Operation::LessEqual - | Operation::Test - | Operation::TestSet - | Operation::Jump - | Operation::Return => false, - Operation::CallNative => { - let function = NativeFunction::from(self.b()); + match self.operation { + Operation::LOAD_BOOLEAN + | Operation::LOAD_CONSTANT + | Operation::LOAD_LIST + | Operation::LOAD_SELF + | Operation::GET_LOCAL + | Operation::ADD + | Operation::SUBTRACT + | Operation::MULTIPLY + | Operation::DIVIDE + | Operation::MODULO + | Operation::NEGATE + | Operation::NOT + | Operation::CALL => true, + Operation::MOVE + | Operation::CLOSE + | Operation::SET_LOCAL + | Operation::EQUAL + | Operation::LESS + | Operation::LESS_EQUAL + | Operation::TEST + | Operation::TEST_SET + | Operation::JUMP + | Operation::RETURN => false, + Operation::CALL_NATIVE => { + let function = NativeFunction::from(self.b); function.returns_value() } + _ => { + if cfg!(debug_assertions) { + panic!("Unknown operation {}", self.operation); + } else { + false + } + } } } pub fn disassembly_info(&self) -> String { - match self.operation() { - Operation::Move => { + match self.operation { + Operation::MOVE => { let Move { from, to } = Move::from(self); format!("R{to} = R{from}") } - Operation::Close => { + Operation::CLOSE => { let Close { from, to } = Close::from(self); format!("R{from}..R{to}") } - Operation::LoadBoolean => { + Operation::LOAD_BOOLEAN => { let LoadBoolean { destination, value, @@ -517,7 +423,7 @@ impl Instruction { format!("{destination} = {value}") } } - Operation::LoadConstant => { + Operation::LOAD_CONSTANT => { let LoadConstant { destination, constant_index, @@ -530,7 +436,7 @@ impl Instruction { format!("{destination} = C{constant_index}") } } - Operation::LoadList => { + Operation::LOAD_LIST => { let LoadList { destination, start_register, @@ -539,25 +445,12 @@ impl Instruction { format!("{destination} = [R{start_register}..=R{end_register}]",) } - Operation::LoadSelf => { + Operation::LOAD_SELF => { let LoadSelf { destination } = LoadSelf::from(self); format!("{destination} = self") } - Operation::DefineLocal => { - let DefineLocal { - register, - local_index, - is_mutable, - } = DefineLocal::from(self); - - if is_mutable { - format!("mut L{local_index} = R{register}") - } else { - format!("L{local_index} = R{register}") - } - } - Operation::GetLocal => { + Operation::GET_LOCAL => { let GetLocal { destination, local_index, @@ -565,7 +458,7 @@ impl Instruction { format!("{destination} = L{local_index}") } - Operation::SetLocal => { + Operation::SET_LOCAL => { let SetLocal { register, local_index, @@ -573,7 +466,7 @@ impl Instruction { format!("L{local_index} = R{register}") } - Operation::Add => { + Operation::ADD => { let Add { destination, left, @@ -582,7 +475,7 @@ impl Instruction { format!("{destination} = {left} + {right}") } - Operation::Subtract => { + Operation::SUBTRACT => { let Subtract { destination, left, @@ -591,7 +484,7 @@ impl Instruction { format!("{destination} = {left} - {right}") } - Operation::Multiply => { + Operation::MULTIPLY => { let Multiply { destination, left, @@ -600,7 +493,7 @@ impl Instruction { format!("{destination} = {left} * {right}") } - Operation::Divide => { + Operation::DIVIDE => { let Divide { destination, left, @@ -609,7 +502,7 @@ impl Instruction { format!("{destination} = {left} / {right}") } - Operation::Modulo => { + Operation::MODULO => { let Modulo { destination, left, @@ -618,7 +511,7 @@ impl Instruction { format!("{destination} = {left} % {right}") } - Operation::Test => { + Operation::TEST => { let Test { argument, test_value: value, @@ -627,7 +520,7 @@ impl Instruction { format!("if {bang}{argument} {{ JUMP +1 }}",) } - Operation::TestSet => { + Operation::TEST_SET => { let TestSet { destination, argument, @@ -637,25 +530,25 @@ impl Instruction { format!("if {bang}{argument} {{ JUMP +1 }} else {{ {destination} = {argument} }}") } - Operation::Equal => { + Operation::EQUAL => { let Equal { value, left, right } = Equal::from(self); let comparison_symbol = if value { "==" } else { "!=" }; format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}") } - Operation::Less => { + Operation::LESS => { let Less { value, left, right } = Less::from(self); let comparison_symbol = if value { "<" } else { ">=" }; format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}") } - Operation::LessEqual => { + Operation::LESS_EQUAL => { let LessEqual { value, left, right } = LessEqual::from(self); let comparison_symbol = if value { "<=" } else { ">" }; format!("if {left} {comparison_symbol} {right} {{ JUMP +1 }}") } - Operation::Negate => { + Operation::NEGATE => { let Negate { destination, argument, @@ -663,7 +556,7 @@ impl Instruction { format!("{destination} = -{argument}") } - Operation::Not => { + Operation::NOT => { let Not { destination, argument, @@ -671,7 +564,7 @@ impl Instruction { format!("{destination} = !{argument}") } - Operation::Jump => { + Operation::JUMP => { let Jump { offset, is_positive, @@ -683,7 +576,7 @@ impl Instruction { format!("JUMP -{offset}") } } - Operation::Call => { + Operation::CALL => { let Call { destination, function, @@ -694,7 +587,7 @@ impl Instruction { format!("{destination} = {function}(R{arguments_start}..R{arguments_end})") } - Operation::CallNative => { + Operation::CALL_NATIVE => { let CallNative { destination, function, @@ -709,7 +602,7 @@ impl Instruction { format!("{function}(R{arguments_start}..R{arguments_end})") } } - Operation::Return => { + Operation::RETURN => { let Return { should_return_value, } = Return::from(self); @@ -720,19 +613,20 @@ impl Instruction { "".to_string() } } + _ => { + if cfg!(debug_assertions) { + panic!("Unknown operation {}", self.operation); + } else { + "RETURN".to_string() + } + } } } } -impl From<&Instruction> for u64 { - fn from(instruction: &Instruction) -> Self { - instruction.0 - } -} - impl Debug for Instruction { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{} {}", self.operation(), self.disassembly_info()) + write!(f, "{} {}", self.operation, self.disassembly_info()) } } @@ -757,6 +651,13 @@ impl Destination { pub fn is_register(&self) -> bool { matches!(self, Destination::Register(_)) } + + pub fn as_index_and_a_options(&self) -> (u16, InstructionOptions) { + match self { + Destination::Local(index) => (*index, InstructionOptions::A_IS_LOCAL), + Destination::Register(index) => (*index, InstructionOptions::empty()), + } + } } impl Display for Destination { @@ -795,6 +696,22 @@ impl Argument { pub fn is_register(&self) -> bool { matches!(self, Argument::Register(_)) } + + pub fn as_index_and_b_options(&self) -> (u16, InstructionOptions) { + match self { + Argument::Constant(index) => (*index, InstructionOptions::B_IS_CONSTANT), + Argument::Local(index) => (*index, InstructionOptions::B_IS_LOCAL), + Argument::Register(index) => (*index, InstructionOptions::empty()), + } + } + + pub fn as_index_and_c_options(&self) -> (u16, InstructionOptions) { + match self { + Argument::Constant(index) => (*index, InstructionOptions::C_IS_CONSTANT), + Argument::Local(index) => (*index, InstructionOptions::C_IS_LOCAL), + Argument::Register(index) => (*index, InstructionOptions::empty()), + } + } } impl Display for Argument { diff --git a/dust-lang/src/instruction/operation.rs b/dust-lang/src/instruction/operation.rs new file mode 100644 index 0000000..0e9bbec --- /dev/null +++ b/dust-lang/src/instruction/operation.rs @@ -0,0 +1,83 @@ +//! Part of an [Instruction][crate::Instruction] that is encoded as a single byte. + +use std::fmt::{self, Debug, Display, Formatter}; + +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct Operation(u8); + +impl Operation { + pub const MOVE: Operation = Operation(0); + pub const CLOSE: Operation = Operation(1); + pub const LOAD_BOOLEAN: Operation = Operation(2); + pub const LOAD_CONSTANT: Operation = Operation(3); + pub const LOAD_LIST: Operation = Operation(4); + pub const LOAD_SELF: Operation = Operation(5); + pub const GET_LOCAL: Operation = Operation(6); + pub const SET_LOCAL: Operation = Operation(7); + pub const ADD: Operation = Operation(8); + pub const SUBTRACT: Operation = Operation(9); + pub const MULTIPLY: Operation = Operation(10); + pub const DIVIDE: Operation = Operation(11); + pub const MODULO: Operation = Operation(12); + pub const TEST: Operation = Operation(13); + pub const TEST_SET: Operation = Operation(14); + pub const EQUAL: Operation = Operation(15); + pub const LESS: Operation = Operation(16); + pub const LESS_EQUAL: Operation = Operation(17); + pub const NEGATE: Operation = Operation(18); + pub const NOT: Operation = Operation(19); + pub const CALL: Operation = Operation(20); + pub const CALL_NATIVE: Operation = Operation(21); + pub const JUMP: Operation = Operation(22); + pub const RETURN: Operation = Operation(23); + + pub fn name(self) -> &'static str { + match self { + Self::MOVE => "MOVE", + Self::CLOSE => "CLOSE", + Self::LOAD_BOOLEAN => "LOAD_BOOLEAN", + Self::LOAD_CONSTANT => "LOAD_CONSTANT", + Self::LOAD_LIST => "LOAD_LIST", + Self::LOAD_SELF => "LOAD_SELF", + Self::GET_LOCAL => "GET_LOCAL", + Self::SET_LOCAL => "SET_LOCAL", + Self::ADD => "ADD", + Self::SUBTRACT => "SUBTRACT", + Self::MULTIPLY => "MULTIPLY", + Self::DIVIDE => "DIVIDE", + Self::MODULO => "MODULO", + Self::TEST => "TEST", + Self::TEST_SET => "TEST_SET", + Self::EQUAL => "EQUAL", + Self::LESS => "LESS", + Self::LESS_EQUAL => "LESS_EQUAL", + Self::NEGATE => "NEGATE", + Self::NOT => "NOT", + Self::CALL => "CALL", + Self::CALL_NATIVE => "CALL_NATIVE", + Self::JUMP => "JUMP", + Self::RETURN => "RETURN", + _ => { + if cfg!(debug_assertions) { + panic!("Unknown operation code {}", self.0); + } else { + "RETURN" + } + } + } + } +} + +impl Debug for Operation { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Operation({})", self.name()) + } +} + +impl Display for Operation { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self.name()) + } +} diff --git a/dust-lang/src/instruction/options.rs b/dust-lang/src/instruction/options.rs new file mode 100644 index 0000000..01858fe --- /dev/null +++ b/dust-lang/src/instruction/options.rs @@ -0,0 +1,43 @@ +use bitflags::bitflags; +use serde::{Deserialize, Serialize}; + +bitflags! { + #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] + pub struct InstructionOptions: u8 { + const A_IS_LOCAL = 0b00000001; + + const B_IS_CONSTANT = 0b00000010; + const B_IS_LOCAL = 0b00000100; + + const C_IS_CONSTANT = 0b00001000; + const C_IS_LOCAL = 0b00010000; + + const D_FIELD = 0b00100000; + } +} + +impl InstructionOptions { + pub fn a_is_local(self) -> bool { + self.contains(Self::A_IS_LOCAL) + } + + pub fn b_is_constant(self) -> bool { + self.contains(Self::B_IS_CONSTANT) + } + + pub fn b_is_local(self) -> bool { + self.contains(Self::B_IS_LOCAL) + } + + pub fn c_is_constant(self) -> bool { + self.contains(Self::C_IS_CONSTANT) + } + + pub fn c_is_local(self) -> bool { + self.contains(Self::C_IS_LOCAL) + } + + pub fn d(self) -> bool { + self.contains(Self::D_FIELD) + } +} diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 1edd043..19fbef4 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -35,7 +35,6 @@ pub mod dust_error; pub mod instruction; pub mod lexer; pub mod native_function; -pub mod operation; pub mod optimize; pub mod scope; pub mod token; @@ -47,10 +46,9 @@ pub use crate::chunk::{Chunk, Local}; pub use crate::compiler::{compile, CompileError, Compiler}; pub use crate::disassembler::Disassembler; pub use crate::dust_error::{AnnotatedError, DustError}; -pub use crate::instruction::{Argument, Destination, Instruction}; +pub use crate::instruction::{Argument, Destination, Instruction, Operation}; pub use crate::lexer::{lex, LexError, Lexer}; pub use crate::native_function::{NativeFunction, NativeFunctionError}; -pub use crate::operation::Operation; pub use crate::optimize::{optimize_control_flow, optimize_set_local}; pub use crate::r#type::{EnumType, FunctionType, StructType, Type, TypeConflict}; pub use crate::scope::Scope; diff --git a/dust-lang/src/operation.rs b/dust-lang/src/operation.rs deleted file mode 100644 index 1b35e71..0000000 --- a/dust-lang/src/operation.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! Part of an [Instruction][crate::Instruction] that is encoded as a single byte. - -use std::fmt::{self, Display, Formatter}; - -macro_rules! define_operation { - ($(($name:ident, $byte:literal, $str:expr)),*) => { - /// Part of an [Instruction][crate::Instruction] that is encoded as a single byte. - #[derive(Clone, Copy, Debug, PartialEq)] - pub enum Operation { - $( - $name = $byte as isize, - )* - } - - impl From for Operation { - fn from(byte: u8) -> Self { - match byte { - $( - $byte => Operation::$name, - )* - _ => { - if cfg!(test) { - panic!("Invalid operation byte: {}", byte) - } else { - Operation::Return - } - } - } - } - } - - impl From for u8 { - fn from(operation: Operation) -> Self { - match operation { - $( - Operation::$name => $byte, - )* - } - } - } - - impl Display for Operation { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - $( - Operation::$name => write!(f, "{}", $str), - )* - } - } - } - } -} - -define_operation! { - (Move, 0, "MOVE"), - (Close, 1, "CLOSE"), - - (LoadBoolean, 2, "LOAD_BOOLEAN"), - (LoadConstant, 3, "LOAD_CONSTANT"), - (LoadList, 4, "LOAD_LIST"), - (LoadSelf, 5, "LOAD_SELF"), - - (DefineLocal, 6, "DEFINE_LOCAL"), - (GetLocal, 7, "GET_LOCAL"), - (SetLocal, 8, "SET_LOCAL"), - - (Add, 9, "ADD"), - (Subtract, 10, "SUBTRACT"), - (Multiply, 11, "MULTIPLY"), - (Divide, 12, "DIVIDE"), - (Modulo, 13, "MODULO"), - - (Test, 14, "TEST"), - (TestSet, 15, "TEST_SET"), - - (Equal, 16, "EQUAL"), - (Less, 17, "LESS"), - (LessEqual, 18, "LESS_EQUAL"), - - (Negate, 19, "NEGATE"), - (Not, 20, "NOT"), - - (Call, 21, "CALL"), - (CallNative, 22, "CALL_NATIVE"), - - (Jump, 23, "JUMP"), - (Return, 24, "RETURN") -} - -impl Operation { - pub fn is_math(&self) -> bool { - matches!( - self, - Operation::Add - | Operation::Subtract - | Operation::Multiply - | Operation::Divide - | Operation::Modulo - ) - } - - pub fn is_comparison(&self) -> bool { - matches!( - self, - Operation::Equal | Operation::Less | Operation::LessEqual - ) - } - - pub fn is_test(&self) -> bool { - matches!(self, Operation::Test | Operation::TestSet) - } -}