use crate::parser::ast::Expr;
use crate::parser::types::{Value, FunctionValue, LambdaParam};
use crate::parser::interpreter::Interpreter;
use crate::parser::interpreter::apply;
use super::helpers::err_with_pos;
use super::regex::eval_regex_literal;
use super::indexing::eval_index_expr;
impl Interpreter {
pub fn eval_expression(&mut self, expr: &Expr) -> Result<Value, String> {
use Expr::*;
match expr {
Number { value, .. } => Ok(Value::Int(*value)),
NumberFloat { value, .. } => Ok(Value::Float(*value)),
StrLit { value, .. } => Ok(Value::SingleString(value.clone())),
Bool { value, .. } => Ok(Value::Bool(*value)),
Ident { name, line, col } => {
let v = self.lookup_variable(name)
.ok_or_else(|| err_with_pos(format!("Undefined variable '{}'", name), *line, *col))?;
match v {
Value::Ref(arc_mutex) => Ok(arc_mutex.lock().unwrap().clone()),
v => Ok(v),
}
}
Ref { expr: inner, line, col } => {
match &**inner {
Expr::Ident { name, line: n_line, col: n_col } => {
let storage = self.lookup_variable_storage(name)
.ok_or_else(|| err_with_pos(format!("Undefined variable '{}'", name), *n_line, *n_col))?;
Ok(Value::Ref(storage))
}
_ => Err(err_with_pos("Can only take reference of a variable", *line, *col)),
}
}
Placeholder { .. } => Ok(Value::Placeholder),
BracketedArray { items, .. } => crate::parser::interpreter::utils::eval_bracketed_array(self, items),
KeyedArray { pairs, .. } => crate::parser::interpreter::utils::eval_keyed_array(self, pairs),
FunctionCall { callee, args, line, col } => {
let callee_val = self.eval_expression(callee)?;
if let Value::Function(fb) = &callee_val {
if let FunctionValue::InlineLambdaAST { params, .. } = &**fb {
let mut arg_vals = Vec::new();
for (i, a_expr) in args.iter().enumerate() {
let use_ref = params.get(i)
.map(|p| matches!(p, LambdaParam::Ref(_)))
.unwrap_or(false);
if use_ref {
if let Expr::Ident { name, line: v_line, col: v_col } = a_expr {
let storage = self.lookup_variable_storage(name)
.ok_or_else(|| err_with_pos(format!("Undefined variable '{}'", name), *v_line, *v_col))?;
arg_vals.push(Value::Ref(storage));
} else {
let v = self.eval_expression(a_expr)?;
arg_vals.push(Value::Ref(std::sync::Arc::new(std::sync::Mutex::new(v))));
}
} else {
arg_vals.push(self.eval_expression(a_expr)?);
}
}
return apply::apply_n_ary_function_value(self, fb.clone(), arg_vals);
}
}
let mut arg_vals = Vec::new();
for a_expr in args {
arg_vals.push(self.eval_expression(a_expr)?);
}
match callee_val {
Value::Function(fb) => apply::apply_n_ary_function_value(self, fb, arg_vals),
Value::InkTransform(fb) => apply::apply_n_ary_function_value(self, fb, arg_vals),
Value::Stream(sh) => {
Err(err_with_pos(format!("Cannot call a Stream as a function: stream_id={}", sh.stream_id), *line, *col))
}
other => Err(err_with_pos(format!("Cannot call non-function: {:?}", other), *line, *col)),
}
}
Index { base, index, .. } => {
let base_val = self.eval_expression(base)?;
let idx_val = self.eval_expression(index)?;
eval_index_expr(self, base_val, idx_val)
}
Gt { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_gt(lv, rv)
}
Lt { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_lt(lv, rv)
}
EqEq { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_eqeq(lv, rv)
}
Le { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_le(lv, rv)
}
Ge { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_ge(lv, rv)
}
Add { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_add(lv, rv)
}
Sub { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_sub(lv, rv)
}
Mul { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_mul(lv, rv)
}
Div { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_div(lv, rv)
}
Mod { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_mod(lv, rv)
}
Ternary { cond, if_true, if_false, .. } => {
let cval = self.eval_expression(cond)?;
match cval {
Value::Bool(flag) => {
if flag {
self.eval_expression(if_true)
} else {
self.eval_expression(if_false)
}
}
Value::Int(i) => {
if i == 0 {
self.eval_expression(if_false)
} else {
self.eval_expression(if_true)
}
}
Value::Float(f) => {
if f == 0.0 {
self.eval_expression(if_false)
} else {
self.eval_expression(if_true)
}
}
Value::Long(l) => {
if l == 0 {
self.eval_expression(if_false)
} else {
self.eval_expression(if_true)
}
}
_ => Err(err_with_pos("Ternary condition must be bool/int/float/long", 0, 0)),
}
}
InlineLambdaAST { params, body, .. } => {
let fv = FunctionValue::InlineLambdaAST {
params: params.clone(),
body_expr: body.clone(),
};
Ok(Value::Function(Box::new(fv)))
}
Block { stmts, .. } => {
self.push_scope();
let mut last_val = Value::Bool(true);
for s in stmts {
let v = self.exec_statement(s)?;
last_val = v;
}
self.pop_scope();
Ok(last_val)
}
UnaryMinus { expr: subexpr, .. } => {
let val = self.eval_expression(subexpr)?;
match val {
Value::Int(i) => i.checked_neg()
.map(Value::Int)
.ok_or_else(|| err_with_pos("Overflow in unary minus", 0, 0)),
Value::Long(l) => l.checked_neg()
.map(Value::Long)
.ok_or_else(|| err_with_pos("Overflow in unary minus (long)", 0, 0)),
Value::Float(ff) => Ok(Value::Float(-ff)),
other => Err(err_with_pos(format!("Cannot apply unary minus to {:?}", other), 0, 0)),
}
}
AndAnd { left, right, .. } => {
let left_val = self.eval_expression(left)?;
let left_truth = crate::parser::interpreter::utils::bool_like(&left_val)?;
if !left_truth {
Ok(Value::Bool(false))
} else {
let right_val = self.eval_expression(right)?;
let right_truth = crate::parser::interpreter::utils::bool_like(&right_val)?;
Ok(Value::Bool(right_truth))
}
}
UnaryNot { expr: subexpr, .. } => {
let val = self.eval_expression(subexpr)?;
let truth = crate::parser::interpreter::utils::bool_like(&val)?;
Ok(Value::Bool(!truth))
}
Ne { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_ne(lv, rv)
}
BitAnd { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_bitand(lv, rv)
}
OrOr { left, right, .. } => {
let left_val = self.eval_expression(left)?;
let left_truth = crate::parser::interpreter::utils::bool_like(&left_val)?;
if left_truth {
Ok(Value::Bool(true))
} else {
let right_val = self.eval_expression(right)?;
let right_truth = crate::parser::interpreter::utils::bool_like(&right_val)?;
Ok(Value::Bool(right_truth))
}
}
Shl { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_shl(lv, rv)
}
Shr { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_shr(lv, rv)
}
BitXor { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_bitxor(lv, rv)
}
BitTilde { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_bittilde(lv, rv)
}
BitOr { left, right, .. } => {
let lv = self.eval_expression(left)?;
let rv = self.eval_expression(right)?;
self.eval_bitor(lv, rv)
}
RegexLit { pattern, flags, line, col } => {
eval_regex_literal(pattern, flags, *line, *col)
}
}
}
}