diff --git a/dust-lang/src/compiler/mod.rs b/dust-lang/src/compiler/mod.rs index d5e99a6..a52393b 100644 --- a/dust-lang/src/compiler/mod.rs +++ b/dust-lang/src/compiler/mod.rs @@ -629,11 +629,12 @@ impl<'src> Compiler<'src> { if let Token::Boolean(text) = self.current_token { self.advance()?; - let boolean = text.parse::().unwrap(); + let boolean = text.parse::().unwrap() as u16; let destination = self.next_boolean_register(); - let load_boolean = Instruction::load_boolean(destination, boolean, false); + let load_encoded = + Instruction::load_encoded(destination, boolean, TypeCode::BOOLEAN, false); - self.emit_instruction(load_boolean, Type::Boolean, position); + self.emit_instruction(load_encoded, Type::Boolean, position); Ok(()) } else { @@ -652,10 +653,12 @@ impl<'src> Compiler<'src> { self.advance()?; let byte = u8::from_str_radix(&text[2..], 16) - .map_err(|error| CompileError::ParseIntError { error, position })?; - let value = ConcreteValue::Byte(byte); + .map_err(|error| CompileError::ParseIntError { error, position })? + as u16; + let destination = self.next_byte_register(); + let load_encoded = Instruction::load_encoded(destination, byte, TypeCode::BYTE, false); - self.emit_constant(value, position)?; + self.emit_instruction(load_encoded, Type::Byte, position); Ok(()) } else { @@ -836,7 +839,7 @@ impl<'src> Compiler<'src> { let (argument, push_back) = match instruction.operation() { Operation::LOAD_CONSTANT => (Operand::Constant(instruction.b_field()), false), Operation::POINT => (instruction.b_as_operand(), false), - Operation::LOAD_BOOLEAN + Operation::LOAD_ENCODED | Operation::LOAD_LIST | Operation::LOAD_SELF | Operation::ADD @@ -1114,8 +1117,10 @@ impl<'src> Compiler<'src> { } }; let jump = Instruction::jump(1, true); - let load_true = Instruction::load_boolean(destination, true, true); - let load_false = Instruction::load_boolean(destination, false, false); + let load_true = + Instruction::load_encoded(destination, true as u16, TypeCode::BOOLEAN, true); + let load_false = + Instruction::load_encoded(destination, false as u16, TypeCode::BOOLEAN, false); self.emit_instruction(comparison, Type::Boolean, operator_position); self.emit_instruction(jump, Type::None, operator_position); @@ -1385,8 +1390,8 @@ impl<'src> Compiler<'src> { Some([ Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL, Operation::JUMP, - Operation::LOAD_BOOLEAN, - Operation::LOAD_BOOLEAN + Operation::LOAD_ENCODED, + Operation::LOAD_ENCODED ]), ) { self.instructions.pop(); @@ -1456,7 +1461,7 @@ impl<'src> Compiler<'src> { match else_block_distance { 0 => {} 1 => { - if let Some([Operation::LOAD_BOOLEAN | Operation::LOAD_CONSTANT, _]) = + if let Some([Operation::LOAD_ENCODED | Operation::LOAD_CONSTANT, _]) = self.get_last_operations() { let loader_index = self.instructions.len() - 2; @@ -1491,7 +1496,7 @@ impl<'src> Compiler<'src> { self.instructions .insert(if_block_start, (jump, Type::None, if_block_start_position)); - let if_block_last_instruction_index = self.instructions.len() - else_block_distance - 1; + let if_block_last_instruction_index = self.instructions.len() - else_block_distance; let else_block_last_instruction_index = self.instructions.len() - 1; let if_block_last_instruction = self.instructions[if_block_last_instruction_index].0; @@ -1500,8 +1505,6 @@ impl<'src> Compiler<'src> { else_block_last_instruction.set_a_field(if_block_last_instruction.a_field()); - println!("{if_block_last_instruction_index} {else_block_last_instruction_index}"); - Ok(()) } @@ -1517,8 +1520,8 @@ impl<'src> Compiler<'src> { Some([ Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL, Operation::JUMP, - Operation::LOAD_BOOLEAN, - Operation::LOAD_BOOLEAN + Operation::LOAD_ENCODED, + Operation::LOAD_ENCODED ]), ) { self.instructions.pop(); diff --git a/dust-lang/src/instruction/load_boolean.rs b/dust-lang/src/instruction/load_boolean.rs deleted file mode 100644 index 4633de8..0000000 --- a/dust-lang/src/instruction/load_boolean.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::fmt::{self, Display, Formatter}; - -use crate::{Instruction, Operation}; - -use super::InstructionFields; - -pub struct LoadBoolean { - pub destination: u16, - pub value: bool, - pub jump_next: bool, -} - -impl From for LoadBoolean { - fn from(instruction: Instruction) -> Self { - LoadBoolean { - destination: instruction.a_field(), - value: instruction.b_field() != 0, - jump_next: instruction.c_field() != 0, - } - } -} - -impl From for Instruction { - fn from(load_boolean: LoadBoolean) -> Self { - let operation = Operation::LOAD_BOOLEAN; - let a_field = load_boolean.destination; - let b_field = load_boolean.value as u16; - let c_field = load_boolean.jump_next as u16; - - InstructionFields { - operation, - a_field, - b_field, - c_field, - ..Default::default() - } - .build() - } -} - -impl Display for LoadBoolean { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let LoadBoolean { - destination, - value, - jump_next, - } = self; - - write!(f, "R{destination} = {value}")?; - - if *jump_next { - write!(f, " JUMP +1")?; - } - - Ok(()) - } -} diff --git a/dust-lang/src/instruction/load_encoded.rs b/dust-lang/src/instruction/load_encoded.rs new file mode 100644 index 0000000..ed7664c --- /dev/null +++ b/dust-lang/src/instruction/load_encoded.rs @@ -0,0 +1,74 @@ +use std::fmt::{self, Display, Formatter}; + +use crate::{Instruction, Operation}; + +use super::{InstructionFields, TypeCode}; + +pub struct LoadEncoded { + pub destination: u16, + pub value: u16, + pub value_type: TypeCode, + pub jump_next: bool, +} + +impl From for LoadEncoded { + fn from(instruction: Instruction) -> Self { + LoadEncoded { + destination: instruction.a_field(), + value: instruction.b_field(), + value_type: instruction.b_type(), + jump_next: instruction.c_field() != 0, + } + } +} + +impl From for Instruction { + fn from(load_boolean: LoadEncoded) -> Self { + let operation = Operation::LOAD_ENCODED; + let a_field = load_boolean.destination; + let b_field = load_boolean.value; + let b_type = load_boolean.value_type; + let c_field = load_boolean.jump_next as u16; + + InstructionFields { + operation, + a_field, + b_field, + b_type, + c_field, + ..Default::default() + } + .build() + } +} + +impl Display for LoadEncoded { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let LoadEncoded { + destination, + value, + value_type, + jump_next, + } = self; + + match *value_type { + TypeCode::BOOLEAN => { + let boolean = *value != 0; + + write!(f, "R_BOOL_{destination} = {boolean}")? + } + TypeCode::BYTE => { + let byte = *value as u8; + + write!(f, "R_BYTE_{destination} = 0x{byte:0X}")? + } + _ => panic!("Invalid type code {value_type} for LoadEncoded instruction"), + } + + if *jump_next { + write!(f, " JUMP +1")?; + } + + Ok(()) + } +} diff --git a/dust-lang/src/instruction/mod.rs b/dust-lang/src/instruction/mod.rs index c5dcc27..b0b446c 100644 --- a/dust-lang/src/instruction/mod.rs +++ b/dust-lang/src/instruction/mod.rs @@ -102,8 +102,8 @@ mod equal; mod jump; mod less; mod less_equal; -mod load_boolean; mod load_constant; +mod load_encoded; mod load_function; mod load_list; mod load_self; @@ -128,8 +128,8 @@ pub use equal::Equal; pub use jump::Jump; pub use less::Less; pub use less_equal::LessEqual; -pub use load_boolean::LoadBoolean; pub use load_constant::LoadConstant; +pub use load_encoded::LoadEncoded; pub use load_function::LoadFunction; pub use load_list::LoadList; pub use load_self::LoadSelf; @@ -286,10 +286,16 @@ impl Instruction { Instruction::from(Close { from, to }) } - pub fn load_boolean(destination: u16, value: bool, jump_next: bool) -> Instruction { - Instruction::from(LoadBoolean { + pub fn load_encoded( + destination: u16, + value: u16, + value_type: TypeCode, + jump_next: bool, + ) -> Instruction { + Instruction::from(LoadEncoded { destination, value, + value_type, jump_next, }) } @@ -546,7 +552,7 @@ impl Instruction { match self.operation() { Operation::LOAD_CONSTANT => Some(Operand::Constant(self.b_field())), Operation::POINT - | Operation::LOAD_BOOLEAN + | Operation::LOAD_ENCODED | Operation::LOAD_LIST | Operation::LOAD_SELF | Operation::ADD @@ -599,7 +605,7 @@ impl Instruction { pub fn yields_value(&self) -> bool { match self.operation() { Operation::POINT - | Operation::LOAD_BOOLEAN + | Operation::LOAD_ENCODED | Operation::LOAD_CONSTANT | Operation::LOAD_FUNCTION | Operation::LOAD_LIST @@ -633,7 +639,7 @@ impl Instruction { match operation { Operation::POINT => Point::from(*self).to_string(), - Operation::LOAD_BOOLEAN => LoadBoolean::from(*self).to_string(), + Operation::LOAD_ENCODED => LoadEncoded::from(*self).to_string(), Operation::LOAD_CONSTANT => LoadConstant::from(*self).to_string(), Operation::LOAD_FUNCTION => LoadFunction::from(*self).to_string(), Operation::LOAD_LIST => LoadList::from(*self).to_string(), diff --git a/dust-lang/src/instruction/operation.rs b/dust-lang/src/instruction/operation.rs index 5cbdaf6..4f412c3 100644 --- a/dust-lang/src/instruction/operation.rs +++ b/dust-lang/src/instruction/operation.rs @@ -14,7 +14,7 @@ impl Operation { pub const CLOSE: Operation = Operation(1); // Loaders - pub const LOAD_BOOLEAN: Operation = Operation(2); + pub const LOAD_ENCODED: Operation = Operation(2); pub const LOAD_CONSTANT: Operation = Operation(3); pub const LOAD_FUNCTION: Operation = Operation(4); pub const LOAD_LIST: Operation = Operation(5); @@ -53,7 +53,7 @@ impl Operation { pub fn name(&self) -> &'static str { match *self { Self::POINT => "POINT", - Self::LOAD_BOOLEAN => "LOAD_BOOLEAN", + Self::LOAD_ENCODED => "LOAD_ENCODED", Self::LOAD_CONSTANT => "LOAD_CONSTANT", Self::LOAD_FUNCTION => "LOAD_FUNCTION", Self::LOAD_LIST => "LOAD_LIST", diff --git a/dust-lang/src/vm/action.rs b/dust-lang/src/vm/action.rs index bf5417b..347f610 100644 --- a/dust-lang/src/vm/action.rs +++ b/dust-lang/src/vm/action.rs @@ -276,7 +276,7 @@ mod tests { const ALL_OPERATIONS: [(Operation, RunnerLogic); 23] = [ (Operation::POINT, point), (Operation::CLOSE, close), - (Operation::LOAD_BOOLEAN, load_boolean), + (Operation::LOAD_ENCODED, load_boolean), (Operation::LOAD_CONSTANT, load_constant), (Operation::LOAD_FUNCTION, load_function), (Operation::LOAD_LIST, load_list), diff --git a/dust-lang/tests/logic/and.rs b/dust-lang/tests/logic/and.rs index 68f9d6a..0bce420 100644 --- a/dust-lang/tests/logic/and.rs +++ b/dust-lang/tests/logic/and.rs @@ -15,10 +15,10 @@ fn true_and_true() { return_type: Type::Boolean, }, smallvec![ - Instruction::load_boolean(0, true, false), + Instruction::load_encoded(0, true, false), Instruction::test(0, true), Instruction::jump(1, true), - Instruction::load_boolean(1, true, false), + Instruction::load_encoded(1, true, false), Instruction::r#return(true), ], smallvec![ @@ -51,10 +51,10 @@ fn false_and_false() { return_type: Type::Boolean, }, smallvec![ - Instruction::load_boolean(0, false, false), + Instruction::load_encoded(0, false, false), Instruction::test(0, true), Instruction::jump(1, true), - Instruction::load_boolean(1, false, false), + Instruction::load_encoded(1, false, false), Instruction::r#return(true), ], smallvec![ @@ -87,10 +87,10 @@ fn false_and_true() { return_type: Type::Boolean, }, smallvec![ - Instruction::load_boolean(0, false, false), + Instruction::load_encoded(0, false, false), Instruction::test(0, true), Instruction::jump(1, true), - Instruction::load_boolean(1, true, false), + Instruction::load_encoded(1, true, false), Instruction::r#return(true), ], smallvec![ @@ -123,10 +123,10 @@ fn true_and_false() { return_type: Type::Boolean, }, smallvec![ - Instruction::load_boolean(0, true, false), + Instruction::load_encoded(0, true, false), Instruction::test(0, true), Instruction::jump(1, true), - Instruction::load_boolean(1, false, false), + Instruction::load_encoded(1, false, false), Instruction::r#return(true), ], smallvec![ diff --git a/dust-lang/tests/logic/and_and.rs b/dust-lang/tests/logic/and_and.rs index 53c38ba..a0807d2 100644 --- a/dust-lang/tests/logic/and_and.rs +++ b/dust-lang/tests/logic/and_and.rs @@ -15,13 +15,13 @@ fn true_and_true_and_true() { return_type: Type::Boolean, }, smallvec![ - Instruction::load_boolean(0, true, false), + Instruction::load_encoded(0, true, false), Instruction::test(0, true), Instruction::jump(1, true), - Instruction::load_boolean(1, true, false), + Instruction::load_encoded(1, true, false), Instruction::test(1, true), Instruction::jump(1, true), - Instruction::load_boolean(2, true, false), + Instruction::load_encoded(2, true, false), Instruction::r#return(true), ], smallvec![ diff --git a/dust-lang/tests/logic/or.rs b/dust-lang/tests/logic/or.rs index 0886f23..87eb26e 100644 --- a/dust-lang/tests/logic/or.rs +++ b/dust-lang/tests/logic/or.rs @@ -15,10 +15,10 @@ fn true_or_false() { return_type: Type::Boolean, }, smallvec![ - Instruction::load_boolean(0, true, false), + Instruction::load_encoded(0, true, false), Instruction::test(0, false), Instruction::jump(1, true), - Instruction::load_boolean(1, false, false), + Instruction::load_encoded(1, false, false), Instruction::r#return(true), ], smallvec![ diff --git a/dust-lang/tests/unary_operations.rs b/dust-lang/tests/unary_operations.rs index 3b44024..129f441 100644 --- a/dust-lang/tests/unary_operations.rs +++ b/dust-lang/tests/unary_operations.rs @@ -39,7 +39,7 @@ fn not() { return_type: Type::Boolean, }, vec![ - (Instruction::load_boolean(0, true, false), Span(1, 5)), + (Instruction::load_encoded(0, true, false), Span(1, 5)), (Instruction::not(1, Operand::Register(0)), Span(0, 1)), (Instruction::r#return(true), Span(5, 5)), ],