Continue VM improvements
This commit is contained in:
parent
c03ec528b7
commit
f667716336
@ -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' \
|
||||||
|
@ -6,4 +6,4 @@ fn decrement(i: int) -> str {
|
|||||||
decrement(i - 1)
|
decrement(i - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
decrement(1000)
|
write_line(decrement(10_000))
|
||||||
|
@ -6,4 +6,4 @@ function decrement(i) {
|
|||||||
return decrement(i - 1);
|
return decrement(i - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
decrement(1000);
|
console.log(decrement(10_000));
|
||||||
|
@ -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}!");
|
||||||
|
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
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));
|
||||||
@ -22,72 +24,47 @@ pub fn read_line(
|
|||||||
|
|
||||||
record.set_register(destination, register);
|
record.set_register(destination, register);
|
||||||
}
|
}
|
||||||
Err(error) => {
|
|
||||||
return Err(NativeFunctionError::Io {
|
data.next_action = get_next_action(record);
|
||||||
error: error.kind(),
|
|
||||||
position: record.current_position(),
|
false
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let next_action = get_next_action(record);
|
pub fn write(data: &mut ThreadData, _destination: Option<u8>, argument_range: Range<u8>) -> bool {
|
||||||
|
let record = data.records.last_mut_unchecked();
|
||||||
Ok(ThreadSignal::Continue(next_action))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(
|
|
||||||
record: &mut Record,
|
|
||||||
_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))
|
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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};
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
let return_value = if should_return_value {
|
data.return_value_index = Some(return_register);
|
||||||
Some(current_record.empty_register_or_clone_constant_unchecked(return_register))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let destination = current_call.return_register;
|
return true;
|
||||||
|
} else {
|
||||||
if data.call_stack.is_empty() {
|
data.records.pop_unchecked()
|
||||||
return ThreadSignal::End(return_value);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
let outer_record = data.records.last_mut_unchecked();
|
let outer_record = data.records.last_mut_unchecked();
|
||||||
|
let destination = current_call.return_register;
|
||||||
|
|
||||||
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)]
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user