Move eval tests
This commit is contained in:
parent
cd20afc3c7
commit
3caf9c763c
@ -11,6 +11,8 @@ use crate::reduced_ast::{BoundVars, ReducedAST, Stmt, Expr, Lit, Func, Alternati
|
|||||||
use crate::symbol_table::{SymbolSpec, Symbol, SymbolTable};
|
use crate::symbol_table::{SymbolSpec, Symbol, SymbolTable};
|
||||||
use crate::builtin::Builtin;
|
use crate::builtin::Builtin;
|
||||||
|
|
||||||
|
mod test;
|
||||||
|
|
||||||
pub struct State<'a> {
|
pub struct State<'a> {
|
||||||
values: ScopeStack<'a, Rc<String>, ValueEntry>,
|
values: ScopeStack<'a, Rc<String>, ValueEntry>,
|
||||||
symbol_table_handle: Rc<RefCell<SymbolTable>>,
|
symbol_table_handle: Rc<RefCell<SymbolTable>>,
|
||||||
@ -491,257 +493,3 @@ impl<'a> State<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod eval_tests {
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::symbol_table::SymbolTable;
|
|
||||||
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 ast = crate::util::quick_ast(input);
|
|
||||||
state.symbol_table_handle.borrow_mut().add_top_level_symbols(&ast).unwrap();
|
|
||||||
let reduced = ast.reduce(&state.symbol_table_handle.borrow());
|
|
||||||
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
|
|
||||||
let x = Some(9); if x is Some(q) then { q } else { 0 }"#;
|
|
||||||
test_in_fresh_env!(source, "9");
|
|
||||||
|
|
||||||
let source = r#"
|
|
||||||
type Option<T> = Some(T) | None
|
|
||||||
let x = None; if x is Some(q) then { q } else { 0 }"#;
|
|
||||||
test_in_fresh_env!(source, "0");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn full_if_matching() {
|
|
||||||
let source = r#"
|
|
||||||
type Option<T> = Some(T) | None
|
|
||||||
let a = None
|
|
||||||
if a { is None -> 4, is Some(x) -> x }
|
|
||||||
"#;
|
|
||||||
test_in_fresh_env!(source, "4");
|
|
||||||
|
|
||||||
let source = r#"
|
|
||||||
type Option<T> = Some(T) | None
|
|
||||||
let a = Some(99)
|
|
||||||
if a { is None -> 4, is Some(x) -> x }
|
|
||||||
"#;
|
|
||||||
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
|
|
||||||
if Some(10) {
|
|
||||||
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
|
|
||||||
let a = Mulch(20)
|
|
||||||
let b = Jugs(1, "haha")
|
|
||||||
let c = Mardok
|
|
||||||
|
|
||||||
let x = if a {
|
|
||||||
is Mulch(20) -> "x",
|
|
||||||
is _ -> "ERR"
|
|
||||||
}
|
|
||||||
|
|
||||||
let y = if b {
|
|
||||||
is Mulch(n) -> "ERR",
|
|
||||||
is Jugs(2, _) -> "ERR",
|
|
||||||
is Jugs(1, s) -> s,
|
|
||||||
is _ -> "ERR",
|
|
||||||
}
|
|
||||||
|
|
||||||
let z = if c {
|
|
||||||
is Jugs(_, _) -> "ERR",
|
|
||||||
is Mardok -> "NIGH",
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
252
schala-lang/language/src/eval/test.rs
Normal file
252
schala-lang/language/src/eval/test.rs
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::symbol_table::SymbolTable;
|
||||||
|
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 ast = crate::util::quick_ast(input);
|
||||||
|
state.symbol_table_handle.borrow_mut().add_top_level_symbols(&ast).unwrap();
|
||||||
|
let reduced = ast.reduce(&state.symbol_table_handle.borrow());
|
||||||
|
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
|
||||||
|
let x = Some(9); if x is Some(q) then { q } else { 0 }"#;
|
||||||
|
test_in_fresh_env!(source, "9");
|
||||||
|
|
||||||
|
let source = r#"
|
||||||
|
type Option<T> = Some(T) | None
|
||||||
|
let x = None; if x is Some(q) then { q } else { 0 }"#;
|
||||||
|
test_in_fresh_env!(source, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn full_if_matching() {
|
||||||
|
let source = r#"
|
||||||
|
type Option<T> = Some(T) | None
|
||||||
|
let a = None
|
||||||
|
if a { is None -> 4, is Some(x) -> x }
|
||||||
|
"#;
|
||||||
|
test_in_fresh_env!(source, "4");
|
||||||
|
|
||||||
|
let source = r#"
|
||||||
|
type Option<T> = Some(T) | None
|
||||||
|
let a = Some(99)
|
||||||
|
if a { is None -> 4, is Some(x) -> x }
|
||||||
|
"#;
|
||||||
|
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
|
||||||
|
if Some(10) {
|
||||||
|
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
|
||||||
|
let a = Mulch(20)
|
||||||
|
let b = Jugs(1, "haha")
|
||||||
|
let c = Mardok
|
||||||
|
|
||||||
|
let x = if a {
|
||||||
|
is Mulch(20) -> "x",
|
||||||
|
is _ -> "ERR"
|
||||||
|
}
|
||||||
|
|
||||||
|
let y = if b {
|
||||||
|
is Mulch(n) -> "ERR",
|
||||||
|
is Jugs(2, _) -> "ERR",
|
||||||
|
is Jugs(1, s) -> s,
|
||||||
|
is _ -> "ERR",
|
||||||
|
}
|
||||||
|
|
||||||
|
let z = if c {
|
||||||
|
is Jugs(_, _) -> "ERR",
|
||||||
|
is Mardok -> "NIGH",
|
||||||
|
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");
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user