forked from itycodes/shaderc
				
			
							parent
							
								
									1e1d0911e4
								
							
						
					
					
						commit
						9aafb9758f
					
				| @ -0,0 +1,206 @@ | ||||
| use crate::{ | ||||
|     compiler::{ | ||||
|         AddressingModel, Capability, EntryPoint, ExecutionMode, ExecutionModel, Memory, | ||||
|         MemoryModel, expect_list, expect_one_of, expect_symbol, | ||||
|     }, | ||||
|     parser::{Ast, Localised, Location}, | ||||
| }; | ||||
| 
 | ||||
| use super::{ | ||||
|     BuiltinDecoration, CompilerError, Decoration, Function, GlobalVariable, Import, Module, | ||||
|     StorageClass, expect_empty, expect_empty_ast, | ||||
| }; | ||||
| 
 | ||||
| pub fn compile_module<I: Iterator<Item = Ast>>( | ||||
|     module: &mut Module, | ||||
|     mut list: I, | ||||
|     loc: Location, | ||||
| ) -> Result<(), CompilerError> { | ||||
|     let _cap = expect_one_of(&["Shader"], expect_symbol(list.next(), &loc)?)?; | ||||
|     let _exec = expect_one_of(&["Logical"], expect_symbol(list.next(), &loc)?)?; | ||||
|     let _memory = expect_one_of(&["GLSL450"], expect_symbol(list.next(), &loc)?)?; | ||||
|     module.memory_model = Memory { | ||||
|         addressing_model: AddressingModel::Logical, | ||||
|         memory_model: MemoryModel::GLSL450, | ||||
|     }; | ||||
|     module.capabilities.push(Capability::Shader); | ||||
|     expect_empty_ast(list) | ||||
| } | ||||
| 
 | ||||
| pub fn compile_import<I: Iterator<Item = Ast>>( | ||||
|     module: &mut Module, | ||||
|     mut list: I, | ||||
|     loc: Location, | ||||
| ) -> Result<(), CompilerError> { | ||||
|     let name = expect_symbol(list.next(), &loc)?.into_inner(); | ||||
|     let value = expect_symbol(list.next(), &loc)?.into_inner(); | ||||
|     module.imports.push(Import { name, value }); | ||||
|     expect_empty_ast(list) | ||||
| } | ||||
| 
 | ||||
| pub fn compile_bind<I: Iterator<Item = Ast>>( | ||||
|     module: &mut Module, | ||||
|     mut list: I, | ||||
|     loc: Location, | ||||
| ) -> Result<(), CompilerError> { | ||||
|     let Localised { | ||||
|         location: name_and_type_loc, | ||||
|         item: name_and_type, | ||||
|     } = expect_list(list.next(), &loc)?; | ||||
|     let name_and_type = name_and_type | ||||
|         .into_iter() | ||||
|         .map(|x| expect_symbol(Some(x), &name_and_type_loc).map(Localised::into_inner)) | ||||
|         .collect::<Result<String, CompilerError>>()?; | ||||
|     let mut name_and_type = name_and_type.split(':').map(|s| s.to_string()); | ||||
|     // name_and_type is of the name:type format, like foo:f32
 | ||||
|     let name: String = name_and_type | ||||
|         .next() | ||||
|         .ok_or(CompilerError::ExpectedSymbol(name_and_type_loc.clone()))?; | ||||
|     let typ: String = name_and_type | ||||
|         .next() | ||||
|         .ok_or(CompilerError::ExpectedType(name_and_type_loc.tail()))?; | ||||
|     expect_empty(name_and_type, name_and_type_loc)?; | ||||
|     let Localised { | ||||
|         location: bind_loc, | ||||
|         item: bind, | ||||
|     } = expect_list(list.next(), &loc)?; | ||||
|     let bind: Vec<String> = bind | ||||
|         .into_iter() | ||||
|         .map(|x| expect_symbol(Some(x), &bind_loc).map(Localised::into_inner)) | ||||
|         .collect::<Result<_, _>>()?; | ||||
|     let bind_name = bind | ||||
|         .get(0) | ||||
|         .ok_or(CompilerError::ExpectedSymbol(bind_loc.clone()))?; | ||||
| 
 | ||||
|     let bind_name = match bind_name.as_str() { | ||||
|         "BuiltIn" => Decoration::BuiltIn(BuiltinDecoration::FragCoord), | ||||
|         "Location" => Decoration::Location(bind.get(1).unwrap().parse::<u32>().unwrap()), | ||||
|         b => return Err(CompilerError::UnknownBind(b.to_string(), bind_loc)), | ||||
|     }; | ||||
|     let mut exists = false; | ||||
|     for var in &module.globals { | ||||
|         if var.name == name { | ||||
|             exists = true; | ||||
|         } | ||||
|     } | ||||
|     if !exists { | ||||
|         module.globals.push(GlobalVariable { | ||||
|             name, | ||||
|             typ, | ||||
|             storage_class: StorageClass::Undefined, | ||||
|             decorations: vec![bind_name], | ||||
|         }); | ||||
|     } | ||||
|     expect_empty_ast(list) | ||||
| } | ||||
| 
 | ||||
| pub fn compile_dec<I: Iterator<Item = Ast>>( | ||||
|     module: &mut Module, | ||||
|     mut list: I, | ||||
|     loc: Location, | ||||
| ) -> Result<(), CompilerError> { | ||||
|     let Localised { | ||||
|         location: name_and_type_loc, | ||||
|         item: name_and_type, | ||||
|     } = expect_symbol(list.next(), &loc)?; | ||||
|     let mut name_and_type = name_and_type.split(':').map(|s| s.to_string()); | ||||
|     let name: String = name_and_type | ||||
|         .next() | ||||
|         .ok_or(CompilerError::ExpectedSymbol(name_and_type_loc.clone()))?; | ||||
|     let typ: String = name_and_type | ||||
|         .next() | ||||
|         .ok_or(CompilerError::ExpectedType(name_and_type_loc.tail()))?; | ||||
|     expect_empty(name_and_type, name_and_type_loc)?; | ||||
| 
 | ||||
|     let storage_class = expect_symbol(list.next(), &loc)?; | ||||
|     let mut exists = false; | ||||
|     for var in &module.globals { | ||||
|         if var.name.as_str() == name.as_str() { | ||||
|             exists = true; | ||||
|         } | ||||
|     } | ||||
|     let storage_class = match storage_class.as_str() { | ||||
|         "Input" => StorageClass::Input, | ||||
|         "Output" => StorageClass::Output, | ||||
|         _ => StorageClass::Undefined, | ||||
|     }; | ||||
|     if !exists { | ||||
|         module.globals.push(GlobalVariable { | ||||
|             name: name.to_string(), | ||||
|             typ: typ.to_string(), | ||||
|             storage_class: storage_class.clone(), | ||||
|             decorations: vec![], | ||||
|         }); | ||||
|     } | ||||
|     if exists { | ||||
|         module | ||||
|             .globals | ||||
|             .iter_mut() | ||||
|             .find(|x| x.name.as_str() == name.as_str()) | ||||
|             .unwrap() | ||||
|             .storage_class = storage_class.clone(); | ||||
|     } | ||||
|     expect_empty_ast(list) | ||||
| } | ||||
| 
 | ||||
| pub fn compile_entry<I: Iterator<Item = Ast>>( | ||||
|     module: &mut Module, | ||||
|     mut list: I, | ||||
|     loc: Location, | ||||
| ) -> Result<(), CompilerError> { | ||||
|     let name = expect_symbol(list.next(), &loc)?; | ||||
|     let _exec_model = expect_one_of(&["Fragment"], expect_symbol(list.next(), &loc)?)?; | ||||
|     let _exec_mode = expect_one_of(&["OriginUpperLeft"], expect_symbol(list.next(), &loc)?)?; | ||||
|     let Localised { | ||||
|         location: interface_loc, | ||||
|         item: interface, | ||||
|     } = expect_list(list.next(), &loc)?; | ||||
|     let interface: Vec<String> = interface | ||||
|         .into_iter() | ||||
|         .map(|x| expect_symbol(Some(x), &interface_loc).map(|s| s.into_inner().replace(":", ""))) | ||||
|         .collect::<Result<_, _>>()?; | ||||
|     module.entry_points.push(EntryPoint { | ||||
|         execution_model: ExecutionModel::Fragment, | ||||
|         execution_mode: ExecutionMode::OriginUpperLeft, | ||||
|         name: name.to_string(), | ||||
|         interface, | ||||
|     }); | ||||
| 
 | ||||
|     expect_empty_ast(list) | ||||
| } | ||||
| 
 | ||||
| pub fn compile_fun<I: Iterator<Item = Ast>>( | ||||
|     module: &mut Module, | ||||
|     mut list: I, | ||||
|     loc: Location, | ||||
| ) -> Result<(), CompilerError> { | ||||
|     let Localised { | ||||
|         location: name_loc, | ||||
|         item: name, | ||||
|     } = expect_list(list.next(), &loc)?; | ||||
|     let mut name_it = name.into_iter(); | ||||
|     let name = expect_symbol(name_it.next(), &name_loc)?; | ||||
|     expect_empty(name_it, name_loc)?; | ||||
|     let body = list.collect::<Vec<_>>(); | ||||
|     let location = if let (Some(s), Some(e)) = ( | ||||
|         body.first().map(|a| a.location()), | ||||
|         body.last().map(|a| a.location()), | ||||
|     ) { | ||||
|         Location::range(s, e) | ||||
|     } else { | ||||
|         Location::Char { line: 0, col: 0 } | ||||
|     }; | ||||
|     let fun = Function { | ||||
|         name: name.to_string(), | ||||
|         return_type: "void".to_string(), | ||||
|         arguments: vec![], | ||||
|         body: Some(vec![]), | ||||
|         ast: Some(Ast::List(Localised { | ||||
|             location, | ||||
|             item: body, | ||||
|         })), | ||||
|     }; | ||||
|     module.functions.push(fun); | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue