summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rust/src/lambda.rs42
1 files changed, 38 insertions, 4 deletions
diff --git a/rust/src/lambda.rs b/rust/src/lambda.rs
index 9633bdd..9964021 100644
--- a/rust/src/lambda.rs
+++ b/rust/src/lambda.rs
@@ -9,12 +9,46 @@ 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);
+ let result = interpret(&value);
result.to_string()
}
-fn interpret(arg: Value) -> Value {
- // interpreting a value is the value itself
- arg
+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));
+ }
}