From 9e4315665fe5c016d14fa0acc476629d1580e415 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Tue, 10 Oct 2023 02:08:30 +0330 Subject: [PATCH] Fix dyn Fn special casing --- examples/memory_management/main.cpp | 37 ++++++++++++++++++++++++- examples/memory_management/main.zng | 29 ++++++++++++++++++++ examples/memory_management/out.txt | 13 +++++++++ zngur-generator/src/cpp.rs | 42 +++++++++++++++-------------- zngur-generator/src/rust.rs | 16 ++++++++--- 5 files changed, 113 insertions(+), 24 deletions(-) diff --git a/examples/memory_management/main.cpp b/examples/memory_management/main.cpp index 9997508..d3a4201 100644 --- a/examples/memory_management/main.cpp +++ b/examples/memory_management/main.cpp @@ -6,7 +6,7 @@ // Rust values are available in the `::rust` namespace from their absolute path // in Rust template using Vec = rust::std::vec::Vec; -// template using Option = rust::std::option::Option; +template using Option = rust::std::option::Option; template using BoxDyn = rust::Box>; template using RmDyn = rust::RefMut>; using rust::crate::consume_and_panic; @@ -122,4 +122,39 @@ int main() { std::cout << "Checkpoint 34" << std::endl; } std::cout << "Checkpoint 35" << std::endl; + { + auto p1 = Option::Some( + PrintOnDrop(rust::Str::from_char_star("option_A"))); + std::cout << "Checkpoint 36" << std::endl; + auto p2 = Option::Some( + PrintOnDrop(rust::Str::from_char_star("option_B"))); + std::cout << "Checkpoint 37" << std::endl; + p2.take(); + std::cout << "Checkpoint 38" << std::endl; + p2.take(); + std::cout << "Checkpoint 39" << std::endl; + } + std::cout << "Checkpoint 40" << std::endl; + { + const char *elems[3] = {"elem1", "elem2", "elem3"}; + int i = 0; + auto iter = rust::std::iter::from_fn( + ::rust::Box<::rust::Dyn<::rust::Fn<::rust::std::option::Option< + ::rust::crate::PrintOnDrop>>>>::make_box([&] { + if (i == 3) { + return Option::None(); + } + return Option::Some( + PrintOnDrop(rust::Str::from_char_star(elems[i++]))); + })); + std::cout << "Checkpoint 41" << std::endl; + iter.for_each( + ::rust::Box< + ::rust::Dyn<::rust::Fn<::rust::crate::PrintOnDrop, rust::Unit>>>:: + make_box([](PrintOnDrop p) -> rust::Unit { + std::cout << "Checkpoint 42" << std::endl; + return {}; + })); + } + std::cout << "Checkpoint 43" << std::endl; } diff --git a/examples/memory_management/main.zng b/examples/memory_management/main.zng index 9e82bfa..722f8dc 100644 --- a/examples/memory_management/main.zng +++ b/examples/memory_management/main.zng @@ -14,6 +14,14 @@ type str { wellknown_traits(?Sized); } +type Box ::std::option::Option> { + #layout(size = 16, align = 8); +} + +type Box { + #layout(size = 16, align = 8); +} + mod crate { type PrintOnDropPair { #layout(size = 32, align = 8); @@ -60,6 +68,27 @@ mod ::std { fn unwrap(self) -> &crate::PrintOnDrop; } + + type Option { + #layout(size = 16, align = 8); + + constructor Some(crate::PrintOnDrop); + constructor None; + + fn take(&mut self) -> Option; + } + } + + mod iter { + type FromFn ::std::option::Option>> { + #layout(size = 16, align = 8); + + fn for_each>(self, Box); + } + + fn from_fn ::std::option::Option>>( + Box ::std::option::Option> + ) -> FromFn ::std::option::Option>>; } mod vec { diff --git a/examples/memory_management/out.txt b/examples/memory_management/out.txt index 96d49a3..7a94788 100644 --- a/examples/memory_management/out.txt +++ b/examples/memory_management/out.txt @@ -72,4 +72,17 @@ Checkpoint 33 Checkpoint 34 PrintOnDrop(dbg_A) has been dropped Checkpoint 35 +Checkpoint 36 +Checkpoint 37 +PrintOnDrop(option_B) has been dropped +Checkpoint 38 +Checkpoint 39 +PrintOnDrop(option_A) has been dropped +Checkpoint 40 +Checkpoint 41 +PrintOnDrop(iter_elem) has been dropped +PrintOnDrop(iter_elem) has been dropped +PrintOnDrop(iter_elem) has been dropped +Checkpoint 42 +Checkpoint 43 PrintOnDrop(C) has been dropped diff --git a/zngur-generator/src/cpp.rs b/zngur-generator/src/cpp.rs index abee6cc..c91be63 100644 --- a/zngur-generator/src/cpp.rs +++ b/zngur-generator/src/cpp.rs @@ -37,7 +37,10 @@ impl CppPath { } fn need_header(&self) -> bool { - self.0.first().map(|x| x.as_str()) == Some("rust") && self.0 != ["rust", "Unit"] + self.0.first().map(|x| x.as_str()) == Some("rust") + && self.0 != ["rust", "Unit"] + && self.0 != ["rust", "Ref"] + && self.0 != ["rust", "RefMut"] } pub(crate) fn from_rust_path(path: &[String]) -> CppPath { @@ -107,13 +110,7 @@ impl CppType { } self.path.emit_in_namespace(state, |state| { if !self.generic_args.is_empty() { - writeln!( - state, - "template<{}>", - (0..self.generic_args.len()) - .map(|n| format!("typename T{n}")) - .join(", ") - )?; + writeln!(state, "template")?; } writeln!(state, "struct {};", self.path.name()) }) @@ -345,16 +342,16 @@ impl CppTraitDefinition { sig: CppFnSig { rust_link_name, - inputs: _, + inputs, output: _, }, } => { - // TODO: too special writeln!( state, "void {rust_link_name}(uint8_t *data, void destructor(uint8_t *), - void call(uint8_t *, uint8_t *, uint8_t *), - uint8_t *o);" + void call(uint8_t *, {} uint8_t *), + uint8_t *o);", + (0..inputs.len()).map(|_| "uint8_t *, ").join(" ") )?; } CppTraitDefinition::Normal { @@ -1086,18 +1083,24 @@ namespace rust {{ } match self.from_trait.as_ref().and_then(|k| traits.get(k)) { Some(CppTraitDefinition::Fn { sig }) => { - // TODO: too special let as_std_function = format!( "::std::function<{}({})>", sig.output, sig.inputs.iter().join(", ") ); - let ii_args = sig + let ii_names = sig + .inputs + .iter() + .enumerate() + .map(|(n, x)| format!("::rust::__zngur_internal_move_from_rust<{x}>(i{n})")) + .join(", "); + let uint8_t_ix = sig .inputs .iter() .enumerate() - .map(|(n, x)| format!("{x} ii{n} = *reinterpret_cast<{x} *>(i{n});")) - .join("\n"); + .map(|(n, _)| format!("uint8_t* i{n},")) + .join(" "); + let out_ty = &sig.output; writeln!( state, r#" @@ -1108,11 +1111,10 @@ auto data = new {as_std_function}(f); {link_name}( reinterpret_cast(data), [](uint8_t *d) {{ delete reinterpret_cast<{as_std_function}*>(d); }}, -[](uint8_t *d, uint8_t *i0, uint8_t *o) {{ -int32_t *oo = reinterpret_cast(o); -{ii_args} +[](uint8_t *d, {uint8_t_ix} uint8_t *o) {{ auto dd = reinterpret_cast<{as_std_function} *>(d); -*oo = (*dd)(ii0); +{out_ty} oo = (*dd)({ii_names}); +::rust::__zngur_internal_move_to_rust<{out_ty}>(o, oo); }}, ::rust::__zngur_internal_data_ptr(o)); return o; diff --git a/zngur-generator/src/rust.rs b/zngur-generator/src/rust.rs index 44762b2..9740c47 100644 --- a/zngur-generator/src/rust.rs +++ b/zngur-generator/src/rust.rs @@ -442,16 +442,26 @@ pub extern "C" fn {mangled_name}( pub extern "C" fn {mangled_name}( data: *mut u8, destructor: extern "C" fn(*mut u8), - call: extern "C" fn(data: *mut u8, i1: *mut u8, o: *mut u8), + call: extern "C" fn(data: *mut u8, {} o: *mut u8), o: *mut u8, ) {{ let this = unsafe {{ ZngurCppOpaqueOwnedObject::new(data, destructor) }}; - let r: Box = Box::new(move |i0| unsafe {{ + let r: Box = Box::new(move |{}| unsafe {{ _ = &this; let data = this.ptr(); "#, + inputs + .iter() + .enumerate() + .map(|(n, _)| format!("i{n}: *mut u8, ")) + .join(" "), + inputs + .iter() + .enumerate() + .map(|(n, ty)| format!("i{n}: {ty}")) + .join(", "), ); - self.call_cpp_function("call(data, ", 1); + self.call_cpp_function("call(data, ", inputs.len()); wln!( self, r#"