You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
6.7 KiB

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 _return_type = expect_one_of(&[":<>"], expect_symbol(list.next(), &loc)?)?;
let return_type = _return_type.into_inner().replace(":", "");
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: return_type,
arguments: vec![],
body: Some(vec![]),
ast: Some(Ast::List(Localised {
location,
item: body,
})),
};
module.functions.push(fun);
Ok(())
}