extern crate lichen;
use lichen::parse::Parser;
use lichen::var::Var;
use lichen::eval::Evaluator;
use lichen::fun::Fun;
use std::sync::{Arc,Mutex};
#[derive(Debug)]
struct Player {
coins: f32,
name: String
}
#[test]
fn state_mut() {
let src = "\n
def global\n
;\n
\n
root\n
@global.coins 1\n
emit \"step\"\n
@global.coins + 5\n
emit global.coins\n
;";
let mut env = Parser::parse_blocks(src).expect("ERROR: Unable to parse source").into_env();
let ev = Evaluator::new(&mut env);
let (vars,_) = ev.last().unwrap();
assert_eq!(vars[0], 6.0 .into());
}
#[test]
fn parse_cust_fn() {
let src = "root\n
@root.five (inc) 1 2 3\n
emit root.five\n
;\n
def root\n
five 5\n
;";
let mut env = Parser::parse_blocks(src).expect("ERROR: Unable to parse source").into_env();
let inc = Fun::new(move |args, def| {
let mut r = 0.;
for n in args.iter() {
if let Ok(v) = n.get_num(def) {
r += v;
}
}
return Some(Var::Num(r))
});
env.fun.insert("inc".to_owned(), inc);
let ev = Evaluator::new(&mut env);
let (vars,_) = ev.last().unwrap();
assert_eq!(vars[0], 6.0 .into());
}
#[test]
fn parse_def_block() {
let src = "root\n
emit global.name global.size\n
;\n
\n
def global\n
name \"my-game\"\n
size 1.5\n
;";
let mut env = Parser::parse_blocks(src).expect("ERROR: Unable to parse source").into_env();
let mut ev = Evaluator::new(&mut env);
let (vars,_) = ev.next().unwrap();
assert_eq!(vars[0], Var::String("my-game".to_owned()));
assert_eq!(vars[1], Var::Num(1.5 .to_owned()));
}
#[test]
fn validate_def_block() {
let src = "root\n
@global.size + 0.5\n
@global.name \"other-game\"\n
emit global.name global.size\n\n
;\n
\n
def global\n
name \"my-game\"\n
size 1.5\n
;";
let mut env = Parser::parse_blocks(src).expect("ERROR: Unable to parse source").into_env();
let ev = Evaluator::new(&mut env);
let (vars,_) = ev.last().unwrap();
assert_eq!(vars[0], Var::String("other-game".to_owned()));
assert_eq!(vars[1], Var::Num(2.0 .to_owned()));
}
#[test]
fn validate_when_block() {
let src = "root\n
needs_coins global.coins < 1\n
when {needs_coins @global.coins + 2, \n
!global.name @global.name \"new-name\"}\n
emit global.name global.coins\n
;\n
def global\n
coins 0\n
;\n";
let mut env = Parser::parse_blocks(src).expect("ERROR: Unable to parse source").into_env();
let ev = Evaluator::new(&mut env);
let (vars,_) = ev.last().unwrap();
assert_eq!(vars[1], 2.0 .into());
assert_eq!(vars[0], "new-name".into());
}
#[test]
fn save_state() {
let src = "root\n
emit root.coins\n
@root.coins (inc) \"coins\" 1 2 3\n
next:await no-where\n
emit root.coins\n
;\n
def root\n
coins 0\n
;";
let mut env = Parser::parse_blocks(src).expect("ERROR: Unable to parse source").into_env();
let data = Player { coins: 0.0, name: "Pan".to_owned() };
let data = Arc::new(Mutex::new(data));
let dc = data.clone();
let inc = Fun::new(move |args, def| {
let mut r = dc.lock().unwrap();
for n in args.iter() {
if let Ok(v) = n.get_num(def) {
r.coins += v;
}
}
Some(r.coins.into())
});
env.fun.insert("inc".to_owned(), inc);
let state = {
let mut ev = Evaluator::new(&mut env);
let (vars,_) = ev.next().unwrap();
assert_eq!(vars[0], 0.0 .into());
ev.save()
};
let state = { let mut ev = state.to_eval(&mut env);
let (_,_) = ev.next().unwrap();
ev.save()
};
let mut ev = state.to_eval(&mut env);
let (vars,_) = ev.next().unwrap();
assert_eq!(vars[0], 6.0 .into());
let player = data.lock().unwrap();
assert_eq!(player.coins, 6.0);
}
#[test]
fn validate_or_block() {
let src = "root\n
if !global.drunk \"not drunk\"\n
or \"is drunk\"\n
\n
@global.drunk true\n
\n
if !global.drunk \"not drunk\"\n
or \"is drunk\"\n
;\n
\n
def global\n
drunk false
;";
let mut env = Parser::parse_blocks(src).expect("ERROR: Unable to parse source").into_env();
let mut ev = Evaluator::new(&mut env);
let (vars,_) = ev.next().unwrap();
assert_eq!(vars[0], "not drunk".into());
let (vars,_) = ev.next().unwrap();
assert_eq!(vars[0], "is drunk".into());
}