diff options
| author | Arnaud Bailly <arnaud.bailly@iohk.io> | 2024-09-24 16:35:42 +0200 |
|---|---|---|
| committer | Arnaud Bailly <arnaud.bailly@iohk.io> | 2024-09-24 16:35:42 +0200 |
| commit | c06a076741ae0ad77b21fe58cf0f31e64d1d30d2 (patch) | |
| tree | 78f99fef81601ca37ee2dddee4b3b7c7f8c238d5 /rust/src | |
| parent | 91356e9786cce67ed49b4c25b1b66ec9f1d17db2 (diff) | |
| download | lambda-nantes-c06a076741ae0ad77b21fe58cf0f31e64d1d30d2.tar.gz | |
Basic substitution for a single variable
Diffstat (limited to 'rust/src')
| -rw-r--r-- | rust/src/lambda.rs | 42 |
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)); + } } |
