use std::rc::Rc;
use ast::types::*;
use eval::types::*;
pub fn eval<'a>(expr: Expression, stack: &'a mut CallStack) {
stack.push_frame();
let out = match expr {
Expression::Call(symbol, arguments) => {
if stack.env.borrow().language_functions.contains_key(&symbol) {
let env_rc = Rc::clone(&stack.env);
let env = env_rc.borrow();
let func = env.language_functions.get(&symbol).as_ref().unwrap().clone();
func.call((arguments, stack))
} else {
let mut arg_values = Vec::<Value>::new();
for sub_expr in arguments {
eval(sub_expr, stack);
arg_values.push(stack.pop_return());
};
if let Some(func) = stack.env.borrow().static_functions.get(&symbol) {
func.call((arg_values,))
}
else if let Value::Function(ref func) = stack.get_value(&symbol) {
func.call(arg_values)
}
else {
Value::Null }
}
},
Expression::Symbol(ref symbol) => {
stack.get_value(symbol)
},
Expression::Value(value) => value,
_ => Value::Null
};
stack.top().borrow_mut().returns = out;
}