1
0

Replace complex actions with a simple loop

This commit is contained in:
Jeff 2025-02-17 08:01:10 -05:00
parent 0292a01162
commit 5de44b58ee
7 changed files with 555 additions and 505 deletions

View File

@ -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<usize>) {
let current_frame = data.current_frame();
@ -8,20 +8,9 @@ pub fn panic(data: &mut Thread, _: usize, argument_range: Range<usize>) {
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');
}

View File

@ -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<usize>) {
@ -13,53 +13,34 @@ pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range<u
buffer.truncate(length.saturating_sub(1));
let string = RuntimeValue::Raw(DustString::from(buffer));
let string = DustString::from(buffer);
current_frame.registers.strings[destination].set(string);
current_frame
.registers
.strings
.set_to_new_register(destination, string);
}
}
pub fn write(data: &mut Thread, _: usize, argument_range: Range<usize>) {
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<usize>) {
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");

View File

@ -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<usize>) {
let current_frame = data.current_frame_mut();
@ -14,9 +14,7 @@ pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range<u
let register_index = argument_range_iter
.next()
.unwrap_or_else(|| panic!("No argument was passed to \"random_int\""));
let integer = current_frame
.get_integer_from_register(register_index)
.clone_inner();
let integer = current_frame.get_integer_from_register(register_index);
if min.is_none() {
min = Some(integer);
@ -31,6 +29,5 @@ pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range<u
current_frame
.registers
.integers
.get_mut(destination)
.set(RuntimeValue::Raw(random_integer));
.set_to_new_register(destination, random_integer);
}

View File

@ -507,117 +507,117 @@ fn r#return(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &m
let return_type = instruction.b_type();
let current_frame = thread.current_frame();
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());
// 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!(),
// }
// }
}

View File

@ -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<bool> {
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<bool> {
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<u8> {
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<u8> {
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<char> {
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<char> {
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<char> {
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<f64> {
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<f64> {
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<f64> {
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<i64> {
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<i64> {
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<i64> {
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<i64> {
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<i64> {
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<i64> {
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<DustString> {
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<DustString> {
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<DustString> {
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<DustString> {
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<AbstractList> {
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<AbstractList> {
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<AbstractList> {
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<Function> {
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<Function> {
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<Function> {
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<RuntimeValue<char>>,
pub floats: Vec<RuntimeValue<f64>>,
pub integers: Vec<RuntimeValue<i64>>,
pub strings: Vec<RuntimeValue<DustString>>,
}
#[derive(Debug)]
pub struct RegisterTable {
pub booleans: RegisterList<bool>,
@ -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<T> IndexMut<usize> for RegisterList<T> {
#[derive(Clone, Debug)]
pub enum Register<T> {
Value {
value: RuntimeValue<T>,
is_closed: bool,
},
Pointer {
pointer: Pointer,
is_closed: bool,
},
Value { value: T, is_closed: bool },
Pointer { pointer: Pointer, is_closed: bool },
}
impl<T> Register<T> {
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<T> Register<T> {
}
}
pub fn set(&mut self, new_value: RuntimeValue<T>) {
pub fn set(&mut self, new_value: T) {
match self {
Self::Value {
value: old_value, ..
@ -434,14 +367,14 @@ impl<T> Register<T> {
}
}
pub fn as_value(&self) -> &RuntimeValue<T> {
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<T> {
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<T> Register<T> {
impl<T: Default> Default for Register<T> {
fn default() -> Self {
Self::Value {
value: RuntimeValue::Raw(Default::default()),
value: Default::default(),
is_closed: false,
}
}
}
#[derive(Clone, Debug)]
pub enum RuntimeValue<T> {
Raw(T),
Rc(Rc<T>),
RefCell(Rc<RefCell<T>>),
}
impl<T: Clone> RuntimeValue<T> {
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<T> {
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<u8> {
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<f64> {
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<i64> {
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<T: PartialEq> PartialEq for RuntimeValue<T> {
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<T: PartialOrd> PartialOrd for RuntimeValue<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
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<T: Display> Display for RuntimeValue<T> {
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),

View File

@ -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;

View File

@ -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<Chunk>,
call_stack: Vec<CallFrame>,
pub return_value: Option<Value>,
_spawned_threads: Vec<JoinHandle<()>>,
}
@ -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 = &current_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 {