use std::fs::read_to_string; mod ast; use ast::*; mod parser; use parser::*; pub fn run(arg: &str) -> String { let content = read_to_string(arg).unwrap(); let value = parse(&content.to_string()); let result = interpret(&value); result.to_string() } fn interpret(arg: &Value) -> Value { match arg { Value::App(l, r) => apply(l, r), other => other.clone(), } } fn apply(l: &Value, r: &Value) -> Value { if let Value::Lam(v, body) = l { subst(r, v, body) } else { Value::App(Box::new(l.clone()), Box::new(r.clone())) } } fn subst(r: &Value, v: &str, body: &Value) -> Value { match r { Value::Sym(x) if x == v => body.clone(), other => other.clone(), } } #[cfg(test)] mod lambda_test { use crate::{interpret, parse, Value}; #[test] fn evaluating_a_non_reducible_value_yields_itself() { let value = parse("(foo 12)"); assert_eq!(value, interpret(&value)); } #[test] fn evaluating_application_on_an_abstraction_reduces_it() { let value = parse("((lam x x) 12)"); assert_eq!(Value::Num(12), interpret(&value)); } }