Skip to content

Commit 2b9cd91

Browse files
committed
Load ASTs first, print docs for geters/setters
1 parent a262fc5 commit 2b9cd91

File tree

10 files changed

+676
-8
lines changed

10 files changed

+676
-8
lines changed

c-bindings-gen/src/main.rs

Lines changed: 139 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ fn println_struct<W: std::io::Write>(w: &mut W, s: &syn::ItemStruct, types: &mut
496496
and_token: syn::Token!(&)(Span::call_site()), lifetime: None, mutability: None,
497497
elem: Box::new(field.ty.clone()) });
498498
if types.understood_c_type(&ref_type, Some(&gen_types)) {
499+
println_docs(w, &field.attrs, "");
499500
write!(w, "#[no_mangle]\npub extern \"C\" fn {}_get_{}(this_ptr: &{}) -> ", struct_name, ident, struct_name).unwrap();
500501
types.print_c_type(w, &ref_type, Some(&gen_types), true);
501502
write!(w, " {{\n\t").unwrap();
@@ -507,6 +508,7 @@ fn println_struct<W: std::io::Write>(w: &mut W, s: &syn::ItemStruct, types: &mut
507508
}
508509

509510
if types.understood_c_type(&field.ty, Some(&gen_types)) {
511+
println_docs(w, &field.attrs, "");
510512
write!(w, "#[no_mangle]\npub extern \"C\" fn {}_set_{}(this_ptr: &mut {}, val: ", struct_name, ident, struct_name).unwrap();
511513
types.print_c_type(w, &field.ty, Some(&gen_types), false);
512514
write!(w, ") {{\n\t").unwrap();
@@ -567,7 +569,18 @@ fn println_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &TypeRes
567569
if trait_path.0.is_some() { unimplemented!(); }
568570
if types.understood_c_path(&trait_path.1) {
569571
eprintln!("WIP: IMPL {:?} FOR {}", trait_path.1, ident);
572+
} else if let Some(trait_ident) = trait_path.1.get_ident() {
570573
//XXX: implement for basic things like ToString and implement traits
574+
match &format!("{}", trait_ident) as &str {
575+
"From" => {},
576+
"Default" => {
577+
write!(w, "#[no_mangle]\npub extern \"C\" fn {}_default() -> {} {{\n", ident, ident).unwrap();
578+
write!(w, "\t{} {{ inner: Box::into_raw(Box::new(Default::default())) }}\n", ident).unwrap();
579+
write!(w, "}}\n").unwrap();
580+
},
581+
"PartialEq" => {},
582+
_ => {},
583+
}
571584
}
572585
} else {
573586
let declared_type = types.get_declared_type(&ident).unwrap();
@@ -678,14 +691,15 @@ fn should_export(path: &str) -> bool {
678691
}
679692
}
680693

681-
fn convert_file(path: &str, out_path: &str, orig_crate: &str, module: &str, header_file: &mut File) {
694+
struct FullLibraryAST {
695+
files: HashMap<String, syn::File>,
696+
}
697+
698+
fn convert_file(libast: &FullLibraryAST, crate_types: &CrateTypes, path: &str, out_path: &str, orig_crate: &str, module: &str, header_file: &mut File) {
682699
if !should_export(path) { return; }
683700
eprintln!("Converting {}...", path);
684701

685-
let mut file = File::open(path).expect("Unable to open file");
686-
let mut src = String::new();
687-
file.read_to_string(&mut src).expect("Unable to read file");
688-
let syntax = syn::parse_file(&src).expect("Unable to parse file");
702+
let syntax = if let Some(ast) = libast.files.get(module) { ast } else { return };
689703

690704
assert!(syntax.shebang.is_none()); // Not sure what this is, hope we dont have one
691705

@@ -744,15 +758,17 @@ fn convert_file(path: &str, out_path: &str, orig_crate: &str, module: &str, head
744758
if should_export(&f_path) {
745759
println_docs(&mut out, &m.attrs, "");
746760
write!(out, "pub mod {};\n", m.ident).unwrap();
747-
convert_file(&f_path, &format!("{}/{}.rs", (out_path.as_ref() as &Path).parent().unwrap().display(), m.ident),
761+
convert_file(libast, crate_types, &f_path,
762+
&format!("{}/{}.rs", (out_path.as_ref() as &Path).parent().unwrap().display(), m.ident),
748763
orig_crate, &new_mod, header_file);
749764
}
750765
} else {
751766
let f_path = format!("{}/{}/mod.rs", (path.as_ref() as &Path).parent().unwrap().display(), m.ident);
752767
if should_export(&f_path) {
753768
println_docs(&mut out, &m.attrs, "");
754769
write!(out, "pub mod {};\n", m.ident).unwrap();
755-
convert_file(&f_path, &format!("{}/{}/mod.rs", (out_path.as_ref() as &Path).parent().unwrap().display(), m.ident),
770+
convert_file(libast, crate_types, &f_path,
771+
&format!("{}/{}/mod.rs", (out_path.as_ref() as &Path).parent().unwrap().display(), m.ident),
756772
orig_crate, &new_mod, header_file);
757773
}
758774
}
@@ -784,6 +800,115 @@ fn convert_file(path: &str, out_path: &str, orig_crate: &str, module: &str, head
784800
out.flush().unwrap();
785801
}
786802

803+
fn load_ast(path: &str, module: String, ast_storage: &mut FullLibraryAST) {
804+
if !should_export(path) { return; }
805+
eprintln!("Loading {}...", path);
806+
807+
let mut file = File::open(path).expect("Unable to open file");
808+
let mut src = String::new();
809+
file.read_to_string(&mut src).expect("Unable to read file");
810+
let syntax = syn::parse_file(&src).expect("Unable to parse file");
811+
812+
assert_eq!(export_status(&syntax.attrs), ExportStatus::Export);
813+
814+
for item in syntax.items.iter() {
815+
match item {
816+
syn::Item::Mod(m) => {
817+
if let syn::Visibility::Public(_) = m.vis {
818+
match export_status(&m.attrs) {
819+
ExportStatus::Export => {},
820+
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
821+
}
822+
823+
let f_path = format!("{}/{}.rs", (path.as_ref() as &Path).parent().unwrap().display(), m.ident);
824+
let new_mod = if module.is_empty() { format!("{}", m.ident) } else { format!("{}::{}", module, m.ident) };
825+
if let Ok(_) = File::open(&f_path) {
826+
if should_export(&f_path) {
827+
load_ast(&f_path, new_mod, ast_storage);
828+
}
829+
} else {
830+
let f_path = format!("{}/{}/mod.rs", (path.as_ref() as &Path).parent().unwrap().display(), m.ident);
831+
if should_export(&f_path) {
832+
load_ast(&f_path, new_mod, ast_storage);
833+
}
834+
}
835+
}
836+
},
837+
_ => {},
838+
}
839+
}
840+
ast_storage.files.insert(module, syntax);
841+
}
842+
843+
fn walk_ast<'a>(path: &str, module: String, ast_storage: &'a FullLibraryAST, crate_types: &mut CrateTypes<'a>) {
844+
if !should_export(path) { return; }
845+
eprintln!("Walking {}...", path);
846+
let syntax = if let Some(ast) = ast_storage.files.get(&module) { ast } else { return };
847+
assert_eq!(export_status(&syntax.attrs), ExportStatus::Export);
848+
849+
for item in syntax.items.iter() {
850+
match item {
851+
syn::Item::Mod(m) => {
852+
if let syn::Visibility::Public(_) = m.vis {
853+
match export_status(&m.attrs) {
854+
ExportStatus::Export => {},
855+
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
856+
}
857+
858+
let f_path = format!("{}/{}.rs", (path.as_ref() as &Path).parent().unwrap().display(), m.ident);
859+
let new_mod = if module.is_empty() { format!("{}", m.ident) } else { format!("{}::{}", module, m.ident) };
860+
if let Ok(_) = File::open(&f_path) {
861+
if should_export(&f_path) {
862+
walk_ast(&f_path, new_mod, ast_storage, crate_types);
863+
}
864+
} else {
865+
let f_path = format!("{}/{}/mod.rs", (path.as_ref() as &Path).parent().unwrap().display(), m.ident);
866+
if should_export(&f_path) {
867+
walk_ast(&f_path, new_mod, ast_storage, crate_types);
868+
}
869+
}
870+
}
871+
},
872+
syn::Item::Struct(s) => {
873+
if let syn::Visibility::Public(_) = s.vis {
874+
match export_status(&s.attrs) {
875+
ExportStatus::Export => {},
876+
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
877+
}
878+
let struct_path = format!("{}::{}", module, s.ident);
879+
crate_types.structs.insert(struct_path, &s);
880+
}
881+
},
882+
syn::Item::Trait(t) => {
883+
if let syn::Visibility::Public(_) = t.vis {
884+
match export_status(&t.attrs) {
885+
ExportStatus::Export => {},
886+
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
887+
}
888+
let trait_path = format!("{}::{}", module, t.ident);
889+
crate_types.traits.insert(trait_path, &t);
890+
}
891+
},
892+
syn::Item::Impl(i) => {
893+
match export_status(&i.attrs) {
894+
ExportStatus::Export => {},
895+
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
896+
}
897+
if i.defaultness.is_none() && i.unsafety.is_none() && i.trait_.is_some() {
898+
if let syn::Type::Path(path) = &*i.self_ty {
899+
if let Some(ident) = single_ident_generic_path_to_ident(&path.path) {
900+
if let Some(trait_ident) = single_ident_generic_path_to_ident(&i.trait_.as_ref().unwrap().1) {
901+
crate_types.trait_impls.entry(format!("{}::{}", module, ident)).or_insert(Vec::new()).push(trait_ident);
902+
}
903+
}
904+
}
905+
}
906+
},
907+
_ => {},
908+
}
909+
}
910+
}
911+
787912
fn main() {
788913
let args: Vec<String> = env::args().collect();
789914
if args.len() != 5 {
@@ -794,7 +919,13 @@ fn main() {
794919
let mut header_file = std::fs::OpenOptions::new().write(true).append(true)
795920
.open(&args[4]).expect("Unable to open new header file");
796921

797-
convert_file(&(args[1].clone() + "/lib.rs"), &(args[2].clone() + "lib.rs"), &args[3], "", &mut header_file);
922+
let mut libast = FullLibraryAST { files: HashMap::new() };
923+
load_ast(&(args[1].clone() + "/lib.rs"), "".to_string(), &mut libast);
924+
925+
let mut libtypes = CrateTypes { traits: HashMap::new(), trait_impls: HashMap::new(), structs: HashMap::new() };
926+
walk_ast(&(args[1].clone() + "/lib.rs"), "".to_string(), &libast, &mut libtypes);
927+
928+
convert_file(&libast, &libtypes, &(args[1].clone() + "/lib.rs"), &(args[2].clone() + "lib.rs"), &args[3], "", &mut header_file);
798929

799930
header_file.flush().unwrap();
800931
}

c-bindings-gen/src/types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ pub enum DeclType<'a> {
169169
}
170170

171171
pub struct CrateTypes<'a> {
172+
pub structs: HashMap<String, &'a syn::ItemStruct>,
172173
pub traits: HashMap<String, &'a syn::ItemTrait>,
173174
pub trait_impls: HashMap<String, Vec<&'a syn::Ident>>,
174175
}

0 commit comments

Comments
 (0)