Compare commits
	
		
			No commits in common. "57486f7a65b2aae06ee7f38dfe05e8ff253f3ca4" and "b639d02027358b130efa952ae76d05e5ac7f54a8" have entirely different histories. 
		
	
	
		
			57486f7a65
			...
			b639d02027
		
	
		|  | @ -251,25 +251,19 @@ pub fn parse_block <R: Read> (rdr: &mut R, blocks: &mut Vec <Block>) | ||||||
| 	} | 	} | ||||||
| 	
 | 	
 | ||||||
| 	let upvalue_count = parse_int (rdr).unwrap () as usize; | 	let upvalue_count = parse_int (rdr).unwrap () as usize; | ||||||
| 	let mut upvalues = Vec::with_capacity (upvalue_count); | 	
 | ||||||
| 	for _ in 0..upvalue_count { | 	for _ in 0..upvalue_count { | ||||||
| 		let in_stack = parse_byte (rdr).unwrap () == 1; | 		// Just ignore these
 | ||||||
| 		let idx = parse_byte (rdr).unwrap (); |  | ||||||
| 		let kind = parse_byte (rdr).unwrap (); |  | ||||||
| 		
 | 		
 | ||||||
| 		let upvalue = crate::state::Upvalue { | 		for _ in 0..3 { | ||||||
| 			in_stack, | 			parse_byte (rdr).unwrap (); | ||||||
| 			idx, | 		} | ||||||
| 			kind, |  | ||||||
| 		}; |  | ||||||
| 		
 |  | ||||||
| 		upvalues.push (upvalue); |  | ||||||
| 	} | 	} | ||||||
| 	
 | 	
 | ||||||
| 	blocks.push (Block { | 	blocks.push (Block { | ||||||
| 		constants, | 		constants, | ||||||
| 		instructions, | 		instructions, | ||||||
| 		upvalues, | 		upvalue_count, | ||||||
| 	}); | 	}); | ||||||
| 	
 | 	
 | ||||||
| 	// Recursion
 | 	// Recursion
 | ||||||
|  |  | ||||||
							
								
								
									
										74
									
								
								src/main.rs
								
								
								
								
							
							
						
						
									
										74
									
								
								src/main.rs
								
								
								
								
							|  | @ -14,24 +14,12 @@ fn main () { | ||||||
| 	let mut list_bytecode = false; | 	let mut list_bytecode = false; | ||||||
| 	let mut pipe_bytecode = false; | 	let mut pipe_bytecode = false; | ||||||
| 	let mut script = None; | 	let mut script = None; | ||||||
| 	let mut breakpoints = vec![]; |  | ||||||
| 	
 | 	
 | ||||||
| 	let mut args = std::env::args (); | 	let mut args = std::env::args (); | ||||||
| 	let exe_name = args.next ().unwrap (); | 	let exe_name = args.next ().unwrap (); | ||||||
| 	
 | 	
 | ||||||
| 	while let Some (arg) = args.next () { | 	while let Some (arg) = args.next () { | ||||||
| 		match arg.as_str () { | 		match arg.as_str () { | ||||||
| 			"--break" => { |  | ||||||
| 				let s = args.next ().unwrap (); |  | ||||||
| 				let (block_idx, program_counter) = s.split_once (":").unwrap (); |  | ||||||
| 				let block_idx = str::parse (block_idx).unwrap (); |  | ||||||
| 				let program_counter = str::parse (program_counter).unwrap (); |  | ||||||
| 				
 |  | ||||||
| 				breakpoints.push (state::Breakpoint { |  | ||||||
| 					block_idx, |  | ||||||
| 					program_counter, |  | ||||||
| 				}); |  | ||||||
| 			}, |  | ||||||
| 			"--list-bytecode" => list_bytecode = true, | 			"--list-bytecode" => list_bytecode = true, | ||||||
| 			"--pipe-bytecode" => pipe_bytecode = true, | 			"--pipe-bytecode" => pipe_bytecode = true, | ||||||
| 			"--script" => script = Some (args.next ().unwrap ()), | 			"--script" => script = Some (args.next ().unwrap ()), | ||||||
|  | @ -57,63 +45,17 @@ fn main () { | ||||||
| 		dbg! (&chunk); | 		dbg! (&chunk); | ||||||
| 	} | 	} | ||||||
| 	
 | 	
 | ||||||
| 	let upvalues = State::upvalues_from_args ([exe_name].into_iter ().chain (args)); | 	let mut vm = State::default (); | ||||||
| 	
 | 	if std::env::var("LUA_DEBUG").is_ok() { | ||||||
| 	let mut vm = State::new (&chunk, &upvalues); |  | ||||||
| 	if std::env::var("LWVM_DEBUG").is_ok() { |  | ||||||
| 		vm.debug_print = true; | 		vm.debug_print = true; | ||||||
| 	} | 	} | ||||||
| 	
 | 	
 | ||||||
| 	let max_iters = 2000; | 	let upvalues = State::upvalues_from_args ([exe_name].into_iter ().chain (args)); | ||||||
| 	let mut in_break = false; |  | ||||||
| 	let mut last_input = String::new (); |  | ||||||
| 	
 | 	
 | ||||||
| 	for _ in 0..max_iters { | 	vm.breakpoints.push (state::Breakpoint { | ||||||
| 		if in_break || breakpoints.iter ().any (|bp| vm.at_breakpoint (bp)) { | 		block_idx: 3, | ||||||
| 			in_break = true; | 		program_counter: 0, | ||||||
| 			dbg! (&vm.stack); | 	}); | ||||||
| 			
 |  | ||||||
| 			let mut input = Default::default (); |  | ||||||
| 			std::io::stdin ().read_line (&mut input).unwrap (); |  | ||||||
| 			
 |  | ||||||
| 			let input = if input == "" { |  | ||||||
| 				&last_input |  | ||||||
| 			} |  | ||||||
| 			else { |  | ||||||
| 				last_input = input; |  | ||||||
| 				&last_input |  | ||||||
| 			}; |  | ||||||
| 			
 |  | ||||||
| 			match input.as_str ().trim_end () { |  | ||||||
| 				"c" => in_break = false, |  | ||||||
| 				"q" => return, |  | ||||||
| 				"registers" => { |  | ||||||
| 					dbg! (&vm.registers); |  | ||||||
| 					continue; |  | ||||||
| 				} |  | ||||||
| 				"s" => { |  | ||||||
| 					match vm.step () { |  | ||||||
| 						None => (), |  | ||||||
| 						Some (state::StepOutput::ChunkReturned (x)) => { |  | ||||||
| 							dbg! (x); |  | ||||||
| 							return; |  | ||||||
| 						}, |  | ||||||
| 					} |  | ||||||
| 					continue; |  | ||||||
| 				}, |  | ||||||
| 				x => { dbg! (x); }, |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		
 |  | ||||||
| 		match vm.step () { |  | ||||||
| 			None => (), |  | ||||||
| 			Some (state::StepOutput::ChunkReturned (x)) => { |  | ||||||
| 				dbg! (x); |  | ||||||
| 				return; |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	
 | 	
 | ||||||
| 	dbg! (vm); | 	vm.execute_chunk (&chunk, &upvalues); | ||||||
| 	panic! ("Hit max iterations before block returned"); |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										1002
									
								
								src/state.rs
								
								
								
								
							
							
						
						
									
										1002
									
								
								src/state.rs
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										33
									
								
								src/tests.rs
								
								
								
								
							
							
						
						
									
										33
									
								
								src/tests.rs
								
								
								
								
							|  | @ -23,9 +23,9 @@ fn calculate_hash<T: Hash>(t: &T) -> u64 { | ||||||
| /// and returns the output
 | /// and returns the output
 | ||||||
| 
 | 
 | ||||||
| fn run_chunk (args: &[&str], chunk: &Chunk) -> Vec <Value> { | fn run_chunk (args: &[&str], chunk: &Chunk) -> Vec <Value> { | ||||||
|  | 	let mut vm = State::default (); | ||||||
| 	let upvalues = State::upvalues_from_args (args.into_iter ().map (|s| s.to_string ())); | 	let upvalues = State::upvalues_from_args (args.into_iter ().map (|s| s.to_string ())); | ||||||
| 	let mut vm = State::new (chunk, &upvalues); | 	vm.execute_chunk (chunk, &upvalues) | ||||||
| 	vm.execute_chunk (&[]) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Takes arguments and Lua bytecode, loads it, runs it,
 | /// Takes arguments and Lua bytecode, loads it, runs it,
 | ||||||
|  | @ -93,7 +93,7 @@ fn bools () { | ||||||
| 					"arg".into (), | 					"arg".into (), | ||||||
| 					"print".into (), | 					"print".into (), | ||||||
| 				], | 				], | ||||||
| 				upvalues: vec! [], | 				upvalue_count: 1, | ||||||
| 			}, | 			}, | ||||||
| 			Block { | 			Block { | ||||||
| 				instructions: vec! [ | 				instructions: vec! [ | ||||||
|  | @ -107,7 +107,7 @@ fn bools () { | ||||||
| 					Inst::Return0, | 					Inst::Return0, | ||||||
| 				], | 				], | ||||||
| 				constants: vec! [], | 				constants: vec! [], | ||||||
| 				upvalues: vec! [], | 				upvalue_count: 0, | ||||||
| 			}, | 			}, | ||||||
| 		], | 		], | ||||||
| 	}; | 	}; | ||||||
|  | @ -118,9 +118,10 @@ fn bools () { | ||||||
| 	] { | 	] { | ||||||
| 		let expected: Vec <Value> = expected; | 		let expected: Vec <Value> = expected; | ||||||
| 		
 | 		
 | ||||||
|  | 		let mut vm = State::default (); | ||||||
| 		let upvalues = State::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ())); | 		let upvalues = State::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ())); | ||||||
| 		let mut vm = State::new (&chunk, &upvalues); | 		
 | ||||||
| 		let actual = vm.execute_chunk (&[]); | 		let actual = vm.execute_chunk (&chunk, &upvalues); | ||||||
| 		assert_eq! (actual, expected); | 		assert_eq! (actual, expected); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -163,7 +164,7 @@ fn floats () { | ||||||
| 			0.5.into (), | 			0.5.into (), | ||||||
| 			"print".into (), | 			"print".into (), | ||||||
| 		], | 		], | ||||||
| 		upvalues: vec! [], | 		upvalue_count: 1, | ||||||
| 	}; | 	}; | ||||||
| 	let chunk = Chunk { | 	let chunk = Chunk { | ||||||
| 		blocks: vec! [block], | 		blocks: vec! [block], | ||||||
|  | @ -174,9 +175,9 @@ fn floats () { | ||||||
| 		(vec! ["_exe_name", " "], vec! [3.5.into ()]), | 		(vec! ["_exe_name", " "], vec! [3.5.into ()]), | ||||||
| 	] { | 	] { | ||||||
| 		let expected: Vec <Value> = expected; | 		let expected: Vec <Value> = expected; | ||||||
|  | 		let mut vm = State::default (); | ||||||
| 		let upvalues = State::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ())); | 		let upvalues = State::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ())); | ||||||
| 		let mut vm = State::new (&chunk, &upvalues); | 		let actual = vm.execute_chunk (&chunk, &upvalues); | ||||||
| 		let actual = vm.execute_chunk (&[]); |  | ||||||
| 		
 | 		
 | ||||||
| 		assert_eq! (actual, expected); | 		assert_eq! (actual, expected); | ||||||
| 	} | 	} | ||||||
|  | @ -184,21 +185,19 @@ fn floats () { | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn fma () { | fn fma () { | ||||||
| 	let source = include_bytes! ("../test_vectors/fma.lua"); | 	let bytecode = include_bytes! ("../test_vectors/fma.luac"); | ||||||
| 	let bytecode = &crate::loader::compile_bytecode_from_stdin (source.to_vec ()); | 	let mut rdr = std::io::Cursor::new (bytecode); | ||||||
| 	let chunk = crate::loader::parse_chunk_from_bytes (bytecode).unwrap (); | 	let file = crate::loader::parse_chunk (&mut rdr).unwrap (); | ||||||
| 	assert_eq! (chunk.blocks.len (), 5); | 	assert_eq! (file.blocks.len (), 4); | ||||||
| 	
 |  | ||||||
| 	assert_eq! (chunk.blocks [3].upvalues.len (), 2); |  | ||||||
| 	
 | 	
 | ||||||
| 	for (arg, expected) in [ | 	for (arg, expected) in [ | ||||||
| 		(vec! ["_exe_name"], vec! [122.into ()]), | 		(vec! ["_exe_name"], vec! [122.into ()]), | ||||||
| 		(vec! ["_exe_name"], vec! [122.into ()]), | 		(vec! ["_exe_name"], vec! [122.into ()]), | ||||||
| 	] { | 	] { | ||||||
| 		let expected: Vec <Value> = expected; | 		let expected: Vec <Value> = expected; | ||||||
|  | 		let mut vm = State::default (); | ||||||
| 		let upvalues = State::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ())); | 		let upvalues = State::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ())); | ||||||
| 		let mut vm = State::new (&chunk, &upvalues); | 		let actual = vm.execute_chunk (&file, &upvalues); | ||||||
| 		let actual = vm.execute_chunk (&[]); |  | ||||||
| 		
 | 		
 | ||||||
| 		assert_eq! (actual, expected); | 		assert_eq! (actual, expected); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
							
								
								
									
										47
									
								
								src/value.rs
								
								
								
								
							
							
						
						
									
										47
									
								
								src/value.rs
								
								
								
								
							|  | @ -11,12 +11,11 @@ use std::{ | ||||||
| 
 | 
 | ||||||
| #[derive (Debug, Eq, PartialEq)] | #[derive (Debug, Eq, PartialEq)] | ||||||
| pub struct BogusClosure { | pub struct BogusClosure { | ||||||
| 	// I'm pretty sure this should be absolute?
 |  | ||||||
| 	pub idx: usize, | 	pub idx: usize, | ||||||
| 	pub upvalues: Vec <Value>, | 	pub upvalues: Vec <Value>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive (Clone, PartialEq)] | #[derive (Clone, Debug, PartialEq)] | ||||||
| pub enum Value { | pub enum Value { | ||||||
| 	Nil, | 	Nil, | ||||||
| 	Boolean (bool), | 	Boolean (bool), | ||||||
|  | @ -33,24 +32,7 @@ pub enum Value { | ||||||
| 	// These are all bogus, I haven't figured out how to implement
 | 	// These are all bogus, I haven't figured out how to implement
 | ||||||
| 	// closures yet
 | 	// closures yet
 | ||||||
| 	
 | 	
 | ||||||
| 	BogusClosure (Rc <RefCell <BogusClosure>>), | 	BogusClosure (Rc <BogusClosure>), | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl fmt::Debug for Value { |  | ||||||
| 	fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result { |  | ||||||
| 		match self { |  | ||||||
| 			Value::Nil => write! (f, "nil"), |  | ||||||
| 			Value::Boolean (false) => write! (f, "false"), |  | ||||||
| 			Value::Boolean (true) => write! (f, "true"), |  | ||||||
| 			Value::Float (x) => write! (f, "{:?}", x), |  | ||||||
| 			Value::Integer (x) => write! (f, "{}", x), |  | ||||||
| 			Value::RsFunc (x) => write! (f, "function: {:?}", x), |  | ||||||
| 			Value::String (s) => write! (f, "\"{}\"", s), |  | ||||||
| 			Value::Table (t) => write! (f, "{:?}", t.borrow ()), |  | ||||||
| 			
 |  | ||||||
| 			Value::BogusClosure (x) => write! (f, "{:?}", x.borrow ()), |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Default for Value { | impl Default for Value { | ||||||
|  | @ -71,17 +53,11 @@ impl fmt::Display for Value { | ||||||
| 			Value::String (s) => write! (f, "{}", s), | 			Value::String (s) => write! (f, "{}", s), | ||||||
| 			Value::Table (t) => write! (f, "table: {:?}", std::rc::Rc::as_ptr (t)), | 			Value::Table (t) => write! (f, "table: {:?}", std::rc::Rc::as_ptr (t)), | ||||||
| 			
 | 			
 | ||||||
| 			Value::BogusClosure (x) => write! (f, "BogusClosure: {:?}", std::rc::Rc::as_ptr (x)), | 			Value::BogusClosure (_) => write! (f, "BogusClosure"), | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl From <BogusClosure> for Value { |  | ||||||
| 	fn from (x: BogusClosure) -> Self { |  | ||||||
| 		Self::BogusClosure (Rc::new (RefCell::new (x))) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl From <bool> for Value { | impl From <bool> for Value { | ||||||
| 	fn from (x: bool) -> Self { | 	fn from (x: bool) -> Self { | ||||||
| 		Self::Boolean (x) | 		Self::Boolean (x) | ||||||
|  | @ -180,13 +156,6 @@ impl PartialEq <i64> for Value { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Value { | impl Value { | ||||||
| 	pub fn as_closure (&self) -> Option <&Rc <RefCell <BogusClosure>>> { |  | ||||||
| 		match self { |  | ||||||
| 			Self::BogusClosure (x) => Some (x), |  | ||||||
| 			_ => None, |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	
 |  | ||||||
| 	/// Coerces ints to float
 | 	/// Coerces ints to float
 | ||||||
| 	
 | 	
 | ||||||
| 	pub fn as_float (&self) -> Option <f64> { | 	pub fn as_float (&self) -> Option <f64> { | ||||||
|  | @ -231,20 +200,12 @@ impl Value { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive (Default, Eq, PartialEq)] | #[derive (Debug, Default, Eq, PartialEq)] | ||||||
| pub struct Table { | pub struct Table { | ||||||
| 	array: Vec <Value>, | 	array: Vec <Value>, | ||||||
| 	hash: HashMap <Value, Value>, | 	hash: HashMap <Value, Value>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl fmt::Debug for Table { |  | ||||||
| 	fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result { |  | ||||||
| 		write! (f, "Table {:#?}", self.hash)?; |  | ||||||
| 		
 |  | ||||||
| 		Ok (()) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Table { | impl Table { | ||||||
| 	fn get_inner (&self, key: &Value) -> Value { | 	fn get_inner (&self, key: &Value) -> Value { | ||||||
| 		self.hash.get (key).cloned ().unwrap_or_default () | 		self.hash.get (key).cloned ().unwrap_or_default () | ||||||
|  |  | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| local function make_closure (t) | local function make_closure (x) | ||||||
|  | 	print (x) | ||||||
| 	return function (y) | 	return function (y) | ||||||
| 		return t.x + y | 		return x + y | ||||||
| 	end | 	end | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| local f = make_closure ({ x = 11 }) | local f = make_closure (11) | ||||||
| local t = {} |  | ||||||
| local x = f (12) | local x = f (12) | ||||||
| print (x) | print (x) | ||||||
| return x | return x | ||||||
|  |  | ||||||
|  | @ -1,7 +1,5 @@ | ||||||
| -- This one fails :( I haven't implemented closures properly yet. | -- This one fails :( I haven't implemented closures properly yet. | ||||||
| 
 | 
 | ||||||
| local ii = "bogus" |  | ||||||
| 
 |  | ||||||
| local function add (aa, bb) | local function add (aa, bb) | ||||||
| 	return aa + bb | 	return aa + bb | ||||||
| end | end | ||||||
|  | @ -14,13 +12,6 @@ local function fma (ee, ff, gg) | ||||||
| 	return add (mul (ee, ff), gg) | 	return add (mul (ee, ff), gg) | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| local function run () | local hh = fma (10, 11, 12) | ||||||
| 	local hh = fma (10, 11, 12) | print (hh) | ||||||
| 	print (hh) |  | ||||||
| 	return hh |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| local hh = run () |  | ||||||
| print (ii) |  | ||||||
| 
 |  | ||||||
| return hh | return hh | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue