From 25b4230aa463bc5d18815f2eaaf9a3dcbce62976 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 7 Feb 2025 10:19:38 -0500 Subject: [PATCH] Use Operand type to store instruction argument types --- dust-lang/src/compiler/mod.rs | 154 +++---------- dust-lang/src/instruction/add.rs | 16 +- dust-lang/src/instruction/divide.rs | 24 ++- dust-lang/src/instruction/equal.rs | 14 +- dust-lang/src/instruction/less.rs | 14 +- dust-lang/src/instruction/less_equal.rs | 14 +- dust-lang/src/instruction/mod.rs | 276 ++++++++++-------------- dust-lang/src/instruction/modulo.rs | 24 ++- dust-lang/src/instruction/multiply.rs | 24 ++- dust-lang/src/instruction/point.rs | 12 +- dust-lang/src/instruction/subtract.rs | 24 ++- dust-lang/src/instruction/type_code.rs | 4 +- 12 files changed, 213 insertions(+), 387 deletions(-) diff --git a/dust-lang/src/compiler/mod.rs b/dust-lang/src/compiler/mod.rs index 46ac35c..61989a8 100644 --- a/dust-lang/src/compiler/mod.rs +++ b/dust-lang/src/compiler/mod.rs @@ -785,7 +785,7 @@ impl<'src> Compiler<'src> { let (previous_instruction, previous_type, previous_position) = self.instructions.pop().unwrap(); - let (argument, push_back) = self.handle_binary_argument(&previous_instruction)?; + let (argument, push_back) = self.handle_binary_argument(&previous_instruction); if push_back { self.instructions.push(( @@ -832,48 +832,10 @@ impl<'src> Compiler<'src> { Ok(()) } - fn handle_binary_argument( - &mut self, - instruction: &Instruction, - ) -> Result<(Operand, bool), CompileError> { - 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_ENCODED - | 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 => (Operand::Register(instruction.a_field()), true), - Operation::CALL_NATIVE => { - let function = NativeFunction::from(instruction.b_field()); + fn handle_binary_argument(&mut self, instruction: &Instruction) -> (Operand, bool) { + let (argument, push_back) = (instruction.as_operand(), !instruction.yields_value()); - if function.returns_value() { - (Operand::Register(instruction.a_field()), true) - } else { - return Err(CompileError::ExpectedExpression { - found: self.previous_token.to_owned(), - position: self.previous_position, - }); - } - } - _ => { - return Err(CompileError::ExpectedExpression { - found: self.previous_token.to_owned(), - position: self.previous_position, - }); - } - }; - - Ok((argument, push_back)) + (argument, push_back) } fn parse_math_binary(&mut self) -> Result<(), CompileError> { @@ -884,7 +846,7 @@ impl<'src> Compiler<'src> { found: self.previous_token.to_owned(), position: self.previous_position, })?; - let (left, push_back_left) = self.handle_binary_argument(&left_instruction)?; + let (left, push_back_left) = self.handle_binary_argument(&left_instruction); let left_is_mutable_local = if left_instruction.operation() == Operation::POINT { let Point { to, .. } = Point::from(left_instruction); @@ -915,13 +877,13 @@ impl<'src> Compiler<'src> { check_math_type(&left_type, operator, &left_position)?; - let (left_type_code, destination) = match left_type { - Type::Boolean => (TypeCode::BOOLEAN, self.next_boolean_register()), - Type::Byte => (TypeCode::BYTE, self.next_byte_register()), - Type::Character => (TypeCode::CHARACTER, self.next_character_register()), - Type::Float => (TypeCode::FLOAT, self.next_float_register()), - Type::Integer => (TypeCode::INTEGER, self.next_integer_register()), - Type::String => (TypeCode::STRING, self.next_string_register()), + let destination = match left_type { + Type::Boolean => self.next_boolean_register(), + Type::Byte => self.next_byte_register(), + Type::Character => self.next_character_register(), + Type::Float => self.next_float_register(), + Type::Integer => self.next_integer_register(), + Type::String => self.next_string_register(), _ => unreachable!(), }; @@ -936,7 +898,7 @@ impl<'src> Compiler<'src> { self.parse_sub_expression(&rule.precedence)?; let (right_instruction, right_type, right_position) = self.instructions.pop().unwrap(); - let (right, push_back_right) = self.handle_binary_argument(&right_instruction)?; + let (right, push_back_right) = self.handle_binary_argument(&right_instruction); check_math_type(&right_type, operator, &right_position)?; check_math_types( @@ -947,16 +909,6 @@ impl<'src> Compiler<'src> { &right_position, )?; - let right_type_code = match right_type { - Type::Boolean => TypeCode::BOOLEAN, - Type::Byte => TypeCode::BYTE, - Type::Character => TypeCode::CHARACTER, - Type::Float => TypeCode::FLOAT, - Type::Integer => TypeCode::INTEGER, - Type::String => TypeCode::STRING, - _ => unreachable!(), - }; - if push_back_right { self.instructions .push((right_instruction, right_type, right_position)); @@ -970,21 +922,11 @@ impl<'src> Compiler<'src> { left_type.clone() }; let instruction = match operator { - Token::Plus | Token::PlusEqual => { - Instruction::add(destination, left, left_type_code, right, right_type_code) - } - Token::Minus | Token::MinusEqual => { - Instruction::subtract(destination, left, left_type_code, right, right_type_code) - } - Token::Star | Token::StarEqual => { - Instruction::multiply(destination, left, left_type_code, right, right_type_code) - } - Token::Slash | Token::SlashEqual => { - Instruction::divide(destination, left, left_type_code, right, right_type_code) - } - Token::Percent | Token::PercentEqual => { - Instruction::modulo(destination, left, left_type_code, right, right_type_code) - } + Token::Plus | Token::PlusEqual => Instruction::add(destination, left, right), + Token::Minus | Token::MinusEqual => Instruction::subtract(destination, left, right), + Token::Star | Token::StarEqual => Instruction::multiply(destination, left, right), + Token::Slash | Token::SlashEqual => Instruction::divide(destination, left, right), + Token::Percent | Token::PercentEqual => Instruction::modulo(destination, left, right), _ => { return Err(CompileError::ExpectedTokenMultiple { expected: &[ @@ -1031,23 +973,13 @@ impl<'src> Compiler<'src> { found: self.previous_token.to_owned(), position: self.previous_position, })?; - let (left, push_back_left) = self.handle_binary_argument(&left_instruction)?; + let (left, push_back_left) = self.handle_binary_argument(&left_instruction); let operator = self.current_token; let operator_position = self.current_position; let rule = ParseRule::from(&operator); // TODO: Check if the left type is a valid type for comparison - let left_type_code = match left_type { - Type::Boolean => TypeCode::BOOLEAN, - Type::Byte => TypeCode::BYTE, - Type::Character => TypeCode::CHARACTER, - Type::Float => TypeCode::FLOAT, - Type::Integer => TypeCode::INTEGER, - Type::String => TypeCode::STRING, - _ => unreachable!(), - }; - if push_back_left { self.instructions .push((left_instruction, left_type, left_position)); @@ -1063,21 +995,11 @@ impl<'src> Compiler<'src> { found: self.previous_token.to_owned(), position: self.previous_position, })?; - let (right, push_back_right) = self.handle_binary_argument(&right_instruction)?; + let (right, push_back_right) = self.handle_binary_argument(&right_instruction); // TODO: Check if the right type is a valid type for comparison // TODO: Check if the left and right types are compatible - let right_type_code = match right_type { - Type::Boolean => TypeCode::BOOLEAN, - Type::Byte => TypeCode::BYTE, - Type::Character => TypeCode::CHARACTER, - Type::Float => TypeCode::FLOAT, - Type::Integer => TypeCode::INTEGER, - Type::String => TypeCode::STRING, - _ => unreachable!(), - }; - if push_back_right { self.instructions .push((right_instruction, right_type, right_position)); @@ -1085,22 +1007,12 @@ impl<'src> Compiler<'src> { let destination = self.next_boolean_register(); let comparison = match operator { - Token::DoubleEqual => { - Instruction::equal(true, left, left_type_code, right, right_type_code) - } - Token::BangEqual => { - Instruction::equal(false, left, left_type_code, right, right_type_code) - } - Token::Less => Instruction::less(true, left, left_type_code, right, right_type_code), - Token::LessEqual => { - Instruction::less_equal(true, left, left_type_code, right, right_type_code) - } - Token::Greater => { - Instruction::less_equal(false, left, left_type_code, right, right_type_code) - } - Token::GreaterEqual => { - Instruction::less(false, left, left_type_code, right, right_type_code) - } + Token::DoubleEqual => Instruction::equal(true, left, right), + Token::BangEqual => Instruction::equal(false, left, right), + Token::Less => Instruction::less(true, left, right), + Token::LessEqual => Instruction::less_equal(true, left, right), + Token::Greater => Instruction::less_equal(false, left, right), + Token::GreaterEqual => Instruction::less(false, left, right), _ => { return Err(CompileError::ExpectedTokenMultiple { expected: &[ @@ -1289,8 +1201,7 @@ impl<'src> Compiler<'src> { }; let point = Instruction::point( local_register_index, - Operand::Register(register), - r#type.type_code(), + Operand::Register(register, r#type.type_code()), ); self.emit_instruction(point, r#type, start_position); @@ -1310,8 +1221,7 @@ impl<'src> Compiler<'src> { }; let point = Instruction::point( destination, - Operand::Register(local_register_index), - r#type.type_code(), + Operand::Register(local_register_index, r#type.type_code()), ); self.emit_instruction(point, r#type, self.previous_position); @@ -1704,14 +1614,10 @@ impl<'src> Compiler<'src> { fn parse_implicit_return(&mut self) -> Result<(), CompileError> { if matches!(self.get_last_operation(), Some(Operation::POINT)) { - let Point { - destination, - r#type: type_code, - .. - } = Point::from(self.instructions.last().unwrap().0); + let Point { destination, to } = Point::from(self.instructions.last().unwrap().0); let (_, r#type, _) = self.instructions.pop().unwrap(); - let r#return = Instruction::r#return(true, destination, type_code); + let r#return = Instruction::r#return(true, destination, to.as_type()); self.emit_instruction(r#return, r#type, self.current_position); } else if matches!(self.get_last_operation(), Some(Operation::RETURN)) diff --git a/dust-lang/src/instruction/add.rs b/dust-lang/src/instruction/add.rs index be81cc5..f5cf9bb 100644 --- a/dust-lang/src/instruction/add.rs +++ b/dust-lang/src/instruction/add.rs @@ -5,24 +5,18 @@ use super::{Instruction, InstructionFields, Operand, Operation, TypeCode}; pub struct Add { pub destination: u16, pub left: Operand, - pub left_type: TypeCode, pub right: Operand, - pub right_type: TypeCode, } impl From for Add { fn from(instruction: Instruction) -> Self { let destination = instruction.a_field(); let (left, right) = instruction.b_and_c_as_operands(); - let left_type = instruction.b_type(); - let right_type = instruction.c_type(); Add { destination, left, - left_type, right, - right_type, } } } @@ -33,8 +27,8 @@ impl From for Instruction { let a_field = add.destination; let (b_field, b_is_constant) = add.left.as_index_and_constant_flag(); let (c_field, c_is_constant) = add.right.as_index_and_constant_flag(); - let b_type = add.left_type; - let c_type = add.right_type; + let b_type = add.left.as_type(); + let c_type = add.right.as_type(); InstructionFields { operation, @@ -56,15 +50,13 @@ impl Display for Add { let Add { destination, left, - left_type, right, - right_type: _, } = self; - match *left_type { + match left.as_type() { TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination}")?, TypeCode::BYTE => write!(f, "R_BYTE_{destination}")?, - TypeCode::CHARACTER => write!(f, "R_CHAR_{destination}")?, + TypeCode::CHARACTER => write!(f, "R_STR_{destination}")?, TypeCode::FLOAT => write!(f, "R_FLOAT_{destination}")?, TypeCode::INTEGER => write!(f, "R_INT_{destination}")?, TypeCode::STRING => write!(f, "R_STR_{destination}")?, diff --git a/dust-lang/src/instruction/divide.rs b/dust-lang/src/instruction/divide.rs index 8e3fc62..efbcdd6 100644 --- a/dust-lang/src/instruction/divide.rs +++ b/dust-lang/src/instruction/divide.rs @@ -5,24 +5,18 @@ use super::{Instruction, InstructionFields, Operand, Operation, TypeCode}; pub struct Divide { pub destination: u16, pub left: Operand, - pub left_type: TypeCode, pub right: Operand, - pub right_type: TypeCode, } impl From for Divide { fn from(instruction: Instruction) -> Self { let destination = instruction.a_field(); let (left, right) = instruction.b_and_c_as_operands(); - let left_type = instruction.b_type(); - let right_type = instruction.c_type(); Divide { destination, left, - left_type, right, - right_type, } } } @@ -33,8 +27,8 @@ impl From for Instruction { let a_field = divide.destination; let (b_field, b_is_constant) = divide.left.as_index_and_constant_flag(); let (c_field, c_is_constant) = divide.right.as_index_and_constant_flag(); - let b_type = divide.left_type; - let c_type = divide.right_type; + let b_type = divide.left.as_type(); + let c_type = divide.right.as_type(); InstructionFields { operation, @@ -56,11 +50,19 @@ impl Display for Divide { let Divide { destination, left, - left_type: _, right, - right_type: _, } = self; - write!(f, "R{destination} = {left} ÷ {right}",) + match left.as_type() { + TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination}")?, + TypeCode::BYTE => write!(f, "R_BYTE_{destination}")?, + TypeCode::CHARACTER => write!(f, "R_STR_{destination}")?, + TypeCode::FLOAT => write!(f, "R_FLOAT_{destination}")?, + TypeCode::INTEGER => write!(f, "R_INT_{destination}")?, + TypeCode::STRING => write!(f, "R_STR_{destination}")?, + _ => todo!(), + } + + write!(f, " = {left} ÷ {right}",) } } diff --git a/dust-lang/src/instruction/equal.rs b/dust-lang/src/instruction/equal.rs index 987d8db..9122014 100644 --- a/dust-lang/src/instruction/equal.rs +++ b/dust-lang/src/instruction/equal.rs @@ -1,28 +1,22 @@ use std::fmt::{self, Display, Formatter}; -use super::{Instruction, InstructionFields, Operand, Operation, TypeCode}; +use super::{Instruction, InstructionFields, Operand, Operation}; pub struct Equal { pub comparator: bool, pub left: Operand, - pub left_type: TypeCode, pub right: Operand, - pub right_type: TypeCode, } impl From for Equal { fn from(instruction: Instruction) -> Self { let comparator = instruction.d_field(); let (left, right) = instruction.b_and_c_as_operands(); - let left_type = instruction.b_type(); - let right_type = instruction.c_type(); Equal { comparator, left, - left_type, right, - right_type, } } } @@ -33,8 +27,8 @@ impl From for Instruction { let (b_field, b_is_constant) = equal_bool.left.as_index_and_constant_flag(); let (c_field, c_is_constant) = equal_bool.right.as_index_and_constant_flag(); let d_field = equal_bool.comparator; - let b_type = equal_bool.left_type; - let c_type = equal_bool.right_type; + let b_type = equal_bool.left.as_type(); + let c_type = equal_bool.right.as_type(); InstructionFields { operation, @@ -56,9 +50,7 @@ impl Display for Equal { let Equal { comparator, left, - left_type: _, right, - right_type: _, } = self; let operator = if *comparator { "==" } else { "≠" }; diff --git a/dust-lang/src/instruction/less.rs b/dust-lang/src/instruction/less.rs index 43908b8..b06c9a6 100644 --- a/dust-lang/src/instruction/less.rs +++ b/dust-lang/src/instruction/less.rs @@ -1,28 +1,22 @@ use std::fmt::{self, Display, Formatter}; -use super::{Instruction, InstructionFields, Operand, Operation, TypeCode}; +use super::{Instruction, InstructionFields, Operand, Operation}; pub struct Less { pub comparator: bool, pub left: Operand, - pub left_type: TypeCode, pub right: Operand, - pub right_type: TypeCode, } impl From for Less { fn from(instruction: Instruction) -> Self { let comparator = instruction.d_field(); let (left, right) = instruction.b_and_c_as_operands(); - let left_type = instruction.b_type(); - let right_type = instruction.c_type(); Less { comparator, left, - left_type, right, - right_type, } } } @@ -33,8 +27,8 @@ impl From for Instruction { let (b_field, b_is_constant) = less.left.as_index_and_constant_flag(); let (c_field, c_is_constant) = less.right.as_index_and_constant_flag(); let d_field = less.comparator; - let b_type = less.left_type; - let c_type = less.right_type; + let b_type = less.left.as_type(); + let c_type = less.right.as_type(); InstructionFields { operation, @@ -56,9 +50,7 @@ impl Display for Less { let Less { comparator, left, - left_type: _, right, - right_type: _, } = self; let operator = if *comparator { "<" } else { "≥" }; diff --git a/dust-lang/src/instruction/less_equal.rs b/dust-lang/src/instruction/less_equal.rs index f9c0764..3c56803 100644 --- a/dust-lang/src/instruction/less_equal.rs +++ b/dust-lang/src/instruction/less_equal.rs @@ -1,28 +1,22 @@ use std::fmt::{self, Display, Formatter}; -use super::{Instruction, InstructionFields, Operand, Operation, TypeCode}; +use super::{Instruction, InstructionFields, Operand, Operation}; pub struct LessEqual { pub comparator: bool, pub left: Operand, - pub left_type: TypeCode, pub right: Operand, - pub right_type: TypeCode, } impl From for LessEqual { fn from(instruction: Instruction) -> Self { let comparator = instruction.d_field(); let (left, right) = instruction.b_and_c_as_operands(); - let left_type = instruction.b_type(); - let right_type = instruction.c_type(); LessEqual { comparator, left, - left_type, right, - right_type, } } } @@ -33,8 +27,8 @@ impl From for Instruction { let (b_field, b_is_constant) = less_equal_byte.left.as_index_and_constant_flag(); let (c_field, c_is_constant) = less_equal_byte.right.as_index_and_constant_flag(); let d_field = less_equal_byte.comparator; - let b_type = less_equal_byte.left_type; - let c_type = less_equal_byte.right_type; + let b_type = less_equal_byte.left.as_type(); + let c_type = less_equal_byte.right.as_type(); InstructionFields { operation, @@ -56,9 +50,7 @@ impl Display for LessEqual { let LessEqual { comparator, left, - left_type: _, right, - right_type: _, } = self; let operator = if *comparator { "≤" } else { ">" }; diff --git a/dust-lang/src/instruction/mod.rs b/dust-lang/src/instruction/mod.rs index 8e130d7..3ac87e8 100644 --- a/dust-lang/src/instruction/mod.rs +++ b/dust-lang/src/instruction/mod.rs @@ -278,12 +278,52 @@ impl Instruction { *self = fields.build(); } - pub fn point(destination: u16, to: Operand, r#type: TypeCode) -> Instruction { - Instruction::from(Point { - destination, - to, - r#type, - }) + pub fn as_operand(&self) -> Operand { + match self.operation() { + Operation::POINT => { + let Point { destination, to } = Point::from(*self); + + Operand::Register(destination, to.as_type()) + } + Operation::LOAD_ENCODED => { + let LoadEncoded { + destination, + value_type, + .. + } = LoadEncoded::from(*self); + + Operand::Register(destination, value_type) + } + Operation::LOAD_CONSTANT => { + let LoadConstant { + constant_type, + constant_index, + .. + } = LoadConstant::from(*self); + + Operand::Constant(constant_index, constant_type) + } + Operation::LOAD_LIST => { + let LoadList { destination, .. } = LoadList::from(*self); + + Operand::Register(destination, TypeCode::LIST) + } + Operation::LOAD_FUNCTION => { + let LoadFunction { destination, .. } = LoadFunction::from(*self); + + Operand::Register(destination, TypeCode::FUNCTION) + } + Operation::LOAD_SELF => { + let LoadSelf { destination, .. } = LoadSelf::from(*self); + + Operand::Register(destination, TypeCode::FUNCTION) + } + _ => todo!(), + } + } + + pub fn point(destination: u16, to: Operand) -> Instruction { + Instruction::from(Point { destination, to }) } pub fn close(from: u16, to: u16) -> Instruction { @@ -341,131 +381,67 @@ impl Instruction { }) } - pub fn add( - destination: u16, - left: Operand, - left_type: TypeCode, - right: Operand, - right_type: TypeCode, - ) -> Instruction { + pub fn add(destination: u16, left: Operand, right: Operand) -> Instruction { Instruction::from(Add { destination, left, - left_type, right, - right_type, }) } - pub fn subtract( - destination: u16, - left: Operand, - left_type: TypeCode, - right: Operand, - right_type: TypeCode, - ) -> Instruction { + pub fn subtract(destination: u16, left: Operand, right: Operand) -> Instruction { Instruction::from(Subtract { destination, left, - left_type, right, - right_type, }) } - pub fn multiply( - destination: u16, - left: Operand, - left_type: TypeCode, - right: Operand, - right_type: TypeCode, - ) -> Instruction { + pub fn multiply(destination: u16, left: Operand, right: Operand) -> Instruction { Instruction::from(Multiply { destination, left, - left_type, right, - right_type, }) } - pub fn divide( - destination: u16, - left: Operand, - left_type: TypeCode, - right: Operand, - right_type: TypeCode, - ) -> Instruction { + pub fn divide(destination: u16, left: Operand, right: Operand) -> Instruction { Instruction::from(Divide { destination, left, - left_type, right, - right_type, }) } - pub fn modulo( - destination: u16, - left: Operand, - left_type: TypeCode, - right: Operand, - right_type: TypeCode, - ) -> Instruction { + pub fn modulo(destination: u16, left: Operand, right: Operand) -> Instruction { Instruction::from(Modulo { destination, left, - left_type, right, - right_type, }) } - pub fn equal( - comparator: bool, - left: Operand, - left_type: TypeCode, - right: Operand, - right_type: TypeCode, - ) -> Instruction { + pub fn equal(comparator: bool, left: Operand, right: Operand) -> Instruction { Instruction::from(Equal { comparator, left, - left_type, right, - right_type, }) } - pub fn less( - comparator: bool, - left: Operand, - left_type: TypeCode, - right: Operand, - right_type: TypeCode, - ) -> Instruction { + pub fn less(comparator: bool, left: Operand, right: Operand) -> Instruction { Instruction::from(Less { comparator, left, - left_type, right, - right_type, }) } - pub fn less_equal( - comparator: bool, - left: Operand, - left_type: TypeCode, - right: Operand, - right_type: TypeCode, - ) -> Instruction { + pub fn less_equal(comparator: bool, left: Operand, right: Operand) -> Instruction { Instruction::from(LessEqual { comparator, left, - left_type, right, - right_type, }) } @@ -552,55 +528,20 @@ impl Instruction { self.operation().is_comparison() } - pub fn as_argument(&self) -> Option { - match self.operation() { - Operation::LOAD_CONSTANT => Some(Operand::Constant(self.b_field())), - Operation::POINT - | Operation::LOAD_ENCODED - | 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 => Some(Operand::Register(self.a_field())), - Operation::CALL_NATIVE => { - let function = NativeFunction::from(self.b_field()); - - if function.returns_value() { - Some(Operand::Register(self.a_field())) - } else { - None - } - } - _ => None, - } - } - pub fn b_as_operand(&self) -> Operand { if self.b_is_constant() { - Operand::Constant(self.b_field()) + Operand::Constant(self.b_field(), self.b_type()) } else { - Operand::Register(self.b_field()) + Operand::Register(self.b_field(), self.b_type()) } } pub fn b_and_c_as_operands(&self) -> (Operand, Operand) { - let left = if self.b_is_constant() { - Operand::Constant(self.b_field()) - } else { - Operand::Register(self.b_field()) - }; + let left = self.b_as_operand(); let right = if self.c_is_constant() { - Operand::Constant(self.c_field()) + Operand::Constant(self.c_field(), self.c_type()) } else { - Operand::Register(self.c_field()) + Operand::Register(self.c_field(), self.c_type()) }; (left, right) @@ -684,30 +625,37 @@ impl Display for Instruction { #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Operand { - Constant(u16), - Register(u16), + Constant(u16, TypeCode), + Register(u16, TypeCode), } impl Operand { pub fn index(&self) -> u16 { match self { - Operand::Constant(index) => *index, - Operand::Register(index) => *index, + Operand::Constant(index, _) => *index, + Operand::Register(index, _) => *index, } } pub fn is_constant(&self) -> bool { - matches!(self, Operand::Constant(_)) + matches!(self, Operand::Constant(_, _)) } pub fn is_register(&self) -> bool { - matches!(self, Operand::Register(_)) + matches!(self, Operand::Register(_, _)) } pub fn as_index_and_constant_flag(&self) -> (u16, bool) { match self { - Operand::Constant(index) => (*index, true), - Operand::Register(index) => (*index, false), + Operand::Constant(index, _) => (*index, true), + Operand::Register(index, _) => (*index, false), + } + } + + pub fn as_type(&self) -> TypeCode { + match self { + Operand::Constant(_, r#type) => *r#type, + Operand::Register(_, r#type) => *r#type, } } } @@ -715,8 +663,26 @@ impl Operand { impl Display for Operand { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Operand::Constant(index) => write!(f, "{index}"), - Operand::Register(index) => write!(f, "{index}"), + Operand::Constant(index, r#type) => match *r#type { + TypeCode::BOOLEAN => write!(f, "C_{}", index), + TypeCode::CHARACTER => write!(f, "C_{}", index), + TypeCode::INTEGER => write!(f, "C_{}", index), + TypeCode::FLOAT => write!(f, "C_{}", index), + TypeCode::STRING => write!(f, "C_{}", index), + TypeCode::LIST => write!(f, "C_{}", index), + TypeCode::FUNCTION => write!(f, "C_{}", index), + _ => panic!("Unknown type code: {}", r#type.0), + }, + Operand::Register(index, r#type) => match *r#type { + TypeCode::BOOLEAN => write!(f, "R_BOOL_{}", index), + TypeCode::CHARACTER => write!(f, "R_CHAR_{}", index), + TypeCode::INTEGER => write!(f, "R_INT_{}", index), + TypeCode::FLOAT => write!(f, "R_FLOAT_{}", index), + TypeCode::STRING => write!(f, "R_STR_{}", index), + TypeCode::LIST => write!(f, "R_LIST_{}", index), + TypeCode::FUNCTION => write!(f, "R_FN_{}", index), + _ => panic!("Unknown type code: {}", r#type.0), + }, } } } @@ -729,10 +695,8 @@ mod tests { fn decode_operation() { let instruction = Instruction::add( 42, - Operand::Constant(4), - TypeCode::STRING, - Operand::Register(2), - TypeCode::CHARACTER, + Operand::Constant(4, TypeCode::STRING), + Operand::Register(2, TypeCode::CHARACTER), ); assert_eq!(instruction.operation(), Operation::ADD); @@ -742,10 +706,8 @@ mod tests { fn decode_a_field() { let instruction = Instruction::add( 42, - Operand::Constant(4), - TypeCode::STRING, - Operand::Register(2), - TypeCode::CHARACTER, + Operand::Constant(4, TypeCode::STRING), + Operand::Register(2, TypeCode::CHARACTER), ); assert_eq!(42, instruction.a_field()); @@ -755,10 +717,8 @@ mod tests { fn decode_b_field() { let instruction = Instruction::add( 42, - Operand::Constant(4), - TypeCode::STRING, - Operand::Register(2), - TypeCode::CHARACTER, + Operand::Constant(4, TypeCode::STRING), + Operand::Register(2, TypeCode::CHARACTER), ); assert_eq!(4, instruction.b_field()); @@ -768,10 +728,8 @@ mod tests { fn decode_c_field() { let instruction = Instruction::add( 42, - Operand::Constant(4), - TypeCode::STRING, - Operand::Register(2), - TypeCode::CHARACTER, + Operand::Constant(4, TypeCode::STRING), + Operand::Register(2, TypeCode::CHARACTER), ); assert_eq!(2, instruction.c_field()); @@ -781,10 +739,8 @@ mod tests { fn decode_d_field() { let instruction = Instruction::add( 42, - Operand::Constant(4), - TypeCode::STRING, - Operand::Register(2), - TypeCode::CHARACTER, + Operand::Constant(4, TypeCode::STRING), + Operand::Register(2, TypeCode::CHARACTER), ); assert!(!instruction.d_field()); @@ -794,10 +750,8 @@ mod tests { fn decode_b_is_constant() { let instruction = Instruction::add( 42, - Operand::Constant(4), - TypeCode::STRING, - Operand::Register(2), - TypeCode::CHARACTER, + Operand::Constant(4, TypeCode::STRING), + Operand::Register(2, TypeCode::CHARACTER), ); assert!(instruction.b_is_constant()); @@ -807,10 +761,8 @@ mod tests { fn decode_c_is_constant() { let instruction = Instruction::add( 42, - Operand::Register(2), - TypeCode::STRING, - Operand::Constant(4), - TypeCode::CHARACTER, + Operand::Register(2, TypeCode::STRING), + Operand::Constant(4, TypeCode::CHARACTER), ); assert!(instruction.c_is_constant()); @@ -820,10 +772,8 @@ mod tests { fn decode_b_type() { let instruction = Instruction::add( 42, - Operand::Constant(4), - TypeCode::STRING, - Operand::Register(2), - TypeCode::CHARACTER, + Operand::Constant(4, TypeCode::STRING), + Operand::Register(2, TypeCode::CHARACTER), ); assert_eq!(TypeCode::STRING, instruction.b_type()); @@ -833,10 +783,8 @@ mod tests { fn decode_c_type() { let instruction = Instruction::add( 42, - Operand::Constant(4), - TypeCode::STRING, - Operand::Register(2), - TypeCode::CHARACTER, + Operand::Constant(4, TypeCode::STRING), + Operand::Register(2, TypeCode::CHARACTER), ); assert_eq!(TypeCode::CHARACTER, instruction.c_type()); diff --git a/dust-lang/src/instruction/modulo.rs b/dust-lang/src/instruction/modulo.rs index 5aa4fb6..422ec97 100644 --- a/dust-lang/src/instruction/modulo.rs +++ b/dust-lang/src/instruction/modulo.rs @@ -5,24 +5,18 @@ use super::{Instruction, InstructionFields, Operand, Operation, TypeCode}; pub struct Modulo { pub destination: u16, pub left: Operand, - pub left_type: TypeCode, pub right: Operand, - pub right_type: TypeCode, } impl From for Modulo { fn from(instruction: Instruction) -> Self { let destination = instruction.a_field(); let (left, right) = instruction.b_and_c_as_operands(); - let left_type = instruction.b_type(); - let right_type = instruction.c_type(); Modulo { destination, left, - left_type, right, - right_type, } } } @@ -33,8 +27,8 @@ impl From for Instruction { let a_field = modulo.destination; let (b_field, b_is_constant) = modulo.left.as_index_and_constant_flag(); let (c_field, c_is_constant) = modulo.right.as_index_and_constant_flag(); - let b_type = modulo.left_type; - let c_type = modulo.right_type; + let b_type = modulo.left.as_type(); + let c_type = modulo.right.as_type(); InstructionFields { operation, @@ -56,11 +50,19 @@ impl Display for Modulo { let Modulo { destination, left, - left_type: _, right, - right_type: _, } = self; - write!(f, "R{destination} = {left} % {right}",) + match left.as_type() { + TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination}")?, + TypeCode::BYTE => write!(f, "R_BYTE_{destination}")?, + TypeCode::CHARACTER => write!(f, "R_STR_{destination}")?, + TypeCode::FLOAT => write!(f, "R_FLOAT_{destination}")?, + TypeCode::INTEGER => write!(f, "R_INT_{destination}")?, + TypeCode::STRING => write!(f, "R_STR_{destination}")?, + _ => todo!(), + } + + write!(f, " = {left} % {right}",) } } diff --git a/dust-lang/src/instruction/multiply.rs b/dust-lang/src/instruction/multiply.rs index 76b1e7c..785b67f 100644 --- a/dust-lang/src/instruction/multiply.rs +++ b/dust-lang/src/instruction/multiply.rs @@ -5,24 +5,18 @@ use super::{Instruction, InstructionFields, Operand, Operation, TypeCode}; pub struct Multiply { pub destination: u16, pub left: Operand, - pub left_type: TypeCode, pub right: Operand, - pub right_type: TypeCode, } impl From for Multiply { fn from(instruction: Instruction) -> Self { let destination = instruction.a_field(); let (left, right) = instruction.b_and_c_as_operands(); - let left_type = instruction.b_type(); - let right_type = instruction.c_type(); Multiply { destination, left, - left_type, right, - right_type, } } } @@ -33,8 +27,8 @@ impl From for Instruction { let a_field = multiply.destination; let (b_field, b_is_constant) = multiply.left.as_index_and_constant_flag(); let (c_field, c_is_constant) = multiply.right.as_index_and_constant_flag(); - let b_type = multiply.left_type; - let c_type = multiply.right_type; + let b_type = multiply.left.as_type(); + let c_type = multiply.right.as_type(); InstructionFields { operation, @@ -56,11 +50,19 @@ impl Display for Multiply { let Multiply { destination, left, - left_type: _, right, - right_type: _, } = self; - write!(f, "R{destination} = {left} ✕ {right}",) + match left.as_type() { + TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination}")?, + TypeCode::BYTE => write!(f, "R_BYTE_{destination}")?, + TypeCode::CHARACTER => write!(f, "R_STR_{destination}")?, + TypeCode::FLOAT => write!(f, "R_FLOAT_{destination}")?, + TypeCode::INTEGER => write!(f, "R_INT_{destination}")?, + TypeCode::STRING => write!(f, "R_STR_{destination}")?, + _ => todo!(), + } + + write!(f, " = {left} ✕ {right}",) } } diff --git a/dust-lang/src/instruction/point.rs b/dust-lang/src/instruction/point.rs index 70d3504..93bd206 100644 --- a/dust-lang/src/instruction/point.rs +++ b/dust-lang/src/instruction/point.rs @@ -7,7 +7,6 @@ use super::{InstructionFields, Operand, TypeCode}; pub struct Point { pub destination: u16, pub to: Operand, - pub r#type: TypeCode, } impl From for Point { @@ -15,7 +14,6 @@ impl From for Point { Point { destination: instruction.a_field(), to: instruction.b_as_operand(), - r#type: instruction.b_type(), } } } @@ -25,7 +23,7 @@ impl From for Instruction { let operation = Operation::POINT; let a_field = r#move.destination; let (b_field, b_is_constant) = r#move.to.as_index_and_constant_flag(); - let b_type = r#move.r#type; + let b_type = r#move.to.as_type(); InstructionFields { operation, @@ -41,13 +39,9 @@ impl From for Instruction { impl Display for Point { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let Point { - destination, - to, - r#type, - } = self; + let Point { destination, to } = self; - match *r#type { + match to.as_type() { TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination} -> R_BOOL_{to}"), TypeCode::BYTE => write!(f, "R_BYTE_{destination} -> R_BYTE_{to}"), TypeCode::CHARACTER => write!(f, "R_CHAR_{destination} -> R_CHAR_{to}"), diff --git a/dust-lang/src/instruction/subtract.rs b/dust-lang/src/instruction/subtract.rs index 1381788..f82911a 100644 --- a/dust-lang/src/instruction/subtract.rs +++ b/dust-lang/src/instruction/subtract.rs @@ -5,24 +5,18 @@ use super::{Instruction, InstructionFields, Operand, Operation, TypeCode}; pub struct Subtract { pub destination: u16, pub left: Operand, - pub left_type: TypeCode, pub right: Operand, - pub right_type: TypeCode, } impl From for Subtract { fn from(instruction: Instruction) -> Self { let destination = instruction.a_field(); let (left, right) = instruction.b_and_c_as_operands(); - let left_type = instruction.b_type(); - let right_type = instruction.c_type(); Subtract { destination, left, - left_type, right, - right_type, } } } @@ -33,8 +27,8 @@ impl From for Instruction { let a_field = subtract.destination; let (b_field, b_is_constant) = subtract.left.as_index_and_constant_flag(); let (c_field, c_is_constant) = subtract.right.as_index_and_constant_flag(); - let b_type = subtract.left_type; - let c_type = subtract.right_type; + let b_type = subtract.left.as_type(); + let c_type = subtract.right.as_type(); InstructionFields { operation, @@ -56,11 +50,19 @@ impl Display for Subtract { let Subtract { destination, left, - left_type: _, right, - right_type: _, } = self; - write!(f, "R{destination} = {left} - {right}",) + match left.as_type() { + TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination}")?, + TypeCode::BYTE => write!(f, "R_BYTE_{destination}")?, + TypeCode::CHARACTER => write!(f, "R_STR_{destination}")?, + TypeCode::FLOAT => write!(f, "R_FLOAT_{destination}")?, + TypeCode::INTEGER => write!(f, "R_INT_{destination}")?, + TypeCode::STRING => write!(f, "R_STR_{destination}")?, + _ => todo!(), + } + + write!(f, " = {left} - {right}",) } } diff --git a/dust-lang/src/instruction/type_code.rs b/dust-lang/src/instruction/type_code.rs index 228d699..11c3746 100644 --- a/dust-lang/src/instruction/type_code.rs +++ b/dust-lang/src/instruction/type_code.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)] pub struct TypeCode(pub u8); impl TypeCode { @@ -11,6 +11,8 @@ impl TypeCode { pub const FLOAT: TypeCode = TypeCode(4); pub const INTEGER: TypeCode = TypeCode(5); pub const STRING: TypeCode = TypeCode(6); + pub const LIST: TypeCode = TypeCode(7); + pub const FUNCTION: TypeCode = TypeCode(8); pub fn panic_from_unknown_code(self) -> ! { panic!("Unknown type code: {}", self.0);