From 3eaf91760ee5a8fdb4cb73cf75c8ee97d54b8a7d Mon Sep 17 00:00:00 2001 From: Sofia Date: Fri, 20 Mar 2026 16:05:02 +0200 Subject: [PATCH] Fix various issues with upvalues --- examples/test.lua | 83 ++++++++++++++++++++++++++++++++++++++++++++--- src/compile.rs | 13 ++++++-- src/vm.rs | 12 +++++-- 3 files changed, 99 insertions(+), 9 deletions(-) diff --git a/examples/test.lua b/examples/test.lua index 17a9fc7..469c44d 100644 --- a/examples/test.lua +++ b/examples/test.lua @@ -1,4 +1,81 @@ -local table = {10, 20, 30} +global b = 5 + +function add(x) + return function (y) + x = x + 1 + b = b + 1 + return x + y, 1, 2, b + end +end + +function min(x, y) + local m = x + if y < x then + m = y + end + return m +end + + +function f(x, ...) + local b = {10, ..., add(10)(15)} + return x + 5, b +end + +global sometable = {} +sometable["hello"] = { 100, 150, add(10)(15) } +print(#sometable["hello"]) +sometable["hello"].there = "my dude" +print(sometable.hello.there) + +print(max(11.12345, 9)) +print(add(10)(15)) +print(add(10)(15)) +print(b) +print(min(11, 9)) +print(10 - 15) +print("hello there!") +print(true or 0) + +global value, table = f(10, 11, 12) + +print("hello") +for i=1,#table do + print(table[i]) + if i > 2 then + goto test + end +end +::test:: + +local test = table[1] +if test == 10 then + print("first") +elseif test == 11 then + print("second") +else + print("third") +end +print("after if/elseif/else") + + +local i = 0 +print("before") +while i < 10 do + i = i + 1 + print(i) +end +print("after while") + + +local i = 0 +print("before") +repeat + i = i + 1 + print(i) +until i >= 10 +print("after repeat") + function ipairs(t) print("inside!") @@ -13,8 +90,6 @@ function ipairs(t) end, "otus", "potus" end -print("before") for k, v in ipairs(table) do print(k, v) -end -print("after!") +end \ No newline at end of file diff --git a/src/compile.rs b/src/compile.rs index 3cea605..625ffce 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -1,4 +1,7 @@ -use std::collections::{HashMap, HashSet}; +use std::{ + collections::{HashMap, HashSet}, + num::IntErrorKind, +}; use crate::{ ast::{ @@ -882,11 +885,15 @@ impl Expression { scope.highest_upvalue + scope.register_counter.0 as i32; inner_scope.upvalues = scope.upvalues.clone(); + dbg!(&scope.highest_upvalue, &scope.register_counter.0); + for (name, reg) in &scope.locals { - let new_reg = *reg + (scope.highest_upvalue + 1) as u16; - inner_scope.upvalues.insert(name.clone(), new_reg); + let upvalue_reg = *reg + (scope.highest_upvalue + 1) as u16; + inner_scope.upvalues.insert(name.clone(), upvalue_reg); } + dbg!(&inner_scope.upvalues); + let instructions = block.compile(state, &mut inner_scope); state.prototypes.push(Prototype { instructions: process_pre_instrs(instructions), diff --git a/src/vm.rs b/src/vm.rs index 34b8fa3..a9c4e0a 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -597,6 +597,7 @@ impl Closure { return_registers: Vec::new(), top: 0, parameters: params, + to_close_upvalues: 0, } } @@ -621,6 +622,7 @@ pub struct ClosureRunner { return_registers: Vec, top: u16, parameters: Vec, + to_close_upvalues: u16, } #[derive(Clone, Debug)] @@ -666,7 +668,11 @@ impl ClosureRunner { .unwrap_or(-1); let mut upvalues = self.closure.upvalues.clone(); - for (reg, value) in &self.stack { + for (reg, value) in self + .stack + .iter() + .filter(|(r, _)| **r < self.to_close_upvalues) + { upvalues.insert(reg + (highest_upvalue + 1) as u16, value.clone()); } upvalues @@ -997,7 +1003,9 @@ impl ClosureRunner { _ => return Err(RuntimeError::TriedCallingNonFunction(value.clone())), } } - Instruction::Close(_) => {} + Instruction::Close(up_until) => { + self.to_close_upvalues = *up_until; + } Instruction::Closure(reg, protok) => { let upvalues = self.close_upvalues(); self.set_stack(