Skip to content

Commit

Permalink
analysis/cdecl: add a way to dump a "pseudo-Rust" view of all parsed …
Browse files Browse the repository at this point in the history
…`CDecl`s.
  • Loading branch information
eddyb committed Jan 28, 2024
1 parent 84a3dd2 commit fd9956a
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 0 deletions.
85 changes: 85 additions & 0 deletions analysis/src/cdecl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 + " " + &param.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!(),
}
}
}
36 changes: 36 additions & 0 deletions analysis/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod cdecl;
mod xml;

use log::debug;
Expand All @@ -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)]
Expand Down
3 changes: 3 additions & 0 deletions generator-rewrite/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ use analysis::Analysis;
fn main() {
env_logger::init();
let _analysis = Analysis::new("generator/Vulkan-Headers");
if false {
_analysis.dump_as_pseudo_rust();
}
}

0 comments on commit fd9956a

Please sign in to comment.