Compare commits
	
		
			2 Commits 
		
	
	
		
			8baea40e82
			...
			543cf58b1e
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						543cf58b1e | |
| 
							
							
								 | 
						b88735a61b | 
| 
						 | 
					@ -12,7 +12,3 @@ lunar_wave_vm = { path = "../lunar_wave_vm" }
 | 
				
			||||||
linker = "/usr/bin/clang"
 | 
					linker = "/usr/bin/clang"
 | 
				
			||||||
# Recommended for flamegraph
 | 
					# Recommended for flamegraph
 | 
				
			||||||
rustflags = ["-Clink-arg=-fuse-ld=lld", "-Clink-arg=-Wl,--no-rosegment"]
 | 
					rustflags = ["-Clink-arg=-fuse-ld=lld", "-Clink-arg=-Wl,--no-rosegment"]
 | 
				
			||||||
 | 
					 | 
				
			||||||
[profile.release]
 | 
					 | 
				
			||||||
# Recommended for profiling, e.g. flamegraph
 | 
					 | 
				
			||||||
debug = true
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -160,6 +160,7 @@ pub fn parse_inst (buf: [u8; 4]) -> Option <Inst>
 | 
				
			||||||
		0x4a => Inst::ForPrep (a, bx),
 | 
							0x4a => Inst::ForPrep (a, bx),
 | 
				
			||||||
		0x4e => Inst::SetList (a, b, c, k),
 | 
							0x4e => Inst::SetList (a, b, c, k),
 | 
				
			||||||
		0x4f => Inst::Closure (a, bx),
 | 
							0x4f => Inst::Closure (a, bx),
 | 
				
			||||||
 | 
							0x50 => unimplemented! ("OP_VARARG"),
 | 
				
			||||||
		0x51 => Inst::VarArgPrep (a.into ()),
 | 
							0x51 => Inst::VarArgPrep (a.into ()),
 | 
				
			||||||
		0x52 => Inst::ExtraArg (ax),
 | 
							0x52 => Inst::ExtraArg (ax),
 | 
				
			||||||
		_ => return None,
 | 
							_ => return None,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,6 @@ fn lw_print (l: &mut State, num_args: usize) -> usize {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	println! ("");
 | 
						println! ("");
 | 
				
			||||||
	*l.reg_mut (0) = Value::from (1993);
 | 
					 | 
				
			||||||
	1
 | 
						1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,9 +106,39 @@ fn lw_string_format (l: &mut State, num_args: usize) -> usize {
 | 
				
			||||||
	1
 | 
						1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn lw_tonumber (l: &mut State, num_args: usize) -> usize {
 | 
					fn lw_table_concat (l: &mut State, num_args: usize) -> usize {
 | 
				
			||||||
	assert_eq! (num_args, 1, "tonumber only implemented for 1 argument");
 | 
						assert_eq! (num_args, 2);
 | 
				
			||||||
	let output = match l.reg (0) {
 | 
						
 | 
				
			||||||
 | 
						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::Float (x) => Value::Float (*x),
 | 
				
			||||||
		Value::Integer (x) => Value::Integer (*x),
 | 
							Value::Integer (x) => Value::Integer (*x),
 | 
				
			||||||
		Value::String (x) => {
 | 
							Value::String (x) => {
 | 
				
			||||||
| 
						 | 
					@ -124,7 +153,12 @@ fn lw_tonumber (l: &mut State, num_args: usize) -> usize {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		_ => Value::Nil,
 | 
							_ => 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;
 | 
						*l.reg_mut (0) = output;
 | 
				
			||||||
	1
 | 
						1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -182,12 +216,18 @@ impl State {
 | 
				
			||||||
			("format", Value::RsFunc (lw_string_format)),
 | 
								("format", Value::RsFunc (lw_string_format)),
 | 
				
			||||||
		].into_iter ().map (|(k, v)| (k.to_string (), v));
 | 
							].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 = [
 | 
							let env = [
 | 
				
			||||||
			("arg", arg),
 | 
								("arg", arg),
 | 
				
			||||||
			("io", Value::from_iter (io.into_iter ())),
 | 
								("io", Value::from_iter (io.into_iter ())),
 | 
				
			||||||
			("math", Value::from_iter (math.into_iter ())),
 | 
								("math", Value::from_iter (math.into_iter ())),
 | 
				
			||||||
			("print", Value::RsFunc (lw_print)),
 | 
								("print", Value::RsFunc (lw_print)),
 | 
				
			||||||
			("string", Value::from_iter (string.into_iter ())),
 | 
								("string", Value::from_iter (string.into_iter ())),
 | 
				
			||||||
 | 
								("table", Value::from_iter (table.into_iter ())),
 | 
				
			||||||
			("tonumber", Value::RsFunc (lw_tonumber)),
 | 
								("tonumber", Value::RsFunc (lw_tonumber)),
 | 
				
			||||||
		].into_iter ().map (|(k, v)| (k.to_string (), v));
 | 
							].into_iter ().map (|(k, v)| (k.to_string (), v));
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					@ -336,7 +376,7 @@ impl State {
 | 
				
			||||||
						});
 | 
											});
 | 
				
			||||||
						
 | 
											
 | 
				
			||||||
						let num_args = if b == 0 {
 | 
											let num_args = if b == 0 {
 | 
				
			||||||
							self.top - a as usize
 | 
												self.top - new_offset
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						else {
 | 
											else {
 | 
				
			||||||
							b - 1
 | 
												b - 1
 | 
				
			||||||
| 
						 | 
					@ -385,7 +425,7 @@ impl State {
 | 
				
			||||||
					upvalues: new_upvalues,
 | 
										upvalues: new_upvalues,
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Instruction::Concat (a, b) => {
 | 
								Instruction::Concat (_a, _b) => {
 | 
				
			||||||
				unimplemented! ("OP_CONCAT")
 | 
									unimplemented! ("OP_CONCAT")
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Instruction::Div (a, b, c) => {
 | 
								Instruction::Div (a, b, c) => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -208,9 +208,30 @@ fn function_calls () {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	vm.eval ("print (x ())").ok ();
 | 
						vm.eval ("print (x ())").ok ();
 | 
				
			||||||
	vm.eval ("x = function () return 5 end").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 ();
 | 
						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]
 | 
					#[test]
 | 
				
			||||||
fn heap () {
 | 
					fn heap () {
 | 
				
			||||||
	use std::{
 | 
						use std::{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue