Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tuple support #3

Merged
merged 3 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions examples/memory_management/main.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
#include <cstdint>
#include <iostream>
#include <vector>

#include "./generated.h"

// Rust values are available in the `::rust` namespace from their absolute path
// in Rust
template <typename T> using Vec = rust::std::vec::Vec<T>;
template <typename T> using Option = rust::std::option::Option<T>;
template <typename T> using BoxDyn = rust::Box<rust::Dyn<T>>;
template <typename T> using RmDyn = rust::RefMut<rust::Dyn<T>>;
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 {
Expand Down Expand Up @@ -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<rust::Dyn<rust::Fn<Option<PrintOnDrop>>>>::make_box([&] {
if (i == 3) {
return Option<PrintOnDrop>::None();
}
Expand All @@ -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<rust::Dyn<rust::Fn<PrintOnDrop, rust::Unit>>>::make_box(
[](PrintOnDrop p) -> rust::Unit {
std::cout << "Checkpoint 42" << std::endl;
return {};
}));
}
std::cout << "Checkpoint 43" << std::endl;
{
auto tuple = rust::Tuple<PrintOnDrop, int32_t, PrintOnDrop>(
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;
}
4 changes: 4 additions & 0 deletions examples/memory_management/main.zng
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ type () {
wellknown_traits(Copy);
}

type (crate::PrintOnDrop, i32, crate::PrintOnDrop) {
#layout(size = 40, align = 8);
}

type bool {
#layout(size = 1, align = 1);
wellknown_traits(Copy);
Expand Down
21 changes: 14 additions & 7 deletions examples/memory_management/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ Checkpoint 20
Checkpoint 21
PrintOnDrop(A) has been dropped
Checkpoint 22
thread '<unnamed>' panicked at 'consume_and_panic executed with value B', examples/memory_management/src/lib.rs:29:9
thread '<unnamed>' 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
Expand All @@ -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
Expand All @@ -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
10 changes: 10 additions & 0 deletions zngur-generator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
29 changes: 28 additions & 1 deletion zngur-generator/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ impl IntoCpp for RustType {
if v.is_empty() {
return CppType::from("rust::Unit");
}
todo!()
CppType {
path: CppPath::from("rust::Tuple"),
generic_args: v.into_iter().map(|x| x.into_cpp()).collect(),
}
}
RustType::Dyn(tr, marker_bounds) => {
let tr_as_cpp_type = tr.into_cpp();
Expand Down Expand Up @@ -473,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,
Expand Down
8 changes: 8 additions & 0 deletions zngur-parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,13 @@ fn rust_type<'a>(
let unit = just(Token::ParenOpen)
.then(just(Token::ParenClose))
.map(|_| ParsedRustType::Tuple(vec![]));
let tuple = parser
.clone()
.separated_by(just(Token::Comma))
.allow_trailing()
.collect::<Vec<_>>()
.delimited_by(just(Token::ParenOpen), just(Token::ParenClose))
.map(|xs| ParsedRustType::Tuple(xs));
let slice = parser
.clone()
.map(|x| ParsedRustType::Slice(Box::new(x)))
Expand All @@ -748,6 +755,7 @@ fn rust_type<'a>(
scalar
.or(boxed)
.or(unit)
.or(tuple)
.or(slice)
.or(adt)
.or(reference)
Expand Down
11 changes: 11 additions & 0 deletions zngur-parser/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ type () {
);
}

#[test]
fn parse_tuple() {
check_success(
r#"
type (i8, u8) {
#layout(size = 0, align = 1);
}
"#,
);
}

#[test]
fn typo_in_wellknown_trait() {
check_fail(
Expand Down