aboutsummaryrefslogtreecommitdiff
path: root/src/simple.rs
blob: c65905827857868bbea917a06f54d5c1281665e5 (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
33
use crate::ast::*;

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