✅ another test
							parent
							
								
									eb5a1947a1
								
							
						
					
					
						commit
						8a2807f879
					
				|  | @ -1,2 +1,3 @@ | |||
| /luac.out | ||||
| /target | ||||
| /untracked | ||||
|  |  | |||
							
								
								
									
										187
									
								
								src/main.rs
								
								
								
								
							
							
						
						
									
										187
									
								
								src/main.rs
								
								
								
								
							|  | @ -1,7 +1,14 @@ | |||
| use std::collections::BTreeMap; | ||||
| 
 | ||||
| #[derive (Debug)] | ||||
| enum Instruction { | ||||
| 	VarArgPrep (i32), | ||||
| 	Add (u8, u8, u8), | ||||
| 	
 | ||||
| 	Call (u8, u8, u8), | ||||
| 	Closure (u8, i32), | ||||
| 	
 | ||||
| 	// Equals Constant?
 | ||||
| 	EqK (u8, u8, u8), | ||||
| 	
 | ||||
| 	// Get Table, Upvalue
 | ||||
| 	GetTabUp (u8, u8, u8), | ||||
|  | @ -9,9 +16,6 @@ enum Instruction { | |||
| 	// Get Immediate?
 | ||||
| 	GetI (u8, u8, u8), | ||||
| 	
 | ||||
| 	// Equals Constant?
 | ||||
| 	EqK (u8, u8, u8), | ||||
| 	
 | ||||
| 	// Jump
 | ||||
| 	Jmp (i32), | ||||
| 	
 | ||||
|  | @ -21,12 +25,15 @@ enum Instruction { | |||
| 	// Load Constant
 | ||||
| 	LoadK (u8, i32), | ||||
| 	
 | ||||
| 	// MetaMethod, Binary
 | ||||
| 	MmBin (u8, u8, u8), | ||||
| 	
 | ||||
| 	Call (u8, u8, u8), | ||||
| 	Closure (u8, i32), | ||||
| 	Move (u8, u8), | ||||
| 	
 | ||||
| 	// (A, B, _C) Return B - 1 registers starting with  A
 | ||||
| 	Return (u8, u8, u8), | ||||
| 	
 | ||||
| 	VarArgPrep (i32), | ||||
| } | ||||
| 
 | ||||
| #[derive (Clone, Debug, PartialEq)] | ||||
|  | @ -35,7 +42,6 @@ enum Value { | |||
| 	False, | ||||
| 	True, | ||||
| 	Float (f64), | ||||
| 	Integer (i64), | ||||
| 	String (String), | ||||
| 	
 | ||||
| 	// These are all bogus, I haven't figured out how to implement
 | ||||
|  | @ -66,7 +72,22 @@ impl From <&str> for Value { | |||
| 
 | ||||
| impl From <i32> for Value { | ||||
| 	fn from (x: i32) -> Self { | ||||
| 		Self::Integer (x as i64) | ||||
| 		Self::Float (f64::try_from (x).unwrap ()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl From <f64> for Value { | ||||
| 	fn from (x: f64) -> Self { | ||||
| 		Self::Float (x) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl Value { | ||||
| 	fn as_float (&self) -> Option <f64> { | ||||
| 		match self { | ||||
| 			Self::Float (x) => Some (*x), | ||||
| 			_ => None, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -92,6 +113,20 @@ impl Default for VirtualMachine { | |||
| } | ||||
| 
 | ||||
| impl VirtualMachine { | ||||
| 	fn upvalues_from_args <I: Iterator <Item = String>> (args: I) -> Vec <Value> | ||||
| 	{ | ||||
| 		let arg = args.map (|s| s.to_string ()).collect (); | ||||
| 		
 | ||||
| 		let env = BTreeMap::from_iter ([ | ||||
| 			("arg", Value::BogusArg (arg)), | ||||
| 			("print", Value::BogusPrint), | ||||
| 		].map (|(k, v)| (k.to_string (), v)).into_iter ()); | ||||
| 		
 | ||||
| 		vec! [ | ||||
| 			Value::BogusEnv (env), | ||||
| 		] | ||||
| 	} | ||||
| 	
 | ||||
| 	fn execute_chunk (&mut self, chunk: &Chunk, upvalues: &Vec <Value>) 
 | ||||
| 	-> Vec <Value> { | ||||
| 		let max_iters = 2000; | ||||
|  | @ -103,6 +138,16 @@ impl VirtualMachine { | |||
| 			let k = &chunk.constants; | ||||
| 			
 | ||||
| 			match instruction { | ||||
| 				Instruction::Add (a, b, c) => { | ||||
| 					let a = usize::try_from (*a).unwrap (); | ||||
| 					let b = usize::try_from (*b).unwrap (); | ||||
| 					let c = usize::try_from (*c).unwrap (); | ||||
| 					
 | ||||
| 					let v_b = r [b].as_float ().unwrap (); | ||||
| 					let v_c = r [c].as_float ().unwrap (); | ||||
| 					
 | ||||
| 					r [a] = (v_b + v_c).into (); | ||||
| 				}, | ||||
| 				Instruction::Call (a, b, c) => { | ||||
| 					// Take arguments from registers [a + 1, a + b)
 | ||||
| 					// Call the function in register [a]
 | ||||
|  | @ -112,14 +157,15 @@ impl VirtualMachine { | |||
| 					// 
 | ||||
| 					// e.g. CALL 0 2 1 mean "Call 0 with 1 argument, return 1 value", like for printing a constant
 | ||||
| 					
 | ||||
| 					// TODO: Only implement printing constants for now
 | ||||
| 					// TODO: Only implement printing values for now
 | ||||
| 					
 | ||||
| 					let a = usize::try_from (*a).unwrap (); | ||||
| 					
 | ||||
| 					assert_eq! (r.get (a).unwrap (), &Value::BogusPrint); | ||||
| 					assert_eq! (*b, 2); | ||||
| 					assert_eq! (*c, 1); | ||||
| 					
 | ||||
| 					println! ("{:?}", r [a + 1]); | ||||
| 					println! ("{:?}", r.get (a + 1).unwrap ()); | ||||
| 				}, | ||||
| 				Instruction::EqK (a, b, c_k) => { | ||||
| 					let a = usize::try_from (*a).unwrap (); | ||||
|  | @ -178,6 +224,26 @@ impl VirtualMachine { | |||
| 					
 | ||||
| 					r [a] = k [bx].clone (); | ||||
| 				}, | ||||
| 				Instruction::MmBin (a, b, c) => { | ||||
| 					let a = usize::try_from (*a).unwrap (); | ||||
| 					let b = usize::try_from (*b).unwrap (); | ||||
| 					
 | ||||
| 					let a = &r [a]; | ||||
| 					let b = &r [b]; | ||||
| 					
 | ||||
| 					if a.as_float().is_some() && b.as_float().is_some () { | ||||
| 						// No need for metamethods
 | ||||
| 					} | ||||
| 					else { | ||||
| 						panic! ("Not sure how to implememtn OP_MMBIN for these 2 values {a:?}, {b:?}"); | ||||
| 					} | ||||
| 				}, | ||||
| 				Instruction::Move (a, b) => { | ||||
| 					let a = usize::try_from (*a).unwrap (); | ||||
| 					let b = usize::try_from (*b).unwrap (); | ||||
| 					
 | ||||
| 					r [a] = r [b].clone (); | ||||
| 				}, | ||||
| 				Instruction::Return (a, b, _c) => { | ||||
| 					let a = usize::try_from (*a).unwrap (); | ||||
| 					let b = usize::try_from (*b).unwrap (); | ||||
|  | @ -185,7 +251,7 @@ impl VirtualMachine { | |||
| 					return self.registers [a..(a + b - 1)].to_vec(); | ||||
| 				}, | ||||
| 				Instruction::VarArgPrep (_) => (), | ||||
| 				_ => (), | ||||
| 				x => panic! ("Unimplemented instruction {x:?}"), | ||||
| 			} | ||||
| 			
 | ||||
| 			self.program_counter += 1; | ||||
|  | @ -196,45 +262,26 @@ impl VirtualMachine { | |||
| } | ||||
| 
 | ||||
| fn main() { | ||||
| 	let arg: Vec <_> = std::env::args ().collect (); | ||||
| 	
 | ||||
| 	let chunk = Chunk { | ||||
| 		instructions: vec! [ | ||||
| 			Instruction::VarArgPrep (0), | ||||
| 			Instruction::GetTabUp (1, 0, 0), | ||||
| 			Instruction::GetI (1, 1, 1), | ||||
| 			Instruction::EqK (1, 1, 0), | ||||
| 			Instruction::Jmp (6), | ||||
| 			Instruction::GetTabUp (1, 0, 2), | ||||
| 			Instruction::LoadK (2, 3), | ||||
| 			Instruction::Call (1, 2, 1), | ||||
| 			Instruction::LoadI (1, 0), | ||||
| 			Instruction::Return (1, 2, 1), | ||||
| 			Instruction::Jmp (5), | ||||
| 			Instruction::GetTabUp (1, 0, 2), | ||||
| 			Instruction::LoadK (2, 4), | ||||
| 			Instruction::Call (1, 2, 1), | ||||
| 			Instruction::LoadI (1, 1), | ||||
| 			Instruction::Return (1, 2, 1), | ||||
| 			Instruction::Return (1, 1, 1), | ||||
| 			Instruction::LoadK (0, 0), | ||||
| 			Instruction::LoadI (1, 3), | ||||
| 			Instruction::Add (2, 0, 1), | ||||
| 			Instruction::MmBin (0, 1, 6), | ||||
| 			Instruction::GetTabUp (3, 0, 1), | ||||
| 			Instruction::Move (4, 2), | ||||
| 			Instruction::Call (3, 2, 1), | ||||
| 			Instruction::Return (2, 2, 1), | ||||
| 			Instruction::Return (3, 1, 1), | ||||
| 		], | ||||
| 		constants: vec! [ | ||||
| 			"arg", | ||||
| 			"93", | ||||
| 			"print", | ||||
| 			"it's 93", | ||||
| 			"it's not 93", | ||||
| 		].into_iter ().map (|s| Value::from (s)).collect (), | ||||
| 			0.5.into (), | ||||
| 			"print".into (), | ||||
| 		], | ||||
| 	}; | ||||
| 	
 | ||||
| 	let env = BTreeMap::from_iter ([ | ||||
| 		("arg", Value::BogusArg (arg.clone ())), | ||||
| 		("print", Value::BogusPrint), | ||||
| 	].map (|(k, v)| (k.to_string (), v)).into_iter ()); | ||||
| 	
 | ||||
| 	let upvalues = vec! [ | ||||
| 		Value::BogusEnv (env), | ||||
| 	]; | ||||
| 	let upvalues = VirtualMachine::upvalues_from_args (std::env::args ()); | ||||
| 	
 | ||||
| 	let mut vm = VirtualMachine::default (); | ||||
| 	println! ("Returned: {:?}", vm.execute_chunk (&chunk, &upvalues)); | ||||
|  | @ -244,6 +291,48 @@ fn main() { | |||
| mod tests { | ||||
| 	use super::*; | ||||
| 	
 | ||||
| 	#[test] | ||||
| 	fn floats () { | ||||
| 		/* | ||||
| 		local a = 0.5 | ||||
| 		local b = 3 | ||||
| 
 | ||||
| 		local x = a + b | ||||
| 
 | ||||
| 		print (x) | ||||
| 		return x | ||||
| 		*/ | ||||
| 		
 | ||||
| 		let chunk = Chunk { | ||||
| 			instructions: vec! [ | ||||
| 				Instruction::VarArgPrep (0), | ||||
| 				Instruction::LoadK (0, 0), | ||||
| 				Instruction::LoadI (1, 3), | ||||
| 				Instruction::Add (2, 0, 1), | ||||
| 				Instruction::MmBin (0, 1, 6), | ||||
| 				Instruction::GetTabUp (3, 0, 1), | ||||
| 				Instruction::Move (4, 2), | ||||
| 				Instruction::Call (3, 2, 1), | ||||
| 				Instruction::Return (2, 2, 1), | ||||
| 				Instruction::Return (3, 1, 1), | ||||
| 			], | ||||
| 			constants: vec! [ | ||||
| 				0.5.into (), | ||||
| 				"print".into (), | ||||
| 			], | ||||
| 		}; | ||||
| 		
 | ||||
| 		for (arg, expected) in [ | ||||
| 			(vec! ["_exe_name"], vec! [3.5.into ()]), | ||||
| 		] { | ||||
| 			let mut vm = VirtualMachine::default (); | ||||
| 			let upvalues = VirtualMachine::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ())); | ||||
| 			let actual = vm.execute_chunk (&chunk, &upvalues); | ||||
| 			
 | ||||
| 			assert_eq! (actual, expected); | ||||
| 		} | ||||
| 	} | ||||
| 	
 | ||||
| 	#[test] | ||||
| 	fn is_93 () { | ||||
| 		/* | ||||
|  | @ -290,18 +379,8 @@ mod tests { | |||
| 			(vec! ["_exe_name", "93"], vec! [0.into ()]), | ||||
| 			(vec! ["_exe_name", "94"], vec! [1.into ()]), | ||||
| 		] { | ||||
| 			let arg = arg.into_iter ().map (|s| s.to_string ()).collect (); | ||||
| 			
 | ||||
| 			let env = BTreeMap::from_iter ([ | ||||
| 				("arg", Value::BogusArg (arg)), | ||||
| 				("print", Value::BogusPrint), | ||||
| 			].map (|(k, v)| (k.to_string (), v)).into_iter ()); | ||||
| 			
 | ||||
| 			let upvalues = vec! [ | ||||
| 				Value::BogusEnv (env), | ||||
| 			]; | ||||
| 			
 | ||||
| 			let mut vm = VirtualMachine::default (); | ||||
| 			let upvalues = VirtualMachine::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ())); | ||||
| 			let actual = vm.execute_chunk (&chunk, &upvalues); | ||||
| 			
 | ||||
| 			assert_eq! (actual, expected); | ||||
|  |  | |||
|  | @ -0,0 +1,7 @@ | |||
| local a = 0.5 | ||||
| local b = 3 | ||||
| 
 | ||||
| local x = a + b | ||||
| 
 | ||||
| print (x) | ||||
| return x | ||||
		Loading…
	
		Reference in New Issue
	
	 _
						_