From 7ece9423a2e54d65aa5b2aad7d38dde6738cf254 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Wed, 18 Oct 2023 23:39:36 +0330 Subject: [PATCH] Make tuples constructible --- examples/memory_management/main.cpp | 24 ++++++++++++------------ examples/memory_management/main.zng | 5 ++--- examples/memory_management/out.txt | 21 ++++++++++++++------- zngur-generator/src/lib.rs | 10 ++++++++++ zngur-generator/src/rust.rs | 24 ++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 22 deletions(-) diff --git a/examples/memory_management/main.cpp b/examples/memory_management/main.cpp index d3a4201..fa8e4ec 100644 --- a/examples/memory_management/main.cpp +++ b/examples/memory_management/main.cpp @@ -1,19 +1,14 @@ +#include #include #include #include "./generated.h" -// 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 BoxDyn = rust::Box>; template using RmDyn = rust::RefMut>; -using rust::crate::consume_and_panic; -using rust::crate::consume_n_times; -using rust::crate::PrintOnDrop; -using rust::crate::PrintOnDropConsumer; -using rust::crate::PrintOnDropPair; +using namespace rust::crate; class CppPrintOnDropHolder : public PrintOnDropConsumer { rust::Unit consume(PrintOnDrop p) override { @@ -139,8 +134,7 @@ int main() { 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([&] { + rust::Box>>>::make_box([&] { if (i == 3) { return Option::None(); } @@ -149,12 +143,18 @@ int main() { })); 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 { + rust::Box>>::make_box( + [](PrintOnDrop p) -> rust::Unit { std::cout << "Checkpoint 42" << std::endl; return {}; })); } std::cout << "Checkpoint 43" << std::endl; + { + auto tuple = rust::Tuple( + PrintOnDrop(rust::Str::from_char_star("field_0")), 5, + PrintOnDrop(rust::Str::from_char_star("field_2"))); + std::cout << "Checkpoint 44" << std::endl; + } + std::cout << "Checkpoint 45" << std::endl; } diff --git a/examples/memory_management/main.zng b/examples/memory_management/main.zng index b6837cf..b8f0efe 100644 --- a/examples/memory_management/main.zng +++ b/examples/memory_management/main.zng @@ -5,9 +5,8 @@ type () { wellknown_traits(Copy); } -type (i32, u32) { - #layout(size = 8, align = 4); - wellknown_traits(Copy); +type (crate::PrintOnDrop, i32, crate::PrintOnDrop) { + #layout(size = 40, align = 8); } type bool { diff --git a/examples/memory_management/out.txt b/examples/memory_management/out.txt index 7a94788..2dff9a5 100644 --- a/examples/memory_management/out.txt +++ b/examples/memory_management/out.txt @@ -40,7 +40,8 @@ Checkpoint 20 Checkpoint 21 PrintOnDrop(A) has been dropped Checkpoint 22 -thread '' panicked at 'consume_and_panic executed with value B', examples/memory_management/src/lib.rs:29:9 +thread '' panicked at examples/memory_management/src/lib.rs:29:9: +consume_and_panic executed with value B note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace PrintOnDrop(B) has been dropped PrintOnDrop(A) has been dropped @@ -58,15 +59,15 @@ Checkpoint 30 PrintOnDrop(elem1) has been dropped PrintOnDrop(elem2) has been dropped Checkpoint 31 -[main.cpp:117] PrintOnDrop(rust::Str::from_char_star("dbg_A")) = PrintOnDrop( +[main.cpp:112] PrintOnDrop(rust::Str::from_char_star("dbg_A")) = PrintOnDrop( "dbg_A", ) Checkpoint 32 -[main.cpp:119] std::move(p1) = PrintOnDrop( +[main.cpp:114] std::move(p1) = PrintOnDrop( "dbg_A", ) Checkpoint 33 -[main.cpp:121] p2 = PrintOnDrop( +[main.cpp:116] p2 = PrintOnDrop( "dbg_A", ) Checkpoint 34 @@ -80,9 +81,15 @@ 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 +PrintOnDrop(elem1) has been dropped +Checkpoint 42 +PrintOnDrop(elem2) has been dropped +Checkpoint 42 +PrintOnDrop(elem3) has been dropped Checkpoint 43 +Checkpoint 44 +PrintOnDrop(field_0) has been dropped +PrintOnDrop(field_2) has been dropped +Checkpoint 45 PrintOnDrop(C) has been dropped diff --git a/zngur-generator/src/lib.rs b/zngur-generator/src/lib.rs index e61d24a..f63a4f4 100644 --- a/zngur-generator/src/lib.rs +++ b/zngur-generator/src/lib.rs @@ -97,6 +97,16 @@ impl ZngurGenerator { } } } + if let RustType::Tuple(fields) = &ty_def.ty { + if !fields.is_empty() { + let rust_link_name = rust_file.add_tuple_constructor(&fields); + constructors.push(CppFnSig { + rust_link_name, + inputs: fields.iter().map(|x| x.into_cpp()).collect(), + output: ty_def.ty.into_cpp(), + }); + } + } for wellknown_trait in ty_def.wellknown_traits { let data = rust_file.add_wellknown_trait(&ty_def.ty, wellknown_trait); wellknown_traits.push(data); diff --git a/zngur-generator/src/rust.rs b/zngur-generator/src/rust.rs index df3cd5a..bd9dacc 100644 --- a/zngur-generator/src/rust.rs +++ b/zngur-generator/src/rust.rs @@ -476,6 +476,30 @@ pub extern "C" fn {mangled_name}( mangled_name } + pub fn add_tuple_constructor(&mut self, fields: &[RustType]) -> String { + let constructor = mangle_name(&fields.iter().join("&")); + w!( + self, + r#" +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn {constructor}("# + ); + for name in 0..fields.len() { + w!(self, "f_{name}: *mut u8, "); + } + w!( + self, + r#"o: *mut u8) {{ unsafe {{ + ::std::ptr::write(o as *mut _, ("# + ); + for (name, ty) in fields.iter().enumerate() { + w!(self, "::std::ptr::read(f_{name} as *mut {ty}), "); + } + wln!(self, ")) }} }}"); + constructor + } + pub fn add_constructor( &mut self, rust_name: &str,