mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Merge remote-tracking branch 'remote/main' into builtin-task
This commit is contained in:
commit
b489c44b19
262 changed files with 11354 additions and 5821 deletions
|
@ -3912,7 +3912,6 @@ fn list_range_length_overflow() {
|
|||
);
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
mod pattern_match {
|
||||
#[allow(unused_imports)]
|
||||
use crate::helpers::with_larger_debug_stack;
|
||||
|
@ -3926,9 +3925,10 @@ mod pattern_match {
|
|||
#[cfg(feature = "gen-dev")]
|
||||
use crate::helpers::dev::assert_evals_to;
|
||||
|
||||
use super::RocList;
|
||||
use super::{RocList, RocStr};
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn unary_exact_size_match() {
|
||||
assert_evals_to!(
|
||||
r"
|
||||
|
@ -3944,6 +3944,7 @@ mod pattern_match {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn many_exact_size_match() {
|
||||
assert_evals_to!(
|
||||
r"
|
||||
|
@ -3962,6 +3963,7 @@ mod pattern_match {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn ranged_matches_head() {
|
||||
with_larger_debug_stack(|| {
|
||||
assert_evals_to!(
|
||||
|
@ -3994,6 +3996,7 @@ mod pattern_match {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn ranged_matches_tail() {
|
||||
with_larger_debug_stack(|| {
|
||||
assert_evals_to!(
|
||||
|
@ -4026,6 +4029,7 @@ mod pattern_match {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn bind_variables() {
|
||||
assert_evals_to!(
|
||||
r"
|
||||
|
@ -4054,6 +4058,7 @@ mod pattern_match {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn order_list_size_tests_issue_4732() {
|
||||
assert_evals_to!(
|
||||
r"
|
||||
|
@ -4101,6 +4106,7 @@ mod pattern_match {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn rest_as() {
|
||||
assert_evals_to!(
|
||||
r"
|
||||
|
@ -4122,6 +4128,20 @@ mod pattern_match {
|
|||
RocList<u8>
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_str() {
|
||||
assert_evals_to!(
|
||||
r#"
|
||||
when ["d"] is
|
||||
[alone] -> [alone]
|
||||
other -> other
|
||||
"#,
|
||||
RocList::from_slice(&[RocStr::from("d")]),
|
||||
RocList<RocStr>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#[cfg(feature = "gen-wasm")]
|
||||
use crate::helpers::{wasm::assert_refcounts, RefCount::*};
|
||||
use crate::helpers::{wasm::assert_refcounts, RefCount::*, RefCountLoc::*};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use indoc::indoc;
|
||||
|
@ -25,8 +25,8 @@ fn str_inc() {
|
|||
),
|
||||
RocList<RocStr>,
|
||||
&[
|
||||
Live(3), // s
|
||||
Live(1) // result
|
||||
(StandardRC, Live(3)), // s
|
||||
(AfterSize, Live(1)) // result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -43,7 +43,63 @@ fn str_dealloc() {
|
|||
"#
|
||||
),
|
||||
bool,
|
||||
&[Deallocated]
|
||||
&[(StandardRC, Deallocated)]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn str_to_utf8() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
|
||||
Str.toUtf8 s
|
||||
"#
|
||||
),
|
||||
RocStr,
|
||||
&[
|
||||
(StandardRC, Live(1)), // s
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn str_from_utf8() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
|
||||
Str.toUtf8 s
|
||||
|> Str.fromUtf8
|
||||
"#
|
||||
),
|
||||
RocStr,
|
||||
&[
|
||||
(StandardRC, Live(1)), // s
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn str_to_utf8_dealloc() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
|
||||
Str.toUtf8 s
|
||||
|> List.len
|
||||
"#
|
||||
),
|
||||
i64,
|
||||
&[
|
||||
(StandardRC, Deallocated), // s
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -59,8 +115,8 @@ fn list_int_inc() {
|
|||
),
|
||||
RocList<RocList<i64>>,
|
||||
&[
|
||||
Live(3), // list
|
||||
Live(1) // result
|
||||
(StandardRC, Live(3)), // list
|
||||
(AfterSize, Live(1)) // result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -77,8 +133,26 @@ fn list_int_dealloc() {
|
|||
),
|
||||
u64,
|
||||
&[
|
||||
Deallocated, // list
|
||||
Deallocated // result
|
||||
(StandardRC, Deallocated), // list
|
||||
(StandardRC, Deallocated) // result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn list_str() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
[s, s, s]
|
||||
"#
|
||||
),
|
||||
RocList<RocStr>,
|
||||
&[
|
||||
(StandardRC, Live(3)), // s
|
||||
(AfterSize, Live(1)), // Result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -96,9 +170,192 @@ fn list_str_inc() {
|
|||
),
|
||||
RocList<RocList<RocStr>>,
|
||||
&[
|
||||
Live(6), // s
|
||||
Live(2), // list
|
||||
Live(1) // result
|
||||
(StandardRC, Live(3)), // s
|
||||
(AfterSize, Live(2)), // list
|
||||
(AfterSize, Live(1)) // result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn list_str_drop_first() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
list = [s, s, s]
|
||||
List.dropFirst list 1
|
||||
"#
|
||||
),
|
||||
RocList<RocList<RocStr>>,
|
||||
&[
|
||||
// Still has 3 refcounts cause the slice holds onto the list.
|
||||
// So nothing in the list is freed yet.
|
||||
(StandardRC, Live(3)), // s
|
||||
(AfterSize, Live(1)) // result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn list_str_take_first() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
list = [s, s, s]
|
||||
List.takeFirst list 1
|
||||
"#
|
||||
),
|
||||
RocList<RocList<RocStr>>,
|
||||
&[
|
||||
// Take will free tail of a unique list.
|
||||
(StandardRC, Live(1)), // s
|
||||
(AfterSize, Live(1)) // result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn list_str_split() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
list = [s, s, s]
|
||||
List.split list 1
|
||||
"#
|
||||
),
|
||||
(RocList<RocStr>, RocList<RocStr>),
|
||||
&[
|
||||
(StandardRC, Live(3)), // s
|
||||
(AfterSize, Live(2)), // list
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn list_str_split_zero() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
list = [s, s, s]
|
||||
List.split list 0
|
||||
"#
|
||||
),
|
||||
(RocList<RocStr>, RocList<RocStr>),
|
||||
&[
|
||||
(StandardRC, Live(3)), // s
|
||||
(AfterSize, Live(1)), // list
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn list_get() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
i1 = [s, s, s]
|
||||
List.get i1 1
|
||||
|> Result.withDefault ""
|
||||
"#
|
||||
),
|
||||
RocStr,
|
||||
&[
|
||||
(StandardRC, Live(1)), // s
|
||||
(AfterSize, Deallocated), // i1
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn list_map() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
i1 = [s, s, s]
|
||||
List.map i1 Str.toUtf8
|
||||
"#
|
||||
),
|
||||
RocList<RocStr>,
|
||||
&[
|
||||
(StandardRC, Live(3)), // s
|
||||
(AfterSize, Deallocated), // i1
|
||||
(AfterSize, Live(1)), // Result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn list_map_dealloc() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
i1 = [s, s, s]
|
||||
List.map i1 Str.toUtf8
|
||||
|> List.len
|
||||
"#
|
||||
),
|
||||
i64,
|
||||
&[
|
||||
(StandardRC, Deallocated), // s
|
||||
(AfterSize, Deallocated), // i1
|
||||
(AfterSize, Deallocated), // Result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn list_map2_dealloc_tail() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
i1 = [s, s, s]
|
||||
i2 = [1i32, 2]
|
||||
List.map2 i1 i2 \a, b -> (a, b)
|
||||
"#
|
||||
),
|
||||
RocList<(RocStr, i64)>,
|
||||
&[
|
||||
(StandardRC, Live(2)), // s
|
||||
(AfterSize, Deallocated), // i1
|
||||
(StandardRC, Deallocated), // i2
|
||||
(AfterSize, Live(1)), // Result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn list_map2_dealloc() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
i1 = [s, s, s]
|
||||
List.map2 i1 i1 \a, b -> (a, b)
|
||||
|> List.len
|
||||
"#
|
||||
),
|
||||
i64,
|
||||
&[
|
||||
(StandardRC, Deallocated), // s
|
||||
(AfterSize, Deallocated), // i1
|
||||
(AfterSize, Deallocated), // Result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -116,9 +373,9 @@ fn list_str_dealloc() {
|
|||
),
|
||||
u64,
|
||||
&[
|
||||
Deallocated, // s
|
||||
Deallocated, // list
|
||||
Deallocated // result
|
||||
(StandardRC, Deallocated), // s
|
||||
(AfterSize, Deallocated), // list
|
||||
(AfterSize, Deallocated) // result
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -136,7 +393,7 @@ fn struct_inc() {
|
|||
"#
|
||||
),
|
||||
[(i64, RocStr, RocStr); 2],
|
||||
&[Live(4)] // s
|
||||
&[(StandardRC, Live(4))] // s
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -154,7 +411,7 @@ fn struct_dealloc() {
|
|||
"#
|
||||
),
|
||||
i64,
|
||||
&[Deallocated] // s
|
||||
&[(StandardRC, Deallocated)] // s
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -180,7 +437,7 @@ fn union_nonrecursive_inc() {
|
|||
"#
|
||||
),
|
||||
(TwoStr, TwoStr, i64),
|
||||
&[Live(4)]
|
||||
&[(StandardRC, Live(4))]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -203,7 +460,7 @@ fn union_nonrecursive_dec() {
|
|||
"#
|
||||
),
|
||||
RocStr,
|
||||
&[Live(1)] // s
|
||||
&[(StandardRC, Live(1))] // s
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -228,9 +485,9 @@ fn union_recursive_inc() {
|
|||
),
|
||||
(Pointer, Pointer),
|
||||
&[
|
||||
Live(1), // s
|
||||
Live(2), // x
|
||||
Live(2), // e
|
||||
(StandardRC, Live(1)), // s
|
||||
(StandardRC, Live(2)), // x
|
||||
(StandardRC, Live(2)), // e
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -258,9 +515,9 @@ fn union_recursive_dec() {
|
|||
),
|
||||
Pointer,
|
||||
&[
|
||||
Live(1), // s
|
||||
Live(1), // sym
|
||||
Deallocated // e
|
||||
(StandardRC, Live(1)), // s
|
||||
(StandardRC, Live(1)), // sym
|
||||
(StandardRC, Deallocated) // e
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -294,13 +551,13 @@ fn refcount_different_rosetrees_inc() {
|
|||
),
|
||||
(Pointer, Pointer),
|
||||
&[
|
||||
Live(1), // s
|
||||
Live(3), // i1
|
||||
Live(2), // s1
|
||||
Live(1), // [i1, i1]
|
||||
Live(1), // i2
|
||||
Live(1), // [s1, s1]
|
||||
Live(1) // s2
|
||||
(StandardRC, Live(1)), // s
|
||||
(StandardRC, Live(3)), // i1
|
||||
(StandardRC, Live(2)), // s1
|
||||
(AfterSize, Live(1)), // [i1, i1]
|
||||
(StandardRC, Live(1)), // i2
|
||||
(AfterSize, Live(1)), // [s1, s1]
|
||||
(StandardRC, Live(1)) // s2
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -335,13 +592,13 @@ fn refcount_different_rosetrees_dec() {
|
|||
),
|
||||
i64,
|
||||
&[
|
||||
Deallocated, // s
|
||||
Deallocated, // i1
|
||||
Deallocated, // s1
|
||||
Deallocated, // [i1, i1]
|
||||
Deallocated, // i2
|
||||
Deallocated, // [s1, s1]
|
||||
Deallocated, // s2
|
||||
(StandardRC, Deallocated), // s
|
||||
(StandardRC, Deallocated), // i1
|
||||
(StandardRC, Deallocated), // s1
|
||||
(StandardRC, Deallocated), // [i1, i1]
|
||||
(StandardRC, Deallocated), // i2
|
||||
(StandardRC, Deallocated), // [s1, s1]
|
||||
(StandardRC, Deallocated), // s2
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -364,10 +621,10 @@ fn union_linked_list_inc() {
|
|||
),
|
||||
(Pointer, Pointer),
|
||||
&[
|
||||
Live(3), // s
|
||||
Live(1), // inner-most Cons
|
||||
Live(1), // middle Cons
|
||||
Live(2), // linked
|
||||
(StandardRC, Live(3)), // s
|
||||
(StandardRC, Live(1)), // inner-most Cons
|
||||
(StandardRC, Live(1)), // middle Cons
|
||||
(StandardRC, Live(2)), // linked
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -392,10 +649,10 @@ fn union_linked_list_dec() {
|
|||
),
|
||||
RocStr,
|
||||
&[
|
||||
Live(1), // s
|
||||
Deallocated, // Cons
|
||||
Deallocated, // Cons
|
||||
Deallocated, // Cons
|
||||
(StandardRC, Live(1)), // s
|
||||
(StandardRC, Deallocated), // Cons
|
||||
(StandardRC, Deallocated), // Cons
|
||||
(StandardRC, Deallocated), // Cons
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -403,7 +660,7 @@ fn union_linked_list_dec() {
|
|||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn union_linked_list_nil_dec() {
|
||||
let no_refcounts: &[crate::helpers::RefCount] = &[];
|
||||
let no_refcounts: &[(crate::helpers::RefCountLoc, crate::helpers::RefCount)] = &[];
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
|
@ -450,7 +707,7 @@ fn union_linked_list_long_dec() {
|
|||
"#
|
||||
),
|
||||
i64,
|
||||
&[Deallocated; 1_000]
|
||||
&[(StandardRC, Deallocated); 1_000]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -468,8 +725,8 @@ fn boxed_str_inc() {
|
|||
),
|
||||
(Pointer, Pointer),
|
||||
&[
|
||||
Live(1), // s
|
||||
Live(2), // b
|
||||
(StandardRC, Live(1)), // s
|
||||
(StandardRC, Live(2)), // b
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -491,8 +748,8 @@ fn boxed_str_dec() {
|
|||
),
|
||||
(i32, i32),
|
||||
&[
|
||||
Deallocated, // s
|
||||
Deallocated, // b
|
||||
(StandardRC, Deallocated), // s
|
||||
(StandardRC, Deallocated), // b
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -520,9 +777,9 @@ fn non_nullable_unwrapped_alignment_8() {
|
|||
),
|
||||
i64,
|
||||
&[
|
||||
Deallocated, // Val 4
|
||||
Deallocated, // Val 5
|
||||
Deallocated, // ZAdd _ _
|
||||
(StandardRC, Deallocated), // Val 4
|
||||
(StandardRC, Deallocated), // Val 5
|
||||
(StandardRC, Deallocated), // ZAdd _ _
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -565,9 +822,38 @@ fn reset_reuse_alignment_8() {
|
|||
),
|
||||
i64,
|
||||
&[
|
||||
Deallocated, // Val 4
|
||||
Deallocated, // Val 5
|
||||
Deallocated, // ZAdd _ _
|
||||
(StandardRC, Deallocated), // Val 4
|
||||
(StandardRC, Deallocated), // Val 5
|
||||
(StandardRC, Deallocated), // ZAdd _ _
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
fn basic_cli_parser() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
in =
|
||||
"d"
|
||||
|> Str.toUtf8
|
||||
|> List.keepOks \c -> Str.fromUtf8 [c]
|
||||
|
||||
out =
|
||||
when in is
|
||||
[alone] -> [alone]
|
||||
other -> other
|
||||
|
||||
List.len out
|
||||
"#
|
||||
),
|
||||
i64,
|
||||
&[
|
||||
(StandardRC, Deallocated), // str
|
||||
(StandardRC, Deallocated), // [c]
|
||||
(AfterSize, Deallocated), // in
|
||||
(AfterSize, Deallocated), // out
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -89,13 +89,10 @@ pub fn helper(
|
|||
// while you're working on the dev backend!
|
||||
{
|
||||
// println!("=========== Procedures ==========");
|
||||
// if pretty_print_ir_symbols() {
|
||||
// println!("");
|
||||
// for proc in procedures.values() {
|
||||
// println!("{}", proc.to_pretty(200));
|
||||
// }
|
||||
// } else {
|
||||
// println!("{:?}", procedures.values());
|
||||
// let pretty = pretty_print_ir_symbols();
|
||||
// println!("");
|
||||
// for proc in procedures.values() {
|
||||
// println!("{}", proc.to_pretty(&layout_interner, 200, pretty));
|
||||
// }
|
||||
// println!("=================================\n");
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use roc_error_macros::internal_error;
|
||||
use roc_gen_wasm::wasm32_sized::Wasm32Sized;
|
||||
use roc_mono::layout::Builtin;
|
||||
use roc_std::{RocBox, RocDec, RocList, RocOrder, RocResult, RocStr, I128, U128};
|
||||
use roc_std::{RocBox, RocDec, RocList, RocOrder, RocRefcounted, RocResult, RocStr, I128, U128};
|
||||
use roc_wasm_module::round_up_to_alignment;
|
||||
use std::convert::TryInto;
|
||||
|
||||
|
@ -84,7 +84,10 @@ impl FromWasm32Memory for RocStr {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: FromWasm32Memory + Clone> FromWasm32Memory for RocList<T> {
|
||||
impl<T: FromWasm32Memory + Clone> FromWasm32Memory for RocList<T>
|
||||
where
|
||||
T: RocRefcounted,
|
||||
{
|
||||
fn decode(memory: &[u8], offset: u32) -> Self {
|
||||
let elements = <u32 as FromWasm32Memory>::decode(memory, offset + 4 * Builtin::WRAPPER_PTR);
|
||||
let length = <u32 as FromWasm32Memory>::decode(memory, offset + 4 * Builtin::WRAPPER_LEN);
|
||||
|
@ -103,7 +106,10 @@ impl<T: FromWasm32Memory + Clone> FromWasm32Memory for RocList<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: FromWasm32Memory + Clone> FromWasm32Memory for RocBox<T> {
|
||||
impl<T: FromWasm32Memory + Clone> FromWasm32Memory for RocBox<T>
|
||||
where
|
||||
T: RocRefcounted,
|
||||
{
|
||||
fn decode(memory: &[u8], offset: u32) -> Self {
|
||||
let ptr = <u32 as FromWasm32Memory>::decode(memory, offset + 4 * Builtin::WRAPPER_PTR);
|
||||
debug_assert_ne!(ptr, 0);
|
||||
|
|
|
@ -96,3 +96,10 @@ pub enum RefCount {
|
|||
Deallocated,
|
||||
Constant,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum RefCountLoc {
|
||||
StandardRC,
|
||||
AfterSize,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::RefCount;
|
||||
use super::{RefCount, RefCountLoc};
|
||||
use crate::helpers::from_wasm32_memory::FromWasm32Memory;
|
||||
use bumpalo::Bump;
|
||||
use roc_collections::all::MutSet;
|
||||
|
@ -258,7 +258,7 @@ where
|
|||
pub fn assert_wasm_refcounts_help<T>(
|
||||
src: &str,
|
||||
phantom: PhantomData<T>,
|
||||
num_refcounts: usize,
|
||||
refcount_locs: &[RefCountLoc],
|
||||
) -> Result<Vec<RefCount>, String>
|
||||
where
|
||||
T: FromWasm32Memory + Wasm32Result,
|
||||
|
@ -278,6 +278,7 @@ where
|
|||
let mut inst = Instance::for_module(&arena, &module, dispatcher, is_debug_mode)?;
|
||||
|
||||
// Allocate a vector in the test host that refcounts will be copied into
|
||||
let num_refcounts = refcount_locs.len();
|
||||
let mut refcount_vector_addr: i32 = inst
|
||||
.call_export(INIT_REFCOUNT_NAME, [Value::I32(num_refcounts as i32)])?
|
||||
.ok_or_else(|| format!("No return address from {}", INIT_REFCOUNT_NAME))?
|
||||
|
@ -302,15 +303,21 @@ where
|
|||
|
||||
// Read the refcounts
|
||||
let mut refcounts = Vec::with_capacity(num_refcounts);
|
||||
for _ in 0..num_refcounts {
|
||||
for refcount_loc in refcount_locs {
|
||||
// Get the next RC pointer from the host's vector
|
||||
refcount_vector_addr += 4;
|
||||
let rc_ptr = read_i32(&inst.memory, refcount_vector_addr);
|
||||
let mut rc_ptr = read_i32(&inst.memory, refcount_vector_addr);
|
||||
let rc = if rc_ptr == 0 {
|
||||
RefCount::Deallocated
|
||||
} else {
|
||||
// If size is store on the heap for this type, the rc pointer is directly after.
|
||||
if matches!(refcount_loc, RefCountLoc::AfterSize) {
|
||||
rc_ptr += 4
|
||||
}
|
||||
|
||||
// Dereference the RC pointer and decode its value from the negative number format
|
||||
let rc_encoded = read_i32(&inst.memory, rc_ptr);
|
||||
|
||||
if rc_encoded == 0 {
|
||||
RefCount::Constant
|
||||
} else {
|
||||
|
@ -397,15 +404,18 @@ macro_rules! assert_refcounts {
|
|||
// We need the result type to generate the test_wrapper, even though we ignore the value!
|
||||
// We can't just call `main` with no args, because some tests return structs, via pointer arg!
|
||||
// Also we need to know how much stack space to reserve for the struct.
|
||||
($src: expr, $ty: ty, $expected_refcounts: expr) => {{
|
||||
($src: expr, $ty: ty, $expected: expr) => {{
|
||||
let phantom = std::marker::PhantomData;
|
||||
let num_refcounts = $expected_refcounts.len();
|
||||
let (refcount_locs, expected_refcounts): (
|
||||
Vec<$crate::helpers::RefCountLoc>,
|
||||
Vec<$crate::helpers::RefCount>,
|
||||
) = $expected.into_iter().map(|x| *x).unzip();
|
||||
let result =
|
||||
$crate::helpers::wasm::assert_wasm_refcounts_help::<$ty>($src, phantom, num_refcounts);
|
||||
$crate::helpers::wasm::assert_wasm_refcounts_help::<$ty>($src, phantom, &refcount_locs);
|
||||
match result {
|
||||
Err(msg) => panic!("{:?}", msg),
|
||||
Ok(actual_refcounts) => {
|
||||
assert_eq!(&actual_refcounts, $expected_refcounts)
|
||||
assert_eq!(actual_refcounts, expected_refcounts)
|
||||
}
|
||||
}
|
||||
}};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue