From 3af1b6482073f2e7f64b66aef083dbed47e09d2c Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 8 Feb 2025 17:36:30 -0500 Subject: [PATCH] Reimplement more instruction and compiler logic --- dust-lang/src/compiler/mod.rs | 71 ++++--- dust-lang/src/instruction/call_native.rs | 57 ++++- dust-lang/src/instruction/mod.rs | 4 +- dust-lang/src/instruction/test.rs | 2 +- dust-lang/src/native_function/mod.rs | 20 +- dust-lang/src/type.rs | 8 +- dust-lang/src/value/concrete_value.rs | 257 ++--------------------- dust-lang/src/value/mod.rs | 95 --------- dust-lang/src/vm/action.rs | 23 +- dust-lang/src/vm/thread.rs | 9 +- dust-lang/tests/values.rs | 114 ++++++---- 11 files changed, 217 insertions(+), 443 deletions(-) diff --git a/dust-lang/src/compiler/mod.rs b/dust-lang/src/compiler/mod.rs index 309dc40..4aac18b 100644 --- a/dust-lang/src/compiler/mod.rs +++ b/dust-lang/src/compiler/mod.rs @@ -1020,44 +1020,52 @@ impl<'src> Compiler<'src> { } fn parse_logical_binary(&mut self) -> Result<(), CompileError> { - let (last_instruction, last_type, last_position) = + let operator = self.current_token; + let operator_position = self.current_position; + let rule = ParseRule::from(&operator); + 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.operation() == Operation::POINT { - let Point { to, .. } = Point::from(last_instruction); + let operand_register = if left_instruction.operation() == Operation::POINT { + let Point { to, .. } = Point::from(left_instruction); let local = self.get_local(to.index())?; local.register_index - } else if last_instruction.yields_value() { - let register = last_instruction.a_field(); + } else 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 { - let register = match last_type { - 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, - _ => todo!(), - }; - - self.instructions - .push((last_instruction, last_type, last_position)); - - register + return Err(CompileError::ExpectedExpression { + found: self.previous_token.to_owned(), + position: self.previous_position, + }); }; - let operator = self.current_token; - let operator_position = self.current_position; - let rule = ParseRule::from(&operator); + + // TODO: Check if the left type is boolean + + 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 boolean + + right_instruction.set_a_field(operand_register); + let test_boolean = match operator { Token::DoubleAmpersand => true, Token::DoublePipe => false, @@ -1074,8 +1082,8 @@ impl<'src> Compiler<'src> { self.emit_instruction(test, Type::None, operator_position); self.emit_instruction(jump, Type::None, operator_position); - self.advance()?; - self.parse_sub_expression(&rule.precedence)?; + self.instructions + .push((right_instruction, right_type, right_position)); let instructions_length = self.instructions.len(); @@ -1571,7 +1579,7 @@ impl<'src> Compiler<'src> { fn parse_call_native(&mut self, function: NativeFunction) -> Result<(), CompileError> { let start = self.previous_position.0; - let mut argument_count = 0; + let mut first_argument_index = None; self.expect(Token::LeftParenthesis)?; @@ -1579,7 +1587,9 @@ impl<'src> Compiler<'src> { self.parse_expression()?; self.allow(Token::Comma)?; - argument_count += 1; + if first_argument_index.is_none() { + first_argument_index = Some(self.instructions.last().unwrap().0.a_field()); + } } let end = self.previous_position.1; @@ -1594,11 +1604,8 @@ impl<'src> Compiler<'src> { _ => todo!(), }; let return_type = *function.r#type().return_type; - let call_native = Instruction::from(CallNative { - destination, - function, - argument_count, - }); + let call_native = + Instruction::call_native(destination, function, first_argument_index.unwrap_or(0)); self.emit_instruction(call_native, return_type, Span(start, end)); diff --git a/dust-lang/src/instruction/call_native.rs b/dust-lang/src/instruction/call_native.rs index cb3a2b4..fe133f2 100644 --- a/dust-lang/src/instruction/call_native.rs +++ b/dust-lang/src/instruction/call_native.rs @@ -1,24 +1,25 @@ use std::fmt::Display; -use crate::{Instruction, NativeFunction, Operation}; +use crate::{Instruction, NativeFunction, Operation, Type}; use super::InstructionFields; pub struct CallNative { pub destination: u16, pub function: NativeFunction, - pub argument_count: u16, + pub first_argument_index: u16, } impl From for CallNative { fn from(instruction: Instruction) -> Self { let destination = instruction.a_field(); let function = NativeFunction::from(instruction.b_field()); + let first_argument_index = instruction.c_field(); CallNative { destination, function, - argument_count: instruction.c_field(), + first_argument_index, } } } @@ -28,7 +29,7 @@ impl From for Instruction { let operation = Operation::CALL_NATIVE; let a_field = call_native.destination; let b_field = call_native.function as u16; - let c_field = call_native.argument_count; + let c_field = call_native.first_argument_index; InstructionFields { operation, @@ -46,21 +47,57 @@ impl Display for CallNative { let CallNative { destination, function, - argument_count, + first_argument_index, } = self; - let arguments_start = destination.saturating_sub(*argument_count); - let arguments_end = arguments_start + argument_count; + let argument_count = function.r#type().value_parameters.len() as u16; if function.returns_value() { write!(f, "R{destination} = ")?; } + write!(f, "{function}")?; + match argument_count { 0 => { - write!(f, "{function}()") + write!(f, "()") + } + _ => { + let arguments_end = first_argument_index + argument_count - 1; + let arguments_index_range = *first_argument_index..=arguments_end; + let function_type = function.r#type(); + let argument_types = function_type.value_parameters.iter(); + + write!(f, "(")?; + + for (index, r#type) in arguments_index_range.zip(argument_types) { + match r#type { + Type::Boolean => { + write!(f, "R_BOOL_{index}") + } + Type::Byte => { + write!(f, "R_BYTE_{index}") + } + Type::Float => { + write!(f, "R_FLOAT_{index}") + } + Type::Integer => { + write!(f, "R_INT_{index}") + } + Type::String => { + write!(f, "R_STR_{index}") + } + unsupported => { + todo!("Support for {unsupported:?} arguments") + } + }?; + + if index != arguments_end { + write!(f, ", ")?; + } + } + + write!(f, ")") } - 1 => write!(f, "{function}(R{arguments_start})"), - _ => write!(f, "{function}(R{arguments_start}..R{arguments_end})"), } } } diff --git a/dust-lang/src/instruction/mod.rs b/dust-lang/src/instruction/mod.rs index 763bfeb..2fc30ec 100644 --- a/dust-lang/src/instruction/mod.rs +++ b/dust-lang/src/instruction/mod.rs @@ -556,12 +556,12 @@ impl Instruction { pub fn call_native( destination: u16, function: NativeFunction, - argument_count: u16, + first_argument_index: u16, ) -> Instruction { Instruction::from(CallNative { destination, function, - argument_count, + first_argument_index, }) } diff --git a/dust-lang/src/instruction/test.rs b/dust-lang/src/instruction/test.rs index 692457a..779de20 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/native_function/mod.rs b/dust-lang/src/native_function/mod.rs index 928d7ab..aebb1cc 100644 --- a/dust-lang/src/native_function/mod.rs +++ b/dust-lang/src/native_function/mod.rs @@ -143,13 +143,13 @@ define_native_function! { // (ToByte, 5_u8, "to_byte", true), // (ToFloat, 6_u8, "to_float", true), // (ToInteger, 7_u8, "to_integer", true), - ( - ToString, - 8, - "to_string", - FunctionType::new([], [Type::Any], Type::String), - string::to_string - ), + // ( + // ToString, + // 8, + // "to_string", + // FunctionType::new([], [Type::Any], Type::String), + // string::to_string + // ), // // List and string // (All, 9_u8, "all", true), @@ -216,7 +216,7 @@ define_native_function! { Write, 55, "write", - FunctionType::new([], [Type::Any], Type::None), + FunctionType::new([], [Type::String], Type::None), io::write ), // (WriteFile, 56_u8, "write_file", false), @@ -224,7 +224,7 @@ define_native_function! { WriteLine, 57, "write_line", - FunctionType::new([], [Type::Any], Type::None), + FunctionType::new([], [Type::String], Type::None), io::write_line ), @@ -242,7 +242,7 @@ define_native_function! { Spawn, 60, "spawn", - FunctionType::new([], [ Type::function([], [], Type::Any)], Type::None), + FunctionType::new([], [ Type::function([], [], Type::None)], Type::None), thread::spawn ) } diff --git a/dust-lang/src/type.rs b/dust-lang/src/type.rs index 1786456..e35ec24 100644 --- a/dust-lang/src/type.rs +++ b/dust-lang/src/type.rs @@ -13,7 +13,6 @@ use crate::instruction::TypeCode; #[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(tag = "Type", content = "Value")] pub enum Type { - Any, Boolean, Byte, Character, @@ -77,9 +76,7 @@ impl Type { /// Checks that the type is compatible with another type. pub fn check(&self, other: &Type) -> Result<(), TypeConflict> { match (self.concrete_type(), other.concrete_type()) { - (Type::Any, _) - | (_, Type::Any) - | (Type::Boolean, Type::Boolean) + (Type::Boolean, Type::Boolean) | (Type::Byte, Type::Byte) | (Type::Character, Type::Character) | (Type::Float, Type::Float) @@ -171,7 +168,6 @@ impl Type { impl Display for Type { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Type::Any => write!(f, "any"), Type::Boolean => write!(f, "bool"), Type::Byte => write!(f, "byte"), Type::Character => write!(f, "char"), @@ -235,8 +231,6 @@ impl PartialOrd for Type { impl Ord for Type { fn cmp(&self, other: &Self) -> Ordering { match (self, other) { - (Type::Any, Type::Any) => Ordering::Equal, - (Type::Any, _) => Ordering::Greater, (Type::Boolean, Type::Boolean) => Ordering::Equal, (Type::Boolean, _) => Ordering::Greater, (Type::Byte, Type::Byte) => Ordering::Equal, diff --git a/dust-lang/src/value/concrete_value.rs b/dust-lang/src/value/concrete_value.rs index 6d5d22d..b03d9c0 100644 --- a/dust-lang/src/value/concrete_value.rs +++ b/dust-lang/src/value/concrete_value.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use smartstring::{LazyCompact, SmartString}; use tracing::trace; -use crate::{Type, Value, ValueError}; +use crate::{Type, Value, ValueError, instruction::TypeCode}; use super::RangeValue; @@ -18,7 +18,10 @@ pub enum ConcreteValue { Character(char), Float(f64), Integer(i64), - List(Vec), + List { + items: Vec, + item_type: TypeCode, + }, Range(RangeValue), String(DustString), } @@ -28,8 +31,11 @@ impl ConcreteValue { Value::Concrete(self) } - pub fn list>>(into_list: T) -> Self { - ConcreteValue::List(into_list.into()) + pub fn list>>(into_items: T, type_code: TypeCode) -> Self { + ConcreteValue::List { + items: into_items.into(), + item_type: type_code, + } } pub fn string>>(to_string: T) -> Self { @@ -85,8 +91,8 @@ impl ConcreteValue { } pub fn as_list(&self) -> Option<&Vec> { - if let ConcreteValue::List(list) = self { - Some(list) + if let ConcreteValue::List { items, .. } = self { + Some(items) } else { None } @@ -111,239 +117,11 @@ impl ConcreteValue { ConcreteValue::Character(_) => Type::Character, ConcreteValue::Float(_) => Type::Float, ConcreteValue::Integer(_) => Type::Integer, - ConcreteValue::List(list) => { - let item_type = list - .first() - .map_or(Type::Any, |item| item.r#type()) - .type_code(); - - Type::List(item_type) - } + ConcreteValue::List { item_type, .. } => Type::List(*item_type), ConcreteValue::Range(range) => range.r#type(), ConcreteValue::String(_) => Type::String, } } - - pub fn add(&self, other: &Self) -> ConcreteValue { - use ConcreteValue::*; - - match (self, other) { - (Byte(left), Byte(right)) => { - let sum = left.saturating_add(*right); - - Byte(sum) - } - (Character(left), Character(right)) => { - let mut concatenated = DustString::new(); - - concatenated.push(*left); - concatenated.push(*right); - - String(concatenated) - } - (Character(left), String(right)) => { - let mut concatenated = DustString::new(); - - concatenated.push(*left); - concatenated.push_str(right); - - String(concatenated) - } - (Float(left), Float(right)) => { - let sum = left + right; - - Float(sum) - } - (Integer(left), Integer(right)) => { - let sum = left.saturating_add(*right); - - Integer(sum) - } - (String(left), Character(right)) => { - let concatenated = format!("{}{}", left, right); - - String(DustString::from(concatenated)) - } - (String(left), String(right)) => { - let concatenated = format!("{}{}", left, right); - - String(DustString::from(concatenated)) - } - _ => panic!( - "{}", - ValueError::CannotAdd( - Value::Concrete(self.clone()), - Value::Concrete(other.clone()) - ) - ), - } - } - - pub fn subtract(&self, other: &Self) -> ConcreteValue { - use ConcreteValue::*; - - match (self, other) { - (Byte(left), Byte(right)) => ConcreteValue::Byte(left.saturating_sub(*right)), - (Float(left), Float(right)) => ConcreteValue::Float(left - right), - (Integer(left), Integer(right)) => ConcreteValue::Integer(left.saturating_sub(*right)), - _ => panic!( - "{}", - ValueError::CannotSubtract( - Value::Concrete(self.clone()), - Value::Concrete(other.clone()) - ) - ), - } - } - - pub fn multiply(&self, other: &Self) -> Result { - use ConcreteValue::*; - - let product = match (self, other) { - (Byte(left), Byte(right)) => ConcreteValue::Byte(left.saturating_mul(*right)), - (Float(left), Float(right)) => ConcreteValue::Float(left * right), - (Integer(left), Integer(right)) => ConcreteValue::Integer(left.saturating_mul(*right)), - _ => { - return Err(ValueError::CannotMultiply( - self.clone().to_value(), - other.clone().to_value(), - )); - } - }; - - Ok(product) - } - - pub fn divide(&self, other: &Self) -> Result { - use ConcreteValue::*; - - let quotient = match (self, other) { - (Byte(left), Byte(right)) => ConcreteValue::Byte(left.saturating_div(*right)), - (Float(left), Float(right)) => ConcreteValue::Float(left / right), - (Integer(left), Integer(right)) => ConcreteValue::Integer(left.saturating_div(*right)), - _ => { - return Err(ValueError::CannotMultiply( - self.clone().to_value(), - other.clone().to_value(), - )); - } - }; - - Ok(quotient) - } - - pub fn modulo(&self, other: &Self) -> Result { - use ConcreteValue::*; - - let product = match (self, other) { - (Byte(left), Byte(right)) => ConcreteValue::Byte(left.wrapping_rem(*right)), - (Float(left), Float(right)) => ConcreteValue::Float(left % right), - (Integer(left), Integer(right)) => { - ConcreteValue::Integer(left.wrapping_rem_euclid(*right)) - } - _ => { - return Err(ValueError::CannotMultiply( - self.clone().to_value(), - other.clone().to_value(), - )); - } - }; - - Ok(product) - } - - pub fn negate(&self) -> ConcreteValue { - use ConcreteValue::*; - - match self { - Boolean(value) => ConcreteValue::Boolean(!value), - Byte(value) => ConcreteValue::Byte(value.wrapping_neg()), - Float(value) => ConcreteValue::Float(-value), - Integer(value) => ConcreteValue::Integer(value.wrapping_neg()), - _ => panic!("{}", ValueError::CannotNegate(self.clone().to_value())), - } - } - - pub fn not(&self) -> Result { - use ConcreteValue::*; - - let not = match self { - Boolean(value) => ConcreteValue::Boolean(!value), - _ => return Err(ValueError::CannotNot(self.clone().to_value())), - }; - - Ok(not) - } - - pub fn equals(&self, other: &ConcreteValue) -> bool { - use ConcreteValue::*; - - match (self, other) { - (Boolean(left), Boolean(right)) => left == right, - (Byte(left), Byte(right)) => left == right, - (Character(left), Character(right)) => left == right, - (Float(left), Float(right)) => left == right, - (Integer(left), Integer(right)) => left == right, - (List(left), List(right)) => left == right, - (Range(left), Range(right)) => left == right, - (String(left), String(right)) => left == right, - _ => { - panic!( - "{}", - ValueError::CannotCompare( - Value::Concrete(self.clone()), - Value::Concrete(other.clone()) - ) - ) - } - } - } - - pub fn less_than(&self, other: &ConcreteValue) -> Result { - use ConcreteValue::*; - - let less_than = match (self, other) { - (Boolean(left), Boolean(right)) => ConcreteValue::Boolean(left < right), - (Byte(left), Byte(right)) => ConcreteValue::Boolean(left < right), - (Character(left), Character(right)) => ConcreteValue::Boolean(left < right), - (Float(left), Float(right)) => ConcreteValue::Boolean(left < right), - (Integer(left), Integer(right)) => ConcreteValue::Boolean(left < right), - (List(left), List(right)) => ConcreteValue::Boolean(left < right), - (Range(left), Range(right)) => ConcreteValue::Boolean(left < right), - (String(left), String(right)) => ConcreteValue::Boolean(left < right), - _ => { - return Err(ValueError::CannotCompare( - self.clone().to_value(), - other.clone().to_value(), - )); - } - }; - - Ok(less_than) - } - - pub fn less_than_or_equals(&self, other: &ConcreteValue) -> Result { - use ConcreteValue::*; - - let less_than_or_equal = match (self, other) { - (Boolean(left), Boolean(right)) => ConcreteValue::Boolean(left <= right), - (Byte(left), Byte(right)) => ConcreteValue::Boolean(left <= right), - (Character(left), Character(right)) => ConcreteValue::Boolean(left <= right), - (Float(left), Float(right)) => ConcreteValue::Boolean(left <= right), - (Integer(left), Integer(right)) => ConcreteValue::Boolean(left <= right), - (List(left), List(right)) => ConcreteValue::Boolean(left <= right), - (Range(left), Range(right)) => ConcreteValue::Boolean(left <= right), - (String(left), String(right)) => ConcreteValue::Boolean(left <= right), - _ => { - return Err(ValueError::CannotCompare( - self.clone().to_value(), - other.clone().to_value(), - )); - } - }; - - Ok(less_than_or_equal) - } } impl Clone for ConcreteValue { @@ -356,7 +134,10 @@ impl Clone for ConcreteValue { ConcreteValue::Character(character) => ConcreteValue::Character(*character), ConcreteValue::Float(float) => ConcreteValue::Float(*float), ConcreteValue::Integer(integer) => ConcreteValue::Integer(*integer), - ConcreteValue::List(list) => ConcreteValue::List(list.clone()), + ConcreteValue::List { items, item_type } => ConcreteValue::List { + items: items.clone(), + item_type: *item_type, + }, ConcreteValue::Range(range) => ConcreteValue::Range(*range), ConcreteValue::String(string) => ConcreteValue::String(string.clone()), } @@ -379,10 +160,10 @@ impl Display for ConcreteValue { Ok(()) } ConcreteValue::Integer(integer) => write!(f, "{integer}"), - ConcreteValue::List(list) => { + ConcreteValue::List { items, .. } => { write!(f, "[")?; - for (index, item) in list.iter().enumerate() { + for (index, item) in items.iter().enumerate() { if index > 0 { write!(f, ", ")?; } diff --git a/dust-lang/src/value/mod.rs b/dust-lang/src/value/mod.rs index 010b9c1..296eec3 100644 --- a/dust-lang/src/value/mod.rs +++ b/dust-lang/src/value/mod.rs @@ -130,101 +130,6 @@ impl Value { } } - pub fn add(&self, other: &Value) -> Value { - let sum = match (self, other) { - (Value::Concrete(left), Value::Concrete(right)) => left.add(right), - _ => panic!("{}", ValueError::CannotAdd(self.clone(), other.clone())), - }; - - Value::Concrete(sum) - } - - pub fn subtract(&self, other: &Value) -> Value { - let difference = match (self, other) { - (Value::Concrete(left), Value::Concrete(right)) => left.subtract(right), - _ => panic!( - "{}", - ValueError::CannotSubtract(self.clone(), other.clone()) - ), - }; - - Value::Concrete(difference) - } - - pub fn multiply(&self, other: &Value) -> Result { - match (self, other) { - (Value::Concrete(left), Value::Concrete(right)) => { - left.multiply(right).map(Value::Concrete) - } - _ => Err(ValueError::CannotMultiply( - self.to_owned(), - other.to_owned(), - )), - } - } - - pub fn divide(&self, other: &Value) -> Result { - match (self, other) { - (Value::Concrete(left), Value::Concrete(right)) => { - left.divide(right).map(Value::Concrete) - } - _ => Err(ValueError::CannotDivide(self.to_owned(), other.to_owned())), - } - } - - pub fn modulo(&self, other: &Value) -> Result { - match (self, other) { - (Value::Concrete(left), Value::Concrete(right)) => { - left.modulo(right).map(Value::Concrete) - } - _ => Err(ValueError::CannotModulo(self.to_owned(), other.to_owned())), - } - } - - pub fn negate(&self) -> Value { - let concrete = match self { - Value::Concrete(concrete_value) => concrete_value.negate(), - _ => panic!("{}", ValueError::CannotNegate(self.clone())), - }; - - Value::Concrete(concrete) - } - - pub fn not(&self) -> Result { - match self { - Value::Concrete(concrete_value) => concrete_value.not().map(Value::Concrete), - _ => Err(ValueError::CannotNot(self.to_owned())), - } - } - - pub fn equals(&self, other: &Value) -> bool { - match (self, other) { - (Value::Concrete(left), Value::Concrete(right)) => left.equals(right), - _ => panic!( - "{}", - ValueError::CannotCompare(self.to_owned(), other.to_owned()) - ), - } - } - - pub fn less(&self, other: &Value) -> Result { - match (self, other) { - (Value::Concrete(left), Value::Concrete(right)) => { - left.less_than(right).map(Value::Concrete) - } - _ => Err(ValueError::CannotCompare(self.to_owned(), other.to_owned())), - } - } - - pub fn less_than_or_equals(&self, other: &Value) -> Result { - match (self, other) { - (Value::Concrete(left), Value::Concrete(right)) => { - left.less_than_or_equals(right).map(Value::Concrete) - } - _ => Err(ValueError::CannotCompare(self.to_owned(), other.to_owned())), - } - } - pub fn display(&self, data: &Thread) -> DustString { match self { Value::AbstractList(list) => list.display(data), diff --git a/dust-lang/src/vm/action.rs b/dust-lang/src/vm/action.rs index 582235e..5d1b9f9 100644 --- a/dust-lang/src/vm/action.rs +++ b/dust-lang/src/vm/action.rs @@ -759,7 +759,7 @@ pub fn multiply(instruction: InstructionFields, thread: &mut Thread) { let result = left_value.saturating_mul(*right_value); let register = Register::Value(result); - thread.set_integer_register(destination as usize, register); + thread.set_integer_register(destination, register); } _ => unimplemented!(), } @@ -850,9 +850,18 @@ pub fn divide(instruction: InstructionFields, thread: &mut Thread) { _ => unreachable!(), } } + pub fn modulo(instruction: InstructionFields, thread: &mut Thread) {} -pub fn test(instruction: InstructionFields, thread: &mut Thread) {} +pub fn test(instruction: InstructionFields, thread: &mut Thread) { + let operand_register = instruction.b_field as usize; + let test_value = instruction.c_field != 0; + let operand_boolean = thread.get_boolean_register(operand_register); + + if *operand_boolean == test_value { + thread.current_frame_mut().ip += 1; + } +} pub fn test_set(instruction: InstructionFields, thread: &mut Thread) {} @@ -976,16 +985,18 @@ pub fn r#return(instruction: InstructionFields, thread: &mut Thread) { } TypeCode::LIST => { let abstract_list = thread.get_list_register(return_register).clone(); - let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len()); + let mut items = Vec::with_capacity(abstract_list.item_pointers.len()); for pointer in &abstract_list.item_pointers { let value = thread.get_value_from_pointer(pointer); - concrete_list.push(value); + items.push(value); } - thread.return_value = - Some(Some(Value::Concrete(ConcreteValue::List(concrete_list)))); + thread.return_value = Some(Some(Value::Concrete(ConcreteValue::List { + items, + item_type: abstract_list.item_type, + }))); } _ => unimplemented!(), } diff --git a/dust-lang/src/vm/thread.rs b/dust-lang/src/vm/thread.rs index cf22f54..c00c866 100644 --- a/dust-lang/src/vm/thread.rs +++ b/dust-lang/src/vm/thread.rs @@ -119,15 +119,18 @@ impl Thread { } Pointer::RegisterList(register_index) => { let abstract_list = self.get_list_register(*register_index).clone(); - let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len()); + let mut items = Vec::with_capacity(abstract_list.item_pointers.len()); for pointer in &abstract_list.item_pointers { let value = self.get_value_from_pointer(pointer); - concrete_list.push(value); + items.push(value); } - ConcreteValue::List(concrete_list) + ConcreteValue::List { + items, + item_type: abstract_list.item_type, + } } Pointer::RegisterFunction(_) => unimplemented!(), Pointer::ConstantCharacter(constant_index) => { diff --git a/dust-lang/tests/values.rs b/dust-lang/tests/values.rs index ea0d1e6..6d4e063 100644 --- a/dust-lang/tests/values.rs +++ b/dust-lang/tests/values.rs @@ -147,10 +147,10 @@ fn load_boolean_list() { positions: vec![Span(1, 5), Span(7, 12), Span(0, 13), Span(13, 13)], ..Chunk::default() }; - let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ - ConcreteValue::Boolean(true), - ConcreteValue::Boolean(false), - ]))); + let return_value = Some(Value::Concrete(ConcreteValue::List { + items: vec![ConcreteValue::Boolean(true), ConcreteValue::Boolean(false)], + item_type: TypeCode::BOOLEAN, + })); assert_eq!(chunk, compile(source).unwrap()); assert_eq!(return_value, run(source).unwrap()); @@ -170,10 +170,10 @@ fn load_byte_list() { positions: vec![Span(1, 5), Span(7, 11), Span(0, 12), Span(12, 12)], ..Chunk::default() }; - let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ - ConcreteValue::Byte(0x2a), - ConcreteValue::Byte(0x42), - ]))); + let return_value = Some(Value::Concrete(ConcreteValue::List { + items: vec![ConcreteValue::Byte(0x2a), ConcreteValue::Byte(0x42)], + item_type: TypeCode::BYTE, + })); assert_eq!(chunk, compile(source).unwrap()); assert_eq!(return_value, run(source).unwrap()); @@ -194,10 +194,10 @@ fn load_character_list() { constants: vec![ConcreteValue::Character('a'), ConcreteValue::Character('b')], ..Chunk::default() }; - let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ - ConcreteValue::Character('a'), - ConcreteValue::Character('b'), - ]))); + let return_value = Some(Value::Concrete(ConcreteValue::List { + items: vec![ConcreteValue::Character('a'), ConcreteValue::Character('b')], + item_type: TypeCode::CHARACTER, + })); assert_eq!(chunk, compile(source).unwrap()); assert_eq!(return_value, run(source).unwrap()); @@ -218,10 +218,10 @@ fn load_float_list() { constants: vec![ConcreteValue::Float(42.42), ConcreteValue::Float(24.24)], ..Chunk::default() }; - let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ - ConcreteValue::Float(42.42), - ConcreteValue::Float(24.24), - ]))); + let return_value = Some(Value::Concrete(ConcreteValue::List { + items: vec![ConcreteValue::Float(42.42), ConcreteValue::Float(24.24)], + item_type: TypeCode::FLOAT, + })); assert_eq!(chunk, compile(source).unwrap()); assert_eq!(return_value, run(source).unwrap()); @@ -247,11 +247,14 @@ fn load_integer_list() { ], ..Chunk::default() }; - let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ - ConcreteValue::Integer(1), - ConcreteValue::Integer(2), - ConcreteValue::Integer(3), - ]))); + let return_value = Some(Value::Concrete(ConcreteValue::List { + items: vec![ + ConcreteValue::Integer(1), + ConcreteValue::Integer(2), + ConcreteValue::Integer(3), + ], + item_type: TypeCode::INTEGER, + })); assert_eq!(chunk, compile(source).unwrap()); assert_eq!(return_value, run(source).unwrap()); @@ -275,10 +278,13 @@ fn load_string_list() { ], ..Chunk::default() }; - let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ - ConcreteValue::String(DustString::from("Hello")), - ConcreteValue::String(DustString::from("World")), - ]))); + let return_value = Some(Value::Concrete(ConcreteValue::List { + items: vec![ + ConcreteValue::String(DustString::from("Hello")), + ConcreteValue::String(DustString::from("World")), + ], + item_type: TypeCode::STRING, + })); assert_eq!(chunk, compile(source).unwrap()); assert_eq!(return_value, run(source).unwrap()); @@ -317,10 +323,19 @@ fn load_nested_list() { ], ..Chunk::default() }; - let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ - ConcreteValue::List(vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)]), - ConcreteValue::List(vec![ConcreteValue::Integer(3), ConcreteValue::Integer(4)]), - ]))); + let return_value = Some(Value::Concrete(ConcreteValue::List { + items: vec![ + ConcreteValue::List { + items: vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)], + item_type: TypeCode::INTEGER, + }, + ConcreteValue::List { + items: vec![ConcreteValue::Integer(3), ConcreteValue::Integer(4)], + item_type: TypeCode::INTEGER, + }, + ], + item_type: TypeCode::LIST, + })); assert_eq!(chunk, compile(source).unwrap()); assert_eq!(return_value, run(source).unwrap()); @@ -383,16 +398,37 @@ fn load_deeply_nested_list() { ], ..Chunk::default() }; - let return_value = Some(Value::Concrete(ConcreteValue::List(vec![ - ConcreteValue::List(vec![ - ConcreteValue::List(vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)]), - ConcreteValue::List(vec![ConcreteValue::Integer(3), ConcreteValue::Integer(4)]), - ]), - ConcreteValue::List(vec![ - ConcreteValue::List(vec![ConcreteValue::Integer(5), ConcreteValue::Integer(6)]), - ConcreteValue::List(vec![ConcreteValue::Integer(7), ConcreteValue::Integer(8)]), - ]), - ]))); + let return_value = Some(Value::Concrete(ConcreteValue::List { + items: vec![ + ConcreteValue::List { + items: vec![ + ConcreteValue::List { + items: vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)], + item_type: TypeCode::INTEGER, + }, + ConcreteValue::List { + items: vec![ConcreteValue::Integer(3), ConcreteValue::Integer(4)], + item_type: TypeCode::INTEGER, + }, + ], + item_type: TypeCode::LIST, + }, + ConcreteValue::List { + items: vec![ + ConcreteValue::List { + items: vec![ConcreteValue::Integer(5), ConcreteValue::Integer(6)], + item_type: TypeCode::INTEGER, + }, + ConcreteValue::List { + items: vec![ConcreteValue::Integer(7), ConcreteValue::Integer(8)], + item_type: TypeCode::INTEGER, + }, + ], + item_type: TypeCode::LIST, + }, + ], + item_type: TypeCode::LIST, + })); assert_eq!(chunk, compile(source).unwrap()); assert_eq!(return_value, run(source).unwrap());