Modified Machine to take a State, partially implemented metamethods, refactored for adopting freelists. Fails build; in progress.

This commit is contained in:
paladin 2026-09-28 02:04:17 +01:00
parent 60c097518a
commit db0ff1348c
13 changed files with 632 additions and 871 deletions

View file

@ -4,15 +4,15 @@ use crate::parser::{
Args, Block, Call, Chunk, Constructor, Expression, Function, LoadError, Name, Piece, Prefix,
Statement, VarArg, Variable,
};
use crate::table::{Equivalent, Hashed, Hashes, Map, TableEntry};
use crate::vm::{Code, Index, Machine, Offset, Prototype, Reference, Value};
use std::cmp::PartialEq;
use std::ops::Deref;
use std::rc::Rc;
use deimos::map::{Equivalent, Hashed, Hashes, Map, TableEntry};
pub(crate) struct Traversal<'a> {
pub(crate) struct Traversal<'a,S> {
// A 'cursor' of where we are in assumed execution
machine: &'a mut Machine,
machine: &'a mut Machine<S>,
contexts: Vec<Context>, // Stack of function prototypes being compiled
}
@ -70,7 +70,7 @@ pub(crate) struct Scope {
upvalue: bool,
}
impl Traversal<'_> {
impl<S> Traversal<'_,S> {
fn compile<T>(&mut self, it: &T) -> Result<(), LoadError>
where
T: Compile,
@ -132,7 +132,7 @@ impl Traversal<'_> {
| Code::RangeLoop(_)
| Code::RangeBegin
| Code::IteratorLoop(_)
| Code::Comment(_) => {}
| Code::Message(_) => {}
}
let prototype = &mut self.contexts.last_mut().unwrap().prototype;
prototype.code.push(it.it);
@ -247,7 +247,7 @@ impl Traversal<'_> {
}
Ok(context.prototype)
}
pub(crate) fn new(machine: &mut Machine) -> Traversal {
pub(crate) fn new(machine: &mut Machine<S>) -> Traversal<S> {
Traversal {
machine,
contexts: vec![Context {
@ -277,12 +277,12 @@ impl Traversal<'_> {
// todo: not all impl Compile for Piece<T> needs to be &T
trait Compile {
fn compile(&self, traversal: &mut Traversal) -> Result<(), LoadError>;
fn compile<S>(&self, traversal: &mut Traversal<S>) -> Result<(), LoadError>;
}
fn compile_function(
fn compile_function<S>(
this: &Piece<&Function>,
traversal: &mut Traversal,
traversal: &mut Traversal<S>,
method: bool,
) -> Result<(), LoadError> {
let mut self_arguments = Vec::new();
@ -341,9 +341,9 @@ enum Access {
Get,
}
fn compile_identifier(
fn compile_identifier<S>(
name: Piece<String>,
traversal: &mut Traversal,
traversal: &mut Traversal<S>,
access: Access,
) -> Result<(), LoadError> {
let contexts_len = traversal.contexts.len();
@ -416,7 +416,7 @@ fn compile_identifier(
}
}
}
// break 'search avoids this use of the _G table
// At this point there were no returns so we must use _G table
traversal.push_string(name.it.clone(), name.unit())?;
traversal.push_code(name.swap(Code::UpvalueGet(0)));
traversal.push_code(name.swap(match access {
@ -426,9 +426,9 @@ fn compile_identifier(
Ok(())
}
fn compile_variable(
fn compile_variable<S>(
variable: Piece<&Variable>,
traversal: &mut Traversal,
traversal: &mut Traversal<S>,
access: Access,
) -> Result<(), LoadError> {
match &variable.it {
@ -455,13 +455,13 @@ fn compile_variable(
}
impl Compile for Piece<&Function> {
fn compile(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
fn compile<S>(&self, traversal: &mut Traversal<S>) -> Result<(), LoadError> {
compile_function(self, traversal, false)
}
}
impl Compile for Piece<&Args> {
fn compile(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
fn compile<S>(&self, traversal: &mut Traversal<S>) -> Result<(), LoadError> {
let mut expressions_iter = self.it.0.iter().rev();
if let Some(expression) = expressions_iter.next() {
let piece = expression.unit();
@ -491,7 +491,7 @@ impl Compile for Piece<&Args> {
}
impl Compile for Piece<&Call> {
fn compile(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
fn compile<S>(&self, traversal: &mut Traversal<S>) -> Result<(), LoadError> {
let index = traversal.index().map(|it| it + 1).unwrap_or(0); // there will always be at least the callable
traversal.compile(&self.it.args.inner_ref())?; // arguments
traversal.compile(&self.it.prefix.as_ref().inner_ref())?; // call prefix
@ -508,7 +508,7 @@ impl Compile for Piece<&Call> {
}
impl Compile for Piece<&Prefix> {
fn compile<'a, 'b>(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
fn compile<'a, 'b, S>(&self, traversal: &mut Traversal<S>) -> Result<(), LoadError> {
match &self.it {
Prefix::Call(call) => {
let index = traversal.index().unwrap();
@ -528,7 +528,7 @@ impl Compile for Piece<&Prefix> {
// for the sake of erroring alone
impl Compile for Piece<&VarArg> {
fn compile<'a, 'b>(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
fn compile<'a, 'b, S>(&self, traversal: &mut Traversal<S>) -> Result<(), LoadError> {
match &traversal.contexts.last().unwrap().vararg {
Some(piece) => match &piece.it {
Some(that_name) => match &self.it.0 {
@ -576,7 +576,7 @@ impl Compile for Piece<&VarArg> {
}
impl Compile for Piece<&Constructor> {
fn compile<'a, 'b>(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
fn compile<'a, 'b, S>(&self, traversal: &mut Traversal<S>) -> Result<(), LoadError> {
traversal.push_code(self.swap(Code::TableNew));
let index_table = traversal.index().unwrap();
for field in self.it.0.iter() {
@ -626,7 +626,7 @@ impl Compile for Piece<&Constructor> {
}
impl Compile for Piece<&Expression> {
fn compile<'a>(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
fn compile<'a, S>(&self, traversal: &mut Traversal<S>) -> Result<(), LoadError> {
match self.it {
Expression::Nil => {
traversal.push_literal(Value::Nil, self.unit());
@ -684,7 +684,7 @@ fn jump_from(here: usize, there: usize) -> Result<Offset, LoadError> {
Ok((there as i64 - here as i64) as Offset)
}
fn resolve_break(traversal: &mut Traversal, begin: usize, end: usize) -> Result<(), LoadError> {
fn resolve_break<S>(traversal: &mut Traversal<S>, begin: usize, end: usize) -> Result<(), LoadError> {
for jump in std::mem::replace(&mut traversal.last_scope().jumps, Vec::new()) {
// ?
match jump {
@ -700,8 +700,8 @@ fn resolve_break(traversal: &mut Traversal, begin: usize, end: usize) -> Result<
Ok(())
}
fn compile_assignment(
traversal: &mut Traversal,
fn compile_assignment<S>(
traversal: &mut Traversal<S>,
variables: &Vec<Piece<Variable>>,
expressions: &Vec<Piece<Expression>>,
) -> Result<(), LoadError> {
@ -709,7 +709,7 @@ fn compile_assignment(
let mut expressions_iter = expressions.iter().peekable();
while let Some(expression) = expressions_iter.next() {
let compile_variable_expression = |// Compile a variable normally with one value from an expression
traversal: &mut Traversal,
traversal: &mut Traversal<S>,
variable: Option<&Piece<Variable>>,
expression: &Piece<&Expression>|
-> Result<(), LoadError> {
@ -784,7 +784,7 @@ fn compile_assignment(
}
impl Compile for Piece<&Block> {
fn compile(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
fn compile<S>(&self, traversal: &mut Traversal<S>) -> Result<(), LoadError> {
let last_scope_index = traversal.index().unwrap_or(0);
let mut depth = 0; // Counter for 'dangling' scopes produced by any declarations to be closed.
// todo: for some reason, register indices are called "<thing>_index" and code indices "index_<thing>"? fix it
@ -1016,7 +1016,7 @@ impl Compile for Piece<&Block> {
Statement::Declaration(names, expressions) => {
let mut expressions_iter = expressions.iter().peekable();
let mut names_iter = names.iter().peekable();
let compile_declaration = |traversal: &mut Traversal,
let compile_declaration = |traversal: &mut Traversal<S>,
expression: &Piece<Expression>,
name: &Piece<Name>|
-> Result<(), LoadError> {
@ -1125,11 +1125,15 @@ impl Compile for Piece<&Block> {
}
}
// Any 'dangling' scopes that weren't closed (declarations) will be at the end of this block
let return_index = traversal.index().unwrap_or(0);
if let Some(return_expressions) = &self.it.return_exp {
// arguments are backwards
for return_expression in return_expressions.iter().rev() {
traversal.compile(&return_expression.inner_ref())?;
}
if !return_expressions.is_empty() {
traversal.push_code(return_expressions.first().unwrap().swap(Code::Return(return_index)));
}
}
for _ in 0..depth {
traversal.close_scope();
@ -1140,12 +1144,12 @@ impl Compile for Piece<&Block> {
}
impl Compile for Chunk {
fn compile(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
fn compile<S>(&self, traversal: &mut Traversal<S>) -> Result<(), LoadError> {
traversal.compile(&self.0.inner_ref())
}
}
pub(crate) fn compile(chunk: &Chunk, machine: &mut Machine) -> Result<Prototype, LoadError> {
pub(crate) fn compile<S>(chunk: &Chunk, machine: &mut Machine<S>) -> Result<Prototype, LoadError> {
let mut traversal = Traversal::new(machine);
traversal.compile(chunk)?;
traversal.close_context()