diff --git a/bench/addictive_addition/run.sh b/bench/addictive_addition/run.sh index b6509a3..fbe3968 100644 --- a/bench/addictive_addition/run.sh +++ b/bench/addictive_addition/run.sh @@ -3,7 +3,6 @@ hyperfine \ --shell none \ --prepare 'sync' \ --warmup 5 \ - --export-markdown results.md \ '../../target/release/dust addictive_addition.ds' \ 'node addictive_addition.js' \ 'deno addictive_addition.js' \ diff --git a/bench/recursion/recursion.ds b/bench/recursion/recursion.ds index 6383028..257c310 100644 --- a/bench/recursion/recursion.ds +++ b/bench/recursion/recursion.ds @@ -6,4 +6,4 @@ fn decrement(i: int) -> str { decrement(i - 1) } -decrement(1000) +write_line(decrement(10_000)) diff --git a/bench/recursion/recursion.js b/bench/recursion/recursion.js index 964f6c2..f080f1f 100644 --- a/bench/recursion/recursion.js +++ b/bench/recursion/recursion.js @@ -6,4 +6,4 @@ function decrement(i) { return decrement(i - 1); } -decrement(1000); +console.log(decrement(10_000)); diff --git a/dust-lang/src/native_function/assertion.rs b/dust-lang/src/native_function/assertion.rs index c0d4b45..7592eee 100644 --- a/dust-lang/src/native_function/assertion.rs +++ b/dust-lang/src/native_function/assertion.rs @@ -1,15 +1,9 @@ use std::{ops::Range, panic}; -use crate::{ - vm::{Record, ThreadSignal}, - NativeFunctionError, -}; +use crate::vm::ThreadData; -pub fn panic( - record: &mut Record, - _: Option, - argument_range: Range, -) -> Result { +pub fn panic(data: &mut ThreadData, _: Option, argument_range: Range) -> bool { + let record = data.records.last_mut_unchecked(); let position = record.current_position(); let mut message = format!("Dust panic at {position}!"); diff --git a/dust-lang/src/native_function/io.rs b/dust-lang/src/native_function/io.rs index 126cf51..5cc0fe3 100644 --- a/dust-lang/src/native_function/io.rs +++ b/dust-lang/src/native_function/io.rs @@ -1,93 +1,70 @@ -use std::io::{self, stdin, stdout, Write}; +use std::io::{stdin, stdout, Write}; use std::ops::Range; -use crate::vm::{get_next_action, Register, ThreadSignal}; -use crate::{vm::Record, ConcreteValue, NativeFunctionError, Value}; +use crate::{ + vm::{get_next_action, Register, ThreadData}, + ConcreteValue, Value, +}; pub fn read_line( - record: &mut Record, + data: &mut ThreadData, destination: Option, _argument_range: Range, -) -> Result { +) -> bool { + let record = data.records.last_mut_unchecked(); let destination = destination.unwrap(); let mut buffer = String::new(); - match stdin().read_line(&mut buffer) { - Ok(_) => { - let length = buffer.len(); + if stdin().read_line(&mut buffer).is_ok() { + 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); - } - Err(error) => { - return Err(NativeFunctionError::Io { - error: error.kind(), - position: record.current_position(), - }) - } + 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 } -pub fn write( - record: &mut Record, - _destination: Option, - argument_range: Range, -) -> Result { +pub fn write(data: &mut ThreadData, _destination: Option, argument_range: Range) -> bool { + let record = data.records.last_mut_unchecked(); let mut stdout = stdout(); for register_index in argument_range { if let Some(value) = record.open_register_allow_empty_unchecked(register_index) { let string = value.display(record); - - stdout - .write(string.as_bytes()) - .map_err(|io_error| NativeFunctionError::Io { - error: io_error.kind(), - position: record.current_position(), - })?; + let _ = stdout.write(string.as_bytes()); } } - stdout.flush().map_err(|io_error| NativeFunctionError::Io { - error: io_error.kind(), - position: record.current_position(), - })?; + let _ = stdout.flush(); + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - Ok(ThreadSignal::Continue(next_action)) + false } pub fn write_line( - record: &mut Record, + data: &mut ThreadData, _destination: Option, argument_range: Range, -) -> Result { - let map_err = |io_error: io::Error| NativeFunctionError::Io { - error: io_error.kind(), - position: record.current_position(), - }; +) -> bool { + let record = data.records.last_mut_unchecked(); let mut stdout = stdout().lock(); for register_index in argument_range { if let Some(value) = record.open_register_allow_empty_unchecked(register_index) { let string = value.display(record); - - stdout.write(string.as_bytes()).map_err(map_err)?; - stdout.write(b"\n").map_err(map_err)?; + let _ = stdout.write(string.as_bytes()); + let _ = stdout.write(b"\n"); } } - stdout.flush().map_err(map_err)?; + let _ = stdout.flush(); + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - Ok(ThreadSignal::Continue(next_action)) + false } diff --git a/dust-lang/src/native_function/mod.rs b/dust-lang/src/native_function/mod.rs index 1fd5ed4..c7b6c29 100644 --- a/dust-lang/src/native_function/mod.rs +++ b/dust-lang/src/native_function/mod.rs @@ -16,10 +16,7 @@ use std::{ use serde::{Deserialize, Serialize}; use smallvec::{smallvec, SmallVec}; -use crate::{ - vm::{Record, ThreadSignal}, - AnnotatedError, FunctionType, Span, Type, -}; +use crate::{vm::ThreadData, AnnotatedError, FunctionType, Span, Type}; macro_rules! define_native_function { ($(($name:ident, $bytes:literal, $str:expr, $type:expr, $function:expr)),*) => { @@ -36,13 +33,13 @@ macro_rules! define_native_function { impl NativeFunction { pub fn call( &self, - record: &mut Record, + data: &mut ThreadData, destination: Option, argument_range: Range, - ) -> Result { + ) -> bool { match self { $( - NativeFunction::$name => $function(record, destination, argument_range), + NativeFunction::$name => $function(data, destination, argument_range), )* } } diff --git a/dust-lang/src/native_function/string.rs b/dust-lang/src/native_function/string.rs index 38f2b70..525761e 100644 --- a/dust-lang/src/native_function/string.rs +++ b/dust-lang/src/native_function/string.rs @@ -1,15 +1,16 @@ use std::ops::Range; use crate::{ - vm::{get_next_action, Record, Register, ThreadSignal}, - ConcreteValue, NativeFunctionError, Value, + vm::{get_next_action, Register, ThreadData}, + ConcreteValue, Value, }; pub fn to_string( - record: &mut Record, + data: &mut ThreadData, destination: Option, argument_range: Range, -) -> Result { +) -> bool { + let record = data.records.last_mut_unchecked(); let argument_value = record.open_register_unchecked(argument_range.start); let argument_string = argument_value.display(record); let destination = destination.unwrap(); @@ -17,7 +18,7 @@ pub fn to_string( 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 } diff --git a/dust-lang/src/vm/mod.rs b/dust-lang/src/vm/mod.rs index e32ff1d..f39ad72 100644 --- a/dust-lang/src/vm/mod.rs +++ b/dust-lang/src/vm/mod.rs @@ -16,7 +16,7 @@ pub use record::Record; pub(crate) use run_action::get_next_action; pub use run_action::RunAction; pub use stack::{FunctionCall, Stack}; -pub use thread::{Thread, ThreadSignal}; +pub use thread::{Thread, ThreadData}; use tracing::{span, Level}; diff --git a/dust-lang/src/vm/run_action.rs b/dust-lang/src/vm/run_action.rs index 29eca8b..f636133 100644 --- a/dust-lang/src/vm/run_action.rs +++ b/dust-lang/src/vm/run_action.rs @@ -10,7 +10,7 @@ use crate::{ 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)] pub struct RunAction { @@ -27,7 +27,7 @@ impl From 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] = [ point, @@ -57,15 +57,17 @@ pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 25] = [ 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 operation = instruction.operation(); let logic = RUNNER_LOGIC_TABLE[operation.0 as usize]; + record.ip += 1; + 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 Point { from, to } = instruction.into(); 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.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 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.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 LoadBoolean { destination, @@ -115,14 +113,12 @@ pub fn load_boolean(instruction: Instruction, data: &mut ThreadData) -> ThreadSi record.ip += 1; } - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 LoadConstant { destination, @@ -139,14 +135,12 @@ pub fn load_constant(instruction: Instruction, data: &mut ThreadData) -> ThreadS record.ip += 1; } - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 LoadList { destination, @@ -183,14 +177,12 @@ pub fn load_list(instruction: Instruction, data: &mut ThreadData) -> ThreadSigna record.set_register(destination, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 LoadFunction { destination, @@ -202,14 +194,12 @@ pub fn load_function(instruction: Instruction, data: &mut ThreadData) -> ThreadS record.set_register(destination, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 LoadSelf { destination } = instruction.into(); 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.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 GetLocal { destination, @@ -235,14 +223,12 @@ pub fn get_local(instruction: Instruction, data: &mut ThreadData) -> ThreadSigna record.set_register(destination, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 SetLocal { register_index, @@ -253,14 +239,12 @@ pub fn set_local(instruction: Instruction, data: &mut ThreadData) -> ThreadSigna record.set_register(local_register_index, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Add { destination, @@ -274,14 +258,12 @@ pub fn add(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { record.set_register(destination, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Subtract { destination, @@ -295,14 +277,12 @@ pub fn subtract(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal record.set_register(destination, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Multiply { destination, @@ -324,14 +304,12 @@ pub fn multiply(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal record.set_register(destination, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Divide { destination, @@ -353,14 +331,12 @@ pub fn divide(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { record.set_register(destination, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Modulo { destination, @@ -382,14 +358,12 @@ pub fn modulo(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { record.set_register(destination, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Test { operand_register, @@ -406,14 +380,12 @@ pub fn test(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { record.ip += 1; } - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 TestSet { destination, @@ -428,7 +400,6 @@ pub fn test_set(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal }; if boolean == test_value { - record.ip += 1; } else { let pointer = match argument { 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.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Equal { value, left, right } = instruction.into(); 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; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Less { value, left, right } = instruction.into(); 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; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 LessEqual { value, left, right } = instruction.into(); 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; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Negate { destination, @@ -512,14 +475,12 @@ pub fn negate(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { record.set_register(destination, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Not { destination, @@ -534,14 +495,12 @@ pub fn not(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { record.set_register(destination, register); - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -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 Jump { offset, @@ -555,22 +514,19 @@ pub fn jump(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { record.ip -= offset + 1; } - record.ip += 1; + data.next_action = get_next_action(record); - let next_action = get_next_action(record); - - ThreadSignal::Continue(next_action) + false } -pub fn call(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { - let mut current_record = data.records.pop_unchecked(); +pub fn call(instruction: Instruction, data: &mut ThreadData) -> bool { + let current_record = data.records.pop_unchecked(); let Call { destination: return_register, function_register, argument_count, is_recursive, } = instruction.into(); - let function = current_record .open_register_unchecked(function_register) .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)); } - let next_action = get_next_action(&next_record); - - current_record.ip += 1; + data.next_action = get_next_action(&mut next_record); data.call_stack.push(next_call); data.records.push(current_record); data.records.push(next_record); - ThreadSignal::Continue(next_action) + false } -pub fn call_native(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal { - let record = data.records.last_mut_unchecked(); +pub fn call_native(instruction: Instruction, data: &mut ThreadData) -> bool { let CallNative { destination, function, @@ -623,18 +576,10 @@ pub fn call_native(instruction: Instruction, data: &mut ThreadData) -> ThreadSig let first_argument_index = destination - argument_count; let argument_range = first_argument_index..destination; - function - .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) + function.call(data, Some(destination), argument_range) } -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); let Return { @@ -642,29 +587,29 @@ pub fn r#return(instruction: Instruction, data: &mut ThreadData) -> ThreadSignal return_register, } = instruction.into(); 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 { - Some(current_record.empty_register_or_clone_constant_unchecked(return_register)) + return true; } else { - None + data.records.pop_unchecked() }; + let outer_record = data.records.last_mut_unchecked(); 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 { - 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)] diff --git a/dust-lang/src/vm/thread.rs b/dust-lang/src/vm/thread.rs index 66c1e75..3adaaa2 100644 --- a/dust-lang/src/vm/thread.rs +++ b/dust-lang/src/vm/thread.rs @@ -1,6 +1,4 @@ -use std::fmt::{self, Display, Formatter}; - -use tracing::info; +use tracing::{info, trace}; use crate::{vm::FunctionCall, Chunk, DustString, Value}; @@ -16,15 +14,6 @@ impl Thread { } pub fn run(&mut self) -> Option { - 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!( "Starting thread with {}", self.chunk @@ -33,28 +22,47 @@ impl Thread { .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); records.push(main_record); + let first_action = RunAction::from(*self.chunk.instructions.first().unwrap()); let mut thread_data = ThreadData { call_stack, records, + next_action: first_action, + return_value_index: None, }; - let mut next_action = RunAction::from(*self.chunk.instructions.first().unwrap()); - loop { - let signal = (next_action.logic)(next_action.instruction, &mut thread_data); + trace!("Instruction: {}", thread_data.next_action.instruction); - match signal { - ThreadSignal::Continue(action) => { - next_action = action; - } - ThreadSignal::End(value_option) => { - info!("Thread ended"); + let should_end = (thread_data.next_action.logic)( + thread_data.next_action.instruction, + &mut thread_data, + ); - 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 call_stack: Stack, pub records: Stack>, -} - -#[derive(Debug)] -pub enum ThreadSignal { - Continue(RunAction), - End(Option), -} - -impl Display for ThreadSignal { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } + pub next_action: RunAction, + pub return_value_index: Option, }