🐛 bug: fix a bug in OP_CALL when b or c is 0
parent
8baea40e82
commit
b88735a61b
|
@ -160,6 +160,7 @@ pub fn parse_inst (buf: [u8; 4]) -> Option <Inst>
|
|||
0x4a => Inst::ForPrep (a, bx),
|
||||
0x4e => Inst::SetList (a, b, c, k),
|
||||
0x4f => Inst::Closure (a, bx),
|
||||
0x50 => unimplemented! ("OP_VARARG"),
|
||||
0x51 => Inst::VarArgPrep (a.into ()),
|
||||
0x52 => Inst::ExtraArg (ax),
|
||||
_ => return None,
|
||||
|
|
|
@ -82,7 +82,6 @@ fn lw_print (l: &mut State, num_args: usize) -> usize {
|
|||
}
|
||||
}
|
||||
println! ("");
|
||||
*l.reg_mut (0) = Value::from (1993);
|
||||
1
|
||||
}
|
||||
|
||||
|
@ -107,9 +106,39 @@ fn lw_string_format (l: &mut State, num_args: usize) -> usize {
|
|||
1
|
||||
}
|
||||
|
||||
fn lw_tonumber (l: &mut State, num_args: usize) -> usize {
|
||||
assert_eq! (num_args, 1, "tonumber only implemented for 1 argument");
|
||||
let output = match l.reg (0) {
|
||||
fn lw_table_concat (l: &mut State, num_args: usize) -> usize {
|
||||
assert_eq! (num_args, 2);
|
||||
|
||||
let s = {
|
||||
let t = l.reg (0).as_table ().unwrap ().borrow ();
|
||||
let joiner = l.reg (1).as_str ().unwrap ();
|
||||
|
||||
let mut s = String::new ();
|
||||
|
||||
for i in 0..t.length () {
|
||||
if i > 0 {
|
||||
s.push_str (joiner);
|
||||
}
|
||||
let x = t.get_int (i + 1);
|
||||
s.push_str (&format! ("{}", x));
|
||||
}
|
||||
s
|
||||
};
|
||||
*l.reg_mut (0) = Value::from (s);
|
||||
1
|
||||
}
|
||||
|
||||
fn lw_table_pack (l: &mut State, num_args: usize) -> usize {
|
||||
let mut v = vec! [];
|
||||
for i in 0..num_args {
|
||||
v.push (l.reg (u8::try_from (i).unwrap ()).clone ());
|
||||
}
|
||||
*l.reg_mut (0) = Value::from_iter (v.into_iter ());
|
||||
1
|
||||
}
|
||||
|
||||
fn tonumber (value: &Value) -> Value {
|
||||
match value {
|
||||
Value::Float (x) => Value::Float (*x),
|
||||
Value::Integer (x) => Value::Integer (*x),
|
||||
Value::String (x) => {
|
||||
|
@ -124,7 +153,12 @@ fn lw_tonumber (l: &mut State, num_args: usize) -> usize {
|
|||
}
|
||||
},
|
||||
_ => Value::Nil,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn lw_tonumber (l: &mut State, num_args: usize) -> usize {
|
||||
assert_eq! (num_args, 1, "tonumber only implemented for 1 argument");
|
||||
let output = tonumber (l.reg (0));
|
||||
*l.reg_mut (0) = output;
|
||||
1
|
||||
}
|
||||
|
@ -182,12 +216,18 @@ impl State {
|
|||
("format", Value::RsFunc (lw_string_format)),
|
||||
].into_iter ().map (|(k, v)| (k.to_string (), v));
|
||||
|
||||
let table = [
|
||||
("concat", Value::RsFunc (lw_table_concat)),
|
||||
("pack", Value::RsFunc (lw_table_pack)),
|
||||
].into_iter ().map (|(k, v)| (k.to_string (), v));
|
||||
|
||||
let env = [
|
||||
("arg", arg),
|
||||
("io", Value::from_iter (io.into_iter ())),
|
||||
("math", Value::from_iter (math.into_iter ())),
|
||||
("print", Value::RsFunc (lw_print)),
|
||||
("string", Value::from_iter (string.into_iter ())),
|
||||
("table", Value::from_iter (table.into_iter ())),
|
||||
("tonumber", Value::RsFunc (lw_tonumber)),
|
||||
].into_iter ().map (|(k, v)| (k.to_string (), v));
|
||||
|
||||
|
@ -336,7 +376,7 @@ impl State {
|
|||
});
|
||||
|
||||
let num_args = if b == 0 {
|
||||
self.top - a as usize
|
||||
self.top - new_offset
|
||||
}
|
||||
else {
|
||||
b - 1
|
||||
|
@ -385,7 +425,7 @@ impl State {
|
|||
upvalues: new_upvalues,
|
||||
});
|
||||
},
|
||||
Instruction::Concat (a, b) => {
|
||||
Instruction::Concat (_a, _b) => {
|
||||
unimplemented! ("OP_CONCAT")
|
||||
},
|
||||
Instruction::Div (a, b, c) => {
|
||||
|
|
|
@ -208,9 +208,30 @@ fn function_calls () {
|
|||
|
||||
vm.eval ("print (x ())").ok ();
|
||||
vm.eval ("x = function () return 5 end").ok ();
|
||||
|
||||
// Currently failing because I don't have a way to jump into a Lua
|
||||
// function that's no longer in the currently-executing chunk
|
||||
vm.eval ("print (x ())").ok ();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn function_returns () {
|
||||
let upvalues = crate::State::upvalues_from_args (vec! ["_exe_name".to_string ()].into_iter ());
|
||||
|
||||
let mut vm = crate::State::new (crate::Chunk::default (), upvalues);
|
||||
|
||||
assert_eq! (
|
||||
vm.eval ("return ((function () return 5 end)())").unwrap (),
|
||||
vec! [Value::from (5)]
|
||||
);
|
||||
assert_eq! (
|
||||
vm.eval ("return (math.sqrt (25))").unwrap (),
|
||||
vec! [Value::from (5.0)]
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn heap () {
|
||||
use std::{
|
||||
|
|
Loading…
Reference in New Issue