Skip to content

Commit 6633207

Browse files
committed
Fix test
1 parent f14505b commit 6633207

File tree

8 files changed

+59
-25
lines changed

8 files changed

+59
-25
lines changed

crates/luars/src/lib_registry.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,11 @@ pub fn get_arg(vm: &LuaVM, index: usize) -> Option<LuaValue> {
220220
let base_ptr = frame.base_ptr;
221221
let top = frame.top;
222222

223-
// Arguments are 0-indexed from caller's perspective
224-
// But register 0 is the function, so arg 0 is at register 1
225-
// get_arg(1) should return register[base_ptr + 1]
226-
// get_arg(2) should return register[base_ptr + 2]
227-
let reg_offset = index; // +1 to skip the function at register 0
223+
// Arguments use 1-based indexing (Lua convention)
224+
// Register 0 is the function itself
225+
// get_arg(1) returns register[base_ptr + 1] (first argument)
226+
// get_arg(2) returns register[base_ptr + 2] (second argument)
227+
let reg_offset = index;
228228
if reg_offset < top {
229229
let reg_index = base_ptr + reg_offset;
230230
if reg_index < vm.register_stack.len() {

crates/luars/src/lua_vm/dispatcher/control_instructions.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,15 @@ pub fn exec_return(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
126126
// CRITICAL: If frames are now empty, we're done - return control to caller
127127
// This prevents run() loop from trying to access empty frame
128128
if vm.frames.is_empty() {
129-
// Signal end of execution - return_values are already set
130-
return Err(vm.error("__VM_EXIT__".to_string()));
129+
// Save return values before exiting
130+
vm.return_values.clear();
131+
for i in 0..return_count {
132+
if base_ptr + a + i < vm.register_stack.len() {
133+
vm.return_values.push(vm.register_stack[base_ptr + a + i]);
134+
}
135+
}
136+
// Signal end of execution
137+
return Err(LuaError::Exit);
131138
}
132139

133140
Ok(())
@@ -1170,6 +1177,9 @@ pub fn exec_return0(vm: &mut LuaVM, _instr: u32) -> LuaResult<()> {
11701177

11711178
// Update caller's top to indicate 0 return values (for variable returns)
11721179
vm.current_frame_mut().top = result_reg; // No return values, so top = result_reg + 0
1180+
} else {
1181+
// If frames are empty, signal VM exit
1182+
return Err(LuaError::Exit);
11731183
}
11741184

11751185
Ok(())
@@ -1226,6 +1236,9 @@ pub fn exec_return1(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
12261236
if should_update_top {
12271237
vm.current_frame_mut().top = result_reg + 1;
12281238
}
1239+
} else {
1240+
// If frames are empty, signal VM exit
1241+
return Err(LuaError::Exit);
12291242
}
12301243

12311244
Ok(())

crates/luars/src/lua_vm/mod.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ impl LuaVM {
275275
if let Err(e) = dispatch_instruction(self, instr) {
276276
match e {
277277
LuaError::Yield => return Ok(LuaValue::nil()),
278+
LuaError::Exit => {
279+
// Normal exit when all frames are popped
280+
return Ok(LuaValue::nil());
281+
}
278282
_ => return Err(e),
279283
}
280284
}
@@ -523,7 +527,7 @@ impl LuaVM {
523527
self.return_values = args;
524528

525529
// Continue execution from where it yielded
526-
self.run().map(|v| vec![v])
530+
self.run().map(|_| self.return_values.clone())
527531
};
528532

529533
// Check if thread yielded by examining the result
@@ -564,9 +568,15 @@ impl LuaVM {
564568
thread.status = CoroutineStatus::Dead;
565569
Ok((true, values))
566570
}
567-
Err(e) => {
571+
Err(LuaError::Exit) => {
572+
// Normal exit - coroutine finished successfully
573+
thread.status = CoroutineStatus::Dead;
574+
Ok((true, thread.return_values.clone()))
575+
}
576+
Err(_) => {
568577
thread.status = CoroutineStatus::Dead;
569-
Ok((false, vec![self.create_string(&format!("{}", e))]))
578+
let error_msg = self.get_error_message().to_string();
579+
Ok((false, vec![self.create_string(&error_msg)]))
570580
}
571581
}
572582
};

crates/luars/src/stdlib/basic.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ fn lua_print(vm: &mut LuaVM) -> LuaResult<MultiValue> {
5959

6060
/// type(v) - Return the type of a value as a string
6161
fn lua_type(vm: &mut LuaVM) -> LuaResult<MultiValue> {
62-
let value = get_arg(vm, 0).unwrap_or(LuaValue::nil());
62+
let value = get_arg(vm, 1).unwrap_or(LuaValue::nil());
6363

6464
let type_name = match value.kind() {
6565
LuaValueKind::Nil => "nil",
@@ -78,10 +78,10 @@ fn lua_type(vm: &mut LuaVM) -> LuaResult<MultiValue> {
7878

7979
/// assert(v [, message]) - Raise error if v is false or nil
8080
fn lua_assert(vm: &mut LuaVM) -> LuaResult<MultiValue> {
81-
let condition = get_arg(vm, 0).unwrap_or(LuaValue::nil());
81+
let condition = get_arg(vm, 1).unwrap_or(LuaValue::nil());
8282

8383
if !condition.is_truthy() {
84-
let message = get_arg(vm, 1)
84+
let message = get_arg(vm, 2)
8585
.and_then(|v| v.as_lua_string().map(|s| s.as_str().to_string()))
8686
.unwrap_or_else(|| "assertion failed!".to_string());
8787
return Err(vm.error(message));
@@ -93,7 +93,7 @@ fn lua_assert(vm: &mut LuaVM) -> LuaResult<MultiValue> {
9393

9494
/// error(message) - Raise an error
9595
fn lua_error(vm: &mut LuaVM) -> LuaResult<MultiValue> {
96-
let message = get_arg(vm, 0)
96+
let message = get_arg(vm, 1)
9797
.map(|v| {
9898
vm.value_to_string(&v)
9999
.unwrap_or_else(|_| v.to_string_repr())
@@ -107,7 +107,7 @@ fn lua_error(vm: &mut LuaVM) -> LuaResult<MultiValue> {
107107
/// tonumber(e [, base]) - Convert to number
108108
fn lua_tonumber(vm: &mut LuaVM) -> LuaResult<MultiValue> {
109109
let value = require_arg(vm, 1, "tonumber")?;
110-
let base = get_arg(vm, 1).and_then(|v| v.as_integer()).unwrap_or(10);
110+
let base = get_arg(vm, 2).and_then(|v| v.as_integer()).unwrap_or(10);
111111

112112
if base < 2 || base > 36 {
113113
return Err(vm.error("bad argument #2 to 'tonumber' (base out of range)".to_string()));
@@ -250,13 +250,13 @@ fn lua_ipairs(vm: &mut LuaVM) -> LuaResult<MultiValue> {
250250
#[inline]
251251
fn ipairs_next(vm: &mut LuaVM) -> LuaResult<MultiValue> {
252252
// Ultra-fast path: direct argument access without validation
253-
let table_val = if let Some(val) = get_arg(vm, 0) {
253+
let table_val = if let Some(val) = get_arg(vm, 1) {
254254
val
255255
} else {
256256
return Err(vm.error("ipairs iterator: table expected".to_string()));
257257
};
258258

259-
let index_val = if let Some(val) = get_arg(vm, 1) {
259+
let index_val = if let Some(val) = get_arg(vm, 2) {
260260
val
261261
} else {
262262
return Err(vm.error("ipairs iterator: index expected".to_string()));
@@ -428,6 +428,16 @@ fn lua_setmetatable(vm: &mut LuaVM) -> LuaResult<MultiValue> {
428428
return Err(vm.error("Invalid table".to_string()));
429429
};
430430

431+
// Check if current metatable has __metatable field (protection)
432+
if let Some(current_mt) = table_ref.borrow().get_metatable() {
433+
if let Some(mt_table) = current_mt.as_lua_table() {
434+
let metatable_field = vm.create_string("__metatable");
435+
if let Some(_) = mt_table.borrow().raw_get(&metatable_field) {
436+
return Err(vm.error("cannot change a protected metatable".to_string()));
437+
}
438+
}
439+
}
440+
431441
match metatable.kind() {
432442
LuaValueKind::Nil => {
433443
table_ref.borrow_mut().set_metatable(None);
@@ -501,8 +511,8 @@ fn lua_rawlen(vm: &mut LuaVM) -> LuaResult<MultiValue> {
501511

502512
/// rawequal(v1, v2) - Equality without metamethods
503513
fn lua_rawequal(vm: &mut LuaVM) -> LuaResult<MultiValue> {
504-
let v1 = get_arg(vm, 0).unwrap_or(LuaValue::nil());
505-
let v2 = get_arg(vm, 1).unwrap_or(LuaValue::nil());
514+
let v1 = get_arg(vm, 1).unwrap_or(LuaValue::nil());
515+
let v2 = get_arg(vm, 2).unwrap_or(LuaValue::nil());
506516

507517
let result = v1 == v2;
508518
Ok(MultiValue::single(LuaValue::boolean(result)))

crates/luars/src/stdlib/math.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ fn math_modf(vm: &mut LuaVM) -> LuaResult<MultiValue> {
183183
}
184184

185185
fn math_rad(vm: &mut LuaVM) -> LuaResult<MultiValue> {
186-
let x = get_number(vm, 0, "math.rad")?;
186+
let x = get_number(vm, 1, "math.rad")?;
187187
Ok(MultiValue::single(LuaValue::float(x.to_radians())))
188188
}
189189

crates/luars/src/stdlib/string.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ fn string_format(vm: &mut LuaVM) -> LuaResult<MultiValue> {
239239
// Copy the format string to avoid holding a borrow on vm throughout the loop
240240
let format = format_str.as_str();
241241
let mut result = String::new();
242-
let mut arg_index = 1;
242+
let mut arg_index = 2; // Start from 2 since arg 1 is the format string
243243
let mut chars = format.chars().peekable();
244244

245245
while let Some(ch) = chars.next() {

crates/luars/src/stdlib/table.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ fn table_concat(vm: &mut LuaVM) -> LuaResult<MultiValue> {
3939
return Err(vm.error("Invalid table".to_string()));
4040
};
4141
let len = table_ref.borrow().len();
42-
let i = get_arg(vm, 2).and_then(|v| v.as_integer()).unwrap_or(1);
42+
let i = get_arg(vm, 3).and_then(|v| v.as_integer()).unwrap_or(1);
4343

44-
let j = get_arg(vm, 3)
44+
let j = get_arg(vm, 4)
4545
.and_then(|v| v.as_integer())
4646
.unwrap_or(len as i64);
4747

crates/luars_interpreter/src/bin/main.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,11 @@ fn execute_file(vm: &mut LuaVM, filename: &str) -> Result<(), String> {
161161

162162
match vm.compile(&code) {
163163
Ok(chunk) => {
164-
vm.execute(Rc::new(chunk)).map_err(|e| format!("{}", e))?;
164+
vm.execute(Rc::new(chunk))
165+
.map_err(|e| format!("{}: {}", e, vm.get_error_message()))?;
165166
Ok(())
166167
}
167-
Err(e) => Err(format!("{}: {}", filename, e)),
168+
Err(e) => Err(format!("{}: {}: {}", filename, e, vm.get_error_message())),
168169
}
169170
}
170171

0 commit comments

Comments
 (0)