Fixed loop instructions, local registers in other instructions, upvalues and tables. Builds and passes test.
This commit is contained in:
parent
110e035efd
commit
60c097518a
9 changed files with 229 additions and 151 deletions
126
src/compiler.rs
126
src/compiler.rs
|
|
@ -346,13 +346,13 @@ fn compile_identifier(
|
|||
traversal: &mut Traversal,
|
||||
access: Access,
|
||||
) -> Result<(), LoadError> {
|
||||
let length = traversal.contexts.len();
|
||||
for i in 0..length {
|
||||
let contexts_len = traversal.contexts.len();
|
||||
for context_index in 0..contexts_len {
|
||||
// For each context
|
||||
let i = length - i - 1; // From top to bottom
|
||||
if i == length - 1 {
|
||||
let context_index = contexts_len - context_index - 1; // From top to bottom
|
||||
if context_index == contexts_len - 1 {
|
||||
// If this is our context
|
||||
for scope in traversal.contexts[i].scopes.iter().rev() {
|
||||
for scope in traversal.contexts[context_index].scopes.iter().rev() {
|
||||
// Go through the scopes
|
||||
if scope.symbol.as_ref().is_some_and(|it| it.eq(&name.it)) {
|
||||
// Find it
|
||||
|
|
@ -366,36 +366,23 @@ fn compile_identifier(
|
|||
}
|
||||
} else {
|
||||
// Otherwise it's another function's 'scope'(s)
|
||||
let length = traversal.contexts[i].scopes.len();
|
||||
for j in 0..length {
|
||||
let scopes_len = traversal.contexts[context_index].scopes.len();
|
||||
for scope_index in 0..scopes_len {
|
||||
// For each scope in that foreign context
|
||||
let j = length - j - 1; // From top to bottom
|
||||
if traversal.contexts[i].scopes[j]
|
||||
let scope_index = scopes_len - scope_index - 1; // From top to bottom
|
||||
if traversal.contexts[context_index].scopes[scope_index]
|
||||
.symbol
|
||||
.as_ref()
|
||||
.is_some_and(|it| it.eq(&name.it))
|
||||
{
|
||||
// Go through...
|
||||
// todo: fix this comment it's talking about something i ended up dropping
|
||||
/*
|
||||
So here we know this 'traversal.contexts[i]' is the function holding the upvalue
|
||||
in 'scopes[j]', if it has an upvalue already made, we use its 'prototype.closing'
|
||||
index and set our initial rolling variable 'reference' to Reference::Register('index').
|
||||
This is significant because this 'upvalue' MUST be made in this owning function's
|
||||
prototype's closing list, but 'reference' also acts as a variable holding the upvalue
|
||||
that the current function in the loop 'for k in j+1..length' produced so that the next
|
||||
function context can reference it, this also means that the last 'reference' after the
|
||||
loop is sort of vacuously a 'Reference::Upvalue' that is only storing our 'index'
|
||||
for the eventual instruction itself.
|
||||
*/
|
||||
let register = traversal.contexts[i].scopes[j].index;
|
||||
traversal.contexts[i].scopes[j].upvalue = true;
|
||||
let register = traversal.contexts[context_index].scopes[scope_index].index;
|
||||
traversal.contexts[context_index].scopes[scope_index].upvalue = true;
|
||||
let mut reference = Reference::Closing(register);
|
||||
// its important that a few conditions are held here e.g. length > 2, j < length + 1...
|
||||
for k in j + 1..length {
|
||||
for down_context_index in context_index + 1..contexts_len {
|
||||
// Ok now going from every context to the one wanting the upvalue
|
||||
// set reference to what we found for the next context
|
||||
reference = match traversal.contexts[k]
|
||||
reference = match traversal.contexts[down_context_index]
|
||||
.prototype
|
||||
.upvalues
|
||||
.iter()
|
||||
|
|
@ -404,8 +391,14 @@ fn compile_identifier(
|
|||
Some(index) => Reference::Upvalue(index.try_into().unwrap()),
|
||||
None => {
|
||||
// we don't even have a reference to this in our upvalues so add it
|
||||
let length = traversal.contexts[k].prototype.upvalues.len();
|
||||
traversal.contexts[k].prototype.upvalues.push(reference);
|
||||
let length = traversal.contexts[down_context_index]
|
||||
.prototype
|
||||
.upvalues
|
||||
.len();
|
||||
traversal.contexts[down_context_index]
|
||||
.prototype
|
||||
.upvalues
|
||||
.push(reference);
|
||||
Reference::Upvalue(length.try_into().unwrap()) // Reference (child) to this reference to that reference (parent) for next context
|
||||
}
|
||||
}
|
||||
|
|
@ -499,6 +492,8 @@ impl Compile for Piece<&Args> {
|
|||
|
||||
impl Compile for Piece<&Call> {
|
||||
fn compile(&self, traversal: &mut Traversal) -> 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
|
||||
match &self.it.method {
|
||||
Some(name) => {
|
||||
|
|
@ -507,8 +502,6 @@ impl Compile for Piece<&Call> {
|
|||
}
|
||||
None => {}
|
||||
}
|
||||
let index = traversal.index().unwrap();
|
||||
traversal.compile(&self.it.args.inner_ref())?; // arguments
|
||||
traversal.push_code(self.it.prefix.unit().end().swap(Code::Call(index))); // Our responsibility to discard here
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -720,7 +713,7 @@ fn compile_assignment(
|
|||
variable: Option<&Piece<Variable>>,
|
||||
expression: &Piece<&Expression>|
|
||||
-> Result<(), LoadError> {
|
||||
let index = traversal.index().unwrap();
|
||||
let index = traversal.index().unwrap_or(0);
|
||||
traversal.compile(expression)?;
|
||||
if let Some(variable) = variable {
|
||||
compile_variable(variable.inner_ref(), traversal, Access::Set)?;
|
||||
|
|
@ -794,12 +787,6 @@ impl Compile for Piece<&Block> {
|
|||
fn compile(&self, traversal: &mut Traversal) -> 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.
|
||||
let mut var_scope = |traversal: &mut Traversal, symbol: String| -> Index {
|
||||
let index = traversal.temp_scope();
|
||||
traversal.last_scope().symbol = Some(symbol);
|
||||
depth += 1;
|
||||
index
|
||||
};
|
||||
// todo: for some reason, register indices are called "<thing>_index" and code indices "index_<thing>"? fix it
|
||||
// todo: maybe refactor this so that there are less indents
|
||||
for statement in self.it.statements.iter() {
|
||||
|
|
@ -928,27 +915,16 @@ impl Compile for Piece<&Block> {
|
|||
}
|
||||
}
|
||||
Statement::Range(var, init, limit, step, block) => {
|
||||
let init_index = traversal.temp_scope(); // init
|
||||
traversal.compile(&init.inner_ref())?;
|
||||
traversal.push_code(init.swap(Code::RegisterSet(init_index)));
|
||||
|
||||
let limit_index = traversal.temp_scope(); // limit
|
||||
traversal.compile(&limit.inner_ref())?;
|
||||
traversal.push_code(limit.swap(Code::RegisterSet(limit_index)));
|
||||
|
||||
let step_index = traversal.temp_scope(); // step;
|
||||
match step {
|
||||
Some(expression) => traversal.compile(&expression.inner_ref())?,
|
||||
None => traversal.push_literal(Value::Integer(1), limit.unit().end()),
|
||||
};
|
||||
let piece = match step {
|
||||
Some(expression) => expression.unit().start(),
|
||||
None => limit.unit().end(),
|
||||
};
|
||||
traversal.push_code(piece.swap(Code::RegisterSet(step_index)));
|
||||
let index_loop =
|
||||
traversal.push_code(block.unit().start().swap(Code::RangeBegin)) + 1;
|
||||
var_scope(traversal, var.it.0.clone());
|
||||
traversal.temp_scope();
|
||||
traversal.last_scope().symbol = Some(var.it.0.clone());
|
||||
traversal.compile(&block.inner_ref())?;
|
||||
traversal.close_scope(); // temporary for v
|
||||
let index_jump = traversal.push_code(block.unit().start().swap(Code::UNSURE)); // Dummy NOP
|
||||
|
|
@ -957,9 +933,7 @@ impl Compile for Piece<&Block> {
|
|||
Code::RangeLoop(jump_from(index_jump, index_loop)?),
|
||||
); // Reinsert into above
|
||||
resolve_break(traversal, index_loop, index_jump + 1)?;
|
||||
traversal.close_scope();
|
||||
traversal.close_scope();
|
||||
traversal.close_scope(); // init, limit, step
|
||||
traversal.consume_scope(3); // init, limit, step
|
||||
}
|
||||
Statement::Iterator(names, expressions, block) => {
|
||||
let mut iterator_variables = Vec::new();
|
||||
|
|
@ -1035,10 +1009,9 @@ impl Compile for Piece<&Block> {
|
|||
}
|
||||
}
|
||||
Statement::LocalFunction(name, function) => {
|
||||
var_scope(traversal, name.it.0.clone());
|
||||
let index = traversal.index().unwrap();
|
||||
traversal.compile(&self.swap(function))?;
|
||||
traversal.push_code(name.swap(Code::RegisterSet(index)).end());
|
||||
traversal.last_scope().symbol = Some(name.it.0.clone());
|
||||
depth += 1;
|
||||
}
|
||||
Statement::Declaration(names, expressions) => {
|
||||
let mut expressions_iter = expressions.iter().peekable();
|
||||
|
|
@ -1068,6 +1041,7 @@ impl Compile for Piece<&Block> {
|
|||
traversal.last_context().scopes.iter_mut().rev();
|
||||
for name in names.iter().rev() {
|
||||
scopes.next().unwrap().symbol = Some(name.it.0.clone());
|
||||
depth += 1;
|
||||
}
|
||||
}
|
||||
Expression::Prefix(ref prefix) => {
|
||||
|
|
@ -1091,28 +1065,38 @@ impl Compile for Piece<&Block> {
|
|||
for name in names.iter().rev() {
|
||||
scopes.next().unwrap().symbol =
|
||||
Some(name.it.0.clone());
|
||||
depth += 1;
|
||||
}
|
||||
}
|
||||
_ => compile_declaration(
|
||||
traversal,
|
||||
expression,
|
||||
names_iter.next().unwrap(),
|
||||
)?,
|
||||
_ => {
|
||||
compile_declaration(
|
||||
traversal,
|
||||
expression,
|
||||
names_iter.next().unwrap(),
|
||||
)?;
|
||||
depth += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => compile_declaration(
|
||||
traversal,
|
||||
expression,
|
||||
names_iter.next().unwrap(),
|
||||
)?,
|
||||
_ => {
|
||||
compile_declaration(
|
||||
traversal,
|
||||
expression,
|
||||
names_iter.next().unwrap(),
|
||||
)?;
|
||||
depth += 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
(Some(expression), false) => compile_declaration(
|
||||
traversal,
|
||||
expression,
|
||||
names_iter.next().unwrap(),
|
||||
)?, // expression is not last, just use it
|
||||
(Some(expression), false) => {
|
||||
compile_declaration(
|
||||
traversal,
|
||||
expression,
|
||||
names_iter.next().unwrap(),
|
||||
)?;
|
||||
depth += 1;
|
||||
} // expression is not last, just use it
|
||||
(None, ..) => {
|
||||
// no more expressions
|
||||
let index = traversal.index().unwrap_or(0) as usize;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue