Split gen_builtins into gen_num and gen_list

This commit is contained in:
Richard Feldman 2020-06-25 22:02:25 -04:00
parent 714a81f40a
commit 22cc618436
2 changed files with 411 additions and 376 deletions

View File

@ -0,0 +1,383 @@
#[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_builtins {
use crate::helpers::{can_expr, infer_expr, uniq_expr, CanExprOut};
use bumpalo::Bump;
use inkwell::context::Context;
use inkwell::execution_engine::JitFunction;
use inkwell::passes::PassManager;
use inkwell::types::BasicType;
use inkwell::OptimizationLevel;
use roc_collections::all::ImMap;
use roc_gen::llvm::build::{build_proc, build_proc_header};
use roc_gen::llvm::convert::basic_type_from_layout;
use roc_mono::expr::{Expr, Procs};
use roc_mono::layout::Layout;
use roc_types::subs::Subs;
#[test]
fn empty_list_literal() {
assert_evals_to!("[]", &[], &'static [i64]);
}
#[test]
fn int_list_literal() {
assert_evals_to!("[ 12, 9, 6, 3 ]", &[12, 9, 6, 3], &'static [i64]);
}
// #[test]
// fn list_push() {
// assert_evals_to!("List.push [] 1", &[1], &'static [i64]);
// }
#[test]
fn list_single() {
assert_evals_to!("List.single 1", &[1], &'static [i64]);
assert_evals_to!("List.single 5.6", &[5.6], &'static [f64]);
}
#[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]
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 get_empty_list() {
assert_evals_to!(
indoc!(
r#"
when List.get [] 0 is
Ok val -> val
Err _ -> -1
"#
),
-1,
i64
);
}
#[test]
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",
&[12, 9, 33, 1, 5],
&'static [i64]
);
}
#[test]
fn set_unique_list_oob() {
assert_evals_to!(
"List.set [ 3, 17, 4.1 ] 1337 9.25",
&[3.0, 17.0, 4.1],
&'static [f64]
);
}
#[test]
fn set_shared_int_list() {
assert_evals_to!(
indoc!(
r#"
shared = [ 2.1, 4.3 ]
# 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 }
"#
),
(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_quicksort() {
if true {
todo!("fix gen_quicksort stack overflow (note: TCO test passes, check to see if there's a stack overflow *before* the code begins to execute");
}
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), Int, Int -> 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 : Int, Int, 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 : Int, Int, List (Num a) -> [ Pair Int (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 : Int, Int, List (Num a), Int, Int -> [ Pair Int (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 ]
"#
),
&[4, 7, 19, 21],
&'static [i64]
);
}
}

View File

@ -29,17 +29,18 @@ mod gen_builtins {
#[test]
fn f64_sqrt() {
assert_evals_to!(
indoc!(
r#"
when Num.sqrt 144 is
Ok val -> val
Err _ -> -1
"#
),
12.0,
f64
);
todo!("if I change Num.sqrt 1000 to Num.sqrt 144 I get a BadPattern error?!");
// assert_evals_to!(
// indoc!(
// r#"
// when Num.sqrt 100 is
// Ok val -> val
// Err _ -> -1
// "#
// ),
// 12.0,
// f64
// );
}
#[test]
@ -59,16 +60,6 @@ mod gen_builtins {
assert_evals_to!("Num.abs 7", 7, i64);
}
#[test]
fn empty_list_literal() {
assert_evals_to!("[]", &[], &'static [i64]);
}
#[test]
fn int_list_literal() {
assert_evals_to!("[ 12, 9, 6, 3 ]", &[12, 9, 6, 3], &'static [i64]);
}
#[test]
fn gen_if_fn() {
assert_evals_to!(
@ -118,15 +109,18 @@ mod gen_builtins {
#[test]
fn gen_div_f64() {
assert_evals_to!(
indoc!(
r#"
48 / 2
"#
),
24.0,
f64
);
todo!("if I change 1000 / 10 to 48 / 2 I get a BadPattern error?!");
// assert_evals_to!(
// indoc!(
// r#"
// when 1000 / 10 is
// Ok val -> val
// Err _ -> -1
// "#
// ),
// 24.0,
// f64
// );
}
#[test]
@ -421,10 +415,10 @@ mod gen_builtins {
assert_evals_to!(
indoc!(
r#"
48 / 2 + 3
3 - 48 * 2.0
"#
),
27.0,
-93.0,
f64
);
}
@ -455,6 +449,7 @@ mod gen_builtins {
i64
);
}
#[test]
fn tail_call_elimination() {
assert_evals_to!(
@ -472,6 +467,7 @@ mod gen_builtins {
i64
);
}
#[test]
fn int_negate() {
assert_evals_to!("Num.neg 123", -123, i64);
@ -493,276 +489,6 @@ mod gen_builtins {
);
}
// #[test]
// fn list_push() {
// assert_evals_to!("List.push [] 1", &[1], &'static [i64]);
// }
#[test]
fn list_single() {
assert_evals_to!("List.single 1", &[1], &'static [i64]);
assert_evals_to!("List.single 5.6", &[5.6], &'static [f64]);
}
#[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]
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 get_empty_list() {
assert_evals_to!(
indoc!(
r#"
when List.get [] 0 is
Ok val -> val
Err _ -> -1
"#
),
-1,
i64
);
}
#[test]
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",
&[12, 9, 33, 1, 5],
&'static [i64]
);
}
#[test]
fn set_unique_list_oob() {
assert_evals_to!(
"List.set [ 3, 17, 4.1 ] 1337 9.25",
&[3.0, 17.0, 4.1],
&'static [f64]
);
}
#[test]
fn set_shared_int_list() {
assert_evals_to!(
indoc!(
r#"
shared = [ 2.1, 4.3 ]
# 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 }
"#
),
(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 int_to_float() {
assert_evals_to!("Num.toFloat 0x9", 9.0, f64);
@ -777,78 +503,4 @@ mod gen_builtins {
fn float_to_float() {
assert_evals_to!("Num.toFloat 0.5", 0.5, f64);
}
#[test]
fn gen_quicksort() {
if true {
todo!("fix gen_quicksort");
}
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), Int, Int -> 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 : Int, Int, 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 : Int, Int, List (Num a) -> [ Pair Int (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 : Int, Int, List (Num a), Int, Int -> [ Pair Int (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 ]
"#
),
&[4, 7, 19, 21],
&'static [i64]
);
}
}