commit 0706056111e8bed1b49796578d3635e2a210dd59 Author: Gabriel Tofvesson Date: Sat Aug 23 21:32:48 2025 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a8cabc --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +.idea diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..508891c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bred" +version = "0.1.0" +dependencies = [ + "take_mut", +] + +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..780912c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bred" +version = "0.1.0" +edition = "2024" + +[dependencies] +take_mut = "0.2.2" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..3403a39 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,113 @@ +use std::cell::RefCell; +use std::rc::Rc; + +#[derive(Debug)] +struct ArgCell(Rc>>); + +#[derive(Debug)] +struct Lambda { + arg: ArgCell, + expression: Expression +} + +#[derive(Debug)] +enum EitherValue { + Lambda(Lambda), + Expression(Expression) +} + +#[derive(Debug, Clone)] +enum Expression { + Valued(ArgCell), + Expression(ArgCell, ArgCell) +} + +impl ArgCell { + fn lambda(value: Lambda) -> Self { + ArgCell(Rc::new(RefCell::new(Some(EitherValue::Lambda(value))))) + } + + fn expression(expression: Expression) -> Self { + ArgCell(Rc::new(RefCell::new(Some(EitherValue::Expression(expression))))) + } + + fn future() -> Self { + ArgCell(Rc::new(RefCell::new(None))) + } + + fn copy_retain(&self) -> Self { + Self(self.0.clone()) + } +} + +impl Clone for ArgCell { + fn clone(&self) -> Self { + let cell = self.0.borrow(); + if cell.is_some() { + Self(self.0.clone()) + } else { + Self(Rc::new(RefCell::new(None))) + } + } +} + +impl Lambda { + fn new(expression: impl FnOnce(ArgCell) -> Expression) -> Self { + let cell = ArgCell::future(); + Self { + arg: cell.copy_retain(), + expression: expression(cell) + } + } + + fn beta_reduce(self, argument: Option) -> Expression { + *self.arg.0.borrow_mut() = argument; + self.expression + } +} + +impl Clone for Lambda { + fn clone(&self) -> Self { + Self::new(|_| self.expression.clone()) + } +} + +impl EitherValue { + fn is_lambda(&self) -> bool { + matches!(*self, EitherValue::Lambda(_)) + } + + fn is_expression(&self) -> bool { + matches!(*self, EitherValue::Expression(_)) + } +} + +impl Expression { + fn new_valued(value: ArgCell) -> Self { + Self::Valued(value) + } + + fn new_expression(callee: ArgCell, argument: ArgCell) -> Self { + Self::Expression(callee, argument) + } + + fn can_beta_reduce(&self) -> bool { + // TODO: Clean this up + matches!(self, Self::Expression(callee, _) if callee.0.borrow().is_some() && callee.0.borrow().as_ref().unwrap().is_lambda()) + } +} + +// (lx.(ly.x(xy))) (lz.z) +// -> (ly.(lz.z)((lw.w)y)) +// -> (ly.(lz.z)y) +// -> (ly.y) +fn main() { + // Lambda_x { Expression { Lambda_y { Expression { x(Expression(x, y)) } } } } + let func = Lambda::new(|x| + Expression::new_valued(ArgCell::lambda(Lambda::new(|y| Expression::new_expression(x.copy_retain(), ArgCell::expression(Expression::Expression(x, y)))))) + ); + + let func_identity = Some(EitherValue::Lambda(Lambda::new(Expression::Valued))); + let reduced = func.beta_reduce(func_identity); + dbg!(reduced); +}