diff --git a/crates/program_builder/src/lib.rs b/crates/program_builder/src/lib.rs index 807fab29..30ff50cb 100644 --- a/crates/program_builder/src/lib.rs +++ b/crates/program_builder/src/lib.rs @@ -5,62 +5,61 @@ use uplc::ast::{Constant, Name, Program, Term, Unique}; #[cfg(test)] mod tests; -#[derive(Default)] pub struct Builder { version: (usize, usize, usize), - term_builder: TermBuilder, + term: Term, } -#[derive(Clone)] -enum TermBuilder { - Null, - Constant(Constant), - Lambda(Box), +pub struct Empty { + version: (usize, usize, usize), } -impl TermBuilder { - pub fn build_named(&self) -> Term { - match self.clone() { - Self::Null => todo!("Make fallible?"), - Self::Constant(c) => Term::Constant(c), - Self::Lambda(term) => Term::Lambda { - parameter_name: Name { - text: "i".to_string(), - unique: Unique::new(0), - }, - body: Box::new(term.build_named()), - }, +pub trait WithTerm +where + Self: Sized, +{ + type Next; + + fn next(self, term: Term) -> Self::Next; + + fn with_constant_int(self, int: isize) -> Self::Next { + let term = Term::Constant(Constant::Integer(int)); + self.next(term) + } + + fn with_lambda(self) -> Self::Next { + let text = "i_0".to_string(); + let unique = Unique::new(0); + let parameter_name = Name { text, unique }; + let term = Term::Lambda { + parameter_name, + body: Box::new(Term::Constant(Constant::Integer(1))), + }; + self.next(term) + } +} + +impl WithTerm for Empty { + type Next = Builder; + fn next(self, term: Term) -> Self::Next { + Builder { + version: self.version, + term, } } } -impl Default for TermBuilder { - fn default() -> Self { - Self::Null - } -} - impl Builder { - pub fn with_version(&mut self, maj: usize, min: usize, patch: usize) -> &mut Self { - self.version = (maj, min, patch); - self - } - - pub fn with_constant_int(&mut self, int: isize) -> &mut Self { - self.term_builder = TermBuilder::Constant(Constant::Integer(int)); - self - } - - pub fn with_lambda(&mut self, int: isize) -> &mut Self { - let inner = TermBuilder::Constant(Constant::Integer(int)); - self.term_builder = TermBuilder::Lambda(Box::new(inner)); - self + pub fn new(maj: usize, min: usize, patch: usize) -> Empty { + Empty { + version: (maj, min, patch), + } } pub fn build_named(&self) -> Program { Program { version: self.version, - term: self.term_builder.build_named(), + term: self.term.clone(), } } } diff --git a/crates/program_builder/src/tests.rs b/crates/program_builder/src/tests.rs index a69b8370..ded6559c 100644 --- a/crates/program_builder/src/tests.rs +++ b/crates/program_builder/src/tests.rs @@ -1,4 +1,4 @@ -use crate::Builder; +use crate::{Builder, WithTerm}; use uplc::parser; #[test] @@ -8,10 +8,7 @@ fn build_named__with_const() { (con integer 11) )"; let expected = parser::program(code).unwrap(); - let actual = Builder::default() - .with_version(11, 22, 33) - .with_constant_int(11) - .build_named(); + let actual = Builder::new(11, 22, 33).with_constant_int(11).build_named(); assert_eq!(expected, actual); } @@ -22,10 +19,7 @@ fn build_named__with_different_const() { (con integer 22) )"; let expected = parser::program(code).unwrap(); - let actual = Builder::default() - .with_version(11, 22, 33) - .with_constant_int(22) - .build_named(); + let actual = Builder::new(11, 22, 33).with_constant_int(22).build_named(); assert_eq!(expected, actual); } @@ -36,10 +30,7 @@ fn build_named__with_const_different_version() { (con integer 11) )"; let expected = parser::program(code).unwrap(); - let actual = Builder::default() - .with_version(44, 55, 66) - .with_constant_int(11) - .build_named(); + let actual = Builder::new(44, 55, 66).with_constant_int(11).build_named(); assert_eq!(expected, actual); } @@ -50,9 +41,20 @@ fn build_named__with_lam() { (lam i_0 (con integer 1)) )"; let expected = parser::program(code).unwrap(); - let actual = Builder::default() - .with_version(1, 2, 3) - .with_lambda(1) - .build_named(); + let actual = Builder::new(1, 2, 3).with_lambda().build_named(); assert_eq!(expected, actual); } + +// #[test] +// fn build_named__with_nested_lam() { +// let code = r"(program +// 1.2.3 +// (lam i_0 (lam i_1 (con integer 1))) +// )"; +// let expected = parser::program(code).unwrap(); +// let actual = Builder::default() +// .with_version(1, 2, 3) +// .with_lambda(1) +// .build_named(); +// assert_eq!(expected, actual); +// }