130 lines
2.5 KiB
Rust
130 lines
2.5 KiB
Rust
use std::rc::Rc;
|
|
|
|
use talc_lang::{compiler::compile, optimize::optimize, parser, value::Value, vm::Vm};
|
|
|
|
fn assert_eval(src: &str, value: Value) {
|
|
let mut ex = parser::parse(src).expect(&format!("failed to parse expression"));
|
|
optimize(&mut ex);
|
|
let f = compile(&ex, None).expect("failed to compile expression");
|
|
let f = Rc::new(f);
|
|
let mut vm = Vm::new(16, Vec::new());
|
|
let res = vm
|
|
.run_function(f.clone(), vec![f.into()])
|
|
.expect("vm produced an exception");
|
|
|
|
assert_eq!(
|
|
res.get_type().name(),
|
|
value.get_type().name(),
|
|
"result and target types differ"
|
|
);
|
|
assert_eq!(res, value, "result and target differ");
|
|
}
|
|
|
|
#[test]
|
|
fn scope() {
|
|
assert_eval(
|
|
"
|
|
var x = 7
|
|
var y = 10
|
|
do
|
|
var x = 200
|
|
y = 100
|
|
end
|
|
x + y
|
|
",
|
|
Value::Int(7 + 100),
|
|
);
|
|
assert_eval(
|
|
"
|
|
var cond = true
|
|
var z = 2
|
|
if cond then var z = 5 else var z = 6 end
|
|
z
|
|
",
|
|
Value::Int(2),
|
|
);
|
|
assert_eval(
|
|
"
|
|
var i = 55
|
|
var j = 66
|
|
for i in 0..10 do
|
|
j = i
|
|
end
|
|
i + j
|
|
",
|
|
Value::Int(55 + 9),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn forloop() {
|
|
assert_eval(
|
|
"
|
|
sum = 0
|
|
for i in 0..5 do
|
|
for j in 0..10 do
|
|
sum += i*j
|
|
end
|
|
end
|
|
sum
|
|
",
|
|
Value::Int(45 * 10),
|
|
);
|
|
assert_eval(
|
|
"
|
|
map = {a=3, b=2, c=4, d=7}
|
|
prod = 1
|
|
for k in map do
|
|
prod *= map[k]
|
|
end
|
|
prod
|
|
",
|
|
Value::Int(3 * 2 * 4 * 7),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn closures() {
|
|
assert_eval(
|
|
"
|
|
var x = 2
|
|
next = \\. do x = x * 2 + 1 end
|
|
next() + next() + next()
|
|
",
|
|
Value::Int(5 + 11 + 23),
|
|
);
|
|
assert_eval(
|
|
"
|
|
var x = 0
|
|
fn outer(n) do
|
|
fn inner() do
|
|
x += n
|
|
n += 1
|
|
x
|
|
end
|
|
end
|
|
|
|
var f = outer(2)
|
|
var g = outer(6)
|
|
f() + f() + g() + g() + f()
|
|
",
|
|
Value::Int(2 + 5 + 11 + 18 + 22),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn tailcall() {
|
|
assert_eval(
|
|
"
|
|
fn test(n, a) do
|
|
if n <= 0 then
|
|
a
|
|
else
|
|
self(n-1, n+a)
|
|
end
|
|
end
|
|
test(24, 0)
|
|
",
|
|
Value::Int(300),
|
|
) // = 24 + 23 + ... + 1
|
|
}
|