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

View file

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