schala/schala-lang/language/src/eval/test.rs

261 lines
4.7 KiB
Rust
Raw Normal View History

2019-08-16 10:39:21 -07:00
#![cfg(test)]
use std::cell::RefCell;
use std::rc::Rc;
use crate::symbol_table::SymbolTable;
use crate::scope_resolution::ScopeResolver;
use crate::reduced_ast::reduce;
2019-08-16 10:39:21 -07:00
use crate::eval::State;
fn evaluate_all_outputs(input: &str) -> Vec<Result<String, String>> {
let symbol_table = Rc::new(RefCell::new(SymbolTable::new()));
let mut state = State::new(symbol_table);
let mut ast = crate::util::quick_ast(input);
2019-08-16 10:39:21 -07:00
state.symbol_table_handle.borrow_mut().add_top_level_symbols(&ast).unwrap();
2019-09-09 18:12:14 -07:00
{
let mut t = &mut state.symbol_table_handle.borrow_mut();
let mut scope_resolver = crate::scope_resolution::ScopeResolver::new(&mut t);
let _ = scope_resolver.resolve(&mut ast);
2019-09-09 18:12:14 -07:00
}
let reduced = reduce(&ast, &state.symbol_table_handle.borrow());
2019-08-16 10:39:21 -07:00
let all_output = state.evaluate(reduced, true);
all_output
}
macro_rules! test_in_fresh_env {
($string:expr, $correct:expr) => {
{
let all_output = evaluate_all_outputs($string);
let ref output = all_output.last().unwrap();
assert_eq!(**output, Ok($correct.to_string()));
}
}
}
#[test]
fn test_basic_eval() {
test_in_fresh_env!("1 + 2", "3");
test_in_fresh_env!("let mut a = 1; a = 2", "Unit");
/*
test_in_fresh_env!("let mut a = 1; a = 2; a", "2");
test_in_fresh_env!(r#"("a", 1 + 2)"#, r#"("a", 3)"#);
*/
}
#[test]
fn op_eval() {
test_in_fresh_env!("- 13", "-13");
test_in_fresh_env!("10 - 2", "8");
}
#[test]
fn function_eval() {
test_in_fresh_env!("fn oi(x) { x + 1 }; oi(4)", "5");
test_in_fresh_env!("fn oi(x) { x + 1 }; oi(1+2)", "4");
}
#[test]
fn scopes() {
let scope_ok = r#"
let a = 20
fn haha() {
let a = 10
a
}
haha()
"#;
test_in_fresh_env!(scope_ok, "10");
let scope_ok = r#"
let a = 20
fn haha() {
let a = 10
a
}
a
"#;
test_in_fresh_env!(scope_ok, "20");
}
#[test]
fn if_is_patterns() {
let source = r#"
type Option<T> = Some(T) | None
2019-09-10 03:31:23 -07:00
let x = Option::Some(9); if x is Option::Some(q) then { q } else { 0 }"#;
2019-08-16 10:39:21 -07:00
test_in_fresh_env!(source, "9");
let source = r#"
type Option<T> = Some(T) | None
2019-09-10 03:31:23 -07:00
let x = Option::None; if x is Option::Some(q) then { q } else { 0 }"#;
2019-08-16 10:39:21 -07:00
test_in_fresh_env!(source, "0");
}
#[test]
fn full_if_matching() {
let source = r#"
type Option<T> = Some(T) | None
2019-09-10 03:31:23 -07:00
let a = Option::None
2019-09-09 01:04:46 -07:00
if a { is Option::None -> 4, is Option::Some(x) -> x }
2019-08-16 10:39:21 -07:00
"#;
test_in_fresh_env!(source, "4");
let source = r#"
type Option<T> = Some(T) | None
2019-09-10 03:31:23 -07:00
let a = Option::Some(99)
if a { is Option::None -> 4, is Option::Some(x) -> x }
2019-08-16 10:39:21 -07:00
"#;
test_in_fresh_env!(source, "99");
let source = r#"
let a = 10
if a { is 10 -> "x", is 4 -> "y" }
"#;
test_in_fresh_env!(source, "\"x\"");
let source = r#"
let a = 10
if a { is 15 -> "x", is 10 -> "y" }
"#;
test_in_fresh_env!(source, "\"y\"");
}
#[test]
fn string_pattern() {
let source = r#"
let a = "foo"
if a { is "foo" -> "x", is _ -> "y" }
"#;
test_in_fresh_env!(source, "\"x\"");
}
#[test]
fn boolean_pattern() {
let source = r#"
let a = true
if a {
is true -> "x",
is false -> "y"
}
"#;
test_in_fresh_env!(source, "\"x\"");
}
#[test]
fn boolean_pattern_2() {
let source = r#"
let a = false
if a { is true -> "x", is false -> "y" }
"#;
test_in_fresh_env!(source, "\"y\"");
}
#[test]
fn ignore_pattern() {
let source = r#"
type Option<T> = Some(T) | None
2019-09-10 03:31:23 -07:00
if Option::Some(10) {
2019-08-16 10:39:21 -07:00
is _ -> "hella"
}
"#;
test_in_fresh_env!(source, "\"hella\"");
}
#[test]
fn tuple_pattern() {
let source = r#"
if (1, 2) {
is (1, x) -> x,
is _ -> 99
}
"#;
test_in_fresh_env!(source, 2);
}
#[test]
fn tuple_pattern_2() {
let source = r#"
if (1, 2) {
is (10, x) -> x,
is (y, x) -> x + y
}
"#;
test_in_fresh_env!(source, 3);
}
#[test]
fn tuple_pattern_3() {
let source = r#"
if (1, 5) {
is (10, x) -> x,
is (1, x) -> x
}
"#;
test_in_fresh_env!(source, 5);
}
#[test]
fn tuple_pattern_4() {
let source = r#"
if (1, 5) {
is (10, x) -> x,
is (1, x) -> x,
}
"#;
test_in_fresh_env!(source, 5);
}
#[test]
fn prim_obj_pattern() {
let source = r#"
type Stuff = Mulch(Nat) | Jugs(Nat, String) | Mardok
2019-09-10 03:31:23 -07:00
let a = Stuff::Mulch(20)
let b = Stuff::Jugs(1, "haha")
let c = Stuff::Mardok
2019-08-16 10:39:21 -07:00
let x = if a {
2019-09-10 03:31:23 -07:00
is Stuff::Mulch(20) -> "x",
2019-08-16 10:39:21 -07:00
is _ -> "ERR"
}
let y = if b {
2019-09-10 03:31:23 -07:00
is Stuff::Mulch(n) -> "ERR",
is Stuff::Jugs(2, _) -> "ERR",
is Stuff::Jugs(1, s) -> s,
2019-08-16 10:39:21 -07:00
is _ -> "ERR",
}
let z = if c {
2019-09-10 03:31:23 -07:00
is Stuff::Jugs(_, _) -> "ERR",
is Stuff::Mardok -> "NIGH",
2019-08-16 10:39:21 -07:00
is _ -> "ERR",
}
(x, y, z)
"#;
test_in_fresh_env!(source, r#"("x", "haha", "NIGH")"#);
}
#[test]
fn basic_lambda_syntax() {
let source = r#"
let q = \(x, y) { x * y }
let x = q(5,2)
let y = \(m, n, o) { m + n + o }(1,2,3)
(x, y)
"#;
test_in_fresh_env!(source, r"(10, 6)");
}
#[test]
fn lambda_syntax_2() {
let source = r#"
fn milta() {
\(x) { x + 33 }
}
milta()(10)
"#;
test_in_fresh_env!(source, "43");
}