Adjusted inappropriate use of the dummy scope in the compiler. Reimplemented try_string. Amended shifted instruction operands in VM. Builds and runs basic loop.

This commit is contained in:
paladin 2026-08-28 10:47:48 +01:00
parent c10d56c0f8
commit ab43ff9f9e
2 changed files with 62 additions and 54 deletions

View file

@ -1321,7 +1321,7 @@ impl Traversal<'_> {
self.consume_scope(2); // Value, Table
}
Code::Return(index) | Code::Call(index) => {
let diff = self.last_scope().index - index;
let diff = self.index().unwrap() - index;
self.consume_scope(diff + 1);
//assert_eq!(self.last_scope().index, index);
/* So note that Code::Call here doesn't do any temp_scope() magic, this is an edge-case for
@ -1389,11 +1389,9 @@ impl Traversal<'_> {
Ok(string) => Ok(self.push_literal(string, piece)),
}
}
fn new_scope(&mut self) {
let context = &mut self.contexts.last_mut().unwrap();
let scopes = &mut context.scopes;
let index = scopes.last().unwrap().index;
scopes.push(Scope {
fn new_scope(&mut self) { // Make some new scope
let index = self.last_scope().index;
self.contexts.last_mut().unwrap().scopes.push(Scope {
index,
jumps: vec![],
labels: vec![],
@ -1401,15 +1399,23 @@ impl Traversal<'_> {
upvalue: false,
});
}
fn temp_scope(&mut self) -> Index {
fn temp_scope(&mut self) -> Index { // Make a new scope with index++
self.new_scope();
let index = self.last_scope().index + 1;
self.last_scope().index = index;
index
if self.last_context().scopes.len() > 2 { // For the dummy scope
self.last_scope().index += 1;
}
self.last_scope().index
}
fn last_scope(&mut self) -> &mut Scope {
self.last_context().scopes.last_mut().unwrap()
}
fn index(&mut self) -> Option<Index> {
if self.last_context().scopes.len() == 1 {
None
} else {
Some(self.last_context().scopes.last_mut().unwrap().index)
}
}
fn code_length(&mut self) -> usize {
self.last_context().prototype.code.len()
}
@ -1436,7 +1442,10 @@ impl Traversal<'_> {
self.contexts.last_mut().unwrap()
}
fn close_context(&mut self) -> Result<Prototype, LoadError> {
let context = self.contexts.pop().unwrap();
let mut context = self.contexts.pop().unwrap();
for jump in context.scopes.pop().unwrap().jumps { // Get back the dummy one and error any jumps
return Err(LoadError::from(format!("{:?}",jump).as_str(), &Piece::<()>::null())) // todo: we need Vec or some append in LoadError and also BlindJumps need pieces!
}
Ok(context.prototype)
}
}
@ -1483,7 +1492,7 @@ fn compile_function(
.map(|it| it.swap(it.clone().it.0.map(|string| string.0.clone()))),
scopes: argument_scopes,
prototype: Prototype {
args: this.it.0.len() as Index,
args: this.it.0.len().try_into().unwrap(),
vararg: this.it.1.is_some(),
prototypes: vec![],
constants: vec![],
@ -1496,7 +1505,7 @@ fn compile_function(
traversal.compile(&this.it.2.inner_ref())?; // compile the block
let prototype = traversal.close_context()?;
let prototypes = &mut traversal.last_context().prototype.prototypes; // add this to the upper function's prototypes list
let index = prototypes.len() as Index;
let index = prototypes.len().try_into().unwrap();
prototypes.push(Rc::new(prototype));
traversal.push_code(this.swap(Code::Closure(index))); // reference this closure
Ok(())
@ -1567,12 +1576,12 @@ fn compile_identifier(
.iter()
.position(|it| *it == reference)
{
Some(index) => Reference::Upvalue(index as Index),
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);
Reference::Upvalue(length as Index) // Reference (child) to this reference to that reference (parent) for next context
Reference::Upvalue(length.try_into().unwrap()) // Reference (child) to this reference to that reference (parent) for next context
}
}
}
@ -1673,7 +1682,7 @@ impl Compile for Piece<&Call> {
}
None => {}
}
let index = traversal.last_scope().index;
let index = traversal.index().unwrap();
traversal.compile(&self.it.2.inner_ref())?; // arguments
traversal.push_code(self.it.0.unit().end().swap(Code::Call(index))); // Our responsibility to discard here
Ok(())
@ -1684,7 +1693,7 @@ impl Compile for Piece<&Prefix> {
fn compile<'a, 'b>(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
match &self.it {
Prefix::Call(call) => {
let index = traversal.last_scope().index;
let index = traversal.index().unwrap();
traversal.compile(&self.swap(call))?;
traversal.push_code(self.swap(Code::Discard(index + 1)).end()); // produce 1 return value, or pad nil
}
@ -1836,8 +1845,7 @@ fn jump_from(here: usize, there: usize) -> Result<Offset, LoadError> {
}
fn resolve_break(traversal: &mut Traversal, begin: usize, end: usize) -> Result<(), LoadError> {
let mut jumps = Vec::new();
for jump in traversal.last_scope().jumps.clone() {
for jump in std::mem::replace(&mut traversal.last_scope().jumps,Vec::new()) {
// ?
match jump {
BlindJump::Continue(index) => {
@ -1846,10 +1854,9 @@ fn resolve_break(traversal: &mut Traversal, begin: usize, end: usize) -> Result<
BlindJump::Break(index) => {
traversal.insert_code(index, Code::Jump(jump_from(index, end)?));
}
_ => jumps.push(jump),
_ => traversal.last_scope().jumps.push(jump),
}
}
traversal.last_scope().jumps = jumps;
Ok(())
}
@ -1866,7 +1873,7 @@ fn compile_assignment(
variable: Option<&Piece<Variable>>,
expression: &Piece<&Expression>|
-> Result<(), LoadError> {
let index = traversal.last_scope().index;
let index = traversal.index().unwrap();
traversal.compile(expression)?;
if let Some(variable) = variable {
compile_variable(variable.inner_ref(), traversal, Access::Set)?;
@ -1882,14 +1889,14 @@ fn compile_assignment(
match &**prefix {
Prefix::Call(call) => {
// multiple
let mut index = traversal.last_scope().index;
let mut index = traversal.index().unwrap();
traversal.compile(&expression.swap(call))?;
let index_discard = traversal.push_code(expression.swap(Code::UNSURE));
while let Some(variable) = variables_iter.next() {
index += 1; // The index we would need to pad nil to or restrict to
compile_variable(variable.inner_ref(), traversal, Access::Set)?; // Pops each return value off the stack
}
traversal.insert_code(index_discard, Code::Discard(index as Index));
traversal.insert_code(index_discard, Code::Discard(index.try_into().unwrap()));
}
prefix => {
if let Some(variable) = variables_iter.next() {
@ -1908,7 +1915,7 @@ fn compile_assignment(
count += 1;
compile_variable(variable.inner_ref(), traversal, Access::Set)?;
}
traversal.insert_code(index_vararg, Code::VarArg(count as Index));
traversal.insert_code(index_vararg, Code::VarArg(count.try_into().unwrap()));
}
}
_ => {
@ -1934,7 +1941,7 @@ fn compile_assignment(
impl Compile for Piece<&Block> {
fn compile(&self, traversal: &mut Traversal) -> Result<(), LoadError> {
let last_scope_index = traversal.last_scope().index;
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();
@ -1951,7 +1958,7 @@ impl Compile for Piece<&Block> {
compile_assignment(traversal, variables, expressions)?;
}
Statement::Call(call) => {
let index = traversal.last_scope().index;
let index = traversal.index().unwrap_or(0);
traversal.compile(&self.swap(call))?;
traversal.push_code(self.swap(Code::Discard(index)));
}
@ -2109,7 +2116,7 @@ impl Compile for Piece<&Block> {
traversal.new_scope();
iterator_variables.push(
block
.swap(Variable::Register(traversal.last_scope().index))
.swap(Variable::Register(traversal.index().unwrap()))
.start(),
);
}
@ -2117,10 +2124,10 @@ impl Compile for Piece<&Block> {
compile_assignment(traversal, &iterator_variables, expressions)?;
let index_loop = traversal.push_code(block.swap(Code::UNSURE));
// Discard to fill all names
let index = traversal.last_scope().index;
let index = traversal.index().unwrap();
traversal.push_code(
block
.swap(Code::Discard(index + names.len() as Index))
.swap(Code::Discard((index as usize + names.len()).try_into().unwrap()))
.start(),
);
for name in names.iter() {
@ -2175,7 +2182,7 @@ impl Compile for Piece<&Block> {
}
Statement::LocalFunction(name, function) => {
var_scope(traversal, name.it.0.clone());
let index = traversal.last_scope().index;
let index = traversal.index().unwrap();
traversal.compile(&self.swap(function))?;
traversal.push_code(name.swap(Code::RegisterSet(index)).end());
}
@ -2201,10 +2208,7 @@ impl Compile for Piece<&Block> {
for _ in 0..depth {
traversal.close_scope();
}
if traversal.last_scope().index != last_scope_index {
println!("{:?}", traversal.last_scope())
}
assert_eq!(traversal.last_scope().index, last_scope_index);
assert_eq!(traversal.index().unwrap_or(0), last_scope_index);
Ok(())
}
}
@ -2470,6 +2474,13 @@ impl Value {
_ => true,
}
}
fn unwrap_str(&mut self) -> Rc<str> {
match self {
Value::CachedString(cached) => cached.0.clone(),
Value::String(string,_hash) => string.clone(),
_ => panic!()
}
}
}
impl PartialEq for Value {
@ -2674,12 +2685,12 @@ impl Machine {
_ => Ok(Value::Nil),
}
}
/*fn try_string(&mut self, machine: &mut Machine) -> Result<Value, RunError> {
Ok(match self {
Value::Nil => machine.new_string("nil".to_string().as_str())?,
Value::Bool(bool) => machine.new_string(format!("{}", bool).as_str())?,
Value::Integer(integer) => machine.new_string(format!("{}", integer).as_str())?,
Value::Number(number) => machine.new_string(format!("{}", number).as_str())?,
fn try_string(&mut self, value: &mut Value) -> Result<Value, RunError> {
Ok(match value {
Value::Nil => self.new_string("nil".to_string().as_str())?,
Value::Bool(bool) => self.new_string(format!("{}", bool).as_str())?,
Value::Integer(integer) => self.new_string(format!("{}", integer).as_str())?,
Value::Number(number) => self.new_string(format!("{}", number).as_str())?,
it @ Value::String(..) => return Ok(it.clone()),
it @ Value::CachedString(..) => return Ok(it.clone()),
#[cfg(feature = "vector3")]
@ -2689,16 +2700,16 @@ impl Machine {
if let Some(_metatable) = &table.meta {
return Err(RunError("Metatables unimplemented".to_string()));
} else {
machine.new_string("{...}".to_string().as_str())?
self.new_string("{...}".to_string().as_str())?
}
}
Value::Object(object) => match object.borrow_mut().0.meta_string()? {
string @ Value::String(..) => return Ok(string),
it => return Err(RunError(format!("Expected string but got {:?}", it))),
},
Value::Function(callable) => machine.new_string(format!("{:?}", callable).as_str())?,
Value::Function(callable) => self.new_string(format!("{:?}", callable).as_str())?,
})
}*/
}
fn set(&mut self, subject: Value, index: Value, value: Value) -> Result<(), RunError> {
match subject {
Value::Nil => Err(RunError("Cannot get from nil".to_string())),
@ -2817,8 +2828,7 @@ impl Machine {
let mut traversal = Traversal {
machine: self,
contexts: vec![Context {
scopes: vec![Scope {
// Dummy initial scope so the rest can start from index = 0
scopes: vec![Scope { // Dummy scope
index: 0,
jumps: vec![],
labels: vec![],
@ -2900,7 +2910,7 @@ impl Machine {
};
let mut jump = |frame: &mut Frame, offset: Offset| {
if offset < 0 {
frame.counter -= (-offset) as usize
frame.counter -= -(offset) as usize
} else {
frame.counter += offset as usize
}
@ -3195,8 +3205,8 @@ impl Machine {
fn enter(&mut self, closure: Gc<Closure>) -> Result<(), RunError> {
let mut needle = Needle {
frames: vec![Frame {
vararg: 0,
offset: 0,
vararg: 1, // Both 1 since there is a single NIL on the stack
offset: 1,
counter: 0,
closure,
}],
@ -3216,7 +3226,7 @@ impl Machine {
string,
Value::Function(Callable::Rust(Rc::from(Native(|machine: &mut Machine, needle: &mut Needle, index: usize| -> Result<(), RunError> {
for i in index..needle.stack.len() {
println!("{:?}",needle.pop())
println!("{}",machine.try_string(&mut needle.pop())?.unwrap_str())
}
Ok(())
}))))

View file

@ -1,5 +1,3 @@
if true then
print("whats good")
else
print("oh no")
while true do
print("i am a loop!")
end