Modified Machine to take a State, partially implemented metamethods, refactored for adopting freelists. Fails build; in progress.
This commit is contained in:
parent
60c097518a
commit
db0ff1348c
13 changed files with 632 additions and 871 deletions
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue