|  |  |  | @ -7,6 +7,8 @@ use std::fmt::Write; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use super::StorageClass; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use crate::parser::Ast; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #[derive(Debug, PartialEq, Clone)] | 
			
		
	
		
			
				
					|  |  |  |  | pub enum Type { | 
			
		
	
		
			
				
					|  |  |  |  |     Pointer(Box<Type>, StorageClass), | 
			
		
	
	
		
			
				
					|  |  |  | @ -292,3 +294,116 @@ pub fn spirv_meta(module: Module) -> String { | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     spirv_asm | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | enum Number { | 
			
		
	
		
			
				
					|  |  |  |  |     Int(i32), | 
			
		
	
		
			
				
					|  |  |  |  |     Float(f32), | 
			
		
	
		
			
				
					|  |  |  |  |     NotANumber, | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | fn match_number(s: &str) -> Number { | 
			
		
	
		
			
				
					|  |  |  |  |     // floats have to be in the format of [0-9]+\.[0-9]*
 | 
			
		
	
		
			
				
					|  |  |  |  |     // integers have to be in the format of [0-9]+
 | 
			
		
	
		
			
				
					|  |  |  |  |     let mut chars = s.chars(); | 
			
		
	
		
			
				
					|  |  |  |  |     let mut has_dot = false; | 
			
		
	
		
			
				
					|  |  |  |  |     while let Some(c) = chars.next() { | 
			
		
	
		
			
				
					|  |  |  |  |         if c == '.' { | 
			
		
	
		
			
				
					|  |  |  |  |             if has_dot { | 
			
		
	
		
			
				
					|  |  |  |  |                 // only one dot allowed.
 | 
			
		
	
		
			
				
					|  |  |  |  |                 return Number::NotANumber; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             has_dot = true; | 
			
		
	
		
			
				
					|  |  |  |  |         } else if !c.is_digit(10) { | 
			
		
	
		
			
				
					|  |  |  |  |             // not a number;
 | 
			
		
	
		
			
				
					|  |  |  |  |             // has a character that is not a digit or a dot.
 | 
			
		
	
		
			
				
					|  |  |  |  |             return Number::NotANumber; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     if has_dot { | 
			
		
	
		
			
				
					|  |  |  |  |         // we have checked that the whole thing is numbers and dots
 | 
			
		
	
		
			
				
					|  |  |  |  |         // and that there is precisely one dot
 | 
			
		
	
		
			
				
					|  |  |  |  |         // that matches the regex.
 | 
			
		
	
		
			
				
					|  |  |  |  |         Number::Float(s.parse().unwrap()) | 
			
		
	
		
			
				
					|  |  |  |  |     } else { | 
			
		
	
		
			
				
					|  |  |  |  |         // this is an integer, since no dots.
 | 
			
		
	
		
			
				
					|  |  |  |  |         Number::Int(s.parse().unwrap()) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub fn compile_ast_ssa( | 
			
		
	
		
			
				
					|  |  |  |  |     ast: Ast, | 
			
		
	
		
			
				
					|  |  |  |  |     vars: &mut Vec<(String, String)>, | 
			
		
	
		
			
				
					|  |  |  |  |     mut constants: &mut Vec<(String, String)>, | 
			
		
	
		
			
				
					|  |  |  |  |     mut counter: &mut Box<i32>, | 
			
		
	
		
			
				
					|  |  |  |  |     mut stack: &mut Vec<String>, | 
			
		
	
		
			
				
					|  |  |  |  |     mut out: &mut Vec<(Option<String>, String)>, | 
			
		
	
		
			
				
					|  |  |  |  | ) { | 
			
		
	
		
			
				
					|  |  |  |  |     match ast.clone().list() { | 
			
		
	
		
			
				
					|  |  |  |  |         Some(l) => { | 
			
		
	
		
			
				
					|  |  |  |  |             let mut lst = l.clone(); | 
			
		
	
		
			
				
					|  |  |  |  |             assert!(!lst.is_empty()); | 
			
		
	
		
			
				
					|  |  |  |  |             let fun = lst.remove(0); | 
			
		
	
		
			
				
					|  |  |  |  |             assert!(true); // no safe remove, thanks Rust
 | 
			
		
	
		
			
				
					|  |  |  |  |             let fun_name = fun.symbol(); | 
			
		
	
		
			
				
					|  |  |  |  |             assert!(fun_name.is_some()); | 
			
		
	
		
			
				
					|  |  |  |  |             let fun_name = fun_name.unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             match fun_name.as_str() { | 
			
		
	
		
			
				
					|  |  |  |  |                 "store-ptr" => { | 
			
		
	
		
			
				
					|  |  |  |  |                     assert!(lst.len() == 2); | 
			
		
	
		
			
				
					|  |  |  |  |                     let ptr = lst.pop().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |                     let val = lst.pop().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |                     compile_ast_ssa(ptr, vars, constants, counter, stack, out); | 
			
		
	
		
			
				
					|  |  |  |  |                     compile_ast_ssa(val, vars, constants, counter, stack, out); | 
			
		
	
		
			
				
					|  |  |  |  |                     let val_id = stack.pop().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |                     let ptr_id = stack.pop().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |                     out.push((None, format!("OpStore {} {}", fix_name(&val_id), fix_name(&ptr_id)))); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 s => { | 
			
		
	
		
			
				
					|  |  |  |  |                     panic!("Unknown function: {} with params {:#?} in context:\n{:#?}", s, lst, ast); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         None => { | 
			
		
	
		
			
				
					|  |  |  |  |             let sym = ast.clone().symbol(); | 
			
		
	
		
			
				
					|  |  |  |  |             assert!(sym.is_some()); | 
			
		
	
		
			
				
					|  |  |  |  |             let sym = sym.unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             match match_number(&sym) { | 
			
		
	
		
			
				
					|  |  |  |  |                 Number::Int(i) => { | 
			
		
	
		
			
				
					|  |  |  |  |                     let key = format!("i32_{}", i); | 
			
		
	
		
			
				
					|  |  |  |  |                     let mut contains = false; | 
			
		
	
		
			
				
					|  |  |  |  |                     for c in constants.iter() { | 
			
		
	
		
			
				
					|  |  |  |  |                         if c.0 == key { | 
			
		
	
		
			
				
					|  |  |  |  |                             contains = true; | 
			
		
	
		
			
				
					|  |  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                     if contains { | 
			
		
	
		
			
				
					|  |  |  |  |                         constants.push((key.clone(), format!("OpConstant %i32 {}", i.to_string()))); | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                     stack.push(key); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 Number::Float(f) => { | 
			
		
	
		
			
				
					|  |  |  |  |                     let key = format!("f32_{}", f); | 
			
		
	
		
			
				
					|  |  |  |  |                     let mut contains = false; | 
			
		
	
		
			
				
					|  |  |  |  |                     for c in constants.iter() { | 
			
		
	
		
			
				
					|  |  |  |  |                         if c.0 == key { | 
			
		
	
		
			
				
					|  |  |  |  |                             contains = true; | 
			
		
	
		
			
				
					|  |  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                     if contains { | 
			
		
	
		
			
				
					|  |  |  |  |                         constants.push((key.clone(), format!("OpConstant %f32 {}", f.to_string()))); | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                     stack.push(key); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 Number::NotANumber => { | 
			
		
	
		
			
				
					|  |  |  |  |                     for v in vars.iter() { | 
			
		
	
		
			
				
					|  |  |  |  |                         if v.0 == sym { | 
			
		
	
		
			
				
					|  |  |  |  |                             stack.push(v.0.clone()); | 
			
		
	
		
			
				
					|  |  |  |  |                             return; | 
			
		
	
		
			
				
					|  |  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                     panic!("Unknown variable or constant: {}", sym); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
	
		
			
				
					|  |  |  | 
 |