diff --git a/dust-lang/src/native_function/assert.rs b/dust-lang/src/native_function/assert.rs index 28d96e7..3925582 100644 --- a/dust-lang/src/native_function/assert.rs +++ b/dust-lang/src/native_function/assert.rs @@ -1,6 +1,6 @@ use std::{ops::Range, panic}; -use crate::vm::{RuntimeValue, Thread}; +use crate::vm::Thread; pub fn panic(data: &mut Thread, _: usize, argument_range: Range) { let current_frame = data.current_frame(); @@ -8,20 +8,9 @@ pub fn panic(data: &mut Thread, _: usize, argument_range: Range) { let mut message = format!("Dust panic at {position}!"); for register_index in argument_range { - let string_value = current_frame.get_string_from_register(register_index); - - match string_value { - RuntimeValue::Raw(value) => { - message.push_str(value.as_str()); - } - RuntimeValue::Rc(rc) => { - message.push_str(rc.as_str()); - } - RuntimeValue::RefCell(ref_cell) => { - message.push_str(ref_cell.borrow().as_str()); - } - } + let string = current_frame.get_string_from_register(register_index); + message.push_str(string); message.push('\n'); } diff --git a/dust-lang/src/native_function/io.rs b/dust-lang/src/native_function/io.rs index ba39c39..dfa8f1d 100644 --- a/dust-lang/src/native_function/io.rs +++ b/dust-lang/src/native_function/io.rs @@ -1,7 +1,7 @@ use std::io::{stdin, stdout, Write}; use std::ops::Range; -use crate::vm::{RuntimeValue, Thread}; +use crate::vm::Thread; use crate::DustString; pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range) { @@ -13,53 +13,34 @@ pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range) { - let current_frame = data.current_frame(); + let current_frame = data.current_frame_mut(); let mut stdout = stdout(); for register_index in argument_range { - let value = current_frame.get_string_from_register(register_index); - - match value { - RuntimeValue::Raw(value) => { - let _ = stdout.write(value.as_bytes()); - } - RuntimeValue::Rc(value) => { - let _ = stdout.write(value.as_bytes()); - } - RuntimeValue::RefCell(ref_cell) => { - let _ = stdout.write(ref_cell.borrow().as_bytes()); - } - } + let string = current_frame.get_string_from_register(register_index); + let _ = stdout.write(string.as_bytes()); } let _ = stdout.flush(); } pub fn write_line(data: &mut Thread, _: usize, argument_range: Range) { - let current_frame = data.current_frame(); + let current_frame = data.current_frame_mut(); let mut stdout = stdout().lock(); for register_index in argument_range { - let value = current_frame.get_string_from_register(register_index); - - match value { - RuntimeValue::Raw(value) => { - let _ = stdout.write(value.as_bytes()); - } - RuntimeValue::Rc(value) => { - let _ = stdout.write(value.as_bytes()); - } - RuntimeValue::RefCell(ref_cell) => { - let _ = stdout.write(ref_cell.borrow().as_bytes()); - } - } + let string = current_frame.get_string_from_register(register_index); + let _ = stdout.write(string.as_bytes()); } let _ = stdout.write(b"\n"); diff --git a/dust-lang/src/native_function/random.rs b/dust-lang/src/native_function/random.rs index c928b26..cb1d05b 100644 --- a/dust-lang/src/native_function/random.rs +++ b/dust-lang/src/native_function/random.rs @@ -2,7 +2,7 @@ use std::ops::Range; use rand::Rng; -use crate::vm::{RuntimeValue, Thread}; +use crate::vm::Thread; pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range) { let current_frame = data.current_frame_mut(); @@ -14,9 +14,7 @@ pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range { - let return_value = current_frame - .get_boolean_from_register(return_register) - .clone_inner(); - thread.return_value = Some(Value::boolean(return_value)); - } - TypeCode::BYTE => { - let return_value = current_frame - .get_byte_from_register(return_register) - .clone_inner(); - thread.return_value = Some(Value::byte(return_value)); - } - TypeCode::CHARACTER => { - let return_value = current_frame - .get_character_from_register(return_register) - .clone_inner(); - thread.return_value = Some(Value::character(return_value)); - } - TypeCode::FLOAT => { - let return_value = current_frame - .get_float_from_register(return_register) - .clone_inner(); - thread.return_value = Some(Value::float(return_value)); - } - TypeCode::INTEGER => { - let return_value = current_frame - .get_integer_from_register(return_register) - .clone_inner(); - thread.return_value = Some(Value::integer(return_value)); - } - TypeCode::STRING => { - let return_value = current_frame - .get_string_from_register(return_register) - .clone_inner(); - thread.return_value = Some(Value::string(return_value)); - } - TypeCode::LIST => { - let abstract_list = current_frame - .get_list_from_register(return_register) - .clone_inner(); - let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len()); + // if should_return_value { + // match return_type { + // TypeCode::BOOLEAN => { + // let return_value = current_frame + // .get_boolean_from_register(return_register) + // .clone_inner(); + // thread.return_value = Some(Value::boolean(return_value)); + // } + // TypeCode::BYTE => { + // let return_value = current_frame + // .get_byte_from_register(return_register) + // .clone_inner(); + // thread.return_value = Some(Value::byte(return_value)); + // } + // TypeCode::CHARACTER => { + // let return_value = current_frame + // .get_character_from_register(return_register) + // .clone_inner(); + // thread.return_value = Some(Value::character(return_value)); + // } + // TypeCode::FLOAT => { + // let return_value = current_frame + // .get_float_from_register(return_register) + // .clone_inner(); + // thread.return_value = Some(Value::float(return_value)); + // } + // TypeCode::INTEGER => { + // let return_value = current_frame + // .get_integer_from_register(return_register) + // .clone_inner(); + // thread.return_value = Some(Value::integer(return_value)); + // } + // TypeCode::STRING => { + // let return_value = current_frame + // .get_string_from_register(return_register) + // .clone_inner(); + // thread.return_value = Some(Value::string(return_value)); + // } + // TypeCode::LIST => { + // let abstract_list = current_frame + // .get_list_from_register(return_register) + // .clone_inner(); + // let mut concrete_list = Vec::with_capacity(abstract_list.item_pointers.len()); - match abstract_list.item_type { - TypeCode::BOOLEAN => { - for pointer in abstract_list.item_pointers { - let boolean = current_frame - .get_boolean_from_pointer(&pointer) - .clone_inner(); - let value = ConcreteValue::Boolean(boolean); + // match abstract_list.item_type { + // TypeCode::BOOLEAN => { + // for pointer in abstract_list.item_pointers { + // let boolean = current_frame + // .get_boolean_from_pointer(&pointer) + // .clone_inner(); + // let value = ConcreteValue::Boolean(boolean); - concrete_list.push(value); - } - } - TypeCode::BYTE => { - for pointer in abstract_list.item_pointers { - let byte = current_frame.get_byte_from_pointer(&pointer).clone_inner(); - let value = ConcreteValue::Byte(byte); + // concrete_list.push(value); + // } + // } + // TypeCode::BYTE => { + // for pointer in abstract_list.item_pointers { + // let byte = current_frame.get_byte_from_pointer(&pointer).clone_inner(); + // let value = ConcreteValue::Byte(byte); - concrete_list.push(value); - } - } - TypeCode::CHARACTER => { - for pointer in abstract_list.item_pointers { - let character = current_frame - .get_character_from_pointer(&pointer) - .clone_inner(); - let value = ConcreteValue::Character(character); + // concrete_list.push(value); + // } + // } + // TypeCode::CHARACTER => { + // for pointer in abstract_list.item_pointers { + // let character = current_frame + // .get_character_from_pointer(&pointer) + // .clone_inner(); + // let value = ConcreteValue::Character(character); - concrete_list.push(value); - } - } - TypeCode::FLOAT => { - for pointer in abstract_list.item_pointers { - let float = - current_frame.get_float_from_pointer(&pointer).clone_inner(); - let value = ConcreteValue::Float(float); + // concrete_list.push(value); + // } + // } + // TypeCode::FLOAT => { + // for pointer in abstract_list.item_pointers { + // let float = + // current_frame.get_float_from_pointer(&pointer).clone_inner(); + // let value = ConcreteValue::Float(float); - concrete_list.push(value); - } - } - TypeCode::INTEGER => { - for pointer in abstract_list.item_pointers { - let integer = current_frame - .get_integer_from_pointer(&pointer) - .clone_inner(); - let value = ConcreteValue::Integer(integer); + // concrete_list.push(value); + // } + // } + // TypeCode::INTEGER => { + // for pointer in abstract_list.item_pointers { + // let integer = current_frame + // .get_integer_from_pointer(&pointer) + // .clone_inner(); + // let value = ConcreteValue::Integer(integer); - concrete_list.push(value); - } - } - TypeCode::STRING => { - for pointer in abstract_list.item_pointers { - let string = current_frame - .get_string_from_pointer(&pointer) - .clone_inner(); - let value = ConcreteValue::String(string); + // concrete_list.push(value); + // } + // } + // TypeCode::STRING => { + // for pointer in abstract_list.item_pointers { + // let string = current_frame + // .get_string_from_pointer(&pointer) + // .clone_inner(); + // let value = ConcreteValue::String(string); - concrete_list.push(value); - } - } - _ => todo!(), - } + // concrete_list.push(value); + // } + // } + // _ => todo!(), + // } - thread.return_value = Some(Value::Concrete(ConcreteValue::list( - concrete_list, - abstract_list.item_type, - ))); - } - _ => unreachable!(), - } - } + // thread.return_value = Some(Value::Concrete(ConcreteValue::list( + // concrete_list, + // abstract_list.item_type, + // ))); + // } + // _ => unreachable!(), + // } + // } } diff --git a/dust-lang/src/vm/call_frame.rs b/dust-lang/src/vm/call_frame.rs index fabe60f..ef026fc 100644 --- a/dust-lang/src/vm/call_frame.rs +++ b/dust-lang/src/vm/call_frame.rs @@ -15,7 +15,6 @@ pub struct CallFrame { pub ip: usize, pub return_register: u16, pub registers: RegisterTable, - pub constants: ConstantTable, } impl CallFrame { @@ -30,174 +29,126 @@ impl CallFrame { lists: RegisterList::new(chunk.list_register_count as usize), functions: RegisterList::new(chunk.function_register_count as usize), }; - let constants = ConstantTable { - characters: chunk - .character_constants - .iter() - .map(|&character| RuntimeValue::Raw(character)) - .collect(), - floats: chunk - .float_constants - .iter() - .map(|&float| RuntimeValue::Raw(float)) - .collect(), - integers: chunk - .integer_constants - .iter() - .map(|&integer| RuntimeValue::Raw(integer)) - .collect(), - strings: chunk - .string_constants - .iter() - .map(|string| RuntimeValue::Raw(string.clone())) - .collect(), - }; Self { chunk, ip: 0, return_register, registers, - constants, } } - pub fn get_boolean_from_register(&self, register_index: usize) -> &RuntimeValue { + pub fn get_boolean_from_register(&self, register_index: usize) -> bool { let register = self.registers.booleans.get(register_index); match register { - Register::Value { value, .. } => value, + Register::Value { value, .. } => *value, Register::Pointer { pointer, .. } => self.get_boolean_from_pointer(pointer), } } - pub fn get_boolean_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + pub fn get_boolean_from_pointer(&self, pointer: &Pointer) -> bool { match pointer { Pointer::Register(register_index) => self.get_boolean_from_register(*register_index), Pointer::Constant(_) => panic!("Attempted to get boolean from constant pointer"), } } - pub fn get_byte_from_register(&self, register_index: usize) -> &RuntimeValue { + pub fn get_byte_from_register(&self, register_index: usize) -> u8 { let register = self.registers.bytes.get(register_index); match register { - Register::Value { value, .. } => value, + Register::Value { value, .. } => *value, Register::Pointer { pointer, .. } => self.get_byte_from_pointer(pointer), } } - pub fn get_byte_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + pub fn get_byte_from_pointer(&self, pointer: &Pointer) -> u8 { match pointer { Pointer::Register(register_index) => self.get_byte_from_register(*register_index), Pointer::Constant(_) => panic!("Attempted to get byte from constant pointer"), } } - pub fn get_character_from_register(&self, register_index: usize) -> &RuntimeValue { + pub fn get_character_from_register(&self, register_index: usize) -> char { let register = self.registers.characters.get(register_index); match register { - Register::Value { value, .. } => value, + Register::Value { value, .. } => *value, Register::Pointer { pointer, .. } => self.get_character_from_pointer(pointer), } } - pub fn get_character_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + pub fn get_character_from_pointer(&self, pointer: &Pointer) -> char { match pointer { Pointer::Register(register_index) => self.get_character_from_register(*register_index), Pointer::Constant(constant_index) => self.get_character_constant(*constant_index), } } - pub fn get_character_constant(&self, constant_index: usize) -> &RuntimeValue { - if cfg!(debug_assertions) { - self.constants.characters.get(constant_index).unwrap() + pub fn get_character_constant(&self, constant_index: usize) -> char { + let constant = if cfg!(debug_assertions) { + self.chunk.character_constants.get(constant_index).unwrap() } else { - unsafe { self.constants.characters.get_unchecked(constant_index) } - } + unsafe { self.chunk.character_constants.get_unchecked(constant_index) } + }; + + *constant } - pub fn get_float_from_register(&self, register_index: usize) -> &RuntimeValue { + pub fn get_float_from_register(&self, register_index: usize) -> f64 { let register = self.registers.floats.get(register_index); match register { - Register::Value { value, .. } => value, + Register::Value { value, .. } => *value, Register::Pointer { pointer, .. } => self.get_float_from_pointer(pointer), } } - pub fn get_float_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + pub fn get_float_from_pointer(&self, pointer: &Pointer) -> f64 { match pointer { Pointer::Register(register_index) => self.get_float_from_register(*register_index), Pointer::Constant(constant_index) => self.get_float_constant(*constant_index), } } - pub fn get_float_constant(&self, constant_index: usize) -> &RuntimeValue { - if cfg!(debug_assertions) { - self.constants.floats.get(constant_index).unwrap() + pub fn get_float_constant(&self, constant_index: usize) -> f64 { + let constant = if cfg!(debug_assertions) { + self.chunk.float_constants.get(constant_index).unwrap() } else { - unsafe { self.constants.floats.get_unchecked(constant_index) } - } + unsafe { self.chunk.float_constants.get_unchecked(constant_index) } + }; + + *constant } - pub fn get_integer_from_register(&self, register_index: usize) -> &RuntimeValue { + pub fn get_integer_from_register(&self, register_index: usize) -> i64 { let register = self.registers.integers.get(register_index); match register { - Register::Value { value, .. } => value, + Register::Value { value, .. } => *value, Register::Pointer { pointer, .. } => self.get_integer_from_pointer(pointer), } } - pub fn get_integer_from_register_mut( - &mut self, - register_index: usize, - ) -> &mut RuntimeValue { - let register = self.registers.integers.get_mut(register_index); - - match register { - Register::Value { value, .. } => value, - Register::Pointer { .. } => { - panic!("Attempted to get mutable integer from pointer") - } - } - } - - pub fn get_integer_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + pub fn get_integer_from_pointer(&self, pointer: &Pointer) -> i64 { match pointer { Pointer::Register(register_index) => self.get_integer_from_register(*register_index), Pointer::Constant(constant_index) => self.get_integer_constant(*constant_index), } } - pub fn get_integer_from_pointer_mut(&mut self, pointer: &Pointer) -> &mut RuntimeValue { - match pointer { - Pointer::Register(register_index) => { - self.get_integer_from_register_mut(*register_index) - } - Pointer::Constant(constant_index) => self.get_integer_constant_mut(*constant_index), - } - } - - pub fn get_integer_constant(&self, constant_index: usize) -> &RuntimeValue { - if cfg!(debug_assertions) { - self.constants.integers.get(constant_index).unwrap() + pub fn get_integer_constant(&self, constant_index: usize) -> i64 { + let constant = if cfg!(debug_assertions) { + self.chunk.integer_constants.get(constant_index).unwrap() } else { - unsafe { self.constants.integers.get_unchecked(constant_index) } - } + unsafe { self.chunk.integer_constants.get_unchecked(constant_index) } + }; + + *constant } - pub fn get_integer_constant_mut(&mut self, constant_index: usize) -> &mut RuntimeValue { - if cfg!(debug_assertions) { - self.constants.integers.get_mut(constant_index).unwrap() - } else { - unsafe { self.constants.integers.get_unchecked_mut(constant_index) } - } - } - - pub fn get_string_from_register(&self, register_index: usize) -> &RuntimeValue { + pub fn get_string_from_register(&self, register_index: usize) -> &DustString { let register = self.registers.strings.get(register_index); match register { @@ -206,33 +157,22 @@ impl CallFrame { } } - pub fn get_string_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + pub fn get_string_from_pointer(&self, pointer: &Pointer) -> &DustString { match pointer { Pointer::Register(register_index) => self.get_string_from_register(*register_index), Pointer::Constant(constant_index) => self.get_string_constant(*constant_index), } } - pub fn get_string_constant(&self, constant_index: usize) -> &RuntimeValue { + pub fn get_string_constant(&self, constant_index: usize) -> &DustString { if cfg!(debug_assertions) { - self.constants.strings.get(constant_index).unwrap() + self.chunk.string_constants.get(constant_index).unwrap() } else { - unsafe { self.constants.strings.get_unchecked(constant_index) } + unsafe { self.chunk.string_constants.get_unchecked(constant_index) } } } - pub fn get_string_constant_mut( - &mut self, - constant_index: usize, - ) -> &mut RuntimeValue { - if cfg!(debug_assertions) { - self.constants.strings.get_mut(constant_index).unwrap() - } else { - unsafe { self.constants.strings.get_unchecked_mut(constant_index) } - } - } - - pub fn get_list_from_register(&self, register_index: usize) -> &RuntimeValue { + pub fn get_list_from_register(&self, register_index: usize) -> &AbstractList { let register = self.registers.lists.get(register_index); match register { @@ -241,10 +181,7 @@ impl CallFrame { } } - pub fn get_list_from_register_mut( - &mut self, - register_index: usize, - ) -> &mut RuntimeValue { + pub fn get_list_from_register_mut(&mut self, register_index: usize) -> &mut AbstractList { let register = self.registers.lists.get_mut(register_index); match register { @@ -253,14 +190,14 @@ impl CallFrame { } } - pub fn get_list_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + pub fn get_list_from_pointer(&self, pointer: &Pointer) -> &AbstractList { match pointer { Pointer::Register(register_index) => self.get_list_from_register(*register_index), Pointer::Constant(_) => panic!("Attempted to get list from constant pointer"), } } - pub fn get_function_from_register(&self, register_index: usize) -> &RuntimeValue { + pub fn get_function_from_register(&self, register_index: usize) -> &Function { let register = self.registers.functions.get(register_index); match register { @@ -269,10 +206,7 @@ impl CallFrame { } } - pub fn get_function_from_register_mut( - &mut self, - register_index: usize, - ) -> &mut RuntimeValue { + pub fn get_function_from_register_mut(&mut self, register_index: usize) -> &mut Function { let register = self.registers.functions.get_mut(register_index); match register { @@ -281,7 +215,7 @@ impl CallFrame { } } - pub fn get_function_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + pub fn get_function_from_pointer(&self, pointer: &Pointer) -> &Function { match pointer { Pointer::Register(register_index) => self.get_function_from_register(*register_index), Pointer::Constant(_) => panic!("Attempted to get function from constant pointer"), @@ -303,14 +237,6 @@ impl Display for CallFrame { } } -#[derive(Debug, Default)] -pub struct ConstantTable { - pub characters: Vec>, - pub floats: Vec>, - pub integers: Vec>, - pub strings: Vec>, -} - #[derive(Debug)] pub struct RegisterTable { pub booleans: RegisterList, @@ -362,6 +288,12 @@ where } } + pub fn set_to_new_register(&mut self, index: usize, new_value: T) { + assert!(index < self.registers.len(), "Register index out of bounds"); + + self.registers[index] = Register::value(new_value) + } + pub fn close(&mut self, index: usize) { if cfg!(debug_assertions) { self.registers.get_mut(index).unwrap().close() @@ -395,17 +327,18 @@ impl IndexMut for RegisterList { #[derive(Clone, Debug)] pub enum Register { - Value { - value: RuntimeValue, - is_closed: bool, - }, - Pointer { - pointer: Pointer, - is_closed: bool, - }, + Value { value: T, is_closed: bool }, + Pointer { pointer: Pointer, is_closed: bool }, } impl Register { + pub fn value(value: T) -> Self { + Self::Value { + value, + is_closed: false, + } + } + pub fn is_closed(&self) -> bool { match self { Self::Value { is_closed, .. } => *is_closed, @@ -420,7 +353,7 @@ impl Register { } } - pub fn set(&mut self, new_value: RuntimeValue) { + pub fn set(&mut self, new_value: T) { match self { Self::Value { value: old_value, .. @@ -434,14 +367,14 @@ impl Register { } } - pub fn as_value(&self) -> &RuntimeValue { + pub fn as_value(&self) -> &T { match self { Self::Value { value, .. } => value, Self::Pointer { .. } => panic!("Attempted to use pointer as value"), } } - pub fn as_value_mut(&mut self) -> &mut RuntimeValue { + pub fn as_value_mut(&mut self) -> &mut T { match self { Self::Value { value, .. } => value, Self::Pointer { .. } => panic!("Attempted to use pointer as value"), @@ -452,217 +385,12 @@ impl Register { impl Default for Register { fn default() -> Self { Self::Value { - value: RuntimeValue::Raw(Default::default()), + value: Default::default(), is_closed: false, } } } -#[derive(Clone, Debug)] -pub enum RuntimeValue { - Raw(T), - Rc(Rc), - RefCell(Rc>), -} - -impl RuntimeValue { - pub fn ref_cell(value: T) -> Self { - Self::RefCell(Rc::new(RefCell::new(value))) - } - - pub fn rc(value: T) -> Self { - Self::Rc(Rc::new(value)) - } - - pub fn to_ref_cell(&mut self) -> Self { - match self { - Self::Raw(value) => RuntimeValue::ref_cell(value.clone()), - Self::Rc(value) => RuntimeValue::ref_cell(value.as_ref().clone()), - Self::RefCell(_) => self.clone(), - } - } - - pub fn to_rc(&mut self) -> Self { - match self { - Self::Raw(value) => RuntimeValue::rc(value.clone()), - Self::Rc(_) => self.clone(), - Self::RefCell(value) => RuntimeValue::rc(value.borrow().clone()), - } - } - - pub fn set_inner(&mut self, new_value: T) { - match self { - Self::Raw(value) => *value = new_value, - Self::RefCell(value) => { - let _ = value.replace(new_value); - } - Self::Rc(_) => panic!("Attempted to modify immutable runtime value"), - } - } - - pub fn clone_inner(&self) -> T { - match self { - Self::Raw(value) => value.clone(), - Self::Rc(value) => value.as_ref().clone(), - Self::RefCell(value) => value.borrow().clone(), - } - } - - pub fn borrow_mut(&self) -> RefMut { - match self { - Self::RefCell(value) => value.borrow_mut(), - _ => panic!("Attempted to borrow mutable reference from immutable runtime value"), - } - } -} - -const BYTE_ADD: fn(u8, u8) -> u8 = u8::saturating_add; - -impl Add for &RuntimeValue { - type Output = u8; - - fn add(self, other: Self) -> Self::Output { - let left = match self { - RuntimeValue::Raw(value) => *value, - RuntimeValue::Rc(value) => **value, - RuntimeValue::RefCell(value) => *value.borrow(), - }; - let right = match other { - RuntimeValue::Raw(value) => *value, - RuntimeValue::Rc(value) => **value, - RuntimeValue::RefCell(value) => *value.borrow(), - }; - - BYTE_ADD(left, right) - } -} - -const FLOAT_ADD: fn(f64, f64) -> f64 = f64::add; - -impl Add for &RuntimeValue { - type Output = f64; - - fn add(self, other: Self) -> Self::Output { - let left = match self { - RuntimeValue::Raw(value) => *value, - RuntimeValue::Rc(value) => **value, - RuntimeValue::RefCell(value) => *value.borrow(), - }; - let right = match other { - RuntimeValue::Raw(value) => *value, - RuntimeValue::Rc(value) => **value, - RuntimeValue::RefCell(value) => *value.borrow(), - }; - - FLOAT_ADD(left, right) - } -} - -const INTEGER_ADD: fn(i64, i64) -> i64 = i64::saturating_add; - -impl Add for &RuntimeValue { - type Output = i64; - - fn add(self, other: Self) -> Self::Output { - let left = match self { - RuntimeValue::Raw(value) => *value, - RuntimeValue::Rc(value) => **value, - RuntimeValue::RefCell(value) => *value.borrow(), - }; - let right = match other { - RuntimeValue::Raw(value) => *value, - RuntimeValue::Rc(value) => **value, - RuntimeValue::RefCell(value) => *value.borrow(), - }; - - INTEGER_ADD(left, right) - } -} - -impl PartialEq for RuntimeValue { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (RuntimeValue::Raw(left), RuntimeValue::Raw(right)) => left == right, - (RuntimeValue::Raw(left), RuntimeValue::Rc(right)) => left == &**right, - (RuntimeValue::Raw(left), RuntimeValue::RefCell(right)) => { - let right = right.borrow(); - - left == &*right - } - (RuntimeValue::Rc(left), RuntimeValue::Raw(right)) => **left == *right, - (RuntimeValue::Rc(left), RuntimeValue::Rc(right)) => **left == **right, - (RuntimeValue::Rc(left), RuntimeValue::RefCell(right)) => { - let right = right.borrow(); - - **left == *right - } - (RuntimeValue::RefCell(left), RuntimeValue::RefCell(right)) => { - let left = left.borrow(); - let right = right.borrow(); - - *left == *right - } - (RuntimeValue::RefCell(left), RuntimeValue::Raw(right)) => { - let left = left.borrow(); - - *left == *right - } - (RuntimeValue::RefCell(left), RuntimeValue::Rc(right)) => { - let left = left.borrow(); - - *left == **right - } - } - } -} - -impl PartialOrd for RuntimeValue { - fn partial_cmp(&self, other: &Self) -> Option { - match (self, other) { - (RuntimeValue::Raw(left), RuntimeValue::Raw(right)) => left.partial_cmp(right), - (RuntimeValue::Raw(left), RuntimeValue::Rc(right)) => left.partial_cmp(&**right), - (RuntimeValue::Raw(left), RuntimeValue::RefCell(right)) => { - let right = right.borrow(); - - left.partial_cmp(&*right) - } - (RuntimeValue::Rc(left), RuntimeValue::Raw(right)) => (**left).partial_cmp(right), - (RuntimeValue::Rc(left), RuntimeValue::Rc(right)) => left.partial_cmp(right), - (RuntimeValue::Rc(left), RuntimeValue::RefCell(right)) => { - let right = right.borrow(); - - (**left).partial_cmp(&right) - } - (RuntimeValue::RefCell(left), RuntimeValue::RefCell(right)) => { - let left = left.borrow(); - let right = right.borrow(); - - left.partial_cmp(&*right) - } - (RuntimeValue::RefCell(left), RuntimeValue::Raw(right)) => { - let left = left.borrow(); - - left.partial_cmp(right) - } - (RuntimeValue::RefCell(left), RuntimeValue::Rc(right)) => { - let left = left.borrow(); - - left.partial_cmp(&**right) - } - } - } -} - -impl Display for RuntimeValue { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - Self::Raw(value) => write!(f, "{}", value), - Self::Rc(value) => write!(f, "{}", value), - Self::RefCell(value) => write!(f, "{}", value.borrow()), - } - } -} - #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Pointer { Register(usize), diff --git a/dust-lang/src/vm/mod.rs b/dust-lang/src/vm/mod.rs index 581932b..b330a7a 100644 --- a/dust-lang/src/vm/mod.rs +++ b/dust-lang/src/vm/mod.rs @@ -1,11 +1,11 @@ //! Virtual machine and errors -mod action; +// mod action; mod call_frame; mod thread; use std::{rc::Rc, thread::Builder}; -pub use call_frame::{CallFrame, Pointer, Register, RegisterTable, RuntimeValue}; +pub use call_frame::{CallFrame, Pointer, Register, RegisterTable}; pub use thread::Thread; use crossbeam_channel::bounded; diff --git a/dust-lang/src/vm/thread.rs b/dust-lang/src/vm/thread.rs index 559dd45..28c4660 100644 --- a/dust-lang/src/vm/thread.rs +++ b/dust-lang/src/vm/thread.rs @@ -1,16 +1,14 @@ use std::{rc::Rc, thread::JoinHandle}; -use tracing::{info, trace}; +use tracing::info; use crate::{ - vm::{action::ActionSequence, CallFrame}, - Chunk, DustString, Span, Value, + instruction::TypeCode, vm::CallFrame, Chunk, ConcreteValue, DustString, Operation, Span, Value, }; pub struct Thread { chunk: Rc, call_stack: Vec, - pub return_value: Option, _spawned_threads: Vec>, } @@ -24,7 +22,6 @@ impl Thread { Thread { chunk, call_stack, - return_value: None, _spawned_threads: Vec::new(), } } @@ -38,13 +35,371 @@ impl Thread { .unwrap_or_else(|| DustString::from("anonymous")) ); - let mut actions = ActionSequence::new(self.chunk.instructions.iter().copied()); + while !self.call_stack.is_empty() { + let current_frame = self.current_frame_mut(); + let instructions = ¤t_frame.chunk.instructions; + let ip = { + let current = current_frame.ip; + current_frame.ip += 1; - trace!("Thread actions: {}", actions); + current + }; - actions.run(&mut self); + assert!(ip < instructions.len(), "IP out of bounds"); - self.return_value + let instruction = &instructions[ip]; + + info!("Run instruction {}", instruction.operation()); + + match instruction.operation() { + Operation::LOAD_CONSTANT => { + 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 character = current_frame.get_character_constant(constant_index); + + current_frame + .registers + .characters + .get_mut(destination) + .set(character); + } + TypeCode::FLOAT => { + let float = current_frame.get_float_constant(constant_index); + + current_frame + .registers + .floats + .get_mut(destination) + .set(float); + } + TypeCode::INTEGER => { + let integer = current_frame.get_integer_constant(constant_index); + + current_frame + .registers + .integers + .get_mut(destination) + .set(integer); + } + TypeCode::STRING => { + let string = current_frame.get_string_constant(constant_index).clone(); + + current_frame + .registers + .strings + .get_mut(destination) + .set(string); + } + _ => unreachable!(), + } + + if jump_next { + current_frame.ip += 1; + } + } + Operation::LESS => match (instruction.b_type(), instruction.c_type()) { + (TypeCode::INTEGER, TypeCode::INTEGER) => { + let left = instruction.b_field() as usize; + let left_is_constant = instruction.b_is_constant(); + let right = instruction.c_field() as usize; + let right_is_constant = instruction.c_is_constant(); + let comparator = instruction.d_field(); + + let left_value = if left_is_constant { + current_frame.get_integer_constant(left) + } else { + current_frame.get_integer_from_register(left) + }; + let right_value = if right_is_constant { + current_frame.get_integer_constant(right) + } else { + current_frame.get_integer_from_register(right) + }; + let is_less_than = left_value < right_value; + + if is_less_than == comparator { + current_frame.ip += 1; + } + } + _ => todo!(), + }, + Operation::ADD => match (instruction.b_type(), instruction.c_type()) { + (TypeCode::BYTE, TypeCode::BYTE) => { + let left_index = instruction.b_field() as usize; + let right_index = instruction.c_field() as usize; + let destination_index = instruction.a_field() as usize; + + let left_value = current_frame.get_byte_from_register(left_index); + let right_value = current_frame.get_byte_from_register(right_index); + let sum = left_value + right_value; + + current_frame + .registers + .bytes + .set_to_new_register(destination_index, sum); + } + (TypeCode::CHARACTER, TypeCode::CHARACTER) => { + let left_index = instruction.b_field() as usize; + let left_is_constant = instruction.b_is_constant(); + let right_index = instruction.c_field() as usize; + let right_is_constant = instruction.c_is_constant(); + let destination_index = instruction.a_field() as usize; + + let left_value = if left_is_constant { + current_frame.get_character_constant(left_index) + } else { + current_frame.get_character_from_register(left_index) + }; + let right_value = if right_is_constant { + current_frame.get_character_constant(right_index) + } else { + current_frame.get_character_from_register(right_index) + }; + let concatenated = { + let mut concatenated = DustString::from(String::with_capacity(2)); + + concatenated.push(left_value); + concatenated.push(right_value); + + concatenated + }; + + current_frame + .registers + .strings + .set_to_new_register(destination_index, concatenated); + } + (TypeCode::CHARACTER, TypeCode::STRING) => { + let left_index = instruction.b_field() as usize; + let left_is_constant = instruction.b_is_constant(); + let right_index = instruction.c_field() as usize; + let right_is_constant = instruction.c_is_constant(); + let destination_index = instruction.a_field() as usize; + + let left_value = if left_is_constant { + current_frame.get_character_constant(left_index) + } else { + current_frame.get_character_from_register(left_index) + }; + let right_value = if right_is_constant { + current_frame.get_string_constant(right_index) + } else { + current_frame.get_string_from_register(right_index) + }; + let concatenated = DustString::from(format!("{left_value}{right_value}")); + + current_frame + .registers + .strings + .set_to_new_register(destination_index, concatenated); + } + (TypeCode::FLOAT, TypeCode::FLOAT) => { + let left_index = instruction.b_field() as usize; + let right_index = instruction.c_field() as usize; + let destination_index = instruction.a_field() as usize; + + let left_value = current_frame.get_float_from_register(left_index); + let right_value = current_frame.get_float_from_register(right_index); + let sum = left_value + right_value; + + current_frame + .registers + .floats + .set_to_new_register(destination_index, sum); + } + (TypeCode::INTEGER, TypeCode::INTEGER) => { + let left = instruction.b_field() as usize; + let left_is_constant = instruction.b_is_constant(); + let right = instruction.c_field() as usize; + let right_is_constant = instruction.c_is_constant(); + let destination_index = instruction.a_field() as usize; + + let left_value = if left_is_constant { + current_frame.get_integer_constant(left) + } else { + current_frame.get_integer_from_register(left) + }; + let right_value = if right_is_constant { + current_frame.get_integer_constant(right) + } else { + current_frame.get_integer_from_register(right) + }; + let sum = left_value + right_value; + + current_frame + .registers + .integers + .set_to_new_register(destination_index, sum); + } + (TypeCode::STRING, TypeCode::STRING) => { + let left = instruction.b_field() as usize; + let left_is_constant = instruction.b_is_constant(); + let right = instruction.c_field() as usize; + let right_is_constant = instruction.c_is_constant(); + let destination_index = instruction.a_field() as usize; + + let left_value = if left_is_constant { + current_frame.get_string_constant(left) + } else { + current_frame.get_string_from_register(left) + }; + let right_value = if right_is_constant { + current_frame.get_string_constant(right) + } else { + current_frame.get_string_from_register(right) + }; + let concatenated = DustString::from(format!("{left_value}{right_value}")); + + current_frame + .registers + .strings + .set_to_new_register(destination_index, concatenated); + } + _ => todo!(), + }, + Operation::JUMP => { + let offset = instruction.b_field() as usize; + let is_positive = instruction.c_field() != 0; + + if is_positive { + current_frame.ip += offset; + } else { + current_frame.ip -= offset + 1; + } + } + Operation::RETURN => { + let should_return_value = instruction.b_field() != 0; + let return_register = instruction.c_field() as usize; + let return_type = instruction.b_type(); + + if should_return_value { + match return_type { + TypeCode::BOOLEAN => { + let return_value = + current_frame.get_boolean_from_register(return_register); + + return Some(Value::boolean(return_value)); + } + TypeCode::BYTE => { + let return_value = + current_frame.get_byte_from_register(return_register); + + return Some(Value::byte(return_value)); + } + TypeCode::CHARACTER => { + let return_value = + current_frame.get_character_from_register(return_register); + + return Some(Value::character(return_value)); + } + TypeCode::FLOAT => { + let return_value = + current_frame.get_float_from_register(return_register); + + return Some(Value::float(return_value)); + } + TypeCode::INTEGER => { + let return_value = + current_frame.get_integer_from_register(return_register); + + return Some(Value::integer(return_value)); + } + TypeCode::STRING => { + let return_value = current_frame + .get_string_from_register(return_register) + .clone(); + + return Some(Value::string(return_value)); + } + TypeCode::LIST => { + let abstract_list = + current_frame.get_list_from_register(return_register); + + let mut concrete_list = + Vec::with_capacity(abstract_list.item_pointers.len()); + + match abstract_list.item_type { + TypeCode::BOOLEAN => { + for pointer in &abstract_list.item_pointers { + let boolean = + current_frame.get_boolean_from_pointer(&pointer); + let value = ConcreteValue::Boolean(boolean); + + concrete_list.push(value); + } + } + TypeCode::BYTE => { + for pointer in &abstract_list.item_pointers { + let byte = + current_frame.get_byte_from_pointer(&pointer); + let value = ConcreteValue::Byte(byte); + + concrete_list.push(value); + } + } + TypeCode::CHARACTER => { + for pointer in &abstract_list.item_pointers { + let character = + current_frame.get_character_from_pointer(&pointer); + let value = ConcreteValue::Character(character); + + concrete_list.push(value); + } + } + TypeCode::FLOAT => { + for pointer in &abstract_list.item_pointers { + let float = + current_frame.get_float_from_pointer(&pointer); + let value = ConcreteValue::Float(float); + + concrete_list.push(value); + } + } + TypeCode::INTEGER => { + for pointer in &abstract_list.item_pointers { + let integer = + current_frame.get_integer_from_pointer(&pointer); + let value = ConcreteValue::Integer(integer); + + concrete_list.push(value); + } + } + TypeCode::STRING => { + for pointer in &abstract_list.item_pointers { + let string = current_frame + .get_string_from_pointer(pointer) + .clone(); + let value = ConcreteValue::String(string); + + concrete_list.push(value); + } + } + _ => todo!(), + } + + return Some(Value::Concrete(ConcreteValue::list( + concrete_list, + abstract_list.item_type, + ))); + } + _ => unreachable!(), + } + } else { + return None; + } + } + unimplemented => { + todo!("{unimplemented} has not been implemented in the VM"); + } + } + } + + None } pub fn current_position(&self) -> Span {