|  |  |  | @ -1,11 +1,12 @@ | 
			
		
	
		
			
				
					|  |  |  |  | #[cfg(test)] | 
			
		
	
		
			
				
					|  |  |  |  | mod tests; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use crate::compiler::{Instruction, Module}; | 
			
		
	
		
			
				
					|  |  |  |  | use crate::compiler::{ | 
			
		
	
		
			
				
					|  |  |  |  |     AddressingModel, BuiltinDecoration, Decoration, ExecutionMode, ExecutionModel, Instruction, | 
			
		
	
		
			
				
					|  |  |  |  |     MemoryModel, Module, StorageClass, | 
			
		
	
		
			
				
					|  |  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  |  | use std::fmt; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use super::StorageClass; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use crate::parser::Ast; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #[derive(Debug, PartialEq, Clone)] | 
			
		
	
	
		
			
				
					|  |  |  | @ -43,48 +44,43 @@ pub fn parse_type(typ: &String) -> Type { | 
			
		
	
		
			
				
					|  |  |  |  |     // So, *v4f32i is a pointer to a vector of 4 floats, with the storage class Input.
 | 
			
		
	
		
			
				
					|  |  |  |  |     // *v4f32o is a pointer to a vector of 4 floats, with the storage class Output.
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     let c = typ.chars().next().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |     match c { | 
			
		
	
		
			
				
					|  |  |  |  |         '<' => { | 
			
		
	
		
			
				
					|  |  |  |  |     let mut chars = typ.chars(); | 
			
		
	
		
			
				
					|  |  |  |  |     match chars.next() { | 
			
		
	
		
			
				
					|  |  |  |  |         Some('<') => { | 
			
		
	
		
			
				
					|  |  |  |  |             assert_eq!(typ.as_str(), "<>"); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Void | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         '*' => { | 
			
		
	
		
			
				
					|  |  |  |  |             let mut chars = typ.chars(); | 
			
		
	
		
			
				
					|  |  |  |  |             chars.next(); | 
			
		
	
		
			
				
					|  |  |  |  |             let typ = chars.collect::<String>(); | 
			
		
	
		
			
				
					|  |  |  |  |             let storage_class = match typ.chars().last().unwrap() { | 
			
		
	
		
			
				
					|  |  |  |  |                 'i' => StorageClass::Input, | 
			
		
	
		
			
				
					|  |  |  |  |                 'o' => StorageClass::Output, | 
			
		
	
		
			
				
					|  |  |  |  |         Some('*') => { | 
			
		
	
		
			
				
					|  |  |  |  |             let mut typ = chars.collect::<String>(); | 
			
		
	
		
			
				
					|  |  |  |  |             let storage_class = match typ.pop() { | 
			
		
	
		
			
				
					|  |  |  |  |                 Some('i') => StorageClass::Input, | 
			
		
	
		
			
				
					|  |  |  |  |                 Some('o') => StorageClass::Output, | 
			
		
	
		
			
				
					|  |  |  |  |                 _ => panic!("Invalid storage class"), | 
			
		
	
		
			
				
					|  |  |  |  |             }; | 
			
		
	
		
			
				
					|  |  |  |  |             let typ = typ.chars().take(typ.len() - 1).collect::<String>(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Pointer(Box::new(parse_type(&typ)), storage_class) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         'v' => { | 
			
		
	
		
			
				
					|  |  |  |  |             let mut chars = typ.chars(); | 
			
		
	
		
			
				
					|  |  |  |  |             chars.next(); | 
			
		
	
		
			
				
					|  |  |  |  |             let size = chars.next().unwrap().to_digit(10).unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |         Some('v') => { | 
			
		
	
		
			
				
					|  |  |  |  |             let size = chars.next().map(|s| s.to_digit(10)).flatten().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             let typ = chars.collect::<String>(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Vector(Box::new(parse_type(&typ)), size) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         'f' => { | 
			
		
	
		
			
				
					|  |  |  |  |             let size = typ.chars().skip(1).collect::<String>().parse().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |         Some('f') => { | 
			
		
	
		
			
				
					|  |  |  |  |             let size = chars.collect::<String>().parse().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Float(size) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         's' => { | 
			
		
	
		
			
				
					|  |  |  |  |             let size = typ.chars().skip(1).collect::<String>().parse().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |         Some('s') => { | 
			
		
	
		
			
				
					|  |  |  |  |             let size = chars.collect::<String>().parse().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Int(size) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         'u' => { | 
			
		
	
		
			
				
					|  |  |  |  |             let size = typ.chars().skip(1).collect::<String>().parse().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |         Some('u') => { | 
			
		
	
		
			
				
					|  |  |  |  |             let size = chars.collect::<String>().parse().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Unsigned(size) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         _ => panic!("Invalid type"), | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | fn emit_type(typ: Type, ops: &mut Vec<(String, String)>) { | 
			
		
	
		
			
				
					|  |  |  |  | fn emit_type(typ: &Type, ops: &mut Vec<(String, String)>) { | 
			
		
	
		
			
				
					|  |  |  |  |     match &typ { | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Void => { | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push(("%void".to_string(), "OpTypeVoid".to_string())); | 
			
		
	
	
		
			
				
					|  |  |  | @ -108,18 +104,14 @@ fn emit_type(typ: Type, ops: &mut Vec<(String, String)>) { | 
			
		
	
		
			
				
					|  |  |  |  |             )); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Vector(in_typ, size) => { | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(*in_typ.clone(), ops); | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(in_typ, ops); | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |                 fix_name(&typ.to_string()), | 
			
		
	
		
			
				
					|  |  |  |  |                 format!( | 
			
		
	
		
			
				
					|  |  |  |  |                     "OpTypeVector {} {}", | 
			
		
	
		
			
				
					|  |  |  |  |                     fix_name(&in_typ.clone().to_string()), | 
			
		
	
		
			
				
					|  |  |  |  |                     size | 
			
		
	
		
			
				
					|  |  |  |  |                 ), | 
			
		
	
		
			
				
					|  |  |  |  |                 format!("OpTypeVector {} {}", fix_name(&in_typ.to_string()), size), | 
			
		
	
		
			
				
					|  |  |  |  |             )) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Pointer(in_typ, storage_class) => { | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(*in_typ.clone(), ops); | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(in_typ, ops); | 
			
		
	
		
			
				
					|  |  |  |  |             let typ_id = fix_name(&typ.to_string()); | 
			
		
	
		
			
				
					|  |  |  |  |             let storage_class = match storage_class { | 
			
		
	
		
			
				
					|  |  |  |  |                 StorageClass::Input => "Input", | 
			
		
	
	
		
			
				
					|  |  |  | @ -138,24 +130,20 @@ fn emit_type(typ: Type, ops: &mut Vec<(String, String)>) { | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | fn fix_name(name: &String) -> String { | 
			
		
	
		
			
				
					|  |  |  |  | fn fix_name(name: &str) -> String { | 
			
		
	
		
			
				
					|  |  |  |  |     format!( | 
			
		
	
		
			
				
					|  |  |  |  |         "%{}", | 
			
		
	
		
			
				
					|  |  |  |  |         name.clone() | 
			
		
	
		
			
				
					|  |  |  |  |             .replace("-", "_") | 
			
		
	
		
			
				
					|  |  |  |  |         name.replace("-", "_") | 
			
		
	
		
			
				
					|  |  |  |  |             .replace("*", "p") | 
			
		
	
		
			
				
					|  |  |  |  |             .replace("<>", "void") | 
			
		
	
		
			
				
					|  |  |  |  |             .replace(".", "_") | 
			
		
	
		
			
				
					|  |  |  |  |     ) | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | fn has_id<T>(name: String, ops: &Vec<(Option<String>, T)>) -> bool { | 
			
		
	
		
			
				
					|  |  |  |  |     for op in ops { | 
			
		
	
		
			
				
					|  |  |  |  |         if op.0.is_some() && op.0.clone().unwrap() == name { | 
			
		
	
		
			
				
					|  |  |  |  |             return true; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     false | 
			
		
	
		
			
				
					|  |  |  |  | fn has_id<T>(name: &str, ops: &Vec<(Option<String>, T)>) -> bool { | 
			
		
	
		
			
				
					|  |  |  |  |     ops.iter() | 
			
		
	
		
			
				
					|  |  |  |  |         .find(|op| op.0.as_ref().map(|s| *s == name).unwrap_or(false)) | 
			
		
	
		
			
				
					|  |  |  |  |         .is_some() | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> { | 
			
		
	
	
		
			
				
					|  |  |  | @ -171,15 +159,15 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> { | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     let memory_model_address = match module.memory_model.addressing_model { | 
			
		
	
		
			
				
					|  |  |  |  |         crate::compiler::AddressingModel::Logical => "Logical", | 
			
		
	
		
			
				
					|  |  |  |  |         crate::compiler::AddressingModel::Physical32 => "Physical32", | 
			
		
	
		
			
				
					|  |  |  |  |         crate::compiler::AddressingModel::Physical64 => "Physical64", | 
			
		
	
		
			
				
					|  |  |  |  |         crate::compiler::AddressingModel::PhysicalStorageBuffer64 => "PhysicalStorageBuffer64", | 
			
		
	
		
			
				
					|  |  |  |  |         AddressingModel::Logical => "Logical", | 
			
		
	
		
			
				
					|  |  |  |  |         AddressingModel::Physical32 => "Physical32", | 
			
		
	
		
			
				
					|  |  |  |  |         AddressingModel::Physical64 => "Physical64", | 
			
		
	
		
			
				
					|  |  |  |  |         AddressingModel::PhysicalStorageBuffer64 => "PhysicalStorageBuffer64", | 
			
		
	
		
			
				
					|  |  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  |  |     let memory_model_model = match module.memory_model.memory_model { | 
			
		
	
		
			
				
					|  |  |  |  |         crate::compiler::MemoryModel::Simple => "Simple", | 
			
		
	
		
			
				
					|  |  |  |  |         crate::compiler::MemoryModel::GLSL450 => "GLSL450", | 
			
		
	
		
			
				
					|  |  |  |  |         crate::compiler::MemoryModel::OpenCL => "OpenCL", | 
			
		
	
		
			
				
					|  |  |  |  |         MemoryModel::Simple => "Simple", | 
			
		
	
		
			
				
					|  |  |  |  |         MemoryModel::GLSL450 => "GLSL450", | 
			
		
	
		
			
				
					|  |  |  |  |         MemoryModel::OpenCL => "OpenCL", | 
			
		
	
		
			
				
					|  |  |  |  |         _ => todo!(), | 
			
		
	
		
			
				
					|  |  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  |  |     ops.push(( | 
			
		
	
	
		
			
				
					|  |  |  | @ -193,8 +181,8 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     for entry in module.entry_points.clone() { | 
			
		
	
		
			
				
					|  |  |  |  |         let exec_model = match entry.execution_model { | 
			
		
	
		
			
				
					|  |  |  |  |             crate::compiler::ExecutionModel::Fragment => "Fragment", | 
			
		
	
		
			
				
					|  |  |  |  |             crate::compiler::ExecutionModel::Vertex => "Vertex", | 
			
		
	
		
			
				
					|  |  |  |  |             ExecutionModel::Fragment => "Fragment", | 
			
		
	
		
			
				
					|  |  |  |  |             ExecutionModel::Vertex => "Vertex", | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         let name = entry.name; | 
			
		
	
		
			
				
					|  |  |  |  |         let interface: Vec<String> = entry | 
			
		
	
	
		
			
				
					|  |  |  | @ -203,7 +191,7 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> { | 
			
		
	
		
			
				
					|  |  |  |  |             .map(|i| fix_name(&i.to_string())) | 
			
		
	
		
			
				
					|  |  |  |  |             .collect(); | 
			
		
	
		
			
				
					|  |  |  |  |         let exec_mode = match entry.execution_mode { | 
			
		
	
		
			
				
					|  |  |  |  |             crate::compiler::ExecutionMode::OriginUpperLeft => "OriginUpperLeft", | 
			
		
	
		
			
				
					|  |  |  |  |             ExecutionMode::OriginUpperLeft => "OriginUpperLeft", | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |             None, | 
			
		
	
	
		
			
				
					|  |  |  | @ -243,17 +231,17 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> { | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     for global in module.globals.clone() { | 
			
		
	
		
			
				
					|  |  |  |  |         let name: String = fix_name(&global.name); | 
			
		
	
		
			
				
					|  |  |  |  |         let _typ = global.typ; | 
			
		
	
		
			
				
					|  |  |  |  |         let name = fix_name(&global.name); | 
			
		
	
		
			
				
					|  |  |  |  |         let typ = global.typ; | 
			
		
	
		
			
				
					|  |  |  |  |         let storage_class = match global.storage_class { | 
			
		
	
		
			
				
					|  |  |  |  |             crate::compiler::StorageClass::Input => "Input", | 
			
		
	
		
			
				
					|  |  |  |  |             crate::compiler::StorageClass::Output => "Output", | 
			
		
	
		
			
				
					|  |  |  |  |             crate::compiler::StorageClass::Undefined => panic!("Bound a non-declared variable"), | 
			
		
	
		
			
				
					|  |  |  |  |             StorageClass::Input => "Input", | 
			
		
	
		
			
				
					|  |  |  |  |             StorageClass::Output => "Output", | 
			
		
	
		
			
				
					|  |  |  |  |             StorageClass::Undefined => panic!("Bound a non-declared variable"), | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         let mut type_ops = Vec::new(); | 
			
		
	
		
			
				
					|  |  |  |  |         emit_type(parse_type(&_typ), &mut type_ops); | 
			
		
	
		
			
				
					|  |  |  |  |         emit_type(&parse_type(&typ), &mut type_ops); | 
			
		
	
		
			
				
					|  |  |  |  |         for op in type_ops { | 
			
		
	
		
			
				
					|  |  |  |  |             if has_id(op.0.clone(), &ops) { | 
			
		
	
		
			
				
					|  |  |  |  |             if has_id(&op.0, &ops) { | 
			
		
	
		
			
				
					|  |  |  |  |                 continue; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((Some(op.0), vec![op.1])); | 
			
		
	
	
		
			
				
					|  |  |  | @ -262,7 +250,7 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> { | 
			
		
	
		
			
				
					|  |  |  |  |             Some(name.clone()), | 
			
		
	
		
			
				
					|  |  |  |  |             vec![ | 
			
		
	
		
			
				
					|  |  |  |  |                 "OpVariable".to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |                 fix_name(&_typ), | 
			
		
	
		
			
				
					|  |  |  |  |                 fix_name(&typ), | 
			
		
	
		
			
				
					|  |  |  |  |                 storage_class.to_string(), | 
			
		
	
		
			
				
					|  |  |  |  |             ], | 
			
		
	
		
			
				
					|  |  |  |  |         )); | 
			
		
	
	
		
			
				
					|  |  |  | @ -272,29 +260,26 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> { | 
			
		
	
		
			
				
					|  |  |  |  |         let name = fix_name(&format!("l_{}", fun.name)); | 
			
		
	
		
			
				
					|  |  |  |  |         let return_type = fix_name(&fun.return_type); | 
			
		
	
		
			
				
					|  |  |  |  |         let mut type_ops = Vec::new(); | 
			
		
	
		
			
				
					|  |  |  |  |         emit_type(parse_type(&fun.return_type), &mut type_ops); | 
			
		
	
		
			
				
					|  |  |  |  |         emit_type(&parse_type(&fun.return_type), &mut type_ops); | 
			
		
	
		
			
				
					|  |  |  |  |         for op in type_ops { | 
			
		
	
		
			
				
					|  |  |  |  |             if has_id(op.0.clone(), &ops) { | 
			
		
	
		
			
				
					|  |  |  |  |             if has_id(&op.0, &ops) { | 
			
		
	
		
			
				
					|  |  |  |  |                 continue; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((Some(op.0), vec![op.1])); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         ops.push(( | 
			
		
	
		
			
				
					|  |  |  |  |             Some(name.clone()), | 
			
		
	
		
			
				
					|  |  |  |  |             vec!["OpTypeFunction".to_string(), return_type.clone()], | 
			
		
	
		
			
				
					|  |  |  |  |         )); | 
			
		
	
		
			
				
					|  |  |  |  |         // Push OpFunctionType
 | 
			
		
	
		
			
				
					|  |  |  |  |         ops.push((Some(name), vec!["OpTypeFunction".to_string(), return_type])); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // for op in ops {
 | 
			
		
	
		
			
				
					|  |  |  |  |     //     if op.0.is_some() {
 | 
			
		
	
		
			
				
					|  |  |  |  |     //         write!(spirv_asm, "{} = ", op.0.unwrap()).unwrap();
 | 
			
		
	
		
			
				
					|  |  |  |  |     //     if let Some(op0) = op.0 {
 | 
			
		
	
		
			
				
					|  |  |  |  |     //         write!(spirv_asm, "{} = ", op0).unwrap();
 | 
			
		
	
		
			
				
					|  |  |  |  |     //     }
 | 
			
		
	
		
			
				
					|  |  |  |  |     //     for arg in op.1 {
 | 
			
		
	
		
			
				
					|  |  |  |  |     //         write!(spirv_asm, "{} ", arg).unwrap();
 | 
			
		
	
		
			
				
					|  |  |  |  |     //     }
 | 
			
		
	
		
			
				
					|  |  |  |  |     //     writeln!(spirv_asm).unwrap();
 | 
			
		
	
		
			
				
					|  |  |  |  |     // }
 | 
			
		
	
		
			
				
					|  |  |  |  |     // spirv_asm
 | 
			
		
	
		
			
				
					|  |  |  |  |     ops | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -407,14 +392,17 @@ fn compile_comp_constr( | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | fn compile_comp_extract(    lst: &mut Vec<Ast>, | 
			
		
	
		
			
				
					|  |  |  |  | fn compile_comp_extract( | 
			
		
	
		
			
				
					|  |  |  |  |     lst: &mut Vec<Ast>, | 
			
		
	
		
			
				
					|  |  |  |  |     vars: &mut Vec<(String, String)>, | 
			
		
	
		
			
				
					|  |  |  |  |     constants: &mut Vec<(String, String)>, | 
			
		
	
		
			
				
					|  |  |  |  |     types: &mut Vec<String>, | 
			
		
	
		
			
				
					|  |  |  |  |     counter: &mut i32, | 
			
		
	
		
			
				
					|  |  |  |  |     stack: &mut Vec<String>, | 
			
		
	
		
			
				
					|  |  |  |  |     out: &mut Vec<(Option<String>, String)>, | 
			
		
	
		
			
				
					|  |  |  |  |     typ: &str, inx: u32) { | 
			
		
	
		
			
				
					|  |  |  |  |     typ: &str, | 
			
		
	
		
			
				
					|  |  |  |  |     inx: u32, | 
			
		
	
		
			
				
					|  |  |  |  | ) { | 
			
		
	
		
			
				
					|  |  |  |  |     assert!(lst.len() == 1); | 
			
		
	
		
			
				
					|  |  |  |  |     let vec = lst.pop().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |     compile_ast_ssa(vec, vars, constants, types, counter, stack, out); | 
			
		
	
	
		
			
				
					|  |  |  | @ -423,7 +411,12 @@ fn compile_comp_extract(    lst: &mut Vec<Ast>, | 
			
		
	
		
			
				
					|  |  |  |  |     *counter += 1; | 
			
		
	
		
			
				
					|  |  |  |  |     out.push(( | 
			
		
	
		
			
				
					|  |  |  |  |         Some(id.clone()), | 
			
		
	
		
			
				
					|  |  |  |  |         format!("OpCompositeExtract {} {} {}", fix_name(&String::from(typ)), fix_name(&vec_id), inx), | 
			
		
	
		
			
				
					|  |  |  |  |         format!( | 
			
		
	
		
			
				
					|  |  |  |  |             "OpCompositeExtract {} {} {}", | 
			
		
	
		
			
				
					|  |  |  |  |             fix_name(&String::from(typ)), | 
			
		
	
		
			
				
					|  |  |  |  |             fix_name(&vec_id), | 
			
		
	
		
			
				
					|  |  |  |  |             inx | 
			
		
	
		
			
				
					|  |  |  |  |         ), | 
			
		
	
		
			
				
					|  |  |  |  |     )); | 
			
		
	
		
			
				
					|  |  |  |  |     stack.push(id); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
	
		
			
				
					|  |  |  | @ -438,8 +431,7 @@ pub fn compile_ast_ssa( | 
			
		
	
		
			
				
					|  |  |  |  |     out: &mut Vec<(Option<String>, String)>, | 
			
		
	
		
			
				
					|  |  |  |  | ) { | 
			
		
	
		
			
				
					|  |  |  |  |     match ast.clone().list() { | 
			
		
	
		
			
				
					|  |  |  |  |         Some(l) => { | 
			
		
	
		
			
				
					|  |  |  |  |             let mut lst = l.clone(); | 
			
		
	
		
			
				
					|  |  |  |  |         Some(mut lst) => { | 
			
		
	
		
			
				
					|  |  |  |  |             assert!(!lst.is_empty()); | 
			
		
	
		
			
				
					|  |  |  |  |             let fun = lst.remove(0); | 
			
		
	
		
			
				
					|  |  |  |  |             assert!(true); // no safe remove, thanks Rust
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -453,7 +445,9 @@ pub fn compile_ast_ssa( | 
			
		
	
		
			
				
					|  |  |  |  |                 let inx = split[0]; | 
			
		
	
		
			
				
					|  |  |  |  |                 let typ = split[1]; | 
			
		
	
		
			
				
					|  |  |  |  |                 let inx = str::parse::<u32>(inx).expect("Invalid index!"); | 
			
		
	
		
			
				
					|  |  |  |  |                 compile_comp_extract(&mut lst, vars, constants, types, counter, stack, out, typ, inx); | 
			
		
	
		
			
				
					|  |  |  |  |                 compile_comp_extract( | 
			
		
	
		
			
				
					|  |  |  |  |                     &mut lst, vars, constants, types, counter, stack, out, typ, inx, | 
			
		
	
		
			
				
					|  |  |  |  |                 ); | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -465,7 +459,6 @@ pub fn compile_ast_ssa( | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if fun_name.starts_with("*") { | 
			
		
	
		
			
				
					|  |  |  |  |                 let typ = &fun_name[1..fun_name.len()]; | 
			
		
	
		
			
				
					|  |  |  |  |                 compile_biop( | 
			
		
	
	
		
			
				
					|  |  |  | @ -474,7 +467,6 @@ pub fn compile_ast_ssa( | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if fun_name.starts_with("+") { | 
			
		
	
		
			
				
					|  |  |  |  |                 let typ = &fun_name[1..fun_name.len()]; | 
			
		
	
		
			
				
					|  |  |  |  |                 compile_biop( | 
			
		
	
	
		
			
				
					|  |  |  | @ -483,7 +475,6 @@ pub fn compile_ast_ssa( | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if fun_name.starts_with("-") { | 
			
		
	
		
			
				
					|  |  |  |  |                 let typ = &fun_name[1..fun_name.len()]; | 
			
		
	
		
			
				
					|  |  |  |  |                 compile_biop( | 
			
		
	
	
		
			
				
					|  |  |  | @ -494,7 +485,14 @@ pub fn compile_ast_ssa( | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if fun_name.starts_with("v") { | 
			
		
	
		
			
				
					|  |  |  |  |                 compile_comp_constr( | 
			
		
	
		
			
				
					|  |  |  |  |                     &mut lst, vars, constants, types, counter, stack, out, fun_name.as_str(), | 
			
		
	
		
			
				
					|  |  |  |  |                     &mut lst, | 
			
		
	
		
			
				
					|  |  |  |  |                     vars, | 
			
		
	
		
			
				
					|  |  |  |  |                     constants, | 
			
		
	
		
			
				
					|  |  |  |  |                     types, | 
			
		
	
		
			
				
					|  |  |  |  |                     counter, | 
			
		
	
		
			
				
					|  |  |  |  |                     stack, | 
			
		
	
		
			
				
					|  |  |  |  |                     out, | 
			
		
	
		
			
				
					|  |  |  |  |                     fun_name.as_str(), | 
			
		
	
		
			
				
					|  |  |  |  |                 ); | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
	
		
			
				
					|  |  |  | @ -509,7 +507,11 @@ pub fn compile_ast_ssa( | 
			
		
	
		
			
				
					|  |  |  |  |                 *counter += 1; | 
			
		
	
		
			
				
					|  |  |  |  |                 out.push(( | 
			
		
	
		
			
				
					|  |  |  |  |                     Some(id.clone()), | 
			
		
	
		
			
				
					|  |  |  |  |                     format!("OpLoad {} {}", fix_name(&String::from(typ)), fix_name(&ptr_id)), | 
			
		
	
		
			
				
					|  |  |  |  |                     format!( | 
			
		
	
		
			
				
					|  |  |  |  |                         "OpLoad {} {}", | 
			
		
	
		
			
				
					|  |  |  |  |                         fix_name(&String::from(typ)), | 
			
		
	
		
			
				
					|  |  |  |  |                         fix_name(&ptr_id) | 
			
		
	
		
			
				
					|  |  |  |  |                     ), | 
			
		
	
		
			
				
					|  |  |  |  |                 )); | 
			
		
	
		
			
				
					|  |  |  |  |                 stack.push(id); | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
	
		
			
				
					|  |  |  | @ -538,9 +540,7 @@ pub fn compile_ast_ssa( | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         None => { | 
			
		
	
		
			
				
					|  |  |  |  |             let sym = ast.clone().symbol(); | 
			
		
	
		
			
				
					|  |  |  |  |             assert!(sym.is_some()); | 
			
		
	
		
			
				
					|  |  |  |  |             let sym = sym.unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             let sym = ast.symbol().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             match match_number(&sym) { | 
			
		
	
		
			
				
					|  |  |  |  |                 Number::Int(i) => { | 
			
		
	
		
			
				
					|  |  |  |  |                     let key = format!("i32_{}", i); | 
			
		
	
	
		
			
				
					|  |  |  | @ -617,14 +617,14 @@ pub fn compile_fun_ssa(module: &mut Module, ops: &Vec<(Option<String>, String)>) | 
			
		
	
		
			
				
					|  |  |  |  |         let mut out_pre = vec![]; | 
			
		
	
		
			
				
					|  |  |  |  |         for t in &types { | 
			
		
	
		
			
				
					|  |  |  |  |             let typ = parse_type(t); | 
			
		
	
		
			
				
					|  |  |  |  |             if has_id(fix_name(&typ.to_string()), ops) { | 
			
		
	
		
			
				
					|  |  |  |  |             if has_id(&fix_name(&typ.to_string()), ops) { | 
			
		
	
		
			
				
					|  |  |  |  |                 continue; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             if has_id(fix_name(&typ.to_string()), &out_pre) { | 
			
		
	
		
			
				
					|  |  |  |  |             if has_id(&fix_name(&typ.to_string()), &out_pre) { | 
			
		
	
		
			
				
					|  |  |  |  |                 continue; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             let mut type_ops = vec![]; | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(typ, &mut type_ops); | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(&typ, &mut type_ops); | 
			
		
	
		
			
				
					|  |  |  |  |             for type_op in type_ops { | 
			
		
	
		
			
				
					|  |  |  |  |                 out_pre.push((Some(type_op.0), type_op.1)); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
	
		
			
				
					|  |  |  | 
 |