roc/compiler/gen/tests/gen_primitives.rs
Richard Feldman 17b2eebcfc REVERT THIS! Temporarily disable exception tests.
These currently break on Linux, but pass on macOS.

They worked fine with JITExecutionEngine on Linux,
but JITExecutionEngine failed on macOS.
2020-10-25 01:42:10 -04:00

1059 lines
22 KiB
Rust

#[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_primitives {
#[test]
fn basic_int() {
assert_evals_to!("123", 123, i64);
}
#[test]
fn basic_float() {
assert_evals_to!("1234.0", 1234.0, f64);
}
#[test]
fn branch_first_float() {
assert_evals_to!(
indoc!(
r#"
when 1.23 is
1.23 -> 12
_ -> 34
"#
),
12,
i64
);
}
#[test]
fn branch_second_float() {
assert_evals_to!(
indoc!(
r#"
when 2.34 is
1.23 -> 63
_ -> 48
"#
),
48,
i64
);
}
#[test]
fn branch_third_float() {
assert_evals_to!(
indoc!(
r#"
when 10.0 is
1.0 -> 63
2.0 -> 48
_ -> 112
"#
),
112,
i64
);
}
#[test]
fn branch_first_int() {
assert_evals_to!(
indoc!(
r#"
when 1 is
1 -> 12
_ -> 34
"#
),
12,
i64
);
}
#[test]
fn branch_second_int() {
assert_evals_to!(
indoc!(
r#"
when 2 is
1 -> 63
_ -> 48
"#
),
48,
i64
);
}
#[test]
fn branch_third_int() {
assert_evals_to!(
indoc!(
r#"
when 10 is
1 -> 63
2 -> 48
_ -> 112
"#
),
112,
i64
);
}
#[test]
fn branch_store_variable() {
assert_evals_to!(
indoc!(
r#"
when 0 is
1 -> 12
a -> a
"#
),
0,
i64
);
}
#[test]
fn when_one_element_tag() {
assert_evals_to!(
indoc!(
r#"
x : [ Pair Int Int ]
x = Pair 0x2 0x3
when x is
Pair l r -> l + r
"#
),
5,
i64
);
}
#[test]
fn when_two_element_tag_first() {
assert_evals_to!(
indoc!(
r#"
x : [A Int, B Int]
x = A 0x2
when x is
A v -> v
B v -> v
"#
),
2,
i64
);
}
#[test]
fn when_two_element_tag_second() {
assert_evals_to!(
indoc!(
r#"
x : [A Int, B Int]
x = B 0x3
when x is
A v -> v
B v -> v
"#
),
3,
i64
);
}
#[test]
fn gen_when_one_branch() {
assert_evals_to!(
indoc!(
r#"
when 3.14 is
_ -> 23
"#
),
23,
i64
);
}
#[test]
fn gen_large_when_int() {
assert_evals_to!(
indoc!(
r#"
foo = \num ->
when num is
0 -> 200
-3 -> 111 # TODO adding more negative numbers reproduces parsing bugs here
3 -> 789
1 -> 123
2 -> 456
_ -> 1000
foo -3
"#
),
111,
i64
);
}
// #[test]
// fn gen_large_when_float() {
// assert_evals_to!(
// indoc!(
// r#"
// foo = \num ->
// when num is
// 0.5 -> 200.1
// -3.6 -> 111.2 # TODO adding more negative numbers reproduces parsing bugs here
// 3.6 -> 789.5
// 1.7 -> 123.3
// 2.8 -> 456.4
// _ -> 1000.6
// foo -3.6
// "#
// ),
// 111.2,
// f64
// );
// }
#[test]
fn or_pattern() {
assert_evals_to!(
indoc!(
r#"
when 2 is
1 | 2 -> 42
_ -> 1
"#
),
42,
i64
);
}
#[test]
fn apply_identity() {
assert_evals_to!(
indoc!(
r#"
identity = \a -> a
identity 5
"#
),
5,
i64
);
}
#[test]
fn apply_unnamed_identity() {
assert_evals_to!(
indoc!(
r#"
wrapper = \{} ->
(\a -> a) 5
wrapper {}
"#
),
5,
i64
);
}
#[test]
fn return_unnamed_fn() {
assert_evals_to!(
indoc!(
r#"
wrapper = \{} ->
alwaysFloatIdentity : Int -> (Float -> Float)
alwaysFloatIdentity = \num ->
(\a -> a)
(alwaysFloatIdentity 2) 3.14
wrapper {}
"#
),
3.14,
f64
);
}
#[test]
fn gen_when_fn() {
assert_evals_to!(
indoc!(
r#"
limitedNegate = \num ->
when num is
1 -> -1
-1 -> 1
_ -> num
limitedNegate 1
"#
),
-1,
i64
);
}
#[test]
fn gen_basic_def() {
assert_evals_to!(
indoc!(
r#"
answer = 42
answer
"#
),
42,
i64
);
assert_evals_to!(
indoc!(
r#"
pi = 3.14
pi
"#
),
3.14,
f64
);
}
#[test]
fn gen_multiple_defs() {
assert_evals_to!(
indoc!(
r#"
answer = 42
pi = 3.14
answer
"#
),
42,
i64
);
assert_evals_to!(
indoc!(
r#"
answer = 42
pi = 3.14
pi
"#
),
3.14,
f64
);
}
#[test]
fn gen_chained_defs() {
assert_evals_to!(
indoc!(
r#"
x = i1
i3 = i2
i1 = 1337
i2 = i1
y = 12.4
i3
"#
),
1337,
i64
);
}
#[test]
fn gen_nested_defs_old() {
assert_evals_to!(
indoc!(
r#"
x = 5
answer =
i3 = i2
nested =
a = 1.0
b = 5
i1
i1 = 1337
i2 = i1
nested
# None of this should affect anything, even though names
# overlap with the previous nested defs
unused =
nested = 17
i1 = 84.2
nested
y = 12.4
answer
"#
),
1337,
i64
);
}
#[test]
fn let_x_in_x() {
assert_evals_to!(
indoc!(
r#"
x = 5
answer =
1337
unused =
nested = 17
nested
answer
"#
),
1337,
i64
);
}
#[test]
fn factorial() {
assert_evals_to!(
indoc!(
r#"
factorial = \n, accum ->
when n is
0 ->
accum
_ ->
factorial (n - 1) (n * accum)
factorial 10 1
"#
),
3628800,
i64
);
}
#[test]
fn peano1() {
assert_evals_to!(
indoc!(
r#"
Peano : [ S Peano, Z ]
three : Peano
three = S (S (S Z))
when three is
Z -> 2
S _ -> 1
"#
),
1,
i64
);
}
#[test]
fn peano2() {
assert_evals_to!(
indoc!(
r#"
Peano : [ S Peano, Z ]
three : Peano
three = S (S (S Z))
when three is
S (S _) -> 1
S (_) -> 0
Z -> 0
"#
),
1,
i64
);
}
#[test]
fn top_level_constant() {
assert_evals_to!(
indoc!(
r#"
app LinkedListLen0 provides [ main ] imports []
pi = 3.1415
main =
pi + pi
"#
),
3.1415 + 3.1415,
f64
);
}
#[test]
fn linked_list_len_0() {
assert_evals_to!(
indoc!(
r#"
app LinkedListLen0 provides [ main ] imports []
LinkedList a : [ Nil, Cons a (LinkedList a) ]
nil : LinkedList Int
nil = Nil
length : LinkedList a -> Int
length = \list ->
when list is
Nil -> 0
Cons _ rest -> 1 + length rest
main =
length nil
"#
),
0,
i64
);
}
#[test]
fn linked_list_len_twice_0() {
assert_evals_to!(
indoc!(
r#"
app LinkedListLenTwice0 provides [ main ] imports []
LinkedList a : [ Nil, Cons a (LinkedList a) ]
nil : LinkedList Int
nil = Nil
length : LinkedList a -> Int
length = \list ->
when list is
Nil -> 0
Cons _ rest -> 1 + length rest
main =
length nil + length nil
"#
),
0,
i64
);
}
#[test]
fn linked_list_len_1() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
LinkedList a : [ Nil, Cons a (LinkedList a) ]
one : LinkedList Int
one = Cons 1 Nil
length : LinkedList a -> Int
length = \list ->
when list is
Nil -> 0
Cons _ rest -> 1 + length rest
main =
length one
"#
),
1,
i64
);
}
#[test]
fn linked_list_len_twice_1() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
LinkedList a : [ Nil, Cons a (LinkedList a) ]
one : LinkedList Int
one = Cons 1 Nil
length : LinkedList a -> Int
length = \list ->
when list is
Nil -> 0
Cons _ rest -> 1 + length rest
main =
length one + length one
"#
),
2,
i64
);
}
#[test]
fn linked_list_len_3() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
LinkedList a : [ Nil, Cons a (LinkedList a) ]
three : LinkedList Int
three = Cons 3 (Cons 2 (Cons 1 Nil))
length : LinkedList a -> Int
length = \list ->
when list is
Nil -> 0
Cons _ rest -> 1 + length rest
main =
length three
"#
),
3,
i64
);
}
#[test]
fn linked_list_sum_num_a() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
LinkedList a : [ Nil, Cons a (LinkedList a) ]
three : LinkedList Int
three = Cons 3 (Cons 2 (Cons 1 Nil))
sum : LinkedList (Num a) -> Num a
sum = \list ->
when list is
Nil -> 0
Cons x rest -> x + sum rest
main =
sum three
"#
),
3 + 2 + 1,
i64
)
}
#[test]
fn linked_list_sum_int() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
LinkedList a : [ Nil, Cons a (LinkedList a) ]
zero : LinkedList Int
zero = Nil
sum : LinkedList Int -> Int
sum = \list ->
when list is
Nil -> 0
Cons x rest -> x + sum rest
main =
sum zero
"#
),
0,
i64
)
}
#[test]
fn linked_list_map() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
LinkedList a : [ Nil, Cons a (LinkedList a) ]
three : LinkedList Int
three = Cons 3 (Cons 2 (Cons 1 Nil))
sum : LinkedList (Num a) -> Num a
sum = \list ->
when list is
Nil -> 0
Cons x rest -> x + sum rest
map : (a -> b), LinkedList a -> LinkedList b
map = \f, list ->
when list is
Nil -> Nil
Cons x rest -> Cons (f x) (map f rest)
main =
sum (map (\_ -> 1) three)
"#
),
3,
i64
);
}
#[test]
fn when_nested_maybe() {
assert_evals_to!(
indoc!(
r#"
Maybe a : [ Nothing, Just a ]
x : Maybe (Maybe Int)
x = Just (Just 41)
when x is
Just (Just v) -> v + 0x1
_ -> 0x1
"#
),
42,
i64
);
assert_evals_to!(
indoc!(
r#"
Maybe a : [ Nothing, Just a ]
x : Maybe (Maybe Int)
x = Just Nothing
when x is
Just (Just v) -> v + 0x1
Just Nothing -> 0x2
Nothing -> 0x1
"#
),
2,
i64
);
assert_evals_to!(
indoc!(
r#"
Maybe a : [ Nothing, Just a ]
x : Maybe (Maybe Int)
x = Nothing
when x is
Just (Just v) -> v + 0x1
Just Nothing -> 0x2
Nothing -> 0x1
"#
),
1,
i64
);
}
#[test]
fn when_peano() {
assert_evals_to!(
indoc!(
r#"
Peano : [ S Peano, Z ]
three : Peano
three = S (S (S Z))
when three is
S (S _) -> 1
S (_) -> 2
Z -> 3
"#
),
1,
i64
);
assert_evals_to!(
indoc!(
r#"
Peano : [ S Peano, Z ]
three : Peano
three = S Z
when three is
S (S _) -> 1
S (_) -> 2
Z -> 3
"#
),
2,
i64
);
assert_evals_to!(
indoc!(
r#"
Peano : [ S Peano, Z ]
three : Peano
three = Z
when three is
S (S _) -> 1
S (_) -> 2
Z -> 3
"#
),
3,
i64
);
}
// #[test]
// #[should_panic(expected = "Roc failed with message: ")]
// fn exception() {
// assert_evals_to!(
// indoc!(
// r#"
// if True then
// x + z
// else
// y + z
// "#
// ),
// 3,
// i64
// );
// }
#[test]
fn closure() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
x = 42
f = \{} -> x
main =
f {}
"#
),
42,
i64
);
}
#[test]
fn nested_closure() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
foo = \{} ->
x = 41
y = 1
f = \{} -> x + y
f
main =
g = foo {}
g {}
"#
),
42,
i64
);
}
#[test]
fn closure_in_list() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
foo = \{} ->
x = 41
f = \{} -> x
[ f ]
main =
items = foo {}
List.len items
"#
),
1,
i64
);
}
#[test]
fn specialize_closure() {
use roc_std::RocList;
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
foo = \{} ->
x = 41
y = 1
f = \{} -> x
g = \{} -> x + y
[ f, g ]
main =
items = foo {}
# List.len items
List.map items (\f -> f {})
"#
),
RocList::from_slice(&[41, 42]),
RocList<i64>
);
}
#[test]
fn io_poc_effect() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
Effect a : [ @Effect ({} -> a) ]
# succeed : a -> Effect a
succeed = \x -> @Effect \{} -> x
# runEffect : Effect a -> a
runEffect = \@Effect thunk -> thunk {}
# foo : Effect Float
foo =
succeed 3.14
main : Float
main =
runEffect foo
"#
),
3.14,
f64
);
}
#[test]
fn io_poc_desugared() {
assert_evals_to!(
indoc!(
r#"
app Test provides [ main ] imports []
# succeed : a -> ({} -> a)
succeed = \x -> \{} -> x
foo : {} -> Float
foo =
succeed 3.14
# runEffect : ({} -> a) -> a
runEffect = \thunk -> thunk {}
main : Float
main =
runEffect foo
"#
),
3.14,
f64
);
}
}