diff --git a/crates/glue/tests/fixtures/single-tag-union/app.roc b/crates/glue/tests/fixtures/single-tag-union/app.roc new file mode 100644 index 0000000000..be494c5fad --- /dev/null +++ b/crates/glue/tests/fixtures/single-tag-union/app.roc @@ -0,0 +1,6 @@ +app "app" + packages { pf: "platform.roc" } + imports [] + provides [main] to pf + +main = OneTag diff --git a/crates/glue/tests/fixtures/single-tag-union/platform.roc b/crates/glue/tests/fixtures/single-tag-union/platform.roc new file mode 100644 index 0000000000..c6c13c5e58 --- /dev/null +++ b/crates/glue/tests/fixtures/single-tag-union/platform.roc @@ -0,0 +1,11 @@ +platform "test-platform" + requires {} { main : _ } + exposes [] + packages {} + imports [] + provides [mainForHost] + +SingleTagUnion : [OneTag] + +mainForHost : SingleTagUnion +mainForHost = main diff --git a/crates/glue/tests/fixtures/single-tag-union/src/lib.rs b/crates/glue/tests/fixtures/single-tag-union/src/lib.rs new file mode 100644 index 0000000000..c815430939 --- /dev/null +++ b/crates/glue/tests/fixtures/single-tag-union/src/lib.rs @@ -0,0 +1,99 @@ +mod test_glue; + +use indoc::indoc; +use test_glue::SingleTagUnion; + +extern "C" { + #[link_name = "roc__mainForHost_1_exposed_generic"] + fn roc_main(_: *mut SingleTagUnion); +} + +#[no_mangle] +pub extern "C" fn rust_main() -> i32 { + use std::cmp::Ordering; + use std::collections::hash_set::HashSet; + + let tag_union = unsafe { + let mut ret: core::mem::MaybeUninit = core::mem::MaybeUninit::uninit(); + + roc_main(ret.as_mut_ptr()); + + ret.assume_init() + }; + + // Verify that it has all the expected traits. + + assert!(tag_union == SingleTagUnion::OneTag); // PartialEq + assert!(tag_union.clone() == tag_union.clone()); // Clone + + assert!(tag_union.partial_cmp(&tag_union) == Some(Ordering::Equal)); // PartialOrd + assert!(tag_union.cmp(&tag_union) == Ordering::Equal); // Ord + + print!( + indoc!( + r#" + tag_union was: {:?} + "# + ), + tag_union, + ); // Debug + + let mut set = HashSet::new(); + + set.insert(tag_union.clone()); // Eq, Hash + set.insert(tag_union); + + assert_eq!(set.len(), 1); + + // Exit code + 0 +} + +// Externs required by roc_std and by the Roc app + +use core::ffi::c_void; +use std::ffi::CStr; +use std::os::raw::c_char; + +#[no_mangle] +pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void { + return libc::malloc(size); +} + +#[no_mangle] +pub unsafe extern "C" fn roc_realloc( + c_ptr: *mut c_void, + new_size: usize, + _old_size: usize, + _alignment: u32, +) -> *mut c_void { + return libc::realloc(c_ptr, new_size); +} + +#[no_mangle] +pub unsafe extern "C" fn roc_dealloc(c_ptr: *mut c_void, _alignment: u32) { + return libc::free(c_ptr); +} + +#[no_mangle] +pub unsafe extern "C" fn roc_panic(c_ptr: *mut c_void, tag_id: u32) { + match tag_id { + 0 => { + let slice = CStr::from_ptr(c_ptr as *const c_char); + let string = slice.to_str().unwrap(); + eprintln!("Roc hit a panic: {}", string); + std::process::exit(1); + } + _ => todo!(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn roc_memcpy(dst: *mut c_void, src: *mut c_void, n: usize) -> *mut c_void { + libc::memcpy(dst, src, n) +} + +#[no_mangle] +pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { + libc::memset(dst, c, n) +} diff --git a/crates/glue/tests/test_glue_cli.rs b/crates/glue/tests/test_glue_cli.rs index cc8831bfc3..ba35725c34 100644 --- a/crates/glue/tests/test_glue_cli.rs +++ b/crates/glue/tests/test_glue_cli.rs @@ -79,6 +79,9 @@ mod glue_cli_run { `Baz` is: NonRecursive::Baz `Blah 456` is: NonRecursive::Blah(456) "#), + single_tag_union:"single-tag-union" => indoc!(r#" + tag_union was: SingleTagUnion::OneTag + "#), union_without_padding:"union-without-padding" => indoc!(r#" tag_union was: NonRecursive::Foo("This is a test") `Foo "small str"` is: NonRecursive::Foo("small str")