diff --git a/dust-lang/src/compiler/mod.rs b/dust-lang/src/compiler/mod.rs index a52393b..46ac35c 100644 --- a/dust-lang/src/compiler/mod.rs +++ b/dust-lang/src/compiler/mod.rs @@ -1287,7 +1287,11 @@ impl<'src> Compiler<'src> { Type::String => self.next_string_register(), _ => todo!(), }; - let point = Instruction::point(local_register_index, Operand::Register(register)); + let point = Instruction::point( + local_register_index, + Operand::Register(register), + r#type.type_code(), + ); self.emit_instruction(point, r#type, start_position); } @@ -1304,7 +1308,11 @@ impl<'src> Compiler<'src> { Type::String => self.next_string_register(), _ => todo!(), }; - let point = Instruction::point(destination, Operand::Register(local_register_index)); + let point = Instruction::point( + destination, + Operand::Register(local_register_index), + r#type.type_code(), + ); self.emit_instruction(point, r#type, self.previous_position); @@ -1695,7 +1703,18 @@ impl<'src> Compiler<'src> { } fn parse_implicit_return(&mut self) -> Result<(), CompileError> { - if matches!(self.get_last_operation(), Some(Operation::RETURN)) + if matches!(self.get_last_operation(), Some(Operation::POINT)) { + let Point { + destination, + r#type: type_code, + .. + } = Point::from(self.instructions.last().unwrap().0); + + let (_, r#type, _) = self.instructions.pop().unwrap(); + let r#return = Instruction::r#return(true, destination, type_code); + + self.emit_instruction(r#return, r#type, self.current_position); + } else if matches!(self.get_last_operation(), Some(Operation::RETURN)) || matches!( self.get_last_operations(), Some([Operation::RETURN, Operation::JUMP]) diff --git a/dust-lang/src/instruction/mod.rs b/dust-lang/src/instruction/mod.rs index b0b446c..a50ba9b 100644 --- a/dust-lang/src/instruction/mod.rs +++ b/dust-lang/src/instruction/mod.rs @@ -278,8 +278,12 @@ impl Instruction { *self = fields.build(); } - pub fn point(destination: u16, to: Operand) -> Instruction { - Instruction::from(Point { destination, to }) + pub fn point(destination: u16, to: Operand, r#type: TypeCode) -> Instruction { + Instruction::from(Point { + destination, + to, + r#type, + }) } pub fn close(from: u16, to: u16) -> Instruction { @@ -711,8 +715,8 @@ 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::Constant(index) => write!(f, "{index}"), + Operand::Register(index) => write!(f, "{index}"), } } } diff --git a/dust-lang/src/instruction/point.rs b/dust-lang/src/instruction/point.rs index 5013b1f..70d3504 100644 --- a/dust-lang/src/instruction/point.rs +++ b/dust-lang/src/instruction/point.rs @@ -2,11 +2,12 @@ use std::fmt::{self, Display, Formatter}; use crate::{Instruction, Operation}; -use super::{InstructionFields, Operand}; +use super::{InstructionFields, Operand, TypeCode}; pub struct Point { pub destination: u16, pub to: Operand, + pub r#type: TypeCode, } impl From for Point { @@ -14,6 +15,7 @@ impl From for Point { Point { destination: instruction.a_field(), to: instruction.b_as_operand(), + r#type: instruction.b_type(), } } } @@ -23,11 +25,13 @@ 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; InstructionFields { operation, a_field, b_field, + b_type, b_is_constant, ..Default::default() } @@ -37,8 +41,23 @@ impl From for Instruction { impl Display for Point { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let Point { destination, to } = self; + let Point { + destination, + to, + r#type, + } = self; - write!(f, "R{destination} -> {to}") + match *r#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}"), + 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 => write!( + f, + "Unsupported type code: {unsupported} for Point instruction" + ), + } } } diff --git a/dust-lang/src/native_function/io.rs b/dust-lang/src/native_function/io.rs index 5ef1840..118905f 100644 --- a/dust-lang/src/native_function/io.rs +++ b/dust-lang/src/native_function/io.rs @@ -2,7 +2,7 @@ use std::io::{Write, stdin, stdout}; use std::ops::Range; use crate::DustString; -use crate::vm::Thread; +use crate::vm::{Register, Thread}; pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range) { let mut buffer = String::new(); @@ -13,8 +13,9 @@ pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range) { let mut argument_range_iter = argument_range.into_iter(); @@ -16,14 +16,15 @@ pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range Option { + pub fn as_boolean(&self) -> Option<&bool> { if let ConcreteValue::Boolean(boolean) = self { - Some(*boolean) + Some(boolean) } else { None } } - pub fn as_byte(&self) -> Option { + pub fn as_byte(&self) -> Option<&u8> { if let ConcreteValue::Byte(byte) = self { - Some(*byte) + Some(byte) } else { None } } - pub fn as_character(&self) -> Option { + pub fn as_character(&self) -> Option<&char> { if let ConcreteValue::Character(character) = self { - Some(*character) + Some(character) } else { None } } - pub fn as_float(&self) -> Option { + pub fn as_float(&self) -> Option<&f64> { if let ConcreteValue::Float(float) = self { - Some(*float) + Some(float) } else { None } } - pub fn as_integer(&self) -> Option { + pub fn as_integer(&self) -> Option<&i64> { if let ConcreteValue::Integer(integer) = self { - Some(*integer) + Some(integer) } else { None } diff --git a/dust-lang/src/vm/action.rs b/dust-lang/src/vm/action.rs index 347f610..37af11c 100644 --- a/dust-lang/src/vm/action.rs +++ b/dust-lang/src/vm/action.rs @@ -3,7 +3,7 @@ use crate::{ instruction::{InstructionFields, TypeCode}, }; -use super::thread::Thread; +use super::{Pointer, Register, thread::Thread}; #[derive(Debug)] pub struct ActionSequence { @@ -74,7 +74,39 @@ pub fn close(instruction: InstructionFields, thread: &mut Thread) {} pub fn load_boolean(instruction: InstructionFields, thread: &mut Thread) {} -pub fn load_constant(instruction: InstructionFields, thread: &mut Thread) {} +pub fn load_constant(instruction: InstructionFields, thread: &mut Thread) { + let destination = instruction.a_field as usize; + let constant_index = instruction.b_field as usize; + let constant_type = instruction.b_type; + let jump_next = instruction.c_field != 0; + + match constant_type { + TypeCode::CHARACTER => { + let constant = *thread.get_constant(constant_index).as_character().unwrap(); + let register = Register::Value(constant); + + thread.set_character_register(destination, register); + } + TypeCode::FLOAT => { + let constant = *thread.get_constant(constant_index).as_float().unwrap(); + let register = Register::Value(constant); + + thread.set_float_register(destination, register); + } + TypeCode::INTEGER => { + let constant = *thread.get_constant(constant_index).as_integer().unwrap(); + let register = Register::Value(constant); + + thread.set_integer_register(destination as usize, register); + } + TypeCode::STRING => { + let register = Register::Pointer(Pointer::Constant(constant_index)); + + thread.set_string_register(destination as usize, register); + } + _ => unimplemented!(), + } +} pub fn load_list(instruction: InstructionFields, thread: &mut Thread) {} @@ -111,9 +143,10 @@ pub fn add(instruction: InstructionFields, thread: &mut Thread) { } else { thread.get_integer_register(right) }; - let result = left_value + right_value; + let sum = left_value + right_value; + let register = Register::Value(sum); - thread.set_integer_register(destination, result); + thread.set_integer_register(destination, register); } (TypeCode::STRING, TypeCode::STRING) => { let left_value = if left_is_constant { @@ -146,9 +179,10 @@ pub fn add(instruction: InstructionFields, thread: &mut Thread) { } else { thread.get_string_register(right).clone() }; - let result = left_value + &right_value; + let concatenated = left_value + &right_value; + let register = Register::Value(concatenated); - thread.set_string_register(destination, result); + thread.set_string_register(destination, register); } _ => unimplemented!(), } @@ -220,7 +254,7 @@ pub fn jump(instruction: InstructionFields, thread: &mut Thread) { if is_positive { thread.current_frame_mut().ip += offset; } else { - thread.current_frame_mut().ip -= offset; + thread.current_frame_mut().ip -= offset + 1; } } @@ -236,23 +270,23 @@ pub fn r#return(instruction: InstructionFields, thread: &mut Thread) { if should_return_value { match return_type { TypeCode::BOOLEAN => { - let return_value = thread.get_boolean_register(return_register); + let return_value = *thread.get_boolean_register(return_register); thread.return_value = Some(Some(Value::boolean(return_value))); } TypeCode::BYTE => { - let return_value = thread.get_byte_register(return_register); + let return_value = *thread.get_byte_register(return_register); thread.return_value = Some(Some(Value::byte(return_value))); } TypeCode::CHARACTER => { - let return_value = thread.get_character_register(return_register); + let return_value = *thread.get_character_register(return_register); thread.return_value = Some(Some(Value::character(return_value))); } TypeCode::FLOAT => { - let return_value = thread.get_float_register(return_register); + let return_value = *thread.get_float_register(return_register); thread.return_value = Some(Some(Value::float(return_value))); } TypeCode::INTEGER => { - let return_value = thread.get_integer_register(return_register); + let return_value = *thread.get_integer_register(return_register); thread.return_value = Some(Some(Value::integer(return_value))); } TypeCode::STRING => { diff --git a/dust-lang/src/vm/thread.rs b/dust-lang/src/vm/thread.rs index a0057de..dcbb4ba 100644 --- a/dust-lang/src/vm/thread.rs +++ b/dust-lang/src/vm/thread.rs @@ -1,4 +1,4 @@ -use std::{sync::Arc, thread::JoinHandle}; +use std::{collections::HashMap, sync::Arc, thread::JoinHandle}; use tracing::{info, trace}; @@ -10,6 +10,7 @@ pub struct Thread { chunk: Arc, call_stack: Vec, pub return_value: Option>, + pub integer_cache: HashMap, _spawned_threads: Vec>, } @@ -24,6 +25,7 @@ impl Thread { chunk, call_stack, return_value: None, + integer_cache: HashMap::new(), _spawned_threads: Vec::new(), } } @@ -46,9 +48,9 @@ impl Thread { ip }; let current_action = if cfg!(debug_assertions) { - current_frame.action_sequence.actions.get(ip).unwrap() + current_frame.action_sequence.actions.get_mut(ip).unwrap() } else { - unsafe { current_frame.action_sequence.actions.get_unchecked(ip) } + unsafe { current_frame.action_sequence.actions.get_unchecked_mut(ip) } }; trace!( @@ -86,7 +88,7 @@ impl Thread { } } - pub fn get_boolean_register(&self, register_index: usize) -> bool { + pub fn get_boolean_register(&self, register_index: usize) -> &bool { let register = if cfg!(debug_assertions) { self.call_stack .last() @@ -107,13 +109,13 @@ impl Thread { }; match register { - Register::Value(value) => *value, + Register::Value(value) => value, Register::Pointer(pointer) => self.get_pointer_to_boolean(pointer), Register::Empty => panic!("Attempted to get value from empty register"), } } - pub fn get_pointer_to_boolean(&self, pointer: &Pointer) -> bool { + pub fn get_pointer_to_boolean(&self, pointer: &Pointer) -> &bool { match pointer { Pointer::Register(register_index) => self.get_boolean_register(*register_index), Pointer::Constant(constant_index) => { @@ -132,7 +134,7 @@ impl Thread { }; match register { - Register::Value(value) => *value, + Register::Value(value) => value, Register::Pointer(pointer) => self.get_pointer_to_boolean(pointer), Register::Empty => panic!("Attempted to get value from empty register"), } @@ -140,8 +142,8 @@ impl Thread { } } - pub fn set_boolean_register(&mut self, register_index: usize, value: bool) { - let register = if cfg!(debug_assertions) { + pub fn set_boolean_register(&mut self, register_index: usize, new_register: Register) { + let old_register = if cfg!(debug_assertions) { self.call_stack .last_mut() .unwrap() @@ -160,10 +162,10 @@ impl Thread { } }; - *register = Register::Value(value); + *old_register = new_register; } - pub fn get_byte_register(&self, register_index: usize) -> u8 { + pub fn get_byte_register(&self, register_index: usize) -> &u8 { let register = if cfg!(debug_assertions) { self.call_stack .last() @@ -184,13 +186,13 @@ impl Thread { }; match register { - Register::Value(value) => *value, + Register::Value(value) => value, Register::Pointer(pointer) => self.get_pointer_to_byte(pointer), Register::Empty => panic!("Attempted to get value from empty register"), } } - pub fn get_pointer_to_byte(&self, pointer: &Pointer) -> u8 { + pub fn get_pointer_to_byte(&self, pointer: &Pointer) -> &u8 { match pointer { Pointer::Register(register_index) => self.get_byte_register(*register_index), Pointer::Constant(constant_index) => { @@ -209,7 +211,7 @@ impl Thread { }; match register { - Register::Value(value) => *value, + Register::Value(value) => value, Register::Pointer(pointer) => self.get_pointer_to_byte(pointer), Register::Empty => panic!("Attempted to get value from empty register"), } @@ -217,8 +219,8 @@ impl Thread { } } - pub fn set_byte_register(&mut self, register_index: usize, value: u8) { - let register = if cfg!(debug_assertions) { + pub fn set_byte_register(&mut self, register_index: usize, new_register: Register) { + let old_register = if cfg!(debug_assertions) { self.call_stack .last_mut() .unwrap() @@ -237,10 +239,10 @@ impl Thread { } }; - *register = Register::Value(value); + *old_register = new_register; } - pub fn get_character_register(&self, register_index: usize) -> char { + pub fn get_character_register(&self, register_index: usize) -> &char { let register = if cfg!(debug_assertions) { self.call_stack .last() @@ -261,13 +263,13 @@ impl Thread { }; match register { - Register::Value(value) => *value, + Register::Value(value) => value, Register::Pointer(pointer) => self.get_pointer_to_character(pointer), Register::Empty => panic!("Attempted to get value from empty register"), } } - pub fn get_pointer_to_character(&self, pointer: &Pointer) -> char { + pub fn get_pointer_to_character(&self, pointer: &Pointer) -> &char { match pointer { Pointer::Register(register_index) => self.get_character_register(*register_index), Pointer::Constant(constant_index) => { @@ -295,7 +297,7 @@ impl Thread { }; match register { - Register::Value(value) => *value, + Register::Value(value) => value, Register::Pointer(pointer) => self.get_pointer_to_character(pointer), Register::Empty => panic!("Attempted to get value from empty register"), } @@ -303,8 +305,8 @@ impl Thread { } } - pub fn set_character_register(&mut self, register_index: usize, value: char) { - let register = if cfg!(debug_assertions) { + pub fn set_character_register(&mut self, register_index: usize, new_register: Register) { + let old_register = if cfg!(debug_assertions) { self.call_stack .last_mut() .unwrap() @@ -323,10 +325,10 @@ impl Thread { } }; - *register = Register::Value(value); + *old_register = new_register; } - pub fn get_float_register(&self, register_index: usize) -> f64 { + pub fn get_float_register(&self, register_index: usize) -> &f64 { let register = if cfg!(debug_assertions) { self.call_stack .last() @@ -347,13 +349,13 @@ impl Thread { }; match register { - Register::Value(value) => *value, + Register::Value(value) => value, Register::Pointer(pointer) => self.get_pointer_to_float(pointer), Register::Empty => panic!("Attempted to get value from empty register"), } } - pub fn get_pointer_to_float(&self, pointer: &Pointer) -> f64 { + pub fn get_pointer_to_float(&self, pointer: &Pointer) -> &f64 { match pointer { Pointer::Register(register_index) => self.get_float_register(*register_index), Pointer::Constant(constant_index) => { @@ -372,7 +374,7 @@ impl Thread { }; match register { - Register::Value(value) => *value, + Register::Value(value) => value, Register::Pointer(pointer) => self.get_pointer_to_float(pointer), Register::Empty => panic!("Attempted to get value from empty register"), } @@ -380,8 +382,8 @@ impl Thread { } } - pub fn set_float_register(&mut self, register_index: usize, value: f64) { - let register = if cfg!(debug_assertions) { + pub fn set_float_register(&mut self, register_index: usize, new_register: Register) { + let old_register = if cfg!(debug_assertions) { self.call_stack .last_mut() .unwrap() @@ -400,10 +402,10 @@ impl Thread { } }; - *register = Register::Value(value); + *old_register = new_register; } - pub fn get_integer_register(&self, register_index: usize) -> i64 { + pub fn get_integer_register(&self, register_index: usize) -> &i64 { let register = if cfg!(debug_assertions) { self.call_stack .last() @@ -424,13 +426,13 @@ impl Thread { }; match register { - Register::Value(value) => *value, + Register::Value(value) => value, Register::Pointer(pointer) => self.get_pointer_to_integer(pointer), Register::Empty => panic!("Attempted to get value from empty register"), } } - pub fn get_pointer_to_integer(&self, pointer: &Pointer) -> i64 { + pub fn get_pointer_to_integer(&self, pointer: &Pointer) -> &i64 { match pointer { Pointer::Register(register_index) => self.get_integer_register(*register_index), Pointer::Constant(constant_index) => { @@ -449,7 +451,7 @@ impl Thread { }; match register { - Register::Value(value) => *value, + Register::Value(value) => value, Register::Pointer(pointer) => self.get_pointer_to_integer(pointer), Register::Empty => panic!("Attempted to get value from empty register"), } @@ -457,8 +459,8 @@ impl Thread { } } - pub fn set_integer_register(&mut self, register_index: usize, value: i64) { - let register = if cfg!(debug_assertions) { + pub fn set_integer_register(&mut self, register_index: usize, new_register: Register) { + let old_register = if cfg!(debug_assertions) { self.call_stack .last_mut() .unwrap() @@ -477,7 +479,7 @@ impl Thread { } }; - *register = Register::Value(value); + *old_register = new_register; } pub fn get_string_register(&self, register_index: usize) -> &DustString { @@ -534,8 +536,12 @@ impl Thread { } } - pub fn set_string_register(&mut self, register_index: usize, value: DustString) { - let register = if cfg!(debug_assertions) { + pub fn set_string_register( + &mut self, + register_index: usize, + new_register: Register, + ) { + let old_register = if cfg!(debug_assertions) { self.call_stack .last_mut() .unwrap() @@ -554,7 +560,7 @@ impl Thread { } }; - *register = Register::Value(value); + *old_register = new_register; } pub fn get_constant(&self, constant_index: usize) -> &ConcreteValue {