use super::*;
use core::panic;
use std::sync::{Arc, Mutex};
use crate::compiler::{Token, Type};
use crate::Error;
macro_rules! test_output {
($name:ident, $source:expr, $output:expr) => {
#[test]
fn $name() {
check_output($source, $output)
}
};
($( ( $($e:tt)* ) )*) => {
$( test_output!( $($e)* ); )*
};
}
fn check_output(source: &str, expected: Result<&str, ErrorKind>) {
let binary = compile(source);
match (expected, binary) {
(Err(expected), Err(binary)) => assert_eq!(expected, binary.kind),
(expected, Ok(binary)) => {
let out = Arc::new(Mutex::new(String::new()));
run_wasm::run_binary(&binary, out.clone()).unwrap();
match expected {
Err(expected) => panic!("expected {:?}, received {:?}", expected, binary),
Ok(expected) => assert_eq!(*out.lock().unwrap(), expected),
}
}
(expected, binary) => panic!("expected {:?}, received {:?}", expected, binary),
}
}
#[rustfmt::skip]
test_output!(
(print_12, "print 12", Ok("12\n"))
(print_n8, "print -8", Ok("-8\n"))
(mult_print, "print 12 print -8 print 44 print 0.1 print -1e-02", Ok("12\n-8\n44\n0.1\n-0.01\n"))
(print_1p1, "print (1 + 1)", Ok("2\n"))
(print_expr3, "print ((3*2) - (21/7))", Ok("3\n"))
(print_var_a, "var a = 12 print a", Ok("12\n"))
(print_var_b, "var b = (46*72) b = (b/46) print b", Ok("72\n"))
(fibonacci, "
var a = 0
var b = 1
var i = 0
while (i < 10)
print a
b = (a + b)
a = (b - a)
i = (i + 1)
endwhile",
Ok("0\n1\n1\n2\n3\n5\n8\n13\n21\n34\n"))
(if_block, "if (1==1) print 1 endif print 2", Ok("1\n2\n"))
(if_block_no, "if (1==2) print 1 endif print 2", Ok("2\n"))
(if_else_block, "if (1==1) print 1 else print 3 endif print 2", Ok("1\n2\n"))
(if_else_block_no, "if (1==2) print 1 else print 3 endif print 2", Ok("3\n2\n"))
(proc_call, "proc a(x) print x endproc a(10)", Ok("10\n"))
(proc_call3, "proc func(a,b,c) print (a+(b+c)) endproc func(5,2,7)", Ok("14\n"))
(proc_call_local, "proc func(a,b,c) x = 14 print ((a+(b+c))/x) endproc a = 5 m = 2 n = 7 func(a,m,n)", Ok("1\n"))
(recur_call, "
proc A () B() endproc
proc B () print 5 endproc
A()",
Ok("5\n"))
(recur_call3, "
proc A (x) B(x, 2) endproc
proc B (x, y) C(x, y, 4) endproc
proc C (x, y, z) print ((x+y)+z) endproc
A(1)",
Ok("7\n"))
(setpixel_side_effect, "print 0 setpixel(0, 1, 2) print x print y print color", Ok("0\n0\n1\n2\n"))
(print_print,
"print print",
Err(ErrorKind::UnexpectedToken {
received: Token::Print,
expected: &[Token::Number, Token::LeftParen]
})
)
(while_float, "while 0.0 print 1 endwhile",
Err(ErrorKind::UnexpectedType { expected: &[Type::I32], received: vec![Type::F32] }))
(if_float, "if 0.0 print 1 endif",
Err(ErrorKind::UnexpectedType { expected: &[Type::I32], received: vec![Type::F32] }))
(equal_bool, "print ((0.0 == 0.0) == (1.0 == 1.0))",
Err(ErrorKind::UnexpectedType { expected: &[Type::F32, Type::F32], received: vec![Type::I32, Type::I32] }))
(divide_bool, "print ((0.0 == 0.0) / (1.0 == 1.0))",
Err(ErrorKind::UnexpectedType { expected: &[Type::F32, Type::F32], received: vec![Type::I32, Type::I32] }))
(and_float, "print (0.0 && 0.0)",
Err(ErrorKind::UnexpectedType { expected: &[Type::I32, Type::I32], received: vec![Type::F32, Type::F32] }))
(unknown_proc, "\n\n\nvM(8)",
Err(ErrorKind::UndeclaredProc { name: "vM".to_string() }))
(unclosed_paren, "LM((88,8",
Err(ErrorKind::UnexpectedToken { expected: &[Token::Operator], received: Token::Comma }))
);
#[test]
fn mandelbrot() -> Result<(), Error<'static>> {
let source = "
var y = 0
while (y < 100)
y = (y + 1)
var x = 0
while (x < 100)
x = (x + 1)
var e = ((y / 50) - 1.5)
var f = ((x / 50) - 1)
var a = 0
var b = 0
var i = 0
var j = 0
var c = 0
while ((((i * i) + (j * j)) < 4) && (c < 255))
i = (((a * a) - (b * b)) + e)
j = (((2 * a) * b) + f)
a = i
b = j
c = (c + 1)
endwhile
setpixel (x, y, c)
endwhile
endwhile";
let binary = compile(source)?;
let out = Arc::new(Mutex::new(String::new()));
let output = run_wasm::run_binary(&binary, out.clone()).unwrap();
let hash = blake3::hash(&output);
assert_eq!(&hash.to_hex()[0..16], "28ad088dd153090f");
Ok(())
}