aboutsummaryrefslogtreecommitdiff
path: root/src/simple.rs
blob: 8d87dbf6c982fd4b512de0455b123fa1f0b1ee43 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use crate::ast::*;

/// Evaluates an expression given a context (of variables) to a term, or fails.
pub fn execute(context: &Context, expression: Expression) -> Result<Term, String> {
    match expression {
        Expression::Annotation { expr, .. } => execute(context, *expr),
        Expression::Constant { term } => Ok(term),
        Expression::Variable { id } => match context.get(&id) {
            Some(term) => Ok(term.clone()),
            None => Err(format!("no such variable in context {context:?}"))
        },
        Expression::Abstraction { param, func } =>
            Err(format!("attempting to execute an abstraction ({}){}", param, func)),
        Expression::Application { func, arg } => match *func {
            Expression::Abstraction { param, func } => {
                let value = execute(context, *arg)?;
                let mut context = context.clone();
                context.insert(param, value);
                return execute(&context, *func);
            }
            _ => Err(format!("attempting to execute an application to non-abstraction {}", *func))
        },
        Expression::Conditional { if_cond, if_then, if_else } => {
            match execute(context, *if_cond)? {
                Term::Boolean(true) => execute(context, *if_then),
                Term::Boolean(false) => execute(context, *if_else),
                term => Err(format!("invalid type {} for a conditional", convert(&term)?))
            }
        }
    }
}