mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 06:55:15 +00:00
Merge branch 'trunk' into str_trim_left
This commit is contained in:
commit
07cd3850d7
62 changed files with 3288 additions and 7733 deletions
4
.cargo/config
Normal file
4
.cargo/config
Normal file
|
@ -0,0 +1,4 @@
|
|||
[alias]
|
||||
test-gen-llvm = "test -p test_gen"
|
||||
test-gen-dev = "test -p test_gen --no-default-features --features gen-dev"
|
||||
test-gen-wasm = "test -p test_gen --no-default-features --features gen-wasm"
|
57
Cargo.lock
generated
57
Cargo.lock
generated
|
@ -3402,12 +3402,10 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"bumpalo",
|
||||
"roc_builtins",
|
||||
"roc_can",
|
||||
"roc_collections",
|
||||
"roc_module",
|
||||
"roc_mono",
|
||||
"roc_std",
|
||||
"roc_types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4070,29 +4068,6 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test_dev"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"indoc",
|
||||
"libloading 0.7.1",
|
||||
"roc_build",
|
||||
"roc_builtins",
|
||||
"roc_can",
|
||||
"roc_collections",
|
||||
"roc_constrain",
|
||||
"roc_gen_dev",
|
||||
"roc_load",
|
||||
"roc_mono",
|
||||
"roc_parse",
|
||||
"roc_problem",
|
||||
"roc_reporting",
|
||||
"roc_std",
|
||||
"target-lexicon",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test_gen"
|
||||
version = "0.1.0"
|
||||
|
@ -4110,7 +4085,9 @@ dependencies = [
|
|||
"roc_can",
|
||||
"roc_collections",
|
||||
"roc_constrain",
|
||||
"roc_gen_dev",
|
||||
"roc_gen_llvm",
|
||||
"roc_gen_wasm",
|
||||
"roc_load",
|
||||
"roc_module",
|
||||
"roc_mono",
|
||||
|
@ -4124,7 +4101,6 @@ dependencies = [
|
|||
"roc_unify",
|
||||
"target-lexicon",
|
||||
"tempfile",
|
||||
"test_wasm_util",
|
||||
"wasmer",
|
||||
"wasmer-wasi",
|
||||
]
|
||||
|
@ -4154,35 +4130,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test_wasm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"indoc",
|
||||
"libc",
|
||||
"roc_builtins",
|
||||
"roc_can",
|
||||
"roc_collections",
|
||||
"roc_gen_wasm",
|
||||
"roc_load",
|
||||
"roc_module",
|
||||
"roc_std",
|
||||
"roc_types",
|
||||
"target-lexicon",
|
||||
"test_wasm_util",
|
||||
"wasmer",
|
||||
"wasmer-wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test_wasm_util"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"roc_std",
|
||||
"wasmer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
|
|
|
@ -22,9 +22,7 @@ members = [
|
|||
"compiler/gen_wasm",
|
||||
"compiler/build",
|
||||
"compiler/arena_pool",
|
||||
"compiler/test_dev",
|
||||
"compiler/test_gen",
|
||||
"compiler/test_wasm",
|
||||
"vendor/ena",
|
||||
"vendor/inkwell",
|
||||
"vendor/pathfinding",
|
||||
|
@ -44,7 +42,6 @@ exclude = [
|
|||
# The tests will still correctly build them.
|
||||
"cli_utils",
|
||||
"compiler/test_mono_macros",
|
||||
"compiler/test_wasm_util",
|
||||
]
|
||||
# Needed to be able to run `cargo run -p roc_cli --no-default-features` -
|
||||
# see www/build.sh for more.
|
||||
|
|
|
@ -79,10 +79,13 @@ test-rust:
|
|||
# not pre-compiling the host can cause race conditions
|
||||
RUN echo "4" | cargo run --release examples/benchmarks/NQueens.roc
|
||||
RUN --mount=type=cache,target=$SCCACHE_DIR \
|
||||
cargo test --release --features with_sound --workspace --exclude test_wasm && sccache --show-stats
|
||||
# test_wasm has some multithreading problems to do with the wasmer runtime. Run it single-threaded as a separate job
|
||||
cargo test --release --features with_sound --workspace && sccache --show-stats
|
||||
# test the dev and wasm backend: they require an explicit feature flag.
|
||||
RUN --mount=type=cache,target=$SCCACHE_DIR \
|
||||
cargo test --release --package test_wasm -- --test-threads=1 && sccache --show-stats
|
||||
cargo test --release --package test_gen --no-default-features --features gen-dev && sccache --show-stats
|
||||
# gen-wasm has some multithreading problems to do with the wasmer runtime. Run it single-threaded as a separate job
|
||||
RUN --mount=type=cache,target=$SCCACHE_DIR \
|
||||
cargo test --release --package test_gen --no-default-features --features gen-wasm -- --test-threads=1 && sccache --show-stats
|
||||
# run i386 (32-bit linux) cli tests
|
||||
RUN echo "4" | cargo run --release --features="target-x86" -- --backend=x86_32 examples/benchmarks/NQueens.roc
|
||||
RUN --mount=type=cache,target=$SCCACHE_DIR \
|
||||
|
|
|
@ -888,6 +888,34 @@ pub fn listTakeFirst(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn listTakeLast(
|
||||
list: RocList,
|
||||
alignment: u32,
|
||||
element_width: usize,
|
||||
take_count: usize,
|
||||
dec: Dec,
|
||||
) callconv(.C) RocList {
|
||||
if (take_count == 0) {
|
||||
return RocList.empty();
|
||||
}
|
||||
if (list.bytes) |source_ptr| {
|
||||
const size = list.len();
|
||||
if (size <= take_count) {
|
||||
return list;
|
||||
}
|
||||
const drop_count = size - take_count;
|
||||
return listDrop(
|
||||
list,
|
||||
alignment,
|
||||
element_width,
|
||||
drop_count,
|
||||
dec,
|
||||
);
|
||||
} else {
|
||||
return RocList.empty();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn listDrop(
|
||||
list: RocList,
|
||||
alignment: u32,
|
||||
|
@ -1333,3 +1361,39 @@ inline fn listSetImmutable(
|
|||
//return list;
|
||||
return new_bytes;
|
||||
}
|
||||
|
||||
pub fn listFindUnsafe(
|
||||
list: RocList,
|
||||
caller: Caller1,
|
||||
data: Opaque,
|
||||
inc_n_data: IncN,
|
||||
data_is_owned: bool,
|
||||
alignment: u32,
|
||||
element_width: usize,
|
||||
inc: Inc,
|
||||
dec: Dec,
|
||||
) callconv(.C) extern struct { value: Opaque, found: bool } {
|
||||
if (list.bytes) |source_ptr| {
|
||||
const size = list.len();
|
||||
if (data_is_owned) {
|
||||
inc_n_data(data, size);
|
||||
}
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < size) : (i += 1) {
|
||||
var theOne = false;
|
||||
const element = source_ptr + (i * element_width);
|
||||
inc(element);
|
||||
caller(data, element, @ptrCast(?[*]u8, &theOne));
|
||||
|
||||
if (theOne) {
|
||||
return .{ .value = element, .found = true };
|
||||
} else {
|
||||
dec(element);
|
||||
}
|
||||
}
|
||||
return .{ .value = null, .found = false };
|
||||
} else {
|
||||
return .{ .value = null, .found = false };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,12 +46,14 @@ comptime {
|
|||
exportListFn(list.listSortWith, "sort_with");
|
||||
exportListFn(list.listConcat, "concat");
|
||||
exportListFn(list.listTakeFirst, "take_first");
|
||||
exportListFn(list.listTakeLast, "take_last");
|
||||
exportListFn(list.listDrop, "drop");
|
||||
exportListFn(list.listDropAt, "drop_at");
|
||||
exportListFn(list.listSet, "set");
|
||||
exportListFn(list.listSetInPlace, "set_in_place");
|
||||
exportListFn(list.listSwap, "swap");
|
||||
exportListFn(list.listAny, "any");
|
||||
exportListFn(list.listFindUnsafe, "find_unsafe");
|
||||
}
|
||||
|
||||
// Dict Module
|
||||
|
|
|
@ -690,3 +690,7 @@ all : List elem, (elem -> Bool) -> Bool
|
|||
## Run the given predicate on each element of the list, returning `True` if
|
||||
## any of the elements satisfy it.
|
||||
any : List elem, (elem -> Bool) -> Bool
|
||||
|
||||
## Returns the first element of the list satisfying a predicate function.
|
||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||
find : List elem, (elem -> Bool) -> Result elem [ NotFound ]*
|
||||
|
|
|
@ -179,6 +179,7 @@ pub const LIST_REPEAT: &str = "roc_builtins.list.repeat";
|
|||
pub const LIST_APPEND: &str = "roc_builtins.list.append";
|
||||
pub const LIST_PREPEND: &str = "roc_builtins.list.prepend";
|
||||
pub const LIST_TAKE_FIRST: &str = "roc_builtins.list.take_first";
|
||||
pub const LIST_TAKE_LAST: &str = "roc_builtins.list.take_last";
|
||||
pub const LIST_DROP: &str = "roc_builtins.list.drop";
|
||||
pub const LIST_DROP_AT: &str = "roc_builtins.list.drop_at";
|
||||
pub const LIST_SWAP: &str = "roc_builtins.list.swap";
|
||||
|
@ -191,6 +192,7 @@ pub const LIST_CONCAT: &str = "roc_builtins.list.concat";
|
|||
pub const LIST_SET: &str = "roc_builtins.list.set";
|
||||
pub const LIST_SET_IN_PLACE: &str = "roc_builtins.list.set_in_place";
|
||||
pub const LIST_ANY: &str = "roc_builtins.list.any";
|
||||
pub const LIST_FIND_UNSAFE: &str = "roc_builtins.list.find_unsafe";
|
||||
|
||||
pub const DEC_FROM_F64: &str = "roc_builtins.dec.from_f64";
|
||||
pub const DEC_EQ: &str = "roc_builtins.dec.eq";
|
||||
|
|
|
@ -985,6 +985,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
|||
Box::new(list_type(flex(TVAR1))),
|
||||
);
|
||||
|
||||
// takeLast : List elem, Nat -> List elem
|
||||
add_top_level_function_type!(
|
||||
Symbol::LIST_TAKE_LAST,
|
||||
vec![list_type(flex(TVAR1)), nat_type()],
|
||||
Box::new(list_type(flex(TVAR1))),
|
||||
);
|
||||
|
||||
// drop : List elem, Nat -> List elem
|
||||
add_top_level_function_type!(
|
||||
Symbol::LIST_DROP,
|
||||
|
@ -1093,6 +1100,23 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
|||
Box::new(list_type(flex(TVAR1))),
|
||||
);
|
||||
|
||||
// find : List elem, (elem -> Bool) -> Result elem [ NotFound ]*
|
||||
{
|
||||
let not_found = SolvedType::TagUnion(
|
||||
vec![(TagName::Global("NotFound".into()), vec![])],
|
||||
Box::new(SolvedType::Wildcard),
|
||||
);
|
||||
let (elem, cvar) = (TVAR1, TVAR2);
|
||||
add_top_level_function_type!(
|
||||
Symbol::LIST_FIND,
|
||||
vec![
|
||||
list_type(flex(elem)),
|
||||
closure(vec![flex(elem)], cvar, Box::new(bool_type())),
|
||||
],
|
||||
Box::new(result_type(flex(elem), not_found)),
|
||||
)
|
||||
}
|
||||
|
||||
// Dict module
|
||||
|
||||
// len : Dict * * -> Nat
|
||||
|
|
|
@ -93,6 +93,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
|
|||
LIST_MAP3 => list_map3,
|
||||
LIST_MAP4 => list_map4,
|
||||
LIST_TAKE_FIRST => list_take_first,
|
||||
LIST_TAKE_LAST => list_take_last,
|
||||
LIST_DROP => list_drop,
|
||||
LIST_DROP_AT => list_drop_at,
|
||||
LIST_DROP_FIRST => list_drop_first,
|
||||
|
@ -108,6 +109,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
|
|||
LIST_WALK_UNTIL => list_walk_until,
|
||||
LIST_SORT_WITH => list_sort_with,
|
||||
LIST_ANY => list_any,
|
||||
LIST_FIND => list_find,
|
||||
DICT_LEN => dict_len,
|
||||
DICT_EMPTY => dict_empty,
|
||||
DICT_SINGLE => dict_single,
|
||||
|
@ -2035,6 +2037,29 @@ fn list_take_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
)
|
||||
}
|
||||
|
||||
/// List.takeLast : List elem, Nat -> List elem
|
||||
fn list_take_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let list_var = var_store.fresh();
|
||||
let len_var = var_store.fresh();
|
||||
|
||||
let body = RunLowLevel {
|
||||
op: LowLevel::ListTakeLast,
|
||||
args: vec![
|
||||
(list_var, Var(Symbol::ARG_1)),
|
||||
(len_var, Var(Symbol::ARG_2)),
|
||||
],
|
||||
ret_var: list_var,
|
||||
};
|
||||
|
||||
defn(
|
||||
symbol,
|
||||
vec![(list_var, Symbol::ARG_1), (len_var, Symbol::ARG_2)],
|
||||
var_store,
|
||||
body,
|
||||
list_var,
|
||||
)
|
||||
}
|
||||
|
||||
/// List.drop : List elem, Nat -> List elem
|
||||
fn list_drop(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let list_var = var_store.fresh();
|
||||
|
@ -2730,6 +2755,87 @@ fn list_any(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
lowlevel_2(symbol, LowLevel::ListAny, var_store)
|
||||
}
|
||||
|
||||
/// List.find : List elem, (elem -> Bool) -> Result elem [ NotFound ]*
|
||||
fn list_find(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let list = Symbol::ARG_1;
|
||||
let find_predicate = Symbol::ARG_2;
|
||||
|
||||
let find_result = Symbol::LIST_FIND_RESULT;
|
||||
|
||||
let t_list = var_store.fresh();
|
||||
let t_pred_fn = var_store.fresh();
|
||||
let t_bool = var_store.fresh();
|
||||
let t_found = var_store.fresh();
|
||||
let t_value = var_store.fresh();
|
||||
let t_ret = var_store.fresh();
|
||||
let t_find_result = var_store.fresh();
|
||||
let t_ext_var1 = var_store.fresh();
|
||||
let t_ext_var2 = var_store.fresh();
|
||||
|
||||
// ListFindUnsafe returns { value: elem, found: Bool }.
|
||||
// When `found` is true, the value was found. Otherwise `List.find` should return `Err ...`
|
||||
let find_result_def = Def {
|
||||
annotation: None,
|
||||
expr_var: t_find_result,
|
||||
loc_expr: no_region(RunLowLevel {
|
||||
op: LowLevel::ListFindUnsafe,
|
||||
args: vec![(t_list, Var(list)), (t_pred_fn, Var(find_predicate))],
|
||||
ret_var: t_find_result,
|
||||
}),
|
||||
loc_pattern: no_region(Pattern::Identifier(find_result)),
|
||||
pattern_vars: Default::default(),
|
||||
};
|
||||
|
||||
let get_value = Access {
|
||||
record_var: t_find_result,
|
||||
ext_var: t_ext_var1,
|
||||
field_var: t_value,
|
||||
loc_expr: Box::new(no_region(Var(find_result))),
|
||||
field: "value".into(),
|
||||
};
|
||||
|
||||
let get_found = Access {
|
||||
record_var: t_find_result,
|
||||
ext_var: t_ext_var2,
|
||||
field_var: t_found,
|
||||
loc_expr: Box::new(no_region(Var(find_result))),
|
||||
field: "found".into(),
|
||||
};
|
||||
|
||||
let make_ok = tag("Ok", vec![get_value], var_store);
|
||||
|
||||
let make_err = tag(
|
||||
"Err",
|
||||
vec![tag("NotFound", Vec::new(), var_store)],
|
||||
var_store,
|
||||
);
|
||||
|
||||
let inspect = If {
|
||||
cond_var: t_bool,
|
||||
branch_var: t_ret,
|
||||
branches: vec![(
|
||||
// if-condition
|
||||
no_region(get_found),
|
||||
no_region(make_ok),
|
||||
)],
|
||||
final_else: Box::new(no_region(make_err)),
|
||||
};
|
||||
|
||||
let body = LetNonRec(
|
||||
Box::new(find_result_def),
|
||||
Box::new(no_region(inspect)),
|
||||
t_ret,
|
||||
);
|
||||
|
||||
defn(
|
||||
symbol,
|
||||
vec![(t_list, Symbol::ARG_1), (t_pred_fn, Symbol::ARG_2)],
|
||||
var_store,
|
||||
body,
|
||||
t_ret,
|
||||
)
|
||||
}
|
||||
|
||||
/// Dict.len : Dict * * -> Nat
|
||||
fn dict_len(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let arg1_var = var_store.fresh();
|
||||
|
|
|
@ -67,10 +67,9 @@ This is the general procedure I follow with some helpful links:
|
|||
1. Find a feature that is just n+1.
|
||||
For example, since we already have integers, adding a builtin that functions on them should be n+1.
|
||||
On the other hand, since we don't yet have booleans/conditionals, adding if statements may not yet be n+1.
|
||||
A good place to look for missing features is in the test files for both the [regular](https://github.com/rtfeldman/roc/tree/trunk/compiler/gen/tests) and [dev](https://github.com/rtfeldman/roc/tree/trunk/compiler/gen_dev/tests) backend.
|
||||
Eventually these test files should be practically identical.
|
||||
A good place to look for missing features is in the test files for generation in [test_gen](https://github.com/rtfeldman/roc/tree/trunk/compiler/test_gen). Any test that is not enabled for the `gen-dev` feature still needs to be added to the dev backend. Eventually all features should be enabled for the dev backend.
|
||||
1. Pick/write the simplest test case you can find for the new feature.
|
||||
Just uncomment/copy over the test if it already exists.
|
||||
Just add `feature = "gen-dev"` to the `cfg` line for the test case.
|
||||
1. Uncomment the code to print out procedures [from here](https://github.com/rtfeldman/roc/blob/trunk/compiler/gen_dev/tests/helpers/eval.rs) and run the test.
|
||||
It should fail and print out the mono ir for this test case.
|
||||
Seeing the actual mono ir tends to be very helpful for complex additions.
|
||||
|
|
|
@ -9,10 +9,11 @@ use crate::llvm::build_dict::{
|
|||
use crate::llvm::build_hash::generic_hash;
|
||||
use crate::llvm::build_list::{
|
||||
self, allocate_list, empty_list, empty_polymorphic_list, list_any, list_append, list_concat,
|
||||
list_contains, list_drop, list_drop_at, list_get_unsafe, list_join, list_keep_errs,
|
||||
list_keep_if, list_keep_oks, list_len, list_map, list_map2, list_map3, list_map4,
|
||||
list_map_with_index, list_prepend, list_range, list_repeat, list_reverse, list_set,
|
||||
list_single, list_sort_with, list_swap, list_take_first,
|
||||
list_contains, list_drop, list_drop_at, list_find_trivial_not_found, list_find_unsafe,
|
||||
list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len, list_map,
|
||||
list_map2, list_map3, list_map4, list_map_with_index, list_prepend, list_range, list_repeat,
|
||||
list_reverse, list_set, list_single, list_sort_with, list_swap, list_take_first,
|
||||
list_take_last,
|
||||
};
|
||||
use crate::llvm::build_str::{
|
||||
empty_str, str_concat, str_count_graphemes, str_ends_with, str_from_float, str_from_int,
|
||||
|
@ -4887,6 +4888,37 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
_ => unreachable!("invalid list layout"),
|
||||
}
|
||||
}
|
||||
ListFindUnsafe { xs } => {
|
||||
let (list, list_layout) = load_symbol_and_layout(scope, &xs);
|
||||
|
||||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => {
|
||||
// Returns { found: False, elem: \empty }, where the `elem` field is zero-sized.
|
||||
// NB: currently we never hit this case, since the only caller of this
|
||||
// lowlevel, namely List.find, will fail during monomorphization when there is no
|
||||
// concrete list element type. This is because List.find returns a
|
||||
// `Result elem [ NotFound ]*`, and we can't figure out the size of that if
|
||||
// `elem` is not concrete.
|
||||
list_find_trivial_not_found(env)
|
||||
}
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
let argument_layouts = &[**element_layout];
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
closure_layout,
|
||||
function_owns_closure_data,
|
||||
argument_layouts,
|
||||
);
|
||||
list_find_unsafe(env, layout_ids, roc_function_call, list, element_layout)
|
||||
}
|
||||
_ => unreachable!("invalid list layout"),
|
||||
}
|
||||
}
|
||||
DictWalk { xs, state } => {
|
||||
let (dict, dict_layout) = load_symbol_and_layout(scope, &xs);
|
||||
let (default, default_layout) = load_symbol_and_layout(scope, &state);
|
||||
|
@ -5178,6 +5210,27 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
_ => unreachable!("Invalid layout {:?} in List.takeFirst", list_layout),
|
||||
}
|
||||
}
|
||||
ListTakeLast => {
|
||||
// List.takeLast : List elem, Nat -> List elem
|
||||
debug_assert_eq!(args.len(), 2);
|
||||
|
||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
let original_wrapper = list.into_struct_value();
|
||||
|
||||
let count = load_symbol(scope, &args[1]);
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||
Layout::Builtin(Builtin::List(element_layout)) => list_take_last(
|
||||
env,
|
||||
layout_ids,
|
||||
original_wrapper,
|
||||
count.into_int_value(),
|
||||
element_layout,
|
||||
),
|
||||
_ => unreachable!("Invalid layout {:?} in List.takeLast", list_layout),
|
||||
}
|
||||
}
|
||||
ListDrop => {
|
||||
// List.drop : List elem, Nat -> List elem
|
||||
debug_assert_eq!(args.len(), 2);
|
||||
|
@ -5763,7 +5816,9 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListKeepIf | ListWalk
|
||||
| ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith
|
||||
| ListAny | DictWalk => unreachable!("these are higher order, and are handled elsewhere"),
|
||||
| ListAny | ListFindUnsafe | DictWalk => {
|
||||
unreachable!("these are higher order, and are handled elsewhere")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -316,6 +316,28 @@ pub fn list_take_first<'a, 'ctx, 'env>(
|
|||
)
|
||||
}
|
||||
|
||||
/// List.takeLast : List elem, Nat -> List elem
|
||||
pub fn list_take_last<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
count: IntValue<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
|
||||
call_bitcode_fn_returns_list(
|
||||
env,
|
||||
&[
|
||||
pass_list_cc(env, original_wrapper.into()),
|
||||
env.alignment_intvalue(element_layout),
|
||||
layout_width(env, element_layout),
|
||||
count.into(),
|
||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||
],
|
||||
bitcode::LIST_TAKE_LAST,
|
||||
)
|
||||
}
|
||||
|
||||
/// List.drop : List elem, Nat -> List elem
|
||||
pub fn list_drop<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
|
@ -936,6 +958,123 @@ pub fn list_any<'a, 'ctx, 'env>(
|
|||
)
|
||||
}
|
||||
|
||||
/// List.findUnsafe : List elem, (elem -> Bool) -> { value: elem, found: bool }
|
||||
pub fn list_find_unsafe<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
list: BasicValueEnum<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let inc_element_fn = build_inc_wrapper(env, layout_ids, element_layout);
|
||||
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
|
||||
|
||||
// { value: *const u8, found: bool }
|
||||
let result = call_bitcode_fn(
|
||||
env,
|
||||
&[
|
||||
pass_list_cc(env, list),
|
||||
roc_function_call.caller.into(),
|
||||
pass_as_opaque(env, roc_function_call.data),
|
||||
roc_function_call.inc_n_data.into(),
|
||||
roc_function_call.data_is_owned.into(),
|
||||
env.alignment_intvalue(element_layout),
|
||||
layout_width(env, element_layout),
|
||||
inc_element_fn.as_global_value().as_pointer_value().into(),
|
||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||
],
|
||||
bitcode::LIST_FIND_UNSAFE,
|
||||
)
|
||||
.into_struct_value();
|
||||
|
||||
// We promised the caller we'd give them back a struct containing the element
|
||||
// loaded on the stack, so we do that now. The element can't be loaded directly
|
||||
// in the Zig definition called above, because we don't know the size of the
|
||||
// element until user compile time, which is later than the compile time of bitcode defs.
|
||||
|
||||
let value_u8_ptr = env
|
||||
.builder
|
||||
.build_extract_value(result, 0, "get_value_ptr")
|
||||
.unwrap()
|
||||
.into_pointer_value();
|
||||
|
||||
let found = env
|
||||
.builder
|
||||
.build_extract_value(result, 1, "get_found")
|
||||
.unwrap()
|
||||
.into_int_value();
|
||||
|
||||
let start_block = env.builder.get_insert_block().unwrap();
|
||||
let parent = start_block.get_parent().unwrap();
|
||||
|
||||
let if_not_null = env.context.append_basic_block(parent, "if_not_null");
|
||||
let done_block = env.context.append_basic_block(parent, "done");
|
||||
|
||||
let value_bt = basic_type_from_layout(env, element_layout);
|
||||
let default = value_bt.const_zero();
|
||||
|
||||
env.builder
|
||||
.build_conditional_branch(found, if_not_null, done_block);
|
||||
|
||||
env.builder.position_at_end(if_not_null);
|
||||
let value_ptr = env
|
||||
.builder
|
||||
.build_bitcast(
|
||||
value_u8_ptr,
|
||||
value_bt.ptr_type(AddressSpace::Generic),
|
||||
"from_opaque",
|
||||
)
|
||||
.into_pointer_value();
|
||||
let loaded = env.builder.build_load(value_ptr, "load_value");
|
||||
env.builder.build_unconditional_branch(done_block);
|
||||
|
||||
env.builder.position_at_end(done_block);
|
||||
let result_phi = env.builder.build_phi(value_bt, "result");
|
||||
|
||||
result_phi.add_incoming(&[(&default, start_block), (&loaded, if_not_null)]);
|
||||
|
||||
let value = result_phi.as_basic_value();
|
||||
|
||||
let result = env
|
||||
.context
|
||||
.struct_type(&[value_bt, env.context.bool_type().into()], false)
|
||||
.const_zero();
|
||||
|
||||
let result = env
|
||||
.builder
|
||||
.build_insert_value(result, value, 0, "insert_value")
|
||||
.unwrap();
|
||||
|
||||
env.builder
|
||||
.build_insert_value(result, found, 1, "insert_found")
|
||||
.unwrap()
|
||||
.into_struct_value()
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Returns { value: \empty, found: False }, representing that no element was found in a call
|
||||
/// to List.find when the layout of the element is also unknown.
|
||||
pub fn list_find_trivial_not_found<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let empty_type = env.context.custom_width_int_type(0);
|
||||
let result = env
|
||||
.context
|
||||
.struct_type(&[empty_type.into(), env.context.bool_type().into()], false)
|
||||
.const_zero();
|
||||
|
||||
env.builder
|
||||
.build_insert_value(
|
||||
result,
|
||||
env.context.bool_type().const_zero(),
|
||||
1,
|
||||
"insert_found",
|
||||
)
|
||||
.unwrap()
|
||||
.into_struct_value()
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn decrementing_elem_loop<'ctx, LoopFn>(
|
||||
builder: &Builder<'ctx>,
|
||||
ctx: &'ctx Context,
|
||||
|
|
|
@ -6,15 +6,9 @@ edition = "2018"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bumpalo = { version = "3.8.0", features = ["collections"] }
|
||||
roc_builtins = { path = "../builtins" }
|
||||
roc_collections = { path = "../collections" }
|
||||
roc_module = { path = "../module" }
|
||||
roc_mono = { path = "../mono" }
|
||||
bumpalo = { version = "3.8.0", features = ["collections"] }
|
||||
|
||||
roc_std = { path = "../../roc_std" }
|
||||
|
||||
[dev-dependencies]
|
||||
roc_can = { path = "../can" }
|
||||
roc_builtins = { path = "../builtins" }
|
||||
roc_types = { path = "../types" }
|
||||
roc_module = { path = "../module" }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use bumpalo::{self, collections::Vec};
|
||||
|
||||
use code_builder::Align;
|
||||
use roc_builtins::bitcode::{self, FloatWidth};
|
||||
use roc_collections::all::MutMap;
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::Symbol;
|
||||
|
@ -9,10 +10,12 @@ use roc_mono::layout::{Layout, LayoutIds};
|
|||
|
||||
use crate::layout::WasmLayout;
|
||||
use crate::storage::{Storage, StoredValue, StoredValueKind};
|
||||
use crate::wasm_module::linking::{DataSymbol, LinkingSection, RelocationSection};
|
||||
use crate::wasm_module::linking::{
|
||||
DataSymbol, LinkingSection, RelocationSection, WasmObjectSymbol, WASM_SYM_UNDEFINED,
|
||||
};
|
||||
use crate::wasm_module::sections::{
|
||||
CodeSection, DataMode, DataSection, DataSegment, ExportSection, FunctionSection, GlobalSection,
|
||||
ImportSection, MemorySection, TypeSection, WasmModule,
|
||||
Import, ImportDesc, ImportSection, MemorySection, TypeSection, WasmModule,
|
||||
};
|
||||
use crate::wasm_module::{
|
||||
code_builder, BlockType, CodeBuilder, ConstExpr, Export, ExportType, Global, GlobalType,
|
||||
|
@ -28,6 +31,8 @@ const CONST_SEGMENT_BASE_ADDR: u32 = 1024;
|
|||
/// Index of the data segment where we store constants
|
||||
const CONST_SEGMENT_INDEX: usize = 0;
|
||||
|
||||
const IMPORT_MODULE_BUILTINS: &str = "builtins";
|
||||
|
||||
pub struct WasmBackend<'a> {
|
||||
env: &'a Env<'a>,
|
||||
|
||||
|
@ -35,6 +40,7 @@ pub struct WasmBackend<'a> {
|
|||
pub module: WasmModule<'a>,
|
||||
layout_ids: LayoutIds<'a>,
|
||||
constant_sym_index_map: MutMap<&'a str, usize>,
|
||||
builtin_sym_index_map: MutMap<&'a str, usize>,
|
||||
proc_symbols: Vec<'a, Symbol>,
|
||||
pub linker_symbols: Vec<'a, SymInfo>,
|
||||
|
||||
|
@ -52,7 +58,7 @@ impl<'a> WasmBackend<'a> {
|
|||
env: &'a Env<'a>,
|
||||
layout_ids: LayoutIds<'a>,
|
||||
proc_symbols: Vec<'a, Symbol>,
|
||||
linker_symbols: Vec<'a, SymInfo>,
|
||||
mut linker_symbols: Vec<'a, SymInfo>,
|
||||
mut exports: Vec<'a, Export>,
|
||||
) -> Self {
|
||||
const MEMORY_INIT_SIZE: u32 = 1024 * 1024;
|
||||
|
@ -60,7 +66,7 @@ impl<'a> WasmBackend<'a> {
|
|||
let num_procs = proc_symbols.len();
|
||||
|
||||
exports.push(Export {
|
||||
name: "memory".to_string(),
|
||||
name: "__linear_memory".to_string(),
|
||||
ty: ExportType::Mem,
|
||||
index: 0,
|
||||
});
|
||||
|
@ -72,6 +78,11 @@ impl<'a> WasmBackend<'a> {
|
|||
},
|
||||
init: ConstExpr::I32(MEMORY_INIT_SIZE as i32),
|
||||
};
|
||||
linker_symbols.push(SymInfo::Global(WasmObjectSymbol::Defined {
|
||||
flags: 0,
|
||||
index: 0,
|
||||
name: "__stack_pointer".to_string(),
|
||||
}));
|
||||
|
||||
let const_segment = DataSegment {
|
||||
mode: DataMode::Active {
|
||||
|
@ -92,7 +103,9 @@ impl<'a> WasmBackend<'a> {
|
|||
export: ExportSection { entries: exports },
|
||||
start: (),
|
||||
element: (),
|
||||
code: CodeSection::new(arena),
|
||||
code: CodeSection {
|
||||
code_builders: Vec::with_capacity_in(num_procs, arena),
|
||||
},
|
||||
data: DataSection {
|
||||
segments: bumpalo::vec![in arena; const_segment],
|
||||
},
|
||||
|
@ -108,6 +121,7 @@ impl<'a> WasmBackend<'a> {
|
|||
|
||||
layout_ids,
|
||||
constant_sym_index_map: MutMap::default(),
|
||||
builtin_sym_index_map: MutMap::default(),
|
||||
proc_symbols,
|
||||
linker_symbols,
|
||||
|
||||
|
@ -181,7 +195,7 @@ impl<'a> WasmBackend<'a> {
|
|||
self.end_block();
|
||||
|
||||
// Write local declarations and stack frame push/pop code
|
||||
self.code_builder.finalize(
|
||||
self.code_builder.build_fn_header(
|
||||
&self.storage.local_types,
|
||||
self.storage.stack_frame_size,
|
||||
self.storage.stack_frame_pointer,
|
||||
|
@ -650,42 +664,60 @@ impl<'a> WasmBackend<'a> {
|
|||
) -> Result<(), String> {
|
||||
self.storage.load_symbols(&mut self.code_builder, args);
|
||||
let wasm_layout = WasmLayout::new(return_layout);
|
||||
self.build_instructions_lowlevel(lowlevel, wasm_layout.value_type())?;
|
||||
Ok(())
|
||||
}
|
||||
let ret_type = wasm_layout.value_type();
|
||||
|
||||
let panic_ret_type = || panic!("Invalid return type for {:?}: {:?}", lowlevel, ret_type);
|
||||
|
||||
fn build_instructions_lowlevel(
|
||||
&mut self,
|
||||
lowlevel: &LowLevel,
|
||||
return_value_type: ValueType,
|
||||
) -> Result<(), String> {
|
||||
// TODO: Find a way to organise all the lowlevel ops and layouts! There's lots!
|
||||
//
|
||||
// Some Roc low-level ops care about wrapping, clipping, sign-extending...
|
||||
// For those, we'll need to pre-process each argument before the main op,
|
||||
// so simple arrays of instructions won't work. But there are common patterns.
|
||||
match lowlevel {
|
||||
LowLevel::NumAdd => match return_value_type {
|
||||
LowLevel::NumAdd => match ret_type {
|
||||
ValueType::I32 => self.code_builder.i32_add(),
|
||||
ValueType::I64 => self.code_builder.i64_add(),
|
||||
ValueType::F32 => self.code_builder.f32_add(),
|
||||
ValueType::F64 => self.code_builder.f64_add(),
|
||||
},
|
||||
LowLevel::NumSub => match return_value_type {
|
||||
LowLevel::NumSub => match ret_type {
|
||||
ValueType::I32 => self.code_builder.i32_sub(),
|
||||
ValueType::I64 => self.code_builder.i64_sub(),
|
||||
ValueType::F32 => self.code_builder.f32_sub(),
|
||||
ValueType::F64 => self.code_builder.f64_sub(),
|
||||
},
|
||||
LowLevel::NumMul => match return_value_type {
|
||||
LowLevel::NumMul => match ret_type {
|
||||
ValueType::I32 => self.code_builder.i32_mul(),
|
||||
ValueType::I64 => self.code_builder.i64_mul(),
|
||||
ValueType::F32 => self.code_builder.f32_mul(),
|
||||
ValueType::F64 => self.code_builder.f64_mul(),
|
||||
},
|
||||
LowLevel::NumGt => {
|
||||
// needs layout of the argument to be implemented fully
|
||||
self.code_builder.i32_gt_s()
|
||||
LowLevel::NumGt => match self.get_uniform_arg_type(args) {
|
||||
ValueType::I32 => self.code_builder.i32_gt_s(),
|
||||
ValueType::I64 => self.code_builder.i64_gt_s(),
|
||||
ValueType::F32 => self.code_builder.f32_gt(),
|
||||
ValueType::F64 => self.code_builder.f64_gt(),
|
||||
},
|
||||
LowLevel::Eq => match self.get_uniform_arg_type(args) {
|
||||
ValueType::I32 => self.code_builder.i32_eq(),
|
||||
ValueType::I64 => self.code_builder.i64_eq(),
|
||||
ValueType::F32 => self.code_builder.f32_eq(),
|
||||
ValueType::F64 => self.code_builder.f64_eq(),
|
||||
},
|
||||
LowLevel::NumNeg => match ret_type {
|
||||
ValueType::I32 => {
|
||||
self.code_builder.i32_const(-1);
|
||||
self.code_builder.i32_mul();
|
||||
}
|
||||
ValueType::I64 => {
|
||||
self.code_builder.i64_const(-1);
|
||||
self.code_builder.i64_mul();
|
||||
}
|
||||
ValueType::F32 => self.code_builder.f32_neg(),
|
||||
ValueType::F64 => self.code_builder.f64_neg(),
|
||||
},
|
||||
LowLevel::NumAtan => {
|
||||
let name = match ret_type {
|
||||
ValueType::F32 => &bitcode::NUM_ATAN[FloatWidth::F32],
|
||||
ValueType::F64 => &bitcode::NUM_ATAN[FloatWidth::F64],
|
||||
_ => panic_ret_type(),
|
||||
};
|
||||
self.call_imported_builtin(name, &[ret_type], Some(ret_type));
|
||||
}
|
||||
_ => {
|
||||
return Err(format!("unsupported low-level op {:?}", lowlevel));
|
||||
|
@ -693,4 +725,61 @@ impl<'a> WasmBackend<'a> {
|
|||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the ValueType for a set of arguments that are required to have the same type
|
||||
fn get_uniform_arg_type(&self, args: &'a [Symbol]) -> ValueType {
|
||||
let value_type = self.storage.get(&args[0]).value_type();
|
||||
for arg in args.iter().skip(1) {
|
||||
debug_assert!(self.storage.get(arg).value_type() == value_type);
|
||||
}
|
||||
value_type
|
||||
}
|
||||
|
||||
fn call_imported_builtin(
|
||||
&mut self,
|
||||
name: &'a str,
|
||||
arg_types: &[ValueType],
|
||||
ret_type: Option<ValueType>,
|
||||
) {
|
||||
let (fn_index, linker_symbol_index) = match self.builtin_sym_index_map.get(name) {
|
||||
Some(sym_idx) => match &self.linker_symbols[*sym_idx] {
|
||||
SymInfo::Function(WasmObjectSymbol::Imported { index, .. }) => {
|
||||
(*index, *sym_idx as u32)
|
||||
}
|
||||
x => unreachable!("Invalid linker symbol for builtin {}: {:?}", name, x),
|
||||
},
|
||||
|
||||
None => {
|
||||
let mut param_types = Vec::with_capacity_in(arg_types.len(), self.env.arena);
|
||||
param_types.extend_from_slice(arg_types);
|
||||
let signature_index = self.module.types.insert(Signature {
|
||||
param_types,
|
||||
ret_type,
|
||||
});
|
||||
|
||||
let import_index = self.module.import.entries.len() as u32;
|
||||
let import = Import {
|
||||
module: IMPORT_MODULE_BUILTINS,
|
||||
name: name.to_string(),
|
||||
description: ImportDesc::Func { signature_index },
|
||||
};
|
||||
self.module.import.entries.push(import);
|
||||
|
||||
let sym_idx = self.linker_symbols.len() as u32;
|
||||
let sym_info = SymInfo::Function(WasmObjectSymbol::Imported {
|
||||
flags: WASM_SYM_UNDEFINED,
|
||||
index: import_index,
|
||||
});
|
||||
self.linker_symbols.push(sym_info);
|
||||
|
||||
(import_index, sym_idx)
|
||||
}
|
||||
};
|
||||
self.code_builder.call(
|
||||
fn_index,
|
||||
linker_symbol_index,
|
||||
arg_types.len(),
|
||||
ret_type.is_some(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ pub fn build_module<'a>(
|
|||
) -> Result<std::vec::Vec<u8>, String> {
|
||||
let mut wasm_module = build_module_help(env, procedures)?;
|
||||
let mut buffer = std::vec::Vec::with_capacity(4096);
|
||||
wasm_module.serialize(&mut buffer);
|
||||
wasm_module.serialize_mut(&mut buffer);
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,16 @@ pub enum StoredValue {
|
|||
size: u32,
|
||||
alignment_bytes: u32,
|
||||
},
|
||||
// TODO: const data storage (fixed address)
|
||||
}
|
||||
|
||||
impl StoredValue {
|
||||
pub fn value_type(&self) -> ValueType {
|
||||
match self {
|
||||
Self::VirtualMachineStack { value_type, .. } => *value_type,
|
||||
Self::Local { value_type, .. } => *value_type,
|
||||
Self::StackMemory { .. } => ValueType::I32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper structure for WasmBackend, to keep track of how values are stored,
|
||||
|
|
|
@ -350,11 +350,9 @@ impl<'a> CodeBuilder<'a> {
|
|||
self.set_global(STACK_POINTER_GLOBAL_ID);
|
||||
}
|
||||
|
||||
/// Finalize the function
|
||||
/// Generate all the "extra" bytes: local declarations, stack frame push/pop code, and function length
|
||||
/// After this, bytes will have been _generated_, but not yet _serialized_ into a single stream.
|
||||
/// Returns the final number of bytes the function will occupy in the target binary
|
||||
pub fn finalize(
|
||||
/// Build the function header: local declarations, stack frame push/pop code, and function length
|
||||
/// After this, all bytes have been generated (but not yet serialized) and we know the final size.
|
||||
pub fn build_fn_header(
|
||||
&mut self,
|
||||
local_types: &[ValueType],
|
||||
frame_size: i32,
|
||||
|
|
|
@ -174,6 +174,7 @@ impl<'a> Serialize for RelocationSection<'a> {
|
|||
*******************************************************************/
|
||||
|
||||
/// Linking metadata for data segments
|
||||
#[derive(Debug)]
|
||||
pub struct LinkingSegment {
|
||||
pub name: String,
|
||||
pub alignment: Align,
|
||||
|
@ -187,6 +188,7 @@ impl Serialize for LinkingSegment {
|
|||
}
|
||||
|
||||
/// Linking metadata for init (start) functions
|
||||
#[derive(Debug)]
|
||||
pub struct LinkingInitFunc {
|
||||
pub priority: u32,
|
||||
pub symbol_index: u32, // index in the symbol table, not the function index
|
||||
|
@ -213,6 +215,7 @@ pub enum ComdatSymKind {
|
|||
Section = 5,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ComdatSym {
|
||||
pub kind: ComdatSymKind,
|
||||
pub index: u32,
|
||||
|
@ -229,6 +232,7 @@ impl Serialize for ComdatSym {
|
|||
/// The linker will include all of these elements with a given group name from one object file,
|
||||
/// and will exclude any element with this group name from all other object files.
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub struct LinkingComdat<'a> {
|
||||
name: String,
|
||||
flags: u32,
|
||||
|
@ -413,6 +417,7 @@ impl Serialize for SymInfo {
|
|||
// Linking subsections
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LinkingSubSection<'a> {
|
||||
/// Extra metadata about the data segments.
|
||||
SegmentInfo(Vec<'a, LinkingSegment>),
|
||||
|
@ -454,6 +459,7 @@ impl<'a> Serialize for LinkingSubSection<'a> {
|
|||
|
||||
const LINKING_VERSION: u8 = 2;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LinkingSection<'a> {
|
||||
pub subsections: Vec<'a, LinkingSubSection<'a>>,
|
||||
}
|
||||
|
@ -464,6 +470,15 @@ impl<'a> LinkingSection<'a> {
|
|||
subsections: Vec::with_capacity_in(1, arena),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn symbol_table_mut(&mut self) -> &mut Vec<'a, SymInfo> {
|
||||
for sub in self.subsections.iter_mut() {
|
||||
if let LinkingSubSection::SymbolTable(syminfos) = sub {
|
||||
return syminfos;
|
||||
}
|
||||
}
|
||||
panic!("Symbol table not found");
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Serialize for LinkingSection<'a> {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
|
||||
use super::linking::{LinkingSection, RelocationEntry, RelocationSection};
|
||||
use super::linking::{
|
||||
IndexRelocType, LinkingSection, RelocationEntry, RelocationSection, SymInfo, WasmObjectSymbol,
|
||||
};
|
||||
use super::opcodes;
|
||||
use super::serialize::{SerialBuffer, Serialize};
|
||||
use super::{CodeBuilder, ValueType};
|
||||
|
@ -87,7 +89,7 @@ fn serialize_vector_section<B: SerialBuffer, T: Serialize>(
|
|||
*
|
||||
*******************************************************************/
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct Signature<'a> {
|
||||
pub param_types: Vec<'a, ValueType>,
|
||||
pub ret_type: Option<ValueType>,
|
||||
|
@ -101,6 +103,7 @@ impl<'a> Serialize for Signature<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TypeSection<'a> {
|
||||
/// Private. See WasmModule::add_function_signature
|
||||
signatures: Vec<'a, Signature<'a>>,
|
||||
|
@ -114,7 +117,7 @@ impl<'a> TypeSection<'a> {
|
|||
}
|
||||
|
||||
/// Find a matching signature or insert a new one. Return the index.
|
||||
fn insert(&mut self, signature: Signature<'a>) -> u32 {
|
||||
pub fn insert(&mut self, signature: Signature<'a>) -> u32 {
|
||||
// Using linear search because we need to preserve indices stored in
|
||||
// the Function section. (Also for practical sizes it's fast)
|
||||
let maybe_index = self.signatures.iter().position(|s| *s == signature);
|
||||
|
@ -148,6 +151,7 @@ pub enum RefType {
|
|||
Extern = 0x6f,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TableType {
|
||||
pub ref_type: RefType,
|
||||
pub limits: Limits,
|
||||
|
@ -160,6 +164,7 @@ impl Serialize for TableType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ImportDesc {
|
||||
Func { signature_index: u32 },
|
||||
Table { ty: TableType },
|
||||
|
@ -167,8 +172,9 @@ pub enum ImportDesc {
|
|||
Global { ty: GlobalType },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Import {
|
||||
pub module: String,
|
||||
pub module: &'static str,
|
||||
pub name: String,
|
||||
pub description: ImportDesc,
|
||||
}
|
||||
|
@ -198,8 +204,9 @@ impl Serialize for Import {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImportSection<'a> {
|
||||
entries: Vec<'a, Import>,
|
||||
pub entries: Vec<'a, Import>,
|
||||
}
|
||||
|
||||
impl<'a> ImportSection<'a> {
|
||||
|
@ -208,6 +215,13 @@ impl<'a> ImportSection<'a> {
|
|||
entries: bumpalo::vec![in arena],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn function_count(&self) -> usize {
|
||||
self.entries
|
||||
.iter()
|
||||
.filter(|import| matches!(import.description, ImportDesc::Func { .. }))
|
||||
.count()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Serialize for ImportSection<'a> {
|
||||
|
@ -223,6 +237,7 @@ impl<'a> Serialize for ImportSection<'a> {
|
|||
*
|
||||
*******************************************************************/
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionSection<'a> {
|
||||
/// Private. See WasmModule::add_function_signature
|
||||
signature_indices: Vec<'a, u32>,
|
||||
|
@ -247,6 +262,7 @@ impl<'a> Serialize for FunctionSection<'a> {
|
|||
*
|
||||
*******************************************************************/
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Limits {
|
||||
Min(u32),
|
||||
MinMax(u32, u32),
|
||||
|
@ -268,6 +284,7 @@ impl Serialize for Limits {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MemorySection(Option<Limits>);
|
||||
|
||||
impl MemorySection {
|
||||
|
@ -309,6 +326,7 @@ impl Serialize for MemorySection {
|
|||
*
|
||||
*******************************************************************/
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GlobalType {
|
||||
pub value_type: ValueType,
|
||||
pub is_mutable: bool,
|
||||
|
@ -323,6 +341,7 @@ impl Serialize for GlobalType {
|
|||
|
||||
/// Constant expression for initialising globals or data segments
|
||||
/// Note: This is restricted for simplicity, but the spec allows arbitrary constant expressions
|
||||
#[derive(Debug)]
|
||||
pub enum ConstExpr {
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
|
@ -354,6 +373,7 @@ impl Serialize for ConstExpr {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Global {
|
||||
/// Type and mutability of the global
|
||||
pub ty: GlobalType,
|
||||
|
@ -368,6 +388,7 @@ impl Serialize for Global {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GlobalSection<'a> {
|
||||
pub entries: Vec<'a, Global>,
|
||||
}
|
||||
|
@ -393,6 +414,7 @@ pub enum ExportType {
|
|||
Global = 3,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Export {
|
||||
pub name: String,
|
||||
pub ty: ExportType,
|
||||
|
@ -406,18 +428,11 @@ impl Serialize for Export {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExportSection<'a> {
|
||||
pub entries: Vec<'a, Export>,
|
||||
}
|
||||
|
||||
impl<'a> ExportSection<'a> {
|
||||
pub fn new(arena: &'a Bump) -> Self {
|
||||
ExportSection {
|
||||
entries: bumpalo::vec![in arena],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Serialize for ExportSection<'a> {
|
||||
fn serialize<T: SerialBuffer>(&self, buffer: &mut T) {
|
||||
serialize_vector_section(buffer, SectionId::Export, &self.entries);
|
||||
|
@ -436,18 +451,12 @@ pub struct CodeSection<'a> {
|
|||
}
|
||||
|
||||
impl<'a> CodeSection<'a> {
|
||||
pub fn new(arena: &'a Bump) -> Self {
|
||||
CodeSection {
|
||||
code_builders: Vec::with_capacity_in(8, arena),
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize the code builders for all functions, and get code relocations with final offsets
|
||||
pub fn serialize_with_relocs<T: SerialBuffer>(
|
||||
&self,
|
||||
buffer: &mut T,
|
||||
relocations: &mut Vec<'a, RelocationEntry>,
|
||||
) {
|
||||
) -> usize {
|
||||
let header_indices = write_section_header(buffer, SectionId::Code);
|
||||
buffer.encode_u32(self.code_builders.len() as u32);
|
||||
|
||||
|
@ -455,7 +464,9 @@ impl<'a> CodeSection<'a> {
|
|||
code_builder.serialize_with_relocs(buffer, relocations, header_indices.body_index);
|
||||
}
|
||||
|
||||
let code_section_body_index = header_indices.body_index;
|
||||
update_section_size(buffer, header_indices);
|
||||
code_section_body_index
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -465,6 +476,7 @@ impl<'a> CodeSection<'a> {
|
|||
*
|
||||
*******************************************************************/
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DataMode {
|
||||
/// A data segment that auto-loads into memory on instantiation
|
||||
Active { offset: ConstExpr },
|
||||
|
@ -472,6 +484,7 @@ pub enum DataMode {
|
|||
Passive,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DataSegment<'a> {
|
||||
pub mode: DataMode,
|
||||
pub init: Vec<'a, u8>,
|
||||
|
@ -493,6 +506,7 @@ impl Serialize for DataSegment<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DataSection<'a> {
|
||||
pub segments: Vec<'a, DataSegment<'a>>,
|
||||
}
|
||||
|
@ -521,6 +535,7 @@ impl Serialize for DataSection<'_> {
|
|||
*
|
||||
*******************************************************************/
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DataCountSection {
|
||||
count: u32,
|
||||
}
|
||||
|
@ -583,6 +598,7 @@ impl SectionCounter {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WasmModule<'a> {
|
||||
pub types: TypeSection<'a>,
|
||||
pub import: ImportSection<'a>,
|
||||
|
@ -611,8 +627,10 @@ impl<'a> WasmModule<'a> {
|
|||
self.function.signature_indices.push(index);
|
||||
}
|
||||
|
||||
/// Serialize the module to bytes
|
||||
/// (Mutates some data related to linking)
|
||||
#[allow(clippy::unit_arg)]
|
||||
pub fn serialize<T: SerialBuffer>(&mut self, buffer: &mut T) {
|
||||
pub fn serialize_mut<T: SerialBuffer>(&mut self, buffer: &mut T) {
|
||||
buffer.append_u8(0);
|
||||
buffer.append_slice("asm".as_bytes());
|
||||
buffer.write_unencoded_u32(Self::WASM_VERSION);
|
||||
|
@ -623,6 +641,13 @@ impl<'a> WasmModule<'a> {
|
|||
section_index: 0,
|
||||
};
|
||||
|
||||
// If we have imports, then references to other functions need to be re-indexed.
|
||||
// Modify exports before serializing them, since we don't have linker data for them
|
||||
let n_imported_fns = self.import.function_count() as u32;
|
||||
if n_imported_fns > 0 {
|
||||
self.finalize_exported_fn_indices(n_imported_fns);
|
||||
}
|
||||
|
||||
counter.serialize_and_count(buffer, &self.types);
|
||||
counter.serialize_and_count(buffer, &self.import);
|
||||
counter.serialize_and_count(buffer, &self.function);
|
||||
|
@ -640,9 +665,16 @@ impl<'a> WasmModule<'a> {
|
|||
|
||||
// Code section is the only one with relocations so we can stop counting
|
||||
let code_section_index = counter.section_index;
|
||||
self.code
|
||||
let code_section_body_index = self
|
||||
.code
|
||||
.serialize_with_relocs(buffer, &mut self.relocations.entries);
|
||||
|
||||
// If we have imports, references to other functions need to be re-indexed.
|
||||
// Simplest to do after serialization, using linker data
|
||||
if n_imported_fns > 0 {
|
||||
self.finalize_code_fn_indices(buffer, code_section_body_index, n_imported_fns);
|
||||
}
|
||||
|
||||
self.data.serialize(buffer);
|
||||
|
||||
self.linking.serialize(buffer);
|
||||
|
@ -650,4 +682,52 @@ impl<'a> WasmModule<'a> {
|
|||
self.relocations.target_section_index = Some(code_section_index);
|
||||
self.relocations.serialize(buffer);
|
||||
}
|
||||
|
||||
/// Shift indices of exported functions to make room for imported functions,
|
||||
/// which come first in the function index space.
|
||||
/// Must be called after traversing the full IR, but before export section is serialized.
|
||||
fn finalize_exported_fn_indices(&mut self, n_imported_fns: u32) {
|
||||
for export in self.export.entries.iter_mut() {
|
||||
if export.ty == ExportType::Func {
|
||||
export.index += n_imported_fns;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-index internally-defined functions to make room for imported functions.
|
||||
/// We do this after serialization, when all buffers in all CodeBuilders have been combined.
|
||||
/// That makes the code simpler and avoids spreading it across multiple impl's and files.
|
||||
fn finalize_code_fn_indices<T: SerialBuffer>(
|
||||
&mut self,
|
||||
buffer: &mut T,
|
||||
code_section_body_index: usize,
|
||||
n_imported_fns: u32,
|
||||
) {
|
||||
// Modify symbol table entries
|
||||
let symbol_table = self.linking.symbol_table_mut();
|
||||
let mut target_symbol_indices = std::vec::Vec::with_capacity(symbol_table.len());
|
||||
for (i, sym_info) in symbol_table.iter_mut().enumerate() {
|
||||
if let SymInfo::Function(WasmObjectSymbol::Defined { index, .. }) = sym_info {
|
||||
target_symbol_indices.push(i as u32);
|
||||
*index += n_imported_fns;
|
||||
}
|
||||
}
|
||||
|
||||
// Modify call instructions, using linker data
|
||||
for reloc in &self.relocations.entries {
|
||||
if let RelocationEntry::Index {
|
||||
type_id: IndexRelocType::FunctionIndexLeb,
|
||||
offset,
|
||||
symbol_index,
|
||||
} = reloc
|
||||
{
|
||||
if target_symbol_indices.contains(symbol_index) {
|
||||
let orig_fn_index = *symbol_index; // trick: we know these were the first symbols we created
|
||||
let new_fn_index = orig_fn_index + n_imported_fns;
|
||||
let buffer_index = code_section_body_index + (*offset as usize);
|
||||
buffer.overwrite_padded_u32(buffer_index, new_fn_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,10 +44,12 @@ pub enum LowLevel {
|
|||
ListKeepErrs,
|
||||
ListSortWith,
|
||||
ListTakeFirst,
|
||||
ListTakeLast,
|
||||
ListDrop,
|
||||
ListDropAt,
|
||||
ListSwap,
|
||||
ListAny,
|
||||
ListFindUnsafe,
|
||||
DictSize,
|
||||
DictEmpty,
|
||||
DictInsert,
|
||||
|
@ -135,6 +137,7 @@ macro_rules! first_order {
|
|||
| ListGetUnsafe
|
||||
| ListSet
|
||||
| ListTakeFirst
|
||||
| ListTakeLast
|
||||
| ListDrop
|
||||
| ListDropAt
|
||||
| ListSingle
|
||||
|
@ -227,6 +230,7 @@ macro_rules! higher_order {
|
|||
| ListKeepErrs
|
||||
| ListSortWith
|
||||
| ListAny
|
||||
| ListFindUnsafe
|
||||
| DictWalk
|
||||
};
|
||||
}
|
||||
|
@ -261,6 +265,7 @@ impl LowLevel {
|
|||
ListKeepErrs => 1,
|
||||
ListSortWith => 1,
|
||||
ListAny => 1,
|
||||
ListFindUnsafe => 1,
|
||||
DictWalk => 2,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1067,6 +1067,9 @@ define_builtins! {
|
|||
43 LIST_JOIN_MAP_CONCAT: "#joinMapConcat"
|
||||
44 LIST_ANY: "any"
|
||||
45 LIST_TAKE_FIRST: "takeFirst"
|
||||
46 LIST_TAKE_LAST: "takeLast"
|
||||
47 LIST_FIND: "find"
|
||||
48 LIST_FIND_RESULT: "#find_result" // symbol used in the definition of List.find
|
||||
}
|
||||
5 RESULT: "Result" => {
|
||||
0 RESULT_RESULT: "Result" imported // the Result.Result type alias
|
||||
|
|
|
@ -1093,6 +1093,41 @@ fn call_spec(
|
|||
|
||||
add_loop(builder, block, state_type, init_state, loop_body)
|
||||
}
|
||||
ListFindUnsafe { xs } => {
|
||||
let list = env.symbols[xs];
|
||||
|
||||
// ListFindUnsafe returns { value: v, found: Bool=Int1 }
|
||||
let output_layouts = vec![arg_layouts[0], Layout::Builtin(Builtin::Int1)];
|
||||
let output_layout = Layout::Struct(&output_layouts);
|
||||
let output_type = layout_spec(builder, &output_layout)?;
|
||||
|
||||
let loop_body = |builder: &mut FuncDefBuilder, block, output| {
|
||||
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
||||
let element = builder.add_bag_get(block, bag)?;
|
||||
let _is_found = call_function!(builder, block, [element]);
|
||||
|
||||
// We may or may not use the element we got from the list in the output struct,
|
||||
// depending on whether we found the element to satisfy the "find" predicate.
|
||||
// If we did find the element, our output "changes" to be a record including that element.
|
||||
let found_branch = builder.add_block();
|
||||
let new_output =
|
||||
builder.add_unknown_with(block, &[element], output_type)?;
|
||||
|
||||
let not_found_branch = builder.add_block();
|
||||
|
||||
builder.add_choice(
|
||||
block,
|
||||
&[
|
||||
BlockExpr(found_branch, new_output),
|
||||
BlockExpr(not_found_branch, output),
|
||||
],
|
||||
)
|
||||
};
|
||||
|
||||
// Assume the output is initially { found: False, value: \empty }
|
||||
let output_state = builder.add_unknown_with(block, &[], output_type)?;
|
||||
add_loop(builder, block, output_type, output_state, loop_body)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -618,7 +618,8 @@ impl<'a> BorrowInfState<'a> {
|
|||
| ListKeepIf { xs }
|
||||
| ListKeepOks { xs }
|
||||
| ListKeepErrs { xs }
|
||||
| ListAny { xs } => {
|
||||
| ListAny { xs }
|
||||
| ListFindUnsafe { xs } => {
|
||||
// own the list if the function wants to own the element
|
||||
if !function_ps[0].borrow {
|
||||
self.own_var(*xs);
|
||||
|
@ -960,11 +961,13 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
|
|||
arena.alloc_slice_copy(&[owned, owned, function, closure_data])
|
||||
}
|
||||
ListSortWith => arena.alloc_slice_copy(&[owned, function, closure_data]),
|
||||
ListFindUnsafe => arena.alloc_slice_copy(&[owned, function, closure_data]),
|
||||
|
||||
// TODO when we have lists with capacity (if ever)
|
||||
// List.append should own its first argument
|
||||
ListAppend => arena.alloc_slice_copy(&[owned, owned]),
|
||||
ListTakeFirst => arena.alloc_slice_copy(&[owned, irrelevant]),
|
||||
ListTakeLast => arena.alloc_slice_copy(&[owned, irrelevant]),
|
||||
ListDrop => arena.alloc_slice_copy(&[owned, irrelevant]),
|
||||
ListDropAt => arena.alloc_slice_copy(&[owned, irrelevant]),
|
||||
ListSwap => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
|
||||
|
|
|
@ -531,7 +531,8 @@ impl<'a> Context<'a> {
|
|||
| ListKeepIf { xs }
|
||||
| ListKeepOks { xs }
|
||||
| ListKeepErrs { xs }
|
||||
| ListAny { xs } => {
|
||||
| ListAny { xs }
|
||||
| ListFindUnsafe { xs } => {
|
||||
let borrows = [function_ps[0].borrow, FUNCTION, CLOSURE_DATA];
|
||||
|
||||
let b = self.add_dec_after_lowlevel(arguments, &borrows, b, b_live_vars);
|
||||
|
|
|
@ -4164,6 +4164,11 @@ pub fn with_hole<'a>(
|
|||
|
||||
match_on_closure_argument!(ListMap4, [xs, ys, zs, ws])
|
||||
}
|
||||
ListFindUnsafe => {
|
||||
debug_assert_eq!(arg_symbols.len(), 2);
|
||||
let xs = arg_symbols[0];
|
||||
match_on_closure_argument!(ListFindUnsafe, [xs])
|
||||
}
|
||||
_ => {
|
||||
let call = self::Call {
|
||||
call_type: CallType::LowLevel {
|
||||
|
|
|
@ -50,6 +50,9 @@ pub enum HigherOrder {
|
|||
ListAny {
|
||||
xs: Symbol,
|
||||
},
|
||||
ListFindUnsafe {
|
||||
xs: Symbol,
|
||||
},
|
||||
DictWalk {
|
||||
xs: Symbol,
|
||||
state: Symbol,
|
||||
|
@ -71,6 +74,7 @@ impl HigherOrder {
|
|||
HigherOrder::ListKeepOks { .. } => 1,
|
||||
HigherOrder::ListKeepErrs { .. } => 1,
|
||||
HigherOrder::ListSortWith { .. } => 2,
|
||||
HigherOrder::ListFindUnsafe { .. } => 1,
|
||||
HigherOrder::DictWalk { .. } => 2,
|
||||
HigherOrder::ListAny { .. } => 1,
|
||||
}
|
||||
|
@ -97,6 +101,7 @@ enum FirstOrder {
|
|||
ListGetUnsafe,
|
||||
ListSet,
|
||||
ListTakeFirst,
|
||||
ListTakeLast,
|
||||
ListDrop,
|
||||
ListDropAt,
|
||||
ListSingle,
|
||||
|
|
|
@ -3769,6 +3769,18 @@ mod solve_expr {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_take_last() {
|
||||
infer_eq_without_problem(
|
||||
indoc!(
|
||||
r#"
|
||||
List.takeLast
|
||||
"#
|
||||
),
|
||||
"List a, Nat -> List a",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_drop_last() {
|
||||
infer_eq_without_problem(
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
[package]
|
||||
name = "test_dev"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[[test]]
|
||||
name = "test_dev"
|
||||
path = "src/tests.rs"
|
||||
|
||||
[dev-dependencies]
|
||||
roc_collections = { path = "../collections" }
|
||||
roc_can = { path = "../can" }
|
||||
roc_build = { path = "../build" }
|
||||
roc_parse = { path = "../parse" }
|
||||
roc_reporting = { path = "../reporting" }
|
||||
roc_load = { path = "../load" }
|
||||
roc_constrain = { path = "../constrain" }
|
||||
roc_std = { path = "../../roc_std" }
|
||||
roc_gen_dev = { path = "../gen_dev" }
|
||||
roc_mono = { path = "../mono" }
|
||||
roc_problem = { path = "../problem" }
|
||||
roc_builtins = { path = "../builtins" }
|
||||
indoc = "1.0.3"
|
||||
bumpalo = { version = "3.8.0", features = ["collections"] }
|
||||
tempfile = "3.2.0"
|
||||
libloading = "0.7.1"
|
||||
target-lexicon = "0.12.2"
|
|
@ -1,871 +0,0 @@
|
|||
#![cfg(all(test, any(target_os = "linux", target_os = "macos"), any(target_arch = "x86_64"/*, target_arch = "aarch64"*/)))]
|
||||
|
||||
use crate::assert_evals_to;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
fn i64_values() {
|
||||
assert_evals_to!("0", 0, i64);
|
||||
assert_evals_to!("-0", 0, i64);
|
||||
assert_evals_to!("-1", -1, i64);
|
||||
assert_evals_to!("1", 1, i64);
|
||||
assert_evals_to!("9_000_000_000_000", 9_000_000_000_000, i64);
|
||||
assert_evals_to!("-9_000_000_000_000", -9_000_000_000_000, i64);
|
||||
assert_evals_to!("0b1010", 0b1010, i64);
|
||||
assert_evals_to!("0o17", 0o17, i64);
|
||||
assert_evals_to!("0x1000_0000_0000_0000", 0x1000_0000_0000_0000, i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_values() {
|
||||
assert_evals_to!("0.0", 0.0, f64);
|
||||
assert_evals_to!("-0.0", 0.0, f64);
|
||||
assert_evals_to!("1.0", 1.0, f64);
|
||||
assert_evals_to!("-1.0", -1.0, f64);
|
||||
assert_evals_to!("3.1415926535897932", 3.141_592_653_589_793, f64);
|
||||
assert_evals_to!(&format!("{:0.1}", f64::MIN), f64::MIN, f64);
|
||||
assert_evals_to!(&format!("{:0.1}", f64::MAX), f64::MAX, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_add_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
1 + 2 + 3
|
||||
"#
|
||||
),
|
||||
6,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_add_f64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
1.1 + 2.4 + 3
|
||||
"#
|
||||
),
|
||||
6.5,
|
||||
f64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_sub_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
1 - 2 - 3
|
||||
"#
|
||||
),
|
||||
-4,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_mul_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
2 * 4 * 6
|
||||
"#
|
||||
),
|
||||
48,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn i64_force_stack() {
|
||||
// This claims 33 registers. One more than Arm and RISC-V, and many more than x86-64.
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
a = 0
|
||||
b = 1
|
||||
c = 2
|
||||
d = 3
|
||||
e = 4
|
||||
f = 5
|
||||
g = 6
|
||||
h = 7
|
||||
i = 8
|
||||
j = 9
|
||||
k = 10
|
||||
l = 11
|
||||
m = 12
|
||||
n = 13
|
||||
o = 14
|
||||
p = 15
|
||||
q = 16
|
||||
r = 17
|
||||
s = 18
|
||||
t = 19
|
||||
u = 20
|
||||
v = 21
|
||||
w = 22
|
||||
x = 23
|
||||
y = 24
|
||||
z = 25
|
||||
aa = 26
|
||||
ab = 27
|
||||
ac = 28
|
||||
ad = 29
|
||||
ae = 30
|
||||
af = 31
|
||||
ag = 32
|
||||
|
||||
a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t + u + v + w + x + y + z + aa + ab + ac + ad + ae + af + ag
|
||||
"#
|
||||
),
|
||||
528,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn i64_abs() {
|
||||
assert_evals_to!("Num.abs -6", 6, i64);
|
||||
assert_evals_to!("Num.abs 7", 7, i64);
|
||||
assert_evals_to!("Num.abs 0", 0, i64);
|
||||
assert_evals_to!("Num.abs -0", 0, i64);
|
||||
assert_evals_to!("Num.abs -1", 1, i64);
|
||||
assert_evals_to!("Num.abs 1", 1, i64);
|
||||
assert_evals_to!("Num.abs 9_000_000_000_000", 9_000_000_000_000, i64);
|
||||
assert_evals_to!("Num.abs -9_000_000_000_000", 9_000_000_000_000, i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_int_eq() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
4 == 4
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
3 == 4
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_basic_fn() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
always42 : Num.Num (Num.Integer Num.Signed64) -> Num.Num (Num.Integer Num.Signed64)
|
||||
always42 = \_ -> 42
|
||||
|
||||
always42 5
|
||||
"#
|
||||
),
|
||||
42,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_wrap_add_nums() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
add2 = \num1, num2 -> num1 + num2
|
||||
|
||||
add2 4 5
|
||||
"#
|
||||
),
|
||||
9,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_wrap_add_nums_force_stack() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
add9 = \num1, num2, num3, num4, num5, num6, num7, num8, num9 -> num1 + num2 + num3 + num4 + num5 + num6 + num7 + num8 + num9
|
||||
|
||||
add9 1 2 3 4 5 6 7 8 9
|
||||
"#
|
||||
),
|
||||
45,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pow_int() {
|
||||
assert_evals_to!("Num.powInt 2 3", 8, i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acos() {
|
||||
assert_evals_to!("Num.acos 0.5", 1.0471975511965979, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn asin() {
|
||||
assert_evals_to!("Num.asin 0.5", 0.5235987755982989, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn atan() {
|
||||
assert_evals_to!("Num.atan 10", 1.4711276743037347, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_if_fn() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
limitedNegate = \num ->
|
||||
x =
|
||||
if num == 1 then
|
||||
-1
|
||||
else if num == -1 then
|
||||
1
|
||||
else
|
||||
num
|
||||
x
|
||||
|
||||
limitedNegate 1
|
||||
"#
|
||||
),
|
||||
-1,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_fib_fn() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
fib = \n ->
|
||||
if n == 0 then
|
||||
0
|
||||
else if n == 1 then
|
||||
1
|
||||
else
|
||||
(fib (n - 1)) + (fib (n - 2))
|
||||
|
||||
fib 10
|
||||
"#
|
||||
),
|
||||
55,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_fast_fib_fn() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
fib = \n, a, b ->
|
||||
if n == 0 then
|
||||
a
|
||||
else
|
||||
fib (n - 1) b (a + b)
|
||||
fib 10 0 1
|
||||
"#
|
||||
),
|
||||
55,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_abs() {
|
||||
assert_evals_to!("Num.abs -4.7", 4.7, f64);
|
||||
assert_evals_to!("Num.abs 5.8", 5.8, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_round() {
|
||||
assert_evals_to!("Num.round 3.6", 4, i64);
|
||||
assert_evals_to!("Num.round 3.4", 3, i64);
|
||||
assert_evals_to!("Num.round 2.5", 3, i64);
|
||||
assert_evals_to!("Num.round -2.3", -2, i64);
|
||||
assert_evals_to!("Num.round -2.5", -3, i64);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn f64_sqrt() {
|
||||
// // FIXME this works with normal types, but fails when checking uniqueness types
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Num.sqrt 100 is
|
||||
// Ok val -> val
|
||||
// Err _ -> -1
|
||||
// "#
|
||||
// ),
|
||||
// 10.0,
|
||||
// f64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_float_eq() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// 1.0 == 1.0
|
||||
// "#
|
||||
// ),
|
||||
// true,
|
||||
// bool
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_div_f64() {
|
||||
// // FIXME this works with normal types, but fails when checking uniqueness types
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when 48 / 2 is
|
||||
// Ok val -> val
|
||||
// Err _ -> -1
|
||||
// "#
|
||||
// ),
|
||||
// 24.0,
|
||||
// f64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_int_neq() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// 4 != 5
|
||||
// "#
|
||||
// ),
|
||||
// true,
|
||||
// bool
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_wrap_int_neq() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// wrappedNotEq : a, a -> Bool
|
||||
// wrappedNotEq = \num1, num2 ->
|
||||
// num1 != num2
|
||||
|
||||
// wrappedNotEq 2 3
|
||||
// "#
|
||||
// ),
|
||||
// true,
|
||||
// bool
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_sub_f64() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// 1.5 - 2.4 - 3
|
||||
// "#
|
||||
// ),
|
||||
// -3.9,
|
||||
// f64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_div_i64() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when 1000 // 10 is
|
||||
// Ok val -> val
|
||||
// Err _ -> -1
|
||||
// "#
|
||||
// ),
|
||||
// 100,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_div_by_zero_i64() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when 1000 // 0 is
|
||||
// Err DivByZero -> 99
|
||||
// _ -> -24
|
||||
// "#
|
||||
// ),
|
||||
// 99,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_rem_i64() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Num.rem 8 3 is
|
||||
// Ok val -> val
|
||||
// Err _ -> -1
|
||||
// "#
|
||||
// ),
|
||||
// 2,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_rem_div_by_zero_i64() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Num.rem 8 0 is
|
||||
// Err DivByZero -> 4
|
||||
// Ok _ -> -23
|
||||
// "#
|
||||
// ),
|
||||
// 4,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_is_zero_i64() {
|
||||
// assert_evals_to!("Num.isZero 0", true, bool);
|
||||
// assert_evals_to!("Num.isZero 1", false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_is_positive_i64() {
|
||||
// assert_evals_to!("Num.isPositive 0", false, bool);
|
||||
// assert_evals_to!("Num.isPositive 1", true, bool);
|
||||
// assert_evals_to!("Num.isPositive -5", false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_is_negative_i64() {
|
||||
// assert_evals_to!("Num.isNegative 0", false, bool);
|
||||
// assert_evals_to!("Num.isNegative 3", false, bool);
|
||||
// assert_evals_to!("Num.isNegative -2", true, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_is_positive_f64() {
|
||||
// assert_evals_to!("Num.isPositive 0.0", false, bool);
|
||||
// assert_evals_to!("Num.isPositive 4.7", true, bool);
|
||||
// assert_evals_to!("Num.isPositive -8.5", false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_is_negative_f64() {
|
||||
// assert_evals_to!("Num.isNegative 0.0", false, bool);
|
||||
// assert_evals_to!("Num.isNegative 9.9", false, bool);
|
||||
// assert_evals_to!("Num.isNegative -4.4", true, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_is_zero_f64() {
|
||||
// assert_evals_to!("Num.isZero 0", true, bool);
|
||||
// assert_evals_to!("Num.isZero 0_0", true, bool);
|
||||
// assert_evals_to!("Num.isZero 0.0", true, bool);
|
||||
// assert_evals_to!("Num.isZero 1", false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_is_odd() {
|
||||
// assert_evals_to!("Num.isOdd 4", false, bool);
|
||||
// assert_evals_to!("Num.isOdd 5", true, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_is_even() {
|
||||
// assert_evals_to!("Num.isEven 6", true, bool);
|
||||
// assert_evals_to!("Num.isEven 7", false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn sin() {
|
||||
// assert_evals_to!("Num.sin 0", 0.0, f64);
|
||||
// assert_evals_to!("Num.sin 1.41421356237", 0.9877659459922529, f64);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn cos() {
|
||||
// assert_evals_to!("Num.cos 0", 1.0, f64);
|
||||
// assert_evals_to!("Num.cos 3.14159265359", -1.0, f64);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn tan() {
|
||||
// assert_evals_to!("Num.tan 0", 0.0, f64);
|
||||
// assert_evals_to!("Num.tan 1", 1.557407724654902, f64);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn lt_i64() {
|
||||
// assert_evals_to!("1 < 2", true, bool);
|
||||
// assert_evals_to!("1 < 1", false, bool);
|
||||
// assert_evals_to!("2 < 1", false, bool);
|
||||
// assert_evals_to!("0 < 0", false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn lte_i64() {
|
||||
// assert_evals_to!("1 <= 1", true, bool);
|
||||
// assert_evals_to!("2 <= 1", false, bool);
|
||||
// assert_evals_to!("1 <= 2", true, bool);
|
||||
// assert_evals_to!("0 <= 0", true, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gt_i64() {
|
||||
// assert_evals_to!("2 > 1", true, bool);
|
||||
// assert_evals_to!("2 > 2", false, bool);
|
||||
// assert_evals_to!("1 > 1", false, bool);
|
||||
// assert_evals_to!("0 > 0", false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gte_i64() {
|
||||
// assert_evals_to!("1 >= 1", true, bool);
|
||||
// assert_evals_to!("1 >= 2", false, bool);
|
||||
// assert_evals_to!("2 >= 1", true, bool);
|
||||
// assert_evals_to!("0 >= 0", true, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn lt_f64() {
|
||||
// assert_evals_to!("1.1 < 1.2", true, bool);
|
||||
// assert_evals_to!("1.1 < 1.1", false, bool);
|
||||
// assert_evals_to!("1.2 < 1.1", false, bool);
|
||||
// assert_evals_to!("0.0 < 0.0", false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn lte_f64() {
|
||||
// assert_evals_to!("1.1 <= 1.1", true, bool);
|
||||
// assert_evals_to!("1.2 <= 1.1", false, bool);
|
||||
// assert_evals_to!("1.1 <= 1.2", true, bool);
|
||||
// assert_evals_to!("0.0 <= 0.0", true, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gt_f64() {
|
||||
// assert_evals_to!("2.2 > 1.1", true, bool);
|
||||
// assert_evals_to!("2.2 > 2.2", false, bool);
|
||||
// assert_evals_to!("1.1 > 2.2", false, bool);
|
||||
// assert_evals_to!("0.0 > 0.0", false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gte_f64() {
|
||||
// assert_evals_to!("1.1 >= 1.1", true, bool);
|
||||
// assert_evals_to!("1.1 >= 1.2", false, bool);
|
||||
// assert_evals_to!("1.2 >= 1.1", true, bool);
|
||||
// assert_evals_to!("0.0 >= 0.0", true, bool);
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn gen_order_of_arithmetic_ops() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
1 + 3 * 7 - 2
|
||||
"#
|
||||
),
|
||||
20,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn gen_order_of_arithmetic_ops_complex_float() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// 3 - 48 * 2.0
|
||||
// "#
|
||||
// ),
|
||||
// -93.0,
|
||||
// f64
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn if_guard_bind_variable_false() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
wrapper = \{} ->
|
||||
when 10 is
|
||||
x if x == 5 -> 0
|
||||
_ -> 42
|
||||
|
||||
wrapper {}
|
||||
"#
|
||||
),
|
||||
42,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn if_guard_bind_variable_true() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
wrapper = \{} ->
|
||||
when 10 is
|
||||
x if x == 10 -> 42
|
||||
_ -> 0
|
||||
|
||||
wrapper {}
|
||||
"#
|
||||
),
|
||||
42,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tail_call_elimination() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
sum = \n, accum ->
|
||||
when n is
|
||||
0 -> accum
|
||||
_ -> sum (n - 1) (n + accum)
|
||||
|
||||
sum 1_000_000 0
|
||||
"#
|
||||
),
|
||||
500000500000,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn int_negate() {
|
||||
// assert_evals_to!("Num.neg 123", -123, i64);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn gen_wrap_int_neg() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// wrappedNeg = \num -> -num
|
||||
|
||||
// wrappedNeg 3
|
||||
// "#
|
||||
// ),
|
||||
// -3,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn int_to_float() {
|
||||
// assert_evals_to!("Num.toFloat 0x9", 9.0, f64);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn num_to_float() {
|
||||
// assert_evals_to!("Num.toFloat 9", 9.0, f64);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn float_to_float() {
|
||||
// assert_evals_to!("Num.toFloat 0.5", 0.5, f64);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn int_compare() {
|
||||
// assert_evals_to!("Num.compare 0 1", RocOrder::Lt, RocOrder);
|
||||
// assert_evals_to!("Num.compare 1 1", RocOrder::Eq, RocOrder);
|
||||
// assert_evals_to!("Num.compare 1 0", RocOrder::Gt, RocOrder);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn float_compare() {
|
||||
// assert_evals_to!("Num.compare 0.01 3.14", RocOrder::Lt, RocOrder);
|
||||
// assert_evals_to!("Num.compare 3.14 3.14", RocOrder::Eq, RocOrder);
|
||||
// assert_evals_to!("Num.compare 3.14 0.01", RocOrder::Gt, RocOrder);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn pow() {
|
||||
// assert_evals_to!("Num.pow 2.0 2.0", 4.0, f64);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn ceiling() {
|
||||
// assert_evals_to!("Num.ceiling 1.1", 2, i64);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn floor() {
|
||||
// assert_evals_to!("Num.floor 1.9", 1, i64);
|
||||
// }
|
||||
|
||||
// // #[test]
|
||||
// // #[should_panic(expected = r#"Roc failed with message: "integer addition overflowed!"#)]
|
||||
// // fn int_overflow() {
|
||||
// // assert_evals_to!(
|
||||
// // indoc!(
|
||||
// // r#"
|
||||
// // 9_223_372_036_854_775_807 + 1
|
||||
// // "#
|
||||
// // ),
|
||||
// // 0,
|
||||
// // i64
|
||||
// // );
|
||||
// // }
|
||||
|
||||
// #[test]
|
||||
// fn int_add_checked() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Num.addChecked 1 2 is
|
||||
// Ok v -> v
|
||||
// _ -> -1
|
||||
// "#
|
||||
// ),
|
||||
// 3,
|
||||
// i64
|
||||
// );
|
||||
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Num.addChecked 9_223_372_036_854_775_807 1 is
|
||||
// Err Overflow -> -1
|
||||
// Ok v -> v
|
||||
// "#
|
||||
// ),
|
||||
// -1,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn int_add_wrap() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Num.addWrap 9_223_372_036_854_775_807 1
|
||||
// "#
|
||||
// ),
|
||||
// std::i64::MIN,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn float_add_checked_pass() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Num.addChecked 1.0 0.0 is
|
||||
// Ok v -> v
|
||||
// Err Overflow -> -1.0
|
||||
// "#
|
||||
// ),
|
||||
// 1.0,
|
||||
// f64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn float_add_checked_fail() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Num.addChecked 1.7976931348623157e308 1.7976931348623157e308 is
|
||||
// Err Overflow -> -1
|
||||
// Ok v -> v
|
||||
// "#
|
||||
// ),
|
||||
// -1.0,
|
||||
// f64
|
||||
// );
|
||||
// }
|
||||
|
||||
// // #[test]
|
||||
// // #[should_panic(expected = r#"Roc failed with message: "float addition overflowed!"#)]
|
||||
// // fn float_overflow() {
|
||||
// // assert_evals_to!(
|
||||
// // indoc!(
|
||||
// // r#"
|
||||
// // 1.7976931348623157e308 + 1.7976931348623157e308
|
||||
// // "#
|
||||
// // ),
|
||||
// // 0.0,
|
||||
// // f64
|
||||
// // );
|
||||
// // }
|
||||
|
||||
// #[test]
|
||||
// fn max_i128() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Num.maxI128
|
||||
// "#
|
||||
// ),
|
||||
// i128::MAX,
|
||||
// i128
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn num_max_int() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Num.maxInt
|
||||
// "#
|
||||
// ),
|
||||
// i64::MAX,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn num_min_int() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Num.minInt
|
||||
// "#
|
||||
// ),
|
||||
// i64::MIN,
|
||||
// i64
|
||||
// );
|
||||
// }
|
|
@ -1,933 +0,0 @@
|
|||
#![cfg(all(test, any(target_os = "linux", target_os = "macos"), any(target_arch = "x86_64"/*, target_arch = "aarch64"*/)))]
|
||||
|
||||
use crate::assert_evals_to;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
fn basic_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ y: 17, x: 15, z: 19 }.x
|
||||
"#
|
||||
),
|
||||
15,
|
||||
i64
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 15, y: 17, z: 19 }.y
|
||||
"#
|
||||
),
|
||||
17,
|
||||
i64
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 15, y: 17, z: 19 }.z
|
||||
"#
|
||||
),
|
||||
19,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.x
|
||||
"#
|
||||
),
|
||||
15,
|
||||
i64
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.y.a
|
||||
"#
|
||||
),
|
||||
12,
|
||||
i64
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.y.b
|
||||
"#
|
||||
),
|
||||
15,
|
||||
i64
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.y.c
|
||||
"#
|
||||
),
|
||||
2,
|
||||
i64
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.z
|
||||
"#
|
||||
),
|
||||
19,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
rec = { y: 17.2, x: 15.1, z: 19.3 }
|
||||
|
||||
rec.x
|
||||
"#
|
||||
),
|
||||
15.1,
|
||||
f64
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
rec = { y: 17.2, x: 15.1, z: 19.3 }
|
||||
|
||||
rec.y
|
||||
"#
|
||||
),
|
||||
17.2,
|
||||
f64
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
rec = { y: 17.2, x: 15.1, z: 19.3 }
|
||||
|
||||
rec.z
|
||||
"#
|
||||
),
|
||||
19.3,
|
||||
f64
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn fn_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// getRec = \x -> { y: 17, x, z: 19 }
|
||||
|
||||
// (getRec 15).x
|
||||
// "#
|
||||
// ),
|
||||
// 15,
|
||||
// i64
|
||||
// );
|
||||
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { x: 15, y: 17, z: 19 }
|
||||
|
||||
// rec.y
|
||||
// "#
|
||||
// ),
|
||||
// 17,
|
||||
// i64
|
||||
// );
|
||||
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { x: 15, y: 17, z: 19 }
|
||||
|
||||
// rec.z
|
||||
// "#
|
||||
// ),
|
||||
// 19,
|
||||
// i64
|
||||
// );
|
||||
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { x: 15, y: 17, z: 19 }
|
||||
|
||||
// rec.z + rec.x
|
||||
// "#
|
||||
// ),
|
||||
// 34,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn def_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
rec = { y: 17, x: 15, z: 19 }
|
||||
|
||||
rec.x
|
||||
"#
|
||||
),
|
||||
15,
|
||||
i64
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
rec = { x: 15, y: 17, z: 19 }
|
||||
|
||||
rec.y
|
||||
"#
|
||||
),
|
||||
17,
|
||||
i64
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
rec = { x: 15, y: 17, z: 19 }
|
||||
|
||||
rec.z
|
||||
"#
|
||||
),
|
||||
19,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn when_on_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when { x: 0x2 } is
|
||||
{ x } -> x + 3
|
||||
"#
|
||||
),
|
||||
5,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn when_record_with_guard_pattern() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when { x: 0x2, y: 3.14 } is
|
||||
{ x: var } -> var + 3
|
||||
"#
|
||||
),
|
||||
5,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn let_with_record_pattern() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x } = { x: 0x2, y: 3.14 }
|
||||
|
||||
x
|
||||
"#
|
||||
),
|
||||
2,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_guard_pattern() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when { x: 0x2, y: 3.14 } is
|
||||
{ x: 0x4 } -> 5
|
||||
{ x } -> x + 3
|
||||
"#
|
||||
),
|
||||
5,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn twice_record_access() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x = {a: 0x2, b: 0x3 }
|
||||
|
||||
x.a + x.b
|
||||
"#
|
||||
),
|
||||
5,
|
||||
i64
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn empty_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
v = {}
|
||||
|
||||
v
|
||||
"#
|
||||
),
|
||||
(),
|
||||
()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn i64_record1_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 3 }
|
||||
"#
|
||||
),
|
||||
3,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn i64_record2_literal() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 3, y: 5 }
|
||||
// "#
|
||||
// ),
|
||||
// (3, 5),
|
||||
// (i64, i64)
|
||||
// );
|
||||
// }
|
||||
|
||||
// // #[test]
|
||||
// // fn i64_record3_literal() {
|
||||
// // assert_evals_to!(
|
||||
// // indoc!(
|
||||
// // r#"
|
||||
// // { x: 3, y: 5, z: 17 }
|
||||
// // "#
|
||||
// // ),
|
||||
// // (3, 5, 17),
|
||||
// // (i64, i64, i64)
|
||||
// // );
|
||||
// // }
|
||||
|
||||
// #[test]
|
||||
// fn f64_record2_literal() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 3.1, y: 5.1 }
|
||||
// "#
|
||||
// ),
|
||||
// (3.1, 5.1),
|
||||
// (f64, f64)
|
||||
// );
|
||||
// }
|
||||
|
||||
// // #[test]
|
||||
// // fn f64_record3_literal() {
|
||||
// // assert_evals_to!(
|
||||
// // indoc!(
|
||||
// // r#"
|
||||
// // { x: 3.1, y: 5.1, z: 17.1 }
|
||||
// // "#
|
||||
// // ),
|
||||
// // (3.1, 5.1, 17.1),
|
||||
// // (f64, f64, f64)
|
||||
// // );
|
||||
// // }
|
||||
|
||||
// // #[test]
|
||||
// // fn bool_record4_literal() {
|
||||
// // assert_evals_to!(
|
||||
// // indoc!(
|
||||
// // r#"
|
||||
// // record : { a : Bool, b : Bool, c : Bool, d : Bool }
|
||||
// // record = { a: True, b: True, c : True, d : Bool }
|
||||
|
||||
// // record
|
||||
// // "#
|
||||
// // ),
|
||||
// // (true, false, false, true),
|
||||
// // (bool, bool, bool, bool)
|
||||
// // );
|
||||
// // }
|
||||
|
||||
// #[test]
|
||||
// fn i64_record1_literal() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { a: 3 }
|
||||
// "#
|
||||
// ),
|
||||
// 3,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// // #[test]
|
||||
// // fn i64_record9_literal() {
|
||||
// // assert_evals_to!(
|
||||
// // indoc!(
|
||||
// // r#"
|
||||
// // { a: 3, b: 5, c: 17, d: 1, e: 9, f: 12, g: 13, h: 14, i: 15 }
|
||||
// // "#
|
||||
// // ),
|
||||
// // (3, 5, 17, 1, 9, 12, 13, 14, 15),
|
||||
// // (i64, i64, i64, i64, i64, i64, i64, i64, i64)
|
||||
// // );
|
||||
// // }
|
||||
|
||||
// // #[test]
|
||||
// // fn f64_record3_literal() {
|
||||
// // assert_evals_to!(
|
||||
// // indoc!(
|
||||
// // r#"
|
||||
// // { x: 3.1, y: 5.1, z: 17.1 }
|
||||
// // "#
|
||||
// // ),
|
||||
// // (3.1, 5.1, 17.1),
|
||||
// // (f64, f64, f64)
|
||||
// // );
|
||||
// // }
|
||||
|
||||
// #[test]
|
||||
// fn bool_literal() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// x : Bool
|
||||
// x = True
|
||||
|
||||
// x
|
||||
// "#
|
||||
// ),
|
||||
// true,
|
||||
// bool
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_when_use_default() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// app "test" provides [ main ] to "./platform"
|
||||
|
||||
// f = \r ->
|
||||
// when r is
|
||||
// { x: Blue, y ? 3 } -> y
|
||||
// { x: Red, y ? 5 } -> y
|
||||
|
||||
// main =
|
||||
// a = f { x: Blue, y: 7 }
|
||||
// b = f { x: Blue }
|
||||
// c = f { x: Red, y: 11 }
|
||||
// d = f { x: Red }
|
||||
|
||||
// a * b * c * d
|
||||
// "#
|
||||
// ),
|
||||
// 3 * 5 * 7 * 11,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_when_use_default_nested() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \r ->
|
||||
// when r is
|
||||
// { x: Blue, y ? 3 } -> y
|
||||
// { x: Red, y ? 5 } -> y
|
||||
|
||||
// a = f { x: Blue, y: 7 }
|
||||
// b = f { x: Blue }
|
||||
// c = f { x: Red, y: 11 }
|
||||
// d = f { x: Red }
|
||||
|
||||
// a * b * c * d
|
||||
// "#
|
||||
// ),
|
||||
// 3 * 5 * 7 * 11,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_when_no_use_default() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// app "test" provides [ main ] to "./platform"
|
||||
|
||||
// f = \r ->
|
||||
// { x ? 10, y } = r
|
||||
// x + y
|
||||
|
||||
// main =
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_when_no_use_default_nested() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \r ->
|
||||
// { x ? 10, y } = r
|
||||
// x + y
|
||||
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_let_use_default() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// app "test" provides [ main ] to "./platform"
|
||||
|
||||
// f = \r ->
|
||||
// { x ? 10, y } = r
|
||||
// x + y
|
||||
|
||||
// main =
|
||||
// f { y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 19,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_let_no_use_default() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// app "test" provides [ main ] to "./platform"
|
||||
|
||||
// f = \r ->
|
||||
// { x ? 10, y } = r
|
||||
// x + y
|
||||
|
||||
// main =
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_let_no_use_default_nested() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \r ->
|
||||
// { x ? 10, y } = r
|
||||
// x + y
|
||||
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_function_use_default() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \{ x ? 10, y } -> x + y
|
||||
|
||||
// f { y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 19,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// #[ignore]
|
||||
// fn optional_field_function_no_use_default() {
|
||||
// // blocked on https://github.com/rtfeldman/roc/issues/786
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// app "test" provides [ main ] to "./platform"
|
||||
|
||||
// f = \{ x ? 10, y } -> x + y
|
||||
|
||||
// main =
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// #[ignore]
|
||||
// fn optional_field_function_no_use_default_nested() {
|
||||
// // blocked on https://github.com/rtfeldman/roc/issues/786
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \{ x ? 10, y } -> x + y
|
||||
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_singleton_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when { x : 4 } is
|
||||
// { x ? 3 } -> x
|
||||
// "#
|
||||
// ),
|
||||
// 4,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_empty_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when { } is
|
||||
// { x ? 3 } -> x
|
||||
// "#
|
||||
// ),
|
||||
// 3,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_record_2() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 3, y: 5 }
|
||||
// "#
|
||||
// ),
|
||||
// [3, 5],
|
||||
// [i64; 2]
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_record_3() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 3, y: 5, z: 4 }
|
||||
// "#
|
||||
// ),
|
||||
// (3, 5, 4),
|
||||
// (i64, i64, i64)
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_record_4() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { a: 3, b: 5, c: 4, d: 2 }
|
||||
// "#
|
||||
// ),
|
||||
// [3, 5, 4, 2],
|
||||
// [i64; 4]
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_record_5() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { a: 3, b: 5, c: 4, d: 2, e: 1 }
|
||||
// "#
|
||||
// ),
|
||||
// [3, 5, 4, 2, 1],
|
||||
// [i64; 5]
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_record_6() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { a: 3, b: 5, c: 4, d: 2, e: 1, f: 7 }
|
||||
// "#
|
||||
// ),
|
||||
// [3, 5, 4, 2, 1, 7],
|
||||
// [i64; 6]
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_record_7() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { a: 3, b: 5, c: 4, d: 2, e: 1, f: 7, g: 8 }
|
||||
// "#
|
||||
// ),
|
||||
// [3, 5, 4, 2, 1, 7, 8],
|
||||
// [i64; 7]
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_record_float_int() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { a: 3.14, b: 0x1 }
|
||||
// "#
|
||||
// ),
|
||||
// (3.14, 0x1),
|
||||
// (f64, i64)
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_record_int_float() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { a: 0x1, b: 3.14 }
|
||||
// "#
|
||||
// ),
|
||||
// (0x1, 3.14),
|
||||
// (i64, f64)
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_record_float_float() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { a: 6.28, b: 3.14 }
|
||||
// "#
|
||||
// ),
|
||||
// (6.28, 3.14),
|
||||
// (f64, f64)
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_record_float_float_float() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { a: 6.28, b: 3.14, c: 0.1 }
|
||||
// "#
|
||||
// ),
|
||||
// (6.28, 3.14, 0.1),
|
||||
// (f64, f64, f64)
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn return_nested_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { flag: 0x0, payload: { a: 6.28, b: 3.14, c: 0.1 } }
|
||||
// "#
|
||||
// ),
|
||||
// (0x0, (6.28, 3.14, 0.1)),
|
||||
// (i64, (f64, f64, f64))
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn accessor() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// .foo { foo: 4 } + .foo { bar: 6.28, foo: 3 }
|
||||
// "#
|
||||
// ),
|
||||
// 7,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn accessor_single_element_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// .foo { foo: 4 }
|
||||
// "#
|
||||
// ),
|
||||
// 4,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn update_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { foo: 42, bar: 6 }
|
||||
|
||||
// { rec & foo: rec.foo + 1 }
|
||||
// "#
|
||||
// ),
|
||||
// (6, 43),
|
||||
// (i64, i64)
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn update_single_element_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
rec = { foo: 42}
|
||||
|
||||
{ rec & foo: rec.foo + 1 }
|
||||
"#
|
||||
),
|
||||
43,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn booleans_in_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!("{ x: 1 == 1, y: 1 == 1 }"),
|
||||
// (true, true),
|
||||
// (bool, bool)
|
||||
// );
|
||||
// assert_evals_to!(
|
||||
// indoc!("{ x: 1 != 1, y: 1 == 1 }"),
|
||||
// (false, true),
|
||||
// (bool, bool)
|
||||
// );
|
||||
// assert_evals_to!(
|
||||
// indoc!("{ x: 1 == 1, y: 1 != 1 }"),
|
||||
// (true, false),
|
||||
// (bool, bool)
|
||||
// );
|
||||
// assert_evals_to!(
|
||||
// indoc!("{ x: 1 != 1, y: 1 != 1 }"),
|
||||
// (false, false),
|
||||
// (bool, bool)
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn alignment_in_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!("{ c: 32, b: if True then Red else if True then Green else Blue, a: 1 == 1 }"),
|
||||
// (32i64, true, 2u8),
|
||||
// (i64, bool, u8)
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn blue_and_present() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \r ->
|
||||
// when r is
|
||||
// { x: Blue, y ? 3 } -> y
|
||||
// { x: Red, y ? 5 } -> y
|
||||
|
||||
// f { x: Blue, y: 7 }
|
||||
// "#
|
||||
// ),
|
||||
// 7,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn blue_and_absent() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \r ->
|
||||
// when r is
|
||||
// { x: Blue, y ? 3 } -> y
|
||||
// { x: Red, y ? 5 } -> y
|
||||
|
||||
// f { x: Blue }
|
||||
// "#
|
||||
// ),
|
||||
// 3,
|
||||
// i64
|
||||
// );
|
||||
// }
|
|
@ -1,950 +0,0 @@
|
|||
#![cfg(all(test, any(target_os = "linux", target_os = "macos"), any(target_arch = "x86_64"/*, target_arch = "aarch64"*/)))]
|
||||
|
||||
//use indoc::indoc;
|
||||
use crate::assert_evals_to;
|
||||
|
||||
// use roc_std::{RocList, RocStr};
|
||||
// #[test]
|
||||
// fn str_split_bigger_delimiter_small_str() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// List.len (Str.split "hello" "JJJJ there")
|
||||
// "#
|
||||
// ),
|
||||
// 1,
|
||||
// i64
|
||||
// );
|
||||
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when List.first (Str.split "JJJ" "JJJJ there") is
|
||||
// Ok str ->
|
||||
// Str.countGraphemes str
|
||||
|
||||
// _ ->
|
||||
// -1
|
||||
|
||||
// "#
|
||||
// ),
|
||||
// 3,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_split_str_concat_repeated() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when List.first (Str.split "JJJJJ" "JJJJ there") is
|
||||
// Ok str ->
|
||||
// str
|
||||
// |> Str.concat str
|
||||
// |> Str.concat str
|
||||
// |> Str.concat str
|
||||
// |> Str.concat str
|
||||
|
||||
// _ ->
|
||||
// "Not Str!"
|
||||
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from_slice(b"JJJJJJJJJJJJJJJJJJJJJJJJJ"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_split_small_str_bigger_delimiter() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when
|
||||
// List.first
|
||||
// (Str.split "JJJ" "0123456789abcdefghi")
|
||||
// is
|
||||
// Ok str -> str
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from_slice(b"JJJ"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_split_big_str_small_delimiter() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Str.split "01234567789abcdefghi?01234567789abcdefghi" "?"
|
||||
// "#
|
||||
// ),
|
||||
// RocList::from_slice(&[
|
||||
// RocStr::from_slice(b"01234567789abcdefghi"),
|
||||
// RocStr::from_slice(b"01234567789abcdefghi")
|
||||
// ]),
|
||||
// RocList<RocStr>
|
||||
// );
|
||||
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Str.split "01234567789abcdefghi 3ch 01234567789abcdefghi" "3ch"
|
||||
// "#
|
||||
// ),
|
||||
// RocList::from_slice(&[
|
||||
// RocStr::from_slice(b"01234567789abcdefghi "),
|
||||
// RocStr::from_slice(b" 01234567789abcdefghi")
|
||||
// ]),
|
||||
// RocList<RocStr>
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_split_small_str_small_delimiter() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Str.split "J!J!J" "!"
|
||||
// "#
|
||||
// ),
|
||||
// RocList::from_slice(&[
|
||||
// RocStr::from_slice(b"J"),
|
||||
// RocStr::from_slice(b"J"),
|
||||
// RocStr::from_slice(b"J")
|
||||
// ]),
|
||||
// RocList<RocStr>
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_split_bigger_delimiter_big_strs() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Str.split
|
||||
// "string to split is shorter"
|
||||
// "than the delimiter which happens to be very very long"
|
||||
// "#
|
||||
// ),
|
||||
// RocList::from_slice(&[RocStr::from_slice(b"string to split is shorter")]),
|
||||
// RocList<RocStr>
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_split_empty_strs() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Str.split "" ""
|
||||
// "#
|
||||
// ),
|
||||
// RocList::from_slice(&[RocStr::from_slice(b"")]),
|
||||
// RocList<RocStr>
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_split_minimal_example() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Str.split "a," ","
|
||||
// "#
|
||||
// ),
|
||||
// RocList::from_slice(&[RocStr::from_slice(b"a"), RocStr::from_slice(b"")]),
|
||||
// RocList<RocStr>
|
||||
// )
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_split_small_str_big_delimiter() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Str.split
|
||||
// "1---- ---- ---- ---- ----2---- ---- ---- ---- ----"
|
||||
// "---- ---- ---- ---- ----"
|
||||
// |> List.len
|
||||
// "#
|
||||
// ),
|
||||
// 3,
|
||||
// i64
|
||||
// );
|
||||
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Str.split
|
||||
// "1---- ---- ---- ---- ----2---- ---- ---- ---- ----"
|
||||
// "---- ---- ---- ---- ----"
|
||||
// "#
|
||||
// ),
|
||||
// RocList::from_slice(&[
|
||||
// RocStr::from_slice(b"1"),
|
||||
// RocStr::from_slice(b"2"),
|
||||
// RocStr::from_slice(b"")
|
||||
// ]),
|
||||
// RocList<RocStr>
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_split_small_str_20_char_delimiter() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Str.split
|
||||
// "3|-- -- -- -- -- -- |4|-- -- -- -- -- -- |"
|
||||
// "|-- -- -- -- -- -- |"
|
||||
// "#
|
||||
// ),
|
||||
// RocList::from_slice(&[
|
||||
// RocStr::from_slice(b"3"),
|
||||
// RocStr::from_slice(b"4"),
|
||||
// RocStr::from_slice(b"")
|
||||
// ]),
|
||||
// RocList<RocStr>
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_concat_big_to_big() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Str.concat
|
||||
// "First string that is fairly long. Longer strings make for different errors. "
|
||||
// "Second string that is also fairly long. Two long strings test things that might not appear with short strings."
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from_slice(b"First string that is fairly long. Longer strings make for different errors. Second string that is also fairly long. Two long strings test things that might not appear with short strings."),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn small_str_literal() {
|
||||
assert_evals_to!(
|
||||
"\"JJJJJJJJJJJJJJJ\"",
|
||||
[
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0b1000_1111
|
||||
],
|
||||
[u8; 16]
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn small_str_zeroed_literal() {
|
||||
// // Verifies that we zero out unused bytes in the string.
|
||||
// // This is important so that string equality tests don't randomly
|
||||
// // fail due to unused memory being there!
|
||||
// assert_evals_to!(
|
||||
// "\"J\"",
|
||||
// [
|
||||
// 0x4a,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0b1000_0001
|
||||
// ],
|
||||
// [u8; 16]
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn small_str_concat_empty_first_arg() {
|
||||
assert_evals_to!(
|
||||
r#"Str.concat "" "JJJJJJJJJJJJJJJ""#,
|
||||
[
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0b1000_1111
|
||||
],
|
||||
[u8; 16]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn small_str_concat_empty_second_arg() {
|
||||
assert_evals_to!(
|
||||
r#"Str.concat "JJJJJJJJJJJJJJJ" """#,
|
||||
[
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0b1000_1111
|
||||
],
|
||||
[u8; 16]
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn small_str_concat_small_to_big() {
|
||||
// assert_evals_to!(
|
||||
// r#"Str.concat "abc" " this is longer than 15 chars""#,
|
||||
// RocStr::from_slice(b"abc this is longer than 15 chars"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn small_str_concat_small_to_small_staying_small() {
|
||||
assert_evals_to!(
|
||||
r#"Str.concat "J" "JJJJJJJJJJJJJJ""#,
|
||||
[
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0x4a,
|
||||
0b1000_1111
|
||||
],
|
||||
[u8; 16]
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn small_str_concat_small_to_small_overflow_to_big() {
|
||||
// assert_evals_to!(
|
||||
// r#"Str.concat "abcdefghijklm" "nopqrstuvwxyz""#,
|
||||
// RocStr::from_slice(b"abcdefghijklmnopqrstuvwxyz"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_concat_empty() {
|
||||
// assert_evals_to!(r#"Str.concat "" """#, RocStr::default(), RocStr);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn small_str_is_empty() {
|
||||
// assert_evals_to!(r#"Str.isEmpty "abc""#, false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn big_str_is_empty() {
|
||||
// assert_evals_to!(
|
||||
// r#"Str.isEmpty "this is more than 15 chars long""#,
|
||||
// false,
|
||||
// bool
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn empty_str_is_empty() {
|
||||
// assert_evals_to!(r#"Str.isEmpty """#, true, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_starts_with() {
|
||||
// assert_evals_to!(r#"Str.startsWith "hello world" "hell""#, true, bool);
|
||||
// assert_evals_to!(r#"Str.startsWith "hello world" """#, true, bool);
|
||||
// assert_evals_to!(r#"Str.startsWith "nope" "hello world""#, false, bool);
|
||||
// assert_evals_to!(r#"Str.startsWith "hell" "hello world""#, false, bool);
|
||||
// assert_evals_to!(r#"Str.startsWith "" "hello world""#, false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_starts_with_code_point() {
|
||||
// assert_evals_to!(
|
||||
// &format!(r#"Str.startsWithCodePt "foobar" {}"#, 'f' as u32),
|
||||
// true,
|
||||
// bool
|
||||
// );
|
||||
// assert_evals_to!(
|
||||
// &format!(r#"Str.startsWithCodePt "zoobar" {}"#, 'f' as u32),
|
||||
// false,
|
||||
// bool
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_ends_with() {
|
||||
// assert_evals_to!(r#"Str.endsWith "hello world" "world""#, true, bool);
|
||||
// assert_evals_to!(r#"Str.endsWith "nope" "hello world""#, false, bool);
|
||||
// assert_evals_to!(r#"Str.endsWith "" "hello world""#, false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_count_graphemes_small_str() {
|
||||
// assert_evals_to!(r#"Str.countGraphemes "å🤔""#, 2, usize);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_count_graphemes_three_js() {
|
||||
// assert_evals_to!(r#"Str.countGraphemes "JJJ""#, 3, usize);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_count_graphemes_big_str() {
|
||||
// assert_evals_to!(
|
||||
// r#"Str.countGraphemes "6🤔å🤔e¥🤔çppkd🙃1jdal🦯asdfa∆ltråø˚waia8918.,🏅jjc""#,
|
||||
// 45,
|
||||
// usize
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_starts_with_same_big_str() {
|
||||
// assert_evals_to!(
|
||||
// r#"Str.startsWith "123456789123456789" "123456789123456789""#,
|
||||
// true,
|
||||
// bool
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_starts_with_different_big_str() {
|
||||
// assert_evals_to!(
|
||||
// r#"Str.startsWith "12345678912345678910" "123456789123456789""#,
|
||||
// true,
|
||||
// bool
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_starts_with_same_small_str() {
|
||||
// assert_evals_to!(r#"Str.startsWith "1234" "1234""#, true, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_starts_with_different_small_str() {
|
||||
// assert_evals_to!(r#"Str.startsWith "1234" "12""#, true, bool);
|
||||
// }
|
||||
// #[test]
|
||||
// fn str_starts_with_false_small_str() {
|
||||
// assert_evals_to!(r#"Str.startsWith "1234" "23""#, false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_int() {
|
||||
// assert_evals_to!(
|
||||
// r#"Str.fromInt 1234"#,
|
||||
// roc_std::RocStr::from_slice("1234".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// assert_evals_to!(
|
||||
// r#"Str.fromInt 0"#,
|
||||
// roc_std::RocStr::from_slice("0".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// assert_evals_to!(
|
||||
// r#"Str.fromInt -1"#,
|
||||
// roc_std::RocStr::from_slice("-1".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
|
||||
// let max = format!("{}", i64::MAX);
|
||||
// assert_evals_to!(
|
||||
// r#"Str.fromInt Num.maxInt"#,
|
||||
// RocStr::from_slice(max.as_bytes()),
|
||||
// RocStr
|
||||
// );
|
||||
|
||||
// let min = format!("{}", i64::MIN);
|
||||
// assert_evals_to!(
|
||||
// r#"Str.fromInt Num.minInt"#,
|
||||
// RocStr::from_slice(min.as_bytes()),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_pass_single_ascii() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 97 ] is
|
||||
// Ok val -> val
|
||||
// Err _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("a".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_pass_many_ascii() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 97, 98, 99, 0x7E ] is
|
||||
// Ok val -> val
|
||||
// Err _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("abc~".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_pass_single_unicode() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 0xE2, 0x88, 0x86 ] is
|
||||
// Ok val -> val
|
||||
// Err _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("∆".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_pass_many_unicode() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 0xE2, 0x88, 0x86, 0xC5, 0x93, 0xC2, 0xAC ] is
|
||||
// Ok val -> val
|
||||
// Err _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("∆œ¬".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_pass_single_grapheme() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 0xF0, 0x9F, 0x92, 0x96 ] is
|
||||
// Ok val -> val
|
||||
// Err _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("💖".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_pass_many_grapheme() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 0xF0, 0x9F, 0x92, 0x96, 0xF0, 0x9F, 0xA4, 0xA0, 0xF0, 0x9F, 0x9A, 0x80 ] is
|
||||
// Ok val -> val
|
||||
// Err _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("💖🤠🚀".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_pass_all() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 0xF0, 0x9F, 0x92, 0x96, 98, 0xE2, 0x88, 0x86 ] is
|
||||
// Ok val -> val
|
||||
// Err _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("💖b∆".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_fail_invalid_start_byte() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 97, 98, 0x80, 99 ] is
|
||||
// Err (BadUtf8 InvalidStartByte byteIndex) ->
|
||||
// if byteIndex == 2 then
|
||||
// "a"
|
||||
// else
|
||||
// "b"
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("a".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 97, 98, 99, 0xC2 ] is
|
||||
// Err (BadUtf8 UnexpectedEndOfSequence byteIndex) ->
|
||||
// if byteIndex == 3 then
|
||||
// "a"
|
||||
// else
|
||||
// "b"
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("a".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_fail_expected_continuation() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 97, 98, 99, 0xC2, 0x00 ] is
|
||||
// Err (BadUtf8 ExpectedContinuation byteIndex) ->
|
||||
// if byteIndex == 3 then
|
||||
// "a"
|
||||
// else
|
||||
// "b"
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("a".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_fail_overlong_encoding() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 97, 0xF0, 0x80, 0x80, 0x80 ] is
|
||||
// Err (BadUtf8 OverlongEncoding byteIndex) ->
|
||||
// if byteIndex == 1 then
|
||||
// "a"
|
||||
// else
|
||||
// "b"
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("a".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_fail_codepoint_too_large() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 97, 0xF4, 0x90, 0x80, 0x80 ] is
|
||||
// Err (BadUtf8 CodepointTooLarge byteIndex) ->
|
||||
// if byteIndex == 1 then
|
||||
// "a"
|
||||
// else
|
||||
// "b"
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("a".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_fail_surrogate_half() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when Str.fromUtf8 [ 97, 98, 0xED, 0xA0, 0x80 ] is
|
||||
// Err (BadUtf8 EncodesSurrogateHalf byteIndex) ->
|
||||
// if byteIndex == 2 then
|
||||
// "a"
|
||||
// else
|
||||
// "b"
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// roc_std::RocStr::from_slice("a".as_bytes()),
|
||||
// roc_std::RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_equality() {
|
||||
// assert_evals_to!(r#""a" == "a""#, true, bool);
|
||||
// assert_evals_to!(
|
||||
// r#""loremipsumdolarsitamet" == "loremipsumdolarsitamet""#,
|
||||
// true,
|
||||
// bool
|
||||
// );
|
||||
// assert_evals_to!(r#""a" != "b""#, true, bool);
|
||||
// assert_evals_to!(r#""a" == "b""#, false, bool);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_clone() {
|
||||
// use roc_std::RocStr;
|
||||
// let long = RocStr::from_slice("loremipsumdolarsitamet".as_bytes());
|
||||
// let short = RocStr::from_slice("x".as_bytes());
|
||||
// let empty = RocStr::from_slice("".as_bytes());
|
||||
|
||||
// debug_assert_eq!(long.clone(), long);
|
||||
// debug_assert_eq!(short.clone(), short);
|
||||
// debug_assert_eq!(empty.clone(), empty);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn nested_recursive_literal() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// Expr : [ Add Expr Expr, Val I64, Var I64 ]
|
||||
|
||||
// expr : Expr
|
||||
// expr = Add (Add (Val 3) (Val 1)) (Add (Val 1) (Var 1))
|
||||
|
||||
// printExpr : Expr -> Str
|
||||
// printExpr = \e ->
|
||||
// when e is
|
||||
// Add a b ->
|
||||
// "Add ("
|
||||
// |> Str.concat (printExpr a)
|
||||
// |> Str.concat ") ("
|
||||
// |> Str.concat (printExpr b)
|
||||
// |> Str.concat ")"
|
||||
// Val v -> "Val " |> Str.concat (Str.fromInt v)
|
||||
// Var v -> "Var " |> Str.concat (Str.fromInt v)
|
||||
|
||||
// printExpr expr
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from_slice(b"Add (Add (Val 3) (Val 1)) (Add (Val 1) (Var 1))"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_join_comma_small() {
|
||||
// assert_evals_to!(
|
||||
// r#"Str.joinWith ["1", "2"] ", " "#,
|
||||
// RocStr::from("1, 2"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_join_comma_big() {
|
||||
// assert_evals_to!(
|
||||
// r#"Str.joinWith ["10000000", "2000000", "30000000"] ", " "#,
|
||||
// RocStr::from("10000000, 2000000, 30000000"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_join_comma_single() {
|
||||
// assert_evals_to!(r#"Str.joinWith ["1"] ", " "#, RocStr::from("1"), RocStr);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_float() {
|
||||
// assert_evals_to!(r#"Str.fromFloat 3.14"#, RocStr::from("3.14"), RocStr);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_to_utf8() {
|
||||
// assert_evals_to!(
|
||||
// r#"Str.toUtf8 "hello""#,
|
||||
// RocList::from_slice(&[104, 101, 108, 108, 111]),
|
||||
// RocList<u8>
|
||||
// );
|
||||
// assert_evals_to!(
|
||||
// r#"Str.toUtf8 "this is a long string""#,
|
||||
// RocList::from_slice(&[
|
||||
// 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 108, 111, 110, 103, 32, 115, 116,
|
||||
// 114, 105, 110, 103
|
||||
// ]),
|
||||
// RocList<u8>
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_range() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// bytes = Str.toUtf8 "hello"
|
||||
// when Str.fromUtf8Range bytes { count: 5, start: 0 } is
|
||||
// Ok utf8String -> utf8String
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from("hello"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_range_slice() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// bytes = Str.toUtf8 "hello"
|
||||
// when Str.fromUtf8Range bytes { count: 4, start: 1 } is
|
||||
// Ok utf8String -> utf8String
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from("ello"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_range_slice_not_end() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// bytes = Str.toUtf8 "hello"
|
||||
// when Str.fromUtf8Range bytes { count: 3, start: 1 } is
|
||||
// Ok utf8String -> utf8String
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from("ell"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_range_order_does_not_matter() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// bytes = Str.toUtf8 "hello"
|
||||
// when Str.fromUtf8Range bytes { start: 1, count: 3 } is
|
||||
// Ok utf8String -> utf8String
|
||||
// _ -> ""
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from("ell"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_range_out_of_bounds_start_value() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// bytes = Str.toUtf8 "hello"
|
||||
// when Str.fromUtf8Range bytes { start: 7, count: 3 } is
|
||||
// Ok _ -> ""
|
||||
// Err (BadUtf8 _ _) -> ""
|
||||
// Err OutOfBounds -> "out of bounds"
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from("out of bounds"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_range_count_too_high() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// bytes = Str.toUtf8 "hello"
|
||||
// when Str.fromUtf8Range bytes { start: 0, count: 6 } is
|
||||
// Ok _ -> ""
|
||||
// Err (BadUtf8 _ _) -> ""
|
||||
// Err OutOfBounds -> "out of bounds"
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from("out of bounds"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn str_from_utf8_range_count_too_high_for_start() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// bytes = Str.toUtf8 "hello"
|
||||
// when Str.fromUtf8Range bytes { start: 4, count: 3 } is
|
||||
// Ok _ -> ""
|
||||
// Err (BadUtf8 _ _) -> ""
|
||||
// Err OutOfBounds -> "out of bounds"
|
||||
// "#
|
||||
// ),
|
||||
// RocStr::from("out of bounds"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
|
@ -1,44 +0,0 @@
|
|||
extern crate bumpalo;
|
||||
|
||||
#[macro_use]
|
||||
pub mod eval;
|
||||
|
||||
/// Used in the with_larger_debug_stack() function, for tests that otherwise
|
||||
/// run out of stack space in debug builds (but don't in --release builds)
|
||||
#[allow(dead_code)]
|
||||
const EXPANDED_STACK_SIZE: usize = 8 * 1024 * 1024;
|
||||
|
||||
/// Without this, some tests pass in `cargo test --release` but fail without
|
||||
/// the --release flag because they run out of stack space. This increases
|
||||
/// stack size for debug builds only, while leaving the stack space at the default
|
||||
/// amount for release builds.
|
||||
#[allow(dead_code)]
|
||||
#[cfg(debug_assertions)]
|
||||
pub fn with_larger_debug_stack<F>(run_test: F)
|
||||
where
|
||||
F: FnOnce(),
|
||||
F: Send,
|
||||
F: 'static,
|
||||
{
|
||||
std::thread::Builder::new()
|
||||
.stack_size(EXPANDED_STACK_SIZE)
|
||||
.spawn(run_test)
|
||||
.expect("Error while spawning expanded dev stack size thread")
|
||||
.join()
|
||||
.expect("Error while joining expanded dev stack size thread")
|
||||
}
|
||||
|
||||
/// In --release builds, don't increase the stack size. Run the test normally.
|
||||
/// This way, we find out if any of our tests are blowing the stack even after
|
||||
/// optimizations in release builds.
|
||||
#[allow(dead_code)]
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[inline(always)]
|
||||
pub fn with_larger_debug_stack<F>(run_test: F)
|
||||
where
|
||||
F: FnOnce() -> (),
|
||||
F: Send,
|
||||
F: 'static,
|
||||
{
|
||||
run_test()
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
pub mod dev_num;
|
||||
pub mod dev_records;
|
||||
pub mod dev_str;
|
||||
mod helpers;
|
|
@ -11,6 +11,8 @@ path = "src/tests.rs"
|
|||
|
||||
[dev-dependencies]
|
||||
roc_gen_llvm = { path = "../gen_llvm" }
|
||||
roc_gen_dev = { path = "../gen_dev" }
|
||||
roc_gen_wasm = { path = "../gen_wasm" }
|
||||
roc_collections = { path = "../collections" }
|
||||
roc_region = { path = "../region" }
|
||||
roc_module = { path = "../module" }
|
||||
|
@ -27,7 +29,6 @@ roc_can = { path = "../can" }
|
|||
roc_parse = { path = "../parse" }
|
||||
roc_build = { path = "../build" }
|
||||
roc_std = { path = "../../roc_std" }
|
||||
test_wasm_util = { path = "../test_wasm_util" }
|
||||
im = "15.0.0"
|
||||
im-rc = "15.0.0"
|
||||
bumpalo = { version = "3.8.0", features = ["collections"] }
|
||||
|
@ -42,5 +43,8 @@ tempfile = "3.2.0"
|
|||
indoc = "1.0.3"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
default = ["gen-llvm"]
|
||||
gen-llvm = []
|
||||
gen-dev = []
|
||||
gen-wasm = []
|
||||
wasm-cli-run = []
|
||||
|
|
28
compiler/test_gen/README.md
Normal file
28
compiler/test_gen/README.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Running our CodeGen tests
|
||||
|
||||
Our code generation tests are all in this crate. Feature flags are used to run the tests with a specific backend. For convenience, some aliases are added in `.cargo/config`:
|
||||
|
||||
```toml
|
||||
[alias]
|
||||
test-gen-llvm = "test -p test_gen"
|
||||
test-gen-dev = "test -p test_gen --no-default-features --features gen-dev"
|
||||
test-gen-wasm = "test -p test_gen --no-default-features --features gen-wasm"
|
||||
```
|
||||
|
||||
So we can run:
|
||||
|
||||
```
|
||||
cargo test-gen-llvm
|
||||
```
|
||||
|
||||
To run the gen tests with the LLVM backend. To filter tests, append a filter like so:
|
||||
|
||||
```
|
||||
> cargo test-gen-wasm wasm_str::small
|
||||
Finished test [unoptimized + debuginfo] target(s) in 0.13s
|
||||
Running src/tests.rs (target/debug/deps/test_gen-b4ad63a9dd50f050)
|
||||
|
||||
running 2 tests
|
||||
test wasm_str::small_str_literal ... ok
|
||||
test wasm_str::small_str_zeroed_literal ... ok
|
||||
```
|
|
@ -1,196 +1,218 @@
|
|||
#[cfg(test)]
|
||||
mod gen_compare {
|
||||
use crate::assert_evals_to;
|
||||
// use crate::assert_wasm_evals_to as assert_evals_to;
|
||||
use indoc::indoc;
|
||||
#![cfg(not(feature = "gen-wasm"))]
|
||||
|
||||
#[test]
|
||||
fn eq_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[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::assert_wasm_evals_to as assert_evals_to;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn eq_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : I64
|
||||
i = 1
|
||||
|
||||
i == i
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neq_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn neq_i64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : I64
|
||||
i = 1
|
||||
|
||||
i != i
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_u64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn eq_u64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : U64
|
||||
i = 1
|
||||
|
||||
i == i
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neq_u64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn neq_u64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : U64
|
||||
i = 1
|
||||
|
||||
i != i
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_f64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn eq_f64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : F64
|
||||
i = 1
|
||||
|
||||
i == i
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neq_f64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn neq_f64() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
i : F64
|
||||
i = 1
|
||||
|
||||
i != i
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_bool_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn eq_bool_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
true : Bool
|
||||
true = True
|
||||
|
||||
true == True
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neq_bool_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn neq_bool_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
true : Bool
|
||||
true = True
|
||||
|
||||
true == False
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_record() {
|
||||
assert_evals_to!("{} == {}", true, bool);
|
||||
assert_evals_to!("{} != {}", false, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn empty_record() {
|
||||
assert_evals_to!("{} == {}", true, bool);
|
||||
assert_evals_to!("{} != {}", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unit() {
|
||||
assert_evals_to!("Unit == Unit", true, bool);
|
||||
assert_evals_to!("Unit != Unit", false, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn unit() {
|
||||
assert_evals_to!("Unit == Unit", true, bool);
|
||||
assert_evals_to!("Unit != Unit", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtype() {
|
||||
assert_evals_to!("Identity 42 == Identity 42", true, bool);
|
||||
assert_evals_to!("Identity 42 != Identity 42", false, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn newtype() {
|
||||
assert_evals_to!("Identity 42 == Identity 42", true, bool);
|
||||
assert_evals_to!("Identity 42 != Identity 42", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn small_str() {
|
||||
assert_evals_to!("\"aaa\" == \"aaa\"", true, bool);
|
||||
assert_evals_to!("\"aaa\" == \"bbb\"", false, bool);
|
||||
assert_evals_to!("\"aaa\" != \"aaa\"", false, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn small_str() {
|
||||
assert_evals_to!("\"aaa\" == \"aaa\"", true, bool);
|
||||
assert_evals_to!("\"aaa\" == \"bbb\"", false, bool);
|
||||
assert_evals_to!("\"aaa\" != \"aaa\"", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn large_str() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn large_str() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x = "Unicode can represent text values which span multiple languages"
|
||||
y = "Unicode can represent text values which span multiple languages"
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x = "Unicode can represent text values which span multiple languages"
|
||||
y = "Here are some valid Roc strings"
|
||||
|
||||
x != y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_result_tag_true() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn eq_result_tag_true() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Result I64 I64
|
||||
x = Ok 1
|
||||
|
||||
|
@ -199,17 +221,18 @@ mod gen_compare {
|
|||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_result_tag_false() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn eq_result_tag_false() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Result I64 I64
|
||||
x = Ok 1
|
||||
|
||||
|
@ -218,17 +241,18 @@ mod gen_compare {
|
|||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_expr() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn eq_expr() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Expr : [ Add Expr Expr, Mul Expr Expr, Val I64, Var I64 ]
|
||||
|
||||
x : Expr
|
||||
|
@ -239,17 +263,18 @@ mod gen_compare {
|
|||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_linked_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn eq_linked_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||
|
||||
x : LinkedList I64
|
||||
|
@ -260,14 +285,14 @@ mod gen_compare {
|
|||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||
|
||||
x : LinkedList I64
|
||||
|
@ -278,14 +303,14 @@ mod gen_compare {
|
|||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||
|
||||
x : LinkedList I64
|
||||
|
@ -296,17 +321,18 @@ mod gen_compare {
|
|||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_linked_list_false() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn eq_linked_list_false() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
LinkedList a : [ Nil, Cons a (LinkedList a) ]
|
||||
|
||||
x : LinkedList I64
|
||||
|
@ -317,17 +343,18 @@ mod gen_compare {
|
|||
|
||||
y == x
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_nullable_expr() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn eq_nullable_expr() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Expr : [ Add Expr Expr, Mul Expr Expr, Val I64, Empty ]
|
||||
|
||||
x : Expr
|
||||
|
@ -338,17 +365,18 @@ mod gen_compare {
|
|||
|
||||
x != y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eq_rosetree() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn eq_rosetree() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Rose a : [ Rose (List (Rose a)) ]
|
||||
|
||||
x : Rose I64
|
||||
|
@ -359,14 +387,14 @@ mod gen_compare {
|
|||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Rose a : [ Rose (List (Rose a)) ]
|
||||
|
||||
x : Rose I64
|
||||
|
@ -377,20 +405,21 @@ mod gen_compare {
|
|||
|
||||
x != y
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn rosetree_with_tag() {
|
||||
// currently stack overflows in type checking
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn rosetree_with_tag() {
|
||||
// currently stack overflows in type checking
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Rose a : [ Rose (Result (List (Rose a)) I64) ]
|
||||
|
||||
x : Rose I64
|
||||
|
@ -401,53 +430,60 @@ mod gen_compare {
|
|||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_eq_empty() {
|
||||
assert_evals_to!("[] == []", true, bool);
|
||||
assert_evals_to!("[] != []", false, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn list_eq_empty() {
|
||||
assert_evals_to!("[] == []", true, bool);
|
||||
assert_evals_to!("[] != []", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_eq_by_length() {
|
||||
assert_evals_to!("[1] == []", false, bool);
|
||||
assert_evals_to!("[] == [1]", false, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn list_eq_by_length() {
|
||||
assert_evals_to!("[1] == []", false, bool);
|
||||
assert_evals_to!("[] == [1]", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_eq_compare_pointwise() {
|
||||
assert_evals_to!("[1] == [1]", true, bool);
|
||||
assert_evals_to!("[2] == [1]", false, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn list_eq_compare_pointwise() {
|
||||
assert_evals_to!("[1] == [1]", true, bool);
|
||||
assert_evals_to!("[2] == [1]", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_eq_nested() {
|
||||
assert_evals_to!("[[1]] == [[1]]", true, bool);
|
||||
assert_evals_to!("[[2]] == [[1]]", false, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn list_eq_nested() {
|
||||
assert_evals_to!("[[1]] == [[1]]", true, bool);
|
||||
assert_evals_to!("[[2]] == [[1]]", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_neq_compare_pointwise() {
|
||||
assert_evals_to!("[1] != [1]", false, bool);
|
||||
assert_evals_to!("[2] != [1]", true, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn list_neq_compare_pointwise() {
|
||||
assert_evals_to!("[1] != [1]", false, bool);
|
||||
assert_evals_to!("[2] != [1]", true, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_neq_nested() {
|
||||
assert_evals_to!("[[1]] != [[1]]", false, bool);
|
||||
assert_evals_to!("[[2]] != [[1]]", true, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn list_neq_nested() {
|
||||
assert_evals_to!("[[1]] != [[1]]", false, bool);
|
||||
assert_evals_to!("[[2]] != [[1]]", true, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compare_union_same_content() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn compare_union_same_content() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Foo : [ A I64, B I64 ]
|
||||
|
||||
a : Foo
|
||||
|
@ -458,17 +494,18 @@ mod gen_compare {
|
|||
|
||||
a == b
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compare_recursive_union_same_content() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn compare_recursive_union_same_content() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Expr : [ Add Expr Expr, Mul Expr Expr, Val1 I64, Val2 I64 ]
|
||||
|
||||
v1 : Expr
|
||||
|
@ -479,17 +516,18 @@ mod gen_compare {
|
|||
|
||||
v1 == v2
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compare_nullable_recursive_union_same_content() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn compare_nullable_recursive_union_same_content() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
Expr : [ Add Expr Expr, Mul Expr Expr, Val1 I64, Val2 I64, Empty ]
|
||||
|
||||
v1 : Expr
|
||||
|
@ -500,9 +538,8 @@ mod gen_compare {
|
|||
|
||||
v1 == v2
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
#![cfg(test)]
|
||||
#![cfg(feature = "gen-llvm")]
|
||||
|
||||
#[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::assert_evals_to;
|
||||
use indoc::indoc;
|
||||
use roc_std::{RocList, RocStr};
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn dict_empty_len() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -18,6 +27,7 @@ fn dict_empty_len() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn dict_insert_empty() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -32,6 +42,7 @@ fn dict_insert_empty() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn dict_empty_contains() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -48,6 +59,7 @@ fn dict_empty_contains() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn dict_nonempty_contains() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -64,6 +76,7 @@ fn dict_nonempty_contains() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn dict_empty_remove() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -82,6 +95,7 @@ fn dict_empty_remove() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn dict_nonempty_remove() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -100,6 +114,7 @@ fn dict_nonempty_remove() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn dict_nonempty_get() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -142,6 +157,7 @@ fn dict_nonempty_get() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn keys() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -163,6 +179,7 @@ fn keys() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn values() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -184,6 +201,7 @@ fn values() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn from_list_with_fold() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -226,6 +244,7 @@ fn from_list_with_fold() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn small_str_keys() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -247,6 +266,7 @@ fn small_str_keys() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn big_str_keys() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -272,6 +292,7 @@ fn big_str_keys() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn big_str_values() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -296,6 +317,7 @@ fn big_str_values() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn unit_values() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -317,6 +339,7 @@ fn unit_values() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn single() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -334,6 +357,7 @@ fn single() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn union() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -351,6 +375,7 @@ fn union() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn union_prefer_first() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -368,6 +393,7 @@ fn union_prefer_first() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn intersection() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -398,6 +424,7 @@ fn intersection() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn intersection_prefer_first() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -428,6 +455,7 @@ fn intersection_prefer_first() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn difference() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -458,6 +486,7 @@ fn difference() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn difference_prefer_first() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -488,6 +517,7 @@ fn difference_prefer_first() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn walk_sum_keys() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,22 +1,42 @@
|
|||
#![cfg(test)]
|
||||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_evals_to;
|
||||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_llvm_evals_to;
|
||||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_non_opt_evals_to;
|
||||
|
||||
#[cfg(feature = "gen-dev")]
|
||||
use crate::helpers::dev::assert_evals_to;
|
||||
// #[cfg(feature = "gen-dev")]
|
||||
// use crate::helpers::dev::assert_evals_to as assert_llvm_evals_to;
|
||||
// #[cfg(feature = "gen-dev")]
|
||||
// use crate::helpers::dev::assert_evals_to as assert_non_opt_evals_to;
|
||||
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
use crate::helpers::wasm::assert_evals_to;
|
||||
// #[cfg(feature = "gen-wasm")]
|
||||
// use crate::helpers::wasm::assert_evals_to as assert_llvm_evals_to;
|
||||
// #[cfg(feature = "gen-wasm")]
|
||||
// use crate::helpers::wasm::assert_evals_to as assert_non_opt_evals_to;
|
||||
|
||||
use crate::assert_evals_to;
|
||||
use crate::assert_llvm_evals_to;
|
||||
use crate::assert_non_opt_evals_to;
|
||||
use indoc::indoc;
|
||||
#[allow(unused_imports)]
|
||||
use roc_std::RocStr;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn basic_int() {
|
||||
assert_evals_to!("123", 123, i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn basic_float() {
|
||||
assert_evals_to!("1234.0", 1234.0, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn branch_first_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -32,6 +52,7 @@ fn branch_first_float() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn branch_second_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -47,6 +68,7 @@ fn branch_second_float() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn branch_third_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -63,6 +85,7 @@ fn branch_third_float() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn branch_first_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -78,6 +101,7 @@ fn branch_first_int() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn branch_second_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -93,6 +117,7 @@ fn branch_second_int() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn branch_third_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -109,6 +134,7 @@ fn branch_third_int() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn branch_store_variable() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -124,6 +150,7 @@ fn branch_store_variable() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn when_one_element_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -141,6 +168,7 @@ fn when_one_element_tag() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn when_two_element_tag_first() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -159,6 +187,7 @@ fn when_two_element_tag_first() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn when_two_element_tag_second() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -177,6 +206,7 @@ fn when_two_element_tag_second() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn gen_when_one_branch() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -191,6 +221,7 @@ fn gen_when_one_branch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn gen_large_when_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -213,6 +244,7 @@ fn gen_large_when_int() {
|
|||
}
|
||||
|
||||
// #[test]
|
||||
// #[cfg(any(feature = "gen-llvm"))]
|
||||
// fn gen_large_when_float() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -235,6 +267,7 @@ fn gen_large_when_int() {
|
|||
// }
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn or_pattern() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -250,6 +283,7 @@ fn or_pattern() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn apply_identity() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -265,6 +299,7 @@ fn apply_identity() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn apply_unnamed_identity() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -281,6 +316,7 @@ fn apply_unnamed_identity() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn return_unnamed_fn() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -301,6 +337,7 @@ fn return_unnamed_fn() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn gen_when_fn() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -320,6 +357,7 @@ fn gen_when_fn() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn gen_basic_def() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -347,6 +385,7 @@ fn gen_basic_def() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn gen_multiple_defs() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -380,6 +419,7 @@ fn gen_multiple_defs() {
|
|||
// These tests caught a bug in how Defs are converted to the mono IR
|
||||
// but they have UnusedDef or UnusedArgument problems, and don't run any more
|
||||
// #[test]
|
||||
// #[cfg(any(feature = "gen-llvm"))]
|
||||
// fn gen_chained_defs() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -399,6 +439,7 @@ fn gen_multiple_defs() {
|
|||
// }
|
||||
//
|
||||
// #[test]
|
||||
// #[cfg(any(feature = "gen-llvm"))]
|
||||
// fn gen_nested_defs_old() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -440,6 +481,7 @@ fn gen_multiple_defs() {
|
|||
// }
|
||||
//
|
||||
// #[test]
|
||||
// #[cfg(any(feature = "gen-llvm"))]
|
||||
// fn let_x_in_x() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -462,6 +504,7 @@ fn gen_multiple_defs() {
|
|||
// }
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn factorial() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -483,6 +526,7 @@ fn factorial() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn peano1() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -503,6 +547,7 @@ fn peano1() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn peano2() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -524,6 +569,7 @@ fn peano2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn top_level_constant() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -542,6 +588,7 @@ fn top_level_constant() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_len_0() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -569,6 +616,7 @@ fn linked_list_len_0() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_len_twice_0() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -596,6 +644,7 @@ fn linked_list_len_twice_0() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_len_1() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -623,6 +672,7 @@ fn linked_list_len_1() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_len_twice_1() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -650,6 +700,7 @@ fn linked_list_len_twice_1() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_len_3() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -678,6 +729,7 @@ fn linked_list_len_3() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_sum_num_a() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -706,6 +758,7 @@ fn linked_list_sum_num_a() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_sum_int() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -733,6 +786,7 @@ fn linked_list_sum_int() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_map() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -766,6 +820,7 @@ fn linked_list_map() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn when_nested_maybe() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -822,6 +877,7 @@ fn when_nested_maybe() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn when_peano() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -879,6 +935,7 @@ fn when_peano() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "Roc failed with message: ")]
|
||||
fn overflow_frees_list() {
|
||||
assert_evals_to!(
|
||||
|
@ -903,6 +960,7 @@ fn overflow_frees_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "Roc failed with message: ")]
|
||||
fn undefined_variable() {
|
||||
assert_evals_to!(
|
||||
|
@ -920,6 +978,7 @@ fn undefined_variable() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "Roc failed with message: ")]
|
||||
fn annotation_without_body() {
|
||||
assert_evals_to!(
|
||||
|
@ -937,6 +996,7 @@ fn annotation_without_body() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn simple_closure() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -958,6 +1018,7 @@ fn simple_closure() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn nested_closure() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -981,6 +1042,7 @@ fn nested_closure() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn closure_in_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1006,6 +1068,7 @@ fn closure_in_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn specialize_closure() {
|
||||
use roc_std::RocList;
|
||||
|
||||
|
@ -1037,6 +1100,7 @@ fn specialize_closure() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn io_poc_effect() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1067,6 +1131,7 @@ fn io_poc_effect() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn io_poc_desugared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1094,6 +1159,7 @@ fn io_poc_desugared() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn return_wrapped_function_pointer() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1116,6 +1182,7 @@ fn return_wrapped_function_pointer() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn return_wrapped_function_pointer_b() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1137,6 +1204,7 @@ fn return_wrapped_function_pointer_b() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn return_wrapped_closure() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1162,6 +1230,7 @@ fn return_wrapped_closure() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_is_singleton() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1196,6 +1265,7 @@ fn linked_list_is_singleton() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_is_empty_1() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1230,6 +1300,7 @@ fn linked_list_is_empty_1() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_is_empty_2() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1261,6 +1332,7 @@ fn linked_list_is_empty_2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_singleton() {
|
||||
// verifies only that valid llvm is produced
|
||||
assert_non_opt_evals_to!(
|
||||
|
@ -1281,6 +1353,7 @@ fn linked_list_singleton() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn recursive_function_with_rigid() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1307,6 +1380,7 @@ fn recursive_function_with_rigid() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn rbtree_insert() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1394,6 +1468,7 @@ fn rbtree_insert() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn rbtree_balance_3() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1418,6 +1493,7 @@ fn rbtree_balance_3() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn rbtree_layout_issue() {
|
||||
// there is a flex var in here somewhere that blows up layout creation
|
||||
|
@ -1459,6 +1535,7 @@ fn rbtree_layout_issue() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn rbtree_balance_mono_problem() {
|
||||
// because of how the function is written, only `Red` is used and so in the function's
|
||||
|
@ -1512,6 +1589,7 @@ fn rbtree_balance_mono_problem() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn rbtree_balance_full() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1563,6 +1641,7 @@ fn rbtree_balance_full() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn nested_pattern_match_two_ways() {
|
||||
// exposed an issue in the ordering of pattern match checks when ran with `--release` mode
|
||||
assert_non_opt_evals_to!(
|
||||
|
@ -1616,6 +1695,7 @@ fn nested_pattern_match_two_ways() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_guarded_double_pattern_match() {
|
||||
// the important part here is that the first case (with the nested Cons) does not match
|
||||
// TODO this also has undefined behavior
|
||||
|
@ -1647,6 +1727,7 @@ fn linked_list_guarded_double_pattern_match() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn linked_list_double_pattern_match() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1672,6 +1753,7 @@ fn linked_list_double_pattern_match() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn binary_tree_double_pattern_match() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1697,6 +1779,7 @@ fn binary_tree_double_pattern_match() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn unified_empty_closure_bool() {
|
||||
// none of the Closure tags will have a payload
|
||||
// this was not handled correctly in the past
|
||||
|
@ -1721,6 +1804,7 @@ fn unified_empty_closure_bool() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn unified_empty_closure_byte() {
|
||||
// none of the Closure tags will have a payload
|
||||
// this was not handled correctly in the past
|
||||
|
@ -1746,6 +1830,7 @@ fn unified_empty_closure_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn task_always_twice() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1790,6 +1875,7 @@ fn task_always_twice() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn wildcard_rigid() {
|
||||
assert_non_opt_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1819,6 +1905,7 @@ fn wildcard_rigid() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn todo_bad_error_message() {
|
||||
assert_non_opt_evals_to!(
|
||||
|
@ -1866,6 +1953,7 @@ fn todo_bad_error_message() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn hof_conditional() {
|
||||
// exposed issue with the if condition being just a symbol
|
||||
assert_evals_to!(
|
||||
|
@ -1882,6 +1970,7 @@ fn hof_conditional() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(
|
||||
expected = "Roc failed with message: \"Shadowing { original_region: |L 3-3, C 4-5|, shadow: |L 6-6, C 8-9| Ident"
|
||||
)]
|
||||
|
@ -1901,6 +1990,7 @@ fn pattern_shadowing() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "TODO non-exhaustive pattern")]
|
||||
fn non_exhaustive_pattern_let() {
|
||||
assert_evals_to!(
|
||||
|
@ -1920,6 +2010,7 @@ fn non_exhaustive_pattern_let() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
#[should_panic(expected = "")]
|
||||
fn unsupported_pattern_str_interp() {
|
||||
|
@ -1937,6 +2028,7 @@ fn unsupported_pattern_str_interp() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn fingertree_basic() {
|
||||
assert_non_opt_evals_to!(
|
||||
|
@ -1978,6 +2070,7 @@ fn fingertree_basic() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn case_or_pattern() {
|
||||
// the `0` branch body should only be generated once in the future
|
||||
// it is currently duplicated
|
||||
|
@ -1998,6 +2091,7 @@ fn case_or_pattern() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn rosetree_basic() {
|
||||
assert_non_opt_evals_to!(
|
||||
|
@ -2025,6 +2119,7 @@ fn rosetree_basic() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn case_jump() {
|
||||
// the decision tree will generate a jump to the `1` branch here
|
||||
assert_evals_to!(
|
||||
|
@ -2050,6 +2145,7 @@ fn case_jump() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn nullable_eval_cfold() {
|
||||
// the decision tree will generate a jump to the `1` branch here
|
||||
assert_evals_to!(
|
||||
|
@ -2086,6 +2182,7 @@ fn nullable_eval_cfold() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn nested_switch() {
|
||||
// exposed bug with passing the right symbol/layout down into switch branch generation
|
||||
assert_evals_to!(
|
||||
|
@ -2128,6 +2225,7 @@ fn nested_switch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn count_deriv_x() {
|
||||
// exposed bug with basing the block_of_memory on a specific (smaller) tag layout
|
||||
assert_evals_to!(
|
||||
|
@ -2154,6 +2252,7 @@ fn count_deriv_x() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn deriv_pow() {
|
||||
// exposed bug with ordering of variable declarations before switch
|
||||
assert_evals_to!(
|
||||
|
@ -2190,6 +2289,7 @@ fn deriv_pow() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn multiple_increment() {
|
||||
// the `leaf` value will be incremented multiple times at once
|
||||
assert_evals_to!(
|
||||
|
@ -2223,6 +2323,7 @@ fn multiple_increment() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn switch_fuse_rc_non_exhaustive() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2252,6 +2353,7 @@ fn switch_fuse_rc_non_exhaustive() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn switch_fuse_rc_exhaustive() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2280,6 +2382,7 @@ fn switch_fuse_rc_exhaustive() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn build_then_apply_closure() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2299,6 +2402,7 @@ fn build_then_apply_closure() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn expanded_result() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2329,6 +2433,7 @@ fn expanded_result() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn backpassing_result() {
|
||||
assert_evals_to!(
|
||||
|
@ -2362,6 +2467,7 @@ fn backpassing_result() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[should_panic(
|
||||
expected = "Shadowing { original_region: |L 3-3, C 4-5|, shadow: |L 5-5, C 6-7| Ident"
|
||||
)]
|
||||
|
@ -2380,6 +2486,7 @@ fn function_malformed_pattern() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "Hit an erroneous type when creating a layout for")]
|
||||
fn call_invalid_layout() {
|
||||
assert_llvm_evals_to!(
|
||||
|
@ -2399,6 +2506,7 @@ fn call_invalid_layout() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "An expectation failed!")]
|
||||
fn expect_fail() {
|
||||
assert_evals_to!(
|
||||
|
@ -2415,6 +2523,7 @@ fn expect_fail() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn increment_or_double_closure() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2452,6 +2561,7 @@ fn increment_or_double_closure() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn module_thunk_is_function() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2468,6 +2578,7 @@ fn module_thunk_is_function() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "Roc failed with message: ")]
|
||||
fn hit_unresolved_type_variable() {
|
||||
assert_evals_to!(
|
||||
|
@ -2491,6 +2602,7 @@ fn hit_unresolved_type_variable() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn pattern_match_empty_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2510,6 +2622,7 @@ fn pattern_match_empty_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn pattern_match_unit_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2534,6 +2647,7 @@ fn pattern_match_unit_tag() {
|
|||
// see for why this is disabled on wasm32 https://github.com/rtfeldman/roc/issues/1687
|
||||
#[cfg(not(feature = "wasm-cli-run"))]
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn mirror_llvm_alignment_padding() {
|
||||
// see https://github.com/rtfeldman/roc/issues/1569
|
||||
assert_evals_to!(
|
||||
|
@ -2556,6 +2670,7 @@ fn mirror_llvm_alignment_padding() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn lambda_set_bool() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2580,6 +2695,7 @@ fn lambda_set_bool() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn lambda_set_byte() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2605,6 +2721,7 @@ fn lambda_set_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn lambda_set_struct_byte() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2632,6 +2749,7 @@ fn lambda_set_struct_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn lambda_set_enum_byte_byte() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2662,6 +2780,7 @@ fn lambda_set_enum_byte_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn list_walk_until() {
|
||||
// see https://github.com/rtfeldman/roc/issues/1576
|
||||
assert_evals_to!(
|
||||
|
@ -2687,6 +2806,7 @@ fn list_walk_until() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn int_literal_not_specialized_with_annotation() {
|
||||
// see https://github.com/rtfeldman/roc/issues/1600
|
||||
assert_evals_to!(
|
||||
|
@ -2714,6 +2834,7 @@ fn int_literal_not_specialized_with_annotation() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn int_literal_not_specialized_no_annotation() {
|
||||
// see https://github.com/rtfeldman/roc/issues/1600
|
||||
assert_evals_to!(
|
||||
|
@ -2740,6 +2861,7 @@ fn int_literal_not_specialized_no_annotation() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn unresolved_tvar_when_capture_is_unused() {
|
||||
// see https://github.com/rtfeldman/roc/issues/1585
|
||||
assert_evals_to!(
|
||||
|
@ -2766,6 +2888,7 @@ fn unresolved_tvar_when_capture_is_unused() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "Roc failed with message: ")]
|
||||
fn value_not_exposed_hits_panic() {
|
||||
assert_evals_to!(
|
||||
|
@ -2784,6 +2907,7 @@ fn value_not_exposed_hits_panic() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn mix_function_and_closure() {
|
||||
// see https://github.com/rtfeldman/roc/pull/1706
|
||||
assert_evals_to!(
|
||||
|
@ -2809,6 +2933,7 @@ fn mix_function_and_closure() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn mix_function_and_closure_level_of_indirection() {
|
||||
// see https://github.com/rtfeldman/roc/pull/1706
|
||||
assert_evals_to!(
|
||||
|
@ -2833,6 +2958,7 @@ fn mix_function_and_closure_level_of_indirection() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn do_pass_bool_byte_closure_layout() {
|
||||
// see https://github.com/rtfeldman/roc/pull/1706
|
||||
// the distinction is actually important, dropping that info means some functions just get
|
||||
|
@ -2908,6 +3034,7 @@ fn do_pass_bool_byte_closure_layout() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn nested_rigid_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2932,6 +3059,7 @@ fn nested_rigid_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn nested_rigid_alias() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2958,6 +3086,7 @@ fn nested_rigid_alias() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn nested_rigid_tag_union() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -2982,6 +3111,7 @@ fn nested_rigid_tag_union() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn call_that_needs_closure_parameter() {
|
||||
// here both p2 is lifted to the top-level, which means that `list` must be
|
||||
// passed to it from `manyAux`.
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
#![cfg(test)]
|
||||
#[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::assert_evals_to;
|
||||
// use crate::assert_wasm_evals_to as assert_evals_to;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn basic_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -38,6 +45,7 @@ fn basic_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn f64_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -77,6 +85,7 @@ fn f64_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn fn_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -128,6 +137,7 @@ fn fn_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn def_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -167,6 +177,7 @@ fn def_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn when_on_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -181,6 +192,7 @@ fn when_on_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn when_record_with_guard_pattern() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -195,6 +207,7 @@ fn when_record_with_guard_pattern() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn let_with_record_pattern() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -210,6 +223,7 @@ fn let_with_record_pattern() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn record_guard_pattern() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -225,6 +239,7 @@ fn record_guard_pattern() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn twice_record_access() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -239,6 +254,7 @@ fn twice_record_access() {
|
|||
);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-dev"))]
|
||||
fn empty_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -253,6 +269,7 @@ fn empty_record() {
|
|||
);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn i64_record2_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -266,6 +283,7 @@ fn i64_record2_literal() {
|
|||
}
|
||||
|
||||
// #[test]
|
||||
// #[cfg(any(feature = "gen-llvm"))]
|
||||
// fn i64_record3_literal() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -277,8 +295,8 @@ fn i64_record2_literal() {
|
|||
// (i64, i64, i64)
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn f64_record2_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -292,6 +310,7 @@ fn f64_record2_literal() {
|
|||
}
|
||||
|
||||
// #[test]
|
||||
// #[cfg(any(feature = "gen-llvm"))]
|
||||
// fn f64_record3_literal() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -305,6 +324,7 @@ fn f64_record2_literal() {
|
|||
// }
|
||||
|
||||
// #[test]
|
||||
// #[cfg(any(feature = "gen-llvm"))]
|
||||
// fn bool_record4_literal() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -319,8 +339,8 @@ fn f64_record2_literal() {
|
|||
// (bool, bool, bool, bool)
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn i64_record1_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -334,6 +354,7 @@ fn i64_record1_literal() {
|
|||
}
|
||||
|
||||
// #[test]
|
||||
// #[cfg(any(feature = "gen-llvm"))]
|
||||
// fn i64_record9_literal() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -347,6 +368,7 @@ fn i64_record1_literal() {
|
|||
// }
|
||||
|
||||
// #[test]
|
||||
// #[cfg(any(feature = "gen-llvm"))]
|
||||
// fn f64_record3_literal() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -358,8 +380,8 @@ fn i64_record1_literal() {
|
|||
// (f64, f64, f64)
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn bool_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -376,6 +398,7 @@ fn bool_literal() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -392,6 +415,7 @@ fn return_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn optional_field_when_use_default() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -419,6 +443,7 @@ fn optional_field_when_use_default() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn optional_field_when_use_default_nested() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -442,6 +467,7 @@ fn optional_field_when_use_default_nested() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn optional_field_when_no_use_default() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -462,6 +488,7 @@ fn optional_field_when_no_use_default() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn optional_field_when_no_use_default_nested() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -479,6 +506,7 @@ fn optional_field_when_no_use_default_nested() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn optional_field_let_use_default() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -499,6 +527,7 @@ fn optional_field_let_use_default() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn optional_field_let_no_use_default() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -519,6 +548,7 @@ fn optional_field_let_no_use_default() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn optional_field_let_no_use_default_nested() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -536,6 +566,7 @@ fn optional_field_let_no_use_default_nested() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn optional_field_function_use_default() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -552,6 +583,7 @@ fn optional_field_function_use_default() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn optional_field_function_no_use_default() {
|
||||
// blocked on https://github.com/rtfeldman/roc/issues/786
|
||||
|
@ -572,6 +604,7 @@ fn optional_field_function_no_use_default() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn optional_field_function_no_use_default_nested() {
|
||||
// blocked on https://github.com/rtfeldman/roc/issues/786
|
||||
|
@ -590,6 +623,7 @@ fn optional_field_function_no_use_default_nested() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn optional_field_singleton_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -604,6 +638,7 @@ fn optional_field_singleton_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn optional_field_empty_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -618,6 +653,7 @@ fn optional_field_empty_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record_2() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -631,6 +667,7 @@ fn return_record_2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record_3() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -644,6 +681,7 @@ fn return_record_3() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record_4() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -657,6 +695,7 @@ fn return_record_4() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record_5() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -670,6 +709,7 @@ fn return_record_5() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record_6() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -683,6 +723,7 @@ fn return_record_6() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record_7() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -696,6 +737,7 @@ fn return_record_7() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record_float_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -709,6 +751,7 @@ fn return_record_float_int() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record_int_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -722,6 +765,7 @@ fn return_record_int_float() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record_float_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -735,6 +779,7 @@ fn return_record_float_float() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_record_float_float_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -748,6 +793,7 @@ fn return_record_float_float_float() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn return_nested_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -761,11 +807,13 @@ fn return_nested_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn accessor_twice() {
|
||||
assert_evals_to!(".foo { foo: 4 } + .foo { bar: 6.28, foo: 3 } ", 7, i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn accessor_multi_element_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -779,6 +827,7 @@ fn accessor_multi_element_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn accessor_single_element_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -792,6 +841,7 @@ fn accessor_single_element_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn update_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -807,6 +857,7 @@ fn update_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn update_single_element_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -822,6 +873,7 @@ fn update_single_element_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn booleans_in_record() {
|
||||
assert_evals_to!(
|
||||
indoc!("{ x: 1 == 1, y: 1 == 1 }"),
|
||||
|
@ -846,6 +898,7 @@ fn booleans_in_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn alignment_in_record() {
|
||||
assert_evals_to!(
|
||||
indoc!("{ c: 32, b: if True then Red else if True then Green else Blue, a: 1 == 1 }"),
|
||||
|
@ -855,6 +908,7 @@ fn alignment_in_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn blue_and_present() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -873,6 +927,7 @@ fn blue_and_present() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn blue_and_absent() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -891,6 +946,7 @@ fn blue_and_absent() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn update_the_only_field() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
#![cfg(test)]
|
||||
#![cfg(feature = "gen-llvm")]
|
||||
|
||||
#[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::assert_evals_to;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn with_default() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -33,6 +42,7 @@ fn with_default() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn result_map() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -66,6 +76,7 @@ fn result_map() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn result_map_err() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -99,6 +110,7 @@ fn result_map_err() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn err_type_var() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -113,6 +125,7 @@ fn err_type_var() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn err_type_var_annotation() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -130,6 +143,7 @@ fn err_type_var_annotation() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn err_empty_tag_union() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
#![cfg(test)]
|
||||
#![cfg(feature = "gen-llvm")]
|
||||
|
||||
#[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::assert_evals_to;
|
||||
use indoc::indoc;
|
||||
use roc_std::RocList;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn empty_len() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -18,6 +27,7 @@ fn empty_len() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn single_len() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -31,6 +41,7 @@ fn single_len() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn single_to_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -64,6 +75,7 @@ fn single_to_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn insert() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -81,6 +93,7 @@ fn insert() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn remove() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -99,6 +112,7 @@ fn remove() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn union() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -119,6 +133,7 @@ fn union() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn difference() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -139,6 +154,7 @@ fn difference() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn intersection() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -159,6 +175,7 @@ fn intersection() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn walk_sum() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -172,6 +189,7 @@ fn walk_sum() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn contains() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -195,6 +213,7 @@ fn contains() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn from_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
|
@ -1,11 +1,22 @@
|
|||
#![cfg(test)]
|
||||
#![cfg(not(feature = "gen-wasm"))]
|
||||
|
||||
use crate::assert_evals_to;
|
||||
use crate::assert_llvm_evals_to;
|
||||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_evals_to;
|
||||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_llvm_evals_to;
|
||||
|
||||
#[cfg(feature = "gen-dev")]
|
||||
use crate::helpers::dev::assert_evals_to;
|
||||
#[cfg(feature = "gen-dev")]
|
||||
use crate::helpers::dev::assert_evals_to as assert_llvm_evals_to;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use indoc::indoc;
|
||||
#[allow(unused_imports)]
|
||||
use roc_std::{RocList, RocStr};
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_split_bigger_delimiter_small_str() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -35,6 +46,7 @@ fn str_split_bigger_delimiter_small_str() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_split_str_concat_repeated() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -58,6 +70,7 @@ fn str_split_str_concat_repeated() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_split_small_str_bigger_delimiter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -76,6 +89,7 @@ fn str_split_small_str_bigger_delimiter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_split_big_str_small_delimiter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -105,6 +119,7 @@ fn str_split_big_str_small_delimiter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_split_small_str_small_delimiter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -122,6 +137,7 @@ fn str_split_small_str_small_delimiter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_split_bigger_delimiter_big_strs() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -137,6 +153,7 @@ fn str_split_bigger_delimiter_big_strs() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_split_empty_strs() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -150,6 +167,7 @@ fn str_split_empty_strs() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_split_minimal_example() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -163,6 +181,7 @@ fn str_split_minimal_example() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_split_small_str_big_delimiter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -195,6 +214,7 @@ fn str_split_small_str_big_delimiter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_split_small_str_20_char_delimiter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -214,6 +234,7 @@ fn str_split_small_str_20_char_delimiter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_concat_big_to_big() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -229,6 +250,7 @@ fn str_concat_big_to_big() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn small_str_literal() {
|
||||
assert_llvm_evals_to!(
|
||||
"\"JJJJJJJJJJJJJJJ\"",
|
||||
|
@ -255,6 +277,7 @@ fn small_str_literal() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn small_str_zeroed_literal() {
|
||||
// Verifies that we zero out unused bytes in the string.
|
||||
// This is important so that string equality tests don't randomly
|
||||
|
@ -284,6 +307,7 @@ fn small_str_zeroed_literal() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn small_str_concat_empty_first_arg() {
|
||||
assert_llvm_evals_to!(
|
||||
r#"Str.concat "" "JJJJJJJJJJJJJJJ""#,
|
||||
|
@ -310,6 +334,7 @@ fn small_str_concat_empty_first_arg() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn small_str_concat_empty_second_arg() {
|
||||
assert_llvm_evals_to!(
|
||||
r#"Str.concat "JJJJJJJJJJJJJJJ" """#,
|
||||
|
@ -336,6 +361,7 @@ fn small_str_concat_empty_second_arg() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn small_str_concat_small_to_big() {
|
||||
assert_evals_to!(
|
||||
r#"Str.concat "abc" " this is longer than 15 chars""#,
|
||||
|
@ -345,6 +371,7 @@ fn small_str_concat_small_to_big() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn small_str_concat_small_to_small_staying_small() {
|
||||
assert_llvm_evals_to!(
|
||||
r#"Str.concat "J" "JJJJJJJJJJJJJJ""#,
|
||||
|
@ -371,6 +398,7 @@ fn small_str_concat_small_to_small_staying_small() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn small_str_concat_small_to_small_overflow_to_big() {
|
||||
assert_evals_to!(
|
||||
r#"Str.concat "abcdefghijklm" "nopqrstuvwxyz""#,
|
||||
|
@ -380,16 +408,19 @@ fn small_str_concat_small_to_small_overflow_to_big() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn str_concat_empty() {
|
||||
assert_evals_to!(r#"Str.concat "" """#, RocStr::default(), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn small_str_is_empty() {
|
||||
assert_evals_to!(r#"Str.isEmpty "abc""#, false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn big_str_is_empty() {
|
||||
assert_evals_to!(
|
||||
r#"Str.isEmpty "this is more than 15 chars long""#,
|
||||
|
@ -399,11 +430,13 @@ fn big_str_is_empty() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn empty_str_is_empty() {
|
||||
assert_evals_to!(r#"Str.isEmpty """#, true, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_starts_with() {
|
||||
assert_evals_to!(r#"Str.startsWith "hello world" "hell""#, true, bool);
|
||||
assert_evals_to!(r#"Str.startsWith "hello world" """#, true, bool);
|
||||
|
@ -413,6 +446,7 @@ fn str_starts_with() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_starts_with_code_point() {
|
||||
assert_evals_to!(
|
||||
&format!(r#"Str.startsWithCodePt "foobar" {}"#, 'f' as u32),
|
||||
|
@ -427,6 +461,7 @@ fn str_starts_with_code_point() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_ends_with() {
|
||||
assert_evals_to!(r#"Str.endsWith "hello world" "world""#, true, bool);
|
||||
assert_evals_to!(r#"Str.endsWith "nope" "hello world""#, false, bool);
|
||||
|
@ -434,16 +469,19 @@ fn str_ends_with() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_count_graphemes_small_str() {
|
||||
assert_evals_to!(r#"Str.countGraphemes "å🤔""#, 2, usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_count_graphemes_three_js() {
|
||||
assert_evals_to!(r#"Str.countGraphemes "JJJ""#, 3, usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_count_graphemes_big_str() {
|
||||
assert_evals_to!(
|
||||
r#"Str.countGraphemes "6🤔å🤔e¥🤔çppkd🙃1jdal🦯asdfa∆ltråø˚waia8918.,🏅jjc""#,
|
||||
|
@ -453,6 +491,7 @@ fn str_count_graphemes_big_str() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_starts_with_same_big_str() {
|
||||
assert_evals_to!(
|
||||
r#"Str.startsWith "123456789123456789" "123456789123456789""#,
|
||||
|
@ -462,6 +501,7 @@ fn str_starts_with_same_big_str() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_starts_with_different_big_str() {
|
||||
assert_evals_to!(
|
||||
r#"Str.startsWith "12345678912345678910" "123456789123456789""#,
|
||||
|
@ -471,20 +511,24 @@ fn str_starts_with_different_big_str() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_starts_with_same_small_str() {
|
||||
assert_evals_to!(r#"Str.startsWith "1234" "1234""#, true, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_starts_with_different_small_str() {
|
||||
assert_evals_to!(r#"Str.startsWith "1234" "12""#, true, bool);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_starts_with_false_small_str() {
|
||||
assert_evals_to!(r#"Str.startsWith "1234" "23""#, false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_int() {
|
||||
assert_evals_to!(
|
||||
r#"Str.fromInt 1234"#,
|
||||
|
@ -518,6 +562,7 @@ fn str_from_int() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_pass_single_ascii() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -533,6 +578,7 @@ fn str_from_utf8_pass_single_ascii() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_pass_many_ascii() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -548,6 +594,7 @@ fn str_from_utf8_pass_many_ascii() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_pass_single_unicode() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -563,6 +610,7 @@ fn str_from_utf8_pass_single_unicode() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_pass_many_unicode() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -578,6 +626,7 @@ fn str_from_utf8_pass_many_unicode() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_pass_single_grapheme() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -593,6 +642,7 @@ fn str_from_utf8_pass_single_grapheme() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_pass_many_grapheme() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -608,6 +658,7 @@ fn str_from_utf8_pass_many_grapheme() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_pass_all() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -623,6 +674,7 @@ fn str_from_utf8_pass_all() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_fail_invalid_start_byte() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -642,6 +694,7 @@ fn str_from_utf8_fail_invalid_start_byte() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -661,6 +714,7 @@ fn str_from_utf8_fail_unexpected_end_of_sequence() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_fail_expected_continuation() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -680,6 +734,7 @@ fn str_from_utf8_fail_expected_continuation() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_fail_overlong_encoding() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -699,6 +754,7 @@ fn str_from_utf8_fail_overlong_encoding() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_fail_codepoint_too_large() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -718,6 +774,7 @@ fn str_from_utf8_fail_codepoint_too_large() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_fail_surrogate_half() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -737,6 +794,7 @@ fn str_from_utf8_fail_surrogate_half() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_equality() {
|
||||
assert_evals_to!(r#""a" == "a""#, true, bool);
|
||||
assert_evals_to!(
|
||||
|
@ -761,6 +819,7 @@ fn str_clone() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn nested_recursive_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -791,6 +850,7 @@ fn nested_recursive_literal() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_join_comma_small() {
|
||||
assert_evals_to!(
|
||||
r#"Str.joinWith ["1", "2"] ", " "#,
|
||||
|
@ -800,6 +860,7 @@ fn str_join_comma_small() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_join_comma_big() {
|
||||
assert_evals_to!(
|
||||
r#"Str.joinWith ["10000000", "2000000", "30000000"] ", " "#,
|
||||
|
@ -809,16 +870,19 @@ fn str_join_comma_big() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_join_comma_single() {
|
||||
assert_evals_to!(r#"Str.joinWith ["1"] ", " "#, RocStr::from("1"), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_float() {
|
||||
assert_evals_to!(r#"Str.fromFloat 3.14"#, RocStr::from("3.14"), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_to_utf8() {
|
||||
assert_evals_to!(
|
||||
r#"Str.toUtf8 "hello""#,
|
||||
|
@ -836,6 +900,7 @@ fn str_to_utf8() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_range() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -852,6 +917,7 @@ fn str_from_utf8_range() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_range_slice() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -868,6 +934,7 @@ fn str_from_utf8_range_slice() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_range_slice_not_end() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -884,6 +951,7 @@ fn str_from_utf8_range_slice_not_end() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_range_order_does_not_matter() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -900,6 +968,7 @@ fn str_from_utf8_range_order_does_not_matter() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_range_out_of_bounds_start_value() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -917,6 +986,7 @@ fn str_from_utf8_range_out_of_bounds_start_value() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_range_count_too_high() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -934,6 +1004,7 @@ fn str_from_utf8_range_count_too_high() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_from_utf8_range_count_too_high_for_start() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -951,6 +1022,7 @@ fn str_from_utf8_range_count_too_high_for_start() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_repeat_small() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.repeat "Roc" 3"#),
|
||||
|
@ -960,6 +1032,7 @@ fn str_repeat_small() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_repeat_big() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.repeat "more than 16 characters" 2"#),
|
||||
|
@ -969,26 +1042,31 @@ fn str_repeat_big() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_repeat_empty_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.repeat "" 3"#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_repeat_zero_times() {
|
||||
assert_evals_to!(indoc!(r#"Str.repeat "Roc" 0"#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_empty_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trim """#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_small_blank_string() {
|
||||
assert_evals_to!(indoc!(r#"Str.trim " ""#), RocStr::from(""), RocStr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_small_to_small() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trim " hello world ""#),
|
||||
|
@ -998,6 +1076,7 @@ fn str_trim_small_to_small() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_large_to_large_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trim (Str.concat " " "hello world from a large string ")"#),
|
||||
|
@ -1007,6 +1086,7 @@ fn str_trim_large_to_large_unique() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_large_to_small_unique() {
|
||||
assert_evals_to!(
|
||||
indoc!(r#"Str.trim (Str.concat " " "hello world ")"#),
|
||||
|
@ -1016,6 +1096,7 @@ fn str_trim_large_to_small_unique() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_large_to_large_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1035,6 +1116,7 @@ fn str_trim_large_to_large_shared() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_large_to_small_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1054,6 +1136,7 @@ fn str_trim_large_to_small_shared() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn str_trim_small_to_small_shared() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
#![cfg(test)]
|
||||
#![cfg(feature = "gen-llvm")]
|
||||
|
||||
#[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::assert_evals_to;
|
||||
// use crate::assert_wasm_evals_to as assert_evals_to;
|
||||
use indoc::indoc;
|
||||
use roc_std::{RocList, RocStr};
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn width_and_alignment_u8_u8() {
|
||||
use roc_mono::layout::Builtin;
|
||||
use roc_mono::layout::Layout;
|
||||
|
@ -23,6 +32,7 @@ fn width_and_alignment_u8_u8() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn applied_tag_nothing_ir() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -42,6 +52,7 @@ fn applied_tag_nothing_ir() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn applied_tag_nothing() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -61,6 +72,7 @@ fn applied_tag_nothing() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn applied_tag_just() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -79,6 +91,7 @@ fn applied_tag_just() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn applied_tag_just_ir() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -97,6 +110,7 @@ fn applied_tag_just_ir() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn applied_tag_just_enum() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -120,6 +134,7 @@ fn applied_tag_just_enum() {
|
|||
}
|
||||
|
||||
// #[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
// fn raw_result() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -134,8 +149,8 @@ fn applied_tag_just_enum() {
|
|||
// i8
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn true_is_true() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -152,6 +167,7 @@ fn true_is_true() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn false_is_false() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -168,6 +184,7 @@ fn false_is_false() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn basic_enum() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -189,6 +206,7 @@ fn basic_enum() {
|
|||
}
|
||||
|
||||
// #[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
// fn linked_list_empty() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -207,6 +225,7 @@ fn basic_enum() {
|
|||
// }
|
||||
//
|
||||
// #[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
// fn linked_list_singleton() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -225,6 +244,7 @@ fn basic_enum() {
|
|||
// }
|
||||
//
|
||||
// #[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
// fn linked_list_is_empty() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
|
@ -244,8 +264,8 @@ fn basic_enum() {
|
|||
// bool
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn even_odd() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -271,6 +291,7 @@ fn even_odd() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn gen_literal_true() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -284,6 +305,7 @@ fn gen_literal_true() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn gen_if_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -296,6 +318,7 @@ fn gen_if_float() {
|
|||
);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn when_on_nothing() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -314,6 +337,7 @@ fn when_on_nothing() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn when_on_just() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -332,6 +356,7 @@ fn when_on_just() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn when_on_result() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -350,6 +375,7 @@ fn when_on_result() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn when_on_these() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -371,6 +397,7 @@ fn when_on_these() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn match_on_two_values() {
|
||||
// this will produce a Chain internally
|
||||
assert_evals_to!(
|
||||
|
@ -387,6 +414,7 @@ fn match_on_two_values() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn pair_with_guard_pattern() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -403,6 +431,7 @@ fn pair_with_guard_pattern() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn result_with_guard_pattern() {
|
||||
// This test revealed an issue with hashing Test values
|
||||
assert_evals_to!(
|
||||
|
@ -423,6 +452,7 @@ fn result_with_guard_pattern() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn maybe_is_just() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -447,6 +477,7 @@ fn maybe_is_just() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn maybe_is_just_nested() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -468,6 +499,7 @@ fn maybe_is_just_nested() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn nested_pattern_match() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -488,6 +520,7 @@ fn nested_pattern_match() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn if_guard_vanilla() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -503,6 +536,7 @@ fn if_guard_vanilla() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn when_on_single_value_tag() {
|
||||
// this fails because the switched-on symbol is not defined
|
||||
|
@ -520,6 +554,7 @@ fn when_on_single_value_tag() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn if_guard_multiple() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -540,6 +575,7 @@ fn if_guard_multiple() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn if_guard_constructor_switch() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -583,6 +619,7 @@ fn if_guard_constructor_switch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn if_guard_constructor_chain() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -599,6 +636,7 @@ fn if_guard_constructor_chain() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn if_guard_pattern_false() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -617,6 +655,7 @@ fn if_guard_pattern_false() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn if_guard_switch() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -635,6 +674,7 @@ fn if_guard_switch() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn if_guard_pattern_true() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -653,6 +693,7 @@ fn if_guard_pattern_true() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn if_guard_exhaustiveness() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -671,6 +712,7 @@ fn if_guard_exhaustiveness() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn when_on_enum() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -692,6 +734,7 @@ fn when_on_enum() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn pattern_matching_unit() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -750,6 +793,7 @@ fn pattern_matching_unit() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn one_element_tag() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -766,6 +810,7 @@ fn one_element_tag() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn nested_tag_union() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -786,6 +831,7 @@ fn nested_tag_union() {
|
|||
);
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn unit_type() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -804,6 +850,7 @@ fn unit_type() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn nested_record_load() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -821,6 +868,7 @@ fn nested_record_load() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn join_point_if() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -837,6 +885,7 @@ fn join_point_if() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn join_point_when() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -862,6 +911,7 @@ fn join_point_when() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn join_point_with_cond_expr() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -900,6 +950,7 @@ fn join_point_with_cond_expr() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn alignment_in_single_tag_construction() {
|
||||
assert_evals_to!(indoc!("Three (1 == 1) 32"), (32i64, true), (i64, bool));
|
||||
|
||||
|
@ -911,6 +962,7 @@ fn alignment_in_single_tag_construction() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn alignment_in_single_tag_pattern_match() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -942,6 +994,7 @@ fn alignment_in_single_tag_pattern_match() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn alignment_in_multi_tag_construction_two() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -959,6 +1012,7 @@ fn alignment_in_multi_tag_construction_two() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn alignment_in_multi_tag_construction_three() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -975,6 +1029,7 @@ fn alignment_in_multi_tag_construction_three() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn alignment_in_multi_tag_pattern_match() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1013,6 +1068,7 @@ fn alignment_in_multi_tag_pattern_match() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn phantom_polymorphic() {
|
||||
// see https://github.com/rtfeldman/roc/issues/786 and below
|
||||
|
@ -1038,6 +1094,7 @@ fn phantom_polymorphic() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[ignore]
|
||||
fn phantom_polymorphic_record() {
|
||||
// see https://github.com/rtfeldman/roc/issues/786
|
||||
|
@ -1065,6 +1122,7 @@ fn phantom_polymorphic_record() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn result_never() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1086,6 +1144,7 @@ fn result_never() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn nested_recursive_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1105,6 +1164,7 @@ fn nested_recursive_literal() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn newtype_wrapper() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1128,6 +1188,7 @@ fn newtype_wrapper() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn applied_tag_function() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1147,6 +1208,7 @@ fn applied_tag_function() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn applied_tag_function_result() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1166,6 +1228,7 @@ fn applied_tag_function_result() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn applied_tag_function_linked_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1186,6 +1249,7 @@ fn applied_tag_function_linked_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "")]
|
||||
fn tag_must_be_its_own_type() {
|
||||
assert_evals_to!(
|
||||
|
|
|
@ -210,7 +210,7 @@ pub fn helper(
|
|||
(main_fn_name, delayed_errors, lib)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty) => {{
|
||||
assert_evals_to!($src, $expected, $ty, (|val| val));
|
||||
|
@ -237,7 +237,7 @@ macro_rules! assert_evals_to {
|
|||
|
||||
let arena = Bump::new();
|
||||
let (main_fn_name, errors, lib) =
|
||||
$crate::helpers::eval::helper(&arena, $src, stdlib, $leak, $lazy_literals);
|
||||
$crate::helpers::dev::helper(&arena, $src, stdlib, $leak, $lazy_literals);
|
||||
|
||||
let transform = |success| {
|
||||
let expected = $expected;
|
||||
|
@ -247,3 +247,6 @@ macro_rules! assert_evals_to {
|
|||
run_jit_function_raw!(lib, main_fn_name, $ty, transform, errors)
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_evals_to;
|
|
@ -1,3 +1,4 @@
|
|||
use crate::helpers::from_wasm32_memory::FromWasm32Memory;
|
||||
use inkwell::module::Module;
|
||||
use libloading::Library;
|
||||
use roc_build::link::module_to_dylib;
|
||||
|
@ -10,7 +11,6 @@ use roc_module::symbol::Symbol;
|
|||
use roc_mono::ir::OptLevel;
|
||||
use roc_types::subs::VarStore;
|
||||
use target_lexicon::Triple;
|
||||
use test_wasm_util::from_wasm32_memory::FromWasm32Memory;
|
||||
|
||||
fn promote_expr_to_module(src: &str) -> String {
|
||||
let mut buffer = String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n");
|
||||
|
@ -469,7 +469,7 @@ where
|
|||
let stdlib = arena.alloc(roc_builtins::std::standard_stdlib());
|
||||
|
||||
let is_gen_test = true;
|
||||
let instance = crate::helpers::eval::helper_wasm(
|
||||
let instance = crate::helpers::llvm::helper_wasm(
|
||||
&arena,
|
||||
src,
|
||||
stdlib,
|
||||
|
@ -480,7 +480,7 @@ where
|
|||
|
||||
let memory = instance.exports.get_memory("memory").unwrap();
|
||||
|
||||
crate::helpers::eval::MEMORY.with(|f| {
|
||||
crate::helpers::llvm::MEMORY.with(|f| {
|
||||
*f.borrow_mut() = Some(unsafe { std::mem::transmute(memory) });
|
||||
});
|
||||
|
||||
|
@ -494,7 +494,7 @@ where
|
|||
_ => panic!(),
|
||||
};
|
||||
|
||||
let output = <T as crate::helpers::eval::FromWasm32Memory>::decode(
|
||||
let output = <T as crate::helpers::llvm::FromWasm32Memory>::decode(
|
||||
memory,
|
||||
// skip the RocCallResult tag id
|
||||
address as u32 + 8,
|
||||
|
@ -505,10 +505,10 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_wasm_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr, $ignore_problems:expr) => {
|
||||
match $crate::helpers::eval::assert_wasm_evals_to_help::<$ty>($src, $ignore_problems) {
|
||||
match $crate::helpers::llvm::assert_wasm_evals_to_help::<$ty>($src, $ignore_problems) {
|
||||
Err(msg) => panic!("Wasm test failed: {:?}", msg),
|
||||
Ok(actual) => {
|
||||
#[allow(clippy::bool_assert_comparison)]
|
||||
|
@ -518,15 +518,21 @@ macro_rules! assert_wasm_evals_to {
|
|||
};
|
||||
|
||||
($src:expr, $expected:expr, $ty:ty) => {
|
||||
$crate::assert_wasm_evals_to!($src, $expected, $ty, $crate::helpers::eval::identity, false);
|
||||
$crate::helpers::llvm::assert_wasm_evals_to!(
|
||||
$src,
|
||||
$expected,
|
||||
$ty,
|
||||
$crate::helpers::llvm::identity,
|
||||
false
|
||||
);
|
||||
};
|
||||
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr) => {
|
||||
$crate::assert_wasm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
$crate::helpers::llvm::assert_wasm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_llvm_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr, $ignore_problems:expr) => {
|
||||
use bumpalo::Bump;
|
||||
|
@ -540,7 +546,7 @@ macro_rules! assert_llvm_evals_to {
|
|||
let stdlib = arena.alloc(roc_builtins::std::standard_stdlib());
|
||||
|
||||
let is_gen_test = true;
|
||||
let (main_fn_name, errors, lib) = $crate::helpers::eval::helper(
|
||||
let (main_fn_name, errors, lib) = $crate::helpers::llvm::helper(
|
||||
&arena,
|
||||
$src,
|
||||
stdlib,
|
||||
|
@ -559,26 +565,32 @@ macro_rules! assert_llvm_evals_to {
|
|||
};
|
||||
|
||||
($src:expr, $expected:expr, $ty:ty) => {
|
||||
$crate::assert_llvm_evals_to!($src, $expected, $ty, $crate::helpers::eval::identity, false);
|
||||
$crate::helpers::llvm::assert_llvm_evals_to!(
|
||||
$src,
|
||||
$expected,
|
||||
$ty,
|
||||
$crate::helpers::llvm::identity,
|
||||
false
|
||||
);
|
||||
};
|
||||
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr) => {
|
||||
$crate::assert_llvm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
$crate::helpers::llvm::assert_llvm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty) => {{
|
||||
assert_evals_to!($src, $expected, $ty, $crate::helpers::eval::identity);
|
||||
assert_evals_to!($src, $expected, $ty, $crate::helpers::llvm::identity);
|
||||
}};
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr) => {
|
||||
// Same as above, except with an additional transformation argument.
|
||||
{
|
||||
#[cfg(feature = "wasm-cli-run")]
|
||||
$crate::assert_wasm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
$crate::helpers::llvm::assert_wasm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
|
||||
$crate::assert_llvm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
$crate::helpers::llvm::assert_llvm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -588,18 +600,32 @@ pub fn identity<T>(value: T) -> T {
|
|||
value
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_non_opt_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty) => {{
|
||||
$crate::assert_llvm_evals_to!($src, $expected, $ty, $crate::helpers::eval::identity);
|
||||
$crate::helpers::llvm::assert_llvm_evals_to!(
|
||||
$src,
|
||||
$expected,
|
||||
$ty,
|
||||
$crate::helpers::llvm::identity
|
||||
);
|
||||
}};
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr) => {
|
||||
// Same as above, except with an additional transformation argument.
|
||||
{
|
||||
$crate::assert_llvm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
$crate::helpers::llvm::assert_llvm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
}
|
||||
};
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr) => {{
|
||||
$crate::assert_llvm_evals_to!($src, $expected, $ty, $transform);
|
||||
$crate::helpers::llvm::assert_llvm_evals_to!($src, $expected, $ty, $transform);
|
||||
}};
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_llvm_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_non_opt_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_wasm_evals_to;
|
|
@ -1,7 +1,14 @@
|
|||
extern crate bumpalo;
|
||||
|
||||
#[macro_use]
|
||||
pub mod eval;
|
||||
#[cfg(feature = "gen-dev")]
|
||||
pub mod dev;
|
||||
pub mod from_wasm32_memory;
|
||||
#[cfg(feature = "gen-llvm")]
|
||||
pub mod llvm;
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
pub mod wasm;
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
pub mod wasm32_test_result;
|
||||
|
||||
/// Used in the with_larger_debug_stack() function, for tests that otherwise
|
||||
/// run out of stack space in debug builds (but don't in --release builds)
|
||||
|
|
|
@ -2,10 +2,10 @@ use std::cell::Cell;
|
|||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use crate::helpers::from_wasm32_memory::FromWasm32Memory;
|
||||
use crate::helpers::wasm32_test_result::Wasm32TestResult;
|
||||
use roc_can::builtins::builtin_defs_map;
|
||||
use roc_collections::all::{MutMap, MutSet};
|
||||
use test_wasm_util::from_wasm32_memory::FromWasm32Memory;
|
||||
|
||||
const TEST_WRAPPER_NAME: &str = "test_wrapper";
|
||||
|
||||
|
@ -112,7 +112,7 @@ pub fn helper_wasm<'a, T: Wasm32TestResult>(
|
|||
);
|
||||
|
||||
let mut module_bytes = std::vec::Vec::with_capacity(4096);
|
||||
wasm_module.serialize(&mut module_bytes);
|
||||
wasm_module.serialize_mut(&mut module_bytes);
|
||||
|
||||
// for debugging (e.g. with wasm2wat or wasm-objdump)
|
||||
if false {
|
||||
|
@ -169,9 +169,9 @@ where
|
|||
// NOTE the stdlib must be in the arena; just taking a reference will segfault
|
||||
let stdlib = arena.alloc(roc_builtins::std::standard_stdlib());
|
||||
|
||||
let instance = crate::helpers::eval::helper_wasm(&arena, src, stdlib, &expected);
|
||||
let instance = crate::helpers::wasm::helper_wasm(&arena, src, stdlib, &expected);
|
||||
|
||||
let memory = instance.exports.get_memory("memory").unwrap();
|
||||
let memory = instance.exports.get_memory("__linear_memory").unwrap();
|
||||
|
||||
let test_wrapper = instance.exports.get_function(TEST_WRAPPER_NAME).unwrap();
|
||||
|
||||
|
@ -190,10 +190,10 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_wasm_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr) => {
|
||||
match $crate::helpers::eval::assert_wasm_evals_to_help::<$ty>($src, $expected) {
|
||||
match $crate::helpers::wasm::assert_wasm_evals_to_help::<$ty>($src, $expected) {
|
||||
Err(msg) => panic!("{:?}", msg),
|
||||
Ok(actual) => {
|
||||
assert_eq!($transform(actual), $expected)
|
||||
|
@ -202,23 +202,28 @@ macro_rules! assert_wasm_evals_to {
|
|||
};
|
||||
|
||||
($src:expr, $expected:expr, $ty:ty) => {
|
||||
$crate::assert_wasm_evals_to!($src, $expected, $ty, $crate::helpers::eval::identity);
|
||||
$crate::helpers::wasm::assert_wasm_evals_to!(
|
||||
$src,
|
||||
$expected,
|
||||
$ty,
|
||||
$crate::helpers::wasm::identity
|
||||
);
|
||||
};
|
||||
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr) => {
|
||||
$crate::assert_wasm_evals_to!($src, $expected, $ty, $transform);
|
||||
$crate::helpers::wasm::assert_wasm_evals_to!($src, $expected, $ty, $transform);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty) => {{
|
||||
assert_evals_to!($src, $expected, $ty, $crate::helpers::eval::identity);
|
||||
assert_evals_to!($src, $expected, $ty, $crate::helpers::wasm::identity);
|
||||
}};
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr) => {
|
||||
// Same as above, except with an additional transformation argument.
|
||||
{
|
||||
$crate::assert_wasm_evals_to!($src, $expected, $ty, $transform);
|
||||
$crate::helpers::wasm::assert_wasm_evals_to!($src, $expected, $ty, $transform);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -227,3 +232,8 @@ macro_rules! assert_evals_to {
|
|||
pub fn identity<T>(value: T) -> T {
|
||||
value
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_wasm_evals_to;
|
|
@ -1,33 +1,42 @@
|
|||
use bumpalo::collections::Vec;
|
||||
|
||||
use roc_gen_wasm::wasm_module::opcodes;
|
||||
use crate::helpers::from_wasm32_memory::FromWasm32Memory;
|
||||
use roc_gen_wasm::wasm_module::{
|
||||
Align, CodeBuilder, Export, ExportType, LocalId, Signature, ValueType, WasmModule,
|
||||
linking::SymInfo, linking::WasmObjectSymbol, Align, CodeBuilder, Export, ExportType, LocalId,
|
||||
Signature, ValueType, WasmModule,
|
||||
};
|
||||
use roc_std::{RocDec, RocList, RocOrder, RocStr};
|
||||
use test_wasm_util::from_wasm32_memory::FromWasm32Memory;
|
||||
|
||||
pub trait Wasm32TestResult {
|
||||
fn insert_test_wrapper<'a>(
|
||||
arena: &'a bumpalo::Bump,
|
||||
wasm_module: &mut WasmModule<'a>,
|
||||
module: &mut WasmModule<'a>,
|
||||
wrapper_name: &str,
|
||||
main_function_index: u32,
|
||||
) {
|
||||
wasm_module.add_function_signature(Signature {
|
||||
let index = module.code.code_builders.len() as u32;
|
||||
|
||||
module.add_function_signature(Signature {
|
||||
param_types: Vec::with_capacity_in(0, arena),
|
||||
ret_type: Some(ValueType::I32),
|
||||
});
|
||||
|
||||
wasm_module.export.entries.push(Export {
|
||||
module.export.entries.push(Export {
|
||||
name: wrapper_name.to_string(),
|
||||
ty: ExportType::Func,
|
||||
index: wasm_module.code.code_builders.len() as u32,
|
||||
index,
|
||||
});
|
||||
|
||||
let symbol_table = module.linking.symbol_table_mut();
|
||||
symbol_table.push(SymInfo::Function(WasmObjectSymbol::Defined {
|
||||
flags: 0,
|
||||
index,
|
||||
name: wrapper_name.to_string(),
|
||||
}));
|
||||
|
||||
let mut code_builder = CodeBuilder::new(arena);
|
||||
Self::build_wrapper_body(&mut code_builder, main_function_index);
|
||||
wasm_module.code.code_builders.push(code_builder);
|
||||
module.code.code_builders.push(code_builder);
|
||||
}
|
||||
|
||||
fn build_wrapper_body(code_builder: &mut CodeBuilder, main_function_index: u32);
|
||||
|
@ -40,14 +49,15 @@ macro_rules! build_wrapper_body_primitive {
|
|||
let frame_pointer = Some(frame_pointer_id);
|
||||
let local_types = &[ValueType::I32];
|
||||
let frame_size = 8;
|
||||
// Main's symbol index is the same as its function index, since the first symbols we created were for procs
|
||||
let main_symbol_index = main_function_index;
|
||||
|
||||
code_builder.get_local(frame_pointer_id);
|
||||
// Raw "call" instruction. Don't bother with symbol & relocation since we're not going to link.
|
||||
code_builder.inst_imm32(opcodes::CALL, 0, true, main_function_index);
|
||||
code_builder.call(main_function_index, main_symbol_index, 0, true);
|
||||
code_builder.$store_instruction($align, 0);
|
||||
code_builder.get_local(frame_pointer_id);
|
||||
|
||||
code_builder.finalize(local_types, frame_size, frame_pointer);
|
||||
code_builder.build_fn_header(local_types, frame_size, frame_pointer);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -68,12 +78,13 @@ fn build_wrapper_body_stack_memory(
|
|||
let local_id = LocalId(0);
|
||||
let local_types = &[ValueType::I32];
|
||||
let frame_pointer = Some(local_id);
|
||||
// Main's symbol index is the same as its function index, since the first symbols we created were for procs
|
||||
let main_symbol_index = main_function_index;
|
||||
|
||||
code_builder.get_local(local_id);
|
||||
// Raw "call" instruction. Don't bother with symbol & relocation since we're not going to link.
|
||||
code_builder.inst_imm32(opcodes::CALL, 0, true, main_function_index);
|
||||
code_builder.call(main_function_index, main_symbol_index, 0, true);
|
||||
code_builder.get_local(local_id);
|
||||
code_builder.finalize(local_types, size as i32, frame_pointer);
|
||||
code_builder.build_fn_header(local_types, size as i32, frame_pointer);
|
||||
}
|
||||
|
||||
macro_rules! wasm_test_result_stack_memory {
|
||||
|
@ -101,6 +112,7 @@ wasm_test_result_primitive!(u32, i32_store, Align::Bytes4);
|
|||
wasm_test_result_primitive!(i32, i32_store, Align::Bytes4);
|
||||
wasm_test_result_primitive!(u64, i64_store, Align::Bytes8);
|
||||
wasm_test_result_primitive!(i64, i64_store, Align::Bytes8);
|
||||
wasm_test_result_primitive!(usize, i32_store, Align::Bytes4);
|
||||
|
||||
wasm_test_result_primitive!(f32, f32_store, Align::Bytes8);
|
||||
wasm_test_result_primitive!(f64, f64_store, Align::Bytes8);
|
|
@ -10,8 +10,48 @@ pub mod gen_list;
|
|||
pub mod gen_num;
|
||||
pub mod gen_primitives;
|
||||
pub mod gen_records;
|
||||
pub mod gen_result;
|
||||
pub mod gen_set;
|
||||
pub mod gen_str;
|
||||
pub mod gen_tags;
|
||||
mod helpers;
|
||||
pub mod wasm_str;
|
||||
|
||||
use core::ffi::c_void;
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
|
||||
libc::malloc(size)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_realloc(
|
||||
c_ptr: *mut c_void,
|
||||
new_size: usize,
|
||||
_old_size: usize,
|
||||
_alignment: u32,
|
||||
) -> *mut c_void {
|
||||
libc::realloc(c_ptr, new_size)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_dealloc(c_ptr: *mut c_void, _alignment: u32) {
|
||||
libc::free(c_ptr)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_panic(c_ptr: *mut c_void, tag_id: u32) {
|
||||
use roc_gen_llvm::llvm::build::PanicTagId;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
match PanicTagId::try_from(tag_id) {
|
||||
Ok(PanicTagId::NullTerminatedString) => {
|
||||
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);
|
||||
}
|
||||
Err(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
#![cfg(test)]
|
||||
// Wasm pointers are only 32bit. This effects RocStr.
|
||||
// These are versions of the str tests assuming 32bit pointers.
|
||||
#![cfg(not(feature = "gen-dev"))]
|
||||
|
||||
use crate::assert_evals_to;
|
||||
// TODO: We need to make these tests work with the llvm wasm backend.
|
||||
|
||||
// #[cfg(feature = "gen-llvm")]
|
||||
// use crate::helpers::llvm::assert_wasm_evals_to as assert_evals_to;
|
||||
|
||||
#[cfg(feature = "gen-wasm")]
|
||||
use crate::helpers::wasm::assert_evals_to;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use indoc::indoc;
|
||||
// use roc_std::RocStr;
|
||||
|
||||
|
@ -228,6 +238,7 @@ use indoc::indoc;
|
|||
// }
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-wasm"))]
|
||||
fn small_str_literal() {
|
||||
assert_evals_to!(
|
||||
"\"JJJJJJJ\"",
|
||||
|
@ -237,6 +248,7 @@ fn small_str_literal() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-wasm"))]
|
||||
fn small_str_zeroed_literal() {
|
||||
// Verifies that we zero out unused bytes in the string.
|
||||
// This is important so that string equality tests don't randomly
|
|
@ -1,30 +0,0 @@
|
|||
[package]
|
||||
name = "test_wasm"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[[test]]
|
||||
name = "test_wasm"
|
||||
path = "src/tests.rs"
|
||||
|
||||
[dev-dependencies]
|
||||
# roc_module = { path = "../module" }
|
||||
# roc_mono = { path = "../mono" }
|
||||
|
||||
wasmer = { version = "2.0.0", default-features = false, features = ["default-cranelift", "default-universal"] }
|
||||
wasmer-wasi = "2.0.0"
|
||||
|
||||
roc_collections = { path = "../collections" }
|
||||
roc_std = { path = "../../roc_std" }
|
||||
bumpalo = { version = "3.8.0", features = ["collections"] }
|
||||
roc_gen_wasm = { path = "../gen_wasm" }
|
||||
roc_can = { path = "../can" }
|
||||
roc_builtins = { path = "../builtins" }
|
||||
roc_load = { path = "../load" }
|
||||
roc_types = { path = "../types" }
|
||||
roc_module = { path = "../module" }
|
||||
test_wasm_util = { path = "../test_wasm_util" }
|
||||
indoc = "1.0.3"
|
||||
libc = "0.2.106"
|
||||
target-lexicon = "0.12.2"
|
|
@ -1,43 +0,0 @@
|
|||
#[macro_use]
|
||||
pub mod eval;
|
||||
pub mod wasm32_test_result;
|
||||
|
||||
/// Used in the with_larger_debug_stack() function, for tests that otherwise
|
||||
/// run out of stack space in debug builds (but don't in --release builds)
|
||||
#[allow(dead_code)]
|
||||
const EXPANDED_STACK_SIZE: usize = 8 * 1024 * 1024;
|
||||
|
||||
/// Without this, some tests pass in `cargo test --release` but fail without
|
||||
/// the --release flag because they run out of stack space. This increases
|
||||
/// stack size for debug builds only, while leaving the stack space at the default
|
||||
/// amount for release builds.
|
||||
#[allow(dead_code)]
|
||||
#[cfg(debug_assertions)]
|
||||
pub fn with_larger_debug_stack<F>(run_test: F)
|
||||
where
|
||||
F: FnOnce(),
|
||||
F: Send,
|
||||
F: 'static,
|
||||
{
|
||||
std::thread::Builder::new()
|
||||
.stack_size(EXPANDED_STACK_SIZE)
|
||||
.spawn(run_test)
|
||||
.expect("Error while spawning expanded dev stack size thread")
|
||||
.join()
|
||||
.expect("Error while joining expanded dev stack size thread")
|
||||
}
|
||||
|
||||
/// In --release builds, don't increase the stack size. Run the test normally.
|
||||
/// This way, we find out if any of our tests are blowing the stack even after
|
||||
/// optimizations in release builds.
|
||||
#[allow(dead_code)]
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[inline(always)]
|
||||
pub fn with_larger_debug_stack<F>(run_test: F)
|
||||
where
|
||||
F: FnOnce() -> (),
|
||||
F: Send,
|
||||
F: 'static,
|
||||
{
|
||||
run_test()
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
pub mod helpers;
|
||||
pub mod wasm_num;
|
||||
pub mod wasm_records;
|
||||
pub mod wasm_str;
|
File diff suppressed because it is too large
Load diff
|
@ -1,911 +0,0 @@
|
|||
#![cfg(all(test, target_os = "linux", any(target_arch = "x86_64"/*, target_arch = "aarch64"*/)))]
|
||||
use crate::assert_evals_to;
|
||||
use indoc::indoc;
|
||||
|
||||
// #[test]
|
||||
// fn basic_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { y: 17, x: 15, z: 19 }.x
|
||||
// "#
|
||||
// ),
|
||||
// 15,
|
||||
// i64
|
||||
// );
|
||||
//
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 15, y: 17, z: 19 }.y
|
||||
// "#
|
||||
// ),
|
||||
// 17,
|
||||
// i64
|
||||
// );
|
||||
//
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 15, y: 17, z: 19 }.z
|
||||
// "#
|
||||
// ),
|
||||
// 19,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn nested_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.x
|
||||
// "#
|
||||
// ),
|
||||
// 15,
|
||||
// i64
|
||||
// );
|
||||
//
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.y.a
|
||||
// "#
|
||||
// ),
|
||||
// 12,
|
||||
// i64
|
||||
// );
|
||||
//
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.y.b
|
||||
// "#
|
||||
// ),
|
||||
// 15,
|
||||
// i64
|
||||
// );
|
||||
//
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.y.c
|
||||
// "#
|
||||
// ),
|
||||
// 2,
|
||||
// i64
|
||||
// );
|
||||
//
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.z
|
||||
// "#
|
||||
// ),
|
||||
// 19,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn f64_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { y: 17.2, x: 15.1, z: 19.3 }
|
||||
//
|
||||
// rec.x
|
||||
// "#
|
||||
// ),
|
||||
// 15.1,
|
||||
// f64
|
||||
// );
|
||||
//
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { y: 17.2, x: 15.1, z: 19.3 }
|
||||
//
|
||||
// rec.y
|
||||
// "#
|
||||
// ),
|
||||
// 17.2,
|
||||
// f64
|
||||
// );
|
||||
//
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { y: 17.2, x: 15.1, z: 19.3 }
|
||||
//
|
||||
// rec.z
|
||||
// "#
|
||||
// ),
|
||||
// 19.3,
|
||||
// f64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fn_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// getRec = \x -> { y: 17, x, z: 19 }
|
||||
|
||||
// (getRec 15).x
|
||||
// "#
|
||||
// ),
|
||||
// 15,
|
||||
// i64
|
||||
// );
|
||||
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { x: 15, y: 17, z: 19 }
|
||||
|
||||
// rec.y
|
||||
// "#
|
||||
// ),
|
||||
// 17,
|
||||
// i64
|
||||
// );
|
||||
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { x: 15, y: 17, z: 19 }
|
||||
|
||||
// rec.z
|
||||
// "#
|
||||
// ),
|
||||
// 19,
|
||||
// i64
|
||||
// );
|
||||
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { x: 15, y: 17, z: 19 }
|
||||
|
||||
// rec.z + rec.x
|
||||
// "#
|
||||
// ),
|
||||
// 34,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn def_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { y: 17, x: 15, z: 19 }
|
||||
//
|
||||
// rec.x
|
||||
// "#
|
||||
// ),
|
||||
// 15,
|
||||
// i64
|
||||
// );
|
||||
//
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { x: 15, y: 17, z: 19 }
|
||||
//
|
||||
// rec.y
|
||||
// "#
|
||||
// ),
|
||||
// 17,
|
||||
// i64
|
||||
// );
|
||||
//
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { x: 15, y: 17, z: 19 }
|
||||
//
|
||||
// rec.z
|
||||
// "#
|
||||
// ),
|
||||
// 19,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn when_on_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when { x: 0x2 } is
|
||||
// { x } -> x + 3
|
||||
// "#
|
||||
// ),
|
||||
// 5,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn when_record_with_guard_pattern() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when { x: 0x2, y: 3.14 } is
|
||||
// { x: var } -> var + 3
|
||||
// "#
|
||||
// ),
|
||||
// 5,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn let_with_record_pattern() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { x } = { x: 0x2, y: 3.14 }
|
||||
//
|
||||
// x
|
||||
// "#
|
||||
// ),
|
||||
// 2,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn record_guard_pattern() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when { x: 0x2, y: 3.14 } is
|
||||
// { x: 0x4 } -> 5
|
||||
// { x } -> x + 3
|
||||
// "#
|
||||
// ),
|
||||
// 5,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn twice_record_access() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// x = {a: 0x2, b: 0x3 }
|
||||
//
|
||||
// x.a + x.b
|
||||
// "#
|
||||
// ),
|
||||
// 5,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
// #[test]
|
||||
// fn empty_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// v = {}
|
||||
//
|
||||
// v
|
||||
// "#
|
||||
// ),
|
||||
// (),
|
||||
// ()
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn i64_record1_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 3 }
|
||||
"#
|
||||
),
|
||||
3,
|
||||
i64
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn i64_record2_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 3, y: 5 }
|
||||
"#
|
||||
),
|
||||
(3, 5),
|
||||
(i64, i64)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn i64_record3_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 3, y: 5, z: 17 }
|
||||
"#
|
||||
),
|
||||
(3, 5, 17),
|
||||
(i64, i64, i64)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_record2_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 3.1, y: 5.1 }
|
||||
"#
|
||||
),
|
||||
(3.1, 5.1),
|
||||
(f64, f64)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_record3_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 3.1, y: 5.1, z: 17.1 }
|
||||
"#
|
||||
),
|
||||
(3.1, 5.1, 17.1),
|
||||
(f64, f64, f64)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bool_record4_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
record : { a : Bool, b : Bool, c : Bool, d : Bool }
|
||||
record = { a: True, b: False, c : False, d : True }
|
||||
|
||||
record
|
||||
"#
|
||||
),
|
||||
[true, false, false, true],
|
||||
[bool; 4]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn i64_record9_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ a: 3, b: 5, c: 17, d: 1, e: 9, f: 12, g: 13, h: 14, i: 15 }
|
||||
"#
|
||||
),
|
||||
[3, 5, 17, 1, 9, 12, 13, 14, 15],
|
||||
[i64; 9]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bool_literal() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Bool
|
||||
x = True
|
||||
|
||||
x
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_when_use_default() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// app "test" provides [ main ] to "./platform"
|
||||
|
||||
// f = \r ->
|
||||
// when r is
|
||||
// { x: Blue, y ? 3 } -> y
|
||||
// { x: Red, y ? 5 } -> y
|
||||
|
||||
// main =
|
||||
// a = f { x: Blue, y: 7 }
|
||||
// b = f { x: Blue }
|
||||
// c = f { x: Red, y: 11 }
|
||||
// d = f { x: Red }
|
||||
|
||||
// a * b * c * d
|
||||
// "#
|
||||
// ),
|
||||
// 3 * 5 * 7 * 11,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_when_use_default_nested() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \r ->
|
||||
// when r is
|
||||
// { x: Blue, y ? 3 } -> y
|
||||
// { x: Red, y ? 5 } -> y
|
||||
|
||||
// a = f { x: Blue, y: 7 }
|
||||
// b = f { x: Blue }
|
||||
// c = f { x: Red, y: 11 }
|
||||
// d = f { x: Red }
|
||||
|
||||
// a * b * c * d
|
||||
// "#
|
||||
// ),
|
||||
// 3 * 5 * 7 * 11,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_when_no_use_default() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// app "test" provides [ main ] to "./platform"
|
||||
|
||||
// f = \r ->
|
||||
// { x ? 10, y } = r
|
||||
// x + y
|
||||
|
||||
// main =
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_when_no_use_default_nested() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \r ->
|
||||
// { x ? 10, y } = r
|
||||
// x + y
|
||||
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_let_use_default() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// app "test" provides [ main ] to "./platform"
|
||||
|
||||
// f = \r ->
|
||||
// { x ? 10, y } = r
|
||||
// x + y
|
||||
|
||||
// main =
|
||||
// f { y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 19,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_let_no_use_default() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// app "test" provides [ main ] to "./platform"
|
||||
|
||||
// f = \r ->
|
||||
// { x ? 10, y } = r
|
||||
// x + y
|
||||
|
||||
// main =
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_let_no_use_default_nested() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \r ->
|
||||
// { x ? 10, y } = r
|
||||
// x + y
|
||||
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_function_use_default() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \{ x ? 10, y } -> x + y
|
||||
|
||||
// f { y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 19,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// #[ignore]
|
||||
// fn optional_field_function_no_use_default() {
|
||||
// // blocked on https://github.com/rtfeldman/roc/issues/786
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// app "test" provides [ main ] to "./platform"
|
||||
|
||||
// f = \{ x ? 10, y } -> x + y
|
||||
|
||||
// main =
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// #[ignore]
|
||||
// fn optional_field_function_no_use_default_nested() {
|
||||
// // blocked on https://github.com/rtfeldman/roc/issues/786
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \{ x ? 10, y } -> x + y
|
||||
|
||||
// f { x: 4, y: 9 }
|
||||
// "#
|
||||
// ),
|
||||
// 13,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_singleton_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when { x : 4 } is
|
||||
// { x ? 3 } -> x
|
||||
// "#
|
||||
// ),
|
||||
// 4,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional_field_empty_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// when { } is
|
||||
// { x ? 3 } -> x
|
||||
// "#
|
||||
// ),
|
||||
// 3,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn return_record_3() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x: 3, y: 5, z: 4 }
|
||||
"#
|
||||
),
|
||||
(3, 5, 4),
|
||||
(i64, i64, i64)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_record_4() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ a: 3, b: 5, c: 4, d: 2 }
|
||||
"#
|
||||
),
|
||||
[3, 5, 4, 2],
|
||||
[i64; 4]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_record_5() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ a: 3, b: 5, c: 4, d: 2, e: 1 }
|
||||
"#
|
||||
),
|
||||
[3, 5, 4, 2, 1],
|
||||
[i64; 5]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_record_6() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ a: 3, b: 5, c: 4, d: 2, e: 1, f: 7 }
|
||||
"#
|
||||
),
|
||||
[3, 5, 4, 2, 1, 7],
|
||||
[i64; 6]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_record_7() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ a: 3, b: 5, c: 4, d: 2, e: 1, f: 7, g: 8 }
|
||||
"#
|
||||
),
|
||||
[3, 5, 4, 2, 1, 7, 8],
|
||||
[i64; 7]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_record_float_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ a: 3.14, b: 0x1 }
|
||||
"#
|
||||
),
|
||||
(3.14, 0x1),
|
||||
(f64, i64)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_record_int_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ a: 0x1, b: 3.14 }
|
||||
"#
|
||||
),
|
||||
(0x1, 3.14),
|
||||
(i64, f64)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_record_float_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ a: 6.28, b: 3.14 }
|
||||
"#
|
||||
),
|
||||
(6.28, 3.14),
|
||||
(f64, f64)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_record_float_float_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
{ a: 6.28, b: 3.14, c: 0.1 }
|
||||
"#
|
||||
),
|
||||
(6.28, 3.14, 0.1),
|
||||
(f64, f64, f64)
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn return_nested_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// { flag: 0x0, payload: { a: 6.28, b: 3.14, c: 0.1 } }
|
||||
// "#
|
||||
// ),
|
||||
// (0x0, (6.28, 3.14, 0.1)),
|
||||
// (i64, (f64, f64, f64))
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn accessor() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// .foo { foo: 4 } + .foo { bar: 6.28, foo: 3 }
|
||||
// "#
|
||||
// ),
|
||||
// 7,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn accessor_single_element_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// .foo { foo: 4 }
|
||||
// "#
|
||||
// ),
|
||||
// 4,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn update_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { foo: 42, bar: 6 }
|
||||
|
||||
// { rec & foo: rec.foo + 1 }
|
||||
// "#
|
||||
// ),
|
||||
// (6, 43),
|
||||
// (i64, i64)
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn update_single_element_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// rec = { foo: 42}
|
||||
|
||||
// { rec & foo: rec.foo + 1 }
|
||||
// "#
|
||||
// ),
|
||||
// 43,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn booleans_in_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!("{ x: 1 == 1, y: 1 == 1 }"),
|
||||
// (true, true),
|
||||
// (bool, bool)
|
||||
// );
|
||||
// assert_evals_to!(
|
||||
// indoc!("{ x: 1 != 1, y: 1 == 1 }"),
|
||||
// (false, true),
|
||||
// (bool, bool)
|
||||
// );
|
||||
// assert_evals_to!(
|
||||
// indoc!("{ x: 1 == 1, y: 1 != 1 }"),
|
||||
// (true, false),
|
||||
// (bool, bool)
|
||||
// );
|
||||
// assert_evals_to!(
|
||||
// indoc!("{ x: 1 != 1, y: 1 != 1 }"),
|
||||
// (false, false),
|
||||
// (bool, bool)
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn alignment_in_record() {
|
||||
// assert_evals_to!(
|
||||
// indoc!("{ c: 32, b: if True then Red else if True then Green else Blue, a: 1 == 1 }"),
|
||||
// (32i64, true, 2u8),
|
||||
// (i64, bool, u8)
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn stack_memory_return_from_branch() {
|
||||
// stack memory pointer should end up in the right place after returning from a branch
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
stackMemoryJunk = { x: 999, y: 111 }
|
||||
if True then
|
||||
{ x: 123, y: 321 }
|
||||
else
|
||||
stackMemoryJunk
|
||||
"#
|
||||
),
|
||||
(123, 321),
|
||||
(i64, i64)
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn blue_and_present() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \r ->
|
||||
// when r is
|
||||
// { x: Blue, y ? 3 } -> y
|
||||
// { x: Red, y ? 5 } -> y
|
||||
|
||||
// f { x: Blue, y: 7 }
|
||||
// "#
|
||||
// ),
|
||||
// 7,
|
||||
// i64
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn blue_and_absent() {
|
||||
// assert_evals_to!(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// f = \r ->
|
||||
// when r is
|
||||
// { x: Blue, y ? 3 } -> y
|
||||
// { x: Red, y ? 5 } -> y
|
||||
|
||||
// f { x: Blue }
|
||||
// "#
|
||||
// ),
|
||||
// 3,
|
||||
// i64
|
||||
// );
|
||||
// }
|
1055
compiler/test_wasm_util/Cargo.lock
generated
1055
compiler/test_wasm_util/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,13 +0,0 @@
|
|||
[package]
|
||||
name = "test_wasm_util"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[dependencies]
|
||||
# roc_module = { path = "../module" }
|
||||
# roc_mono = { path = "../mono" }
|
||||
|
||||
wasmer = { version = "2.0.0", default-features = false, features = ["default-cranelift", "default-universal"] }
|
||||
|
||||
roc_std = { path = "../../roc_std" }
|
|
@ -1 +0,0 @@
|
|||
pub mod from_wasm32_memory;
|
Loading…
Add table
Add a link
Reference in a new issue