summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Bailly <arnaud.bailly@iohk.io>2024-09-24 16:35:42 +0200
committerArnaud Bailly <arnaud.bailly@iohk.io>2024-09-24 16:35:42 +0200
commitc06a076741ae0ad77b21fe58cf0f31e64d1d30d2 (patch)
tree78f99fef81601ca37ee2dddee4b3b7c7f8c238d5
parent91356e9786cce67ed49b4c25b1b66ec9f1d17db2 (diff)
downloadlambda-nantes-c06a076741ae0ad77b21fe58cf0f31e64d1d30d2.tar.gz
Basic substitution for a single variable
-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));
+ }
}