forked from itycodes/shaderc
				
			
						commit
						93ff59d30e
					
				@ -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