diff --git a/compiler/test_gen/src/gen_dict.rs b/compiler/test_gen/src/gen_dict.rs index 2e2df034ca..b53da1133a 100644 --- a/compiler/test_gen/src/gen_dict.rs +++ b/compiler/test_gen/src/gen_dict.rs @@ -1,522 +1,511 @@ -#[macro_use] -extern crate pretty_assertions; -#[macro_use] -extern crate indoc; +#![cfg(test)] -extern crate bumpalo; -extern crate inkwell; -extern crate libc; -extern crate roc_gen; +use crate::assert_evals_to; +use crate::assert_llvm_evals_to; +use indoc::indoc; +use roc_std::RocStr; -#[macro_use] -mod helpers; - -#[cfg(test)] -mod gen_dict { - use roc_std::RocStr; - - #[test] - fn dict_empty_len() { - assert_evals_to!( - indoc!( - r#" - Dict.len Dict.empty - "# - ), - 0, - usize - ); - } - - #[test] - fn dict_insert_empty() { - assert_evals_to!( - indoc!( - r#" - Dict.insert Dict.empty 42 32 - |> Dict.len - "# - ), - 1, - usize - ); - } - - #[test] - fn dict_empty_contains() { - assert_evals_to!( - indoc!( - r#" - empty : Dict I64 F64 - empty = Dict.empty - - Dict.contains empty 42 - "# - ), - false, - bool - ); - } - - #[test] - fn dict_nonempty_contains() { - assert_evals_to!( - indoc!( - r#" - empty : Dict I64 F64 - empty = Dict.insert Dict.empty 42 3.14 - - Dict.contains empty 42 - "# - ), - true, - bool - ); - } - - #[test] - fn dict_empty_remove() { - assert_evals_to!( - indoc!( - r#" - empty : Dict I64 F64 - empty = Dict.empty - - empty - |> Dict.remove 42 - |> Dict.len - "# - ), - 0, - i64 - ); - } - - #[test] - fn dict_nonempty_remove() { - assert_evals_to!( - indoc!( - r#" - empty : Dict I64 F64 - empty = Dict.insert Dict.empty 42 3.14 - - empty - |> Dict.remove 42 - |> Dict.len - "# - ), - 0, - i64 - ); - } - - #[test] - fn dict_nonempty_get() { - assert_evals_to!( - indoc!( - r#" - empty : Dict I64 F64 - empty = Dict.insert Dict.empty 42 3.14 - - withDefault = \x, def -> - when x is - Ok v -> v - Err _ -> def - - empty - |> Dict.insert 42 3.14 - |> Dict.get 42 - |> withDefault 0 - "# - ), - 3.14, - f64 - ); - - assert_evals_to!( - indoc!( - r#" - withDefault = \x, def -> - when x is - Ok v -> v - Err _ -> def - - Dict.empty - |> Dict.insert 42 3.14 - |> Dict.get 43 - |> withDefault 0 - "# - ), - 0.0, - f64 - ); - } - - #[test] - fn keys() { - assert_evals_to!( - indoc!( - r#" - myDict : Dict I64 I64 - myDict = - Dict.empty - |> Dict.insert 0 100 - |> Dict.insert 1 100 - |> Dict.insert 2 100 - - - Dict.keys myDict - "# - ), - &[0, 1, 2], - &[i64] - ); - } - - #[test] - fn values() { - assert_evals_to!( - indoc!( - r#" - myDict : Dict I64 I64 - myDict = - Dict.empty - |> Dict.insert 0 100 - |> Dict.insert 1 200 - |> Dict.insert 2 300 - - - Dict.values myDict - "# - ), - &[100, 200, 300], - &[i64] - ); - } - - #[test] - fn from_list_with_fold() { - assert_evals_to!( - indoc!( - r#" - myDict : Dict I64 I64 - myDict = - [1,2,3] - |> List.walk (\value, accum -> Dict.insert accum value value) Dict.empty - - Dict.values myDict - "# - ), - &[2, 3, 1], - &[i64] - ); - - assert_evals_to!( - indoc!( - r#" - range : I64, I64, List I64-> List I64 - range = \low, high, accum -> - if low < high then - range (low + 1) high (List.append accum low) - else - accum - - myDict : Dict I64 I64 - myDict = - # 25 elements (8 + 16 + 1) is guaranteed to overflow/reallocate at least twice - range 0 25 [] - |> List.walk (\value, accum -> Dict.insert accum value value) Dict.empty - - Dict.values myDict - |> List.len - "# - ), - 25, - i64 - ); - } - - #[test] - fn small_str_keys() { - assert_evals_to!( - indoc!( - r#" - myDict : Dict Str I64 - myDict = - Dict.empty - |> Dict.insert "a" 100 - |> Dict.insert "b" 100 - |> Dict.insert "c" 100 - - - Dict.keys myDict - "# - ), - &[RocStr::from("c"), RocStr::from("a"), RocStr::from("b"),], - &[RocStr] - ); - } - - #[test] - fn big_str_keys() { - assert_evals_to!( - indoc!( - r#" - myDict : Dict Str I64 - myDict = - Dict.empty - |> Dict.insert "Leverage agile frameworks to provide a robust" 100 - |> Dict.insert "synopsis for high level overviews. Iterative approaches" 200 - |> Dict.insert "to corporate strategy foster collaborative thinking to" 300 - - - Dict.keys myDict - "# - ), - &[ - RocStr::from("Leverage agile frameworks to provide a robust"), - RocStr::from("to corporate strategy foster collaborative thinking to"), - RocStr::from("synopsis for high level overviews. Iterative approaches"), - ], - &[RocStr] - ); - } - - #[test] - fn big_str_values() { - assert_evals_to!( - indoc!( - r#" - myDict : Dict I64 Str - myDict = - Dict.empty - |> Dict.insert 100 "Leverage agile frameworks to provide a robust" - |> Dict.insert 200 "synopsis for high level overviews. Iterative approaches" - |> Dict.insert 300 "to corporate strategy foster collaborative thinking to" - - Dict.values myDict - "# - ), - &[ - RocStr::from("Leverage agile frameworks to provide a robust"), - RocStr::from("to corporate strategy foster collaborative thinking to"), - RocStr::from("synopsis for high level overviews. Iterative approaches"), - ], - &[RocStr] - ); - } - - #[test] - fn unit_values() { - assert_evals_to!( - indoc!( - r#" - myDict : Dict I64 {} - myDict = - Dict.empty - |> Dict.insert 0 {} - |> Dict.insert 1 {} - |> Dict.insert 2 {} - |> Dict.insert 3 {} - - Dict.len myDict - "# - ), - 4, - i64 - ); - } - - #[test] - fn singleton() { - assert_evals_to!( - indoc!( - r#" - myDict : Dict I64 {} - myDict = - Dict.singleton 0 {} - - Dict.len myDict - "# - ), - 1, - i64 - ); - } - - #[test] - fn union() { - assert_evals_to!( - indoc!( - r#" - myDict : Dict I64 {} - myDict = - Dict.union (Dict.singleton 0 {}) (Dict.singleton 1 {}) - - Dict.len myDict - "# - ), - 2, - i64 - ); - } - - #[test] - fn union_prefer_first() { - assert_evals_to!( - indoc!( - r#" - myDict : Dict I64 I64 - myDict = - Dict.union (Dict.singleton 0 100) (Dict.singleton 0 200) - - Dict.values myDict - "# - ), - &[100], - &[i64] - ); - } - - #[test] - fn intersection() { - assert_evals_to!( - indoc!( - r#" - dict1 : Dict I64 {} - dict1 = - Dict.empty - |> Dict.insert 1 {} - |> Dict.insert 2 {} - |> Dict.insert 3 {} - |> Dict.insert 4 {} - |> Dict.insert 5 {} - - dict2 : Dict I64 {} - dict2 = - Dict.empty - |> Dict.insert 0 {} - |> Dict.insert 2 {} - |> Dict.insert 4 {} - - Dict.intersection dict1 dict2 - |> Dict.len - "# - ), - 2, - i64 - ); - } - - #[test] - fn intersection_prefer_first() { - assert_evals_to!( - indoc!( - r#" - dict1 : Dict I64 I64 - dict1 = - Dict.empty - |> Dict.insert 1 1 - |> Dict.insert 2 2 - |> Dict.insert 3 3 - |> Dict.insert 4 4 - |> Dict.insert 5 5 - - dict2 : Dict I64 I64 - dict2 = - Dict.empty - |> Dict.insert 0 100 - |> Dict.insert 2 200 - |> Dict.insert 4 300 - - Dict.intersection dict1 dict2 - |> Dict.values - "# - ), - &[4, 2], - &[i64] - ); - } - - #[test] - fn difference() { - assert_evals_to!( - indoc!( - r#" - dict1 : Dict I64 {} - dict1 = - Dict.empty - |> Dict.insert 1 {} - |> Dict.insert 2 {} - |> Dict.insert 3 {} - |> Dict.insert 4 {} - |> Dict.insert 5 {} - - dict2 : Dict I64 {} - dict2 = - Dict.empty - |> Dict.insert 0 {} - |> Dict.insert 2 {} - |> Dict.insert 4 {} - - Dict.difference dict1 dict2 - |> Dict.len - "# - ), - 3, - i64 - ); - } - - #[test] - fn difference_prefer_first() { - assert_evals_to!( - indoc!( - r#" - dict1 : Dict I64 I64 - dict1 = - Dict.empty - |> Dict.insert 1 1 - |> Dict.insert 2 2 - |> Dict.insert 3 3 - |> Dict.insert 4 4 - |> Dict.insert 5 5 - - dict2 : Dict I64 I64 - dict2 = - Dict.empty - |> Dict.insert 0 100 - |> Dict.insert 2 200 - |> Dict.insert 4 300 - - Dict.difference dict1 dict2 - |> Dict.values - "# - ), - &[5, 3, 1], - &[i64] - ); - } - - #[test] - fn walk_sum_keys() { - assert_evals_to!( - indoc!( - r#" - dict1 : Dict I64 I64 - dict1 = - Dict.empty - |> Dict.insert 1 1 - |> Dict.insert 2 2 - |> Dict.insert 3 3 - |> Dict.insert 4 4 - |> Dict.insert 5 5 - - Dict.walk dict1 (\k, _, a -> k + a) 0 - "# - ), - 15, - i64 - ); - } +#[test] +fn dict_empty_len() { + assert_evals_to!( + indoc!( + r#" + Dict.len Dict.empty + "# + ), + 0, + usize + ); +} + +#[test] +fn dict_insert_empty() { + assert_evals_to!( + indoc!( + r#" + Dict.insert Dict.empty 42 32 + |> Dict.len + "# + ), + 1, + usize + ); +} + +#[test] +fn dict_empty_contains() { + assert_evals_to!( + indoc!( + r#" + empty : Dict I64 F64 + empty = Dict.empty + + Dict.contains empty 42 + "# + ), + false, + bool + ); +} + +#[test] +fn dict_nonempty_contains() { + assert_evals_to!( + indoc!( + r#" + empty : Dict I64 F64 + empty = Dict.insert Dict.empty 42 3.14 + + Dict.contains empty 42 + "# + ), + true, + bool + ); +} + +#[test] +fn dict_empty_remove() { + assert_evals_to!( + indoc!( + r#" + empty : Dict I64 F64 + empty = Dict.empty + + empty + |> Dict.remove 42 + |> Dict.len + "# + ), + 0, + i64 + ); +} + +#[test] +fn dict_nonempty_remove() { + assert_evals_to!( + indoc!( + r#" + empty : Dict I64 F64 + empty = Dict.insert Dict.empty 42 3.14 + + empty + |> Dict.remove 42 + |> Dict.len + "# + ), + 0, + i64 + ); +} + +#[test] +fn dict_nonempty_get() { + assert_evals_to!( + indoc!( + r#" + empty : Dict I64 F64 + empty = Dict.insert Dict.empty 42 3.14 + + withDefault = \x, def -> + when x is + Ok v -> v + Err _ -> def + + empty + |> Dict.insert 42 3.14 + |> Dict.get 42 + |> withDefault 0 + "# + ), + 3.14, + f64 + ); + + assert_evals_to!( + indoc!( + r#" + withDefault = \x, def -> + when x is + Ok v -> v + Err _ -> def + + Dict.empty + |> Dict.insert 42 3.14 + |> Dict.get 43 + |> withDefault 0 + "# + ), + 0.0, + f64 + ); +} + +#[test] +fn keys() { + assert_evals_to!( + indoc!( + r#" + myDict : Dict I64 I64 + myDict = + Dict.empty + |> Dict.insert 0 100 + |> Dict.insert 1 100 + |> Dict.insert 2 100 + + + Dict.keys myDict + "# + ), + &[0, 1, 2], + &[i64] + ); +} + +#[test] +fn values() { + assert_evals_to!( + indoc!( + r#" + myDict : Dict I64 I64 + myDict = + Dict.empty + |> Dict.insert 0 100 + |> Dict.insert 1 200 + |> Dict.insert 2 300 + + + Dict.values myDict + "# + ), + &[100, 200, 300], + &[i64] + ); +} + +#[test] +fn from_list_with_fold() { + assert_evals_to!( + indoc!( + r#" + myDict : Dict I64 I64 + myDict = + [1,2,3] + |> List.walk (\value, accum -> Dict.insert accum value value) Dict.empty + + Dict.values myDict + "# + ), + &[2, 3, 1], + &[i64] + ); + + assert_evals_to!( + indoc!( + r#" + range : I64, I64, List I64-> List I64 + range = \low, high, accum -> + if low < high then + range (low + 1) high (List.append accum low) + else + accum + + myDict : Dict I64 I64 + myDict = + # 25 elements (8 + 16 + 1) is guaranteed to overflow/reallocate at least twice + range 0 25 [] + |> List.walk (\value, accum -> Dict.insert accum value value) Dict.empty + + Dict.values myDict + |> List.len + "# + ), + 25, + i64 + ); +} + +#[test] +fn small_str_keys() { + assert_evals_to!( + indoc!( + r#" + myDict : Dict Str I64 + myDict = + Dict.empty + |> Dict.insert "a" 100 + |> Dict.insert "b" 100 + |> Dict.insert "c" 100 + + + Dict.keys myDict + "# + ), + &[RocStr::from("c"), RocStr::from("a"), RocStr::from("b"),], + &[RocStr] + ); +} + +#[test] +fn big_str_keys() { + assert_evals_to!( + indoc!( + r#" + myDict : Dict Str I64 + myDict = + Dict.empty + |> Dict.insert "Leverage agile frameworks to provide a robust" 100 + |> Dict.insert "synopsis for high level overviews. Iterative approaches" 200 + |> Dict.insert "to corporate strategy foster collaborative thinking to" 300 + + + Dict.keys myDict + "# + ), + &[ + RocStr::from("Leverage agile frameworks to provide a robust"), + RocStr::from("to corporate strategy foster collaborative thinking to"), + RocStr::from("synopsis for high level overviews. Iterative approaches"), + ], + &[RocStr] + ); +} + +#[test] +fn big_str_values() { + assert_evals_to!( + indoc!( + r#" + myDict : Dict I64 Str + myDict = + Dict.empty + |> Dict.insert 100 "Leverage agile frameworks to provide a robust" + |> Dict.insert 200 "synopsis for high level overviews. Iterative approaches" + |> Dict.insert 300 "to corporate strategy foster collaborative thinking to" + + Dict.values myDict + "# + ), + &[ + RocStr::from("Leverage agile frameworks to provide a robust"), + RocStr::from("to corporate strategy foster collaborative thinking to"), + RocStr::from("synopsis for high level overviews. Iterative approaches"), + ], + &[RocStr] + ); +} + +#[test] +fn unit_values() { + assert_evals_to!( + indoc!( + r#" + myDict : Dict I64 {} + myDict = + Dict.empty + |> Dict.insert 0 {} + |> Dict.insert 1 {} + |> Dict.insert 2 {} + |> Dict.insert 3 {} + + Dict.len myDict + "# + ), + 4, + i64 + ); +} + +#[test] +fn singleton() { + assert_evals_to!( + indoc!( + r#" + myDict : Dict I64 {} + myDict = + Dict.singleton 0 {} + + Dict.len myDict + "# + ), + 1, + i64 + ); +} + +#[test] +fn union() { + assert_evals_to!( + indoc!( + r#" + myDict : Dict I64 {} + myDict = + Dict.union (Dict.singleton 0 {}) (Dict.singleton 1 {}) + + Dict.len myDict + "# + ), + 2, + i64 + ); +} + +#[test] +fn union_prefer_first() { + assert_evals_to!( + indoc!( + r#" + myDict : Dict I64 I64 + myDict = + Dict.union (Dict.singleton 0 100) (Dict.singleton 0 200) + + Dict.values myDict + "# + ), + &[100], + &[i64] + ); +} + +#[test] +fn intersection() { + assert_evals_to!( + indoc!( + r#" + dict1 : Dict I64 {} + dict1 = + Dict.empty + |> Dict.insert 1 {} + |> Dict.insert 2 {} + |> Dict.insert 3 {} + |> Dict.insert 4 {} + |> Dict.insert 5 {} + + dict2 : Dict I64 {} + dict2 = + Dict.empty + |> Dict.insert 0 {} + |> Dict.insert 2 {} + |> Dict.insert 4 {} + + Dict.intersection dict1 dict2 + |> Dict.len + "# + ), + 2, + i64 + ); +} + +#[test] +fn intersection_prefer_first() { + assert_evals_to!( + indoc!( + r#" + dict1 : Dict I64 I64 + dict1 = + Dict.empty + |> Dict.insert 1 1 + |> Dict.insert 2 2 + |> Dict.insert 3 3 + |> Dict.insert 4 4 + |> Dict.insert 5 5 + + dict2 : Dict I64 I64 + dict2 = + Dict.empty + |> Dict.insert 0 100 + |> Dict.insert 2 200 + |> Dict.insert 4 300 + + Dict.intersection dict1 dict2 + |> Dict.values + "# + ), + &[4, 2], + &[i64] + ); +} + +#[test] +fn difference() { + assert_evals_to!( + indoc!( + r#" + dict1 : Dict I64 {} + dict1 = + Dict.empty + |> Dict.insert 1 {} + |> Dict.insert 2 {} + |> Dict.insert 3 {} + |> Dict.insert 4 {} + |> Dict.insert 5 {} + + dict2 : Dict I64 {} + dict2 = + Dict.empty + |> Dict.insert 0 {} + |> Dict.insert 2 {} + |> Dict.insert 4 {} + + Dict.difference dict1 dict2 + |> Dict.len + "# + ), + 3, + i64 + ); +} + +#[test] +fn difference_prefer_first() { + assert_evals_to!( + indoc!( + r#" + dict1 : Dict I64 I64 + dict1 = + Dict.empty + |> Dict.insert 1 1 + |> Dict.insert 2 2 + |> Dict.insert 3 3 + |> Dict.insert 4 4 + |> Dict.insert 5 5 + + dict2 : Dict I64 I64 + dict2 = + Dict.empty + |> Dict.insert 0 100 + |> Dict.insert 2 200 + |> Dict.insert 4 300 + + Dict.difference dict1 dict2 + |> Dict.values + "# + ), + &[5, 3, 1], + &[i64] + ); +} + +#[test] +fn walk_sum_keys() { + assert_evals_to!( + indoc!( + r#" + dict1 : Dict I64 I64 + dict1 = + Dict.empty + |> Dict.insert 1 1 + |> Dict.insert 2 2 + |> Dict.insert 3 3 + |> Dict.insert 4 4 + |> Dict.insert 5 5 + + Dict.walk dict1 (\k, _, a -> k + a) 0 + "# + ), + 15, + i64 + ); } diff --git a/compiler/test_gen/src/gen_hash.rs b/compiler/test_gen/src/gen_hash.rs index bc90cc8ba2..45614a033f 100644 --- a/compiler/test_gen/src/gen_hash.rs +++ b/compiler/test_gen/src/gen_hash.rs @@ -1,157 +1,146 @@ -#[macro_use] -extern crate pretty_assertions; -#[macro_use] -extern crate indoc; +#![cfg(test)] -extern crate bumpalo; -extern crate inkwell; -extern crate libc; -extern crate roc_gen; +use crate::assert_evals_to; +use crate::assert_llvm_evals_to; +use indoc::indoc; -#[macro_use] -mod helpers; - -#[cfg(test)] -mod gen_hash { - - #[test] - fn basic_hash() { - assert_evals_to!( - indoc!( - r#" - Dict.hashTestOnly 0 0 - "# - ), - 9718519427346233646, - u64 - ); - } - - #[test] - fn hash_str_with_seed() { - assert_evals_to!("Dict.hashTestOnly 1 \"a\"", 0xbed235177f41d328, u64); - assert_evals_to!("Dict.hashTestOnly 2 \"abc\"", 0xbe348debe59b27c3, u64); - } - - #[test] - fn hash_record() { - assert_evals_to!("Dict.hashTestOnly 1 { x: \"a\" } ", 0xbed235177f41d328, u64); - assert_evals_to!( - "Dict.hashTestOnly 1 { x: 42, y: 3.14 } ", - 5348189196103430707, - u64 - ); - } - - #[test] - fn hash_result() { - assert_evals_to!( - "Dict.hashTestOnly 0 (List.get [ 0x1 ] 0) ", - 2878521786781103245, - u64 - ); - } - - #[test] - fn hash_linked_list() { - assert_evals_to!( - indoc!( - r#" - LinkedList a : [ Nil, Cons a (LinkedList a) ] - - input : LinkedList I64 - input = Nil - - Dict.hashTestOnly 0 input - "# - ), - 0, - u64 - ); - - assert_evals_to!( - indoc!( - r#" - LinkedList a : [ Nil, Cons a (LinkedList a) ] - - input : LinkedList I64 - input = Cons 4 (Cons 3 Nil) - - Dict.hashTestOnly 0 input - "# - ), - 8287696503006938486, - u64 - ); - } - - #[test] - fn hash_expr() { - assert_evals_to!( - indoc!( - r#" - Expr : [ Add Expr Expr, Mul Expr Expr, Val I64, Var I64 ] - - x : Expr - x = Val 1 - - Dict.hashTestOnly 0 (Add x x) - "# - ), - 18264046914072177411, - u64 - ); - } - - #[test] - fn hash_nullable_expr() { - assert_evals_to!( - indoc!( - r#" - Expr : [ Add Expr Expr, Mul Expr Expr, Val I64, Empty ] - - x : Expr - x = Val 1 - - Dict.hashTestOnly 0 (Add x x) - "# - ), - 11103255846683455235, - u64 - ); - } - - #[test] - fn hash_rosetree() { - assert_evals_to!( - indoc!( - r#" - Rose a : [ Rose (List (Rose a)) ] - - x : Rose I64 - x = Rose [] - - Dict.hashTestOnly 0 x - "# - ), - 0, - u64 - ); - } - - #[test] - fn hash_list() { - assert_evals_to!( - indoc!( - r#" - x : List Str - x = [ "foo", "bar", "baz" ] - - Dict.hashTestOnly 0 x - "# - ), - 10731521034618280801, - u64 - ); - } +#[test] +fn basic_hash() { + assert_evals_to!( + indoc!( + r#" + Dict.hashTestOnly 0 0 + "# + ), + 9718519427346233646, + u64 + ); +} + +#[test] +fn hash_str_with_seed() { + assert_evals_to!("Dict.hashTestOnly 1 \"a\"", 0xbed235177f41d328, u64); + assert_evals_to!("Dict.hashTestOnly 2 \"abc\"", 0xbe348debe59b27c3, u64); +} + +#[test] +fn hash_record() { + assert_evals_to!("Dict.hashTestOnly 1 { x: \"a\" } ", 0xbed235177f41d328, u64); + assert_evals_to!( + "Dict.hashTestOnly 1 { x: 42, y: 3.14 } ", + 5348189196103430707, + u64 + ); +} + +#[test] +fn hash_result() { + assert_evals_to!( + "Dict.hashTestOnly 0 (List.get [ 0x1 ] 0) ", + 2878521786781103245, + u64 + ); +} + +#[test] +fn hash_linked_list() { + assert_evals_to!( + indoc!( + r#" + LinkedList a : [ Nil, Cons a (LinkedList a) ] + + input : LinkedList I64 + input = Nil + + Dict.hashTestOnly 0 input + "# + ), + 0, + u64 + ); + + assert_evals_to!( + indoc!( + r#" + LinkedList a : [ Nil, Cons a (LinkedList a) ] + + input : LinkedList I64 + input = Cons 4 (Cons 3 Nil) + + Dict.hashTestOnly 0 input + "# + ), + 8287696503006938486, + u64 + ); +} + +#[test] +fn hash_expr() { + assert_evals_to!( + indoc!( + r#" + Expr : [ Add Expr Expr, Mul Expr Expr, Val I64, Var I64 ] + + x : Expr + x = Val 1 + + Dict.hashTestOnly 0 (Add x x) + "# + ), + 18264046914072177411, + u64 + ); +} + +#[test] +fn hash_nullable_expr() { + assert_evals_to!( + indoc!( + r#" + Expr : [ Add Expr Expr, Mul Expr Expr, Val I64, Empty ] + + x : Expr + x = Val 1 + + Dict.hashTestOnly 0 (Add x x) + "# + ), + 11103255846683455235, + u64 + ); +} + +#[test] +fn hash_rosetree() { + assert_evals_to!( + indoc!( + r#" + Rose a : [ Rose (List (Rose a)) ] + + x : Rose I64 + x = Rose [] + + Dict.hashTestOnly 0 x + "# + ), + 0, + u64 + ); +} + +#[test] +fn hash_list() { + assert_evals_to!( + indoc!( + r#" + x : List Str + x = [ "foo", "bar", "baz" ] + + Dict.hashTestOnly 0 x + "# + ), + 10731521034618280801, + u64 + ); } diff --git a/compiler/test_gen/src/gen_list.rs b/compiler/test_gen/src/gen_list.rs index 60adc5cf02..e1a48a4bdd 100644 --- a/compiler/test_gen/src/gen_list.rs +++ b/compiler/test_gen/src/gen_list.rs @@ -1,1186 +1,1148 @@ -#[macro_use] -extern crate pretty_assertions; -#[macro_use] -extern crate indoc; +#![cfg(test)] -extern crate bumpalo; -extern crate inkwell; -extern crate libc; -extern crate roc_gen; +use crate::assert_evals_to; +use crate::assert_llvm_evals_to; +use crate::helpers::with_larger_debug_stack; +use indoc::indoc; +use roc_std::{RocList, RocStr}; -#[macro_use] -mod helpers; +#[test] +fn roc_list_construction() { + let list = RocList::from_slice(&[1i64; 23]); + assert_eq!(&list, &list); +} -#[cfg(test)] -mod gen_list { - use crate::helpers::with_larger_debug_stack; - use roc_std::{RocList, RocStr}; +#[test] +fn empty_list_literal() { + assert_evals_to!("[]", RocList::from_slice(&[]), RocList); +} - #[test] - fn roc_list_construction() { - let list = RocList::from_slice(&[1i64; 23]); - assert_eq!(&list, &list); - } +#[test] +fn list_literal_empty_record() { + assert_evals_to!("[{}]", RocList::from_slice(&[()]), RocList<()>); +} - #[test] - fn empty_list_literal() { - assert_evals_to!("[]", RocList::from_slice(&[]), RocList); - } +#[test] +fn int_singleton_list_literal() { + assert_evals_to!("[1, 2]", RocList::from_slice(&[1, 2]), RocList); +} - #[test] - fn list_literal_empty_record() { - assert_evals_to!("[{}]", RocList::from_slice(&[()]), RocList<()>); - } +#[test] +fn int_list_literal() { + assert_evals_to!("[ 12, 9 ]", RocList::from_slice(&[12, 9]), RocList); + assert_evals_to!( + "[ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ]", + RocList::from_slice(&[1i64; 23]), + RocList + ); +} - #[test] - fn int_singleton_list_literal() { - assert_evals_to!("[1, 2]", RocList::from_slice(&[1, 2]), RocList); - } +#[test] +fn bool_list_literal() { + // NOTE: make sure to explicitly declare the elements to be of type bool, or + // use both True and False; only using one of them causes the list to in practice be + // of type `List [ True ]` or `List [ False ]`, those are tag unions with one constructor + // and not fields, and don't have a runtime representation. + assert_evals_to!( + indoc!( + r#" + false : Bool + false = False - #[test] - fn int_list_literal() { - assert_evals_to!("[ 12, 9 ]", RocList::from_slice(&[12, 9]), RocList); - assert_evals_to!( - "[ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ]", - RocList::from_slice(&[1i64; 23]), - RocList - ); - } + [ false ] + "# + ), + RocList::from_slice(&[false; 1]), + RocList + ); - #[test] - fn bool_list_literal() { - // NOTE: make sure to explicitly declare the elements to be of type bool, or - // use both True and False; only using one of them causes the list to in practice be - // of type `List [ True ]` or `List [ False ]`, those are tag unions with one constructor - // and not fields, and don't have a runtime representation. - assert_evals_to!( - indoc!( - r#" - false : Bool - false = False + assert_evals_to!( + "[ True, False, True ]", + RocList::from_slice(&[true, false, true]), + RocList + ); - [ false ] - "# - ), - RocList::from_slice(&[false; 1]), - RocList - ); + assert_evals_to!( + indoc!( + r#" + false : Bool + false = False - assert_evals_to!( - "[ True, False, True ]", - RocList::from_slice(&[true, false, true]), - RocList - ); + [false ] + "# + ), + RocList::from_slice(&[false; 1]), + RocList + ); - assert_evals_to!( - indoc!( - r#" - false : Bool - false = False + assert_evals_to!( + indoc!( + r#" + true : Bool + true = True - [false ] - "# - ), - RocList::from_slice(&[false; 1]), - RocList - ); + List.repeat 23 true + "# + ), + RocList::from_slice(&[true; 23]), + RocList + ); - assert_evals_to!( - indoc!( - r#" - true : Bool - true = True + assert_evals_to!( + indoc!( + r#" + true : Bool + true = True - List.repeat 23 true - "# - ), - RocList::from_slice(&[true; 23]), - RocList - ); + List.repeat 23 { x: true, y: true } + "# + ), + RocList::from_slice(&[[true, true]; 23]), + RocList<[bool; 2]> + ); - assert_evals_to!( - indoc!( - r#" - true : Bool - true = True + assert_evals_to!( + indoc!( + r#" + true : Bool + true = True - List.repeat 23 { x: true, y: true } - "# - ), - RocList::from_slice(&[[true, true]; 23]), - RocList<[bool; 2]> - ); + List.repeat 23 { x: true, y: true, a: true, b: true, c: true, d : true, e: true, f: true } + "# + ), + RocList::from_slice(&[[true, true, true, true, true, true, true, true]; 23]), + RocList<[bool; 8]> + ); +} - assert_evals_to!( - indoc!( - r#" - true : Bool - true = True +#[test] +fn variously_sized_list_literals() { + assert_evals_to!("[]", RocList::from_slice(&[]), RocList); + assert_evals_to!("[1]", RocList::from_slice(&[1]), RocList); + assert_evals_to!("[1, 2]", RocList::from_slice(&[1, 2]), RocList); + assert_evals_to!("[1, 2, 3]", RocList::from_slice(&[1, 2, 3]), RocList); + assert_evals_to!( + "[1, 2, 3, 4]", + RocList::from_slice(&[1, 2, 3, 4]), + RocList + ); + assert_evals_to!( + "[1, 2, 3, 4, 5]", + RocList::from_slice(&[1, 2, 3, 4, 5]), + RocList + ); +} - List.repeat 23 { x: true, y: true, a: true, b: true, c: true, d : true, e: true, f: true } - "# - ), - RocList::from_slice(&[[true, true, true, true, true, true, true, true]; 23]), - RocList<[bool; 8]> - ); - } +#[test] +fn list_append() { + assert_evals_to!( + "List.append [1] 2", + RocList::from_slice(&[1, 2]), + RocList + ); + assert_evals_to!( + "List.append [1, 1] 2", + RocList::from_slice(&[1, 1, 2]), + RocList + ); +} - #[test] - fn variously_sized_list_literals() { - assert_evals_to!("[]", RocList::from_slice(&[]), RocList); - assert_evals_to!("[1]", RocList::from_slice(&[1]), RocList); - assert_evals_to!("[1, 2]", RocList::from_slice(&[1, 2]), RocList); - assert_evals_to!("[1, 2, 3]", RocList::from_slice(&[1, 2, 3]), RocList); - assert_evals_to!( - "[1, 2, 3, 4]", - RocList::from_slice(&[1, 2, 3, 4]), - RocList - ); - assert_evals_to!( - "[1, 2, 3, 4, 5]", - RocList::from_slice(&[1, 2, 3, 4, 5]), - RocList - ); - } +#[test] +fn list_append_to_empty_list() { + assert_evals_to!("List.append [] 3", RocList::from_slice(&[3]), RocList); +} - #[test] - fn list_append() { - assert_evals_to!( - "List.append [1] 2", - RocList::from_slice(&[1, 2]), - RocList - ); - assert_evals_to!( - "List.append [1, 1] 2", - RocList::from_slice(&[1, 1, 2]), - RocList - ); - } +#[test] +fn list_append_to_empty_list_of_int() { + assert_evals_to!( + indoc!( + r#" + initThrees : List I64 + initThrees = + [] - #[test] - fn list_append_to_empty_list() { - assert_evals_to!("List.append [] 3", RocList::from_slice(&[3]), RocList); - } + List.append (List.append initThrees 3) 3 + "# + ), + RocList::from_slice(&[3, 3]), + RocList + ); +} - #[test] - fn list_append_to_empty_list_of_int() { - assert_evals_to!( - indoc!( - r#" - initThrees : List I64 - initThrees = - [] +#[test] +fn list_append_bools() { + assert_evals_to!( + "List.append [ True, False ] True", + RocList::from_slice(&[true, false, true]), + RocList + ); +} - List.append (List.append initThrees 3) 3 - "# - ), - RocList::from_slice(&[3, 3]), - RocList - ); - } +#[test] +fn list_append_longer_list() { + assert_evals_to!( + "List.append [ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 ] 23", + RocList::from_slice(&[11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]), + RocList + ); +} - #[test] - fn list_append_bools() { - assert_evals_to!( - "List.append [ True, False ] True", - RocList::from_slice(&[true, false, true]), - RocList - ); - } +#[test] +fn list_prepend() { + assert_evals_to!("List.prepend [] 1", RocList::from_slice(&[1]), RocList); + assert_evals_to!( + "List.prepend [2] 1", + RocList::from_slice(&[1, 2]), + RocList + ); - #[test] - fn list_append_longer_list() { - assert_evals_to!( - "List.append [ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 ] 23", - RocList::from_slice(&[11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]), - RocList - ); - } + assert_evals_to!( + indoc!( + r#" + init : List I64 + init = + [] - #[test] - fn list_prepend() { - assert_evals_to!("List.prepend [] 1", RocList::from_slice(&[1]), RocList); - assert_evals_to!( - "List.prepend [2] 1", - RocList::from_slice(&[1, 2]), - RocList - ); + List.prepend (List.prepend init 4) 6 + "# + ), + RocList::from_slice(&[6, 4]), + RocList + ); +} - assert_evals_to!( - indoc!( - r#" - init : List I64 - init = - [] +#[test] +fn list_prepend_bools() { + assert_evals_to!( + "List.prepend [ True, False ] True", + RocList::from_slice(&[true, true, false]), + RocList + ); +} - List.prepend (List.prepend init 4) 6 - "# - ), - RocList::from_slice(&[6, 4]), - RocList - ); - } +#[test] +fn list_prepend_big_list() { + assert_evals_to!( + "List.prepend [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100 ] 9", + RocList::from_slice(&[ + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100 + ]), + RocList + ); +} - #[test] - fn list_prepend_bools() { - assert_evals_to!( - "List.prepend [ True, False ] True", - RocList::from_slice(&[true, true, false]), - RocList - ); - } +#[test] +fn list_walk_backwards_empty_all_inline() { + assert_evals_to!( + indoc!( + r#" + List.walkBackwards [0x1] (\a, b -> a + b) 0 + "# + ), + 1, + i64 + ); - #[test] - fn list_prepend_big_list() { - assert_evals_to!( - "List.prepend [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100 ] 9", - RocList::from_slice(&[ - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100 - ]), - RocList - ); - } + assert_evals_to!( + indoc!( + r#" + empty : List I64 + empty = + [] - #[test] - fn list_walk_backwards_empty_all_inline() { - assert_evals_to!( - indoc!( - r#" - List.walkBackwards [0x1] (\a, b -> a + b) 0 - "# - ), - 1, - i64 - ); + List.walkBackwards empty (\a, b -> a + b) 0 + "# + ), + 0, + i64 + ); +} - assert_evals_to!( - indoc!( - r#" - empty : List I64 +#[test] +fn list_walk_backwards_with_str() { + assert_evals_to!( + r#"List.walkBackwards [ "x", "y", "z" ] Str.concat "<""#, + RocStr::from("xyz<"), + RocStr + ); + + assert_evals_to!( + r#"List.walkBackwards [ "Third", "Second", "First" ] Str.concat "Fourth""#, + RocStr::from("ThirdSecondFirstFourth"), + RocStr + ); +} + +#[test] +fn list_walk_backwards_with_record() { + assert_evals_to!( + indoc!( + r#" + Bit : [ Zero, One ] + + byte : List Bit + byte = [ Zero, One, Zero, One, Zero, Zero, One, Zero ] + + initialCounts = { zeroes: 0, ones: 0 } + + acc = \b, r -> + when b is + Zero -> { r & zeroes: r.zeroes + 1 } + One -> { r & ones: r.ones + 1 } + + finalCounts = List.walkBackwards byte acc initialCounts + + finalCounts.ones * 10 + finalCounts.zeroes + "# + ), + 35, + i64 + ); +} + +#[test] +fn list_walk_with_str() { + assert_evals_to!( + r#"List.walk [ "x", "y", "z" ] Str.concat "<""#, + RocStr::from("zyx<"), + RocStr + ); + + assert_evals_to!( + r#"List.walk [ "Third", "Second", "First" ] Str.concat "Fourth""#, + RocStr::from("FirstSecondThirdFourth"), + RocStr + ); +} + +#[test] +fn list_walk_substraction() { + assert_evals_to!(r#"List.walk [ 1, 2 ] Num.sub 1"#, 2, i64); +} + +#[test] +fn list_keep_if_empty_list_of_int() { + assert_evals_to!( + indoc!( + r#" + empty : List I64 + empty = + [] + + List.keepIf empty (\_ -> True) + "# + ), + RocList::from_slice(&[]), + RocList + ); +} + +#[test] +fn list_keep_if_empty_list() { + assert_evals_to!( + indoc!( + r#" + alwaysTrue : I64 -> Bool + alwaysTrue = \_ -> + True + + + List.keepIf [] alwaysTrue + "# + ), + RocList::from_slice(&[]), + RocList + ); +} + +#[test] +fn list_keep_if_always_true_for_non_empty_list() { + assert_evals_to!( + indoc!( + r#" + alwaysTrue : I64 -> Bool + alwaysTrue = \_ -> + True + + oneThroughEight : List I64 + oneThroughEight = + [1,2,3,4,5,6,7,8] + + List.keepIf oneThroughEight alwaysTrue + "# + ), + RocList::from_slice(&[1, 2, 3, 4, 5, 6, 7, 8]), + RocList + ); +} + +#[test] +fn list_keep_if_always_false_for_non_empty_list() { + assert_evals_to!( + indoc!( + r#" + alwaysFalse : I64 -> Bool + alwaysFalse = \_ -> + False + + List.keepIf [1,2,3,4,5,6,7,8] alwaysFalse + "# + ), + RocList::from_slice(&[]), + RocList + ); +} + +#[test] +fn list_keep_if_one() { + assert_evals_to!( + indoc!( + r#" + intIsLessThanThree : I64 -> Bool + intIsLessThanThree = \i -> + i < 3 + + List.keepIf [1,2,3,4,5,6,7,8] intIsLessThanThree + "# + ), + RocList::from_slice(&[1, 2]), + RocList + ); +} + +#[test] +fn list_keep_if_str_is_hello() { + assert_evals_to!( + indoc!( + r#" + List.keepIf ["x", "y", "x"] (\x -> x == "x") + "# + ), + RocList::from_slice(&[ + RocStr::from_slice("x".as_bytes()), + RocStr::from_slice("x".as_bytes()) + ]), + RocList + ); +} + +#[test] +fn list_map_on_empty_list_with_int_layout() { + assert_evals_to!( + indoc!( + r#" + empty : List I64 + empty = + [] + + List.map empty (\x -> x) + "# + ), + RocList::from_slice(&[]), + RocList + ); +} + +#[test] +fn list_map_on_non_empty_list() { + assert_evals_to!( + indoc!( + r#" + nonEmpty : List I64 + nonEmpty = + [ 1 ] + + List.map nonEmpty (\x -> x) + "# + ), + RocList::from_slice(&[1]), + RocList + ); +} + +#[test] +fn list_map_changes_input() { + assert_evals_to!( + indoc!( + r#" + nonEmpty : List I64 + nonEmpty = + [ 1 ] + + List.map nonEmpty (\x -> x + 1) + "# + ), + RocList::from_slice(&[2]), + RocList + ); +} + +#[test] +fn list_map_on_big_list() { + assert_evals_to!( + indoc!( + r#" + nonEmpty : List I64 + nonEmpty = + [ 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 ] + + List.map nonEmpty (\x -> x * 2) + "# + ), + RocList::from_slice(&[ + 2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10 + ]), + RocList + ); +} + +#[test] +fn list_map_with_type_change() { + assert_evals_to!( + indoc!( + r#" + nonEmpty : List I64 + nonEmpty = + [ 1, 1, -4, 1, 2 ] + + + List.map nonEmpty (\x -> x > 0) + "# + ), + RocList::from_slice(&[true, true, false, true, true]), + RocList + ); +} + +#[test] +fn list_map_using_defined_function() { + assert_evals_to!( + indoc!( + r#" + nonEmpty : List I64 + nonEmpty = + [ 2, 2, -4, 2, 3 ] + + greaterThanOne : I64 -> Bool + greaterThanOne = \i -> + i > 1 + + List.map nonEmpty greaterThanOne + "# + ), + RocList::from_slice(&[true, true, false, true, true]), + RocList + ); +} + +#[test] +fn list_map_all_inline() { + assert_evals_to!( + indoc!( + r#" + List.map [] (\x -> x > 0) + "# + ), + RocList::from_slice(&[]), + RocList + ); +} + +#[test] +fn list_map_closure() { + assert_evals_to!( + indoc!( + r#" + pi : F64 + pi = 3.14 + + single : List F64 + single = + [ 0 ] + + List.map single (\x -> x + pi) + "# + ), + RocList::from_slice(&[3.14]), + RocList + ); +} + +#[test] +fn list_join_empty_list() { + assert_evals_to!("List.join []", RocList::from_slice(&[]), RocList); +} + +#[test] +fn list_join_one_list() { + assert_evals_to!( + "List.join [ [1, 2, 3 ] ]", + RocList::from_slice(&[1, 2, 3]), + RocList + ); +} + +#[test] +fn list_join_two_non_empty_lists() { + assert_evals_to!( + "List.join [ [1, 2, 3 ] , [4 ,5, 6] ]", + RocList::from_slice(&[1, 2, 3, 4, 5, 6]), + RocList + ); +} + +#[test] +fn list_join_two_non_empty_lists_of_float() { + assert_evals_to!( + "List.join [ [ 1.2, 1.1 ], [ 2.1, 2.2 ] ]", + RocList::from_slice(&[1.2, 1.1, 2.1, 2.2]), + RocList + ); +} + +#[test] +fn list_join_to_big_list() { + assert_evals_to!( + indoc!( + r#" + List.join + [ + [ 1.2, 1.1 ], + [ 2.1, 2.2 ], + [ 3.0, 4.0, 5.0, 6.1, 9.0 ], + [ 3.0, 4.0, 5.0, 6.1, 9.0 ], + [ 3.0, 4.0, 5.0, 6.1, 9.0 ], + [ 3.0, 4.0, 5.0, 6.1, 9.0 ], + [ 3.0, 4.0, 5.0, 6.1, 9.0 ] + ] + "# + ), + RocList::from_slice(&[ + 1.2, 1.1, 2.1, 2.2, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0, 5.0, + 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0 + ]), + RocList + ); +} + +#[test] +fn list_join_defined_empty_list() { + assert_evals_to!( + indoc!( + r#" + empty : List F64 empty = [] - List.walkBackwards empty (\a, b -> a + b) 0 - "# - ), - 0, - i64 - ); - } + List.join [ [ 0.2, 11.11 ], empty ] + "# + ), + RocList::from_slice(&[0.2, 11.11]), + RocList + ); +} - #[test] - fn list_walk_backwards_with_str() { - assert_evals_to!( - r#"List.walkBackwards [ "x", "y", "z" ] Str.concat "<""#, - RocStr::from("xyz<"), - RocStr - ); +#[test] +fn list_join_all_empty_lists() { + assert_evals_to!( + "List.join [ [], [], [] ]", + RocList::from_slice(&[]), + RocList + ); +} - assert_evals_to!( - r#"List.walkBackwards [ "Third", "Second", "First" ] Str.concat "Fourth""#, - RocStr::from("ThirdSecondFirstFourth"), - RocStr - ); - } +#[test] +fn list_join_one_empty_list() { + assert_evals_to!( + "List.join [ [ 1.2, 1.1 ], [] ]", + RocList::from_slice(&[1.2, 1.1]), + RocList + ); +} - #[test] - fn list_walk_backwards_with_record() { - assert_evals_to!( - indoc!( - r#" - Bit : [ Zero, One ] +#[test] +fn list_single() { + assert_evals_to!("List.single 1", RocList::from_slice(&[1]), RocList); + assert_evals_to!("List.single 5.6", RocList::from_slice(&[5.6]), RocList); +} - byte : List Bit - byte = [ Zero, One, Zero, One, Zero, Zero, One, Zero ] +#[test] +fn list_repeat() { + assert_evals_to!( + "List.repeat 5 1", + RocList::from_slice(&[1, 1, 1, 1, 1]), + RocList + ); + assert_evals_to!( + "List.repeat 4 2", + RocList::from_slice(&[2, 2, 2, 2]), + RocList + ); - initialCounts = { zeroes: 0, ones: 0 } - - acc = \b, r -> - when b is - Zero -> { r & zeroes: r.zeroes + 1 } - One -> { r & ones: r.ones + 1 } - - finalCounts = List.walkBackwards byte acc initialCounts - - finalCounts.ones * 10 + finalCounts.zeroes - "# - ), - 35, - i64 - ); - } - - #[test] - fn list_walk_with_str() { - assert_evals_to!( - r#"List.walk [ "x", "y", "z" ] Str.concat "<""#, - RocStr::from("zyx<"), - RocStr - ); - - assert_evals_to!( - r#"List.walk [ "Third", "Second", "First" ] Str.concat "Fourth""#, - RocStr::from("FirstSecondThirdFourth"), - RocStr - ); - } - - #[test] - fn list_walk_substraction() { - assert_evals_to!(r#"List.walk [ 1, 2 ] Num.sub 1"#, 2, i64); - } - - #[test] - fn list_keep_if_empty_list_of_int() { - assert_evals_to!( - indoc!( - r#" - empty : List I64 - empty = + assert_evals_to!("List.repeat 2 []", &[&[], &[]], &'static [&'static [i64]]); + assert_evals_to!( + indoc!( + r#" + noStrs : List Str + noStrs = [] - List.keepIf empty (\_ -> True) - "# - ), - RocList::from_slice(&[]), - RocList - ); - } + List.repeat 2 noStrs + "# + ), + &[&[], &[]], + &'static [&'static [i64]] + ); - #[test] - fn list_keep_if_empty_list() { - assert_evals_to!( - indoc!( - r#" - alwaysTrue : I64 -> Bool - alwaysTrue = \_ -> - True + assert_evals_to!( + "List.repeat 15 4", + RocList::from_slice(&[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]), + RocList + ); +} +#[test] +fn list_reverse() { + assert_evals_to!( + "List.reverse [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]", + RocList::from_slice(&[12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), + RocList + ); + assert_evals_to!( + "List.reverse [1, 2, 3]", + RocList::from_slice(&[3, 2, 1]), + RocList + ); + assert_evals_to!("List.reverse [4]", RocList::from_slice(&[4]), RocList); +} - List.keepIf [] alwaysTrue - "# - ), - RocList::from_slice(&[]), - RocList - ); - } - - #[test] - fn list_keep_if_always_true_for_non_empty_list() { - assert_evals_to!( - indoc!( - r#" - alwaysTrue : I64 -> Bool - alwaysTrue = \_ -> - True - - oneThroughEight : List I64 - oneThroughEight = - [1,2,3,4,5,6,7,8] - - List.keepIf oneThroughEight alwaysTrue - "# - ), - RocList::from_slice(&[1, 2, 3, 4, 5, 6, 7, 8]), - RocList - ); - } - - #[test] - fn list_keep_if_always_false_for_non_empty_list() { - assert_evals_to!( - indoc!( - r#" - alwaysFalse : I64 -> Bool - alwaysFalse = \_ -> - False - - List.keepIf [1,2,3,4,5,6,7,8] alwaysFalse - "# - ), - RocList::from_slice(&[]), - RocList - ); - } - - #[test] - fn list_keep_if_one() { - assert_evals_to!( - indoc!( - r#" - intIsLessThanThree : I64 -> Bool - intIsLessThanThree = \i -> - i < 3 - - List.keepIf [1,2,3,4,5,6,7,8] intIsLessThanThree - "# - ), - RocList::from_slice(&[1, 2]), - RocList - ); - } - - #[test] - fn list_keep_if_str_is_hello() { - assert_evals_to!( - indoc!( - r#" - List.keepIf ["x", "y", "x"] (\x -> x == "x") - "# - ), - RocList::from_slice(&[ - RocStr::from_slice("x".as_bytes()), - RocStr::from_slice("x".as_bytes()) - ]), - RocList - ); - } - - #[test] - fn list_map_on_empty_list_with_int_layout() { - assert_evals_to!( - indoc!( - r#" - empty : List I64 - empty = +#[test] +fn list_reverse_empty_list_of_int() { + assert_evals_to!( + indoc!( + r#" + emptyList : List I64 + emptyList = [] - List.map empty (\x -> x) - "# - ), - RocList::from_slice(&[]), - RocList - ); - } - - #[test] - fn list_map_on_non_empty_list() { - assert_evals_to!( - indoc!( - r#" - nonEmpty : List I64 - nonEmpty = - [ 1 ] - - List.map nonEmpty (\x -> x) - "# - ), - RocList::from_slice(&[1]), - RocList - ); - } - - #[test] - fn list_map_changes_input() { - assert_evals_to!( - indoc!( - r#" - nonEmpty : List I64 - nonEmpty = - [ 1 ] - - List.map nonEmpty (\x -> x + 1) - "# - ), - RocList::from_slice(&[2]), - RocList - ); - } - - #[test] - fn list_map_on_big_list() { - assert_evals_to!( - indoc!( - r#" - nonEmpty : List I64 - nonEmpty = - [ 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 ] - - List.map nonEmpty (\x -> x * 2) - "# - ), - RocList::from_slice(&[ - 2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10 - ]), - RocList - ); - } - - #[test] - fn list_map_with_type_change() { - assert_evals_to!( - indoc!( - r#" - nonEmpty : List I64 - nonEmpty = - [ 1, 1, -4, 1, 2 ] - - - List.map nonEmpty (\x -> x > 0) - "# - ), - RocList::from_slice(&[true, true, false, true, true]), - RocList - ); - } - - #[test] - fn list_map_using_defined_function() { - assert_evals_to!( - indoc!( - r#" - nonEmpty : List I64 - nonEmpty = - [ 2, 2, -4, 2, 3 ] - - greaterThanOne : I64 -> Bool - greaterThanOne = \i -> - i > 1 - - List.map nonEmpty greaterThanOne - "# - ), - RocList::from_slice(&[true, true, false, true, true]), - RocList - ); - } - - #[test] - fn list_map_all_inline() { - assert_evals_to!( - indoc!( - r#" - List.map [] (\x -> x > 0) - "# - ), - RocList::from_slice(&[]), - RocList - ); - } - - #[test] - fn list_map_closure() { - assert_evals_to!( - indoc!( - r#" - pi : F64 - pi = 3.14 - - single : List F64 - single = - [ 0 ] - - List.map single (\x -> x + pi) - "# - ), - RocList::from_slice(&[3.14]), - RocList - ); - } - - #[test] - fn list_join_empty_list() { - assert_evals_to!("List.join []", RocList::from_slice(&[]), RocList); - } - - #[test] - fn list_join_one_list() { - assert_evals_to!( - "List.join [ [1, 2, 3 ] ]", - RocList::from_slice(&[1, 2, 3]), - RocList - ); - } - - #[test] - fn list_join_two_non_empty_lists() { - assert_evals_to!( - "List.join [ [1, 2, 3 ] , [4 ,5, 6] ]", - RocList::from_slice(&[1, 2, 3, 4, 5, 6]), - RocList - ); - } - - #[test] - fn list_join_two_non_empty_lists_of_float() { - assert_evals_to!( - "List.join [ [ 1.2, 1.1 ], [ 2.1, 2.2 ] ]", - RocList::from_slice(&[1.2, 1.1, 2.1, 2.2]), - RocList - ); - } - - #[test] - fn list_join_to_big_list() { - assert_evals_to!( - indoc!( - r#" - List.join - [ - [ 1.2, 1.1 ], - [ 2.1, 2.2 ], - [ 3.0, 4.0, 5.0, 6.1, 9.0 ], - [ 3.0, 4.0, 5.0, 6.1, 9.0 ], - [ 3.0, 4.0, 5.0, 6.1, 9.0 ], - [ 3.0, 4.0, 5.0, 6.1, 9.0 ], - [ 3.0, 4.0, 5.0, 6.1, 9.0 ] - ] - "# - ), - RocList::from_slice(&[ - 1.2, 1.1, 2.1, 2.2, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0, - 5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0 - ]), - RocList - ); - } - - #[test] - fn list_join_defined_empty_list() { - assert_evals_to!( - indoc!( - r#" - empty : List F64 - empty = - [] - - List.join [ [ 0.2, 11.11 ], empty ] - "# - ), - RocList::from_slice(&[0.2, 11.11]), - RocList - ); - } - - #[test] - fn list_join_all_empty_lists() { - assert_evals_to!( - "List.join [ [], [], [] ]", - RocList::from_slice(&[]), - RocList - ); - } - - #[test] - fn list_join_one_empty_list() { - assert_evals_to!( - "List.join [ [ 1.2, 1.1 ], [] ]", - RocList::from_slice(&[1.2, 1.1]), - RocList - ); - } - - #[test] - fn list_single() { - assert_evals_to!("List.single 1", RocList::from_slice(&[1]), RocList); - assert_evals_to!("List.single 5.6", RocList::from_slice(&[5.6]), RocList); - } - - #[test] - fn list_repeat() { - assert_evals_to!( - "List.repeat 5 1", - RocList::from_slice(&[1, 1, 1, 1, 1]), - RocList - ); - assert_evals_to!( - "List.repeat 4 2", - RocList::from_slice(&[2, 2, 2, 2]), - RocList - ); - - assert_evals_to!("List.repeat 2 []", &[&[], &[]], &'static [&'static [i64]]); - assert_evals_to!( - indoc!( - r#" - noStrs : List Str - noStrs = - [] - - List.repeat 2 noStrs - "# - ), - &[&[], &[]], - &'static [&'static [i64]] - ); - - assert_evals_to!( - "List.repeat 15 4", - RocList::from_slice(&[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]), - RocList - ); - } - - #[test] - fn list_reverse() { - assert_evals_to!( - "List.reverse [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]", - RocList::from_slice(&[12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), - RocList - ); - assert_evals_to!( - "List.reverse [1, 2, 3]", - RocList::from_slice(&[3, 2, 1]), - RocList - ); - assert_evals_to!("List.reverse [4]", RocList::from_slice(&[4]), RocList); - } - - #[test] - fn list_reverse_empty_list_of_int() { - assert_evals_to!( - indoc!( - r#" - emptyList : List I64 - emptyList = - [] - - List.reverse emptyList - "# - ), - RocList::from_slice(&[]), - RocList - ); - } - - #[test] - fn list_reverse_empty_list() { - assert_evals_to!("List.reverse []", RocList::from_slice(&[]), RocList); - } - - #[test] - fn foobarbaz() { - assert_evals_to!( - indoc!( - r#" - firstList : List I64 - firstList = - [] - - secondList : List I64 - secondList = - [] - - List.concat firstList secondList - "# - ), - RocList::from_slice(&[]), - RocList - ); - } - - #[test] - fn list_concat_two_empty_lists() { - assert_evals_to!("List.concat [] []", RocList::from_slice(&[]), RocList); - } - - #[test] - fn list_concat_two_empty_lists_of_int() { - assert_evals_to!( - indoc!( - r#" - firstList : List I64 - firstList = - [] - - secondList : List I64 - secondList = - [] - - List.concat firstList secondList - "# - ), - RocList::from_slice(&[]), - RocList - ); - } - - #[test] - fn list_concat_second_list_is_empty() { - assert_evals_to!( - "List.concat [ 12, 13 ] []", - RocList::from_slice(&[12, 13]), - RocList - ); - assert_evals_to!( - "List.concat [ 34, 43 ] [ 64, 55, 66 ]", - RocList::from_slice(&[34, 43, 64, 55, 66]), - RocList - ); - } - - #[test] - fn list_concat_first_list_is_empty() { - assert_evals_to!( - "List.concat [] [ 23, 24 ]", - RocList::from_slice(&[23, 24]), - RocList - ); - } - - #[test] - fn list_concat_two_non_empty_lists() { - assert_evals_to!( - "List.concat [1, 2 ] [ 3, 4 ]", - RocList::from_slice(&[1, 2, 3, 4]), - RocList - ); - } - - #[test] - fn list_concat_two_bigger_non_empty_lists() { - assert_evals_to!( - "List.concat [ 1.1, 2.2 ] [ 3.3, 4.4, 5.5 ]", - RocList::from_slice(&[1.1, 2.2, 3.3, 4.4, 5.5]), - RocList - ); - } - - fn assert_concat_worked(num_elems1: i64, num_elems2: i64) { - let vec1: Vec = (0..num_elems1) - .map(|i| 12345 % (i + num_elems1 + num_elems2 + 1)) - .collect(); - let vec2: Vec = (0..num_elems2) - .map(|i| 54321 % (i + num_elems1 + num_elems2 + 1)) - .collect(); - let slice_str1 = format!("{:?}", vec1); - let slice_str2 = format!("{:?}", vec2); - let mut expected = vec1; - - expected.extend(vec2); - - assert_evals_to!( - &format!("List.concat {} {}", slice_str1, slice_str2), - RocList::from_slice(&expected), - RocList - ); - } - - #[test] - fn list_concat_empty_list() { - assert_concat_worked(0, 0); - assert_concat_worked(1, 0); - assert_concat_worked(2, 0); - assert_concat_worked(3, 0); - assert_concat_worked(4, 0); - assert_concat_worked(7, 0); - assert_concat_worked(8, 0); - assert_concat_worked(9, 0); - assert_concat_worked(25, 0); - assert_concat_worked(150, 0); - assert_concat_worked(0, 1); - assert_concat_worked(0, 2); - assert_concat_worked(0, 3); - assert_concat_worked(0, 4); - assert_concat_worked(0, 7); - assert_concat_worked(0, 8); - assert_concat_worked(0, 9); - assert_concat_worked(0, 25); - assert_concat_worked(0, 150); - } - - #[test] - fn list_concat_nonempty_lists() { - assert_concat_worked(1, 1); - assert_concat_worked(1, 2); - assert_concat_worked(1, 3); - assert_concat_worked(2, 3); - assert_concat_worked(2, 1); - assert_concat_worked(2, 2); - assert_concat_worked(3, 1); - assert_concat_worked(3, 2); - assert_concat_worked(2, 3); - assert_concat_worked(3, 3); - assert_concat_worked(4, 4); - } - - #[test] - fn list_concat_large() { - with_larger_debug_stack(|| { - // these values produce mono ASTs so large that - // it can cause a stack overflow. This has been solved - // for current code, but may become a problem again in the future. - assert_concat_worked(150, 150); - assert_concat_worked(129, 350); - assert_concat_worked(350, 129); - }) - } - - #[test] - fn empty_list_len() { - assert_evals_to!("List.len []", 0, usize); - } - - #[test] - fn basic_int_list_len() { - assert_evals_to!("List.len [ 12, 9, 6, 3 ]", 4, usize); - } - - #[test] - fn loaded_int_list_len() { - assert_evals_to!( - indoc!( - r#" - nums = [ 2, 4, 6 ] - - List.len nums - "# - ), - 3, - usize - ); - } - - #[test] - fn fn_int_list_len() { - assert_evals_to!( - indoc!( - r#" - getLen = \list -> List.len list - - nums = [ 2, 4, 6, 8 ] - - getLen nums - "# - ), - 4, - usize - ); - } - - #[test] - fn int_list_is_empty() { - assert_evals_to!("List.isEmpty [ 12, 9, 6, 3 ]", false, bool); - } - - #[test] - fn empty_list_is_empty() { - assert_evals_to!("List.isEmpty []", true, bool); - } - - #[test] - fn first_int_list() { - assert_evals_to!( - indoc!( - r#" - when List.first [ 12, 9, 6, 3 ] is - Ok val -> val - Err _ -> -1 - "# - ), - 12, - i64 - ); - } - - #[test] - #[ignore] - fn first_wildcard_empty_list() { - assert_evals_to!( - indoc!( - r#" - when List.first [] is - Ok _ -> 5 - Err _ -> -1 - "# - ), - -1, - i64 - ); - } - - #[test] - fn first_empty_list() { - assert_evals_to!( - indoc!( - r#" - when List.first [] is - Ok val -> val - Err _ -> -1 - "# - ), - -1, - i64 - ); - } - - #[test] - fn last_int_list() { - assert_evals_to!( - indoc!( - r#" - when List.last [ 12, 9, 6, 3 ] is - Ok val -> val - Err _ -> -1 - "# - ), - 3, - i64 - ); - } - - #[test] - #[ignore] - fn last_wildcard_empty_list() { - assert_evals_to!( - indoc!( - r#" - when List.last [] is - Ok _ -> 5 - Err _ -> -1 - "# - ), - -1, - i64 - ); - } - - #[test] - fn last_empty_list() { - assert_evals_to!( - indoc!( - r#" - when List.last [] is - Ok val -> val - Err _ -> -1 - "# - ), - -1, - i64 - ); - } - - #[test] - fn get_empty_list() { - assert_evals_to!( - indoc!( - r#" - when List.get [] 0 is - Ok val -> val - Err _ -> -1 - "# - ), - -1, - i64 - ); - } - - #[test] - #[ignore] - fn get_wildcard_empty_list() { - assert_evals_to!( - indoc!( - r#" - when List.get [] 0 is - Ok _ -> 5 - Err _ -> -1 - "# - ), - -1, - i64 - ); - } - - #[test] - fn get_int_list_ok() { - assert_evals_to!( - indoc!( - r#" - when List.get [ 12, 9, 6 ] 1 is - Ok val -> val - Err _ -> -1 - "# - ), - 9, - i64 - ); - } - - #[test] - fn get_int_list_oob() { - assert_evals_to!( - indoc!( - r#" - when List.get [ 12, 9, 6 ] 1000 is - Ok val -> val - Err _ -> -1 - "# - ), - -1, - i64 - ); - } - - #[test] - fn get_set_unique_int_list() { - assert_evals_to!( - indoc!( - r#" - when List.get (List.set [ 12, 9, 7, 3 ] 1 42) 1 is - Ok val -> val - Err _ -> -1 - "# - ), - 42, - i64 - ); - } - - #[test] - fn set_unique_int_list() { - assert_evals_to!( - "List.set [ 12, 9, 7, 1, 5 ] 2 33", - RocList::from_slice(&[12, 9, 33, 1, 5]), - RocList - ); - } - - #[test] - fn set_unique_list_oob() { - assert_evals_to!( - "List.set [ 3, 17, 4.1 ] 1337 9.25", - RocList::from_slice(&[3.0, 17.0, 4.1]), - RocList - ); - } - - #[test] - fn set_shared_int_list() { - assert_evals_to!( - indoc!( - r#" - wrapper = \shared -> - # This should not mutate the original - x = - when List.get (List.set shared 1 7.7) 1 is - Ok num -> num - Err _ -> 0 - - y = - when List.get shared 1 is - Ok num -> num - Err _ -> 0 - - { x, y } - - wrapper [ 2.1, 4.3 ] - "# - ), - (7.7, 4.3), - (f64, f64) - ); - } - - #[test] - fn set_shared_list_oob() { - assert_evals_to!( - indoc!( - r#" - shared = [ 2, 4 ] - - # This List.set is out of bounds, and should have no effect + List.reverse emptyList + "# + ), + RocList::from_slice(&[]), + RocList + ); +} + +#[test] +fn list_reverse_empty_list() { + assert_evals_to!("List.reverse []", RocList::from_slice(&[]), RocList); +} + +#[test] +fn foobarbaz() { + assert_evals_to!( + indoc!( + r#" + firstList : List I64 + firstList = + [] + + secondList : List I64 + secondList = + [] + + List.concat firstList secondList + "# + ), + RocList::from_slice(&[]), + RocList + ); +} + +#[test] +fn list_concat_two_empty_lists() { + assert_evals_to!("List.concat [] []", RocList::from_slice(&[]), RocList); +} + +#[test] +fn list_concat_two_empty_lists_of_int() { + assert_evals_to!( + indoc!( + r#" + firstList : List I64 + firstList = + [] + + secondList : List I64 + secondList = + [] + + List.concat firstList secondList + "# + ), + RocList::from_slice(&[]), + RocList + ); +} + +#[test] +fn list_concat_second_list_is_empty() { + assert_evals_to!( + "List.concat [ 12, 13 ] []", + RocList::from_slice(&[12, 13]), + RocList + ); + assert_evals_to!( + "List.concat [ 34, 43 ] [ 64, 55, 66 ]", + RocList::from_slice(&[34, 43, 64, 55, 66]), + RocList + ); +} + +#[test] +fn list_concat_first_list_is_empty() { + assert_evals_to!( + "List.concat [] [ 23, 24 ]", + RocList::from_slice(&[23, 24]), + RocList + ); +} + +#[test] +fn list_concat_two_non_empty_lists() { + assert_evals_to!( + "List.concat [1, 2 ] [ 3, 4 ]", + RocList::from_slice(&[1, 2, 3, 4]), + RocList + ); +} + +#[test] +fn list_concat_two_bigger_non_empty_lists() { + assert_evals_to!( + "List.concat [ 1.1, 2.2 ] [ 3.3, 4.4, 5.5 ]", + RocList::from_slice(&[1.1, 2.2, 3.3, 4.4, 5.5]), + RocList + ); +} + +fn assert_concat_worked(num_elems1: i64, num_elems2: i64) { + let vec1: Vec = (0..num_elems1) + .map(|i| 12345 % (i + num_elems1 + num_elems2 + 1)) + .collect(); + let vec2: Vec = (0..num_elems2) + .map(|i| 54321 % (i + num_elems1 + num_elems2 + 1)) + .collect(); + let slice_str1 = format!("{:?}", vec1); + let slice_str2 = format!("{:?}", vec2); + let mut expected = vec1; + + expected.extend(vec2); + + assert_evals_to!( + &format!("List.concat {} {}", slice_str1, slice_str2), + RocList::from_slice(&expected), + RocList + ); +} + +#[test] +fn list_concat_empty_list() { + assert_concat_worked(0, 0); + assert_concat_worked(1, 0); + assert_concat_worked(2, 0); + assert_concat_worked(3, 0); + assert_concat_worked(4, 0); + assert_concat_worked(7, 0); + assert_concat_worked(8, 0); + assert_concat_worked(9, 0); + assert_concat_worked(25, 0); + assert_concat_worked(150, 0); + assert_concat_worked(0, 1); + assert_concat_worked(0, 2); + assert_concat_worked(0, 3); + assert_concat_worked(0, 4); + assert_concat_worked(0, 7); + assert_concat_worked(0, 8); + assert_concat_worked(0, 9); + assert_concat_worked(0, 25); + assert_concat_worked(0, 150); +} + +#[test] +fn list_concat_nonempty_lists() { + assert_concat_worked(1, 1); + assert_concat_worked(1, 2); + assert_concat_worked(1, 3); + assert_concat_worked(2, 3); + assert_concat_worked(2, 1); + assert_concat_worked(2, 2); + assert_concat_worked(3, 1); + assert_concat_worked(3, 2); + assert_concat_worked(2, 3); + assert_concat_worked(3, 3); + assert_concat_worked(4, 4); +} + +#[test] +fn list_concat_large() { + with_larger_debug_stack(|| { + // these values produce mono ASTs so large that + // it can cause a stack overflow. This has been solved + // for current code, but may become a problem again in the future. + assert_concat_worked(150, 150); + assert_concat_worked(129, 350); + assert_concat_worked(350, 129); + }) +} + +#[test] +fn empty_list_len() { + assert_evals_to!("List.len []", 0, usize); +} + +#[test] +fn basic_int_list_len() { + assert_evals_to!("List.len [ 12, 9, 6, 3 ]", 4, usize); +} + +#[test] +fn loaded_int_list_len() { + assert_evals_to!( + indoc!( + r#" + nums = [ 2, 4, 6 ] + + List.len nums + "# + ), + 3, + usize + ); +} + +#[test] +fn fn_int_list_len() { + assert_evals_to!( + indoc!( + r#" + getLen = \list -> List.len list + + nums = [ 2, 4, 6, 8 ] + + getLen nums + "# + ), + 4, + usize + ); +} + +#[test] +fn int_list_is_empty() { + assert_evals_to!("List.isEmpty [ 12, 9, 6, 3 ]", false, bool); +} + +#[test] +fn empty_list_is_empty() { + assert_evals_to!("List.isEmpty []", true, bool); +} + +#[test] +fn first_int_list() { + assert_evals_to!( + indoc!( + r#" + when List.first [ 12, 9, 6, 3 ] is + Ok val -> val + Err _ -> -1 + "# + ), + 12, + i64 + ); +} + +#[test] +#[ignore] +fn first_wildcard_empty_list() { + assert_evals_to!( + indoc!( + r#" + when List.first [] is + Ok _ -> 5 + Err _ -> -1 + "# + ), + -1, + i64 + ); +} + +#[test] +fn first_empty_list() { + assert_evals_to!( + indoc!( + r#" + when List.first [] is + Ok val -> val + Err _ -> -1 + "# + ), + -1, + i64 + ); +} + +#[test] +fn last_int_list() { + assert_evals_to!( + indoc!( + r#" + when List.last [ 12, 9, 6, 3 ] is + Ok val -> val + Err _ -> -1 + "# + ), + 3, + i64 + ); +} + +#[test] +#[ignore] +fn last_wildcard_empty_list() { + assert_evals_to!( + indoc!( + r#" + when List.last [] is + Ok _ -> 5 + Err _ -> -1 + "# + ), + -1, + i64 + ); +} + +#[test] +fn last_empty_list() { + assert_evals_to!( + indoc!( + r#" + when List.last [] is + Ok val -> val + Err _ -> -1 + "# + ), + -1, + i64 + ); +} + +#[test] +fn get_empty_list() { + assert_evals_to!( + indoc!( + r#" + when List.get [] 0 is + Ok val -> val + Err _ -> -1 + "# + ), + -1, + i64 + ); +} + +#[test] +#[ignore] +fn get_wildcard_empty_list() { + assert_evals_to!( + indoc!( + r#" + when List.get [] 0 is + Ok _ -> 5 + Err _ -> -1 + "# + ), + -1, + i64 + ); +} + +#[test] +fn get_int_list_ok() { + assert_evals_to!( + indoc!( + r#" + when List.get [ 12, 9, 6 ] 1 is + Ok val -> val + Err _ -> -1 + "# + ), + 9, + i64 + ); +} + +#[test] +fn get_int_list_oob() { + assert_evals_to!( + indoc!( + r#" + when List.get [ 12, 9, 6 ] 1000 is + Ok val -> val + Err _ -> -1 + "# + ), + -1, + i64 + ); +} + +#[test] +fn get_set_unique_int_list() { + assert_evals_to!( + indoc!( + r#" + when List.get (List.set [ 12, 9, 7, 3 ] 1 42) 1 is + Ok val -> val + Err _ -> -1 + "# + ), + 42, + i64 + ); +} + +#[test] +fn set_unique_int_list() { + assert_evals_to!( + "List.set [ 12, 9, 7, 1, 5 ] 2 33", + RocList::from_slice(&[12, 9, 33, 1, 5]), + RocList + ); +} + +#[test] +fn set_unique_list_oob() { + assert_evals_to!( + "List.set [ 3, 17, 4.1 ] 1337 9.25", + RocList::from_slice(&[3.0, 17.0, 4.1]), + RocList + ); +} + +#[test] +fn set_shared_int_list() { + assert_evals_to!( + indoc!( + r#" + wrapper = \shared -> + # This should not mutate the original x = - when List.get (List.set shared 422 0) 1 is + when List.get (List.set shared 1 7.7) 1 is Ok num -> num Err _ -> 0 @@ -1190,92 +1152,255 @@ mod gen_list { Err _ -> 0 { x, y } - "# - ), - (4, 4), - (i64, i64) - ); - } - #[test] - fn get_unique_int_list() { + wrapper [ 2.1, 4.3 ] + "# + ), + (7.7, 4.3), + (f64, f64) + ); +} + +#[test] +fn set_shared_list_oob() { + assert_evals_to!( + indoc!( + r#" + shared = [ 2, 4 ] + + # This List.set is out of bounds, and should have no effect + x = + when List.get (List.set shared 422 0) 1 is + Ok num -> num + Err _ -> 0 + + y = + when List.get shared 1 is + Ok num -> num + Err _ -> 0 + + { x, y } + "# + ), + (4, 4), + (i64, i64) + ); +} + +#[test] +fn get_unique_int_list() { + assert_evals_to!( + indoc!( + r#" + unique = [ 2, 4 ] + + when List.get unique 1 is + Ok num -> num + Err _ -> -1 + "# + ), + 4, + i64 + ); +} + +#[test] +fn gen_wrap_len() { + assert_evals_to!( + indoc!( + r#" + wrapLen = \list -> + [ List.len list ] + + wrapLen [ 1, 7, 9 ] + "# + ), + RocList::from_slice(&[3]), + RocList + ); +} + +#[test] +fn gen_wrap_first() { + assert_evals_to!( + indoc!( + r#" + wrapFirst = \list -> + [ List.first list ] + + wrapFirst [ 1, 2 ] + "# + ), + // RocList::from_slice(&[1]), + // RocList + &[1], + &'static [i64] + ); +} + +#[test] +fn gen_duplicate() { + assert_evals_to!( + indoc!( + r#" + # Duplicate the first element into the second index + dupe = \list -> + when List.first list is + Ok elem -> + List.set list 1 elem + + _ -> + [] + + dupe [ 1, 2 ] + "# + ), + RocList::from_slice(&[1, 1]), + RocList + ); +} + +#[test] +fn gen_swap() { + assert_evals_to!( + indoc!( + r#" + app "quicksort" provides [ main ] to "./platform" + + + swap : Nat, Nat, List a -> List a + swap = \i, j, list -> + when Pair (List.get list i) (List.get list j) is + Pair (Ok atI) (Ok atJ) -> + list + |> List.set i atJ + |> List.set j atI + + _ -> + [] + + main = + swap 0 1 [ 1, 2 ] + "# + ), + RocList::from_slice(&[2, 1]), + RocList + ); +} + +// #[test] +// fn gen_partition() { +// assert_evals_to!( +// indoc!( +// r#" +// swap : I64, I64, List a -> List a +// swap = \i, j, list -> +// when Pair (List.get list i) (List.get list j) is +// Pair (Ok atI) (Ok atJ) -> +// list +// |> List.set i atJ +// |> List.set j atI +// +// _ -> +// [] +// partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ] +// partition = \low, high, initialList -> +// when List.get initialList high is +// Ok pivot -> +// when partitionHelp (low - 1) low initialList high pivot is +// Pair newI newList -> +// Pair (newI + 1) (swap (newI + 1) high newList) +// +// Err _ -> +// Pair (low - 1) initialList +// +// +// partitionHelp : I64, I64, List (Num a), I64, I64 -> [ Pair I64 (List (Num a)) ] +// partitionHelp = \i, j, list, high, pivot -> +// if j < high then +// when List.get list j is +// Ok value -> +// if value <= pivot then +// partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot +// else +// partitionHelp i (j + 1) list high pivot +// +// Err _ -> +// Pair i list +// else +// Pair i list +// +// # when partition 0 0 [ 1,2,3,4,5 ] is +// # Pair list _ -> list +// [ 1,3 ] +// "# +// ), +// RocList::from_slice(&[2, 1]), +// RocList +// ); +// } + +// #[test] +// fn gen_partition() { +// assert_evals_to!( +// indoc!( +// r#" +// swap : I64, I64, List a -> List a +// swap = \i, j, list -> +// when Pair (List.get list i) (List.get list j) is +// Pair (Ok atI) (Ok atJ) -> +// list +// |> List.set i atJ +// |> List.set j atI +// +// _ -> +// [] +// partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ] +// partition = \low, high, initialList -> +// when List.get initialList high is +// Ok pivot -> +// when partitionHelp (low - 1) low initialList high pivot is +// Pair newI newList -> +// Pair (newI + 1) (swap (newI + 1) high newList) +// +// Err _ -> +// Pair (low - 1) initialList +// +// +// partitionHelp : I64, I64, List (Num a), I64, I64 -> [ Pair I64 (List (Num a)) ] +// +// # when partition 0 0 [ 1,2,3,4,5 ] is +// # Pair list _ -> list +// [ 1,3 ] +// "# +// ), +// RocList::from_slice(&[2, 1]), +// RocList +// ); +// } + +#[test] +fn gen_quicksort() { + with_larger_debug_stack(|| { assert_evals_to!( indoc!( r#" - unique = [ 2, 4 ] + quicksort : List (Num a) -> List (Num a) + quicksort = \list -> + n = List.len list + quicksortHelp list 0 (n - 1) - when List.get unique 1 is - Ok num -> num - Err _ -> -1 - "# - ), - 4, - i64 - ); - } - #[test] - fn gen_wrap_len() { - assert_evals_to!( - indoc!( - r#" - wrapLen = \list -> - [ List.len list ] - - wrapLen [ 1, 7, 9 ] - "# - ), - RocList::from_slice(&[3]), - RocList - ); - } - - #[test] - fn gen_wrap_first() { - assert_evals_to!( - indoc!( - r#" - wrapFirst = \list -> - [ List.first list ] - - wrapFirst [ 1, 2 ] - "# - ), - // RocList::from_slice(&[1]), - // RocList - &[1], - &'static [i64] - ); - } - - #[test] - fn gen_duplicate() { - assert_evals_to!( - indoc!( - r#" - # Duplicate the first element into the second index - dupe = \list -> - when List.first list is - Ok elem -> - List.set list 1 elem - - _ -> - [] - - dupe [ 1, 2 ] - "# - ), - RocList::from_slice(&[1, 1]), - RocList - ); - } - - #[test] - fn gen_swap() { - assert_evals_to!( - indoc!( - r#" - app "quicksort" provides [ main ] to "./platform" + quicksortHelp : List (Num a), Nat, Nat -> List (Num a) + quicksortHelp = \list, low, high -> + if low < high then + when partition low high list is + Pair partitionIndex partitioned -> + partitioned + |> quicksortHelp low (partitionIndex - 1) + |> quicksortHelp (partitionIndex + 1) high + else + list swap : Nat, Nat, List a -> List a @@ -1289,467 +1414,331 @@ mod gen_list { _ -> [] - main = - swap 0 1 [ 1, 2 ] - "# - ), - RocList::from_slice(&[2, 1]), - RocList - ); - } + partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] + partition = \low, high, initialList -> + when List.get initialList high is + Ok pivot -> + when partitionHelp (low - 1) low initialList high pivot is + Pair newI newList -> + Pair (newI + 1) (swap (newI + 1) high newList) - // #[test] - // fn gen_partition() { - // assert_evals_to!( - // indoc!( - // r#" - // swap : I64, I64, List a -> List a - // swap = \i, j, list -> - // when Pair (List.get list i) (List.get list j) is - // Pair (Ok atI) (Ok atJ) -> - // list - // |> List.set i atJ - // |> List.set j atI - // - // _ -> - // [] - // partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ] - // partition = \low, high, initialList -> - // when List.get initialList high is - // Ok pivot -> - // when partitionHelp (low - 1) low initialList high pivot is - // Pair newI newList -> - // Pair (newI + 1) (swap (newI + 1) high newList) - // - // Err _ -> - // Pair (low - 1) initialList - // - // - // partitionHelp : I64, I64, List (Num a), I64, I64 -> [ Pair I64 (List (Num a)) ] - // partitionHelp = \i, j, list, high, pivot -> - // if j < high then - // when List.get list j is - // Ok value -> - // if value <= pivot then - // partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot - // else - // partitionHelp i (j + 1) list high pivot - // - // Err _ -> - // Pair i list - // else - // Pair i list - // - // # when partition 0 0 [ 1,2,3,4,5 ] is - // # Pair list _ -> list - // [ 1,3 ] - // "# - // ), - // RocList::from_slice(&[2, 1]), - // RocList - // ); - // } - - // #[test] - // fn gen_partition() { - // assert_evals_to!( - // indoc!( - // r#" - // swap : I64, I64, List a -> List a - // swap = \i, j, list -> - // when Pair (List.get list i) (List.get list j) is - // Pair (Ok atI) (Ok atJ) -> - // list - // |> List.set i atJ - // |> List.set j atI - // - // _ -> - // [] - // partition : I64, I64, List (Num a) -> [ Pair I64 (List (Num a)) ] - // partition = \low, high, initialList -> - // when List.get initialList high is - // Ok pivot -> - // when partitionHelp (low - 1) low initialList high pivot is - // Pair newI newList -> - // Pair (newI + 1) (swap (newI + 1) high newList) - // - // Err _ -> - // Pair (low - 1) initialList - // - // - // partitionHelp : I64, I64, List (Num a), I64, I64 -> [ Pair I64 (List (Num a)) ] - // - // # when partition 0 0 [ 1,2,3,4,5 ] is - // # Pair list _ -> list - // [ 1,3 ] - // "# - // ), - // RocList::from_slice(&[2, 1]), - // RocList - // ); - // } - - #[test] - fn gen_quicksort() { - with_larger_debug_stack(|| { - assert_evals_to!( - indoc!( - r#" - quicksort : List (Num a) -> List (Num a) - quicksort = \list -> - n = List.len list - quicksortHelp list 0 (n - 1) + Err _ -> + Pair (low - 1) initialList - quicksortHelp : List (Num a), Nat, Nat -> List (Num a) - quicksortHelp = \list, low, high -> - if low < high then - when partition low high list is - Pair partitionIndex partitioned -> - partitioned - |> quicksortHelp low (partitionIndex - 1) - |> quicksortHelp (partitionIndex + 1) high - else - list - - - swap : Nat, Nat, List a -> List a - swap = \i, j, list -> - when Pair (List.get list i) (List.get list j) is - Pair (Ok atI) (Ok atJ) -> - list - |> List.set i atJ - |> List.set j atI - - _ -> - [] - - partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] - partition = \low, high, initialList -> - when List.get initialList high is - Ok pivot -> - when partitionHelp (low - 1) low initialList high pivot is - Pair newI newList -> - Pair (newI + 1) (swap (newI + 1) high newList) + partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [ Pair Nat (List (Num a)) ] + partitionHelp = \i, j, list, high, pivot -> + if j < high then + when List.get list j is + Ok value -> + if value <= pivot then + partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot + else + partitionHelp i (j + 1) list high pivot Err _ -> - Pair (low - 1) initialList + Pair i list + else + Pair i list - - partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [ Pair Nat (List (Num a)) ] - partitionHelp = \i, j, list, high, pivot -> - if j < high then - when List.get list j is - Ok value -> - if value <= pivot then - partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot - else - partitionHelp i (j + 1) list high pivot - - Err _ -> - Pair i list - else - Pair i list - - quicksort [ 7, 4, 21, 19 ] - "# - ), - RocList::from_slice(&[4, 7, 19, 21]), - RocList - ); - }) - } - - #[test] - fn foobar2() { - with_larger_debug_stack(|| { - assert_evals_to!( - indoc!( - r#" - quicksort : List (Num a) -> List (Num a) - quicksort = \list -> - quicksortHelp list 0 (List.len list - 1) - - - quicksortHelp : List (Num a), Nat, Nat -> List (Num a) - quicksortHelp = \list, low, high -> - if low < high then - when partition low high list is - Pair partitionIndex partitioned -> - partitioned - |> quicksortHelp low (partitionIndex - 1) - |> quicksortHelp (partitionIndex + 1) high - else - list - - - swap : Nat, Nat, List a -> List a - swap = \i, j, list -> - when Pair (List.get list i) (List.get list j) is - Pair (Ok atI) (Ok atJ) -> - list - |> List.set i atJ - |> List.set j atI - - _ -> - [] - - partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] - partition = \low, high, initialList -> - when List.get initialList high is - Ok pivot -> - when partitionHelp (low - 1) low initialList high pivot is - Pair newI newList -> - Pair (newI + 1) (swap (newI + 1) high newList) - - Err _ -> - Pair (low - 1) initialList - - - partitionHelp : Nat, Nat, List (Num a), Nat, Num a -> [ Pair Nat (List (Num a)) ] - partitionHelp = \i, j, list, high, pivot -> - # if j < high then - if False then - when List.get list j is - Ok value -> - if value <= pivot then - partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot - else - partitionHelp i (j + 1) list high pivot - - Err _ -> - Pair i list - else - Pair i list - - - - quicksort [ 7, 4, 21, 19 ] - "# - ), - RocList::from_slice(&[19, 7, 4, 21]), - RocList - ); - }) - } - - #[test] - fn foobar() { - with_larger_debug_stack(|| { - assert_evals_to!( - indoc!( - r#" - quicksort : List (Num a) -> List (Num a) - quicksort = \list -> - quicksortHelp list 0 (List.len list - 1) - - - quicksortHelp : List (Num a), Nat, Nat -> List (Num a) - quicksortHelp = \list, low, high -> - if low < high then - when partition low high list is - Pair partitionIndex partitioned -> - partitioned - |> quicksortHelp low (partitionIndex - 1) - |> quicksortHelp (partitionIndex + 1) high - else - list - - - swap : Nat, Nat, List a -> List a - swap = \i, j, list -> - when Pair (List.get list i) (List.get list j) is - Pair (Ok atI) (Ok atJ) -> - list - |> List.set i atJ - |> List.set j atI - - _ -> - [] - - partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] - partition = \low, high, initialList -> - when List.get initialList high is - Ok pivot -> - when partitionHelp (low - 1) low initialList high pivot is - Pair newI newList -> - Pair (newI + 1) (swap (newI + 1) high newList) - - Err _ -> - Pair (low - 1) initialList - - - partitionHelp : Nat, Nat, List (Num a), Nat, Num a -> [ Pair Nat (List (Num a)) ] - partitionHelp = \i, j, list, high, pivot -> - if j < high then - when List.get list j is - Ok value -> - if value <= pivot then - partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot - else - partitionHelp i (j + 1) list high pivot - - Err _ -> - Pair i list - else - Pair i list - - - - when List.first (quicksort [0x1]) is - _ -> 4 - "# - ), - 4, - i64 - ); - }) - } - - #[test] - fn empty_list_increment_decrement() { - assert_evals_to!( - indoc!( - r#" - x : List I64 - x = [] - - List.len x + List.len x - "# + quicksort [ 7, 4, 21, 19 ] + "# ), - 0, - i64 - ); - } - - #[test] - fn list_literal_increment_decrement() { - assert_evals_to!( - indoc!( - r#" - x : List I64 - x = [1,2,3] - - List.len x + List.len x - "# - ), - 6, - i64 - ); - } - - #[test] - fn list_pass_to_function() { - assert_evals_to!( - indoc!( - r#" - x : List I64 - x = [1,2,3] - - id : List I64 -> List I64 - id = \y -> y - - id x - "# - ), - RocList::from_slice(&[1, 2, 3]), + RocList::from_slice(&[4, 7, 19, 21]), RocList ); - } - - #[test] - fn list_pass_to_set() { - assert_evals_to!( - indoc!( - r#" - x : List I64 - x = [1,2,3] - - id : List I64 -> List I64 - id = \y -> List.set y 0 0 - - id x - "# - ), - RocList::from_slice(&[0, 2, 3]), - RocList - ); - } - - #[test] - fn list_wrap_in_tag() { - assert_evals_to!( - indoc!( - r#" - id : List I64 -> [ Pair (List I64) I64 ] - id = \y -> Pair y 4 - - when id [1,2,3] is - Pair v _ -> v - "# - ), - RocList::from_slice(&[1, 2, 3]), - RocList - ); - } - - #[test] - fn list_contains() { - assert_evals_to!(indoc!("List.contains [1,2,3] 1"), true, bool); - - assert_evals_to!(indoc!("List.contains [1,2,3] 4"), false, bool); - - assert_evals_to!(indoc!("List.contains [] 4"), false, bool); - } - - #[test] - fn list_sum() { - assert_evals_to!("List.sum []", 0, i64); - assert_evals_to!("List.sum [ 1, 2, 3 ]", 6, i64); - assert_evals_to!("List.sum [ 1.1, 2.2, 3.3 ]", 6.6, f64); - } - - #[test] - fn list_keep_oks() { - assert_evals_to!("List.keepOks [] (\\x -> x)", 0, i64); - assert_evals_to!("List.keepOks [1,2] (\\x -> Ok x)", &[1, 2], &[i64]); - assert_evals_to!("List.keepOks [1,2] (\\x -> x % 2)", &[1, 0], &[i64]); - assert_evals_to!("List.keepOks [Ok 1, Err 2] (\\x -> x)", &[1], &[i64]); - } - - #[test] - fn list_keep_errs() { - assert_evals_to!("List.keepErrs [] (\\x -> x)", 0, i64); - assert_evals_to!("List.keepErrs [1,2] (\\x -> Err x)", &[1, 2], &[i64]); - assert_evals_to!( - "List.keepErrs [0,1,2] (\\x -> x % 0 |> Result.mapErr (\\_ -> 32))", - &[32, 32, 32], - &[i64] - ); - assert_evals_to!("List.keepErrs [Ok 1, Err 2] (\\x -> x)", &[2], &[i64]); - } - - #[test] - fn list_map_with_index() { - assert_evals_to!( - "List.mapWithIndex [0,0,0] (\\index, x -> index + x)", - &[0, 1, 2], - &[i64] - ); - } - - #[test] - #[should_panic(expected = r#"Roc failed with message: "integer addition overflowed!"#)] - fn cleanup_because_exception() { - assert_evals_to!( - indoc!( - r#" - x = [ 1,2 ] - 5 + Num.maxInt + 3 + List.len x - "# - ), - RocList::from_slice(&[false; 1]), - RocList - ); - } + }) +} + +#[test] +fn foobar2() { + with_larger_debug_stack(|| { + assert_evals_to!( + indoc!( + r#" + quicksort : List (Num a) -> List (Num a) + quicksort = \list -> + quicksortHelp list 0 (List.len list - 1) + + + quicksortHelp : List (Num a), Nat, Nat -> List (Num a) + quicksortHelp = \list, low, high -> + if low < high then + when partition low high list is + Pair partitionIndex partitioned -> + partitioned + |> quicksortHelp low (partitionIndex - 1) + |> quicksortHelp (partitionIndex + 1) high + else + list + + + swap : Nat, Nat, List a -> List a + swap = \i, j, list -> + when Pair (List.get list i) (List.get list j) is + Pair (Ok atI) (Ok atJ) -> + list + |> List.set i atJ + |> List.set j atI + + _ -> + [] + + partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] + partition = \low, high, initialList -> + when List.get initialList high is + Ok pivot -> + when partitionHelp (low - 1) low initialList high pivot is + Pair newI newList -> + Pair (newI + 1) (swap (newI + 1) high newList) + + Err _ -> + Pair (low - 1) initialList + + + partitionHelp : Nat, Nat, List (Num a), Nat, Num a -> [ Pair Nat (List (Num a)) ] + partitionHelp = \i, j, list, high, pivot -> + # if j < high then + if False then + when List.get list j is + Ok value -> + if value <= pivot then + partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot + else + partitionHelp i (j + 1) list high pivot + + Err _ -> + Pair i list + else + Pair i list + + + + quicksort [ 7, 4, 21, 19 ] + "# + ), + RocList::from_slice(&[19, 7, 4, 21]), + RocList + ); + }) +} + +#[test] +fn foobar() { + with_larger_debug_stack(|| { + assert_evals_to!( + indoc!( + r#" + quicksort : List (Num a) -> List (Num a) + quicksort = \list -> + quicksortHelp list 0 (List.len list - 1) + + + quicksortHelp : List (Num a), Nat, Nat -> List (Num a) + quicksortHelp = \list, low, high -> + if low < high then + when partition low high list is + Pair partitionIndex partitioned -> + partitioned + |> quicksortHelp low (partitionIndex - 1) + |> quicksortHelp (partitionIndex + 1) high + else + list + + + swap : Nat, Nat, List a -> List a + swap = \i, j, list -> + when Pair (List.get list i) (List.get list j) is + Pair (Ok atI) (Ok atJ) -> + list + |> List.set i atJ + |> List.set j atI + + _ -> + [] + + partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] + partition = \low, high, initialList -> + when List.get initialList high is + Ok pivot -> + when partitionHelp (low - 1) low initialList high pivot is + Pair newI newList -> + Pair (newI + 1) (swap (newI + 1) high newList) + + Err _ -> + Pair (low - 1) initialList + + + partitionHelp : Nat, Nat, List (Num a), Nat, Num a -> [ Pair Nat (List (Num a)) ] + partitionHelp = \i, j, list, high, pivot -> + if j < high then + when List.get list j is + Ok value -> + if value <= pivot then + partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot + else + partitionHelp i (j + 1) list high pivot + + Err _ -> + Pair i list + else + Pair i list + + + + when List.first (quicksort [0x1]) is + _ -> 4 + "# + ), + 4, + i64 + ); + }) +} + +#[test] +fn empty_list_increment_decrement() { + assert_evals_to!( + indoc!( + r#" + x : List I64 + x = [] + + List.len x + List.len x + "# + ), + 0, + i64 + ); +} + +#[test] +fn list_literal_increment_decrement() { + assert_evals_to!( + indoc!( + r#" + x : List I64 + x = [1,2,3] + + List.len x + List.len x + "# + ), + 6, + i64 + ); +} + +#[test] +fn list_pass_to_function() { + assert_evals_to!( + indoc!( + r#" + x : List I64 + x = [1,2,3] + + id : List I64 -> List I64 + id = \y -> y + + id x + "# + ), + RocList::from_slice(&[1, 2, 3]), + RocList + ); +} + +#[test] +fn list_pass_to_set() { + assert_evals_to!( + indoc!( + r#" + x : List I64 + x = [1,2,3] + + id : List I64 -> List I64 + id = \y -> List.set y 0 0 + + id x + "# + ), + RocList::from_slice(&[0, 2, 3]), + RocList + ); +} + +#[test] +fn list_wrap_in_tag() { + assert_evals_to!( + indoc!( + r#" + id : List I64 -> [ Pair (List I64) I64 ] + id = \y -> Pair y 4 + + when id [1,2,3] is + Pair v _ -> v + "# + ), + RocList::from_slice(&[1, 2, 3]), + RocList + ); +} + +#[test] +fn list_contains() { + assert_evals_to!(indoc!("List.contains [1,2,3] 1"), true, bool); + + assert_evals_to!(indoc!("List.contains [1,2,3] 4"), false, bool); + + assert_evals_to!(indoc!("List.contains [] 4"), false, bool); +} + +#[test] +fn list_sum() { + assert_evals_to!("List.sum []", 0, i64); + assert_evals_to!("List.sum [ 1, 2, 3 ]", 6, i64); + assert_evals_to!("List.sum [ 1.1, 2.2, 3.3 ]", 6.6, f64); +} + +#[test] +fn list_keep_oks() { + assert_evals_to!("List.keepOks [] (\\x -> x)", 0, i64); + assert_evals_to!("List.keepOks [1,2] (\\x -> Ok x)", &[1, 2], &[i64]); + assert_evals_to!("List.keepOks [1,2] (\\x -> x % 2)", &[1, 0], &[i64]); + assert_evals_to!("List.keepOks [Ok 1, Err 2] (\\x -> x)", &[1], &[i64]); +} + +#[test] +fn list_keep_errs() { + assert_evals_to!("List.keepErrs [] (\\x -> x)", 0, i64); + assert_evals_to!("List.keepErrs [1,2] (\\x -> Err x)", &[1, 2], &[i64]); + assert_evals_to!( + "List.keepErrs [0,1,2] (\\x -> x % 0 |> Result.mapErr (\\_ -> 32))", + &[32, 32, 32], + &[i64] + ); + assert_evals_to!("List.keepErrs [Ok 1, Err 2] (\\x -> x)", &[2], &[i64]); +} + +#[test] +fn list_map_with_index() { + assert_evals_to!( + "List.mapWithIndex [0,0,0] (\\index, x -> index + x)", + &[0, 1, 2], + &[i64] + ); +} + +#[test] +#[should_panic(expected = r#"Roc failed with message: "integer addition overflowed!"#)] +fn cleanup_because_exception() { + assert_evals_to!( + indoc!( + r#" + x = [ 1,2 ] + 5 + Num.maxInt + 3 + List.len x + "# + ), + RocList::from_slice(&[false; 1]), + RocList + ); } diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index f6976de9e0..9ea315abfa 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1,18 +1,8 @@ -#[macro_use] -extern crate pretty_assertions; -#[macro_use] -extern crate indoc; - -extern crate bumpalo; -extern crate inkwell; -extern crate libc; -extern crate roc_gen; - -#[macro_use] -mod helpers; - #[cfg(test)] mod gen_num { + use crate::assert_evals_to; + use crate::assert_llvm_evals_to; + use indoc::indoc; use roc_std::RocOrder; #[test] diff --git a/compiler/test_gen/src/gen_records.rs b/compiler/test_gen/src/gen_records.rs index bed2cad4ea..7ebb2f583e 100644 --- a/compiler/test_gen/src/gen_records.rs +++ b/compiler/test_gen/src/gen_records.rs @@ -1,410 +1,401 @@ -#[macro_use] -extern crate pretty_assertions; -#[macro_use] -extern crate indoc; +#![cfg(test)] -extern crate bumpalo; -extern crate inkwell; -extern crate libc; -extern crate roc_gen; +use crate::assert_evals_to; +use crate::assert_llvm_evals_to; +use indoc::indoc; -#[macro_use] -mod helpers; - -#[cfg(test)] -mod gen_records { - #[test] - fn basic_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn basic_record() { + assert_evals_to!( + indoc!( + r#" { y: 17, x: 15, z: 19 }.x "# - ), - 15, - i64 - ); + ), + 15, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" { x: 15, y: 17, z: 19 }.y "# - ), - 17, - i64 - ); + ), + 17, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" { x: 15, y: 17, z: 19 }.z "# - ), - 19, - i64 - ); - } + ), + 19, + i64 + ); +} - #[test] - fn f64_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn f64_record() { + assert_evals_to!( + indoc!( + r#" rec = { y: 17.2, x: 15.1, z: 19.3 } rec.x "# - ), - 15.1, - f64 - ); + ), + 15.1, + f64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" rec = { y: 17.2, x: 15.1, z: 19.3 } rec.y "# - ), - 17.2, - f64 - ); + ), + 17.2, + f64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" rec = { y: 17.2, x: 15.1, z: 19.3 } rec.z "# - ), - 19.3, - f64 - ); - } + ), + 19.3, + f64 + ); +} - #[test] - fn fn_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn fn_record() { + assert_evals_to!( + indoc!( + r#" getRec = \x -> { y: 17, x, z: 19 } (getRec 15).x "# - ), - 15, - i64 - ); + ), + 15, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" rec = { x: 15, y: 17, z: 19 } rec.y "# - ), - 17, - i64 - ); + ), + 17, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" rec = { x: 15, y: 17, z: 19 } rec.z "# - ), - 19, - i64 - ); + ), + 19, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" rec = { x: 15, y: 17, z: 19 } rec.z + rec.x "# - ), - 34, - i64 - ); - } + ), + 34, + i64 + ); +} - #[test] - fn def_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn def_record() { + assert_evals_to!( + indoc!( + r#" rec = { y: 17, x: 15, z: 19 } rec.x "# - ), - 15, - i64 - ); + ), + 15, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" rec = { x: 15, y: 17, z: 19 } rec.y "# - ), - 17, - i64 - ); + ), + 17, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" rec = { x: 15, y: 17, z: 19 } rec.z "# - ), - 19, - i64 - ); - } + ), + 19, + i64 + ); +} - #[test] - fn when_on_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn when_on_record() { + assert_evals_to!( + indoc!( + r#" when { x: 0x2 } is { x } -> x + 3 "# - ), - 5, - i64 - ); - } + ), + 5, + i64 + ); +} - #[test] - fn when_record_with_guard_pattern() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + 5, + i64 + ); +} - #[test] - fn let_with_record_pattern() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn let_with_record_pattern() { + assert_evals_to!( + indoc!( + r#" { x } = { x: 0x2, y: 3.14 } x "# - ), - 2, - i64 - ); - } + ), + 2, + i64 + ); +} - #[test] - fn record_guard_pattern() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + 5, + i64 + ); +} - #[test] - fn twice_record_access() { - assert_evals_to!( - indoc!( - r#" +#[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#" + ), + 5, + i64 + ); +} +#[test] +fn empty_record() { + assert_evals_to!( + indoc!( + r#" v = {} v "# - ), - (), - () - ); - } - #[test] - fn i64_record2_literal() { - assert_evals_to!( - indoc!( - r#" + ), + (), + () + ); +} +#[test] +fn i64_record2_literal() { + assert_evals_to!( + indoc!( + r#" { x: 3, y: 5 } "# - ), - (3, 5), - (i64, i64) - ); - } + ), + (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 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#" +#[test] +fn f64_record2_literal() { + assert_evals_to!( + indoc!( + r#" { x: 3.1, y: 5.1 } "# - ), - (3.1, 5.1), - (f64, f64) - ); - } + ), + (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 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 } +// #[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) - // ); - // } +// record +// "# +// ), +// (true, false, false, true), +// (bool, bool, bool, bool) +// ); +// } - #[test] - fn i64_record1_literal() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn i64_record1_literal() { + assert_evals_to!( + indoc!( + r#" { a: 3 } "# - ), - 3, - i64 - ); - } + ), + 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 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 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#" +#[test] +fn bool_literal() { + assert_evals_to!( + indoc!( + r#" x : Bool x = True x "# - ), - true, - bool - ); - } + ), + true, + bool + ); +} - #[test] - fn return_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn return_record() { + assert_evals_to!( + indoc!( + r#" x = 4 y = 3 { x, y } "# - ), - (4, 3), - (i64, i64) - ); - } + ), + (4, 3), + (i64, i64) + ); +} - #[test] - fn optional_field_when_use_default() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn optional_field_when_use_default() { + assert_evals_to!( + indoc!( + r#" app "test" provides [ main ] to "./platform" f = \r -> @@ -421,17 +412,17 @@ mod gen_records { a * b * c * d "# - ), - 3 * 5 * 7 * 11, - i64 - ); - } + ), + 3 * 5 * 7 * 11, + i64 + ); +} - #[test] - fn optional_field_when_use_default_nested() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn optional_field_when_use_default_nested() { + assert_evals_to!( + indoc!( + r#" f = \r -> when r is { x: Blue, y ? 3 } -> y @@ -444,17 +435,17 @@ mod gen_records { a * b * c * d "# - ), - 3 * 5 * 7 * 11, - i64 - ); - } + ), + 3 * 5 * 7 * 11, + i64 + ); +} - #[test] - fn optional_field_when_no_use_default() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn optional_field_when_no_use_default() { + assert_evals_to!( + indoc!( + r#" app "test" provides [ main ] to "./platform" f = \r -> @@ -464,34 +455,34 @@ mod gen_records { main = f { x: 4, y: 9 } "# - ), - 13, - i64 - ); - } + ), + 13, + i64 + ); +} - #[test] - fn optional_field_when_no_use_default_nested() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + 13, + i64 + ); +} - #[test] - fn optional_field_let_use_default() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn optional_field_let_use_default() { + assert_evals_to!( + indoc!( + r#" app "test" provides [ main ] to "./platform" f = \r -> @@ -501,17 +492,17 @@ mod gen_records { main = f { y: 9 } "# - ), - 19, - i64 - ); - } + ), + 19, + i64 + ); +} - #[test] - fn optional_field_let_no_use_default() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn optional_field_let_no_use_default() { + assert_evals_to!( + indoc!( + r#" app "test" provides [ main ] to "./platform" f = \r -> @@ -521,52 +512,52 @@ mod gen_records { main = f { x: 4, y: 9 } "# - ), - 13, - i64 - ); - } + ), + 13, + i64 + ); +} - #[test] - fn optional_field_let_no_use_default_nested() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + 13, + i64 + ); +} - #[test] - fn optional_field_function_use_default() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn optional_field_function_use_default() { + assert_evals_to!( + indoc!( + r#" f = \{ x ? 10, y } -> x + y f { y: 9 } "# - ), - 19, - i64 - ); - } + ), + 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#" +#[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 @@ -574,295 +565,295 @@ mod gen_records { main = f { x: 4, y: 9 } "# - ), - 13, - i64 - ); - } + ), + 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#" +#[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 - ); - } + ), + 13, + i64 + ); +} - #[test] - fn optional_field_singleton_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn optional_field_singleton_record() { + assert_evals_to!( + indoc!( + r#" when { x : 4 } is { x ? 3 } -> x "# - ), - 4, - i64 - ); - } + ), + 4, + i64 + ); +} - #[test] - fn optional_field_empty_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn optional_field_empty_record() { + assert_evals_to!( + indoc!( + r#" when { } is { x ? 3 } -> x "# - ), - 3, - i64 - ); - } + ), + 3, + i64 + ); +} - #[test] - fn return_record_2() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn return_record_2() { + assert_evals_to!( + indoc!( + r#" { x: 3, y: 5 } "# - ), - [3, 5], - [i64; 2] - ); - } + ), + [3, 5], + [i64; 2] + ); +} - #[test] - fn return_record_3() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn return_record_3() { + assert_evals_to!( + indoc!( + r#" { x: 3, y: 5, z: 4 } "# - ), - (3, 5, 4), - (i64, i64, i64) - ); - } + ), + (3, 5, 4), + (i64, i64, i64) + ); +} - #[test] - fn return_record_4() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn return_record_4() { + assert_evals_to!( + indoc!( + r#" { a: 3, b: 5, c: 4, d: 2 } "# - ), - [3, 5, 4, 2], - [i64; 4] - ); - } + ), + [3, 5, 4, 2], + [i64; 4] + ); +} - #[test] - fn return_record_5() { - assert_evals_to!( - indoc!( - r#" +#[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] - ); - } + ), + [3, 5, 4, 2, 1], + [i64; 5] + ); +} - #[test] - fn return_record_6() { - assert_evals_to!( - indoc!( - r#" +#[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] - ); - } + ), + [3, 5, 4, 2, 1, 7], + [i64; 6] + ); +} - #[test] - fn return_record_7() { - assert_evals_to!( - indoc!( - r#" +#[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] - ); - } + ), + [3, 5, 4, 2, 1, 7, 8], + [i64; 7] + ); +} - #[test] - fn return_record_float_int() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn return_record_float_int() { + assert_evals_to!( + indoc!( + r#" { a: 3.14, b: 0x1 } "# - ), - (3.14, 0x1), - (f64, i64) - ); - } + ), + (3.14, 0x1), + (f64, i64) + ); +} - #[test] - fn return_record_int_float() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn return_record_int_float() { + assert_evals_to!( + indoc!( + r#" { a: 0x1, b: 3.14 } "# - ), - (0x1, 3.14), - (i64, f64) - ); - } + ), + (0x1, 3.14), + (i64, f64) + ); +} - #[test] - fn return_record_float_float() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn return_record_float_float() { + assert_evals_to!( + indoc!( + r#" { a: 6.28, b: 3.14 } "# - ), - (6.28, 3.14), - (f64, f64) - ); - } + ), + (6.28, 3.14), + (f64, f64) + ); +} - #[test] - fn return_record_float_float_float() { - assert_evals_to!( - indoc!( - r#" +#[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) - ); - } + ), + (6.28, 3.14, 0.1), + (f64, f64, f64) + ); +} - #[test] - fn return_nested_record() { - assert_evals_to!( - indoc!( - r#" +#[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)) - ); - } + ), + (0x0, (6.28, 3.14, 0.1)), + (i64, (f64, f64, f64)) + ); +} - #[test] - fn accessor() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn accessor() { + assert_evals_to!( + indoc!( + r#" .foo { foo: 4 } + .foo { bar: 6.28, foo: 3 } "# - ), - 7, - i64 - ); - } + ), + 7, + i64 + ); +} - #[test] - fn accessor_single_element_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn accessor_single_element_record() { + assert_evals_to!( + indoc!( + r#" .foo { foo: 4 } "# - ), - 4, - i64 - ); - } + ), + 4, + i64 + ); +} - #[test] - fn update_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn update_record() { + assert_evals_to!( + indoc!( + r#" rec = { foo: 42, bar: 6.28 } { rec & foo: rec.foo + 1 } "# - ), - (6.28, 43), - (f64, i64) - ); - } + ), + (6.28, 43), + (f64, i64) + ); +} - #[test] - fn update_single_element_record() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn update_single_element_record() { + assert_evals_to!( + indoc!( + r#" rec = { foo: 42} { rec & foo: rec.foo + 1 } "# - ), - 43, - i64 - ); - } + ), + 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 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 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#" +#[test] +fn blue_and_present() { + assert_evals_to!( + indoc!( + r#" f = \r -> when r is { x: Blue, y ? 3 } -> y @@ -870,17 +861,17 @@ mod gen_records { f { x: Blue, y: 7 } "# - ), - 7, - i64 - ); - } + ), + 7, + i64 + ); +} - #[test] - fn blue_and_absent() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn blue_and_absent() { + assert_evals_to!( + indoc!( + r#" f = \r -> when r is { x: Blue, y ? 3 } -> y @@ -888,9 +879,8 @@ mod gen_records { f { x: Blue } "# - ), - 3, - i64 - ); - } + ), + 3, + i64 + ); } diff --git a/compiler/test_gen/src/gen_result.rs b/compiler/test_gen/src/gen_result.rs index be63bf39ca..7bf4bd507e 100644 --- a/compiler/test_gen/src/gen_result.rs +++ b/compiler/test_gen/src/gen_result.rs @@ -1,111 +1,100 @@ -#[macro_use] -extern crate pretty_assertions; -#[macro_use] -extern crate indoc; +#![cfg(test)] -extern crate bumpalo; -extern crate inkwell; -extern crate libc; -extern crate roc_gen; +use crate::assert_evals_to; +use crate::assert_llvm_evals_to; +use indoc::indoc; -#[macro_use] -mod helpers; +#[test] +fn with_default() { + assert_evals_to!( + indoc!( + r#" + result : Result I64 {} + result = Ok 2 -#[cfg(test)] -mod gen_result { + Result.withDefault result 0 + "# + ), + 2, + i64 + ); - #[test] - fn with_default() { - assert_evals_to!( - indoc!( - r#" - result : Result I64 {} - result = Ok 2 + assert_evals_to!( + indoc!( + r#" + result : Result I64 {} + result = Err {} - Result.withDefault result 0 - "# - ), - 2, - i64 - ); - - assert_evals_to!( - indoc!( - r#" - result : Result I64 {} - result = Err {} - - Result.withDefault result 0 - "# - ), - 0, - i64 - ); - } - - #[test] - fn result_map() { - assert_evals_to!( - indoc!( - r#" - result : Result I64 {} - result = Ok 2 - - result - |> Result.map (\x -> x + 1) - |> Result.withDefault 0 - "# - ), - 3, - i64 - ); - - assert_evals_to!( - indoc!( - r#" - result : Result I64 {} - result = Err {} - - result - |> Result.map (\x -> x + 1) - |> Result.withDefault 0 - "# - ), - 0, - i64 - ); - } - - #[test] - fn result_map_err() { - assert_evals_to!( - indoc!( - r#" - result : Result {} I64 - result = Err 2 - - when Result.mapErr result (\x -> x + 1) is - Err n -> n - Ok _ -> 0 - "# - ), - 3, - i64 - ); - - assert_evals_to!( - indoc!( - r#" - result : Result {} I64 - result = Ok {} - - when Result.mapErr result (\x -> x + 1) is - Err n -> n - Ok _ -> 0 - "# - ), - 0, - i64 - ); - } + Result.withDefault result 0 + "# + ), + 0, + i64 + ); +} + +#[test] +fn result_map() { + assert_evals_to!( + indoc!( + r#" + result : Result I64 {} + result = Ok 2 + + result + |> Result.map (\x -> x + 1) + |> Result.withDefault 0 + "# + ), + 3, + i64 + ); + + assert_evals_to!( + indoc!( + r#" + result : Result I64 {} + result = Err {} + + result + |> Result.map (\x -> x + 1) + |> Result.withDefault 0 + "# + ), + 0, + i64 + ); +} + +#[test] +fn result_map_err() { + assert_evals_to!( + indoc!( + r#" + result : Result {} I64 + result = Err 2 + + when Result.mapErr result (\x -> x + 1) is + Err n -> n + Ok _ -> 0 + "# + ), + 3, + i64 + ); + + assert_evals_to!( + indoc!( + r#" + result : Result {} I64 + result = Ok {} + + when Result.mapErr result (\x -> x + 1) is + Err n -> n + Ok _ -> 0 + "# + ), + 0, + i64 + ); } diff --git a/compiler/test_gen/src/gen_set.rs b/compiler/test_gen/src/gen_set.rs index 012eaf64ab..675de02a58 100644 --- a/compiler/test_gen/src/gen_set.rs +++ b/compiler/test_gen/src/gen_set.rs @@ -1,248 +1,237 @@ -#[macro_use] -extern crate pretty_assertions; -#[macro_use] -extern crate indoc; +#![cfg(test)] -extern crate bumpalo; -extern crate inkwell; -extern crate libc; -extern crate roc_gen; +use crate::assert_evals_to; +use crate::assert_llvm_evals_to; +use indoc::indoc; -#[macro_use] -mod helpers; - -#[cfg(test)] -mod gen_set { - - #[test] - fn empty_len() { - assert_evals_to!( - indoc!( - r#" - Set.len Set.empty - "# - ), - 0, - usize - ); - } - - #[test] - fn singleton_len() { - assert_evals_to!( - indoc!( - r#" - Set.len (Set.singleton 42) - "# - ), - 1, - usize - ); - } - - #[test] - fn singleton_to_list() { - assert_evals_to!( - indoc!( - r#" - Set.toList (Set.singleton 42) - "# - ), - &[42], - &[i64] - ); - - assert_evals_to!( - indoc!( - r#" - Set.toList (Set.singleton 1) - "# - ), - &[1], - &[i64] - ); - - assert_evals_to!( - indoc!( - r#" - Set.toList (Set.singleton 1.0) - "# - ), - &[1.0], - &[f64] - ); - } - - #[test] - fn insert() { - assert_evals_to!( - indoc!( - r#" - Set.empty - |> Set.insert 0 - |> Set.insert 1 - |> Set.insert 2 - |> Set.toList - "# - ), - &[0, 1, 2], - &[i64] - ); - } - - #[test] - fn remove() { - assert_evals_to!( - indoc!( - r#" - Set.empty - |> Set.insert 0 - |> Set.insert 1 - |> Set.remove 1 - |> Set.remove 2 - |> Set.toList - "# - ), - &[0], - &[i64] - ); - } - - #[test] - fn union() { - assert_evals_to!( - indoc!( - r#" - set1 : Set I64 - set1 = Set.fromList [1,2] - - set2 : Set I64 - set2 = Set.fromList [1,3,4] - - Set.union set1 set2 - |> Set.toList - "# - ), - &[4, 2, 3, 1], - &[i64] - ); - } - - #[test] - fn difference() { - assert_evals_to!( - indoc!( - r#" - set1 : Set I64 - set1 = Set.fromList [1,2] - - set2 : Set I64 - set2 = Set.fromList [1,3,4] - - Set.difference set1 set2 - |> Set.toList - "# - ), - &[2], - &[i64] - ); - } - - #[test] - fn intersection() { - assert_evals_to!( - indoc!( - r#" - set1 : Set I64 - set1 = Set.fromList [1,2] - - set2 : Set I64 - set2 = Set.fromList [1,3,4] - - Set.intersection set1 set2 - |> Set.toList - "# - ), - &[1], - &[i64] - ); - } - - #[test] - fn walk_sum() { - assert_evals_to!( - indoc!( - r#" - Set.walk (Set.fromList [1,2,3]) (\x, y -> x + y) 0 - "# - ), - 6, - i64 - ); - } - - #[test] - fn contains() { - assert_evals_to!( - indoc!( - r#" - Set.contains (Set.fromList [1,3,4]) 4 - "# - ), - true, - bool - ); - - assert_evals_to!( - indoc!( - r#" - Set.contains (Set.fromList [1,3,4]) 2 - "# - ), - false, - bool - ); - } - - #[test] - fn from_list() { - assert_evals_to!( - indoc!( - r#" - [1,2,2,3,1,4] - |> Set.fromList - |> Set.toList - "# - ), - &[4, 2, 3, 1], - &[i64] - ); - - assert_evals_to!( - indoc!( - r#" - [] - |> Set.fromList - |> Set.toList - "# - ), - &[], - &[i64] - ); - - assert_evals_to!( - indoc!( - r#" - empty : List I64 - empty = [] - - empty - |> Set.fromList - |> Set.toList - "# - ), - &[], - &[i64] - ); - } +#[test] +fn empty_len() { + assert_evals_to!( + indoc!( + r#" + Set.len Set.empty + "# + ), + 0, + usize + ); +} + +#[test] +fn singleton_len() { + assert_evals_to!( + indoc!( + r#" + Set.len (Set.singleton 42) + "# + ), + 1, + usize + ); +} + +#[test] +fn singleton_to_list() { + assert_evals_to!( + indoc!( + r#" + Set.toList (Set.singleton 42) + "# + ), + &[42], + &[i64] + ); + + assert_evals_to!( + indoc!( + r#" + Set.toList (Set.singleton 1) + "# + ), + &[1], + &[i64] + ); + + assert_evals_to!( + indoc!( + r#" + Set.toList (Set.singleton 1.0) + "# + ), + &[1.0], + &[f64] + ); +} + +#[test] +fn insert() { + assert_evals_to!( + indoc!( + r#" + Set.empty + |> Set.insert 0 + |> Set.insert 1 + |> Set.insert 2 + |> Set.toList + "# + ), + &[0, 1, 2], + &[i64] + ); +} + +#[test] +fn remove() { + assert_evals_to!( + indoc!( + r#" + Set.empty + |> Set.insert 0 + |> Set.insert 1 + |> Set.remove 1 + |> Set.remove 2 + |> Set.toList + "# + ), + &[0], + &[i64] + ); +} + +#[test] +fn union() { + assert_evals_to!( + indoc!( + r#" + set1 : Set I64 + set1 = Set.fromList [1,2] + + set2 : Set I64 + set2 = Set.fromList [1,3,4] + + Set.union set1 set2 + |> Set.toList + "# + ), + &[4, 2, 3, 1], + &[i64] + ); +} + +#[test] +fn difference() { + assert_evals_to!( + indoc!( + r#" + set1 : Set I64 + set1 = Set.fromList [1,2] + + set2 : Set I64 + set2 = Set.fromList [1,3,4] + + Set.difference set1 set2 + |> Set.toList + "# + ), + &[2], + &[i64] + ); +} + +#[test] +fn intersection() { + assert_evals_to!( + indoc!( + r#" + set1 : Set I64 + set1 = Set.fromList [1,2] + + set2 : Set I64 + set2 = Set.fromList [1,3,4] + + Set.intersection set1 set2 + |> Set.toList + "# + ), + &[1], + &[i64] + ); +} + +#[test] +fn walk_sum() { + assert_evals_to!( + indoc!( + r#" + Set.walk (Set.fromList [1,2,3]) (\x, y -> x + y) 0 + "# + ), + 6, + i64 + ); +} + +#[test] +fn contains() { + assert_evals_to!( + indoc!( + r#" + Set.contains (Set.fromList [1,3,4]) 4 + "# + ), + true, + bool + ); + + assert_evals_to!( + indoc!( + r#" + Set.contains (Set.fromList [1,3,4]) 2 + "# + ), + false, + bool + ); +} + +#[test] +fn from_list() { + assert_evals_to!( + indoc!( + r#" + [1,2,2,3,1,4] + |> Set.fromList + |> Set.toList + "# + ), + &[4, 2, 3, 1], + &[i64] + ); + + assert_evals_to!( + indoc!( + r#" + [] + |> Set.fromList + |> Set.toList + "# + ), + &[], + &[i64] + ); + + assert_evals_to!( + indoc!( + r#" + empty : List I64 + empty = [] + + empty + |> Set.fromList + |> Set.toList + "# + ), + &[], + &[i64] + ); } diff --git a/compiler/test_gen/src/gen_str.rs b/compiler/test_gen/src/gen_str.rs index 53bfa1f53e..a5dc3818d6 100644 --- a/compiler/test_gen/src/gen_str.rs +++ b/compiler/test_gen/src/gen_str.rs @@ -1,64 +1,51 @@ -#[macro_use] -extern crate pretty_assertions; -#[macro_use] -extern crate indoc; - -extern crate bumpalo; -extern crate inkwell; -extern crate libc; -extern crate roc_gen; +#![cfg(test)] +use crate::assert_evals_to; +use crate::assert_llvm_evals_to; +use indoc::indoc; use roc_std::RocStr; - -#[macro_use] -mod helpers; +use std::cmp::min; const ROC_STR_MEM_SIZE: usize = core::mem::size_of::(); -#[cfg(test)] -mod gen_str { - use crate::ROC_STR_MEM_SIZE; - use roc_std::RocStr; - use std::cmp::min; +fn small_str(str: &str) -> [u8; ROC_STR_MEM_SIZE] { + let mut bytes: [u8; ROC_STR_MEM_SIZE] = Default::default(); - fn small_str(str: &str) -> [u8; ROC_STR_MEM_SIZE] { - let mut bytes: [u8; ROC_STR_MEM_SIZE] = Default::default(); - - let mut index: usize = 0; - while index < ROC_STR_MEM_SIZE { - bytes[index] = 0; - index += 1; - } - - let str_bytes = str.as_bytes(); - - let output_len: usize = min(str_bytes.len(), ROC_STR_MEM_SIZE); - index = 0; - while index < output_len { - bytes[index] = str_bytes[index]; - index += 1; - } - - bytes[ROC_STR_MEM_SIZE - 1] = 0b1000_0000 ^ (output_len as u8); - - bytes + let mut index: usize = 0; + while index < ROC_STR_MEM_SIZE { + bytes[index] = 0; + index += 1; } - #[test] - fn str_split_bigger_delimiter_small_str() { - assert_evals_to!( - indoc!( - r#" + let str_bytes = str.as_bytes(); + + let output_len: usize = min(str_bytes.len(), ROC_STR_MEM_SIZE); + index = 0; + while index < output_len { + bytes[index] = str_bytes[index]; + index += 1; + } + + bytes[ROC_STR_MEM_SIZE - 1] = 0b1000_0000 ^ (output_len as u8); + + bytes +} + +#[test] +fn str_split_bigger_delimiter_small_str() { + assert_evals_to!( + indoc!( + r#" List.len (Str.split "hello" "JJJJ there") "# - ), - 1, - i64 - ); + ), + 1, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" when List.first (Str.split "JJJ" "JJJJ there") is Ok str -> Str.countGraphemes str @@ -67,17 +54,17 @@ mod gen_str { -1 "# - ), - 3, - i64 - ); - } + ), + 3, + i64 + ); +} - #[test] - fn str_split_str_concat_repeated() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn str_split_str_concat_repeated() { + assert_evals_to!( + indoc!( + r#" when List.first (Str.split "JJJJJ" "JJJJ there") is Ok str -> str @@ -90,17 +77,17 @@ mod gen_str { "Not Str!" "# - ), - "JJJJJJJJJJJJJJJJJJJJJJJJJ", - &'static str - ); - } + ), + "JJJJJJJJJJJJJJJJJJJJJJJJJ", + &'static str + ); +} - #[test] - fn str_split_small_str_bigger_delimiter() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn str_split_small_str_bigger_delimiter() { + assert_evals_to!( + indoc!( + r#" when List.first (Str.split "JJJ" "0123456789abcdefghi") @@ -108,135 +95,135 @@ mod gen_str { Ok str -> str _ -> "" "# - ), - small_str("JJJ"), - [u8; ROC_STR_MEM_SIZE] - ); - } + ), + small_str("JJJ"), + [u8; ROC_STR_MEM_SIZE] + ); +} - #[test] - fn str_split_big_str_small_delimiter() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn str_split_big_str_small_delimiter() { + assert_evals_to!( + indoc!( + r#" Str.split "01234567789abcdefghi?01234567789abcdefghi" "?" "# - ), - &["01234567789abcdefghi", "01234567789abcdefghi"], - &'static [&'static str] - ); + ), + &["01234567789abcdefghi", "01234567789abcdefghi"], + &'static [&'static str] + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" Str.split "01234567789abcdefghi 3ch 01234567789abcdefghi" "3ch" "# - ), - &["01234567789abcdefghi ", " 01234567789abcdefghi"], - &'static [&'static str] - ); - } + ), + &["01234567789abcdefghi ", " 01234567789abcdefghi"], + &'static [&'static str] + ); +} - #[test] - fn str_split_small_str_small_delimiter() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn str_split_small_str_small_delimiter() { + assert_evals_to!( + indoc!( + r#" Str.split "J!J!J" "!" "# - ), - &[small_str("J"), small_str("J"), small_str("J")], - &'static [[u8; ROC_STR_MEM_SIZE]] - ); - } + ), + &[small_str("J"), small_str("J"), small_str("J")], + &'static [[u8; ROC_STR_MEM_SIZE]] + ); +} - #[test] - fn str_split_bigger_delimiter_big_strs() { - assert_evals_to!( - indoc!( - r#" +#[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" "# - ), - &["string to split is shorter"], - &'static [&'static str] - ); - } + ), + &["string to split is shorter"], + &'static [&'static str] + ); +} - #[test] - fn str_split_empty_strs() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn str_split_empty_strs() { + assert_evals_to!( + indoc!( + r#" Str.split "" "" "# - ), - &[small_str("")], - &'static [[u8; ROC_STR_MEM_SIZE]] - ) - } + ), + &[small_str("")], + &'static [[u8; ROC_STR_MEM_SIZE]] + ) +} - #[test] - fn str_split_minimal_example() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn str_split_minimal_example() { + assert_evals_to!( + indoc!( + r#" Str.split "a," "," "# - ), - &[small_str("a"), small_str("")], - &'static [[u8; ROC_STR_MEM_SIZE]] - ) - } + ), + &[small_str("a"), small_str("")], + &'static [[u8; ROC_STR_MEM_SIZE]] + ) +} - #[test] - fn str_split_small_str_big_delimiter() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn str_split_small_str_big_delimiter() { + assert_evals_to!( + indoc!( + r#" Str.split "1---- ---- ---- ---- ----2---- ---- ---- ---- ----" "---- ---- ---- ---- ----" |> List.len "# - ), - 3, - i64 - ); + ), + 3, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" Str.split "1---- ---- ---- ---- ----2---- ---- ---- ---- ----" "---- ---- ---- ---- ----" "# - ), - &[small_str("1"), small_str("2"), small_str("")], - &'static [[u8; ROC_STR_MEM_SIZE]] - ); - } + ), + &[small_str("1"), small_str("2"), small_str("")], + &'static [[u8; ROC_STR_MEM_SIZE]] + ); +} - #[test] - fn str_split_small_str_20_char_delimiter() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn str_split_small_str_20_char_delimiter() { + assert_evals_to!( + indoc!( + r#" Str.split "3|-- -- -- -- -- -- |4|-- -- -- -- -- -- |" "|-- -- -- -- -- -- |" "# - ), - &[small_str("3"), small_str("4"), small_str("")], - &'static [[u8; ROC_STR_MEM_SIZE]] - ); - } + ), + &[small_str("3"), small_str("4"), small_str("")], + &'static [[u8; ROC_STR_MEM_SIZE]] + ); +} - #[test] - fn str_concat_big_to_big() { - assert_evals_to!( +#[test] +fn str_concat_big_to_big() { + assert_evals_to!( indoc!( r#" Str.concat @@ -247,385 +234,385 @@ mod gen_str { "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.", &'static str ); - } +} - #[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_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_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_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_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""#, - "abc this is longer than 15 chars", - &'static str - ); - } +#[test] +fn small_str_concat_small_to_big() { + assert_evals_to!( + r#"Str.concat "abc" " this is longer than 15 chars""#, + "abc this is longer than 15 chars", + &'static str + ); +} - #[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_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""#, - "abcdefghijklmnopqrstuvwxyz", - &'static str - ); - } +#[test] +fn small_str_concat_small_to_small_overflow_to_big() { + assert_evals_to!( + r#"Str.concat "abcdefghijklm" "nopqrstuvwxyz""#, + "abcdefghijklmnopqrstuvwxyz", + &'static str + ); +} - #[test] - fn str_concat_empty() { - assert_evals_to!(r#"Str.concat "" """#, "", &'static str); - } +#[test] +fn str_concat_empty() { + assert_evals_to!(r#"Str.concat "" """#, "", &'static str); +} - #[test] - fn small_str_is_empty() { - assert_evals_to!(r#"Str.isEmpty "abc""#, false, bool); - } +#[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 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 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() { + 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_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_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_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_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_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_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_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_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_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 - ); +#[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"#, &max, &'static str); + let max = format!("{}", i64::MAX); + assert_evals_to!(r#"Str.fromInt Num.maxInt"#, &max, &'static str); - let min = format!("{}", i64::MIN); - assert_evals_to!(r#"Str.fromInt Num.minInt"#, &min, &'static str); - } + let min = format!("{}", i64::MIN); + assert_evals_to!(r#"Str.fromInt Num.minInt"#, &min, &'static str); +} - #[test] - fn str_from_utf8_pass_single_ascii() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + roc_std::RocStr::from_slice("a".as_bytes()), + roc_std::RocStr + ); +} - #[test] - fn str_from_utf8_pass_many_ascii() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + roc_std::RocStr::from_slice("abc~".as_bytes()), + roc_std::RocStr + ); +} - #[test] - fn str_from_utf8_pass_single_unicode() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + roc_std::RocStr::from_slice("∆".as_bytes()), + roc_std::RocStr + ); +} - #[test] - fn str_from_utf8_pass_many_unicode() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + roc_std::RocStr::from_slice("∆œ¬".as_bytes()), + roc_std::RocStr + ); +} - #[test] - fn str_from_utf8_pass_single_grapheme() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + roc_std::RocStr::from_slice("💖".as_bytes()), + roc_std::RocStr + ); +} - #[test] - fn str_from_utf8_pass_many_grapheme() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + roc_std::RocStr::from_slice("💖🤠🚀".as_bytes()), + roc_std::RocStr + ); +} - #[test] - fn str_from_utf8_pass_all() { - assert_evals_to!( - indoc!( - r#" +#[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 - ); - } + ), + 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#" +#[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 @@ -634,17 +621,17 @@ mod gen_str { "b" _ -> "" "# - ), - roc_std::RocStr::from_slice("a".as_bytes()), - roc_std::RocStr - ); - } + ), + 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#" +#[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 @@ -653,17 +640,17 @@ mod gen_str { "b" _ -> "" "# - ), - roc_std::RocStr::from_slice("a".as_bytes()), - roc_std::RocStr - ); - } + ), + roc_std::RocStr::from_slice("a".as_bytes()), + roc_std::RocStr + ); +} - #[test] - fn str_from_utf8_fail_expected_continuation() { - assert_evals_to!( - indoc!( - r#" +#[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 @@ -672,17 +659,17 @@ mod gen_str { "b" _ -> "" "# - ), - roc_std::RocStr::from_slice("a".as_bytes()), - roc_std::RocStr - ); - } + ), + roc_std::RocStr::from_slice("a".as_bytes()), + roc_std::RocStr + ); +} - #[test] - fn str_from_utf8_fail_overlong_encoding() { - assert_evals_to!( - indoc!( - r#" +#[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 @@ -691,17 +678,17 @@ mod gen_str { "b" _ -> "" "# - ), - roc_std::RocStr::from_slice("a".as_bytes()), - roc_std::RocStr - ); - } + ), + 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#" +#[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 @@ -710,17 +697,17 @@ mod gen_str { "b" _ -> "" "# - ), - roc_std::RocStr::from_slice("a".as_bytes()), - roc_std::RocStr - ); - } + ), + roc_std::RocStr::from_slice("a".as_bytes()), + roc_std::RocStr + ); +} - #[test] - fn str_from_utf8_fail_surrogate_half() { - assert_evals_to!( - indoc!( - r#" +#[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 @@ -729,41 +716,41 @@ mod gen_str { "b" _ -> "" "# - ), - roc_std::RocStr::from_slice("a".as_bytes()), - roc_std::RocStr - ); - } + ), + 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_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()); +#[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); - } + 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#" +#[test] +fn nested_recursive_literal() { + assert_evals_to!( + indoc!( + r#" Expr : [ Add Expr Expr, Val I64, Var I64 ] expr : Expr @@ -783,50 +770,49 @@ mod gen_str { printExpr expr "# - ), - "Add (Add (Val 3) (Val 1)) (Add (Val 1) (Var 1))", - &'static str - ); - } - - #[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.140000"), RocStr); - } - - #[test] - fn str_to_bytes() { - assert_evals_to!(r#"Str.toBytes "hello""#, &[104, 101, 108, 108, 111], &[u8]); - assert_evals_to!( - r#"Str.toBytes "this is a long string""#, - &[ - 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 108, 111, 110, 103, 32, 115, 116, - 114, 105, 110, 103 - ], - &[u8] - ); - } + ), + "Add (Add (Val 3) (Val 1)) (Add (Val 1) (Var 1))", + &'static str + ); +} + +#[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.140000"), RocStr); +} + +#[test] +fn str_to_bytes() { + assert_evals_to!(r#"Str.toBytes "hello""#, &[104, 101, 108, 108, 111], &[u8]); + assert_evals_to!( + r#"Str.toBytes "this is a long string""#, + &[ + 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 108, 111, 110, 103, 32, 115, 116, 114, + 105, 110, 103 + ], + &[u8] + ); } diff --git a/compiler/test_gen/src/gen_tags.rs b/compiler/test_gen/src/gen_tags.rs index cdfef796aa..c178ea5c85 100644 --- a/compiler/test_gen/src/gen_tags.rs +++ b/compiler/test_gen/src/gen_tags.rs @@ -1,20 +1,14 @@ -extern crate bumpalo; -extern crate inkwell; -extern crate libc; -extern crate roc_gen; +#![cfg(test)] -#[cfg(test)] -mod gen_tags { - #[macro_use] - use crate::assert_evals_to; - use crate::assert_llvm_evals_to; - use indoc::indoc; +use crate::assert_evals_to; +use crate::assert_llvm_evals_to; +use indoc::indoc; - #[test] - fn applied_tag_nothing_ir() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn applied_tag_nothing_ir() { + assert_evals_to!( + indoc!( + r#" Maybe a : [ Just a, Nothing ] x : Maybe I64 @@ -22,18 +16,18 @@ mod gen_tags { x "# - ), - 1, - (i64, i64), - |(tag, _)| tag - ); - } + ), + 1, + (i64, i64), + |(tag, _)| tag + ); +} - #[test] - fn applied_tag_nothing() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn applied_tag_nothing() { + assert_evals_to!( + indoc!( + r#" Maybe a : [ Just a, Nothing ] x : Maybe I64 @@ -41,18 +35,18 @@ mod gen_tags { x "# - ), - 1, - (i64, i64), - |(tag, _)| tag - ); - } + ), + 1, + (i64, i64), + |(tag, _)| tag + ); +} - #[test] - fn applied_tag_just() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn applied_tag_just() { + assert_evals_to!( + indoc!( + r#" Maybe a : [ Just a, Nothing ] y : Maybe I64 @@ -60,17 +54,17 @@ mod gen_tags { y "# - ), - (0, 0x4), - (i64, i64) - ); - } + ), + (0, 0x4), + (i64, i64) + ); +} - #[test] - fn applied_tag_just_ir() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn applied_tag_just_ir() { + assert_evals_to!( + indoc!( + r#" Maybe a : [ Just a, Nothing ] y : Maybe I64 @@ -78,17 +72,17 @@ mod gen_tags { y "# - ), - (0, 0x4), - (i64, i64) - ); - } + ), + (0, 0x4), + (i64, i64) + ); +} - #[test] - fn applied_tag_just_enum() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn applied_tag_just_enum() { + assert_evals_to!( + indoc!( + r#" Fruit : [ Orange, Apple, Banana ] Maybe a : [ Just a, Nothing ] @@ -100,65 +94,65 @@ mod gen_tags { y "# - ), - (0, 2), - (i64, u8) - ); - } + ), + (0, 2), + (i64, u8) + ); +} - // #[test] - // fn raw_result() { - // assert_evals_to!( - // indoc!( - // r#" - // x : Result I64 I64 - // x = Err 41 +// #[test] +// fn raw_result() { +// assert_evals_to!( +// indoc!( +// r#" +// x : Result I64 I64 +// x = Err 41 - // x - // "# - // ), - // 0, - // i8 - // ); - // } +// x +// "# +// ), +// 0, +// i8 +// ); +// } - #[test] - fn true_is_true() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn true_is_true() { + assert_evals_to!( + indoc!( + r#" bool : [True, False] bool = True bool "# - ), - true, - bool - ); - } + ), + true, + bool + ); +} - #[test] - fn false_is_false() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn false_is_false() { + assert_evals_to!( + indoc!( + r#" bool : [True, False] bool = False bool "# - ), - false, - bool - ); - } + ), + false, + bool + ); +} - #[test] - fn basic_enum() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn basic_enum() { + assert_evals_to!( + indoc!( + r#" Fruit : [ Apple, Orange, Banana ] apple : Fruit @@ -169,74 +163,74 @@ mod gen_tags { apple == orange "# - ), - false, - bool - ); - } + ), + false, + bool + ); +} - // #[test] - // fn linked_list_empty() { - // assert_evals_to!( - // indoc!( - // r#" - // LinkedList a : [ Cons a (LinkedList a), Nil ] - // - // empty : LinkedList I64 - // empty = Nil - // - // 1 - // "# - // ), - // 1, - // i64 - // ); - // } - // - // #[test] - // fn linked_list_singleton() { - // assert_evals_to!( - // indoc!( - // r#" - // LinkedList a : [ Cons a (LinkedList a), Nil ] - // - // singleton : LinkedList I64 - // singleton = Cons 0x1 Nil - // - // 1 - // "# - // ), - // 1, - // i64 - // ); - // } - // - // #[test] - // fn linked_list_is_empty() { - // assert_evals_to!( - // indoc!( - // r#" - // LinkedList a : [ Cons a (LinkedList a), Nil ] - // - // isEmpty : LinkedList a -> Bool - // isEmpty = \list -> - // when list is - // Nil -> True - // Cons _ _ -> False - // - // isEmpty (Cons 4 Nil) - // "# - // ), - // false, - // bool - // ); - // } +// #[test] +// fn linked_list_empty() { +// assert_evals_to!( +// indoc!( +// r#" +// LinkedList a : [ Cons a (LinkedList a), Nil ] +// +// empty : LinkedList I64 +// empty = Nil +// +// 1 +// "# +// ), +// 1, +// i64 +// ); +// } +// +// #[test] +// fn linked_list_singleton() { +// assert_evals_to!( +// indoc!( +// r#" +// LinkedList a : [ Cons a (LinkedList a), Nil ] +// +// singleton : LinkedList I64 +// singleton = Cons 0x1 Nil +// +// 1 +// "# +// ), +// 1, +// i64 +// ); +// } +// +// #[test] +// fn linked_list_is_empty() { +// assert_evals_to!( +// indoc!( +// r#" +// LinkedList a : [ Cons a (LinkedList a), Nil ] +// +// isEmpty : LinkedList a -> Bool +// isEmpty = \list -> +// when list is +// Nil -> True +// Cons _ _ -> False +// +// isEmpty (Cons 4 Nil) +// "# +// ), +// false, +// bool +// ); +// } - #[test] - fn even_odd() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn even_odd() { + assert_evals_to!( + indoc!( + r#" even = \n -> when n is 0 -> True @@ -251,42 +245,42 @@ mod gen_tags { odd 5 && even 42 "# - ), - true, - bool - ); - } + ), + true, + bool + ); +} - #[test] - fn gen_literal_true() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn gen_literal_true() { + assert_evals_to!( + indoc!( + r#" if True then -1 else 1 "# - ), - -1, - i64 - ); - } + ), + -1, + i64 + ); +} - #[test] - fn gen_if_float() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn gen_if_float() { + assert_evals_to!( + indoc!( + r#" if True then -1.0 else 1.0 "# - ), - -1.0, - f64 - ); - } - #[test] - fn when_on_nothing() { - assert_evals_to!( - indoc!( - r#" + ), + -1.0, + f64 + ); +} +#[test] +fn when_on_nothing() { + assert_evals_to!( + indoc!( + r#" x : [ Nothing, Just I64 ] x = Nothing @@ -294,17 +288,17 @@ mod gen_tags { Nothing -> 0x2 Just _ -> 0x1 "# - ), - 2, - i64 - ); - } + ), + 2, + i64 + ); +} - #[test] - fn when_on_just() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn when_on_just() { + assert_evals_to!( + indoc!( + r#" x : [ Nothing, Just I64 ] x = Just 41 @@ -312,17 +306,17 @@ mod gen_tags { Just v -> v + 0x1 Nothing -> 0x1 "# - ), - 42, - i64 - ); - } + ), + 42, + i64 + ); +} - #[test] - fn when_on_result() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn when_on_result() { + assert_evals_to!( + indoc!( + r#" x : Result I64 I64 x = Err 41 @@ -330,17 +324,17 @@ mod gen_tags { Err v -> v + 1 Ok _ -> 1 "# - ), - 42, - i64 - ); - } + ), + 42, + i64 + ); +} - #[test] - fn when_on_these() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn when_on_these() { + assert_evals_to!( + indoc!( + r#" These a b : [ This a, That b, These a b ] x : These I64 I64 @@ -351,50 +345,50 @@ mod gen_tags { That v -> v This v -> v "# - ), - 5, - i64 - ); - } + ), + 5, + i64 + ); +} - #[test] - fn match_on_two_values() { - // this will produce a Chain internally - assert_evals_to!( - indoc!( - r#" +#[test] +fn match_on_two_values() { + // this will produce a Chain internally + assert_evals_to!( + indoc!( + r#" when Pair 2 3 is Pair 4 3 -> 9 Pair a b -> a + b "# - ), - 5, - i64 - ); - } + ), + 5, + i64 + ); +} - #[test] - fn pair_with_guard_pattern() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn pair_with_guard_pattern() { + assert_evals_to!( + indoc!( + r#" when Pair 2 3 is Pair 4 _ -> 1 Pair 3 _ -> 2 Pair a b -> a + b "# - ), - 5, - i64 - ); - } + ), + 5, + i64 + ); +} - #[test] - fn result_with_guard_pattern() { - // This test revealed an issue with hashing Test values - assert_evals_to!( - indoc!( - r#" +#[test] +fn result_with_guard_pattern() { + // This test revealed an issue with hashing Test values + assert_evals_to!( + indoc!( + r#" x : Result I64 I64 x = Ok 2 @@ -403,17 +397,17 @@ mod gen_tags { Ok _ -> 2 Err _ -> 3 "# - ), - 2, - i64 - ); - } + ), + 2, + i64 + ); +} - #[test] - fn maybe_is_just() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn maybe_is_just() { + assert_evals_to!( + indoc!( + r#" app "test" provides [ main ] to "./platform" Maybe a : [ Just a, Nothing ] @@ -427,17 +421,17 @@ mod gen_tags { main = isJust (Just 42) "# - ), - true, - bool - ); - } + ), + true, + bool + ); +} - #[test] - fn maybe_is_just_nested() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn maybe_is_just_nested() { + assert_evals_to!( + indoc!( + r#" Maybe a : [ Just a, Nothing ] isJust : Maybe a -> Bool @@ -448,17 +442,17 @@ mod gen_tags { isJust (Just 42) "# - ), - true, - bool - ); - } + ), + true, + bool + ); +} - #[test] - fn nested_pattern_match() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn nested_pattern_match() { + assert_evals_to!( + indoc!( + r#" Maybe a : [ Nothing, Just a ] x : Maybe (Maybe I64) @@ -468,16 +462,16 @@ mod gen_tags { Just (Just v) -> v + 0x1 _ -> 0x1 "# - ), - 42, - i64 - ); - } - #[test] - fn if_guard_pattern_false() { - assert_evals_to!( - indoc!( - r#" + ), + 42, + i64 + ); +} +#[test] +fn if_guard_pattern_false() { + assert_evals_to!( + indoc!( + r#" wrapper = \{} -> when 2 is 2 if False -> 0 @@ -485,17 +479,17 @@ mod gen_tags { wrapper {} "# - ), - 42, - i64 - ); - } + ), + 42, + i64 + ); +} - #[test] - fn if_guard_pattern_true() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn if_guard_pattern_true() { + assert_evals_to!( + indoc!( + r#" wrapper = \{} -> when 2 is 2 if True -> 42 @@ -503,17 +497,17 @@ mod gen_tags { wrapper {} "# - ), - 42, - i64 - ); - } + ), + 42, + i64 + ); +} - #[test] - fn if_guard_exhaustiveness() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn if_guard_exhaustiveness() { + assert_evals_to!( + indoc!( + r#" wrapper = \{} -> when 2 is _ if False -> 0 @@ -521,17 +515,17 @@ mod gen_tags { wrapper {} "# - ), - 42, - i64 - ); - } + ), + 42, + i64 + ); +} - #[test] - fn when_on_enum() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn when_on_enum() { + assert_evals_to!( + indoc!( + r#" Fruit : [ Apple, Orange, Banana ] apple : Fruit @@ -542,17 +536,17 @@ mod gen_tags { Banana -> 2 Orange -> 3 "# - ), - 1, - i64 - ); - } + ), + 1, + i64 + ); +} - #[test] - fn pattern_matching_unit() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn pattern_matching_unit() { + assert_evals_to!( + indoc!( + r#" Unit : [ Unit ] f : Unit -> I64 @@ -560,14 +554,14 @@ mod gen_tags { f Unit "# - ), - 42, - i64 - ); + ), + 42, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" Unit : [ Unit ] x : Unit @@ -576,57 +570,57 @@ mod gen_tags { when x is Unit -> 42 "# - ), - 42, - i64 - ); + ), + 42, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" f : {} -> I64 f = \{} -> 42 f {} "# - ), - 42, - i64 - ); + ), + 42, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" when {} is {} -> 42 "# - ), - 42, - i64 - ); - } + ), + 42, + i64 + ); +} - #[test] - fn one_element_tag() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn one_element_tag() { + assert_evals_to!( + indoc!( + r#" x : [ Pair I64 ] x = Pair 2 x "# - ), - 2, - i64 - ); - } + ), + 2, + i64 + ); +} - #[test] - fn nested_tag_union() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn nested_tag_union() { + assert_evals_to!( + indoc!( + r#" app "test" provides [ main ] to "./platform" Maybe a : [ Nothing, Just a ] @@ -637,16 +631,16 @@ mod gen_tags { main = x "# - ), - (0, (0, 41)), - (i64, (i64, i64)) - ); - } - #[test] - fn unit_type() { - assert_evals_to!( - indoc!( - r#" + ), + (0, (0, 41)), + (i64, (i64, i64)) + ); +} +#[test] +fn unit_type() { + assert_evals_to!( + indoc!( + r#" Unit : [ Unit ] v : Unit @@ -654,50 +648,50 @@ mod gen_tags { v "# - ), - (), - () - ); - } + ), + (), + () + ); +} - #[test] - fn nested_record_load() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn nested_record_load() { + assert_evals_to!( + indoc!( + r#" x = { a : { b : 0x5 } } y = x.a y.b "# - ), - 5, - i64 - ); - } + ), + 5, + i64 + ); +} - #[test] - fn join_point_if() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn join_point_if() { + assert_evals_to!( + indoc!( + r#" x = if True then 1 else 2 x "# - ), - 1, - i64 - ); - } + ), + 1, + i64 + ); +} - #[test] - fn join_point_when() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn join_point_when() { + assert_evals_to!( + indoc!( + r#" wrapper = \{} -> x : [ Red, White, Blue ] x = Blue @@ -712,17 +706,17 @@ mod gen_tags { wrapper {} "# - ), - 3.1, - f64 - ); - } + ), + 3.1, + f64 + ); +} - #[test] - fn join_point_with_cond_expr() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn join_point_with_cond_expr() { + assert_evals_to!( + indoc!( + r#" wrapper = \{} -> y = when 1 + 2 is @@ -734,14 +728,14 @@ mod gen_tags { wrapper {} "# - ), - 3, - i64 - ); + ), + 3, + i64 + ); - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" y = if 1 + 2 > 0 then 3 @@ -750,89 +744,89 @@ mod gen_tags { y "# - ), - 3, - i64 - ); - } + ), + 3, + i64 + ); +} - #[test] - fn alignment_in_single_tag_construction() { - assert_evals_to!(indoc!("Three (1 == 1) 32"), (32i64, true), (i64, bool)); +#[test] +fn alignment_in_single_tag_construction() { + assert_evals_to!(indoc!("Three (1 == 1) 32"), (32i64, true), (i64, bool)); - assert_evals_to!( - indoc!("Three (1 == 1) (if True then Red else if True then Green else Blue) 32"), - (32i64, true, 2u8), - (i64, bool, u8) - ); - } + assert_evals_to!( + indoc!("Three (1 == 1) (if True then Red else if True then Green else Blue) 32"), + (32i64, true, 2u8), + (i64, bool, u8) + ); +} - #[test] - fn alignment_in_single_tag_pattern_match() { - assert_evals_to!( - indoc!( - r"# +#[test] +fn alignment_in_single_tag_pattern_match() { + assert_evals_to!( + indoc!( + r"# x = Three (1 == 1) 32 when x is Three bool int -> { bool, int } #" - ), - (32i64, true), - (i64, bool) - ); + ), + (32i64, true), + (i64, bool) + ); - assert_evals_to!( - indoc!( - r"# + assert_evals_to!( + indoc!( + r"# x = Three (1 == 1) (if True then Red else if True then Green else Blue) 32 when x is Three bool color int -> { bool, color, int } #" - ), - (32i64, true, 2u8), - (i64, bool, u8) - ); - } + ), + (32i64, true, 2u8), + (i64, bool, u8) + ); +} - #[test] - fn alignment_in_multi_tag_construction() { - assert_evals_to!( - indoc!( - r"# +#[test] +fn alignment_in_multi_tag_construction() { + assert_evals_to!( + indoc!( + r"# x : [ Three Bool I64, Empty ] x = Three (1 == 1) 32 x #" - ), - (1, 32i64, true), - (i64, i64, bool) - ); + ), + (1, 32i64, true), + (i64, i64, bool) + ); - assert_evals_to!( - indoc!( - r"# + assert_evals_to!( + indoc!( + r"# x : [ Three Bool [ Red, Green, Blue ] I64, Empty ] x = Three (1 == 1) (if True then Red else if True then Green else Blue) 32 x #" - ), - (1, 32i64, true, 2u8), - (i64, i64, bool, u8) - ); - } + ), + (1, 32i64, true, 2u8), + (i64, i64, bool, u8) + ); +} - #[test] - fn alignment_in_multi_tag_pattern_match() { - assert_evals_to!( - indoc!( - r"# +#[test] +fn alignment_in_multi_tag_pattern_match() { + assert_evals_to!( + indoc!( + r"# x : [ Three Bool I64, Empty ] x = Three (1 == 1) 32 @@ -843,14 +837,14 @@ mod gen_tags { Empty -> { bool: False, int: 0 } #" - ), - (32i64, true), - (i64, bool) - ); + ), + (32i64, true), + (i64, bool) + ); - assert_evals_to!( - indoc!( - r"# + assert_evals_to!( + indoc!( + r"# x : [ Three Bool [ Red, Green, Blue ] I64, Empty ] x = Three (1 == 1) (if True then Red else if True then Green else Blue) 32 @@ -860,19 +854,19 @@ mod gen_tags { Empty -> { bool: False, color: Red, int: 0 } #" - ), - (32i64, true, 2u8), - (i64, bool, u8) - ); - } + ), + (32i64, true, 2u8), + (i64, bool, u8) + ); +} - #[test] - #[ignore] - fn phantom_polymorphic() { - // see https://github.com/rtfeldman/roc/issues/786 and below - assert_evals_to!( - indoc!( - r"# +#[test] +#[ignore] +fn phantom_polymorphic() { + // see https://github.com/rtfeldman/roc/issues/786 and below + assert_evals_to!( + indoc!( + r"# Point coordinate : [ Point coordinate I64 I64 ] World : [ @World ] @@ -885,21 +879,21 @@ mod gen_tags { add zero #" - ), - (0, 0), - (i64, i64) - ); - } + ), + (0, 0), + (i64, i64) + ); +} - #[test] - #[ignore] - fn phantom_polymorphic_record() { - // see https://github.com/rtfeldman/roc/issues/786 - // also seemed to hit an issue where we check whether `add` - // has a Closure layout while the type is not fully specialized yet - assert_evals_to!( - indoc!( - r#" +#[test] +#[ignore] +fn phantom_polymorphic_record() { + // see https://github.com/rtfeldman/roc/issues/786 + // also seemed to hit an issue where we check whether `add` + // has a Closure layout while the type is not fully specialized yet + assert_evals_to!( + indoc!( + r#" app "test" provides [ main ] to "./platform" Point coordinate : { coordinate : coordinate, x : I64, y : I64 } @@ -912,17 +906,17 @@ mod gen_tags { main = add zero "# - ), - (0, 0), - (i64, i64) - ); - } + ), + (0, 0), + (i64, i64) + ); +} - #[test] - fn result_never() { - assert_evals_to!( - indoc!( - r"# +#[test] +fn result_never() { + assert_evals_to!( + indoc!( + r"# res : Result I64 [] res = Ok 4 @@ -933,17 +927,17 @@ mod gen_tags { Ok v -> v Err empty -> never empty #" - ), - 4, - i64 - ); - } + ), + 4, + i64 + ); +} - #[test] - fn nested_recursive_literal() { - assert_evals_to!( - indoc!( - r"# +#[test] +fn nested_recursive_literal() { + assert_evals_to!( + indoc!( + r"# Expr : [ Add Expr Expr, Val I64, Var I64 ] e : Expr @@ -951,18 +945,18 @@ mod gen_tags { e #" - ), - 0, - &i64, - |x: &i64| *x - ); - } + ), + 0, + &i64, + |x: &i64| *x + ); +} - #[test] - fn newtype_wrapper() { - assert_evals_to!( - indoc!( - r#" +#[test] +fn newtype_wrapper() { + assert_evals_to!( + indoc!( + r#" app "test" provides [ main ] to "./platform" ConsList a : [ Nil, Cons a (ConsList a) ] @@ -974,10 +968,9 @@ mod gen_tags { main = foo Nil "# - ), - 42, - &i64, - |x: &i64| *x - ); - } + ), + 42, + &i64, + |x: &i64| *x + ); } diff --git a/compiler/test_gen/src/helpers/eval.rs b/compiler/test_gen/src/helpers/eval.rs index 61c48332a4..5f66dd10df 100644 --- a/compiler/test_gen/src/helpers/eval.rs +++ b/compiler/test_gen/src/helpers/eval.rs @@ -29,6 +29,9 @@ pub fn test_builtin_defs(symbol: Symbol, var_store: &mut VarStore) -> Option( arena: &'a bumpalo::Bump, src: &str, diff --git a/compiler/test_gen/src/lib.rs b/compiler/test_gen/src/lib.rs index 90fbbe5354..723c3986dd 100644 --- a/compiler/test_gen/src/lib.rs +++ b/compiler/test_gen/src/lib.rs @@ -4,6 +4,14 @@ // we actually want to compare against the literal float bits #![allow(clippy::clippy::float_cmp)] -pub mod gen_tags; +pub mod gen_dict; +pub mod gen_hash; +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;