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