From 94cfb806114c1db87aa7e8d345a9df88f942e227 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 27 Jan 2024 17:38:12 +0200 Subject: [PATCH] analysis/cdecl: add a way to dump a "pseudo-Rust" view of all parsed `CDecl`s. --- analysis/src/cdecl.rs | 85 +++++++++++++++++++++++++++++++++++ analysis/src/lib.rs | 36 +++++++++++++++ generator-rewrite/src/main.rs | 3 ++ 3 files changed, 124 insertions(+) diff --git a/analysis/src/cdecl.rs b/analysis/src/cdecl.rs index ddc88ea4a..105ef89fa 100644 --- a/analysis/src/cdecl.rs +++ b/analysis/src/cdecl.rs @@ -390,4 +390,89 @@ impl<'a> CDecl<'a> { bitfield_width, }) } + + pub fn to_pseudo_rust(&self) -> String { + self.to_pseudo_rust_with_external_len(None) + } + pub fn to_pseudo_rust_with_external_len(&self, external_len: Option<&str>) -> String { + let CDecl { + ty, + name, + bitfield_width, + } = self; + let decl = format!( + "{name}: {}", + ty.to_pseudo_rust_with_external_len(external_len) + ); + match bitfield_width { + Some(width) => format!("#[bitfield({width})] {decl}"), + None => decl, + } + } +} + +impl CType<'_> { + pub fn to_pseudo_rust_with_external_len(&self, external_len: Option<&str>) -> String { + if let Some(len) = external_len { + match self { + CType::Ptr { + implicit_for_decay: false, + is_const, + pointee, + } => { + let const_or_mut = if *is_const { "const" } else { "mut" }; + format!("*{const_or_mut} [{}; dyn {len}]", pointee.to_pseudo_rust()) + } + _ => unreachable!(), + } + } else { + self.to_pseudo_rust() + } + } + pub fn to_pseudo_rust(&self) -> String { + match self { + &CType::Base(CBaseType { struct_tag, name }) => { + if struct_tag { + format!("/*struct*/{name}") + } else { + name.to_string() + } + } + CType::Ptr { + implicit_for_decay, + is_const, + pointee, + } => { + if let CType::Func { ret_ty, params } = &**pointee { + assert!(!implicit_for_decay); + assert!(!is_const); + let params = if params.is_empty() { + "".to_string() + } else { + params.iter().fold("\n".to_string(), |params, param| { + params + " " + ¶m.to_pseudo_rust() + ",\n" + }) + }; + format!( + "unsafe extern fn({params}){}", + ret_ty + .as_ref() + .map(|ty| format!(" -> {}", ty.to_pseudo_rust())) + .unwrap_or_default() + ) + } else { + let const_or_mut = if *is_const { "const" } else { "mut" }; + format!("*{const_or_mut} {}", pointee.to_pseudo_rust()) + } + } + CType::Array { element, len } => { + let len = match len { + CArrayLen::Named(name) => name.to_string(), + CArrayLen::Literal(len) => len.to_string(), + }; + format!("[{}; {len}]", element.to_pseudo_rust()) + } + CType::Func { .. } => unreachable!(), + } + } } diff --git a/analysis/src/lib.rs b/analysis/src/lib.rs index 81a7707de..09c41fc9d 100644 --- a/analysis/src/lib.rs +++ b/analysis/src/lib.rs @@ -1,3 +1,4 @@ +mod cdecl; mod xml; use std::{fs, path::Path}; @@ -17,6 +18,41 @@ impl Analysis { video: Library::new(vulkan_headers_path.join("registry/video.xml")), } } + + pub fn dump_as_pseudo_rust(&self) { + for fp in &self.vk._xml.funcpointers { + eprintln!( + "type {} = {};", + fp.c_decl.name, + fp.c_decl.ty.to_pseudo_rust() + ); + } + for st in &self.vk._xml.structs { + eprintln!("struct {} {{", st.name); + for m in &st.members { + let len = m.altlen.as_deref().or(m.len.as_deref()); + eprint!(" {}", m.c_decl.to_pseudo_rust_with_external_len(len)); + if let Some(val) = &m.values { + eprint!(" = {val}"); + } + eprintln!(","); + } + eprintln!("}}"); + } + for cmd in &self.vk._xml.commands { + eprintln!("unsafe extern fn {}(", cmd.name); + for p in &cmd.params { + let len = p.altlen.as_deref().or(p.len.as_deref()); + eprint!(" {}", p.c_decl.to_pseudo_rust_with_external_len(len)); + eprintln!(","); + } + eprint!(")"); + if let Some(ret_ty) = &cmd.return_type { + eprint!(" -> {}", ret_ty.to_pseudo_rust()); + } + eprintln!(";"); + } + } } #[derive(Debug)] diff --git a/generator-rewrite/src/main.rs b/generator-rewrite/src/main.rs index fb5ff861d..cc14b0fbf 100644 --- a/generator-rewrite/src/main.rs +++ b/generator-rewrite/src/main.rs @@ -4,4 +4,7 @@ fn main() { tracing_subscriber::fmt::init(); let _analysis = Analysis::new("generator/Vulkan-Headers"); // dbg!(_analysis); + if false { + _analysis.dump_as_pseudo_rust(); + } }