🚧 wip: working on closures / upvalues
							parent
							
								
									05b1d6e1f7
								
							
						
					
					
						commit
						4da634a2aa
					
				
							
								
								
									
										17
									
								
								src/main.rs
								
								
								
								
							
							
						
						
									
										17
									
								
								src/main.rs
								
								
								
								
							|  | @ -14,12 +14,24 @@ fn main () { | |||
| 	let mut list_bytecode = false; | ||||
| 	let mut pipe_bytecode = false; | ||||
| 	let mut script = None; | ||||
| 	let mut breakpoints = vec![]; | ||||
| 	
 | ||||
| 	let mut args = std::env::args (); | ||||
| 	let exe_name = args.next ().unwrap (); | ||||
| 	
 | ||||
| 	while let Some (arg) = args.next () { | ||||
| 		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, | ||||
| 			"--pipe-bytecode" => pipe_bytecode = true, | ||||
| 			"--script" => script = Some (args.next ().unwrap ()), | ||||
|  | @ -52,10 +64,7 @@ fn main () { | |||
| 	
 | ||||
| 	let upvalues = State::upvalues_from_args ([exe_name].into_iter ().chain (args)); | ||||
| 	
 | ||||
| 	vm.breakpoints.push (state::Breakpoint { | ||||
| 		block_idx: 3, | ||||
| 		program_counter: 0, | ||||
| 	}); | ||||
| 	vm.breakpoints = breakpoints; | ||||
| 	
 | ||||
| 	vm.execute_chunk (&chunk, &upvalues); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										52
									
								
								src/state.rs
								
								
								
								
							
							
						
						
									
										52
									
								
								src/state.rs
								
								
								
								
							|  | @ -172,7 +172,9 @@ impl State { | |||
| 						Value::from (v_b + v_c) | ||||
| 					} | ||||
| 					else { | ||||
| 						Value::from (v_b.as_float ().unwrap () + v_c.as_float ().unwrap ()) | ||||
| 						let v_b = v_b.as_float ().unwrap_or_else (|| panic! ("{v_b}")); | ||||
| 						let v_c = v_c.as_float ().unwrap_or_else (|| panic! ("{v_c}")); | ||||
| 						Value::from (v_b + v_c) | ||||
| 					}; | ||||
| 					
 | ||||
| 					*self.reg_mut (*a) = sum; | ||||
|  | @ -195,7 +197,7 @@ impl State { | |||
| 					
 | ||||
| 					match v_a { | ||||
| 						Value::BogusClosure (rc) => { | ||||
| 							let idx = rc.idx; | ||||
| 							let idx = rc.borrow ().idx; | ||||
| 							
 | ||||
| 							let block_idx = frame.block_idx; | ||||
| 							let target_block = idx; | ||||
|  | @ -248,10 +250,17 @@ impl State { | |||
| 				Instruction::Closure (a, b) => { | ||||
| 					let b = usize::try_from (*b).unwrap (); | ||||
| 					
 | ||||
| 					*self.reg_mut (*a) = Value::BogusClosure (BogusClosure { | ||||
| 						idx: b + frame.block_idx + 1, | ||||
| 						upvalues: vec! [], | ||||
| 					}.into ()); | ||||
| 					let idx = b + frame.block_idx + 1; | ||||
| 					let block = &chunk.blocks [idx]; | ||||
| 					let upvalues = block.upvalues.iter ().map (|uv| { | ||||
| 						assert! (uv.in_stack, "off-stack upvalues not implemented"); | ||||
| 						self.reg (uv.idx).clone () | ||||
| 					}).collect (); | ||||
| 					
 | ||||
| 					*self.reg_mut (*a) = Value::from (BogusClosure { | ||||
| 						idx, | ||||
| 						upvalues, | ||||
| 					}); | ||||
| 				}, | ||||
| 				Instruction::EqI (a, sb, k_flag) => { | ||||
| 					if (self.reg (*a).as_int ().unwrap () == *sb as i64) != *k_flag 
 | ||||
|  | @ -324,7 +333,24 @@ impl State { | |||
| 					let b = usize::try_from (*b).unwrap (); | ||||
| 					let c = usize::try_from (*c).unwrap (); | ||||
| 					
 | ||||
| 					let table = upvalues.get (b).unwrap ().as_table ().expect ("GetTabUp only works on tables").borrow (); | ||||
| 					// If we're inside a closure, use its upvalues
 | ||||
| 					// instead of the chunk's upvalues
 | ||||
| 					
 | ||||
| 					let frame = self.stack.last ().unwrap (); | ||||
| 					let value = if frame.register_offset == 0 { | ||||
| 						upvalues.get (b).unwrap ().clone () | ||||
| 					} | ||||
| 					else if let Some (cell) = self.registers [frame.register_offset - 1].as_closure () 
 | ||||
| 					{ | ||||
| 						let closure = cell.borrow (); | ||||
| 						let value = closure.upvalues.get (b).unwrap (); | ||||
| 						value.clone () | ||||
| 					} | ||||
| 					else { | ||||
| 						upvalues.get (b).unwrap ().clone () | ||||
| 					}; | ||||
| 					
 | ||||
| 					let table = value.as_table ().expect ("GetTabUp only works on tables").borrow (); | ||||
| 					
 | ||||
| 					let key = match k.get (c).unwrap () { | ||||
| 						Value::String (s) => String::from (s.as_ref()), | ||||
|  | @ -345,14 +371,14 @@ impl State { | |||
| 				}, | ||||
| 				Instruction::GetUpVal (a, b) => { | ||||
| 					let this_func = self.stack.last ().unwrap ().register_offset - 1; | ||||
| 					let upvalues = match &self.registers [this_func] { | ||||
| 						Value::BogusClosure (rc) => &rc.upvalues, | ||||
| 					let closure = match &self.registers [this_func] { | ||||
| 						Value::BogusClosure (rc) => rc.clone (), | ||||
| 						_ => panic! ("Can't do GetUpVal outside a closure"), | ||||
| 					}; | ||||
| 					
 | ||||
| 					let b  = usize::try_from  (*b).unwrap (); | ||||
| 					
 | ||||
| 					let upvalue = match upvalues.get (b) { | ||||
| 					let upvalue = match closure.borrow ().upvalues.get (b) { | ||||
| 						Some (x) => x.clone (), | ||||
| 						None => { | ||||
| 							dbg! (chunk, &self); | ||||
|  | @ -430,7 +456,7 @@ impl State { | |||
| 					if *k { | ||||
| 						
 | ||||
| 						let closure_idx = match &self.registers [popped_frame.register_offset + a] { | ||||
| 							Value::BogusClosure (rc) => rc.idx, | ||||
| 							Value::BogusClosure (rc) => rc.borrow ().idx, | ||||
| 							_ => panic! ("Impossible"), | ||||
| 						}; | ||||
| 						
 | ||||
|  | @ -440,10 +466,10 @@ impl State { | |||
| 						
 | ||||
| 						let upvalues = self.registers [start_reg..start_reg+upvalue_count].iter ().cloned ().collect (); | ||||
| 						
 | ||||
| 						self.registers [a + popped_frame.register_offset] = Value::BogusClosure (BogusClosure { | ||||
| 						self.registers [a + popped_frame.register_offset] = Value::from (BogusClosure { | ||||
| 							idx: closure_idx, | ||||
| 							upvalues, | ||||
| 						}.into ()); | ||||
| 						}); | ||||
| 					} | ||||
| 					
 | ||||
| 					if self.debug_print { | ||||
|  |  | |||
							
								
								
									
										15
									
								
								src/value.rs
								
								
								
								
							
							
						
						
									
										15
									
								
								src/value.rs
								
								
								
								
							|  | @ -32,7 +32,7 @@ pub enum Value { | |||
| 	// These are all bogus, I haven't figured out how to implement
 | ||||
| 	// closures yet
 | ||||
| 	
 | ||||
| 	BogusClosure (Rc <BogusClosure>), | ||||
| 	BogusClosure (Rc <RefCell <BogusClosure>>), | ||||
| } | ||||
| 
 | ||||
| impl Default for Value { | ||||
|  | @ -58,6 +58,12 @@ impl fmt::Display for Value { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl From <BogusClosure> for Value { | ||||
| 	fn from (x: BogusClosure) -> Self { | ||||
| 		Self::BogusClosure (Rc::new (RefCell::new (x))) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl From <bool> for Value { | ||||
| 	fn from (x: bool) -> Self { | ||||
| 		Self::Boolean (x) | ||||
|  | @ -156,6 +162,13 @@ impl PartialEq <i64> for Value { | |||
| } | ||||
| 
 | ||||
| impl Value { | ||||
| 	pub fn as_closure (&self) -> Option <&Rc <RefCell <BogusClosure>>> { | ||||
| 		match self { | ||||
| 			Self::BogusClosure (x) => Some (x), | ||||
| 			_ => None, | ||||
| 		} | ||||
| 	} | ||||
| 	
 | ||||
| 	/// Coerces ints to float
 | ||||
| 	
 | ||||
| 	pub fn as_float (&self) -> Option <f64> { | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| local function make_closure (x) | ||||
| 	print (x) | ||||
| local function make_closure (t) | ||||
| 	return function (y) | ||||
| 		return x + y | ||||
| 		return t.x + y | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| local f = make_closure (11) | ||||
| local f = make_closure ({ x = 11 }) | ||||
| local t = {} | ||||
| local x = f (12) | ||||
| print (x) | ||||
| return x | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 _
						_