From ae79c2bac1b35098b878992598bb8b0844d09cec Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 3 Feb 2025 13:39:00 -0500 Subject: [PATCH] Continue value overhaul --- dust-lang/src/compiler/mod.rs | 572 ++++++++++++---------- dust-lang/src/instruction/add.rs | 15 +- dust-lang/src/instruction/call.rs | 7 +- dust-lang/src/instruction/less.rs | 9 +- dust-lang/src/instruction/less_equal.rs | 9 +- dust-lang/src/instruction/load_encoded.rs | 6 +- dust-lang/src/instruction/mod.rs | 197 ++++++-- dust-lang/src/instruction/point.rs | 2 +- dust-lang/src/instruction/return.rs | 18 +- dust-lang/src/instruction/test.rs | 2 +- dust-lang/src/instruction/type_code.rs | 4 - dust-lang/src/vm/action.rs | 2 +- 12 files changed, 497 insertions(+), 346 deletions(-) diff --git a/dust-lang/src/compiler/mod.rs b/dust-lang/src/compiler/mod.rs index 195ab70..1df4c1b 100644 --- a/dust-lang/src/compiler/mod.rs +++ b/dust-lang/src/compiler/mod.rs @@ -118,10 +118,6 @@ pub struct Compiler<'src> { /// [`Compiler::finish`] is called. stack_size: usize, - /// Register usage tracker. This is used to determine the next available register of each - /// type. - register_usage: RegisterUsage, - /// Index of the current block. This is used to determine the scope of locals and is incremented /// when a new block is entered. block_index: u8, @@ -169,7 +165,6 @@ impl<'src> Compiler<'src> { argument_lists: Vec::new(), stack_size: 0, lexer, - register_usage: RegisterUsage::default(), block_index: 0, current_scope: Scope::default(), prototype_index: 0, @@ -321,7 +316,7 @@ impl<'src> Compiler<'src> { if let Some(index) = self .constant_strings .iter() - .position(|constant| constant == &string) + .position(|constant| constant == string) { index as u16 } else { @@ -418,64 +413,116 @@ impl<'src> Compiler<'src> { self.instructions.push((instruction, r#type, position)); } - fn emit_constant_character( - &mut self, - character: char, - position: Span, - ) -> Result<(), CompileError> { - let constant_index = self.constant_characters.len() as u16; - - self.constant_characters.push(character); - - let destination = self.register_usage.next_character_register(); - let load_constant = Instruction::load_constant(destination, constant_index, false); - - self.emit_instruction(load_constant, Type::Character, position); - - Ok(()) + fn next_boolean_register(&self) -> u16 { + self.instructions + .iter() + .filter_map(|(instruction, r#type, _)| { + if r#type == &Type::Boolean { + Some(instruction.a_field()) + } else { + None + } + }) + .max() + .map_or(0, |register| register + 1) } - fn emit_constant_float(&mut self, float: f64, position: Span) -> Result<(), CompileError> { - let constant_index = self.constant_floats.len() as u16; - - self.constant_floats.push(float); - - let destination = self.register_usage.next_float_register(); - let load_constant = Instruction::load_constant(destination, constant_index, false); - - self.emit_instruction(load_constant, Type::Float, position); - - Ok(()) + fn next_byte_register(&self) -> u16 { + self.instructions + .iter() + .filter_map(|(instruction, r#type, _)| { + if r#type == &Type::Byte { + Some(instruction.a_field()) + } else { + None + } + }) + .max() + .map_or(0, |register| register + 1) } - fn emit_constant_integer(&mut self, integer: i64, position: Span) -> Result<(), CompileError> { - let constant_index = self.constant_integers.len() as u16; - - self.constant_integers.push(integer); - - let destination = self.register_usage.next_integer_register(); - let load_constant = Instruction::load_constant(destination, constant_index, false); - - self.emit_instruction(load_constant, Type::Integer, position); - - Ok(()) + fn next_character_register(&self) -> u16 { + self.instructions + .iter() + .filter_map(|(instruction, r#type, _)| { + if r#type == &Type::Character { + Some(instruction.a_field()) + } else { + None + } + }) + .max() + .map_or(0, |register| register + 1) } - fn emit_constant_string( - &mut self, - string: DustString, - position: Span, - ) -> Result<(), CompileError> { - let constant_index = self.constant_strings.len() as u16; + fn next_float_register(&self) -> u16 { + self.instructions + .iter() + .filter_map(|(instruction, r#type, _)| { + if r#type == &Type::Float { + Some(instruction.a_field()) + } else { + None + } + }) + .max() + .map_or(0, |register| register + 1) + } - self.constant_strings.push(string); + fn next_integer_register(&self) -> u16 { + self.instructions + .iter() + .filter_map(|(instruction, r#type, _)| { + if r#type == &Type::Integer { + Some(instruction.a_field()) + } else { + None + } + }) + .max() + .map_or(0, |register| register + 1) + } - let destination = self.register_usage.next_string_register(); - let load_constant = Instruction::load_constant(destination, constant_index, false); + fn next_string_register(&self) -> u16 { + self.instructions + .iter() + .filter_map(|(instruction, r#type, _)| { + if r#type == &Type::String { + Some(instruction.a_field()) + } else { + None + } + }) + .max() + .map_or(0, |register| register + 1) + } - self.emit_instruction(load_constant, Type::String, position); + fn next_list_register(&self) -> u16 { + self.instructions + .iter() + .filter_map(|(instruction, r#type, _)| { + if matches!(r#type, Type::List(_)) { + Some(instruction.a_field()) + } else { + None + } + }) + .max() + .map_or(0, |register| register + 1) + } - Ok(()) + fn next_function_register(&self) -> u16 { + self.instructions + .iter() + .filter_map(|(instruction, r#type, _)| { + if matches!(r#type, Type::Function(_)) { + Some(instruction.a_field()) + } else { + None + } + }) + .max() + .map_or(0, |register| register + 1) } fn parse_boolean(&mut self) -> Result<(), CompileError> { @@ -486,7 +533,7 @@ impl<'src> Compiler<'src> { let boolean = text.parse::().unwrap(); let boolean_encoded = boolean as u16; - let destination = self.register_usage.next_boolean_register(); + let destination = self.next_boolean_register(); let load_encoded = Instruction::load_encoded(destination, boolean_encoded, TypeCode::BOOLEAN, false); @@ -510,7 +557,7 @@ impl<'src> Compiler<'src> { let byte = u8::from_str_radix(&text[2..], 16) .map_err(|error| CompileError::ParseIntError { error, position })?; - let destination = self.register_usage.next_byte_register(); + let destination = self.next_byte_register(); let load_encoded = Instruction::load_encoded(destination, byte as u16, TypeCode::BYTE, true); @@ -536,7 +583,7 @@ impl<'src> Compiler<'src> { self.constant_characters.push(character); - let destination = self.register_usage.next_character_register(); + let destination = self.next_character_register(); let load_constant = Instruction::load_constant(destination, constant_index, false); self.emit_instruction(load_constant, Type::Character, position); @@ -567,7 +614,7 @@ impl<'src> Compiler<'src> { self.constant_floats.push(float); - let destination = self.register_usage.next_float_register(); + let destination = self.next_float_register(); let load_constant = Instruction::load_constant(destination, constant_index, false); self.emit_instruction(load_constant, Type::Float, position); @@ -604,7 +651,7 @@ impl<'src> Compiler<'src> { self.constant_integers.push(integer); - let destination = self.register_usage.next_integer_register(); + let destination = self.next_integer_register(); let load_constant = Instruction::load_constant(destination, constant_index, false); self.emit_instruction(load_constant, Type::Integer, position); @@ -629,7 +676,7 @@ impl<'src> Compiler<'src> { self.constant_strings.push(DustString::from(text)); - let destination = self.register_usage.next_string_register(); + let destination = self.next_string_register(); let load_constant = Instruction::load_constant(destination, constant_index, false); self.emit_instruction(load_constant, Type::String, position); @@ -661,7 +708,8 @@ 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, &previous_type)?; if push_back { self.instructions.push(( @@ -672,21 +720,12 @@ impl<'src> Compiler<'src> { } let (destination, type_code) = match previous_type { - Type::Boolean => ( - self.register_usage.next_boolean_register(), - TypeCode::BOOLEAN, - ), - Type::Byte => (self.register_usage.next_byte_register(), TypeCode::BYTE), - Type::Character => ( - self.register_usage.next_character_register(), - TypeCode::CHARACTER, - ), - Type::Float => (self.register_usage.next_float_register(), TypeCode::FLOAT), - Type::Integer => ( - self.register_usage.next_integer_register(), - TypeCode::INTEGER, - ), - Type::String => (self.register_usage.next_string_register(), TypeCode::STRING), + Type::Boolean => (self.next_boolean_register(), TypeCode::BOOLEAN), + Type::Byte => (self.next_byte_register(), TypeCode::BYTE), + Type::Character => (self.next_character_register(), TypeCode::CHARACTER), + Type::Float => (self.next_float_register(), TypeCode::FLOAT), + Type::Integer => (self.next_integer_register(), TypeCode::INTEGER), + Type::String => (self.next_string_register(), TypeCode::STRING), _ => match operator { Token::Minus => { return Err(CompileError::CannotNegateType { @@ -723,29 +762,54 @@ impl<'src> Compiler<'src> { fn handle_binary_argument( &mut self, instruction: &Instruction, + instruction_type: &Type, ) -> Result<(Operand, bool), CompileError> { let (argument, push_back) = match instruction.operation() { - Operation::LOAD_CONSTANT => (Operand::Constant(instruction.b_field()), false), + Operation::LOAD_CONSTANT => match instruction_type { + Type::Character => (Operand::ConstantCharacter(instruction.b_field()), false), + Type::Float => (Operand::ConstantFloat(instruction.b_field()), false), + Type::Integer => (Operand::ConstantInteger(instruction.b_field()), false), + Type::String => (Operand::ConstantString(instruction.b_field()), false), + unsupported => panic!("Unsupported type: {unsupported}"), + }, Operation::POINT | Operation::LOAD_ENCODED | Operation::LOAD_LIST - | Operation::LOAD_SELF | Operation::ADD | Operation::SUBTRACT | Operation::MULTIPLY | Operation::DIVIDE | Operation::MODULO + | Operation::LOAD_SELF | Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL | Operation::NEGATE | Operation::NOT - | Operation::CALL => (Operand::Register(instruction.a_field()), true), + | Operation::CALL => match instruction_type { + Type::Boolean => (Operand::RegisterBoolean(instruction.a_field()), true), + Type::Byte => (Operand::RegisterByte(instruction.a_field()), true), + Type::Character => (Operand::RegisterCharacter(instruction.a_field()), true), + Type::Float => (Operand::RegisterFloat(instruction.a_field()), true), + Type::Integer => (Operand::RegisterInteger(instruction.a_field()), true), + Type::String => (Operand::RegisterString(instruction.a_field()), true), + unsupported => panic!("{unsupported} type is not supported here"), + }, Operation::CALL_NATIVE => { let function = NativeFunction::from(instruction.b_field()); if function.returns_value() { - (Operand::Register(instruction.a_field()), true) + match instruction_type { + Type::Boolean => (Operand::RegisterBoolean(instruction.a_field()), true), + Type::Byte => (Operand::RegisterByte(instruction.a_field()), true), + Type::Character => { + (Operand::RegisterCharacter(instruction.a_field()), true) + } + Type::Float => (Operand::RegisterFloat(instruction.a_field()), true), + Type::Integer => (Operand::RegisterInteger(instruction.a_field()), true), + Type::String => (Operand::RegisterString(instruction.a_field()), true), + unsupported => panic!("{unsupported} type is not supported here"), + } } else { return Err(CompileError::ExpectedExpression { found: self.previous_token.to_owned(), @@ -772,11 +836,17 @@ 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, &left_type)?; let left_is_mutable_local = self.locals.iter().any(|local| { matches!( left, - Operand::Register(register) if register == local.register_index + Operand::RegisterBoolean(register) + | Operand::RegisterByte(register) + | Operand::RegisterCharacter(register) + | Operand::RegisterFloat(register) + | Operand::RegisterInteger(register) + | Operand::RegisterString(register) + if register == local.register_index ) && local.is_mutable }); @@ -820,7 +890,8 @@ 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, &right_type)?; check_math_type(&right_type, operator, &right_position)?; check_math_types( @@ -855,25 +926,33 @@ impl<'src> Compiler<'src> { }; let destination = if is_assignment { match left { - Operand::Register(register) => register, - Operand::Constant(_) => match left_type { - Type::Boolean => self.register_usage.next_boolean_register(), - Type::Byte => self.register_usage.next_byte_register(), - Type::Character => self.register_usage.next_character_register(), - Type::Float => self.register_usage.next_float_register(), - Type::Integer => self.register_usage.next_integer_register(), - Type::String => self.register_usage.next_string_register(), + Operand::RegisterBoolean(register) + | Operand::RegisterByte(register) + | Operand::RegisterCharacter(register) + | Operand::RegisterFloat(register) + | Operand::RegisterInteger(register) + | Operand::RegisterString(register) => register, + Operand::ConstantCharacter(_) + | Operand::ConstantFloat(_) + | Operand::ConstantInteger(_) + | Operand::ConstantString(_) => 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!(), }, } } else { match left_type { - Type::Boolean => self.register_usage.next_boolean_register(), - Type::Byte => self.register_usage.next_byte_register(), - Type::Character => self.register_usage.next_character_register(), - Type::Float => self.register_usage.next_float_register(), - Type::Integer => self.register_usage.next_integer_register(), - Type::String => self.register_usage.next_string_register(), + 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!(), } }; @@ -939,7 +1018,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, &left_type)?; let operator = self.current_token; let operator_position = self.current_position; let rule = ParseRule::from(&operator); @@ -971,7 +1050,8 @@ 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, &right_type)?; // TODO: Check if the right type is a valid type for comparison // TODO: Check if the left and right types are compatible @@ -991,7 +1071,7 @@ impl<'src> Compiler<'src> { .push((right_instruction, right_type, right_position)); } - let destination = self.register_usage.next_boolean_register(); + let destination = self.next_boolean_register(); let comparison = match operator { Token::DoubleEqual => { Instruction::equal(true, left, left_type_code, right, right_type_code) @@ -1039,18 +1119,18 @@ impl<'src> Compiler<'src> { } fn parse_logical_binary(&mut self) -> Result<(), CompileError> { - let (last_instruction, last_type, last_position) = + let (left_instruction, left_type, left_position) = self.instructions .pop() .ok_or_else(|| CompileError::ExpectedExpression { found: self.previous_token.to_owned(), position: self.previous_position, })?; - let operand_register = if last_instruction.yields_value() { - let register = last_instruction.a_field(); + let operand_register = if left_instruction.yields_value() { + let register = left_instruction.a_field(); self.instructions - .push((last_instruction, last_type, last_position)); + .push((left_instruction, left_type, left_position)); register } else { @@ -1081,6 +1161,21 @@ impl<'src> Compiler<'src> { self.advance()?; self.parse_sub_expression(&rule.precedence)?; + let (mut right_instruction, right_type, right_position) = self + .instructions + .pop() + .ok_or_else(|| CompileError::ExpectedExpression { + found: self.previous_token.to_owned(), + position: self.previous_position, + })?; + + // TODO: Check if the right type is a boolean + + right_instruction.set_a_field(left_instruction.a_field()); + + self.instructions + .push((right_instruction, right_type, right_position)); + let instructions_length = self.instructions.len(); for (group_index, instructions) in self.instructions.rchunks_mut(3).enumerate().rev() { @@ -1124,7 +1219,7 @@ impl<'src> Compiler<'src> { } else if let Some(native_function) = NativeFunction::from_str(identifier) { return self.parse_call_native(native_function); } else if self.function_name.as_deref() == Some(identifier) && !self.is_main { - let destination = self.register_usage.next_function_register(); + let destination = self.next_function_register(); let load_self = Instruction::load_self(destination, false); self.emit_instruction(load_self, Type::SelfFunction, start_position); @@ -1176,12 +1271,12 @@ impl<'src> Compiler<'src> { math_instruction.set_a_field(local.register_index); } else { let (register, r#type) = match local.r#type { - Type::Boolean => (self.register_usage.boolean, TypeCode::BOOLEAN), - Type::Byte => (self.register_usage.byte, TypeCode::BYTE), - Type::Character => (self.register_usage.character, TypeCode::CHARACTER), - Type::Float => (self.register_usage.float, TypeCode::FLOAT), - Type::Integer => (self.register_usage.integer, TypeCode::INTEGER), - Type::String => (self.register_usage.string, TypeCode::STRING), + Type::Boolean => (self.next_boolean_register() - 1, TypeCode::BOOLEAN), + Type::Byte => (self.next_byte_register() - 1, TypeCode::BYTE), + Type::Character => (self.next_character_register() - 1, TypeCode::CHARACTER), + Type::Float => (self.next_float_register() - 1, TypeCode::FLOAT), + Type::Integer => (self.next_integer_register() - 1, TypeCode::INTEGER), + Type::String => (self.next_string_register() - 1, TypeCode::STRING), _ => unreachable!(), }; let point = Instruction::point(local.register_index, register, r#type); @@ -1193,21 +1288,12 @@ impl<'src> Compiler<'src> { } let (destination, r#type) = match local.r#type { - Type::Boolean => ( - self.register_usage.next_boolean_register(), - TypeCode::BOOLEAN, - ), - Type::Byte => (self.register_usage.next_byte_register(), TypeCode::BYTE), - Type::Character => ( - self.register_usage.next_character_register(), - TypeCode::CHARACTER, - ), - Type::Float => (self.register_usage.next_float_register(), TypeCode::FLOAT), - Type::Integer => ( - self.register_usage.next_integer_register(), - TypeCode::INTEGER, - ), - Type::String => (self.register_usage.next_string_register(), TypeCode::STRING), + Type::Boolean => (self.next_boolean_register(), TypeCode::BOOLEAN), + Type::Byte => (self.next_byte_register(), TypeCode::BYTE), + Type::Character => (self.next_character_register(), TypeCode::CHARACTER), + Type::Float => (self.next_float_register(), TypeCode::FLOAT), + Type::Integer => (self.next_integer_register(), TypeCode::INTEGER), + Type::String => (self.next_string_register(), TypeCode::STRING), _ => unreachable!(), }; let point = Instruction::point(destination, local.register_index, r#type); @@ -1277,12 +1363,12 @@ impl<'src> Compiler<'src> { self.instructions.pop(); } else { let operand_register = match r#type { - Type::Boolean => self.register_usage.next_boolean_register() - 1, - Type::Byte => self.register_usage.next_byte_register() - 1, - Type::Character => self.register_usage.next_character_register() - 1, - Type::Float => self.register_usage.next_float_register() - 1, - Type::Integer => self.register_usage.next_integer_register() - 1, - Type::String => self.register_usage.next_string_register() - 1, + Type::Boolean => self.next_boolean_register() - 1, + Type::Byte => self.next_byte_register() - 1, + Type::Character => self.next_character_register() - 1, + Type::Float => self.next_float_register() - 1, + Type::Integer => self.next_integer_register() - 1, + Type::String => self.next_string_register() - 1, _ => unreachable!(), }; let test = Instruction::test(operand_register, true); @@ -1400,12 +1486,12 @@ impl<'src> Compiler<'src> { self.instructions.pop(); } else { let operand_register = match r#type { - Type::Boolean => self.register_usage.next_boolean_register() - 1, - Type::Byte => self.register_usage.next_byte_register() - 1, - Type::Character => self.register_usage.next_character_register() - 1, - Type::Float => self.register_usage.next_float_register() - 1, - Type::Integer => self.register_usage.next_integer_register() - 1, - Type::String => self.register_usage.next_string_register() - 1, + Type::Boolean => self.next_boolean_register() - 1, + Type::Byte => self.next_byte_register() - 1, + Type::Character => self.next_character_register() - 1, + Type::Float => self.next_float_register() - 1, + Type::Integer => self.next_integer_register() - 1, + Type::String => self.next_string_register() - 1, _ => unreachable!(), }; let test = Instruction::test(operand_register, true); @@ -1460,12 +1546,12 @@ impl<'src> Compiler<'src> { // TODO: Check if the argument type matches the expected type let argument_register = match argument_type { - Type::Boolean => self.register_usage.boolean, - Type::Byte => self.register_usage.byte, - Type::Character => self.register_usage.character, - Type::Float => self.register_usage.float, - Type::Integer => self.register_usage.integer, - Type::String => self.register_usage.string, + Type::Boolean => self.next_boolean_register() - 1, + Type::Byte => self.next_byte_register() - 1, + Type::Character => self.next_character_register() - 1, + Type::Float => self.next_float_register() - 1, + Type::Integer => self.next_integer_register() - 1, + Type::String => self.next_string_register() - 1, _ => unreachable!(), }; @@ -1479,12 +1565,12 @@ impl<'src> Compiler<'src> { let end = self.previous_position.1; let return_type = function.r#type().return_type; let destination = match return_type { - Type::Boolean => self.register_usage.next_boolean_register(), - Type::Byte => self.register_usage.next_byte_register(), - Type::Character => self.register_usage.next_character_register(), - Type::Float => self.register_usage.next_float_register(), - Type::Integer => self.register_usage.next_integer_register(), - Type::String => self.register_usage.next_string_register(), + 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!(), }; let argument_list_index = self.argument_lists.len() as u16; @@ -1558,18 +1644,25 @@ impl<'src> Compiler<'src> { }; let end = self.current_position.1; let return_register = match self.r#type.return_type { - Type::Boolean => self.register_usage.boolean, - Type::Byte => self.register_usage.byte, - Type::Character => self.register_usage.character, - Type::Float => self.register_usage.float, - Type::Integer => self.register_usage.integer, - Type::String => self.register_usage.string, + Type::Boolean => self.next_boolean_register() - 1, + Type::Byte => self.next_byte_register() - 1, + Type::Character => self.next_character_register() - 1, + Type::Float => self.next_float_register() - 1, + Type::Integer => self.next_integer_register() - 1, + Type::String => self.next_string_register() - 1, _ => unreachable!(), }; - let r#return = Instruction::from(Return { - should_return_value, - return_register, - }); + let return_type_code = match self.r#type.return_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!(), + }; + let r#return = + Instruction::r#return(should_return_value, return_type_code, return_register); self.emit_instruction(r#return, Type::None, Span(start, end)); @@ -1601,7 +1694,7 @@ impl<'src> Compiler<'src> { { // Do nothing if the last instruction is a return or a return followed by a jump } else if self.allow(Token::Semicolon)? { - let r#return = Instruction::r#return(false, 0); + let r#return = Instruction::r#return(false, TypeCode::NONE, 0); self.emit_instruction(r#return, Type::None, self.current_position); } else { @@ -1621,7 +1714,18 @@ impl<'src> Compiler<'src> { })?; let should_return_value = previous_expression_type != Type::None; - let r#return = Instruction::r#return(should_return_value, previous_register); + let return_type_code = match previous_expression_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, + Type::None => TypeCode::NONE, + _ => unreachable!(), + }; + let r#return = + Instruction::r#return(should_return_value, return_type_code, previous_register); self.update_return_type(previous_expression_type.clone())?; self.emit_instruction(r#return, Type::None, self.current_position); @@ -1680,12 +1784,12 @@ impl<'src> Compiler<'src> { // TODO: Check if the actual type matches the explicit type let register_index = match actual_type { - Type::Boolean => self.register_usage.boolean, - Type::Byte => self.register_usage.byte, - Type::Character => self.register_usage.character, - Type::Float => self.register_usage.float, - Type::Integer => self.register_usage.integer, - Type::String => self.register_usage.string, + Type::Boolean => self.next_boolean_register() - 1, + Type::Byte => self.next_byte_register() - 1, + Type::Character => self.next_character_register() - 1, + Type::Float => self.next_float_register() - 1, + Type::Integer => self.next_integer_register() - 1, + Type::String => self.next_string_register() - 1, _ => unreachable!(), }; @@ -1753,12 +1857,12 @@ impl<'src> Compiler<'src> { function_compiler.advance()?; let local_register_index = match r#type { - Type::Boolean => function_compiler.register_usage.next_boolean_register(), - Type::Byte => function_compiler.register_usage.next_byte_register(), - Type::Character => function_compiler.register_usage.next_character_register(), - Type::Float => function_compiler.register_usage.next_float_register(), - Type::Integer => function_compiler.register_usage.next_integer_register(), - Type::String => function_compiler.register_usage.next_string_register(), + Type::Boolean => function_compiler.next_boolean_register(), + Type::Byte => function_compiler.next_byte_register(), + Type::Character => function_compiler.next_character_register(), + Type::Float => function_compiler.next_float_register(), + Type::Integer => function_compiler.next_integer_register(), + Type::String => function_compiler.next_string_register(), _ => unreachable!(), }; let (_, identifier_index) = function_compiler.declare_local( @@ -1807,7 +1911,7 @@ impl<'src> Compiler<'src> { let function_end = function_compiler.previous_position.1; let prototype_index = function_compiler.prototype_index; let chunk = function_compiler.finish(); - let destination = self.register_usage.next_function_register(); + let destination = self.next_function_register(); self.prototypes.push(Arc::new(chunk)); @@ -1868,6 +1972,15 @@ impl<'src> Compiler<'src> { }); } }; + let return_type_code = match function_return_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!(), + }; let is_recursive = last_instruction_type == &Type::SelfFunction; let mut argument_list = Vec::new(); @@ -1878,12 +1991,12 @@ impl<'src> Compiler<'src> { let argument_type = self.get_last_instruction_type(); let argument_register = match argument_type { - Type::Boolean => self.register_usage.next_boolean_register(), - Type::Byte => self.register_usage.next_byte_register(), - Type::Character => self.register_usage.next_character_register(), - Type::Float => self.register_usage.next_float_register(), - Type::Integer => self.register_usage.next_integer_register(), - Type::String => self.register_usage.next_string_register(), + 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!(), }; @@ -1897,8 +2010,14 @@ impl<'src> Compiler<'src> { self.argument_lists.push(argument_list); let end = self.current_position.1; - let destination = self.register_usage.next_function_register(); - let call = Instruction::call(destination, function_register, argument_count, is_recursive); + let destination = self.next_function_register(); + let call = Instruction::call( + destination, + function_register, + argument_count, + return_type_code, + is_recursive, + ); self.emit_instruction(call, function_return_type, Span(start, end)); @@ -1949,90 +2068,3 @@ impl<'src> Compiler<'src> { Ok(()) } } - -#[derive(Debug, Default)] -struct RegisterUsage { - boolean: u16, - byte: u16, - character: u16, - float: u16, - integer: u16, - string: u16, - list: u16, - function: u16, - argument: u16, -} - -impl RegisterUsage { - fn next_boolean_register(&mut self) -> u16 { - let register = self.boolean; - - self.boolean += 1; - - register - } - - fn next_byte_register(&mut self) -> u16 { - let register = self.byte; - - self.byte += 1; - - register - } - - fn next_character_register(&mut self) -> u16 { - let register = self.character; - - self.character += 1; - - register - } - - fn next_float_register(&mut self) -> u16 { - let register = self.float; - - self.float += 1; - - register - } - - fn next_integer_register(&mut self) -> u16 { - let register = self.integer; - - self.integer += 1; - - register - } - - fn next_string_register(&mut self) -> u16 { - let register = self.string; - - self.string += 1; - - register - } - - fn next_list_register(&mut self) -> u16 { - let register = self.list; - - self.list += 1; - - register - } - - fn next_function_register(&mut self) -> u16 { - let register = self.function; - - self.function += 1; - - register - } - - fn next_argument_register(&mut self) -> u16 { - let register = self.argument; - - self.argument += 1; - - register - } -} diff --git a/dust-lang/src/instruction/add.rs b/dust-lang/src/instruction/add.rs index 94230bb..13f2977 100644 --- a/dust-lang/src/instruction/add.rs +++ b/dust-lang/src/instruction/add.rs @@ -58,12 +58,17 @@ impl Display for Add { left, left_type, right, - right_type, + right_type: _, } = self; - write!( - f, - "R{destination} = {left}({left_type}) + {right}({right_type})", - ) + match *left_type { + 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}")?, + unsupported => panic!("Unsupported type code: {}", unsupported.0), + } + + write!(f, " = {left} + {right}",) } } diff --git a/dust-lang/src/instruction/call.rs b/dust-lang/src/instruction/call.rs index ff69533..0d63417 100644 --- a/dust-lang/src/instruction/call.rs +++ b/dust-lang/src/instruction/call.rs @@ -2,12 +2,13 @@ use std::fmt::{self, Display, Formatter}; use crate::{Instruction, Operation}; -use super::InstructionBuilder; +use super::{InstructionBuilder, TypeCode}; pub struct Call { pub destination: u16, pub function_register: u16, pub argument_count: u16, + pub return_type: TypeCode, pub is_recursive: bool, } @@ -16,12 +17,14 @@ impl From for Call { let destination = instruction.a_field(); let function_register = instruction.b_field(); let argument_count = instruction.c_field(); + let return_type = instruction.b_type(); let is_recursive = instruction.d_field(); Call { destination, function_register, argument_count, + return_type, is_recursive, } } @@ -31,6 +34,7 @@ impl From for Instruction { fn from(call: Call) -> Self { let a_field = call.destination; let b_field = call.function_register; + let b_type = call.return_type; let c_field = call.argument_count; let d_field = call.is_recursive; @@ -38,6 +42,7 @@ impl From for Instruction { operation: Operation::CALL, a_field, b_field, + b_type, c_field, d_field, ..Default::default() diff --git a/dust-lang/src/instruction/less.rs b/dust-lang/src/instruction/less.rs index 67fa53b..025b204 100644 --- a/dust-lang/src/instruction/less.rs +++ b/dust-lang/src/instruction/less.rs @@ -56,15 +56,12 @@ impl Display for Less { let Less { comparator, left, - left_type, + left_type: _, right, - right_type, + right_type: _, } = self; let operator = if *comparator { "<" } else { "≥" }; - write!( - f, - "if {left_type}({left}) {operator} {right_type}({right}) {{ JUMP +1 }}" - ) + write!(f, "if {left} {operator} {right} {{ JUMP +1 }}") } } diff --git a/dust-lang/src/instruction/less_equal.rs b/dust-lang/src/instruction/less_equal.rs index fc3238f..d1dbf1a 100644 --- a/dust-lang/src/instruction/less_equal.rs +++ b/dust-lang/src/instruction/less_equal.rs @@ -56,15 +56,12 @@ impl Display for LessEqual { let LessEqual { comparator, left, - left_type, + left_type: _, right, - right_type, + right_type: _, } = self; let operator = if *comparator { "≤" } else { ">" }; - write!( - f, - "if {left_type}({left}) {operator} {right_type}({right}) {{ JUMP +1 }}" - ) + write!(f, "if {left} {operator} {right} {{ JUMP +1 }}") } } diff --git a/dust-lang/src/instruction/load_encoded.rs b/dust-lang/src/instruction/load_encoded.rs index ac8e5b5..a0c347a 100644 --- a/dust-lang/src/instruction/load_encoded.rs +++ b/dust-lang/src/instruction/load_encoded.rs @@ -52,9 +52,9 @@ impl Display for LoadEncoded { } = self; match *r#type { - TypeCode::BOOLEAN => write!(f, "R{destination} = {}", *value != 0)?, - TypeCode::BYTE => write!(f, "R{destination} = {value}")?, - unsupported => unsupported.panic_from_unsupported_code(), + TypeCode::BOOLEAN => write!(f, "R_BOOL_{destination} = {}", *value != 0)?, + TypeCode::BYTE => write!(f, "R_BYTE_{destination} = {value}")?, + unsupported => panic!("Unsupported type code: {}", unsupported.0), }; if *jump_next { diff --git a/dust-lang/src/instruction/mod.rs b/dust-lang/src/instruction/mod.rs index 06458ed..161c705 100644 --- a/dust-lang/src/instruction/mod.rs +++ b/dust-lang/src/instruction/mod.rs @@ -148,7 +148,7 @@ use serde::{Deserialize, Serialize}; use std::fmt::{self, Debug, Display, Formatter}; pub use type_code::TypeCode; -use crate::NativeFunction; +use crate::{NativeFunction, Type}; #[derive(Clone, Copy, Debug)] pub struct InstructionBuilder { @@ -261,15 +261,21 @@ impl Instruction { } pub fn set_a_field(&mut self, bits: u16) { - self.0 = (bits as u64) << 31; + let mut builder = InstructionBuilder::from(&*self); + builder.a_field = bits; + *self = builder.build(); } pub fn set_b_field(&mut self, bits: u16) { - self.0 = (bits as u64) << 47; + let mut builder = InstructionBuilder::from(&*self); + builder.b_field = bits; + *self = builder.build(); } pub fn set_c_field(&mut self, bits: u16) { - self.0 = (bits as u64) << 63; + let mut builder = InstructionBuilder::from(&*self); + builder.c_field = bits; + *self = builder.build(); } pub fn point(destination: u16, to: u16, r#type: TypeCode) -> Instruction { @@ -498,12 +504,14 @@ impl Instruction { destination: u16, function_register: u16, argument_count: u16, + return_type: TypeCode, is_recursive: bool, ) -> Instruction { Instruction::from(Call { destination, function_register, argument_count, + return_type, is_recursive, }) } @@ -520,9 +528,14 @@ impl Instruction { }) } - pub fn r#return(should_return_value: bool, return_register: u16) -> Instruction { + pub fn r#return( + should_return_value: bool, + return_type: TypeCode, + return_register: u16, + ) -> Instruction { Instruction::from(Return { should_return_value, + return_type, return_register, }) } @@ -537,7 +550,13 @@ impl Instruction { pub fn as_argument(&self) -> Option { match self.operation() { - Operation::LOAD_CONSTANT => Some(Operand::Constant(self.b_field())), + Operation::LOAD_CONSTANT => match self.b_type() { + TypeCode::CHARACTER => Some(Operand::ConstantCharacter(self.b_field())), + TypeCode::FLOAT => Some(Operand::ConstantFloat(self.b_field())), + TypeCode::INTEGER => Some(Operand::ConstantInteger(self.b_field())), + TypeCode::STRING => Some(Operand::ConstantString(self.b_field())), + unsupported => panic!("Unsupported type code: {}", unsupported.0), + }, Operation::LOAD_ENCODED | Operation::LOAD_LIST | Operation::LOAD_SELF @@ -551,12 +570,28 @@ impl Instruction { | Operation::LESS_EQUAL | Operation::NEGATE | Operation::NOT - | Operation::CALL => Some(Operand::Register(self.a_field())), + | Operation::CALL => match self.b_type() { + TypeCode::BOOLEAN => Some(Operand::RegisterBoolean(self.b_field())), + TypeCode::BYTE => Some(Operand::RegisterByte(self.b_field())), + TypeCode::CHARACTER => Some(Operand::RegisterCharacter(self.b_field())), + TypeCode::FLOAT => Some(Operand::RegisterFloat(self.b_field())), + TypeCode::INTEGER => Some(Operand::RegisterInteger(self.b_field())), + TypeCode::STRING => Some(Operand::RegisterString(self.b_field())), + unsupported => panic!("Unsupported type code: {}", unsupported.0), + }, Operation::CALL_NATIVE => { let function = NativeFunction::from(self.b_field()); if function.returns_value() { - Some(Operand::Register(self.a_field())) + match function.r#type().return_type { + Type::Boolean => Some(Operand::RegisterBoolean(self.b_field())), + Type::Byte => Some(Operand::RegisterByte(self.b_field())), + Type::Character => Some(Operand::RegisterCharacter(self.b_field())), + Type::Float => Some(Operand::RegisterFloat(self.b_field())), + Type::Integer => Some(Operand::RegisterInteger(self.b_field())), + Type::String => Some(Operand::RegisterString(self.b_field())), + unsupported => panic!("{unsupported} type is not supported here"), + } } else { None } @@ -567,22 +602,46 @@ impl Instruction { pub fn b_as_argument(&self) -> Operand { if self.b_is_constant() { - Operand::Constant(self.b_field()) + match self.b_type() { + TypeCode::CHARACTER => Operand::ConstantCharacter(self.b_field()), + TypeCode::FLOAT => Operand::ConstantFloat(self.b_field()), + TypeCode::INTEGER => Operand::ConstantInteger(self.b_field()), + TypeCode::STRING => Operand::ConstantString(self.b_field()), + unsupported => panic!("Unsupported type code: {}", unsupported.0), + } } else { - Operand::Register(self.b_field()) + match self.b_type() { + TypeCode::BOOLEAN => Operand::RegisterBoolean(self.b_field()), + TypeCode::BYTE => Operand::RegisterByte(self.b_field()), + TypeCode::CHARACTER => Operand::RegisterCharacter(self.b_field()), + TypeCode::FLOAT => Operand::RegisterFloat(self.b_field()), + TypeCode::INTEGER => Operand::RegisterInteger(self.b_field()), + TypeCode::STRING => Operand::RegisterString(self.b_field()), + unsupported => panic!("Unsupported type code: {}", unsupported.0), + } } } 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_argument(); let right = if self.c_is_constant() { - Operand::Constant(self.c_field()) + match self.c_type() { + TypeCode::CHARACTER => Operand::ConstantCharacter(self.c_field()), + TypeCode::FLOAT => Operand::ConstantFloat(self.c_field()), + TypeCode::INTEGER => Operand::ConstantInteger(self.c_field()), + TypeCode::STRING => Operand::ConstantString(self.c_field()), + unsupported => panic!("Unsupported type code: {}", unsupported.0), + } } else { - Operand::Register(self.c_field()) + match self.c_type() { + TypeCode::BOOLEAN => Operand::RegisterBoolean(self.c_field()), + TypeCode::BYTE => Operand::RegisterByte(self.c_field()), + TypeCode::CHARACTER => Operand::RegisterCharacter(self.c_field()), + TypeCode::FLOAT => Operand::RegisterFloat(self.c_field()), + TypeCode::INTEGER => Operand::RegisterInteger(self.c_field()), + TypeCode::STRING => Operand::RegisterString(self.c_field()), + unsupported => panic!("Unsupported type code: {}", unsupported.0), + } }; (left, right) @@ -668,30 +727,68 @@ impl Display for Instruction { #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Operand { - Constant(u16), - Register(u16), + ConstantCharacter(u16), + ConstantFloat(u16), + ConstantInteger(u16), + ConstantString(u16), + RegisterBoolean(u16), + RegisterByte(u16), + RegisterCharacter(u16), + RegisterFloat(u16), + RegisterInteger(u16), + RegisterString(u16), } impl Operand { pub fn index(&self) -> u16 { match self { - Operand::Constant(index) => *index, - Operand::Register(index) => *index, + Operand::ConstantCharacter(index) => *index, + Operand::ConstantFloat(index) => *index, + Operand::ConstantInteger(index) => *index, + Operand::ConstantString(index) => *index, + Operand::RegisterBoolean(index) => *index, + Operand::RegisterByte(index) => *index, + Operand::RegisterCharacter(index) => *index, + Operand::RegisterFloat(index) => *index, + Operand::RegisterInteger(index) => *index, + Operand::RegisterString(index) => *index, } } pub fn is_constant(&self) -> bool { - matches!(self, Operand::Constant(_)) + matches!( + self, + Operand::ConstantCharacter(_) + | Operand::ConstantFloat(_) + | Operand::ConstantInteger(_) + | Operand::ConstantString(_) + ) } pub fn is_register(&self) -> bool { - matches!(self, Operand::Register(_)) + matches!( + self, + Operand::RegisterBoolean(_) + | Operand::RegisterByte(_) + | Operand::RegisterCharacter(_) + | Operand::RegisterFloat(_) + | Operand::RegisterInteger(_) + | Operand::RegisterString(_) + ) } pub fn as_index_and_constant_flag(&self) -> (u16, bool) { match self { - Operand::Constant(index) => (*index, true), - Operand::Register(index) => (*index, false), + Operand::ConstantCharacter(index) => (*index, true), + Operand::ConstantFloat(index) => (*index, true), + Operand::ConstantInteger(index) => (*index, true), + Operand::ConstantString(index) => (*index, true), + Operand::RegisterBoolean(index) => (*index, false), + Operand::RegisterByte(index) => (*index, false), + Operand::RegisterCharacter(index) => (*index, false), + Operand::RegisterFloat(index) => (*index, false), + Operand::RegisterInteger(index) => (*index, false), + Operand::RegisterString(index) => (*index, false), } } } @@ -699,8 +796,16 @@ impl Operand { impl Display for Operand { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Operand::Constant(index) => write!(f, "C{index}"), - Operand::Register(index) => write!(f, "R{index}"), + Operand::ConstantCharacter(index) => write!(f, "C_CHAR_{index}"), + Operand::ConstantFloat(index) => write!(f, "C_FLOAT_{index}"), + Operand::ConstantInteger(index) => write!(f, "C_INT_{index}"), + Operand::ConstantString(index) => write!(f, "C_STR_{index}"), + Operand::RegisterBoolean(index) => write!(f, "R_BOOL_{index}"), + Operand::RegisterByte(index) => write!(f, "R_BYTE_{index}"), + Operand::RegisterCharacter(index) => write!(f, "R_CHAR_{index}"), + Operand::RegisterFloat(index) => write!(f, "R_FLOAT_{index}"), + Operand::RegisterInteger(index) => write!(f, "R_INT_{index}"), + Operand::RegisterString(index) => write!(f, "R_STR_{index}"), } } } @@ -713,9 +818,9 @@ mod tests { fn decode_operation() { let instruction = Instruction::add( 42, - Operand::Constant(4), + Operand::ConstantInteger(40), TypeCode::STRING, - Operand::Register(2), + Operand::RegisterInteger(2), TypeCode::CHARACTER, ); @@ -726,9 +831,9 @@ mod tests { fn decode_a_field() { let instruction = Instruction::add( 42, - Operand::Constant(4), + Operand::ConstantInteger(4), TypeCode::STRING, - Operand::Register(2), + Operand::RegisterInteger(2), TypeCode::CHARACTER, ); @@ -739,9 +844,9 @@ mod tests { fn decode_b_field() { let instruction = Instruction::add( 42, - Operand::Constant(4), + Operand::ConstantInteger(4), TypeCode::STRING, - Operand::Register(2), + Operand::RegisterInteger(2), TypeCode::CHARACTER, ); @@ -752,9 +857,9 @@ mod tests { fn decode_c_field() { let instruction = Instruction::add( 42, - Operand::Constant(4), + Operand::ConstantInteger(4), TypeCode::STRING, - Operand::Register(2), + Operand::RegisterInteger(2), TypeCode::CHARACTER, ); @@ -765,22 +870,22 @@ mod tests { fn decode_d_field() { let instruction = Instruction::add( 42, - Operand::Constant(4), + Operand::ConstantInteger(4), TypeCode::STRING, - Operand::Register(2), + Operand::RegisterInteger(2), TypeCode::CHARACTER, ); - assert!(instruction.d_field()); + assert!(!instruction.d_field()); } #[test] fn decode_b_is_constant() { let instruction = Instruction::add( 42, - Operand::Constant(4), + Operand::ConstantInteger(4), TypeCode::STRING, - Operand::Register(2), + Operand::RegisterInteger(2), TypeCode::CHARACTER, ); @@ -791,9 +896,9 @@ mod tests { fn decode_c_is_constant() { let instruction = Instruction::add( 42, - Operand::Register(2), + Operand::RegisterInteger(2), TypeCode::STRING, - Operand::Constant(4), + Operand::ConstantInteger(4), TypeCode::CHARACTER, ); @@ -804,9 +909,9 @@ mod tests { fn decode_b_type() { let instruction = Instruction::add( 42, - Operand::Constant(4), + Operand::ConstantInteger(4), TypeCode::STRING, - Operand::Register(2), + Operand::RegisterInteger(2), TypeCode::CHARACTER, ); @@ -817,9 +922,9 @@ mod tests { fn decode_c_type() { let instruction = Instruction::add( 42, - Operand::Constant(4), + Operand::ConstantInteger(4), TypeCode::STRING, - Operand::Register(2), + Operand::RegisterInteger(2), TypeCode::CHARACTER, ); diff --git a/dust-lang/src/instruction/point.rs b/dust-lang/src/instruction/point.rs index e0e2d8a..68b48e8 100644 --- a/dust-lang/src/instruction/point.rs +++ b/dust-lang/src/instruction/point.rs @@ -53,7 +53,7 @@ impl Display for Point { TypeCode::FLOAT => write!(f, "R_FLOAT_{destination} = R_FLOAT_{to}"), TypeCode::INTEGER => write!(f, "R_INT_{destination} = R_INT_{to}"), TypeCode::STRING => write!(f, "R_STR_{destination} = R_STR_{to}"), - unsupported => unsupported.panic_from_unsupported_code(), + unsupported => panic!("Unsupported type code: {}", unsupported.0), } } } diff --git a/dust-lang/src/instruction/return.rs b/dust-lang/src/instruction/return.rs index b1c6e76..d808acc 100644 --- a/dust-lang/src/instruction/return.rs +++ b/dust-lang/src/instruction/return.rs @@ -2,20 +2,23 @@ use std::fmt::{self, Display, Formatter}; use crate::{Instruction, Operation}; -use super::InstructionBuilder; +use super::{InstructionBuilder, TypeCode}; pub struct Return { pub should_return_value: bool, + pub return_type: TypeCode, pub return_register: u16, } impl From for Return { fn from(instruction: Instruction) -> Self { let should_return_value = instruction.b_field() != 0; + let return_type = instruction.b_type(); let return_register = instruction.c_field(); Return { should_return_value, + return_type, return_register, } } @@ -25,11 +28,13 @@ impl From for Instruction { fn from(r#return: Return) -> Self { let operation = Operation::RETURN; let b_field = r#return.should_return_value as u16; + let b_type = r#return.return_type; let c_field = r#return.return_register; InstructionBuilder { operation, b_field, + b_type, c_field, ..Default::default() } @@ -41,11 +46,20 @@ impl Display for Return { fn fmt(&self, f: &mut Formatter) -> fmt::Result { let Return { should_return_value, + return_type, return_register, } = self; if *should_return_value { - write!(f, "RETURN R{return_register}") + match *return_type { + TypeCode::BOOLEAN => write!(f, "RETURN R_BOOL_{return_register}"), + TypeCode::BYTE => write!(f, "RETURN R_BYTE_{return_register}"), + TypeCode::CHARACTER => write!(f, "RETURN R_CHAR_{return_register}"), + TypeCode::FLOAT => write!(f, "RETURN R_FLOAT_{return_register}"), + TypeCode::INTEGER => write!(f, "RETURN R_INT_{return_register}"), + TypeCode::STRING => write!(f, "RETURN R_STR_{return_register}"), + unsupported => panic!("Unsupported type code: {}", unsupported.0), + } } else { write!(f, "RETURN") } diff --git a/dust-lang/src/instruction/test.rs b/dust-lang/src/instruction/test.rs index e826ed3..3010616 100644 --- a/dust-lang/src/instruction/test.rs +++ b/dust-lang/src/instruction/test.rs @@ -44,6 +44,6 @@ impl Display for Test { } = self; let bang = if *test_value { "" } else { "!" }; - write!(f, "if {bang}R{operand_register} {{ JUMP +1 }}") + write!(f, "if {bang}R_BOOL_{operand_register} {{ JUMP +1 }}") } } diff --git a/dust-lang/src/instruction/type_code.rs b/dust-lang/src/instruction/type_code.rs index 9a44cf4..228d699 100644 --- a/dust-lang/src/instruction/type_code.rs +++ b/dust-lang/src/instruction/type_code.rs @@ -15,10 +15,6 @@ impl TypeCode { pub fn panic_from_unknown_code(self) -> ! { panic!("Unknown type code: {}", self.0); } - - pub fn panic_from_unsupported_code(self) -> ! { - panic!("Type code {} is not supported in the context", self.0,); - } } impl Display for TypeCode { diff --git a/dust-lang/src/vm/action.rs b/dust-lang/src/vm/action.rs index a23b810..946b299 100644 --- a/dust-lang/src/vm/action.rs +++ b/dust-lang/src/vm/action.rs @@ -91,7 +91,7 @@ pub fn point(instruction: InstructionBuilder, thread: &mut Thread) { TypeCode::STRING => { thread.set_string_register(destination, Register::Pointer(Pointer::Register(to))); } - unsupported => unsupported.panic_from_unsupported_code(), + unsupported => panic!("Unsupported type code: {}", unsupported.0), } }