From 1777ad298be95436560df41de5cc4fc4fbfa00e8 Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 11 Dec 2024 09:26:38 -0500 Subject: [PATCH] Experiment wih more optimizations --- dust-lang/src/compiler/mod.rs | 56 +++--- dust-lang/src/compiler/optimize.rs | 18 +- dust-lang/src/instruction/add.rs | 2 +- dust-lang/src/instruction/call.rs | 2 +- dust-lang/src/instruction/call_native.rs | 2 +- dust-lang/src/instruction/close.rs | 2 +- dust-lang/src/instruction/divide.rs | 2 +- dust-lang/src/instruction/equal.rs | 2 +- dust-lang/src/instruction/get_local.rs | 2 +- dust-lang/src/instruction/jump.rs | 2 +- dust-lang/src/instruction/less.rs | 2 +- dust-lang/src/instruction/less_equal.rs | 2 +- dust-lang/src/instruction/load_boolean.rs | 2 +- dust-lang/src/instruction/load_constant.rs | 2 +- dust-lang/src/instruction/load_list.rs | 2 +- dust-lang/src/instruction/load_self.rs | 2 +- dust-lang/src/instruction/mod.rs | 147 +++++++------- dust-lang/src/instruction/modulo.rs | 2 +- dust-lang/src/instruction/move.rs | 2 +- dust-lang/src/instruction/multiply.rs | 2 +- dust-lang/src/instruction/negate.rs | 2 +- dust-lang/src/instruction/not.rs | 2 +- dust-lang/src/instruction/operation.rs | 218 ++++++--------------- dust-lang/src/instruction/return.rs | 2 +- dust-lang/src/instruction/set_local.rs | 2 +- dust-lang/src/instruction/subtract.rs | 2 +- dust-lang/src/instruction/test.rs | 2 +- dust-lang/src/instruction/test_set.rs | 2 +- dust-lang/src/vm.rs | 75 ++++--- 29 files changed, 239 insertions(+), 323 deletions(-) diff --git a/dust-lang/src/compiler/mod.rs b/dust-lang/src/compiler/mod.rs index 1ff5d79..5b3dea8 100644 --- a/dust-lang/src/compiler/mod.rs +++ b/dust-lang/src/compiler/mod.rs @@ -301,7 +301,7 @@ impl<'src> Compiler<'src> { } fn get_last_operations(&self) -> Option<[Operation; COUNT]> { - let mut n_operations = [Operation::Return; COUNT]; + let mut n_operations = [Operation::RETURN; COUNT]; for (nth, operation) in n_operations.iter_mut().rev().zip( self.instructions @@ -338,14 +338,14 @@ impl<'src> Compiler<'src> { let operation = instruction.operation(); - if let Operation::LoadList = operation { + if let Operation::LOAD_LIST = operation { let LoadList { start_register, .. } = LoadList::from(instruction); let item_type = self.get_register_type(start_register)?; return Ok(Type::List(Box::new(item_type))); } - if let Operation::LoadSelf = operation { + if let Operation::LOAD_SELF = operation { return Ok(Type::SelfChunk); } @@ -612,28 +612,28 @@ impl<'src> Compiler<'src> { instruction: &Instruction, ) -> Result<(Argument, bool), CompileError> { let (argument, push_back) = match instruction.operation() { - Operation::LoadConstant => (Argument::Constant(instruction.b_field()), false), - Operation::GetLocal => { + Operation::LOAD_CONSTANT => (Argument::Constant(instruction.b_field()), false), + Operation::GET_LOCAL => { let local_index = instruction.b_field(); let (local, _) = self.get_local(local_index)?; (Argument::Register(local.register_index), false) } - Operation::LoadBoolean - | Operation::LoadList - | Operation::LoadSelf - | Operation::Add - | Operation::Subtract - | Operation::Multiply - | Operation::Divide - | Operation::Modulo - | Operation::Equal - | Operation::Less - | Operation::LessEqual - | Operation::Negate - | Operation::Not - | Operation::Call => (Argument::Register(instruction.a_field()), true), - Operation::CallNative => { + Operation::LOAD_BOOLEAN + | Operation::LOAD_LIST + | Operation::LOAD_SELF + | Operation::ADD + | Operation::SUBTRACT + | Operation::MULTIPLY + | Operation::DIVIDE + | Operation::MODULO + | Operation::EQUAL + | Operation::LESS + | Operation::LESS_EQUAL + | Operation::NEGATE + | Operation::NOT + | Operation::CALL => (Argument::Register(instruction.a_field()), true), + Operation::CALL_NATIVE => { let function = NativeFunction::from(instruction.b_field()); if function.returns_value() { @@ -665,7 +665,7 @@ impl<'src> Compiler<'src> { position: self.previous_position, })?; let (left, push_back_left) = self.handle_binary_argument(&left_instruction)?; - let left_is_mutable_local = if let Operation::GetLocal = left_instruction.operation() { + let left_is_mutable_local = if let Operation::GET_LOCAL = left_instruction.operation() { let GetLocal { local_index, .. } = GetLocal::from(&left_instruction); self.locals @@ -812,7 +812,7 @@ impl<'src> Compiler<'src> { } fn parse_comparison_binary(&mut self) -> Result<(), CompileError> { - if let Some([Operation::Equal | Operation::Less | Operation::LessEqual, _, _]) = + if let Some([Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL, _, _]) = self.get_last_operations() { return Err(CompileError::CannotChainComparison { @@ -886,7 +886,7 @@ impl<'src> Compiler<'src> { fn parse_logical_binary(&mut self) -> Result<(), CompileError> { let is_logic_chain = matches!( self.get_last_operations(), - Some([Operation::Test, Operation::Jump, _]) + Some([Operation::TEST, Operation::JUMP, _]) ); let (mut left_instruction, left_type, left_position) = self.pop_last_instruction()?; @@ -1204,7 +1204,7 @@ impl<'src> Compiler<'src> { match else_block_distance { 0 => {} 1 => { - if let Some([Operation::LoadBoolean | Operation::LoadConstant]) = + if let Some([Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT]) = self.get_last_operations() { let (mut loader, _, _) = self.instructions.last_mut().unwrap(); @@ -1291,10 +1291,10 @@ impl<'src> Compiler<'src> { if matches!( self.get_last_operations(), Some([ - Operation::Equal | Operation::Less | Operation::LessEqual, - Operation::Jump, - Operation::LoadBoolean, - Operation::LoadBoolean, + Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL, + Operation::JUMP, + Operation::LOAD_BOOLEAN, + Operation::LOAD_BOOLEAN, ],) ) { self.instructions.pop(); diff --git a/dust-lang/src/compiler/optimize.rs b/dust-lang/src/compiler/optimize.rs index b2008ee..c4ff45e 100644 --- a/dust-lang/src/compiler/optimize.rs +++ b/dust-lang/src/compiler/optimize.rs @@ -29,11 +29,11 @@ pub fn optimize_test_with_explicit_booleans(compiler: &mut Compiler) { if matches!( compiler.get_last_operations(), Some([ - Operation::Equal | Operation::Less | Operation::LessEqual, - Operation::Test, - Operation::Jump, - Operation::LoadBoolean, - Operation::LoadBoolean, + Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL, + Operation::TEST, + Operation::JUMP, + Operation::LOAD_BOOLEAN, + Operation::LOAD_BOOLEAN, ]) ) { log::debug!("Removing redundant test, jump and boolean loaders after comparison"); @@ -70,10 +70,10 @@ pub fn optimize_test_with_loader_arguments(compiler: &mut Compiler) { if !matches!( compiler.get_last_operations(), Some([ - Operation::Test, - Operation::Jump, - Operation::LoadBoolean | Operation::LoadConstant, - Operation::LoadBoolean | Operation::LoadConstant, + Operation::TEST, + Operation::JUMP, + Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT, + Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT, ]) ) { return; diff --git a/dust-lang/src/instruction/add.rs b/dust-lang/src/instruction/add.rs index dcd2646..ffd0cd8 100644 --- a/dust-lang/src/instruction/add.rs +++ b/dust-lang/src/instruction/add.rs @@ -21,7 +21,7 @@ impl From<&Instruction> for Add { impl From for Instruction { fn from(add: Add) -> Self { - let operation = Operation::Add; + let operation = Operation::ADD; let a = add.destination; let (b, b_is_constant) = add.left.as_index_and_constant_flag(); let (c, c_is_constant) = add.right.as_index_and_constant_flag(); diff --git a/dust-lang/src/instruction/call.rs b/dust-lang/src/instruction/call.rs index cd5240a..28dd473 100644 --- a/dust-lang/src/instruction/call.rs +++ b/dust-lang/src/instruction/call.rs @@ -26,6 +26,6 @@ impl From for Instruction { let (b, b_is_constant) = call.function.as_index_and_constant_flag(); let c = call.argument_count; - Instruction::new(Operation::Call, a, b, c, b_is_constant, false, false) + Instruction::new(Operation::CALL, a, b, c, b_is_constant, false, false) } } diff --git a/dust-lang/src/instruction/call_native.rs b/dust-lang/src/instruction/call_native.rs index 12f8873..43bf70a 100644 --- a/dust-lang/src/instruction/call_native.rs +++ b/dust-lang/src/instruction/call_native.rs @@ -21,7 +21,7 @@ impl From<&Instruction> for CallNative { impl From for Instruction { fn from(call_native: CallNative) -> Self { - let operation = Operation::CallNative; + let operation = Operation::CALL_NATIVE; let a = call_native.destination; let b = call_native.function as u8; let c = call_native.argument_count; diff --git a/dust-lang/src/instruction/close.rs b/dust-lang/src/instruction/close.rs index b7cbee9..ef33740 100644 --- a/dust-lang/src/instruction/close.rs +++ b/dust-lang/src/instruction/close.rs @@ -16,7 +16,7 @@ impl From<&Instruction> for Close { impl From for Instruction { fn from(close: Close) -> Self { - let operation = Operation::Close; + let operation = Operation::CLOSE; let (a, b, c) = (0, close.from, close.to); Instruction::new(operation, a, b, c, false, false, false) diff --git a/dust-lang/src/instruction/divide.rs b/dust-lang/src/instruction/divide.rs index a4c8ab3..c65b214 100644 --- a/dust-lang/src/instruction/divide.rs +++ b/dust-lang/src/instruction/divide.rs @@ -21,7 +21,7 @@ impl From<&Instruction> for Divide { impl From for Instruction { fn from(divide: Divide) -> Self { - let operation = Operation::Divide; + let operation = Operation::DIVIDE; let a = divide.destination; let (b, b_is_constant) = divide.left.as_index_and_constant_flag(); let (c, c_is_constant) = divide.right.as_index_and_constant_flag(); diff --git a/dust-lang/src/instruction/equal.rs b/dust-lang/src/instruction/equal.rs index e8fc5ca..6091236 100644 --- a/dust-lang/src/instruction/equal.rs +++ b/dust-lang/src/instruction/equal.rs @@ -24,7 +24,7 @@ impl From<&Instruction> for Equal { impl From for Instruction { fn from(equal: Equal) -> Self { - let operation = Operation::Equal; + let operation = Operation::EQUAL; let a = equal.destination; let (b, b_is_constant) = equal.left.as_index_and_constant_flag(); let (c, c_is_constant) = equal.right.as_index_and_constant_flag(); diff --git a/dust-lang/src/instruction/get_local.rs b/dust-lang/src/instruction/get_local.rs index 6462624..8e993df 100644 --- a/dust-lang/src/instruction/get_local.rs +++ b/dust-lang/src/instruction/get_local.rs @@ -19,7 +19,7 @@ impl From<&Instruction> for GetLocal { impl From for Instruction { fn from(get_local: GetLocal) -> Self { - let operation = Operation::GetLocal; + let operation = Operation::GET_LOCAL; let a = get_local.destination; let b = get_local.local_index; diff --git a/dust-lang/src/instruction/jump.rs b/dust-lang/src/instruction/jump.rs index 66ced41..2ec6819 100644 --- a/dust-lang/src/instruction/jump.rs +++ b/dust-lang/src/instruction/jump.rs @@ -16,7 +16,7 @@ impl From<&Instruction> for Jump { impl From for Instruction { fn from(jump: Jump) -> Self { - let operation = Operation::Jump; + let operation = Operation::JUMP; let b = jump.offset; let c = jump.is_positive as u8; diff --git a/dust-lang/src/instruction/less.rs b/dust-lang/src/instruction/less.rs index 4c03d60..6e87ed3 100644 --- a/dust-lang/src/instruction/less.rs +++ b/dust-lang/src/instruction/less.rs @@ -24,7 +24,7 @@ impl From<&Instruction> for Less { impl From for Instruction { fn from(less: Less) -> Self { - let operation = Operation::Less; + let operation = Operation::LESS; let a = less.destination; let (b, b_is_constant) = less.left.as_index_and_constant_flag(); let (c, c_is_constant) = less.right.as_index_and_constant_flag(); diff --git a/dust-lang/src/instruction/less_equal.rs b/dust-lang/src/instruction/less_equal.rs index 9cd8445..2ccd0cc 100644 --- a/dust-lang/src/instruction/less_equal.rs +++ b/dust-lang/src/instruction/less_equal.rs @@ -24,7 +24,7 @@ impl From<&Instruction> for LessEqual { impl From for Instruction { fn from(less_equal: LessEqual) -> Self { - let operation = Operation::LessEqual; + let operation = Operation::LESS_EQUAL; let a = less_equal.destination; let (b, b_options) = less_equal.left.as_index_and_constant_flag(); let (c, c_options) = less_equal.right.as_index_and_constant_flag(); diff --git a/dust-lang/src/instruction/load_boolean.rs b/dust-lang/src/instruction/load_boolean.rs index b224cf9..9937624 100644 --- a/dust-lang/src/instruction/load_boolean.rs +++ b/dust-lang/src/instruction/load_boolean.rs @@ -22,7 +22,7 @@ impl From<&Instruction> for LoadBoolean { impl From for Instruction { fn from(load_boolean: LoadBoolean) -> Self { - let operation = Operation::LoadBoolean; + let operation = Operation::LOAD_BOOLEAN; let a = load_boolean.destination; let b = load_boolean.value as u8; let c = load_boolean.jump_next as u8; diff --git a/dust-lang/src/instruction/load_constant.rs b/dust-lang/src/instruction/load_constant.rs index 7f5da34..b9bf47f 100644 --- a/dust-lang/src/instruction/load_constant.rs +++ b/dust-lang/src/instruction/load_constant.rs @@ -22,7 +22,7 @@ impl From<&Instruction> for LoadConstant { impl From for Instruction { fn from(load_constant: LoadConstant) -> Self { - let operation = Operation::LoadConstant; + let operation = Operation::LOAD_CONSTANT; let a = load_constant.destination; let b = load_constant.constant_index; let c = load_constant.jump_next as u8; diff --git a/dust-lang/src/instruction/load_list.rs b/dust-lang/src/instruction/load_list.rs index b3ca73d..7b8faeb 100644 --- a/dust-lang/src/instruction/load_list.rs +++ b/dust-lang/src/instruction/load_list.rs @@ -19,7 +19,7 @@ impl From<&Instruction> for LoadList { impl From for Instruction { fn from(load_list: LoadList) -> Self { - let operation = Operation::LoadList; + let operation = Operation::LOAD_LIST; let a = load_list.destination; let b = load_list.start_register; diff --git a/dust-lang/src/instruction/load_self.rs b/dust-lang/src/instruction/load_self.rs index 2c53c2d..7bbccfd 100644 --- a/dust-lang/src/instruction/load_self.rs +++ b/dust-lang/src/instruction/load_self.rs @@ -14,7 +14,7 @@ impl From<&Instruction> for LoadSelf { impl From for Instruction { fn from(load_self: LoadSelf) -> Self { - let operation = Operation::LoadSelf; + let operation = Operation::LOAD_SELF; let a = load_self.destination; Instruction::new(operation, a, 0, 0, false, false, false) diff --git a/dust-lang/src/instruction/mod.rs b/dust-lang/src/instruction/mod.rs index 58d606e..59f08f5 100644 --- a/dust-lang/src/instruction/mod.rs +++ b/dust-lang/src/instruction/mod.rs @@ -172,7 +172,7 @@ impl Instruction { c_is_constant: bool, d: bool, ) -> Instruction { - let bits = operation as u32 + let bits = operation.0 as u32 | ((b_is_constant as u32) << 5) | ((c_is_constant as u32) << 6) | ((d as u32) << 7) @@ -186,7 +186,7 @@ impl Instruction { pub fn operation(&self) -> Operation { let operation_bits = self.0 & 0b0001_1111; - Operation::from(operation_bits as u8) + Operation(operation_bits as u8) } pub fn b_is_constant(&self) -> bool { @@ -425,40 +425,40 @@ impl Instruction { pub fn is_math(&self) -> bool { matches!( self.operation(), - Operation::Add - | Operation::Subtract - | Operation::Multiply - | Operation::Divide - | Operation::Modulo + Operation::ADD + | Operation::SUBTRACT + | Operation::MULTIPLY + | Operation::DIVIDE + | Operation::MODULO ) } pub fn is_comparison(&self) -> bool { matches!( self.operation(), - Operation::Equal | Operation::Less | Operation::LessEqual + Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL ) } pub fn as_argument(&self) -> Option { match self.operation() { - Operation::LoadConstant => Some(Argument::Constant(self.b_field())), - Operation::LoadBoolean - | Operation::LoadList - | Operation::LoadSelf - | Operation::GetLocal - | Operation::Add - | Operation::Subtract - | Operation::Multiply - | Operation::Divide - | Operation::Modulo - | Operation::Equal - | Operation::Less - | Operation::LessEqual - | Operation::Negate - | Operation::Not - | Operation::Call => Some(Argument::Register(self.a_field())), - Operation::CallNative => { + Operation::LOAD_CONSTANT => Some(Argument::Constant(self.b_field())), + Operation::LOAD_BOOLEAN + | Operation::LOAD_LIST + | Operation::LOAD_SELF + | Operation::GET_LOCAL + | Operation::ADD + | Operation::SUBTRACT + | Operation::MULTIPLY + | Operation::DIVIDE + | Operation::MODULO + | Operation::EQUAL + | Operation::LESS + | Operation::LESS_EQUAL + | Operation::NEGATE + | Operation::NOT + | Operation::CALL => Some(Argument::Register(self.a_field())), + Operation::CALL_NATIVE => { let function = NativeFunction::from(self.b_field()); if function.returns_value() { @@ -496,50 +496,51 @@ impl Instruction { 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::Equal - | Operation::Less - | Operation::LessEqual - | Operation::Call => true, - Operation::CallNative => { + 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::EQUAL + | Operation::LESS + | Operation::LESS_EQUAL + | Operation::CALL => true, + Operation::CALL_NATIVE => { let function = NativeFunction::from(self.b_field()); function.returns_value() } - Operation::Move - | Operation::Close - | Operation::SetLocal - | Operation::Test - | Operation::TestSet - | Operation::Jump - | Operation::Return => false, + Operation::MOVE + | Operation::CLOSE + | Operation::SET_LOCAL + | Operation::TEST + | Operation::TEST_SET + | Operation::JUMP + | Operation::RETURN => false, + _ => Operation::panic_from_unknown_code(self.operation().0), } } pub fn disassembly_info(&self) -> String { match self.operation() { - Operation::Move => { + 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, @@ -552,7 +553,7 @@ impl Instruction { format!("R{destination} = {value}") } } - Operation::LoadConstant => { + Operation::LOAD_CONSTANT => { let LoadConstant { destination, constant_index, @@ -565,7 +566,7 @@ impl Instruction { format!("R{destination} = C{constant_index}") } } - Operation::LoadList => { + Operation::LOAD_LIST => { let LoadList { destination, start_register, @@ -574,12 +575,12 @@ impl Instruction { format!("R{destination} = [R{start_register}..=R{end_register}]",) } - Operation::LoadSelf => { + Operation::LOAD_SELF => { let LoadSelf { destination } = LoadSelf::from(self); format!("R{destination} = self") } - Operation::GetLocal => { + Operation::GET_LOCAL => { let GetLocal { destination, local_index, @@ -587,7 +588,7 @@ impl Instruction { format!("R{destination} = L{local_index}") } - Operation::SetLocal => { + Operation::SET_LOCAL => { let SetLocal { register_index, local_index, @@ -595,7 +596,7 @@ impl Instruction { format!("L{local_index} = R{register_index}") } - Operation::Add => { + Operation::ADD => { let Add { destination, left, @@ -604,7 +605,7 @@ impl Instruction { format!("R{destination} = {left} + {right}") } - Operation::Subtract => { + Operation::SUBTRACT => { let Subtract { destination, left, @@ -613,7 +614,7 @@ impl Instruction { format!("R{destination} = {left} - {right}") } - Operation::Multiply => { + Operation::MULTIPLY => { let Multiply { destination, left, @@ -622,7 +623,7 @@ impl Instruction { format!("R{destination} = {left} * {right}") } - Operation::Divide => { + Operation::DIVIDE => { let Divide { destination, left, @@ -631,7 +632,7 @@ impl Instruction { format!("R{destination} = {left} / {right}") } - Operation::Modulo => { + Operation::MODULO => { let Modulo { destination, left, @@ -640,7 +641,7 @@ impl Instruction { format!("R{destination} = {left} % {right}") } - Operation::Test => { + Operation::TEST => { let Test { argument, test_value: value, @@ -649,7 +650,7 @@ impl Instruction { format!("if {bang}{argument} {{ JUMP +1 }}",) } - Operation::TestSet => { + Operation::TEST_SET => { let TestSet { destination, argument, @@ -659,7 +660,7 @@ impl Instruction { format!("if {bang}{argument} {{ JUMP +1 }} else {{ R{destination} = {argument} }}") } - Operation::Equal => { + Operation::EQUAL => { let Equal { destination, value, @@ -670,7 +671,7 @@ impl Instruction { format!("R{destination} = {left} {comparison_symbol} {right}") } - Operation::Less => { + Operation::LESS => { let Less { destination, value, @@ -681,7 +682,7 @@ impl Instruction { format!("R{destination} = {left} {comparison_symbol} {right}") } - Operation::LessEqual => { + Operation::LESS_EQUAL => { let LessEqual { destination, value, @@ -692,7 +693,7 @@ impl Instruction { format!("R{destination} = {left} {comparison_symbol} {right}") } - Operation::Negate => { + Operation::NEGATE => { let Negate { destination, argument, @@ -700,7 +701,7 @@ impl Instruction { format!("R{destination} = -{argument}") } - Operation::Not => { + Operation::NOT => { let Not { destination, argument, @@ -708,7 +709,7 @@ impl Instruction { format!("R{destination} = !{argument}") } - Operation::Jump => { + Operation::JUMP => { let Jump { offset, is_positive, @@ -720,7 +721,7 @@ impl Instruction { format!("JUMP -{offset}") } } - Operation::Call => { + Operation::CALL => { let Call { destination, function, @@ -737,7 +738,7 @@ impl Instruction { } } } - Operation::CallNative => { + Operation::CALL_NATIVE => { let CallNative { destination, function, @@ -763,7 +764,7 @@ impl Instruction { info_string } - Operation::Return => { + Operation::RETURN => { let Return { should_return_value, } = Return::from(self); diff --git a/dust-lang/src/instruction/modulo.rs b/dust-lang/src/instruction/modulo.rs index 6435047..6aed458 100644 --- a/dust-lang/src/instruction/modulo.rs +++ b/dust-lang/src/instruction/modulo.rs @@ -21,7 +21,7 @@ impl From<&Instruction> for Modulo { impl From for Instruction { fn from(modulo: Modulo) -> Self { - let operation = Operation::Modulo; + let operation = Operation::MODULO; let a = modulo.destination; let (b, b_is_constant) = modulo.left.as_index_and_constant_flag(); let (c, c_is_constant) = modulo.right.as_index_and_constant_flag(); diff --git a/dust-lang/src/instruction/move.rs b/dust-lang/src/instruction/move.rs index 1625528..4c92c25 100644 --- a/dust-lang/src/instruction/move.rs +++ b/dust-lang/src/instruction/move.rs @@ -16,7 +16,7 @@ impl From<&Instruction> for Move { impl From for Instruction { fn from(r#move: Move) -> Self { - let operation = Operation::Move; + let operation = Operation::MOVE; let b = r#move.from; let c = r#move.to; diff --git a/dust-lang/src/instruction/multiply.rs b/dust-lang/src/instruction/multiply.rs index 4919377..40d8822 100644 --- a/dust-lang/src/instruction/multiply.rs +++ b/dust-lang/src/instruction/multiply.rs @@ -21,7 +21,7 @@ impl From<&Instruction> for Multiply { impl From for Instruction { fn from(multiply: Multiply) -> Self { - let operation = Operation::Multiply; + let operation = Operation::MULTIPLY; let a = multiply.destination; let (b, b_options) = multiply.left.as_index_and_constant_flag(); let (c, c_options) = multiply.right.as_index_and_constant_flag(); diff --git a/dust-lang/src/instruction/negate.rs b/dust-lang/src/instruction/negate.rs index 894bd52..a5e0dd9 100644 --- a/dust-lang/src/instruction/negate.rs +++ b/dust-lang/src/instruction/negate.rs @@ -19,7 +19,7 @@ impl From<&Instruction> for Negate { impl From for Instruction { fn from(negate: Negate) -> Self { - let operation = Operation::Negate; + let operation = Operation::NEGATE; let a = negate.destination; let (b, b_is_constant) = negate.argument.as_index_and_constant_flag(); let c = 0; diff --git a/dust-lang/src/instruction/not.rs b/dust-lang/src/instruction/not.rs index 79fb2ab..b07d266 100644 --- a/dust-lang/src/instruction/not.rs +++ b/dust-lang/src/instruction/not.rs @@ -19,7 +19,7 @@ impl From<&Instruction> for Not { impl From for Instruction { fn from(not: Not) -> Self { - let operation = Operation::Not; + let operation = Operation::NOT; let a = not.destination; let (b, b_is_constant) = not.argument.as_index_and_constant_flag(); diff --git a/dust-lang/src/instruction/operation.rs b/dust-lang/src/instruction/operation.rs index f870d88..c8dfc25 100644 --- a/dust-lang/src/instruction/operation.rs +++ b/dust-lang/src/instruction/operation.rs @@ -4,128 +4,71 @@ use std::fmt::{self, Debug, Display, Formatter}; use serde::{Deserialize, Serialize}; -pub const MOVE_BYTE: u8 = 0; -pub const CLOSE_BYTE: u8 = 1; -pub const LOAD_BOOLEAN_BYTE: u8 = 2; -pub const LOAD_CONSTANT_BYTE: u8 = 3; -pub const LOAD_LIST_BYTE: u8 = 4; -pub const LOAD_SELF_BYTE: u8 = 5; -pub const GET_LOCAL_BYTE: u8 = 6; -pub const SET_LOCAL_BYTE: u8 = 7; -pub const ADD_BYTE: u8 = 8; -pub const SUBTRACT_BYTE: u8 = 9; -pub const MULTIPLY_BYTE: u8 = 10; -pub const DIVIDE_BYTE: u8 = 11; -pub const MODULO_BYTE: u8 = 12; -pub const TEST_BYTE: u8 = 13; -pub const TEST_SET_BYTE: u8 = 14; -pub const EQUAL_BYTE: u8 = 15; -pub const LESS_BYTE: u8 = 16; -pub const LESS_EQUAL_BYTE: u8 = 17; -pub const NEGATE_BYTE: u8 = 18; -pub const NOT_BYTE: u8 = 19; -pub const CALL_BYTE: u8 = 20; -pub const CALL_NATIVE_BYTE: u8 = 21; -pub const JUMP_BYTE: u8 = 22; -pub const RETURN_BYTE: u8 = 23; - /// Part of an [Instruction][crate::Instruction] that is encoded as a single byte. #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -#[repr(u8)] -pub enum Operation { - Move = MOVE_BYTE, - Close = CLOSE_BYTE, - LoadBoolean = LOAD_BOOLEAN_BYTE, - LoadConstant = LOAD_CONSTANT_BYTE, - LoadList = LOAD_LIST_BYTE, - LoadSelf = LOAD_SELF_BYTE, - GetLocal = GET_LOCAL_BYTE, - SetLocal = SET_LOCAL_BYTE, - Add = ADD_BYTE, - Subtract = SUBTRACT_BYTE, - Multiply = MULTIPLY_BYTE, - Divide = DIVIDE_BYTE, - Modulo = MODULO_BYTE, - Test = TEST_BYTE, - TestSet = TEST_SET_BYTE, - Equal = EQUAL_BYTE, - Less = LESS_BYTE, - LessEqual = LESS_EQUAL_BYTE, - Negate = NEGATE_BYTE, - Not = NOT_BYTE, - Call = CALL_BYTE, - CallNative = CALL_NATIVE_BYTE, - Jump = JUMP_BYTE, - Return = RETURN_BYTE, -} +pub struct Operation(pub u8); -impl From for Operation { - fn from(byte: u8) -> Self { - match byte { - MOVE_BYTE => Self::Move, - CLOSE_BYTE => Self::Close, - LOAD_BOOLEAN_BYTE => Self::LoadBoolean, - LOAD_CONSTANT_BYTE => Self::LoadConstant, - LOAD_LIST_BYTE => Self::LoadList, - LOAD_SELF_BYTE => Self::LoadSelf, - GET_LOCAL_BYTE => Self::GetLocal, - SET_LOCAL_BYTE => Self::SetLocal, - ADD_BYTE => Self::Add, - SUBTRACT_BYTE => Self::Subtract, - MULTIPLY_BYTE => Self::Multiply, - DIVIDE_BYTE => Self::Divide, - MODULO_BYTE => Self::Modulo, - TEST_BYTE => Self::Test, - TEST_SET_BYTE => Self::TestSet, - EQUAL_BYTE => Self::Equal, - LESS_BYTE => Self::Less, - LESS_EQUAL_BYTE => Self::LessEqual, - NEGATE_BYTE => Self::Negate, - NOT_BYTE => Self::Not, - CALL_BYTE => Self::Call, - CALL_NATIVE_BYTE => Self::CallNative, - JUMP_BYTE => Self::Jump, - RETURN_BYTE => Self::Return, - _ => { - if cfg!(debug_assertions) { - panic!("Invalid operation byte: {}", byte) - } else { - Self::Return - } - } - } - } +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); } impl Operation { pub fn name(self) -> &'static str { match self { - Self::Move => "MOVE", - Self::Close => "CLOSE", - Self::LoadBoolean => "LOAD_BOOLEAN", - Self::LoadConstant => "LOAD_CONSTANT", - Self::LoadList => "LOAD_LIST", - Self::LoadSelf => "LOAD_SELF", - Self::GetLocal => "GET_LOCAL", - Self::SetLocal => "SET_LOCAL", - Self::Add => "ADD", - Self::Subtract => "SUBTRACT", - Self::Multiply => "MULTIPLY", - Self::Divide => "DIVIDE", - Self::Modulo => "MODULO", - Self::Test => "TEST", - Self::TestSet => "TEST_SET", - Self::Equal => "EQUAL", - Self::Less => "LESS", - Self::LessEqual => "LESS_EQUAL", - Self::Negate => "NEGATE", - Self::Not => "NOT", - Self::Call => "CALL", - Self::CallNative => "CALL_NATIVE", - Self::Jump => "JUMP", - Self::Return => "RETURN", + 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", + _ => Self::panic_from_unknown_code(self.0), } } + + pub fn panic_from_unknown_code(code: u8) -> ! { + panic!("Unknown operation code: {code}"); + } } impl Debug for Operation { @@ -139,54 +82,3 @@ impl Display for Operation { write!(f, "{}", self.name()) } } - -#[cfg(test)] -mod tests { - use super::*; - - const ALL_OPERATIONS: [Operation; 24] = [ - Operation::Move, - Operation::Close, - Operation::LoadBoolean, - Operation::LoadConstant, - Operation::LoadList, - Operation::LoadSelf, - Operation::GetLocal, - Operation::SetLocal, - Operation::Add, - Operation::Subtract, - Operation::Multiply, - Operation::Divide, - Operation::Modulo, - Operation::Test, - Operation::TestSet, - Operation::Equal, - Operation::Less, - Operation::LessEqual, - Operation::Negate, - Operation::Not, - Operation::Call, - Operation::CallNative, - Operation::Jump, - Operation::Return, - ]; - - #[test] - fn operations_are_unique() { - for (i, operation) in ALL_OPERATIONS.into_iter().enumerate() { - assert_eq!(i, operation as usize); - } - } - - #[test] - fn operation_uses_five_bits() { - for operation in ALL_OPERATIONS { - assert_eq!(operation as u8 & 0b1110_0000, 0); - } - } - - #[test] - fn operation_is_one_byte() { - assert_eq!(size_of::(), 1); - } -} diff --git a/dust-lang/src/instruction/return.rs b/dust-lang/src/instruction/return.rs index 99427c3..cba8cfa 100644 --- a/dust-lang/src/instruction/return.rs +++ b/dust-lang/src/instruction/return.rs @@ -16,7 +16,7 @@ impl From<&Instruction> for Return { impl From for Instruction { fn from(r#return: Return) -> Self { - let operation = Operation::Return; + let operation = Operation::RETURN; let b = r#return.should_return_value as u8; Instruction::new(operation, 0, b, 0, false, false, false) diff --git a/dust-lang/src/instruction/set_local.rs b/dust-lang/src/instruction/set_local.rs index cfe1609..4cf1053 100644 --- a/dust-lang/src/instruction/set_local.rs +++ b/dust-lang/src/instruction/set_local.rs @@ -19,7 +19,7 @@ impl From<&Instruction> for SetLocal { impl From for Instruction { fn from(set_local: SetLocal) -> Self { - let operation = Operation::SetLocal; + let operation = Operation::SET_LOCAL; let b = set_local.register_index; let c = set_local.local_index; diff --git a/dust-lang/src/instruction/subtract.rs b/dust-lang/src/instruction/subtract.rs index 5805c50..22202f5 100644 --- a/dust-lang/src/instruction/subtract.rs +++ b/dust-lang/src/instruction/subtract.rs @@ -21,7 +21,7 @@ impl From<&Instruction> for Subtract { impl From for Instruction { fn from(subtract: Subtract) -> Self { - let operation = Operation::Subtract; + let operation = Operation::SUBTRACT; let a = subtract.destination; let (b, b_is_constant) = subtract.left.as_index_and_constant_flag(); let (c, c_is_constant) = subtract.right.as_index_and_constant_flag(); diff --git a/dust-lang/src/instruction/test.rs b/dust-lang/src/instruction/test.rs index 8cbb0ff..bcb93d1 100644 --- a/dust-lang/src/instruction/test.rs +++ b/dust-lang/src/instruction/test.rs @@ -19,7 +19,7 @@ impl From<&Instruction> for Test { impl From for Instruction { fn from(test: Test) -> Self { - let operation = Operation::Test; + let operation = Operation::TEST; let (b, b_is_constant) = test.argument.as_index_and_constant_flag(); let c = test.test_value as u8; diff --git a/dust-lang/src/instruction/test_set.rs b/dust-lang/src/instruction/test_set.rs index 608306c..b6300bc 100644 --- a/dust-lang/src/instruction/test_set.rs +++ b/dust-lang/src/instruction/test_set.rs @@ -22,7 +22,7 @@ impl From<&Instruction> for TestSet { impl From for Instruction { fn from(test_set: TestSet) -> Self { - let operation = Operation::Test; + let operation = Operation::TEST; let a = test_set.destination; let (b, b_is_constant) = test_set.argument.as_index_and_constant_flag(); let c = test_set.test_value as u8; diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 7162c1b..2b6bfa8 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -90,6 +90,7 @@ impl<'a> Vm<'a> { position } + #[allow(clippy::needless_lifetimes)] fn r#move<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -108,6 +109,7 @@ impl<'a> Vm<'a> { Ok(()) } + #[allow(clippy::needless_lifetimes)] fn close<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) -> Result<(), VmError> { let InstructionData { b, c, .. } = instruction_data; @@ -124,6 +126,7 @@ impl<'a> Vm<'a> { Ok(()) } + #[allow(clippy::needless_lifetimes)] fn load_boolean<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -141,6 +144,7 @@ impl<'a> Vm<'a> { Ok(()) } + #[allow(clippy::needless_lifetimes)] fn load_constant<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -157,6 +161,7 @@ impl<'a> Vm<'a> { Ok(()) } + #[allow(clippy::needless_lifetimes)] fn load_list<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -181,6 +186,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn load_self<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -191,6 +197,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn get_local<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -202,6 +209,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn set_local<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -213,6 +221,7 @@ impl<'a> Vm<'a> { vm.set_register(local_register_index, register) } + #[allow(clippy::needless_lifetimes)] fn add<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) -> Result<(), VmError> { let InstructionData { a, @@ -239,6 +248,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn subtract<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -268,6 +278,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn multiply<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -297,6 +308,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn divide<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -326,6 +338,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn modulo<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -355,6 +368,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn test<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) -> Result<(), VmError> { let InstructionData { b, @@ -380,6 +394,7 @@ impl<'a> Vm<'a> { Ok(()) } + #[allow(clippy::needless_lifetimes)] fn test_set<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -418,6 +433,7 @@ impl<'a> Vm<'a> { Ok(()) } + #[allow(clippy::needless_lifetimes)] fn equal<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) -> Result<(), VmError> { let InstructionData { a, @@ -448,6 +464,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn less<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) -> Result<(), VmError> { let InstructionData { a, @@ -478,6 +495,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn less_equal<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -513,6 +531,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn negate<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -533,6 +552,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn not<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) -> Result<(), VmError> { let InstructionData { a, @@ -550,6 +570,7 @@ impl<'a> Vm<'a> { vm.set_register(a, register) } + #[allow(clippy::needless_lifetimes)] fn jump<'b, 'c>(vm: &mut Vm<'c>, instruction_data: InstructionData) -> Result<(), VmError> { let InstructionData { b, c, .. } = instruction_data; let is_positive = c != 0; @@ -559,6 +580,7 @@ impl<'a> Vm<'a> { Ok(()) } + #[allow(clippy::needless_lifetimes)] fn call<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) -> Result<(), VmError> { let InstructionData { a, @@ -609,6 +631,7 @@ impl<'a> Vm<'a> { Ok(()) } + #[allow(clippy::needless_lifetimes)] fn call_native<'b, 'c>( vm: &'b mut Vm<'c>, instruction_data: InstructionData, @@ -665,7 +688,7 @@ impl<'a> Vm<'a> { instruction.disassembly_info() ); - if let Operation::Return = operation { + if let Operation::RETURN = operation { let should_return_value = instruction_data.b != 0; if !should_return_value { @@ -684,7 +707,7 @@ impl<'a> Vm<'a> { }) }; } else { - let runner = RUNNERS[operation as usize]; + let runner = RUNNERS[operation.0 as usize]; runner(self, instruction_data).unwrap(); } @@ -1045,35 +1068,35 @@ mod tests { use super::*; const ALL_OPERATIONS: [(Operation, Runner); 23] = [ - (Operation::Move, Vm::r#move), - (Operation::Close, Vm::close), - (Operation::LoadBoolean, Vm::load_boolean), - (Operation::LoadConstant, Vm::load_constant), - (Operation::LoadList, Vm::load_list), - (Operation::LoadSelf, Vm::load_self), - (Operation::GetLocal, Vm::get_local), - (Operation::SetLocal, Vm::set_local), - (Operation::Add, Vm::add), - (Operation::Subtract, Vm::subtract), - (Operation::Multiply, Vm::multiply), - (Operation::Divide, Vm::divide), - (Operation::Modulo, Vm::modulo), - (Operation::Test, Vm::test), - (Operation::TestSet, Vm::test_set), - (Operation::Equal, Vm::equal), - (Operation::Less, Vm::less), - (Operation::LessEqual, Vm::less_equal), - (Operation::Negate, Vm::negate), - (Operation::Not, Vm::not), - (Operation::Call, Vm::call), - (Operation::CallNative, Vm::call_native), - (Operation::Jump, Vm::jump), + (Operation::MOVE, Vm::r#move), + (Operation::CLOSE, Vm::close), + (Operation::LOAD_BOOLEAN, Vm::load_boolean), + (Operation::LOAD_CONSTANT, Vm::load_constant), + (Operation::LOAD_LIST, Vm::load_list), + (Operation::LOAD_SELF, Vm::load_self), + (Operation::GET_LOCAL, Vm::get_local), + (Operation::SET_LOCAL, Vm::set_local), + (Operation::ADD, Vm::add), + (Operation::SUBTRACT, Vm::subtract), + (Operation::MULTIPLY, Vm::multiply), + (Operation::DIVIDE, Vm::divide), + (Operation::MODULO, Vm::modulo), + (Operation::TEST, Vm::test), + (Operation::TEST_SET, Vm::test_set), + (Operation::EQUAL, Vm::equal), + (Operation::LESS, Vm::less), + (Operation::LESS_EQUAL, Vm::less_equal), + (Operation::NEGATE, Vm::negate), + (Operation::NOT, Vm::not), + (Operation::CALL, Vm::call), + (Operation::CALL_NATIVE, Vm::call_native), + (Operation::JUMP, Vm::jump), ]; #[test] fn operations_map_to_the_correct_runner() { for (operation, expected_runner) in ALL_OPERATIONS { - let actual_runner = RUNNERS[operation as usize]; + let actual_runner = RUNNERS[operation.0 as usize]; assert_eq!( expected_runner, actual_runner,