Attempt alternative to total register overhaul
This commit is contained in:
parent
3fcbde59e5
commit
c1fe54ccd5
@ -56,14 +56,11 @@ impl Display for Add {
|
|||||||
let Add {
|
let Add {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
left_type,
|
left_type: _,
|
||||||
right,
|
right,
|
||||||
right_type,
|
right_type: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
write!(
|
write!(f, "R{destination} = {left} + {right}",)
|
||||||
f,
|
|
||||||
"R{destination} = {left}({left_type}) + {right}({right_type})",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,15 +56,12 @@ impl Display for Less {
|
|||||||
let Less {
|
let Less {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
left_type,
|
left_type: _,
|
||||||
right,
|
right,
|
||||||
right_type,
|
right_type: _,
|
||||||
} = self;
|
} = self;
|
||||||
let operator = if *comparator { "<" } else { "≥" };
|
let operator = if *comparator { "<" } else { "≥" };
|
||||||
|
|
||||||
write!(
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
f,
|
|
||||||
"if {left_type}({left}) {operator} {right_type}({right}) {{ JUMP +1 }}"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,15 +56,12 @@ impl Display for LessEqual {
|
|||||||
let LessEqual {
|
let LessEqual {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
left_type,
|
left_type: _,
|
||||||
right,
|
right,
|
||||||
right_type,
|
right_type: _,
|
||||||
} = self;
|
} = self;
|
||||||
let operator = if *comparator { "≤" } else { ">" };
|
let operator = if *comparator { "≤" } else { ">" };
|
||||||
|
|
||||||
write!(
|
write!(f, "if {left} {operator} {right} {{ JUMP +1 }}")
|
||||||
f,
|
|
||||||
"if {left_type}({left}) {operator} {right_type}({right}) {{ JUMP +1 }}"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,6 +154,7 @@ pub use type_code::TypeCode;
|
|||||||
|
|
||||||
use crate::NativeFunction;
|
use crate::NativeFunction;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct InstructionBuilder {
|
pub struct InstructionBuilder {
|
||||||
pub operation: Operation,
|
pub operation: Operation,
|
||||||
pub a_field: u16,
|
pub a_field: u16,
|
||||||
@ -182,6 +183,22 @@ impl InstructionBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&Instruction> for InstructionBuilder {
|
||||||
|
fn from(instruction: &Instruction) -> Self {
|
||||||
|
InstructionBuilder {
|
||||||
|
operation: instruction.operation(),
|
||||||
|
a_field: instruction.a_field(),
|
||||||
|
b_field: instruction.b_field(),
|
||||||
|
c_field: instruction.c_field(),
|
||||||
|
d_field: instruction.d_field(),
|
||||||
|
b_is_constant: instruction.b_is_constant(),
|
||||||
|
c_is_constant: instruction.c_is_constant(),
|
||||||
|
b_type: instruction.b_type(),
|
||||||
|
c_type: instruction.c_type(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for InstructionBuilder {
|
impl Default for InstructionBuilder {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
InstructionBuilder {
|
InstructionBuilder {
|
||||||
|
@ -3,31 +3,50 @@ use tracing::trace;
|
|||||||
use crate::{
|
use crate::{
|
||||||
AbstractList, ConcreteValue, Instruction, Operand, Type, Value,
|
AbstractList, ConcreteValue, Instruction, Operand, Type, Value,
|
||||||
instruction::{
|
instruction::{
|
||||||
Add, Call, CallNative, Close, Divide, Equal, GetLocal, Jump, Less, LessEqual, LoadBoolean,
|
Add, Call, CallNative, Close, Divide, Equal, GetLocal, InstructionBuilder, Jump, Less,
|
||||||
LoadConstant, LoadFunction, LoadList, LoadSelf, Modulo, Multiply, Negate, Not, Point,
|
LessEqual, LoadBoolean, LoadConstant, LoadFunction, LoadList, LoadSelf, Modulo, Multiply,
|
||||||
Return, SetLocal, Subtract, Test, TestSet, TypeCode,
|
Negate, Not, Point, Return, SetLocal, Subtract, Test, TestSet, TypeCode,
|
||||||
},
|
},
|
||||||
vm::FunctionCall,
|
vm::CallFrame,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Pointer, Register, thread::ThreadData};
|
use super::{Pointer, Register, thread::Thread};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
pub struct ActionSequence {
|
||||||
pub struct RunAction {
|
pub actions: Vec<Action>,
|
||||||
pub logic: RunnerLogic,
|
|
||||||
pub instruction: Instruction,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Instruction> for RunAction {
|
impl ActionSequence {
|
||||||
fn from(instruction: Instruction) -> Self {
|
pub fn new(instructions: &[Instruction]) -> Self {
|
||||||
let operation = instruction.operation();
|
let mut actions = Vec::with_capacity(instructions.len());
|
||||||
let logic = RUNNER_LOGIC_TABLE[operation.0 as usize];
|
|
||||||
|
|
||||||
RunAction { logic, instruction }
|
for instruction in instructions {
|
||||||
|
let action = Action::from(*instruction);
|
||||||
|
|
||||||
|
actions.push(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
ActionSequence { actions }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type RunnerLogic = fn(Instruction, &mut ThreadData) -> bool;
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub struct Action {
|
||||||
|
pub logic: RunnerLogic,
|
||||||
|
pub instruction: InstructionBuilder,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Instruction> for Action {
|
||||||
|
fn from(instruction: &Instruction) -> Self {
|
||||||
|
let operation = instruction.operation();
|
||||||
|
let logic = RUNNER_LOGIC_TABLE[operation.0 as usize];
|
||||||
|
let instruction = InstructionBuilder::from(instruction);
|
||||||
|
|
||||||
|
Action { logic, instruction }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type RunnerLogic = fn(InstructionBuilder, &mut Thread) -> bool;
|
||||||
|
|
||||||
pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 25] = [
|
pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 25] = [
|
||||||
point,
|
point,
|
||||||
@ -57,18 +76,7 @@ pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 25] = [
|
|||||||
r#return,
|
r#return,
|
||||||
];
|
];
|
||||||
|
|
||||||
pub(crate) fn get_next_action(data: &mut ThreadData) -> RunAction {
|
pub fn point(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let current_call = data.call_stack.last_mut_unchecked();
|
|
||||||
let instruction = current_call.chunk.instructions[current_call.ip];
|
|
||||||
let operation = instruction.operation();
|
|
||||||
let logic = RUNNER_LOGIC_TABLE[operation.0 as usize];
|
|
||||||
|
|
||||||
current_call.ip += 1;
|
|
||||||
|
|
||||||
RunAction { logic, instruction }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn point(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|
||||||
let Point { from, to } = instruction.into();
|
let Point { from, to } = instruction.into();
|
||||||
let from_register = data.get_register_unchecked(from);
|
let from_register = data.get_register_unchecked(from);
|
||||||
let from_register_is_empty = matches!(from_register, Register::Empty);
|
let from_register_is_empty = matches!(from_register, Register::Empty);
|
||||||
@ -84,7 +92,7 @@ pub fn point(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn close(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Close { from, to } = instruction.into();
|
let Close { from, to } = instruction.into();
|
||||||
|
|
||||||
for register_index in from..to {
|
for register_index in from..to {
|
||||||
@ -96,7 +104,7 @@ pub fn close(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_boolean(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn load_boolean(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let LoadBoolean {
|
let LoadBoolean {
|
||||||
destination,
|
destination,
|
||||||
value,
|
value,
|
||||||
@ -118,7 +126,7 @@ pub fn load_boolean(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_constant(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn load_constant(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let LoadConstant {
|
let LoadConstant {
|
||||||
destination,
|
destination,
|
||||||
constant_index,
|
constant_index,
|
||||||
@ -141,7 +149,7 @@ pub fn load_constant(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_list(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn load_list(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let LoadList {
|
let LoadList {
|
||||||
destination,
|
destination,
|
||||||
start_register,
|
start_register,
|
||||||
@ -183,7 +191,7 @@ pub fn load_list(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_function(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn load_function(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let LoadFunction {
|
let LoadFunction {
|
||||||
destination,
|
destination,
|
||||||
prototype_index,
|
prototype_index,
|
||||||
@ -202,7 +210,7 @@ pub fn load_function(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_self(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn load_self(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let LoadSelf {
|
let LoadSelf {
|
||||||
destination,
|
destination,
|
||||||
jump_next,
|
jump_next,
|
||||||
@ -219,7 +227,7 @@ pub fn load_self(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_local(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn get_local(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let GetLocal {
|
let GetLocal {
|
||||||
destination,
|
destination,
|
||||||
local_index,
|
local_index,
|
||||||
@ -234,7 +242,7 @@ pub fn get_local(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_local(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn set_local(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let SetLocal {
|
let SetLocal {
|
||||||
register_index,
|
register_index,
|
||||||
local_index,
|
local_index,
|
||||||
@ -249,7 +257,7 @@ pub fn set_local(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn add(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Add {
|
let Add {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
@ -297,7 +305,7 @@ pub fn add(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subtract(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn subtract(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Subtract {
|
let Subtract {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
@ -345,7 +353,7 @@ pub fn subtract(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn multiply(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn multiply(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Multiply {
|
let Multiply {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
@ -393,7 +401,7 @@ pub fn multiply(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn divide(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn divide(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Divide {
|
let Divide {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
@ -441,7 +449,7 @@ pub fn divide(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn modulo(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn modulo(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Modulo {
|
let Modulo {
|
||||||
destination,
|
destination,
|
||||||
left,
|
left,
|
||||||
@ -475,7 +483,7 @@ pub fn modulo(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn test(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Test {
|
let Test {
|
||||||
operand_register,
|
operand_register,
|
||||||
test_value,
|
test_value,
|
||||||
@ -498,7 +506,7 @@ pub fn test(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_set(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn test_set(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let TestSet {
|
let TestSet {
|
||||||
destination,
|
destination,
|
||||||
argument,
|
argument,
|
||||||
@ -527,7 +535,7 @@ pub fn test_set(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn equal(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Equal {
|
let Equal {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
@ -606,7 +614,7 @@ pub fn equal(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn less(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Less {
|
let Less {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
@ -657,7 +665,7 @@ pub fn less(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_equal(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn less_equal(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let LessEqual {
|
let LessEqual {
|
||||||
comparator,
|
comparator,
|
||||||
left,
|
left,
|
||||||
@ -708,7 +716,7 @@ pub fn less_equal(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn negate(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn negate(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Negate {
|
let Negate {
|
||||||
destination,
|
destination,
|
||||||
argument,
|
argument,
|
||||||
@ -725,7 +733,7 @@ pub fn negate(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn not(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn not(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Not {
|
let Not {
|
||||||
destination,
|
destination,
|
||||||
argument,
|
argument,
|
||||||
@ -744,7 +752,7 @@ pub fn not(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jump(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn jump(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Jump {
|
let Jump {
|
||||||
offset,
|
offset,
|
||||||
is_positive,
|
is_positive,
|
||||||
@ -763,7 +771,7 @@ pub fn jump(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn call(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let Call {
|
let Call {
|
||||||
destination: return_register,
|
destination: return_register,
|
||||||
function_register,
|
function_register,
|
||||||
@ -782,7 +790,7 @@ pub fn call(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
|
|
||||||
current_call.chunk.prototypes[function.prototype_index as usize].clone()
|
current_call.chunk.prototypes[function.prototype_index as usize].clone()
|
||||||
};
|
};
|
||||||
let mut next_call = FunctionCall::new(prototype, return_register);
|
let mut next_call = CallFrame::new(prototype, return_register);
|
||||||
let mut argument_index = 0;
|
let mut argument_index = 0;
|
||||||
|
|
||||||
for register_index in first_argument_register..return_register {
|
for register_index in first_argument_register..return_register {
|
||||||
@ -804,7 +812,7 @@ pub fn call(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_native(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn call_native(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
let CallNative {
|
let CallNative {
|
||||||
destination,
|
destination,
|
||||||
function,
|
function,
|
||||||
@ -816,7 +824,7 @@ pub fn call_native(instruction: Instruction, data: &mut ThreadData) -> bool {
|
|||||||
function.call(data, destination, argument_range)
|
function.call(data, destination, argument_range)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#return(instruction: Instruction, data: &mut ThreadData) -> bool {
|
pub fn r#return(instruction: InstructionBuilder, data: &mut Thread) -> bool {
|
||||||
trace!("Returning with call stack:\n{}", data.call_stack);
|
trace!("Returning with call stack:\n{}", data.call_stack);
|
||||||
|
|
||||||
let Return {
|
let Return {
|
@ -8,14 +8,14 @@ use crate::{Chunk, DustString};
|
|||||||
use super::Register;
|
use super::Register;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FunctionCall {
|
pub struct CallFrame {
|
||||||
pub chunk: Arc<Chunk>,
|
pub chunk: Arc<Chunk>,
|
||||||
pub ip: usize,
|
pub ip: usize,
|
||||||
pub return_register: u16,
|
pub return_register: u16,
|
||||||
pub registers: Vec<Register>,
|
pub registers: Vec<Register>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionCall {
|
impl CallFrame {
|
||||||
pub fn new(chunk: Arc<Chunk>, return_register: u16) -> Self {
|
pub fn new(chunk: Arc<Chunk>, return_register: u16) -> Self {
|
||||||
let register_count = chunk.register_count;
|
let register_count = chunk.register_count;
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ impl FunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for FunctionCall {
|
impl Display for CallFrame {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
@ -1,7 +1,6 @@
|
|||||||
//! Virtual machine and errors
|
//! Virtual machine and errors
|
||||||
mod function_call;
|
mod action;
|
||||||
mod run_action;
|
mod call_frame;
|
||||||
mod stack;
|
|
||||||
mod thread;
|
mod thread;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
@ -10,11 +9,10 @@ use std::{
|
|||||||
thread::Builder,
|
thread::Builder,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use function_call::FunctionCall;
|
pub use action::Action;
|
||||||
pub use run_action::RunAction;
|
pub(crate) use action::get_next_action;
|
||||||
pub(crate) use run_action::get_next_action;
|
pub use call_frame::CallFrame;
|
||||||
pub use stack::Stack;
|
pub use thread::Thread;
|
||||||
pub use thread::{Thread, ThreadData};
|
|
||||||
|
|
||||||
use crossbeam_channel::bounded;
|
use crossbeam_channel::bounded;
|
||||||
use tracing::{Level, span};
|
use tracing::{Level, span};
|
||||||
@ -46,12 +44,13 @@ impl Vm {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|name| name.to_string())
|
.map(|name| name.to_string())
|
||||||
.unwrap_or_else(|| "anonymous".to_string());
|
.unwrap_or_else(|| "anonymous".to_string());
|
||||||
let mut main_thread = Thread::new(Arc::new(self.main_chunk));
|
|
||||||
let (tx, rx) = bounded(1);
|
let (tx, rx) = bounded(1);
|
||||||
|
let main_chunk = Arc::new(self.main_chunk);
|
||||||
|
|
||||||
Builder::new()
|
Builder::new()
|
||||||
.name(thread_name)
|
.name(thread_name)
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
|
let main_thread = Thread::new(main_chunk);
|
||||||
let value_option = main_thread.run();
|
let value_option = main_thread.run();
|
||||||
let _ = tx.send(value_option);
|
let _ = tx.send(value_option);
|
||||||
})
|
})
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
use std::{
|
|
||||||
fmt::{self, Debug, Display, Formatter},
|
|
||||||
ops::{Index, IndexMut, Range},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::FunctionCall;
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
|
||||||
pub struct Stack<T> {
|
|
||||||
items: Vec<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Stack<T> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Stack {
|
|
||||||
items: Vec::with_capacity(1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
|
||||||
Stack {
|
|
||||||
items: Vec::with_capacity(capacity),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
|
||||||
self.items.is_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.items.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_unchecked(&self, index: usize) -> &T {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
assert!(index < self.len(), "Stack underflow");
|
|
||||||
|
|
||||||
&self.items[index]
|
|
||||||
} else {
|
|
||||||
unsafe { self.items.get_unchecked(index) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
assert!(index < self.len(), "Stack underflow");
|
|
||||||
|
|
||||||
&mut self.items[index]
|
|
||||||
} else {
|
|
||||||
unsafe { self.items.get_unchecked_mut(index) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, item: T) {
|
|
||||||
self.items.push(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop(&mut self) -> Option<T> {
|
|
||||||
self.items.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn last(&self) -> Option<&T> {
|
|
||||||
self.items.last()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn last_mut(&mut self) -> Option<&mut T> {
|
|
||||||
self.items.last_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop_unchecked(&mut self) -> T {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
assert!(!self.is_empty(), "Stack underflow");
|
|
||||||
|
|
||||||
self.items.pop().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { self.items.pop().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn last_unchecked(&self) -> &T {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
assert!(!self.is_empty(), "Stack underflow");
|
|
||||||
|
|
||||||
self.items.last().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { self.items.last().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn last_mut_unchecked(&mut self) -> &mut T {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
assert!(!self.is_empty(), "Stack underflow");
|
|
||||||
|
|
||||||
self.items.last_mut().unwrap()
|
|
||||||
} else {
|
|
||||||
unsafe { self.items.last_mut().unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Default for Stack<T> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Index<Range<usize>> for Stack<T> {
|
|
||||||
type Output = [T];
|
|
||||||
|
|
||||||
fn index(&self, index: Range<usize>) -> &Self::Output {
|
|
||||||
&self.items[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> IndexMut<Range<usize>> for Stack<T> {
|
|
||||||
fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output {
|
|
||||||
&mut self.items[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Debug> Debug for Stack<T> {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{:?}", self.items)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Stack<FunctionCall> {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
writeln!(f, "----- DUST CALL STACK -----")?;
|
|
||||||
|
|
||||||
for (index, function_call) in self.items.iter().enumerate().rev() {
|
|
||||||
writeln!(f, "{index:02} | {function_call}")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(f, "---------------------------")
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,20 +2,36 @@ use std::{mem::replace, sync::Arc, thread::JoinHandle};
|
|||||||
|
|
||||||
use tracing::{info, trace};
|
use tracing::{info, trace};
|
||||||
|
|
||||||
use crate::{Chunk, DustString, Operand, Span, Value, vm::FunctionCall};
|
use crate::{
|
||||||
|
Chunk, DustString, Operand, Span, Value,
|
||||||
|
vm::{CallFrame, action::ActionSequence},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{Pointer, Register, RunAction, Stack};
|
use super::{Pointer, Register};
|
||||||
|
|
||||||
pub struct Thread {
|
pub struct Thread {
|
||||||
chunk: Arc<Chunk>,
|
chunk: Arc<Chunk>,
|
||||||
|
call_stack: Vec<CallFrame>,
|
||||||
|
return_value_index: Option<Option<usize>>,
|
||||||
|
spawned_threads: Vec<JoinHandle<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Thread {
|
impl Thread {
|
||||||
pub fn new(chunk: Arc<Chunk>) -> Self {
|
pub fn new(chunk: Arc<Chunk>) -> Self {
|
||||||
Thread { chunk }
|
let mut call_stack = Vec::with_capacity(chunk.prototypes.len() + 1);
|
||||||
|
let main_call = CallFrame::new(Arc::clone(&chunk), 0);
|
||||||
|
|
||||||
|
call_stack.push(main_call);
|
||||||
|
|
||||||
|
Thread {
|
||||||
|
chunk,
|
||||||
|
call_stack,
|
||||||
|
return_value_index: None,
|
||||||
|
spawned_threads: Vec::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) -> Option<Value> {
|
pub fn run(mut self) -> Option<Value> {
|
||||||
info!(
|
info!(
|
||||||
"Starting thread with {}",
|
"Starting thread with {}",
|
||||||
self.chunk
|
self.chunk
|
||||||
@ -24,64 +40,59 @@ 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 main_call = self.current_frame();
|
||||||
let mut main_call = FunctionCall::new(self.chunk.clone(), 0);
|
let action_sequence = ActionSequence::new(&main_call.chunk.instructions);
|
||||||
main_call.ip = 1; // The first action is already known
|
|
||||||
|
|
||||||
call_stack.push(main_call);
|
|
||||||
|
|
||||||
let first_action = RunAction::from(*self.chunk.instructions.first().unwrap());
|
|
||||||
let mut thread_data = ThreadData {
|
|
||||||
call_stack,
|
|
||||||
next_action: first_action,
|
|
||||||
return_value_index: None,
|
|
||||||
spawned_threads: Vec::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
trace!("Instruction: {}", thread_data.next_action.instruction);
|
let current_frame = self.current_frame_mut();
|
||||||
|
let ip = {
|
||||||
|
let ip = current_frame.ip;
|
||||||
|
current_frame.ip += 1;
|
||||||
|
|
||||||
let should_end = (thread_data.next_action.logic)(
|
ip
|
||||||
thread_data.next_action.instruction,
|
};
|
||||||
&mut thread_data,
|
let current_action = if cfg!(debug_assertions) {
|
||||||
);
|
action_sequence.actions.get(ip).unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { action_sequence.actions.get_unchecked(ip) }
|
||||||
|
};
|
||||||
|
|
||||||
if should_end {
|
trace!("Operation: {}", current_action.instruction.operation);
|
||||||
let value_option = if let Some(register_index) = thread_data.return_value_index {
|
|
||||||
let value =
|
|
||||||
thread_data.empty_register_or_clone_constant_unchecked(register_index);
|
|
||||||
|
|
||||||
Some(value)
|
(current_action.logic)(current_action.instruction, &mut self);
|
||||||
|
|
||||||
|
if let Some(return_index_option) = self.return_value_index {
|
||||||
|
if let Some(return_index) = return_index_option {
|
||||||
|
let return_value = self.open_register_unchecked(return_index as u16).clone();
|
||||||
|
|
||||||
|
return Some(return_value);
|
||||||
} else {
|
} else {
|
||||||
None
|
return None;
|
||||||
};
|
}
|
||||||
|
|
||||||
thread_data
|
|
||||||
.spawned_threads
|
|
||||||
.into_iter()
|
|
||||||
.for_each(|join_handle| {
|
|
||||||
let _ = join_handle.join();
|
|
||||||
});
|
|
||||||
|
|
||||||
return value_option;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct ThreadData {
|
|
||||||
pub call_stack: Stack<FunctionCall>,
|
|
||||||
pub next_action: RunAction,
|
|
||||||
pub return_value_index: Option<u16>,
|
|
||||||
pub spawned_threads: Vec<JoinHandle<()>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ThreadData {
|
|
||||||
pub fn current_position(&self) -> Span {
|
pub fn current_position(&self) -> Span {
|
||||||
let current_call = self.call_stack.last_unchecked();
|
let current_frame = self.current_frame();
|
||||||
|
|
||||||
current_call.chunk.positions[current_call.ip]
|
current_frame.chunk.positions[current_frame.ip]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_frame(&self) -> &CallFrame {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.call_stack.last().unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { self.call_stack.last().unwrap_unchecked() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_frame_mut(&mut self) -> &mut CallFrame {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
self.call_stack.last_mut().unwrap()
|
||||||
|
} else {
|
||||||
|
unsafe { self.call_stack.last_mut().unwrap_unchecked() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn follow_pointer_unchecked(&self, pointer: Pointer) -> &Value {
|
pub(crate) fn follow_pointer_unchecked(&self, pointer: Pointer) -> &Value {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user