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