Refactor generate_extension

This commit is contained in:
Maik Klein 2018-07-30 19:53:12 +02:00
parent 773c64cde1
commit aeb4ebea51

View file

@ -92,12 +92,17 @@ pub fn define_handle_macro() -> Tokens {
pub struct $name{ pub struct $name{
ptr: *mut u8 ptr: *mut u8
} }
impl Default for $name{
fn default() -> $name {
$name::null()
}
}
unsafe impl Send for $name {} unsafe impl Send for $name {}
unsafe impl Sync for $name {} unsafe impl Sync for $name {}
impl $name{ impl $name{
pub unsafe fn null() -> Self{ pub fn null() -> Self{
$name{ $name{
ptr: ::std::ptr::null_mut() ptr: ::std::ptr::null_mut()
} }
@ -113,7 +118,7 @@ pub fn handle_nondispatchable_macro() -> Tokens {
macro_rules! handle_nondispatchable { macro_rules! handle_nondispatchable {
($name: ident) => { ($name: ident) => {
#[repr(C)] #[repr(C)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash)] #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Default)]
pub struct $name (uint64_t); pub struct $name (uint64_t);
impl $name{ impl $name{
@ -757,11 +762,12 @@ impl<'a> ConstantExt for ExtensionConstant<'a> {
} }
pub fn generate_extension_constants<'a>( pub fn generate_extension_constants<'a>(
extension: &'a vk_parse::Extension, extension_name: &str,
extension_number: i64,
extension_items: &'a [vk_parse::ExtensionItem],
const_cache: &mut HashSet<&'a str>, const_cache: &mut HashSet<&'a str>,
) -> quote::Tokens { ) -> quote::Tokens {
let items = extension let items = extension_items
.items
.iter() .iter()
.filter_map(|item| match item { .filter_map(|item| match item {
vk_parse::ExtensionItem::Require { items, .. } => Some(items.iter()), vk_parse::ExtensionItem::Require { items, .. } => Some(items.iter()),
@ -788,12 +794,13 @@ pub fn generate_extension_constants<'a>(
} => { } => {
let ext_base = 1_000_000_000; let ext_base = 1_000_000_000;
let ext_block_size = 1000; let ext_block_size = 1000;
let extnumber = extnumber.unwrap_or_else(|| extension.number.expect("number")); let extnumber = extnumber.unwrap_or_else(|| extension_number);
let value = ext_base + (extnumber - 1) * ext_block_size + offset; let value = ext_base + (extnumber - 1) * ext_block_size + offset;
Some((Constant::Number(value as i32), Some(extends.clone()))) Some((Constant::Number(value as i32), Some(extends.clone())))
} }
_ => None, _ => None,
}?; }?;
let extends = extends?; let extends = extends?;
let ext_constant = ExtensionConstant { let ext_constant = ExtensionConstant {
name: &_enum.name, name: &_enum.name,
@ -801,7 +808,7 @@ pub fn generate_extension_constants<'a>(
}; };
let ident = name_to_tokens(&extends); let ident = name_to_tokens(&extends);
let impl_block = bitflags_impl_block(ident, &extends, &[&ext_constant]); let impl_block = bitflags_impl_block(ident, &extends, &[&ext_constant]);
let doc_string = format!("Generated from '{}'", extension.name); let doc_string = format!("Generated from '{}'", extension_name);
let q = quote!{ let q = quote!{
#[doc = #doc_string] #[doc = #doc_string]
#impl_block #impl_block
@ -817,11 +824,11 @@ pub fn generate_extension_constants<'a>(
} }
} }
pub fn generate_extension_commands( pub fn generate_extension_commands(
extension: &vk_parse::Extension, extension_name: &str,
items: &[vk_parse::ExtensionItem],
cmd_map: &CommandMap, cmd_map: &CommandMap,
) -> Tokens { ) -> Tokens {
let commands = extension let commands = items
.items
.iter() .iter()
.filter_map(|ext_item| match ext_item { .filter_map(|ext_item| match ext_item {
vk_parse::ExtensionItem::Require { items, .. } => { vk_parse::ExtensionItem::Require { items, .. } => {
@ -834,7 +841,7 @@ pub fn generate_extension_commands(
}) })
.flat_map(|iter| iter) .flat_map(|iter| iter)
.collect_vec(); .collect_vec();
let name = format!("{}Fn", extension.name.to_camel_case()); let name = format!("{}Fn", extension_name.to_camel_case());
let ident = Ident::from(&name[2..]); let ident = Ident::from(&name[2..]);
generate_function_pointers(ident, &commands) generate_function_pointers(ident, &commands)
} }
@ -843,12 +850,17 @@ pub fn generate_extension<'a>(
cmd_map: &CommandMap, cmd_map: &CommandMap,
const_cache: &mut HashSet<&'a str>, const_cache: &mut HashSet<&'a str>,
) -> Option<quote::Tokens> { ) -> Option<quote::Tokens> {
let _ = extension // let _ = extension
.supported // .supported
.as_ref() // .as_ref()
.filter(|s| s.as_str() == "vulkan")?; // .filter(|s| s.as_str() == "vulkan")?;
let extension_tokens = generate_extension_constants(extension, const_cache); let extension_tokens = generate_extension_constants(
let fp = generate_extension_commands(extension, cmd_map); &extension.name,
extension.number.unwrap_or(0),
&extension.items,
const_cache,
);
let fp = generate_extension_commands(&extension.name, &extension.items, cmd_map);
let q = quote!{ let q = quote!{
#fp #fp
#extension_tokens #extension_tokens
@ -983,7 +995,7 @@ pub fn generate_enum<'a>(
} else { } else {
let impl_block = bitflags_impl_block(ident, &_enum.name, &constants); let impl_block = bitflags_impl_block(ident, &_enum.name, &constants);
let enum_quote = quote!{ let enum_quote = quote!{
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(C)] #[repr(C)]
pub struct #ident(pub(crate) i32); pub struct #ident(pub(crate) i32);
#impl_block #impl_block
@ -1050,6 +1062,70 @@ fn is_static_array(field: &vkxml::Field) -> bool {
}) })
.unwrap_or(false) .unwrap_or(false)
} }
pub fn derive_default(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Option<Tokens> {
let name = name_to_tokens(&_struct.name);
let members = _struct.elements.iter().filter_map(|elem| match *elem {
vkxml::StructElement::Member(ref field) => Some(field),
_ => None,
});
let is_structure_type = |field: &vkxml::Field| field.basetype == "VkStructureType";
let is_pfn = |field: &vkxml::Field| {
field
.name
.as_ref()
.map(|n| n.contains("pfn"))
.unwrap_or(false)
};
let contains_pfn = members.clone().any(is_pfn);
let contains_ptr = members.clone().any(|field| field.reference.is_some());
let contains_strucutre_type = members.clone().any(is_structure_type);
let contains_static_array = members.clone().any(is_static_array);
if !(contains_ptr || contains_pfn || contains_strucutre_type || contains_static_array) {
return None;
};
let default_fields = members.clone().map(|field| {
let param_ident = field.param_ident();
if is_structure_type(field) {
let ty = field
.type_enums
.as_ref()
.and_then(|ty| ty.split(',').nth(0));
if let Some(variant) = ty {
let variant_ident = variant_ident("VkStructureType", variant);
quote!{
#param_ident: StructureType::#variant_ident
}
} else {
quote!{
#param_ident: unsafe { ::std::mem::zeroed() }
}
}
} else if field.reference.is_some() || is_static_array(field) || is_pfn(field) {
quote!{
#param_ident: unsafe { ::std::mem::zeroed() }
}
} else {
let ty = field.type_tokens();
quote!{
#param_ident: #ty::default()
}
}
});
let q = quote!{
impl ::std::default::Default for #name {
fn default() -> #name {
#name {
#(
#default_fields
),*
}
}
}
};
Some(q)
}
pub fn derive_debug(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Option<Tokens> { pub fn derive_debug(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Option<Tokens> {
let name = name_to_tokens(&_struct.name); let name = name_to_tokens(&_struct.name);
let members = _struct.elements.iter().filter_map(|elem| match *elem { let members = _struct.elements.iter().filter_map(|elem| match *elem {
@ -1120,14 +1196,25 @@ pub fn generate_struct(_struct: &vkxml::Struct, union_types: &HashSet<&str>) ->
}); });
let debug_tokens = derive_debug(_struct, union_types); let debug_tokens = derive_debug(_struct, union_types);
let dbg_str = if debug_tokens.is_none() { quote!(Debug,) } else {quote!()}; let default_tokens = derive_default(_struct, union_types);
let dbg_str = if debug_tokens.is_none() {
quote!(Debug,)
} else {
quote!()
};
let default_str = if default_tokens.is_none() {
quote!(Default,)
} else {
quote!()
};
quote!{ quote!{
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone, #dbg_str)] #[derive(Copy, Clone, #default_str #dbg_str)]
pub struct #name { pub struct #name {
#(#params,)* #(#params,)*
} }
#debug_tokens #debug_tokens
#default_tokens
} }
} }
@ -1184,6 +1271,11 @@ fn generate_union(union: &vkxml::Union) -> Tokens {
pub union #name { pub union #name {
#(#fields),* #(#fields),*
} }
impl ::std::default::Default for #name {
fn default() -> #name {
unsafe { ::std::mem::zeroed() }
}
}
} }
} }
pub fn generate_definition( pub fn generate_definition(
@ -1296,8 +1388,13 @@ pub fn write_source_code(path: &Path) {
}) })
.nth(0) .nth(0)
.expect("extension"); .expect("extension");
spec2.0.iter().for_each(|item| match item {
vk_parse::RegistryItem::Enums { name, .. } => println!("{:?}", name),
_ => (),
});
let spec = vk_parse::parse_file_as_vkxml(path); let spec = vk_parse::parse_file_as_vkxml(path);
//println!("{:#?}", spec);
let commands: HashMap<vkxml::Identifier, &vkxml::Command> = spec let commands: HashMap<vkxml::Identifier, &vkxml::Command> = spec
.elements .elements
.iter() .iter()