1
0

Continue VM improvements

This commit is contained in:
Jeff 2025-01-08 23:02:08 -05:00
parent c03ec528b7
commit f667716336
10 changed files with 170 additions and 259 deletions

View File

@ -3,7 +3,6 @@ hyperfine \
--shell none \ --shell none \
--prepare 'sync' \ --prepare 'sync' \
--warmup 5 \ --warmup 5 \
--export-markdown results.md \
'../../target/release/dust addictive_addition.ds' \ '../../target/release/dust addictive_addition.ds' \
'node addictive_addition.js' \ 'node addictive_addition.js' \
'deno addictive_addition.js' \ 'deno addictive_addition.js' \

View File

@ -6,4 +6,4 @@ fn decrement(i: int) -> str {
decrement(i - 1) decrement(i - 1)
} }
decrement(1000) write_line(decrement(10_000))

View File

@ -6,4 +6,4 @@ function decrement(i) {
return decrement(i - 1); return decrement(i - 1);
} }
decrement(1000); console.log(decrement(10_000));

View File

@ -1,15 +1,9 @@
use std::{ops::Range, panic}; use std::{ops::Range, panic};
use crate::{ use crate::vm::ThreadData;
vm::{Record, ThreadSignal},
NativeFunctionError,
};
pub fn panic( pub fn panic(data: &mut ThreadData, _: Option<u8>, argument_range: Range<u8>) -> bool {
record: &mut Record, let record = data.records.last_mut_unchecked();
_: Option<u8>,
argument_range: Range<u8>,
) -> Result<ThreadSignal, NativeFunctionError> {
let position = record.current_position(); let position = record.current_position();
let mut message = format!("Dust panic at {position}!"); let mut message = format!("Dust panic at {position}!");

View File

@ -1,93 +1,70 @@
use std::io::{self, stdin, stdout, Write}; use std::io::{stdin, stdout, Write};
use std::ops::Range; use std::ops::Range;
use crate::vm::{get_next_action, Register, ThreadSignal}; use crate::{
use crate::{vm::Record, ConcreteValue, NativeFunctionError, Value}; vm::{get_next_action, Register, ThreadData},
ConcreteValue, Value,
};
pub fn read_line( pub fn read_line(
record: &mut Record, data: &mut ThreadData,
destination: Option<u8>, destination: Option<u8>,
_argument_range: Range<u8>, _argument_range: Range<u8>,
) -> Result<ThreadSignal, NativeFunctionError> { ) -> bool {
let record = data.records.last_mut_unchecked();
let destination = destination.unwrap(); let destination = destination.unwrap();
let mut buffer = String::new(); let mut buffer = String::new();
match stdin().read_line(&mut buffer) { if stdin().read_line(&mut buffer).is_ok() {
Ok(_) => { let length = buffer.len();
let length = buffer.len();
buffer.truncate(length.saturating_sub(1)); buffer.truncate(length.saturating_sub(1));
let register = Register::Value(Value::Concrete(ConcreteValue::string(buffer))); let register = Register::Value(Value::Concrete(ConcreteValue::string(buffer)));
record.set_register(destination, register); record.set_register(destination, register);
}
Err(error) => {
return Err(NativeFunctionError::Io {
error: error.kind(),
position: record.current_position(),
})
}
} }
let next_action = get_next_action(record); data.next_action = get_next_action(record);
Ok(ThreadSignal::Continue(next_action)) false
} }
pub fn write( pub fn write(data: &mut ThreadData, _destination: Option<u8>, argument_range: Range<u8>) -> bool {
record: &mut Record, let record = data.records.last_mut_unchecked();
_destination: Option<u8>,
argument_range: Range<u8>,
) -> Result<ThreadSignal, NativeFunctionError> {
let mut stdout = stdout(); let mut stdout = stdout();
for register_index in argument_range { for register_index in argument_range {
if let Some(value) = record.open_register_allow_empty_unchecked(register_index) { if let Some(value) = record.open_register_allow_empty_unchecked(register_index) {
let string = value.display(record); let string = value.display(record);
let _ = stdout.write(string.as_bytes());
stdout
.write(string.as_bytes())
.map_err(|io_error| NativeFunctionError::Io {
error: io_error.kind(),
position: record.current_position(),
})?;
} }
} }
stdout.flush().map_err(|io_error| NativeFunctionError::Io { let _ = stdout.flush();
error: io_error.kind(), data.next_action = get_next_action(record);
position: record.current_position(),
})?;
let next_action = get_next_action(record); false
Ok(ThreadSignal::Continue(next_action))
} }
pub fn write_line( pub fn write_line(
record: &mut Record, data: &mut ThreadData,
_destination: Option<u8>, _destination: Option<u8>,
argument_range: Range<u8>, argument_range: Range<u8>,
) -> Result<ThreadSignal, NativeFunctionError> { ) -> bool {
let map_err = |io_error: io::Error| NativeFunctionError::Io { let record = data.records.last_mut_unchecked();
error: io_error.kind(),
position: record.current_position(),
};
let mut stdout = stdout().lock(); let mut stdout = stdout().lock();
for register_index in argument_range { for register_index in argument_range {
if let Some(value) = record.open_register_allow_empty_unchecked(register_index) { if let Some(value) = record.open_register_allow_empty_unchecked(register_index) {
let string = value.display(record); let string = value.display(record);
let _ = stdout.write(string.as_bytes());
stdout.write(string.as_bytes()).map_err(map_err)?; let _ = stdout.write(b"\n");
stdout.write(b"\n").map_err(map_err)?;
} }
} }
stdout.flush().map_err(map_err)?; let _ = stdout.flush();
data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
Ok(ThreadSignal::Continue(next_action))
} }

View File

@ -16,10 +16,7 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use crate::{ use crate::{vm::ThreadData, AnnotatedError, FunctionType, Span, Type};
vm::{Record, ThreadSignal},
AnnotatedError, FunctionType, Span, Type,
};
macro_rules! define_native_function { macro_rules! define_native_function {
($(($name:ident, $bytes:literal, $str:expr, $type:expr, $function:expr)),*) => { ($(($name:ident, $bytes:literal, $str:expr, $type:expr, $function:expr)),*) => {
@ -36,13 +33,13 @@ macro_rules! define_native_function {
impl NativeFunction { impl NativeFunction {
pub fn call( pub fn call(
&self, &self,
record: &mut Record, data: &mut ThreadData,
destination: Option<u8>, destination: Option<u8>,
argument_range: Range<u8>, argument_range: Range<u8>,
) -> Result<ThreadSignal, NativeFunctionError> { ) -> bool {
match self { match self {
$( $(
NativeFunction::$name => $function(record, destination, argument_range), NativeFunction::$name => $function(data, destination, argument_range),
)* )*
} }
} }

View File

@ -1,15 +1,16 @@
use std::ops::Range; use std::ops::Range;
use crate::{ use crate::{
vm::{get_next_action, Record, Register, ThreadSignal}, vm::{get_next_action, Register, ThreadData},
ConcreteValue, NativeFunctionError, Value, ConcreteValue, Value,
}; };
pub fn to_string( pub fn to_string(
record: &mut Record, data: &mut ThreadData,
destination: Option<u8>, destination: Option<u8>,
argument_range: Range<u8>, argument_range: Range<u8>,
) -> Result<ThreadSignal, NativeFunctionError> { ) -> bool {
let record = data.records.last_mut_unchecked();
let argument_value = record.open_register_unchecked(argument_range.start); let argument_value = record.open_register_unchecked(argument_range.start);
let argument_string = argument_value.display(record); let argument_string = argument_value.display(record);
let destination = destination.unwrap(); let destination = destination.unwrap();
@ -17,7 +18,7 @@ pub fn to_string(
record.set_register(destination, register); record.set_register(destination, register);
let next_action = get_next_action(record); data.next_action = get_next_action(record);
Ok(ThreadSignal::Continue(next_action)) false
} }

View File

@ -16,7 +16,7 @@ pub use record::Record;
pub(crate) use run_action::get_next_action; pub(crate) use run_action::get_next_action;
pub use run_action::RunAction; pub use run_action::RunAction;
pub use stack::{FunctionCall, Stack}; pub use stack::{FunctionCall, Stack};
pub use thread::{Thread, ThreadSignal}; pub use thread::{Thread, ThreadData};
use tracing::{span, Level}; use tracing::{span, Level};

View File

@ -10,7 +10,7 @@ use crate::{
AbstractList, Argument, ConcreteValue, DustString, Instruction, Type, Value, AbstractList, Argument, ConcreteValue, DustString, Instruction, Type, Value,
}; };
use super::{thread::ThreadData, Pointer, Record, Register, ThreadSignal}; use super::{thread::ThreadData, Pointer, Record, Register};
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub struct RunAction { pub struct RunAction {
@ -27,7 +27,7 @@ impl From<Instruction> for RunAction {
} }
} }
pub type RunnerLogic = fn(Instruction, &mut ThreadData) -> ThreadSignal; pub type RunnerLogic = fn(Instruction, &mut ThreadData) -> bool;
pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 25] = [ pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 25] = [
point, point,
@ -57,15 +57,17 @@ pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 25] = [
r#return, r#return,
]; ];
pub(crate) fn get_next_action(record: &Record) -> RunAction { pub(crate) fn get_next_action(record: &mut Record) -> RunAction {
let instruction = record.chunk.instructions[record.ip]; let instruction = record.chunk.instructions[record.ip];
let operation = instruction.operation(); let operation = instruction.operation();
let logic = RUNNER_LOGIC_TABLE[operation.0 as usize]; let logic = RUNNER_LOGIC_TABLE[operation.0 as usize];
record.ip += 1;
RunAction { logic, instruction } RunAction { logic, instruction }
} }
pub fn point(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn point(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Point { from, to } = instruction.into(); let Point { from, to } = instruction.into();
let from_register = record.get_register_unchecked(from); let from_register = record.get_register_unchecked(from);
@ -77,14 +79,12 @@ pub fn point(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.set_register(from, register); record.set_register(from, register);
} }
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn close(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn close(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Close { from, to } = instruction.into(); let Close { from, to } = instruction.into();
@ -92,14 +92,12 @@ pub fn close(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.set_register(register_index, Register::Empty); record.set_register(register_index, Register::Empty);
} }
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn load_boolean(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn load_boolean(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let LoadBoolean { let LoadBoolean {
destination, destination,
@ -115,14 +113,12 @@ pub fn load_boolean(instruction: Instruction, data: &mut ThreadData) -> ThreadSi
record.ip += 1; record.ip += 1;
} }
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn load_constant(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn load_constant(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let LoadConstant { let LoadConstant {
destination, destination,
@ -139,14 +135,12 @@ pub fn load_constant(instruction: Instruction, data: &mut ThreadData) -> ThreadS
record.ip += 1; record.ip += 1;
} }
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn load_list(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn load_list(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let LoadList { let LoadList {
destination, destination,
@ -183,14 +177,12 @@ pub fn load_list(instruction: Instruction, data: &mut ThreadData) -> ThreadSigna
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn load_function(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn load_function(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let LoadFunction { let LoadFunction {
destination, destination,
@ -202,14 +194,12 @@ pub fn load_function(instruction: Instruction, data: &mut ThreadData) -> ThreadS
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn load_self(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn load_self(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let LoadSelf { destination } = instruction.into(); let LoadSelf { destination } = instruction.into();
let function = record.as_function(); let function = record.as_function();
@ -217,14 +207,12 @@ pub fn load_self(instruction: Instruction, data: &mut ThreadData) -> ThreadSigna
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn get_local(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn get_local(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let GetLocal { let GetLocal {
destination, destination,
@ -235,14 +223,12 @@ pub fn get_local(instruction: Instruction, data: &mut ThreadData) -> ThreadSigna
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn set_local(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn set_local(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let SetLocal { let SetLocal {
register_index, register_index,
@ -253,14 +239,12 @@ pub fn set_local(instruction: Instruction, data: &mut ThreadData) -> ThreadSigna
record.set_register(local_register_index, register); record.set_register(local_register_index, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn add(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn add(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Add { let Add {
destination, destination,
@ -274,14 +258,12 @@ pub fn add(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn subtract(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn subtract(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Subtract { let Subtract {
destination, destination,
@ -295,14 +277,12 @@ pub fn subtract(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn multiply(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn multiply(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Multiply { let Multiply {
destination, destination,
@ -324,14 +304,12 @@ pub fn multiply(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn divide(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn divide(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Divide { let Divide {
destination, destination,
@ -353,14 +331,12 @@ pub fn divide(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn modulo(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn modulo(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Modulo { let Modulo {
destination, destination,
@ -382,14 +358,12 @@ pub fn modulo(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn test(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn test(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Test { let Test {
operand_register, operand_register,
@ -406,14 +380,12 @@ pub fn test(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.ip += 1; record.ip += 1;
} }
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn test_set(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn test_set(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let TestSet { let TestSet {
destination, destination,
@ -428,7 +400,6 @@ pub fn test_set(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal
}; };
if boolean == test_value { if boolean == test_value {
record.ip += 1;
} else { } else {
let pointer = match argument { let pointer = match argument {
Argument::Constant(constant_index) => Pointer::Constant(constant_index), Argument::Constant(constant_index) => Pointer::Constant(constant_index),
@ -439,14 +410,12 @@ pub fn test_set(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal
record.set_register(destination, register); record.set_register(destination, register);
} }
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn equal(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn equal(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Equal { value, left, right } = instruction.into(); let Equal { value, left, right } = instruction.into();
let left = record.get_argument_unchecked(left); let left = record.get_argument_unchecked(left);
@ -457,14 +426,12 @@ pub fn equal(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.ip += 1; record.ip += 1;
} }
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn less(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn less(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Less { value, left, right } = instruction.into(); let Less { value, left, right } = instruction.into();
let left = record.get_argument_unchecked(left); let left = record.get_argument_unchecked(left);
@ -475,14 +442,12 @@ pub fn less(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.ip += 1; record.ip += 1;
} }
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn less_equal(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn less_equal(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let LessEqual { value, left, right } = instruction.into(); let LessEqual { value, left, right } = instruction.into();
let left = record.get_argument_unchecked(left); let left = record.get_argument_unchecked(left);
@ -493,14 +458,12 @@ pub fn less_equal(instruction: Instruction, data: &mut ThreadData) -> ThreadSign
record.ip += 1; record.ip += 1;
} }
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn negate(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn negate(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Negate { let Negate {
destination, destination,
@ -512,14 +475,12 @@ pub fn negate(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn not(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn not(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Not { let Not {
destination, destination,
@ -534,14 +495,12 @@ pub fn not(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.set_register(destination, register); record.set_register(destination, register);
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn jump(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn jump(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked(); let record = data.records.last_mut_unchecked();
let Jump { let Jump {
offset, offset,
@ -555,22 +514,19 @@ pub fn jump(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
record.ip -= offset + 1; record.ip -= offset + 1;
} }
record.ip += 1; data.next_action = get_next_action(record);
let next_action = get_next_action(record); false
ThreadSignal::Continue(next_action)
} }
pub fn call(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn call(instruction: Instruction, data: &mut ThreadData) -> bool {
let mut current_record = data.records.pop_unchecked(); let current_record = data.records.pop_unchecked();
let Call { let Call {
destination: return_register, destination: return_register,
function_register, function_register,
argument_count, argument_count,
is_recursive, is_recursive,
} = instruction.into(); } = instruction.into();
let function = current_record let function = current_record
.open_register_unchecked(function_register) .open_register_unchecked(function_register)
.as_function() .as_function()
@ -602,19 +558,16 @@ pub fn call(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal {
next_record.set_register(argument_index as u8, Register::Value(argument)); next_record.set_register(argument_index as u8, Register::Value(argument));
} }
let next_action = get_next_action(&next_record); data.next_action = get_next_action(&mut next_record);
current_record.ip += 1;
data.call_stack.push(next_call); data.call_stack.push(next_call);
data.records.push(current_record); data.records.push(current_record);
data.records.push(next_record); data.records.push(next_record);
ThreadSignal::Continue(next_action) false
} }
pub fn call_native(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn call_native(instruction: Instruction, data: &mut ThreadData) -> bool {
let record = data.records.last_mut_unchecked();
let CallNative { let CallNative {
destination, destination,
function, function,
@ -623,18 +576,10 @@ pub fn call_native(instruction: Instruction, data: &mut ThreadData) -> ThreadSig
let first_argument_index = destination - argument_count; let first_argument_index = destination - argument_count;
let argument_range = first_argument_index..destination; let argument_range = first_argument_index..destination;
function function.call(data, Some(destination), argument_range)
.call(record, Some(destination), argument_range)
.unwrap_or_else(|error| panic!("{error:?}"));
record.ip += 1;
let next_action = get_next_action(record);
ThreadSignal::Continue(next_action)
} }
pub fn r#return(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { pub fn r#return(instruction: Instruction, data: &mut ThreadData) -> bool {
trace!("Returning with call stack:\n{}", data.call_stack); trace!("Returning with call stack:\n{}", data.call_stack);
let Return { let Return {
@ -642,29 +587,29 @@ pub fn r#return(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal
return_register, return_register,
} = instruction.into(); } = instruction.into();
let current_call = data.call_stack.pop_unchecked(); let current_call = data.call_stack.pop_unchecked();
let mut current_record = data.records.pop_unchecked(); let mut current_record = if data.call_stack.is_empty() {
if should_return_value {
data.return_value_index = Some(return_register);
};
let return_value = if should_return_value { return true;
Some(current_record.empty_register_or_clone_constant_unchecked(return_register))
} else { } else {
None data.records.pop_unchecked()
}; };
let outer_record = data.records.last_mut_unchecked();
let destination = current_call.return_register; let destination = current_call.return_register;
if data.call_stack.is_empty() {
return ThreadSignal::End(return_value);
}
let outer_record = data.records.last_mut_unchecked();
if should_return_value { if should_return_value {
outer_record.set_register(destination, Register::Value(return_value.unwrap())); let return_value =
current_record.empty_register_or_clone_constant_unchecked(return_register);
outer_record.set_register(destination, Register::Value(return_value));
} }
let next_action = get_next_action(outer_record); data.next_action = get_next_action(outer_record);
ThreadSignal::Continue(next_action) false
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,6 +1,4 @@
use std::fmt::{self, Display, Formatter}; use tracing::{info, trace};
use tracing::info;
use crate::{vm::FunctionCall, Chunk, DustString, Value}; use crate::{vm::FunctionCall, Chunk, DustString, Value};
@ -16,15 +14,6 @@ impl Thread {
} }
pub fn run(&mut self) -> Option<Value> { pub fn run(&mut self) -> Option<Value> {
let mut call_stack = Stack::with_capacity(self.chunk.prototypes.len() + 1);
let mut records = Stack::with_capacity(self.chunk.prototypes.len() + 1);
let main_call = FunctionCall {
name: self.chunk.name.clone(),
return_register: 0,
ip: 0,
};
let main_record = Record::new(&self.chunk);
info!( info!(
"Starting thread with {}", "Starting thread with {}",
self.chunk self.chunk
@ -33,28 +22,47 @@ impl Thread {
.unwrap_or_else(|| DustString::from("anonymous")) .unwrap_or_else(|| DustString::from("anonymous"))
); );
let mut call_stack = Stack::with_capacity(self.chunk.prototypes.len() + 1);
let mut records = Stack::with_capacity(self.chunk.prototypes.len() + 1);
let main_call = FunctionCall {
name: self.chunk.name.clone(),
return_register: 0, // Never used, the main function's return is the thread's return
ip: 0,
};
let main_record = Record::new(&self.chunk);
call_stack.push(main_call); call_stack.push(main_call);
records.push(main_record); records.push(main_record);
let first_action = RunAction::from(*self.chunk.instructions.first().unwrap());
let mut thread_data = ThreadData { let mut thread_data = ThreadData {
call_stack, call_stack,
records, records,
next_action: first_action,
return_value_index: None,
}; };
let mut next_action = RunAction::from(*self.chunk.instructions.first().unwrap());
loop { loop {
let signal = (next_action.logic)(next_action.instruction, &mut thread_data); trace!("Instruction: {}", thread_data.next_action.instruction);
match signal { let should_end = (thread_data.next_action.logic)(
ThreadSignal::Continue(action) => { thread_data.next_action.instruction,
next_action = action; &mut thread_data,
} );
ThreadSignal::End(value_option) => {
info!("Thread ended");
return value_option; if should_end {
} let return_value = if let Some(register_index) = thread_data.return_value_index {
let value = thread_data
.records
.last_mut_unchecked()
.empty_register_or_clone_constant_unchecked(register_index);
Some(value)
} else {
None
};
return return_value;
} }
} }
} }
@ -64,16 +72,6 @@ impl Thread {
pub struct ThreadData<'a> { pub struct ThreadData<'a> {
pub call_stack: Stack<FunctionCall>, pub call_stack: Stack<FunctionCall>,
pub records: Stack<Record<'a>>, pub records: Stack<Record<'a>>,
} pub next_action: RunAction,
pub return_value_index: Option<u8>,
#[derive(Debug)]
pub enum ThreadSignal {
Continue(RunAction),
End(Option<Value>),
}
impl Display for ThreadSignal {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
} }