| 
						
						
						
					 | 
					 | 
					@ -1,4 +1,4 @@ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use sexp::{Atom, Sexp, SourcePosition, atom_qs, atom_s}; | 
					 | 
					 | 
					 | 
					use sexp::{Atom, Sexp, SourcePosition, atom_qs}; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::asm::data::literal::{RoutineName}; | 
					 | 
					 | 
					 | 
					use crate::asm::data::literal::{RoutineName}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::asm::data::reg::parse_reg; | 
					 | 
					 | 
					 | 
					use crate::asm::data::reg::parse_reg; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -452,7 +452,7 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if args.is_empty() { | 
					 | 
					 | 
					 | 
					            if args.is_empty() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                sexp::list(&[A("spawn"), A(handle), A(proc)]) | 
					 | 
					 | 
					 | 
					                sexp::list(&[A("spawn"), A(handle), A(proc)]) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            } else { | 
					 | 
					 | 
					 | 
					            } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                let mut v = vec![A("spawn"), A(handle), A(proc)]; | 
					 | 
					 | 
					 | 
					                let mut v = vec![A("spawn"), A(handle), A(&proc.name)]; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                v.extend(args.iter().map(|r| A(r))); | 
					 | 
					 | 
					 | 
					                v.extend(args.iter().map(|r| A(r))); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                sexp::list(&v) | 
					 | 
					 | 
					 | 
					                sexp::list(&v) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            } | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -473,10 +473,15 @@ mod test { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    use sexp::SourcePosition; | 
					 | 
					 | 
					 | 
					    use sexp::SourcePosition; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    use crate::asm::parse::{parse_instructions, ParserContext}; | 
					 | 
					 | 
					 | 
					    use crate::asm::parse::{parse_instructions, ParserContext, ParserState}; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    use crate::asm::parse::sexp_expect::expect_list; | 
					 | 
					 | 
					 | 
					    use crate::asm::parse::sexp_expect::expect_list; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    use crate::builtin::BuiltinOps; | 
					 | 
					 | 
					 | 
					    use crate::builtin::BuiltinOps; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    use crate::module::OpTrait; | 
					 | 
					 | 
					 | 
					    use crate::module::OpTrait; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    use std::cell::RefCell; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    use std::sync::Arc; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    use crate::runtime::run_thread::{ThreadInfo, ThreadToken, RunState}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    use crate::runtime::program::Program; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    use crate::runtime::frame::REG_COUNT; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    #[test] | 
					 | 
					 | 
					 | 
					    #[test] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    fn roundtrip() { | 
					 | 
					 | 
					 | 
					    fn roundtrip() { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -562,13 +567,42 @@ mod test { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let parser = BuiltinOps::new(); | 
					 | 
					 | 
					 | 
					        let parser = BuiltinOps::new(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let parsers = &[parser]; | 
					 | 
					 | 
					 | 
					        let parsers = Arc::new(vec![parser]); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let ti = Arc::new(ThreadInfo { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            id: ThreadToken(0), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            uniq: Default::default(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            program: Program::new(vec![], parsers.clone()).unwrap(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            cycle_time: Default::default(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            scheduler_interval: Default::default(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            extensions: parsers.clone(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let pcx = ParserContext { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            parsers: &parsers, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            state: RefCell::new(ParserState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                reg_aliases: Default::default(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                reg_alias_stack: vec![], | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                global_reg_aliases: Default::default(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                constants: Default::default(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                // This is a fake thread to pass to constant expressions when evaluating them.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                // This allows to evaluate nearly all instructions at compile time.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                const_eval: RunState { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    thread_info: ti.clone(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    cr: Default::default(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    parked: Default::default(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    global_regs: [0; REG_COUNT], | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    ext_data: Default::default(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    cr_deadline: None | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                const_eval_ti: ti.clone(), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                parsing_expr: false | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            }), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        }; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for (sample, expected) in samples { | 
					 | 
					 | 
					 | 
					        for (sample, expected) in samples { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let pcx = ParserContext { | 
					 | 
					 | 
					 | 
					            pcx.state.borrow_mut().reset(); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                parsers, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                state: Default::default(), | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            }; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            println!("Parse: {}", sample); | 
					 | 
					 | 
					 | 
					            println!("Parse: {}", sample); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -587,10 +621,7 @@ mod test { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            assert_eq!(expected, exported); | 
					 | 
					 | 
					 | 
					            assert_eq!(expected, exported); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            println!(" - 2nd cycle"); | 
					 | 
					 | 
					 | 
					            println!(" - 2nd cycle"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let pcx = ParserContext { | 
					 | 
					 | 
					 | 
					            pcx.state.borrow_mut().reset(); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                parsers, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                state: Default::default(), | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            }; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            /* second cycle, nothing should change */ | 
					 | 
					 | 
					 | 
					            /* second cycle, nothing should change */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let s = sexp::parse(&format!("({})", exported)) | 
					 | 
					 | 
					 | 
					            let s = sexp::parse(&format!("({})", exported)) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |