roc/tests/test_infer.rs
2019-09-17 04:31:54 -04:00

579 lines
12 KiB
Rust

#[macro_use]
extern crate pretty_assertions;
#[macro_use]
extern crate indoc;
extern crate roc;
mod helpers;
#[cfg(test)]
mod test_infer {
use helpers::can_expr;
// use roc::can::symbol::Symbol;
// use roc::ident::{Ident, VariantName};
use roc::infer::infer_expr;
use roc::pretty_print_types::content_to_string;
use roc::region::Located;
// use roc::subs::Content::{self, *};
use roc::subs::Subs;
// use roc::subs::{FlatType, Variable};
// use roc::types::Type::*;
// use roc::types::{Problem, Type};
// HELPERS
fn infer_eq(src: &str, expected: &str) {
let (expr, _, _, procedures) = can_expr(src);
let mut subs = Subs::new();
let content = infer_expr(&mut subs, Located::new(0, 0, 0, 0, expr), procedures);
let actual_str = content_to_string(content, &mut subs);
assert_eq!(actual_str, expected.to_string());
}
// fn apply(module_name: &str, type_name: &str, args: Vec<Variable>) -> Content {
// Structure(FlatType::Apply(
// module_name.to_string(),
// type_name.to_string(),
// args,
// ))
// }
// fn var(num: u32) -> Variable {
// Variable::new_for_testing_only(num)
// }
#[test]
fn empty_record() {
infer_eq("{}", "{}");
}
#[test]
fn int_literal() {
infer_eq("5", "Int");
}
#[test]
fn float_literal() {
infer_eq("0.5", "Float");
}
#[test]
fn string_literal() {
infer_eq(
indoc!(
r#"
"type inference!"
"#
),
"String",
);
}
// #[test]
// fn empty_string() {
// infer_eq(
// indoc!(
// r#"
// ""
// "#
// ),
// "String",
// );
// }
// // LIST
// #[test]
// fn empty_list() {
// infer_eq(
// indoc!(
// r#"
// []
// "#
// ),
// "List *",
// );
// }
// #[test]
// fn list_of_lists() {
// infer_eq(
// indoc!(
// r#"
// [[]]
// "#
// ),
// "List (List *)",
// );
// }
// #[test]
// fn triple_nested_list() {
// infer_eq(
// indoc!(
// r#"
// [[[]]]
// "#
// ),
// "List (List (List *))",
// );
// }
// #[test]
// fn nested_empty_list() {
// infer_eq(
// indoc!(
// r#"
// [ [], [ [] ] ]
// "#
// ),
// "List (List (List *))",
// );
// }
// #[test]
// fn list_of_one_int() {
// infer_eq(
// indoc!(
// r#"
// [42]
// "#
// ),
// "List Int",
// );
// }
// #[test]
// fn triple_nested_int_list() {
// infer_eq(
// indoc!(
// r#"
// [[[ 5 ]]]
// "#
// ),
// "List (List (List Int))",
// );
// }
// #[test]
// fn list_of_ints() {
// infer_eq(
// indoc!(
// r#"
// [ 1, 2, 3 ]
// "#
// ),
// "List Int",
// );
// }
// #[test]
// fn nested_list_of_ints() {
// infer_eq(
// indoc!(
// r#"
// [ [ 1 ], [ 2, 3 ] ]
// "#
// ),
// "List (List Int)",
// );
// }
// #[test]
// fn list_of_one_string() {
// infer_eq(
// indoc!(
// r#"
// [ "cowabunga" ]
// "#
// ),
// "List String",
// );
// }
// #[test]
// fn triple_nested_string_list() {
// infer_eq(
// indoc!(
// r#"
// [[[ "foo" ]]]
// "#
// ),
// "List (List (List String))",
// );
// }
// #[test]
// fn list_of_strings() {
// infer_eq(
// indoc!(
// r#"
// [ "foo", "bar" ]
// "#
// ),
// "List String",
// );
// }
// // INTERPOLATED STRING
// #[test]
// fn infer_interpolated_string() {
// infer_eq(
// indoc!(
// r#"
// whatItIs = "great"
// "type inference is \(whatItIs)!"
// "#
// ),
// "String",
// );
// }
// // LIST MISMATCH
// #[test]
// fn mismatch_heterogeneous_list() {
// infer_eq(
// indoc!(
// r#"
// [ "foo", 5 ]
// "#
// ),
// "List <type mismatch>",
// );
// }
// #[test]
// fn mismatch_heterogeneous_nested_list() {
// infer_eq(
// indoc!(
// r#"
// [ [ "foo", 5 ] ]
// "#
// ),
// "List (List <type mismatch>)",
// );
// }
// #[test]
// fn mismatch_heterogeneous_nested_empty_list() {
// infer_eq(
// indoc!(
// r#"
// [ [ 1 ], [ [] ] ]
// "#
// ),
// "List (List <type mismatch>)",
// );
// }
// // CLOSURE
// #[test]
// fn always_return_empty_record() {
// infer_eq(
// indoc!(
// r#"
// \_ -> {}
// "#
// ),
// "* -> {}",
// );
// }
// #[test]
// fn two_arg_return_int() {
// infer_eq(
// indoc!(
// r#"
// \_ _ -> 42
// "#
// ),
// "*, * -> Int",
// );
// }
// #[test]
// fn three_arg_return_string() {
// infer_eq(
// indoc!(
// r#"
// \_ _ _ -> "test!"
// "#
// ),
// "*, *, * -> String",
// );
// }
// // ASSIGN
// #[test]
// fn assign_empty_record() {
// infer_eq(
// indoc!(
// r#"
// foo = {}
// foo
// "#
// ),
// "{}",
// );
// }
// #[test]
// fn assign_string() {
// infer_eq(
// indoc!(
// r#"
// str = "thing"
// str
// "#
// ),
// "String",
// );
// }
// #[test]
// fn assign_1_arg_closure() {
// infer_eq(
// indoc!(
// r#"
// fn = \_ -> {}
// fn
// "#
// ),
// "* -> {}",
// );
// }
// #[test]
// fn assign_2_arg_closure() {
// infer_eq(
// indoc!(
// r#"
// func = \_ _ -> 42
// func
// "#
// ),
// "*, * -> Int",
// );
// }
// #[test]
// fn assign_3_arg_closure() {
// infer_eq(
// indoc!(
// r#"
// f = \_ _ _ -> "test!"
// f
// "#
// ),
// "*, *, * -> String",
// );
// }
// #[test]
// fn assign_multiple_functions() {
// infer_eq(
// indoc!(
// r#"
// a = \_ _ _ -> "test!"
// b = a
// b
// "#
// ),
// "*, *, * -> String",
// );
// }
// #[test]
// fn assign_multiple_strings() {
// infer_eq(
// indoc!(
// r#"
// a = "test!"
// b = a
// b
// "#
// ),
// "String",
// );
// }
// #[test]
// fn assign_multiple_nums() {
// infer_eq(
// indoc!(
// r#"
// c = b
// b = a
// a = 42
// c
// "#
// ),
// "Int",
// );
// }
// // CALLING FUNCTIONS
// #[test]
// fn call_returns_num() {
// infer_eq(
// indoc!(
// r#"
// alwaysFive = \_ -> 5
// alwaysFive "stuff"
// "#
// ),
// "Int",
// );
// }
// #[test]
// fn call_returns_list() {
// infer_eq(
// indoc!(
// r#"
// enlist = \val -> [ val ]
// enlist 5
// "#
// ),
// "List Int",
// );
// }
// // TODO type annotations
// // TODO fix identity inference
// // TODO BoundTypeVariables
// // TODO conditionals
// // #[test]
// // fn indirect_always() {
// // infer_eq(
// // indoc!(r#"
// // always = \val -> (\_ -> val)
// // alwaysFoo = always "foo"
// // alwaysFoo 42
// // "#),
// // "String"
// // );
// // }
// // #[test]
// // fn identity() {
// // infer_eq(
// // indoc!(r#"
// // \val -> val
// // "#),
// // "a -> a"
// // );
// // }
// // #[test]
// // fn always_function() {
// // infer_eq(
// // indoc!(r#"
// // \val -> \_ -> val
// // "#),
// // "a -> (* -> a)"
// // );
// // }
// // OPERATORS
// #[test]
// fn div_operator() {
// infer_eq(
// indoc!(
// r#"
// \l r -> l / r
// "#
// ),
// "Float, Float -> Float",
// );
// }
// #[test]
// fn basic_division() {
// infer_eq(
// indoc!(
// r#"
// 1 / 2
// "#
// ),
// "Float",
// );
// }
// #[test]
// fn basic_addition() {
// infer_eq(
// indoc!(r#"
// 1 + 2
// "#),
// "Num *"
// );
// }
// #[test]
// fn basic_circular_type() {
// assert_eq!(
// infer(indoc!(r#"
// \x -> x x
// "#)),
// Erroneous(Problem::CircularType)
// );
// }
// #[test]
// fn y_combinator_has_circular_type() {
// assert_eq!(
// infer(indoc!(r#"
// \f -> (\x -> f x x) (\x -> f x x)
// "#)),
// Erroneous(Problem::CircularType)
// );
// }
// #[test]
// fn no_higher_ranked_types() {
// // This should error because it can't type of alwaysFive
// infer_eq(
// indoc!(r#"
// alwaysFive = \_ -> 5
// [ alwaysFive "foo", alwaysFive [] ]
// "#),
// "<type mismatch>"
// );
// }
// #[test]
// fn infer_basic_case() {
// assert_eq!(
// infer("case 42 when 1 then 2.5 when _ then 3.5"),
// Builtin(Frac)
// );
// }
}