mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 15:03:46 +00:00
Merge remote-tracking branch 'origin/main' into abilities-syntax
This commit is contained in:
commit
2da41be29f
524 changed files with 47536 additions and 15089 deletions
|
@ -18,7 +18,13 @@ wasi_libc_sys = { path = "../../wasi-libc-sys" }
|
|||
|
||||
tempfile.workspace = true
|
||||
|
||||
[dependencies]
|
||||
roc_gen_llvm = { path = "../gen_llvm", optional = true }
|
||||
inkwell = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
roc_gen_dev = { path = "../gen_dev" }
|
||||
roc_gen_wasm = { path = "../gen_wasm" }
|
||||
roc_bitcode = { path = "../builtins/bitcode" }
|
||||
roc_build = { path = "../build", features = ["target-aarch64", "target-x86_64", "target-wasm32"] }
|
||||
roc_builtins = { path = "../builtins" }
|
||||
|
@ -28,9 +34,6 @@ roc_command_utils = { path = "../../utils/command" }
|
|||
roc_constrain = { path = "../constrain" }
|
||||
roc_debug_flags = { path = "../debug_flags" }
|
||||
roc_error_macros = { path = "../../error_macros" }
|
||||
roc_gen_dev = { path = "../gen_dev" }
|
||||
roc_gen_llvm = { path = "../gen_llvm" }
|
||||
roc_gen_wasm = { path = "../gen_wasm" }
|
||||
roc_load = { path = "../load" }
|
||||
roc_module = { path = "../module" }
|
||||
roc_mono = { path = "../mono" }
|
||||
|
@ -50,8 +53,6 @@ roc_wasm_module = { path = "../../wasm_module" }
|
|||
bumpalo.workspace = true
|
||||
criterion.workspace = true
|
||||
indoc.workspace = true
|
||||
inkwell.workspace = true
|
||||
lazy_static.workspace = true
|
||||
libc.workspace = true
|
||||
libloading.workspace = true
|
||||
target-lexicon.workspace = true
|
||||
|
@ -61,7 +62,7 @@ tempfile.workspace = true
|
|||
[features]
|
||||
default = ["gen-llvm"]
|
||||
gen-dev = []
|
||||
gen-llvm = []
|
||||
gen-llvm = ["roc_gen_llvm", "inkwell"]
|
||||
gen-llvm-wasm = ["gen-llvm"]
|
||||
gen-wasm = []
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ fn roc_function<'a, 'b>(
|
|||
let (main_fn_name, errors, lib) =
|
||||
helpers::llvm::helper(arena, config, source, arena.alloc(context));
|
||||
|
||||
assert!(errors.is_empty(), "Encountered errors:\n{}", errors);
|
||||
assert!(errors.is_empty(), "Encountered errors:\n{errors}");
|
||||
|
||||
run_roc_dylib!(arena.alloc(lib), main_fn_name, &Input, Output)
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ fn roc_function<'a>(
|
|||
let (main_fn_name, errors, lib) =
|
||||
helpers::llvm::helper(arena, config, source, arena.alloc(context));
|
||||
|
||||
assert!(errors.is_empty(), "Encountered errors:\n{}", errors);
|
||||
assert!(errors.is_empty(), "Encountered errors:\n{errors}");
|
||||
|
||||
run_roc_dylib!(arena.alloc(lib), main_fn_name, *mut Input, Output)
|
||||
}
|
||||
|
|
|
@ -41,8 +41,8 @@ fn build_wasm_linking_test_host() {
|
|||
let host_wasm: &str = host_wasm_path.to_str().unwrap();
|
||||
let host_native: &str = host_native_path.to_str().unwrap();
|
||||
|
||||
println!("cargo:rerun-if-changed={}", host_source);
|
||||
println!("cargo:rerun-if-changed={}", import_source);
|
||||
println!("cargo:rerun-if-changed={host_source}");
|
||||
println!("cargo:rerun-if-changed={import_source}");
|
||||
|
||||
if !Path::new("build").exists() {
|
||||
fs::create_dir("build").unwrap();
|
||||
|
@ -57,7 +57,7 @@ fn build_wasm_linking_test_host() {
|
|||
"-target",
|
||||
"wasm32-freestanding-musl",
|
||||
host_source,
|
||||
&format!("-femit-bin={}", host_wasm),
|
||||
&format!("-femit-bin={host_wasm}"),
|
||||
]);
|
||||
|
||||
let mut import_obj_path = PathBuf::from("build").join("wasm_linking_host_imports");
|
||||
|
@ -73,7 +73,7 @@ fn build_wasm_linking_test_host() {
|
|||
"build-exe",
|
||||
host_source,
|
||||
import_obj,
|
||||
&format!("-femit-bin={}", host_native),
|
||||
&format!("-femit-bin={host_native}"),
|
||||
#[cfg(windows)]
|
||||
"--subsystem",
|
||||
#[cfg(windows)]
|
||||
|
@ -148,7 +148,7 @@ fn run_zig(args: &[&str]) {
|
|||
let mut zig_cmd = zig();
|
||||
|
||||
let full_zig_cmd = zig_cmd.args(args);
|
||||
println!("{:?}", full_zig_cmd);
|
||||
println!("{full_zig_cmd:?}");
|
||||
|
||||
let zig_cmd_output = full_zig_cmd.output().unwrap();
|
||||
|
||||
|
@ -164,6 +164,6 @@ fn run_zig(args: &[&str]) {
|
|||
panic!("zig call failed with status {:?}", zig_cmd_output.status);
|
||||
}
|
||||
|
||||
assert!(zig_cmd_output.stdout.is_empty(), "{:#?}", zig_cmd_output);
|
||||
assert!(zig_cmd_output.stderr.is_empty(), "{:#?}", zig_cmd_output);
|
||||
assert!(zig_cmd_output.stdout.is_empty(), "{zig_cmd_output:#?}");
|
||||
assert!(zig_cmd_output.stderr.is_empty(), "{zig_cmd_output:#?}");
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ use roc_std::RocList;
|
|||
#[cfg(all(test, any(feature = "gen-llvm", feature = "gen-wasm")))]
|
||||
use roc_std::RocStr;
|
||||
|
||||
use crate::helpers::with_larger_debug_stack;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn hash_specialization() {
|
||||
|
@ -935,9 +937,10 @@ fn encode_derived_generic_tag_with_different_field_types() {
|
|||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn specialize_unique_newtype_records() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
with_larger_debug_stack(|| {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test"
|
||||
imports [Encode, TotallyNotJson]
|
||||
provides [main] to "./platform"
|
||||
|
@ -949,10 +952,11 @@ fn specialize_unique_newtype_records() {
|
|||
_ -> "<bad>"
|
||||
_ -> "<bad>"
|
||||
"#
|
||||
),
|
||||
RocStr::from(r#"{"a":true}{"b":true}"#),
|
||||
RocStr
|
||||
)
|
||||
),
|
||||
RocStr::from(r#"{"a":true}{"b":true}"#),
|
||||
RocStr
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1056,23 +1060,27 @@ mod decode_immediate {
|
|||
#[cfg(all(test, any(feature = "gen-llvm")))]
|
||||
use roc_std::RocStr;
|
||||
|
||||
use crate::helpers::with_larger_debug_stack;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn string() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [TotallyNotJson] provides [main] to "./platform"
|
||||
with_larger_debug_stack(|| {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [TotallyNotJson] provides [main] to "./platform"
|
||||
|
||||
main =
|
||||
when Str.toUtf8 "\"foo\"" |> Decode.fromBytes TotallyNotJson.json is
|
||||
Ok s -> s
|
||||
_ -> "<bad>"
|
||||
"#
|
||||
),
|
||||
RocStr::from("foo"),
|
||||
RocStr
|
||||
)
|
||||
main =
|
||||
when Str.toUtf8 "\"foo\"" |> Decode.fromBytes TotallyNotJson.json is
|
||||
Ok s -> s
|
||||
_ -> "<bad>"
|
||||
"#
|
||||
),
|
||||
RocStr::from("foo"),
|
||||
RocStr
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1179,59 +1187,65 @@ mod decode_immediate {
|
|||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn decode_list_of_strings() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [TotallyNotJson] provides [main] to "./platform"
|
||||
with_larger_debug_stack(|| {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [TotallyNotJson] provides [main] to "./platform"
|
||||
|
||||
main =
|
||||
when Str.toUtf8 "[\"a\",\"b\",\"c\"]" |> Decode.fromBytes TotallyNotJson.json is
|
||||
Ok l -> Str.joinWith l ","
|
||||
_ -> "<bad>"
|
||||
"#
|
||||
),
|
||||
RocStr::from("a,b,c"),
|
||||
RocStr
|
||||
)
|
||||
main =
|
||||
when Str.toUtf8 "[\"a\",\"b\",\"c\"]" |> Decode.fromBytes TotallyNotJson.json is
|
||||
Ok l -> Str.joinWith l ","
|
||||
_ -> "<bad>"
|
||||
"#
|
||||
),
|
||||
RocStr::from("a,b,c"),
|
||||
RocStr
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(any(feature = "gen-llvm", feature = "gen-wasm")))]
|
||||
fn encode_then_decode_list_of_strings() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [TotallyNotJson] provides [main] to "./platform"
|
||||
with_larger_debug_stack(|| {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [TotallyNotJson] provides [main] to "./platform"
|
||||
|
||||
main =
|
||||
when Encode.toBytes ["a", "b", "c"] TotallyNotJson.json |> Decode.fromBytes TotallyNotJson.json is
|
||||
Ok l -> Str.joinWith l ","
|
||||
_ -> "something went wrong"
|
||||
"#
|
||||
),
|
||||
RocStr::from("a,b,c"),
|
||||
RocStr
|
||||
)
|
||||
main =
|
||||
when Encode.toBytes ["a", "b", "c"] TotallyNotJson.json |> Decode.fromBytes TotallyNotJson.json is
|
||||
Ok l -> Str.joinWith l ","
|
||||
_ -> "something went wrong"
|
||||
"#
|
||||
),
|
||||
RocStr::from("a,b,c"),
|
||||
RocStr
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore = "#3696: Currently hits some weird panic in borrow checking, not sure if it's directly related to abilities."]
|
||||
fn encode_then_decode_list_of_lists_of_strings() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [TotallyNotJson] provides [main] to "./platform"
|
||||
with_larger_debug_stack(|| {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [TotallyNotJson] provides [main] to "./platform"
|
||||
|
||||
main =
|
||||
when Encode.toBytes [["a", "b"], ["c", "d", "e"], ["f"]] TotallyNotJson.json |> Decode.fromBytes TotallyNotJson.json is
|
||||
Ok list -> (List.map list \inner -> Str.joinWith inner ",") |> Str.joinWith l ";"
|
||||
_ -> "something went wrong"
|
||||
"#
|
||||
),
|
||||
RocStr::from("a,b;c,d,e;f"),
|
||||
RocStr
|
||||
)
|
||||
main =
|
||||
when Encode.toBytes [["a", "b"], ["c", "d", "e"], ["f"]] TotallyNotJson.json |> Decode.fromBytes TotallyNotJson.json is
|
||||
Ok list -> (List.map list \inner -> Str.joinWith inner ",") |> Str.joinWith l ";"
|
||||
_ -> "something went wrong"
|
||||
"#
|
||||
),
|
||||
RocStr::from("a,b;c,d,e;f"),
|
||||
RocStr
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2135,32 +2149,34 @@ mod eq {
|
|||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn issue_4772_weakened_monomorphic_destructure() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r###"
|
||||
app "test"
|
||||
imports [TotallyNotJson]
|
||||
provides [main] to "./platform"
|
||||
with_larger_debug_stack(|| {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r###"
|
||||
app "test"
|
||||
imports [TotallyNotJson]
|
||||
provides [main] to "./platform"
|
||||
|
||||
getNumber =
|
||||
{ result, rest } = Decode.fromBytesPartial (Str.toUtf8 "\"1234\"") TotallyNotJson.json
|
||||
|
||||
when result is
|
||||
Ok val ->
|
||||
when Str.toI64 val is
|
||||
Ok number ->
|
||||
Ok {val : number, input : rest}
|
||||
Err InvalidNumStr ->
|
||||
Err (ParsingFailure "not a number")
|
||||
getNumber =
|
||||
{ result, rest } = Decode.fromBytesPartial (Str.toUtf8 "\"1234\"") TotallyNotJson.json
|
||||
|
||||
when result is
|
||||
Ok val ->
|
||||
when Str.toI64 val is
|
||||
Ok number ->
|
||||
Ok {val : number, input : rest}
|
||||
Err InvalidNumStr ->
|
||||
Err (ParsingFailure "not a number")
|
||||
|
||||
Err _ ->
|
||||
Err (ParsingFailure "not a number")
|
||||
Err _ ->
|
||||
Err (ParsingFailure "not a number")
|
||||
|
||||
main =
|
||||
getNumber |> Result.map .val |> Result.withDefault 0
|
||||
"###
|
||||
),
|
||||
1234i64,
|
||||
i64
|
||||
);
|
||||
main =
|
||||
getNumber |> Result.map .val |> Result.withDefault 0
|
||||
"###
|
||||
),
|
||||
1234i64,
|
||||
i64
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
47
crates/compiler/test_gen/src/gen_definitions.rs
Normal file
47
crates/compiler/test_gen/src/gen_definitions.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_evals_to;
|
||||
|
||||
#[cfg(feature = "gen-dev")]
|
||||
use crate::helpers::dev::assert_evals_to;
|
||||
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
use crate::helpers::wasm::assert_evals_to;
|
||||
|
||||
// use crate::helpers::with_larger_debug_stack;
|
||||
//use crate::assert_wasm_evals_to as assert_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
use indoc::indoc;
|
||||
#[allow(unused_imports)]
|
||||
use roc_std::{RocList, RocResult, RocStr};
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn def_closure_in_parens() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
id = (\x -> x)
|
||||
|
||||
id 42u32
|
||||
"#
|
||||
),
|
||||
42,
|
||||
u32
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn def_closure_in_multiple_parens() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
id = (((\x -> x)))
|
||||
|
||||
id 42u32
|
||||
"#
|
||||
),
|
||||
42,
|
||||
u32
|
||||
);
|
||||
}
|
44
crates/compiler/test_gen/src/gen_erased.rs
Normal file
44
crates/compiler/test_gen/src/gen_erased.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_evals_to_erased;
|
||||
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn capture_multiple() {
|
||||
assert_evals_to_erased!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
f = \n, m ->
|
||||
\{} -> n + m + 15u8
|
||||
|
||||
main = (f 10u8 20u8) {}
|
||||
"#
|
||||
),
|
||||
45,
|
||||
u8
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn multi_branch_capturing() {
|
||||
assert_evals_to_erased!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
f = \t, s ->
|
||||
if t
|
||||
then \{} -> 15nat
|
||||
else \{} -> Str.countGraphemes s
|
||||
|
||||
main = ((f Bool.true "abc") {}, (f Bool.false "abc") {})
|
||||
"#
|
||||
),
|
||||
(15, 3),
|
||||
(usize, usize)
|
||||
);
|
||||
}
|
|
@ -7,7 +7,6 @@ use crate::helpers::dev::assert_evals_to;
|
|||
#[cfg(feature = "gen-wasm")]
|
||||
use crate::helpers::wasm::assert_evals_to;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::helpers::with_larger_debug_stack;
|
||||
//use crate::assert_wasm_evals_to as assert_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
|
@ -1777,14 +1776,14 @@ fn assert_concat_worked(num_elems1: i64, num_elems2: i64) {
|
|||
let vec2: Vec<i64> = (0..num_elems2)
|
||||
.map(|i| 54321 % (i + num_elems1 + num_elems2 + 1))
|
||||
.collect();
|
||||
let slice_str1 = format!("{:?}", vec1);
|
||||
let slice_str2 = format!("{:?}", vec2);
|
||||
let slice_str1 = format!("{vec1:?}");
|
||||
let slice_str2 = format!("{vec2:?}");
|
||||
let mut expected = vec1;
|
||||
|
||||
expected.extend(vec2);
|
||||
|
||||
assert_evals_to!(
|
||||
&format!("List.concat {} {}", slice_str1, slice_str2),
|
||||
&format!("List.concat {slice_str1} {slice_str2}"),
|
||||
RocList::from_slice(&expected),
|
||||
RocList<i64>
|
||||
);
|
||||
|
@ -3823,6 +3822,8 @@ mod pattern_match {
|
|||
#[cfg(feature = "gen-dev")]
|
||||
use crate::helpers::dev::assert_evals_to;
|
||||
|
||||
use crate::helpers::with_larger_debug_stack;
|
||||
|
||||
use super::RocList;
|
||||
|
||||
#[test]
|
||||
|
@ -3863,21 +3864,21 @@ mod pattern_match {
|
|||
with_larger_debug_stack(|| {
|
||||
assert_evals_to!(
|
||||
r#"
|
||||
helper = \l -> when l is
|
||||
[] -> 1u8
|
||||
[A] -> 2u8
|
||||
[A, A, ..] -> 3u8
|
||||
[A, B, ..] -> 4u8
|
||||
[B, ..] -> 5u8
|
||||
helper = \l -> when l is
|
||||
[] -> 1u8
|
||||
[A] -> 2u8
|
||||
[A, A, ..] -> 3u8
|
||||
[A, B, ..] -> 4u8
|
||||
[B, ..] -> 5u8
|
||||
|
||||
[
|
||||
helper [],
|
||||
helper [A],
|
||||
helper [A, A], helper [A, A, A], helper [A, A, B], helper [A, A, B, A],
|
||||
helper [A, B], helper [A, B, A], helper [A, B, B], helper [A, B, A, B],
|
||||
helper [B], helper [B, A], helper [B, B], helper [B, A, B, B],
|
||||
]
|
||||
"#,
|
||||
[
|
||||
helper [],
|
||||
helper [A],
|
||||
helper [A, A], helper [A, A, A], helper [A, A, B], helper [A, A, B, A],
|
||||
helper [A, B], helper [A, B, A], helper [A, B, B], helper [A, B, A, B],
|
||||
helper [B], helper [B, A], helper [B, B], helper [B, A, B, B],
|
||||
]
|
||||
"#,
|
||||
RocList::from_slice(&[
|
||||
1, //
|
||||
2, //
|
||||
|
@ -3887,7 +3888,7 @@ mod pattern_match {
|
|||
]),
|
||||
RocList<u8>
|
||||
)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -3895,21 +3896,21 @@ mod pattern_match {
|
|||
with_larger_debug_stack(|| {
|
||||
assert_evals_to!(
|
||||
r#"
|
||||
helper = \l -> when l is
|
||||
[] -> 1u8
|
||||
[A] -> 2u8
|
||||
[.., A, A] -> 3u8
|
||||
[.., B, A] -> 4u8
|
||||
[.., B] -> 5u8
|
||||
helper = \l -> when l is
|
||||
[] -> 1u8
|
||||
[A] -> 2u8
|
||||
[.., A, A] -> 3u8
|
||||
[.., B, A] -> 4u8
|
||||
[.., B] -> 5u8
|
||||
|
||||
[
|
||||
helper [],
|
||||
helper [A],
|
||||
helper [A, A], helper [A, A, A], helper [B, A, A], helper [A, B, A, A],
|
||||
helper [B, A], helper [A, B, A], helper [B, B, A], helper [B, A, B, A],
|
||||
helper [B], helper [A, B], helper [B, B], helper [B, A, B, B],
|
||||
]
|
||||
"#,
|
||||
[
|
||||
helper [],
|
||||
helper [A],
|
||||
helper [A, A], helper [A, A, A], helper [B, A, A], helper [A, B, A, A],
|
||||
helper [B, A], helper [A, B, A], helper [B, B, A], helper [B, A, B, A],
|
||||
helper [B], helper [A, B], helper [B, B], helper [B, A, B, B],
|
||||
]
|
||||
"#,
|
||||
RocList::from_slice(&[
|
||||
1, //
|
||||
2, //
|
||||
|
|
|
@ -3966,3 +3966,27 @@ fn mul_checked_dec() {
|
|||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn num_min() {
|
||||
assert_evals_to!(r#"Num.min 0 0"#, 0, i64);
|
||||
assert_evals_to!(r#"Num.min 1 2"#, 1, i64);
|
||||
assert_evals_to!(r#"Num.min 2 1"#, 1, i64);
|
||||
assert_evals_to!(r#"Num.min 2 -2"#, -2, i64);
|
||||
assert_evals_to!(r#"Num.min -2 2"#, -2, i64);
|
||||
assert_evals_to!(r#"Num.min Num.minI64 Num.maxI64"#, i64::MIN, i64);
|
||||
assert_evals_to!(r#"Num.min Num.maxI64 Num.minI64"#, i64::MIN, i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn num_max() {
|
||||
assert_evals_to!(r#"Num.max 0 0"#, 0, i64);
|
||||
assert_evals_to!(r#"Num.max 1 2"#, 2, i64);
|
||||
assert_evals_to!(r#"Num.max 2 1"#, 2, i64);
|
||||
assert_evals_to!(r#"Num.max 2 -2"#, 2, i64);
|
||||
assert_evals_to!(r#"Num.max -2 2"#, 2, i64);
|
||||
assert_evals_to!(r#"Num.max Num.minI64 Num.maxI64"#, i64::MAX, i64);
|
||||
assert_evals_to!(r#"Num.max Num.maxI64 Num.minI64"#, i64::MAX, i64);
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ fn apply_unnamed_identity() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn return_unnamed_fn() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -325,7 +325,7 @@ fn return_unnamed_fn() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn gen_when_fn() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -345,7 +345,7 @@ fn gen_when_fn() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn gen_basic_def() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -373,7 +373,7 @@ fn gen_basic_def() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn gen_multiple_defs() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -492,7 +492,7 @@ fn gen_multiple_defs() {
|
|||
// }
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn factorial() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -514,7 +514,7 @@ fn factorial() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn peano1() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -535,7 +535,7 @@ fn peano1() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn peano2() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -557,7 +557,7 @@ fn peano2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn top_level_constant() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -577,7 +577,7 @@ fn top_level_constant() {
|
|||
|
||||
#[test]
|
||||
#[ignore]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn top_level_destructure() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -829,7 +829,7 @@ fn linked_list_map() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn when_nested_maybe() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -886,7 +886,7 @@ fn when_nested_maybe() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn when_peano() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -992,6 +992,24 @@ fn undefined_variable() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
#[should_panic(expected = "User crash with message: \"a crash\"")]
|
||||
fn a_crash() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
if Bool.true then
|
||||
crash "a crash"
|
||||
else
|
||||
0u64
|
||||
"#
|
||||
),
|
||||
3,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[should_panic(expected = "Roc failed with message: ")]
|
||||
|
@ -1011,7 +1029,7 @@ fn annotation_without_body() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn simple_closure() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1033,7 +1051,7 @@ fn simple_closure() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn nested_closure() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1057,7 +1075,7 @@ fn nested_closure() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn closure_in_list() {
|
||||
use roc_std::RocList;
|
||||
|
||||
|
@ -1085,7 +1103,7 @@ fn closure_in_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn specialize_closure() {
|
||||
use roc_std::RocList;
|
||||
|
||||
|
@ -1117,7 +1135,7 @@ fn specialize_closure() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn io_poc_effect() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1148,7 +1166,7 @@ fn io_poc_effect() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn io_poc_desugared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1176,7 +1194,7 @@ fn io_poc_desugared() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn return_wrapped_function_a() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1198,7 +1216,7 @@ fn return_wrapped_function_a() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn return_wrapped_function_b() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1219,7 +1237,7 @@ fn return_wrapped_function_b() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn return_wrapped_closure() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1367,7 +1385,7 @@ fn linked_list_singleton() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn recursive_function_with_rigid() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1394,7 +1412,7 @@ fn recursive_function_with_rigid() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn rbtree_insert() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1606,7 +1624,7 @@ fn rbtree_balance_mono_problem() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn rbtree_balance_full() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1658,7 +1676,7 @@ fn rbtree_balance_full() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn nested_pattern_match_two_ways() {
|
||||
// exposed an issue in the ordering of pattern match checks when ran with `--release` mode
|
||||
assert_evals_to!(
|
||||
|
@ -1771,6 +1789,7 @@ fn linked_list_double_pattern_match() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
// dev backend: this test somehow corrupts the errors vector ?!
|
||||
fn binary_tree_double_pattern_match() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1796,7 +1815,7 @@ fn binary_tree_double_pattern_match() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn unified_empty_closure_bool() {
|
||||
// none of the Closure tags will have a payload
|
||||
// this was not handled correctly in the past
|
||||
|
@ -1821,7 +1840,7 @@ fn unified_empty_closure_bool() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn unified_empty_closure_byte() {
|
||||
// none of the Closure tags will have a payload
|
||||
// this was not handled correctly in the past
|
||||
|
@ -1847,7 +1866,7 @@ fn unified_empty_closure_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn task_always_twice() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1892,7 +1911,7 @@ fn task_always_twice() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn wildcard_rigid() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1921,7 +1940,7 @@ fn wildcard_rigid() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn alias_of_alias_with_type_arguments() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1998,7 +2017,7 @@ fn todo_bad_error_message() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn hof_conditional() {
|
||||
// exposed issue with the if condition being just a symbol
|
||||
assert_evals_to!(
|
||||
|
@ -2095,7 +2114,7 @@ fn fingertree_basic() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn case_or_pattern() {
|
||||
// the `0` branch body should only be generated once in the future
|
||||
// it is currently duplicated
|
||||
|
@ -2210,9 +2229,10 @@ fn nullable_eval_cfold() {
|
|||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn nested_switch() {
|
||||
// exposed bug with passing the right symbol/layout down into switch branch generation
|
||||
// This is also the only test_gen test that exercises Reset/Reuse (as of Aug 2022)
|
||||
assert_evals_to!(
|
||||
crate::helpers::with_larger_debug_stack(||
|
||||
// exposed bug with passing the right symbol/layout down into switch branch generation
|
||||
// This is also the only test_gen test that exercises Reset/Reuse (as of Aug 2022)
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
@ -2248,7 +2268,7 @@ fn nested_switch() {
|
|||
),
|
||||
12,
|
||||
i64
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -3576,7 +3596,7 @@ fn polymorphic_lambda_captures_polymorphic_value() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn lambda_capture_niche_u64_vs_u8_capture() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -3604,7 +3624,7 @@ fn lambda_capture_niche_u64_vs_u8_capture() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn lambda_capture_niches_with_other_lambda_capture() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -3637,7 +3657,7 @@ fn lambda_capture_niches_with_other_lambda_capture() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn lambda_capture_niches_with_non_capturing_function() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -3670,7 +3690,7 @@ fn lambda_capture_niches_with_non_capturing_function() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn lambda_capture_niches_have_captured_function_in_closure() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -3862,7 +3882,7 @@ fn recursive_lambda_set_issue_3444_inferred() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn compose_recursive_lambda_set_productive_toplevel() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -3930,7 +3950,7 @@ fn compose_recursive_lambda_set_productive_inferred() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn compose_recursive_lambda_set_productive_nullable_wrapped() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -4216,7 +4236,7 @@ fn issue_4349() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn issue_4712() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -4498,3 +4518,36 @@ fn pass_lambda_set_to_function() {
|
|||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn linked_list_trmc() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
LinkedList a : [Nil, Cons a (LinkedList a)]
|
||||
|
||||
repeat : a, Nat -> LinkedList a
|
||||
repeat = \value, n ->
|
||||
when n is
|
||||
0 -> Nil
|
||||
_ -> Cons value (repeat value (n - 1))
|
||||
|
||||
length : LinkedList a -> I64
|
||||
length = \list ->
|
||||
when list is
|
||||
Nil -> 0
|
||||
Cons _ rest -> 1 + length rest
|
||||
|
||||
main : I64
|
||||
main =
|
||||
repeat "foo" 5
|
||||
|> length
|
||||
"#
|
||||
),
|
||||
5,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1218,15 +1218,15 @@ fn str_trim_small_to_small_shared() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_left_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trimLeft " ""#), RocStr::from(""), RocStr);
|
||||
fn str_trim_start_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trimStart " ""#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_left_small_to_small() {
|
||||
fn str_trim_start_small_to_small() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimLeft " hello world ""#),
|
||||
indoc!(r#"Str.trimStart " hello world ""#),
|
||||
RocStr::from("hello world "),
|
||||
RocStr
|
||||
);
|
||||
|
@ -1234,9 +1234,9 @@ fn str_trim_left_small_to_small() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_left_large_to_large_unique() {
|
||||
fn str_trim_start_large_to_large_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimLeft (Str.concat " " "hello world from a large string ")"#),
|
||||
indoc!(r#"Str.trimStart (Str.concat " " "hello world from a large string ")"#),
|
||||
RocStr::from("hello world from a large string "),
|
||||
RocStr
|
||||
);
|
||||
|
@ -1244,9 +1244,9 @@ fn str_trim_left_large_to_large_unique() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_left_large_to_small_unique() {
|
||||
fn str_trim_start_large_to_small_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimLeft (Str.concat " " "hello world ")"#),
|
||||
indoc!(r#"Str.trimStart (Str.concat " " "hello world ")"#),
|
||||
RocStr::from("hello world "),
|
||||
RocStr
|
||||
);
|
||||
|
@ -1254,14 +1254,14 @@ fn str_trim_left_large_to_small_unique() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_left_large_to_large_shared() {
|
||||
fn str_trim_start_large_to_large_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
original : Str
|
||||
original = " hello world world "
|
||||
|
||||
{ trimmed: Str.trimLeft original, original: original }
|
||||
{ trimmed: Str.trimStart original, original: original }
|
||||
"#
|
||||
),
|
||||
(
|
||||
|
@ -1274,14 +1274,14 @@ fn str_trim_left_large_to_large_shared() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_left_large_to_small_shared() {
|
||||
fn str_trim_start_large_to_small_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
original : Str
|
||||
original = " hello world "
|
||||
|
||||
{ trimmed: Str.trimLeft original, original: original }
|
||||
{ trimmed: Str.trimStart original, original: original }
|
||||
"#
|
||||
),
|
||||
(
|
||||
|
@ -1294,14 +1294,14 @@ fn str_trim_left_large_to_small_shared() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_left_small_to_small_shared() {
|
||||
fn str_trim_start_small_to_small_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
original : Str
|
||||
original = " hello world "
|
||||
|
||||
{ trimmed: Str.trimLeft original, original: original }
|
||||
{ trimmed: Str.trimStart original, original: original }
|
||||
"#
|
||||
),
|
||||
(RocStr::from(" hello world "), RocStr::from("hello world "),),
|
||||
|
@ -1311,15 +1311,15 @@ fn str_trim_left_small_to_small_shared() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_right_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trimRight " ""#), RocStr::from(""), RocStr);
|
||||
fn str_trim_end_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trimEnd " ""#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_right_small_to_small() {
|
||||
fn str_trim_end_small_to_small() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimRight " hello world ""#),
|
||||
indoc!(r#"Str.trimEnd " hello world ""#),
|
||||
RocStr::from(" hello world"),
|
||||
RocStr
|
||||
);
|
||||
|
@ -1327,9 +1327,9 @@ fn str_trim_right_small_to_small() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_right_large_to_large_unique() {
|
||||
fn str_trim_end_large_to_large_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimRight (Str.concat " hello world from a large string" " ")"#),
|
||||
indoc!(r#"Str.trimEnd (Str.concat " hello world from a large string" " ")"#),
|
||||
RocStr::from(" hello world from a large string"),
|
||||
RocStr
|
||||
);
|
||||
|
@ -1337,9 +1337,9 @@ fn str_trim_right_large_to_large_unique() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_trim_right_large_to_small_unique() {
|
||||
fn str_trim_end_large_to_small_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimRight (Str.concat " hello world" " ")"#),
|
||||
indoc!(r#"Str.trimEnd (Str.concat " hello world" " ")"#),
|
||||
RocStr::from(" hello world"),
|
||||
RocStr
|
||||
);
|
||||
|
@ -1347,14 +1347,14 @@ fn str_trim_right_large_to_small_unique() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_right_large_to_large_shared() {
|
||||
fn str_trim_end_large_to_large_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
original : Str
|
||||
original = " hello world world "
|
||||
|
||||
{ trimmed: Str.trimRight original, original: original }
|
||||
{ trimmed: Str.trimEnd original, original: original }
|
||||
"#
|
||||
),
|
||||
(
|
||||
|
@ -1367,14 +1367,14 @@ fn str_trim_right_large_to_large_shared() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_right_large_to_small_shared() {
|
||||
fn str_trim_end_large_to_small_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
original : Str
|
||||
original = " hello world "
|
||||
|
||||
{ trimmed: Str.trimRight original, original: original }
|
||||
{ trimmed: Str.trimEnd original, original: original }
|
||||
"#
|
||||
),
|
||||
(
|
||||
|
@ -1387,14 +1387,14 @@ fn str_trim_right_large_to_small_shared() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_right_small_to_small_shared() {
|
||||
fn str_trim_end_small_to_small_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
original : Str
|
||||
original = " hello world "
|
||||
|
||||
{ trimmed: Str.trimRight original, original: original }
|
||||
{ trimmed: Str.trimEnd original, original: original }
|
||||
"#
|
||||
),
|
||||
(RocStr::from(" hello world "), RocStr::from(" hello world"),),
|
||||
|
|
|
@ -30,8 +30,8 @@ fn width_and_alignment_u8_u8() {
|
|||
|
||||
let layout = LayoutRepr::Union(UnionLayout::NonRecursive(&tt));
|
||||
|
||||
assert_eq!(layout.alignment_bytes(&interner, target_info), 1);
|
||||
assert_eq!(layout.stack_size(&interner, target_info), 2);
|
||||
assert_eq!(layout.alignment_bytes(&interner), 1);
|
||||
assert_eq!(layout.stack_size(&interner), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -2,9 +2,13 @@ use libloading::Library;
|
|||
use roc_build::link::{link, LinkType};
|
||||
use roc_builtins::bitcode;
|
||||
use roc_load::{EntryPoint, ExecutionMode, LoadConfig, Threading};
|
||||
use roc_mono::ir::CrashTag;
|
||||
use roc_mono::ir::SingleEntryPoint;
|
||||
use roc_packaging::cache::RocCacheDir;
|
||||
use roc_region::all::LineInfo;
|
||||
use roc_solve::FunctionKind;
|
||||
use roc_std::RocStr;
|
||||
use std::mem::MaybeUninit;
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
|
@ -58,6 +62,7 @@ pub fn helper(
|
|||
palette: roc_reporting::report::DEFAULT_PALETTE,
|
||||
threading: Threading::Single,
|
||||
exec_mode: ExecutionMode::Executable,
|
||||
function_kind: FunctionKind::LambdaSet,
|
||||
};
|
||||
let loaded = roc_load::load_and_monomorphize_from_str(
|
||||
arena,
|
||||
|
@ -210,8 +215,10 @@ pub fn helper(
|
|||
let builtins_host_tempfile =
|
||||
roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile");
|
||||
|
||||
// TODO make this an envrionment variable
|
||||
if false {
|
||||
std::fs::copy(&app_o_file, "/tmp/app.o").unwrap();
|
||||
let file_path = std::env::temp_dir().join("app.o");
|
||||
std::fs::copy(&app_o_file, file_path).unwrap();
|
||||
}
|
||||
|
||||
let (mut child, dylib_path) = link(
|
||||
|
@ -243,6 +250,81 @@ pub fn helper(
|
|||
(main_fn_name, delayed_errors, lib)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct RocCallResult<T> {
|
||||
pub tag: u64,
|
||||
pub error_msg: *mut RocStr,
|
||||
pub value: MaybeUninit<T>,
|
||||
}
|
||||
|
||||
impl<T> RocCallResult<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
Self {
|
||||
tag: 0,
|
||||
error_msg: std::ptr::null_mut(),
|
||||
value: MaybeUninit::new(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Default for RocCallResult<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
tag: 0,
|
||||
error_msg: std::ptr::null_mut(),
|
||||
value: MaybeUninit::new(Default::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RocCallResult<T> {
|
||||
pub fn into_result(self) -> Result<T, (String, CrashTag)> {
|
||||
match self.tag {
|
||||
0 => Ok(unsafe { self.value.assume_init() }),
|
||||
n => Err({
|
||||
let mut msg = RocStr::default();
|
||||
|
||||
unsafe { std::ptr::swap(&mut msg, self.error_msg) };
|
||||
|
||||
let tag = (n - 1) as u32;
|
||||
let tag = tag
|
||||
.try_into()
|
||||
.unwrap_or_else(|_| panic!("received illegal tag: {tag} {msg}"));
|
||||
|
||||
(msg.as_str().to_owned(), tag)
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_test_main_fn<T>(
|
||||
lib: &libloading::Library,
|
||||
) -> libloading::Symbol<unsafe extern "C" fn() -> RocCallResult<T>> {
|
||||
let main_fn_name = "test_main";
|
||||
|
||||
unsafe {
|
||||
lib.get(main_fn_name.as_bytes())
|
||||
.ok()
|
||||
.ok_or(format!("Unable to JIT compile `{main_fn_name}`"))
|
||||
.expect("errored")
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn run_test_main<T>(lib: &libloading::Library) -> Result<T, (String, CrashTag)> {
|
||||
let main = get_test_main_fn::<T>(lib);
|
||||
|
||||
let result = unsafe { main() };
|
||||
|
||||
result.into_result()
|
||||
}
|
||||
|
||||
impl<T: Sized> From<RocCallResult<T>> for Result<T, (String, CrashTag)> {
|
||||
fn from(call_result: RocCallResult<T>) -> Self {
|
||||
call_result.into_result()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty) => {{
|
||||
|
@ -265,19 +347,40 @@ macro_rules! assert_evals_to {
|
|||
};
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr, $leak:expr, $lazy_literals:expr) => {
|
||||
use bumpalo::Bump;
|
||||
use roc_gen_dev::run_jit_function_raw;
|
||||
|
||||
let arena = Bump::new();
|
||||
let (main_fn_name, errors, lib) =
|
||||
let (_main_fn_name, errors, lib) =
|
||||
$crate::helpers::dev::helper(&arena, $src, $leak, $lazy_literals);
|
||||
|
||||
let transform = |success| {
|
||||
let expected = $expected;
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
let given = $transform(success);
|
||||
assert_eq!(&given, &expected);
|
||||
};
|
||||
run_jit_function_raw!(lib, main_fn_name, $ty, transform, errors)
|
||||
let result = $crate::helpers::dev::run_test_main::<$ty>(&lib);
|
||||
|
||||
if !errors.is_empty() {
|
||||
dbg!(&errors);
|
||||
|
||||
assert_eq!(
|
||||
errors,
|
||||
std::vec::Vec::new(),
|
||||
"Encountered errors: {:?}",
|
||||
errors
|
||||
);
|
||||
}
|
||||
|
||||
match result {
|
||||
Ok(value) => {
|
||||
let expected = $expected;
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
let given = $transform(value);
|
||||
assert_eq!(&given, &expected, "output is different");
|
||||
}
|
||||
Err((msg, tag)) => {
|
||||
use roc_mono::ir::CrashTag;
|
||||
|
||||
match tag {
|
||||
CrashTag::Roc => panic!(r#"Roc failed with message: "{msg}""#),
|
||||
CrashTag::User => panic!(r#"User crash with message: "{msg}""#),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::mem::MaybeUninit;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use inkwell::module::Module;
|
||||
use libloading::Library;
|
||||
|
@ -8,7 +9,9 @@ use roc_collections::all::MutSet;
|
|||
use roc_command_utils::zig;
|
||||
use roc_gen_llvm::llvm::externs::add_default_roc_externs;
|
||||
use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult};
|
||||
use roc_load::{EntryPoint, ExecutionMode, LoadConfig, LoadMonomorphizedError, Threading};
|
||||
use roc_load::{
|
||||
EntryPoint, ExecutionMode, FunctionKind, LoadConfig, LoadMonomorphizedError, Threading,
|
||||
};
|
||||
use roc_mono::ir::{CrashTag, OptLevel, SingleEntryPoint};
|
||||
use roc_packaging::cache::RocCacheDir;
|
||||
use roc_region::all::LineInfo;
|
||||
|
@ -44,13 +47,13 @@ fn promote_expr_to_module(src: &str) -> String {
|
|||
buffer
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn create_llvm_module<'a>(
|
||||
arena: &'a bumpalo::Bump,
|
||||
src: &str,
|
||||
config: HelperConfig,
|
||||
context: &'a inkwell::context::Context,
|
||||
target: &Triple,
|
||||
function_kind: FunctionKind,
|
||||
) -> (&'static str, String, &'a Module<'a>) {
|
||||
let target_info = roc_target::TargetInfo::from(target);
|
||||
|
||||
|
@ -70,6 +73,7 @@ fn create_llvm_module<'a>(
|
|||
|
||||
let load_config = LoadConfig {
|
||||
target_info,
|
||||
function_kind,
|
||||
render: RenderTarget::ColorTerminal,
|
||||
palette: DEFAULT_PALETTE,
|
||||
threading: Threading::Single,
|
||||
|
@ -89,17 +93,18 @@ fn create_llvm_module<'a>(
|
|||
Err(LoadMonomorphizedError::LoadingProblem(roc_load::LoadingProblem::FormattedReport(
|
||||
report,
|
||||
))) => {
|
||||
println!("{}", report);
|
||||
println!("{report}");
|
||||
panic!();
|
||||
}
|
||||
Err(e) => panic!("{:?}", e),
|
||||
Err(e) => panic!("{e:?}"),
|
||||
};
|
||||
|
||||
use roc_load::MonomorphizedModule;
|
||||
let MonomorphizedModule {
|
||||
procedures,
|
||||
host_exposed_lambda_sets,
|
||||
interns,
|
||||
mut layout_interner,
|
||||
layout_interner,
|
||||
..
|
||||
} = loaded;
|
||||
|
||||
|
@ -192,7 +197,7 @@ fn create_llvm_module<'a>(
|
|||
|
||||
let kind_id = Attribute::get_named_enum_kind_id("alwaysinline");
|
||||
debug_assert!(kind_id > 0);
|
||||
let attr = context.create_enum_attribute(kind_id, 1);
|
||||
let attr = context.create_enum_attribute(kind_id, 0);
|
||||
|
||||
for function in module.get_functions() {
|
||||
let name = function.get_name().to_str().unwrap();
|
||||
|
@ -257,16 +262,17 @@ fn create_llvm_module<'a>(
|
|||
LlvmBackendMode::CliTest => unreachable!(),
|
||||
LlvmBackendMode::WasmGenTest => roc_gen_llvm::llvm::build::build_wasm_test_wrapper(
|
||||
&env,
|
||||
&mut layout_interner,
|
||||
&layout_interner,
|
||||
config.opt_level,
|
||||
procedures,
|
||||
entry_point,
|
||||
),
|
||||
LlvmBackendMode::GenTest => roc_gen_llvm::llvm::build::build_procedures_return_main(
|
||||
&env,
|
||||
&mut layout_interner,
|
||||
&layout_interner,
|
||||
config.opt_level,
|
||||
procedures,
|
||||
host_exposed_lambda_sets,
|
||||
entry_point,
|
||||
),
|
||||
};
|
||||
|
@ -279,23 +285,25 @@ fn create_llvm_module<'a>(
|
|||
// Uncomment this to see the module's un-optimized LLVM instruction output:
|
||||
// env.module.print_to_stderr();
|
||||
|
||||
let panic_bad_llvm = |errors| {
|
||||
let path = std::env::temp_dir().join("test.ll");
|
||||
env.module.print_to_file(&path).unwrap();
|
||||
panic!(
|
||||
"Errors defining module:\n\n{errors}\n\nI have written the full module to `{path:?}`"
|
||||
);
|
||||
};
|
||||
|
||||
if main_fn.verify(true) {
|
||||
function_pass.run_on(&main_fn);
|
||||
} else {
|
||||
panic!("Main function {} failed LLVM verification in NON-OPTIMIZED build. Uncomment things nearby to see more details.", main_fn_name);
|
||||
panic_bad_llvm(main_fn_name);
|
||||
}
|
||||
|
||||
module_pass.run_on(env.module);
|
||||
|
||||
// Verify the module
|
||||
if let Err(errors) = env.module.verify() {
|
||||
let path = std::env::temp_dir().join("test.ll");
|
||||
env.module.print_to_file(&path).unwrap();
|
||||
panic!(
|
||||
"Errors defining module:\n\n{}\n\nI have written the full module to `{:?}`",
|
||||
errors.to_string(),
|
||||
path
|
||||
);
|
||||
panic_bad_llvm(&errors.to_string());
|
||||
}
|
||||
|
||||
if let Ok(path) = std::env::var("ROC_DEBUG_LLVM") {
|
||||
|
@ -328,11 +336,12 @@ pub fn helper<'a>(
|
|||
config: HelperConfig,
|
||||
src: &str,
|
||||
context: &'a inkwell::context::Context,
|
||||
function_kind: FunctionKind,
|
||||
) -> (&'static str, String, Library) {
|
||||
let target = target_lexicon::Triple::host();
|
||||
|
||||
let (main_fn_name, delayed_errors, module) =
|
||||
create_llvm_module(arena, src, config, context, &target);
|
||||
create_llvm_module(arena, src, config, context, &target, function_kind);
|
||||
|
||||
let res_lib = if config.add_debug_info {
|
||||
let module = annotate_with_debug_info(module, context);
|
||||
|
@ -371,7 +380,7 @@ fn annotate_with_debug_info<'ctx>(
|
|||
ErrorKind::NotFound => panic!(
|
||||
r"I could not find the `debugir` tool on the PATH, install it from https://github.com/vaivaswatha/debugir"
|
||||
),
|
||||
_ => panic!("{:?}", error),
|
||||
_ => panic!("{error:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -408,24 +417,25 @@ fn write_final_wasm() -> bool {
|
|||
false
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref TEMP_DIR: tempfile::TempDir = tempfile::tempdir().unwrap();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn compile_to_wasm_bytes<'a>(
|
||||
arena: &'a bumpalo::Bump,
|
||||
config: HelperConfig,
|
||||
src: &str,
|
||||
context: &'a inkwell::context::Context,
|
||||
function_kind: FunctionKind,
|
||||
) -> Vec<u8> {
|
||||
// globally cache the temporary directory
|
||||
static TEMP_DIR: OnceLock<tempfile::TempDir> = OnceLock::new();
|
||||
let temp_dir = TEMP_DIR.get_or_init(|| tempfile::tempdir().unwrap());
|
||||
|
||||
let target = wasm32_target_tripple();
|
||||
|
||||
let (_main_fn_name, _delayed_errors, llvm_module) =
|
||||
create_llvm_module(arena, src, config, context, &target);
|
||||
create_llvm_module(arena, src, config, context, &target, function_kind);
|
||||
|
||||
let content_hash = crate::helpers::src_hash(src);
|
||||
let wasm_file = llvm_module_to_wasm_file(&TEMP_DIR, content_hash, llvm_module);
|
||||
let wasm_file = llvm_module_to_wasm_file(temp_dir, content_hash, llvm_module);
|
||||
let compiled_bytes = std::fs::read(wasm_file).unwrap();
|
||||
|
||||
if write_final_wasm() {
|
||||
|
@ -492,17 +502,14 @@ fn llvm_module_to_wasm_file(
|
|||
let msg = String::from_utf8_lossy(&output.stderr);
|
||||
|
||||
if msg.contains("wasm-ld: error: unknown file type") {
|
||||
panic!(
|
||||
"{}\nThis can happen if multiple tests have the same input string",
|
||||
msg
|
||||
);
|
||||
panic!("{msg}\nThis can happen if multiple tests have the same input string");
|
||||
} else {
|
||||
panic!("{}", msg);
|
||||
}
|
||||
}
|
||||
|
||||
assert!(output.status.success(), "{:#?}", output);
|
||||
assert!(output.stdout.is_empty(), "{:#?}", output);
|
||||
assert!(output.status.success(), "{output:#?}");
|
||||
assert!(output.stdout.is_empty(), "{output:#?}");
|
||||
|
||||
test_wasm_path
|
||||
}
|
||||
|
@ -513,7 +520,11 @@ fn fake_wasm_main_function(_: u32, _: u32) -> u32 {
|
|||
}
|
||||
|
||||
#[cfg(feature = "gen-llvm-wasm")]
|
||||
pub fn assert_wasm_evals_to_help<T>(src: &str, ignore_problems: bool) -> Result<T, String>
|
||||
pub fn assert_wasm_evals_to_help<T>(
|
||||
src: &str,
|
||||
ignore_problems: bool,
|
||||
function_kind: FunctionKind,
|
||||
) -> Result<T, String>
|
||||
where
|
||||
T: FromWasm32Memory + Wasm32Result,
|
||||
{
|
||||
|
@ -527,15 +538,19 @@ where
|
|||
opt_level: OPT_LEVEL,
|
||||
};
|
||||
|
||||
let wasm_bytes = compile_to_wasm_bytes(&arena, config, src, &context);
|
||||
let wasm_bytes = compile_to_wasm_bytes(&arena, config, src, &context, function_kind);
|
||||
|
||||
crate::helpers::wasm::run_wasm_test_bytes::<T>(TEST_WRAPPER_NAME, wasm_bytes)
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
#[cfg(feature = "gen-llvm-wasm")]
|
||||
macro_rules! assert_wasm_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr, $ignore_problems:expr) => {
|
||||
match $crate::helpers::llvm::assert_wasm_evals_to_help::<$ty>($src, $ignore_problems) {
|
||||
match $crate::helpers::llvm::assert_wasm_evals_to_help::<$ty>(
|
||||
$src,
|
||||
$ignore_problems,
|
||||
roc_load::FunctionKind::LambdaSet,
|
||||
) {
|
||||
Err(msg) => panic!("Wasm test failed: {}", msg),
|
||||
Ok(actual) => {
|
||||
assert_eq!($transform(actual), $expected, "Wasm test failed")
|
||||
|
@ -567,7 +582,7 @@ pub fn try_run_lib_function<T>(
|
|||
let main: libloading::Symbol<unsafe extern "C" fn(*mut RocCallResult<T>)> = lib
|
||||
.get(main_fn_name.as_bytes())
|
||||
.ok()
|
||||
.ok_or(format!("Unable to JIT compile `{}`", main_fn_name))
|
||||
.ok_or(format!("Unable to JIT compile `{main_fn_name}`"))
|
||||
.expect("errored");
|
||||
|
||||
let mut main_result = MaybeUninit::uninit();
|
||||
|
@ -578,9 +593,13 @@ pub fn try_run_lib_function<T>(
|
|||
}
|
||||
|
||||
// only used in tests
|
||||
#[allow(unused)]
|
||||
pub(crate) fn llvm_evals_to<T, U, F>(src: &str, expected: U, transform: F, ignore_problems: bool)
|
||||
where
|
||||
pub(crate) fn llvm_evals_to<T, U, F>(
|
||||
src: &str,
|
||||
expected: U,
|
||||
transform: F,
|
||||
ignore_problems: bool,
|
||||
function_kind: FunctionKind,
|
||||
) where
|
||||
U: PartialEq + std::fmt::Debug,
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
|
@ -597,14 +616,15 @@ where
|
|||
opt_level: crate::helpers::llvm::OPT_LEVEL,
|
||||
};
|
||||
|
||||
let (main_fn_name, errors, lib) = crate::helpers::llvm::helper(&arena, config, src, &context);
|
||||
let (main_fn_name, errors, lib) =
|
||||
crate::helpers::llvm::helper(&arena, config, src, &context, function_kind);
|
||||
|
||||
let result = crate::helpers::llvm::try_run_lib_function::<T>(main_fn_name, &lib);
|
||||
|
||||
match result {
|
||||
Ok(raw) => {
|
||||
// only if there are no exceptions thrown, check for errors
|
||||
assert!(errors.is_empty(), "Encountered errors:\n{}", errors);
|
||||
assert!(errors.is_empty(), "Encountered errors:\n{errors}");
|
||||
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
let given = transform(raw);
|
||||
|
@ -615,13 +635,12 @@ where
|
|||
std::mem::forget(given);
|
||||
}
|
||||
Err((msg, tag)) => match tag {
|
||||
CrashTag::Roc => panic!(r#"Roc failed with message: "{}""#, msg),
|
||||
CrashTag::User => panic!(r#"User crash with message: "{}""#, msg),
|
||||
CrashTag::Roc => panic!(r#"Roc failed with message: "{msg}""#),
|
||||
CrashTag::User => panic!(r#"User crash with message: "{msg}""#),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_llvm_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr, $ignore_problems:expr) => {
|
||||
crate::helpers::llvm::llvm_evals_to::<$ty, _, _>(
|
||||
|
@ -629,6 +648,7 @@ macro_rules! assert_llvm_evals_to {
|
|||
$expected,
|
||||
$transform,
|
||||
$ignore_problems,
|
||||
roc_load::FunctionKind::LambdaSet,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -654,8 +674,6 @@ macro_rules! assert_llvm_evals_to {
|
|||
//
|
||||
// let (_main_fn_name, _delayed_errors, _module) =
|
||||
// $crate::helpers::llvm::create_llvm_module(&arena, $src, config, &context, &target);
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty) => {{
|
||||
assert_evals_to!($src, $expected, $ty, $crate::helpers::llvm::identity, false);
|
||||
|
@ -686,14 +704,24 @@ macro_rules! assert_evals_to {
|
|||
}};
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
macro_rules! assert_evals_to_erased {
|
||||
($src:expr, $expected:expr, $ty:ty) => {{
|
||||
crate::helpers::llvm::llvm_evals_to::<$ty, _, _>(
|
||||
$src,
|
||||
$expected,
|
||||
$crate::helpers::llvm::identity,
|
||||
false,
|
||||
roc_load::FunctionKind::Erased,
|
||||
);
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn identity<T>(value: T) -> T {
|
||||
value
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_evals_to_erased;
|
||||
pub(crate) use assert_llvm_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(feature = "gen-llvm-wasm")]
|
||||
pub(crate) use assert_wasm_evals_to;
|
||||
|
|
|
@ -24,7 +24,7 @@ pub(crate) fn src_hash(src: &str) -> u64 {
|
|||
pub(crate) fn save_wasm_file(app_module_bytes: &[u8], build_dir_hash: u64) {
|
||||
use std::path::Path;
|
||||
|
||||
let debug_dir_str = format!("/tmp/roc/gen_wasm/{:016x}", build_dir_hash);
|
||||
let debug_dir_str = format!("/tmp/roc/gen_wasm/{build_dir_hash:016x}");
|
||||
let debug_dir_path = Path::new(&debug_dir_str);
|
||||
let final_wasm_file = debug_dir_path.join("final.wasm");
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ use roc_gen_wasm::DEBUG_SETTINGS;
|
|||
use roc_load::{ExecutionMode, LoadConfig, Threading};
|
||||
use roc_packaging::cache::RocCacheDir;
|
||||
use roc_reporting::report::DEFAULT_PALETTE_HTML;
|
||||
use roc_solve::FunctionKind;
|
||||
use roc_std::RocStr;
|
||||
use roc_wasm_interp::{wasi, ImportDispatcher, Instance, WasiDispatcher};
|
||||
use roc_wasm_module::{Export, ExportType, Value, WasmModule};
|
||||
|
@ -92,6 +93,7 @@ fn compile_roc_to_wasm_bytes<'a, T: Wasm32Result>(
|
|||
palette: DEFAULT_PALETTE_HTML,
|
||||
threading: Threading::Single,
|
||||
exec_mode: ExecutionMode::Executable,
|
||||
function_kind: FunctionKind::LambdaSet,
|
||||
};
|
||||
let loaded = roc_load::load_and_monomorphize_from_str(
|
||||
arena,
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
//! Contains all of Roc's [code generation](https://en.wikipedia.org/wiki/Code_generation_(compiler))
|
||||
//! tests.
|
||||
#[cfg(test)]
|
||||
pub mod helpers;
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
pub mod gen_abilities;
|
||||
pub mod gen_compare;
|
||||
pub mod gen_definitions;
|
||||
pub mod gen_dict;
|
||||
pub mod gen_erased;
|
||||
pub mod gen_list;
|
||||
pub mod gen_num;
|
||||
pub mod gen_panic;
|
||||
|
|
|
@ -14,8 +14,7 @@ use roc_module::symbol::{
|
|||
Symbol,
|
||||
};
|
||||
use roc_mono::ir::{
|
||||
Call, CallType, Expr, HostExposedLayouts, Literal, Proc, ProcLayout, SelfRecursive, Stmt,
|
||||
UpdateModeId,
|
||||
Call, CallType, Expr, Literal, Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId,
|
||||
};
|
||||
use roc_mono::layout::{LambdaName, Layout, Niche, STLayoutInterner};
|
||||
use roc_wasm_interp::{wasi, ImportDispatcher, Instance, WasiDispatcher};
|
||||
|
@ -116,7 +115,7 @@ fn build_app_mono<'a>(
|
|||
closure_data_layout: None,
|
||||
ret_layout: int_layout,
|
||||
is_self_recursive: SelfRecursive::NotSelfRecursive,
|
||||
host_exposed_layouts: HostExposedLayouts::NotHostExposed,
|
||||
is_erased: false,
|
||||
};
|
||||
|
||||
let proc_layout = ProcLayout {
|
||||
|
|
|
@ -989,78 +989,78 @@ fn str_trim_small_to_small_shared() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_left_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trimLeft " ""#), RocStr::from(""), RocStr);
|
||||
fn str_trim_start_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trimStart " ""#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_left_small_to_small() {
|
||||
fn str_trim_start_small_to_small() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimLeft " hello ""#),
|
||||
indoc!(r#"Str.trimStart " hello ""#),
|
||||
RocStr::from("hello "),
|
||||
RocStr
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_left_large_to_large_unique() {
|
||||
fn str_trim_start_large_to_large_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimLeft (Str.concat " " "hello world from a large string ")"#),
|
||||
indoc!(r#"Str.trimStart (Str.concat " " "hello world from a large string ")"#),
|
||||
RocStr::from("hello world from a large string "),
|
||||
RocStr
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_left_large_to_small_unique() {
|
||||
fn str_trim_start_large_to_small_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimLeft (Str.concat " " "hello ")"#),
|
||||
indoc!(r#"Str.trimStart (Str.concat " " "hello ")"#),
|
||||
RocStr::from("hello "),
|
||||
RocStr
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_right_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trimRight " ""#), RocStr::from(""), RocStr);
|
||||
fn str_trim_end_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trimEnd " ""#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_right_small_to_small() {
|
||||
fn str_trim_end_small_to_small() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimRight " hello ""#),
|
||||
indoc!(r#"Str.trimEnd " hello ""#),
|
||||
RocStr::from(" hello"),
|
||||
RocStr
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_right_large_to_large_unique() {
|
||||
fn str_trim_end_large_to_large_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimRight (Str.concat " hello world from a large string" " ")"#),
|
||||
indoc!(r#"Str.trimEnd (Str.concat " hello world from a large string" " ")"#),
|
||||
RocStr::from(" hello world from a large string"),
|
||||
RocStr
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_right_large_to_small_unique() {
|
||||
fn str_trim_end_large_to_small_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trimRight (Str.concat " hello" " ")"#),
|
||||
indoc!(r#"Str.trimEnd (Str.concat " hello" " ")"#),
|
||||
RocStr::from(" hello"),
|
||||
RocStr
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_right_large_to_large_shared() {
|
||||
fn str_trim_end_large_to_large_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
original : Str
|
||||
original = " hello world world "
|
||||
|
||||
{ trimmed: Str.trimRight original, original: original }
|
||||
{ trimmed: Str.trimEnd original, original: original }
|
||||
"#
|
||||
),
|
||||
(
|
||||
|
@ -1072,14 +1072,14 @@ fn str_trim_right_large_to_large_shared() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_right_large_to_small_shared() {
|
||||
fn str_trim_end_large_to_small_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
original : Str
|
||||
original = " hello "
|
||||
|
||||
{ trimmed: Str.trimRight original, original: original }
|
||||
{ trimmed: Str.trimEnd original, original: original }
|
||||
"#
|
||||
),
|
||||
(RocStr::from(" hello "), RocStr::from(" hello"),),
|
||||
|
@ -1088,14 +1088,14 @@ fn str_trim_right_large_to_small_shared() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn str_trim_right_small_to_small_shared() {
|
||||
fn str_trim_end_small_to_small_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
original : Str
|
||||
original = " hello "
|
||||
|
||||
{ trimmed: Str.trimRight original, original: original }
|
||||
{ trimmed: Str.trimEnd original, original: original }
|
||||
"#
|
||||
),
|
||||
(RocStr::from(" hello "), RocStr::from(" hello"),),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue