diff options
Diffstat (limited to 'codegen/command')
-rw-r--r-- | codegen/command/functions.rs | 62 | ||||
-rw-r--r-- | codegen/command/globals.rs | 15 | ||||
-rw-r--r-- | codegen/command/mod.rs | 2 |
3 files changed, 79 insertions, 0 deletions
diff --git a/codegen/command/functions.rs b/codegen/command/functions.rs new file mode 100644 index 0000000..6d1a3d3 --- /dev/null +++ b/codegen/command/functions.rs @@ -0,0 +1,62 @@ +use std::error::Error; +use std::str::FromStr; + +use opengl_registry::command::Command; +use proc_macro2::{LexError, TokenStream}; +use quote::{format_ident, quote}; + +use crate::codegen::formatting::{clean_param_name, fix_type}; + +pub fn create_command_functions( + commands: &[Command], +) -> Result<Vec<TokenStream>, Box<dyn Error>> +{ + commands.iter().map(|command| { + let command_name_str = command.prototype().name(); + + let command_name = format_ident!("{}", command.prototype().name()); + + let command_name_prefixless = format_ident!("{}", command.prototype() + .name() + .strip_prefix("gl") + .unwrap_or_else(|| command.prototype().name())); + + let command_args = command + .parameters() + .iter() + .map(|param| { + let param_name = format_ident!("{}", clean_param_name(param.name())); + + let param_type = TokenStream::from_str(&fix_type(param.get_type()))?; + + Ok::<_, LexError>(quote! { #param_name: #param_type }) + }).collect::<Result<Vec<_>, _>>()?; + + let command_return_type = TokenStream::from_str(&fix_type(command.prototype().return_type()))?; + + let command_arg_types = command + .parameters() + .iter() + .map(|param| TokenStream::from_str(&fix_type(param.get_type()))) + .collect::<Result<Vec<_>, _>>()?; + + let command_arg_names = command + .parameters() + .iter() + .map(|param| format_ident!("{}", clean_param_name(param.name()))) + .collect::<Vec<_>>(); + + Ok(quote! { + #[doc = #command_name_str] + #[allow(non_snake_case, clippy::too_many_arguments)] + pub unsafe fn #command_name_prefixless(#(#command_args),*) -> #command_return_type { + type GLFunc = + unsafe extern "C" fn(#(#command_arg_types),*) -> #command_return_type; + + let gl_func = std::mem::transmute::<_, GLFunc>(functions::#command_name); + + gl_func(#(#command_arg_names),*) + } + }) + }).collect() +} diff --git a/codegen/command/globals.rs b/codegen/command/globals.rs new file mode 100644 index 0000000..e522e68 --- /dev/null +++ b/codegen/command/globals.rs @@ -0,0 +1,15 @@ +use opengl_registry::command::Command; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; + +pub fn create_command_globals(commands: &[Command]) -> Vec<TokenStream> +{ + commands.iter().map(|command| { + let command_name = format_ident!("{}", command.prototype().name()); + + quote! { + #[allow(non_upper_case_globals)] + pub static mut #command_name: unsafe extern "C" fn() = function_not_loaded; + } + }).collect() +} diff --git a/codegen/command/mod.rs b/codegen/command/mod.rs new file mode 100644 index 0000000..7559bc1 --- /dev/null +++ b/codegen/command/mod.rs @@ -0,0 +1,2 @@ +pub mod functions; +pub mod globals; |