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:
parent
c10d56c0f8
commit
ab43ff9f9e
2 changed files with 62 additions and 54 deletions
110
src/lib.rs
110
src/lib.rs
|
|
@ -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(())
|
||||
}))))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
if true then
|
||||
print("whats good")
|
||||
else
|
||||
print("oh no")
|
||||
while true do
|
||||
print("i am a loop!")
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue