Fixing bug with if statement 'end'.

This commit is contained in:
paladin 2026-08-20 11:20:06 +01:00
parent 84c6e71646
commit d2f47604bf
2 changed files with 60 additions and 34 deletions

View file

@ -16,6 +16,8 @@ struct Reader<'a> { // 'cursor' states that follow through parsed source
white: bool, // Is the previous 'thing' whitespace?
}
type Error = String;
pub struct LoadError(String, Piece<()>); // Any error returned by a machine loading code
impl LoadError {
@ -25,8 +27,27 @@ impl LoadError {
fn from<T>(message: &str, piece: &Piece<T>) -> LoadError {
LoadError(message.to_string(), piece.unit())
}
fn msg(&self, reader: &Reader) -> String {
self.0.clone().add(reader.slice)
fn msg(&self, reader: &str) -> String {
let mut roll = format!("Error: {} {}",self.1.index,self.0);
let mut begin = self.1.index;
let mut end = self.1.index + self.1.width;
let mut count = 0;
for line in reader.lines() { // todo: improve this
count += 1;
if line.len() >= begin {
begin = 0;
roll = roll.add(format!("\n{}\t",count).as_str());
roll = roll.add(line);
} else {
begin -= line.len();
}
if line.len() > end {
break;
} else {
end -= line.len()
}
}
roll
}
}
@ -928,9 +949,12 @@ impl Parse for Statement {
))
} else {
let names = reader.take::<Vec<Piece<Name>>>()?.it;
reader.consume_white("=")?;
let expressions = reader.take::<Vec<Piece<Expression>>>()?.it;
*reader = *reader;
let expressions = if reader.consume_white("=").is_ok() {
reader.take::<Vec<Piece<Expression>>>()?.it
} else {
Vec::new()
};
*reader = *reader; // todo: what are these
Ok(Piece::from(
Statement::Declaration(names, expressions),
&start,
@ -2354,7 +2378,12 @@ impl Code {
}
impl Machine {
fn load(&mut self, source: &str) -> Result<Callable, LoadError> {
fn load(&mut self, source: &str) -> Result<Callable, Error> {
let parsed = match parse(source) {
Ok(parsed) => parsed,
Err(error) => return Err(error.msg(source))
};
let mut traversal = Traversal{contexts: vec![Context {
scopes: vec![Scope { // Dummy initial scope so the rest can start from index = 0
index: 0,
@ -2376,12 +2405,21 @@ impl Machine {
code: vec![],
},
}]};
parse(source)?.compile(&mut traversal)?;
match parsed.compile(&mut traversal) {
Ok(compiled) => compiled,
Err(error) => return Err(error.msg(source))
};
let prototype = match traversal.close_context() {
Ok(compiled) => compiled,
Err(error) => return Err(error.msg(source))
};
let global = self.global.clone();
let upvalues = vec![self.allocator.alloc(Upvalue::Heap(Value::Table(global)))];
Ok(Callable::Mars(self.allocator.alloc(Closure {
prototype: Rc::new(traversal.close_context()?),
prototype: Rc::new(prototype),
upvalues,
})))
}
@ -2624,18 +2662,17 @@ impl Machine {
}
Code::IteratorLoop(offset) => {
let len = needle.stack.len();
let function_index = len - 2;
let state_index = len - 1;
let var_index = len;
let function = needle.stack[function_index].value.clone();
let state = needle.stack[state_index].value.clone();
let var = needle.stack[var_index].value.clone();
let function = needle.stack[len - 2].value.clone();
let state = needle.stack[len - 1].value.clone();
let var = needle.stack[len].value.clone();
needle.push(function);
needle.push(var);
needle.push(state);
let offset = frame.offset;
frame = call(self, needle,frame,Index::try_from(needle.stack.len() - offset - 2).unwrap())?;
needle.stack.get(len + 2).unwrap_or(&Register::NIL);
needle.push(var);
let frame_offset = frame.offset;
frame = call(self, needle,frame,Index::try_from(needle.stack.len() - frame_offset - 2).unwrap())?;
if needle.stack.get(len + 1).unwrap_or(&Register::NIL).value == Value::Nil {
jump(&mut frame, offset);
};
}
}
frame.counter += 1;
@ -2670,6 +2707,9 @@ mod tests {
fn simple() {
let mut machine = Machine::new();
let result = machine.load(include_str!("tests/script.lua"));
println!("{:#?}", result);
match result {
Err(error) => println!("{}",error),
Ok(result) => println!("{:?}",result)
}
}
}

View file

@ -1,15 +1 @@
local two
do
local one
if something then
local three
print(something)
end
local four
if something2 then
end
end
local function bricked(hello, there)
end
do end