chore: remove program_builder
This commit is contained in:
parent
d8cbcde61d
commit
298e8068ee
|
@ -2735,7 +2735,6 @@ dependencies = [
|
||||||
"peg",
|
"peg",
|
||||||
"pretty",
|
"pretty",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"proptest",
|
|
||||||
"secp256k1",
|
"secp256k1",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
|
@ -42,7 +42,6 @@ thiserror = "1.0.39"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
indoc = "2.0.1"
|
indoc = "2.0.1"
|
||||||
proptest = "1.1.0"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["dep:secp256k1"]
|
default = ["dep:secp256k1"]
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
use uplc::program_builder::{Builder, WithLambda, WithTerm, WithVar};
|
|
||||||
|
|
||||||
trait WithIdentity: WithTerm + WithLambda + WithVar {
|
|
||||||
fn with_identity(self, name_str: &str) -> Self::Next {
|
|
||||||
self.with_lambda(name_str).with_var(name_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: WithTerm> WithIdentity for T {}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let my_var = "some_var";
|
|
||||||
let program = Builder::start(1, 2, 3).with_identity(my_var).build_named();
|
|
||||||
println!("{program:#?}");
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
# Seeds for failure cases proptest has generated in the past. It is
|
|
||||||
# automatically read and these particular cases re-run before any
|
|
||||||
# novel cases are generated.
|
|
||||||
#
|
|
||||||
# It is recommended to check this file in to source control so that
|
|
||||||
# everyone who runs the test benefits from these saved cases.
|
|
||||||
cc a6cf04d97e92892f9c9342f5df205d81b7d686231ba69c9f36ba1166bd21d9a7 # shrinks to int = 0
|
|
||||||
cc ccfa96fb2d6133adc65044ad94e69d282fa104c68128782ecfa2badb8c79b12c # shrinks to some_string = "\""
|
|
|
@ -1,7 +0,0 @@
|
||||||
# Seeds for failure cases proptest has generated in the past. It is
|
|
||||||
# automatically read and these particular cases re-run before any
|
|
||||||
# novel cases are generated.
|
|
||||||
#
|
|
||||||
# It is recommended to check this file in to source control so that
|
|
||||||
# everyone who runs the test benefits from these saved cases.
|
|
||||||
cc db95a6ed96ee7cee987ba4b71bc6ffa9cf5abe295fa57a0eade27ed47335c1a3 # shrinks to maj = 0, min = 0, patch = 0
|
|
|
@ -7,7 +7,6 @@ pub mod machine;
|
||||||
pub mod optimize;
|
pub mod optimize;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
mod pretty;
|
mod pretty;
|
||||||
pub mod program_builder;
|
|
||||||
pub mod tx;
|
pub mod tx;
|
||||||
|
|
||||||
pub use pallas_codec::utils::KeyValuePairs;
|
pub use pallas_codec::utils::KeyValuePairs;
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
#![cfg_attr(test, allow(non_snake_case))]
|
|
||||||
|
|
||||||
use crate::ast::{Name, Program, Term, Unique};
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests;
|
|
||||||
|
|
||||||
mod apply;
|
|
||||||
mod builtin;
|
|
||||||
mod constant;
|
|
||||||
mod delay;
|
|
||||||
mod error;
|
|
||||||
mod force;
|
|
||||||
mod lambda;
|
|
||||||
mod var;
|
|
||||||
|
|
||||||
pub use apply::*;
|
|
||||||
pub use builtin::*;
|
|
||||||
pub use constant::*;
|
|
||||||
pub use delay::*;
|
|
||||||
pub use error::*;
|
|
||||||
pub use force::*;
|
|
||||||
pub use lambda::*;
|
|
||||||
pub use var::*;
|
|
||||||
|
|
||||||
pub struct Builder {
|
|
||||||
version: (usize, usize, usize),
|
|
||||||
term: Term<Name>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Context {
|
|
||||||
next_unique: isize,
|
|
||||||
names: HashMap<String, Unique>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Context {
|
|
||||||
pub fn new() -> Context {
|
|
||||||
Context {
|
|
||||||
next_unique: 0,
|
|
||||||
names: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_name(&mut self, name_str: &str) -> Name {
|
|
||||||
if let Some(unique) = self.names.get(name_str) {
|
|
||||||
Name {
|
|
||||||
text: name_str.to_string(),
|
|
||||||
unique: *unique,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let next_unique = self.next_unique;
|
|
||||||
self.next_unique = next_unique + 1;
|
|
||||||
let unique = Unique::new(next_unique);
|
|
||||||
self.names.insert(name_str.to_string(), unique);
|
|
||||||
Name {
|
|
||||||
text: name_str.to_string(),
|
|
||||||
unique,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Core {
|
|
||||||
version: (usize, usize, usize),
|
|
||||||
ctx: RefCell<Context>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait WithTerm
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
type Next;
|
|
||||||
|
|
||||||
fn next(self, term: Term<Name>) -> Self::Next;
|
|
||||||
fn get_name(&self, name_str: &str) -> Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WithTerm for Core {
|
|
||||||
type Next = Builder;
|
|
||||||
fn next(self, term: Term<Name>) -> Self::Next {
|
|
||||||
Builder {
|
|
||||||
version: self.version,
|
|
||||||
term,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self, name_str: &str) -> Name {
|
|
||||||
let mut ctx = self.ctx.borrow_mut();
|
|
||||||
ctx.get_name(name_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Builder {
|
|
||||||
/// Max: `9223372036854775807`
|
|
||||||
pub fn start(maj: usize, min: usize, patch: usize) -> Core {
|
|
||||||
Core {
|
|
||||||
version: (maj, min, patch),
|
|
||||||
ctx: RefCell::new(Context::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_named(&self) -> Program<Name> {
|
|
||||||
Program {
|
|
||||||
version: self.version,
|
|
||||||
term: self.term.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::ast::{Name, Term};
|
|
||||||
use crate::program_builder::WithTerm;
|
|
||||||
|
|
||||||
pub struct ApplyBuilderFunction<T> {
|
|
||||||
outer: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ApplyBuilderArgument<T> {
|
|
||||||
outer: T,
|
|
||||||
function: Term<Name>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: WithTerm> WithTerm for ApplyBuilderFunction<T> {
|
|
||||||
type Next = ApplyBuilderArgument<T>;
|
|
||||||
|
|
||||||
fn next(self, term: Term<Name>) -> Self::Next {
|
|
||||||
ApplyBuilderArgument {
|
|
||||||
outer: self.outer,
|
|
||||||
function: term,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self, name_str: &str) -> Name {
|
|
||||||
self.outer.get_name(name_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: WithTerm> WithTerm for ApplyBuilderArgument<T> {
|
|
||||||
type Next = T::Next;
|
|
||||||
|
|
||||||
fn next(self, term: Term<Name>) -> Self::Next {
|
|
||||||
let term = Term::Apply {
|
|
||||||
function: Rc::new(self.function),
|
|
||||||
argument: Rc::new(term),
|
|
||||||
};
|
|
||||||
self.outer.next(term)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self, name_str: &str) -> Name {
|
|
||||||
self.outer.get_name(name_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait WithApply: WithTerm {
|
|
||||||
fn with_apply(self) -> ApplyBuilderFunction<Self> {
|
|
||||||
ApplyBuilderFunction { outer: self }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a naive blanket impl. If needed, we can control which states of the builder can
|
|
||||||
// call this by implementing manually.
|
|
||||||
impl<T: WithTerm> WithApply for T {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::parser;
|
|
||||||
use crate::program_builder::{Builder, WithConstant, WithLambda, WithVar};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_apply() {
|
|
||||||
let my_var = "i_0";
|
|
||||||
let code = r"(program
|
|
||||||
1.2.3
|
|
||||||
[(lam i_0 i_0) (con integer 1)]
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(1, 2, 3)
|
|
||||||
.with_apply()
|
|
||||||
.with_lambda(my_var)
|
|
||||||
.with_var(my_var)
|
|
||||||
.with_int(1)
|
|
||||||
.build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_apply__with_lambda_as_arg() {
|
|
||||||
let my_var = "i_0";
|
|
||||||
let their_var = "i_1";
|
|
||||||
let code = r"(program
|
|
||||||
1.2.3
|
|
||||||
[(lam i_0 i_0) (lam i_1 (con integer 1))]
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(1, 2, 3)
|
|
||||||
.with_apply()
|
|
||||||
.with_lambda(my_var)
|
|
||||||
.with_var(my_var)
|
|
||||||
.with_lambda(their_var)
|
|
||||||
.with_int(1)
|
|
||||||
.build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
use crate::ast::Term;
|
|
||||||
use crate::builtins::DefaultFunction;
|
|
||||||
use crate::program_builder::WithTerm;
|
|
||||||
|
|
||||||
pub trait WithBuiltin: WithTerm {
|
|
||||||
// TODO: Add all the builtin variants explicitly
|
|
||||||
fn with_builtin(self, builtin: DefaultFunction) -> Self::Next {
|
|
||||||
let term = Term::Builtin(builtin);
|
|
||||||
self.next(term)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: WithTerm> WithBuiltin for T {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::parser;
|
|
||||||
use crate::program_builder::Builder;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named() {
|
|
||||||
let code = r"(program
|
|
||||||
11.22.33
|
|
||||||
(builtin addInteger)
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(11, 22, 33)
|
|
||||||
.with_builtin(DefaultFunction::AddInteger)
|
|
||||||
.build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,135 +0,0 @@
|
||||||
use crate::ast::{Constant, Term};
|
|
||||||
use crate::program_builder::WithTerm;
|
|
||||||
|
|
||||||
pub trait WithConstant: WithTerm {
|
|
||||||
fn with_int(self, int: i128) -> Self::Next {
|
|
||||||
let term = Term::Constant(Constant::Integer(int.into()).into());
|
|
||||||
self.next(term)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_byte_string(self, bytes: Vec<u8>) -> Self::Next {
|
|
||||||
let term = Term::Constant(Constant::ByteString(bytes).into());
|
|
||||||
self.next(term)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_string(self, string: String) -> Self::Next {
|
|
||||||
let term = Term::Constant(Constant::String(string).into());
|
|
||||||
self.next(term)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_unit(self) -> Self::Next {
|
|
||||||
let term = Term::Constant(Constant::Unit.into());
|
|
||||||
self.next(term)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_bool(self, bool: bool) -> Self::Next {
|
|
||||||
let term = Term::Constant(Constant::Bool(bool).into());
|
|
||||||
self.next(term)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a naive blanket impl. If needed, we can control which states of the builder can
|
|
||||||
// call this by implementing manually.
|
|
||||||
impl<T: WithTerm> WithConstant for T {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::parser;
|
|
||||||
use crate::program_builder::Builder;
|
|
||||||
use proptest::prelude::*;
|
|
||||||
|
|
||||||
proptest! {
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_const(
|
|
||||||
int: i128
|
|
||||||
) {
|
|
||||||
let code = format!(r"(program
|
|
||||||
11.22.33
|
|
||||||
(con integer {int})
|
|
||||||
)");
|
|
||||||
let expected = parser::program(&code).unwrap();
|
|
||||||
let actual = Builder::start(11, 22, 33).with_int(int).build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proptest! {
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_bytestring(
|
|
||||||
bytes: Vec<u8>
|
|
||||||
) {
|
|
||||||
let bstring = hex::encode(&bytes);
|
|
||||||
let code = format!(r"(program
|
|
||||||
11.22.33
|
|
||||||
(con bytestring #{bstring})
|
|
||||||
)");
|
|
||||||
let expected = parser::program(&code).unwrap();
|
|
||||||
let actual = Builder::start(11, 22, 33)
|
|
||||||
.with_byte_string(bytes)
|
|
||||||
.build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prop_compose! {
|
|
||||||
fn safe_string()(
|
|
||||||
some_string: String
|
|
||||||
) -> String {
|
|
||||||
some_string.chars().filter(|a| *a != '\"').collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proptest! {
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_string(
|
|
||||||
some_string in safe_string()
|
|
||||||
) {
|
|
||||||
let code = format!(
|
|
||||||
r#"(program
|
|
||||||
11.22.33
|
|
||||||
(con string "{}")
|
|
||||||
)"#,
|
|
||||||
&some_string
|
|
||||||
);
|
|
||||||
let expected = parser::program(&code).unwrap();
|
|
||||||
let actual = Builder::start(11, 22, 33)
|
|
||||||
.with_string(some_string)
|
|
||||||
.build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_unit() {
|
|
||||||
let code = r"(program
|
|
||||||
11.22.33
|
|
||||||
(con unit ())
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(11, 22, 33).with_unit().build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_true() {
|
|
||||||
let code = r"(program
|
|
||||||
11.22.33
|
|
||||||
(con bool True)
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(11, 22, 33).with_bool(true).build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_false() {
|
|
||||||
let code = r"(program
|
|
||||||
11.22.33
|
|
||||||
(con bool False)
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(11, 22, 33).with_bool(false).build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::ast::{Name, Term};
|
|
||||||
use crate::program_builder::WithTerm;
|
|
||||||
|
|
||||||
pub struct DelayBuilder<T> {
|
|
||||||
outer: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: WithTerm> WithTerm for DelayBuilder<T> {
|
|
||||||
type Next = T::Next;
|
|
||||||
|
|
||||||
fn next(self, term: Term<Name>) -> Self::Next {
|
|
||||||
let term = Term::Delay(Rc::new(term));
|
|
||||||
self.outer.next(term)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self, name_str: &str) -> Name {
|
|
||||||
self.outer.get_name(name_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait WithDelay: WithTerm {
|
|
||||||
fn with_delay(self) -> DelayBuilder<Self> {
|
|
||||||
DelayBuilder { outer: self }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a naive blanket impl. If needed, we can control which states of the builder can
|
|
||||||
// call this by implementing manually.
|
|
||||||
impl<T: WithTerm> WithDelay for T {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::parser;
|
|
||||||
use crate::program_builder::{Builder, WithConstant, WithLambda};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_delay() {
|
|
||||||
let code = r"(program
|
|
||||||
1.2.3
|
|
||||||
(delay (con integer 1))
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(1, 2, 3)
|
|
||||||
.with_delay()
|
|
||||||
.with_int(1)
|
|
||||||
.build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_delay__with_lambda() {
|
|
||||||
let code = r"(program
|
|
||||||
1.2.3
|
|
||||||
(delay (lam i_0 (con integer 1)))
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(1, 2, 3)
|
|
||||||
.with_delay()
|
|
||||||
.with_lambda("i_0")
|
|
||||||
.with_int(1)
|
|
||||||
.build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
use crate::ast::Term;
|
|
||||||
use crate::program_builder::WithTerm;
|
|
||||||
|
|
||||||
pub trait WithError: WithTerm {
|
|
||||||
fn with_error(self) -> Self::Next {
|
|
||||||
let term = Term::Error;
|
|
||||||
self.next(term)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: WithTerm> WithError for T {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::parser;
|
|
||||||
use crate::program_builder::Builder;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_error() {
|
|
||||||
let code = r"(program
|
|
||||||
11.22.33
|
|
||||||
(error)
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(11, 22, 33).with_error().build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::ast::{Name, Term};
|
|
||||||
use crate::program_builder::WithTerm;
|
|
||||||
|
|
||||||
pub struct ForceBuilder<T> {
|
|
||||||
outer: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: WithTerm> WithTerm for ForceBuilder<T> {
|
|
||||||
type Next = T::Next;
|
|
||||||
|
|
||||||
fn next(self, term: Term<Name>) -> Self::Next {
|
|
||||||
let term = Term::Force(Rc::new(term));
|
|
||||||
self.outer.next(term)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self, name_str: &str) -> Name {
|
|
||||||
self.outer.get_name(name_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait WithForce: WithTerm {
|
|
||||||
fn with_force(self) -> ForceBuilder<Self> {
|
|
||||||
ForceBuilder { outer: self }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a naive blanket impl. If needed, we can control which states of the builder can
|
|
||||||
// call this by implementing manually.
|
|
||||||
impl<T: WithTerm> WithForce for T {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::parser;
|
|
||||||
use crate::program_builder::{Builder, WithConstant, WithLambda};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_force() {
|
|
||||||
let code = r"(program
|
|
||||||
1.2.3
|
|
||||||
(force (lam i_0 (con integer 1)))
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(1, 2, 3)
|
|
||||||
.with_force()
|
|
||||||
.with_lambda("i_0")
|
|
||||||
.with_int(1)
|
|
||||||
.build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::ast::{Name, Term};
|
|
||||||
use crate::program_builder::WithTerm;
|
|
||||||
|
|
||||||
pub struct LambdaBuilder<T> {
|
|
||||||
outer: T,
|
|
||||||
parameter_name: Name,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: WithTerm> WithTerm for LambdaBuilder<T> {
|
|
||||||
type Next = T::Next;
|
|
||||||
|
|
||||||
fn next(self, term: Term<Name>) -> Self::Next {
|
|
||||||
let term = Term::Lambda {
|
|
||||||
parameter_name: self.parameter_name.into(),
|
|
||||||
body: Rc::new(term),
|
|
||||||
};
|
|
||||||
self.outer.next(term)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self, name_str: &str) -> Name {
|
|
||||||
self.outer.get_name(name_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait WithLambda: WithTerm {
|
|
||||||
fn with_lambda(self, name_str: &str) -> LambdaBuilder<Self> {
|
|
||||||
let parameter_name = self.get_name(name_str);
|
|
||||||
LambdaBuilder {
|
|
||||||
outer: self,
|
|
||||||
parameter_name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a naive blanket impl. If needed, we can control which states of the builder can
|
|
||||||
// call this by implementing manually.
|
|
||||||
impl<T: WithTerm> WithLambda for T {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::parser;
|
|
||||||
use crate::program_builder::constant::WithConstant;
|
|
||||||
use crate::program_builder::Builder;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_lam() {
|
|
||||||
let code = r"(program
|
|
||||||
1.2.3
|
|
||||||
(lam i_0 (con integer 1))
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(1, 2, 3)
|
|
||||||
.with_lambda("i_0")
|
|
||||||
.with_int(1)
|
|
||||||
.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::start(1, 2, 3)
|
|
||||||
.with_lambda("i_0")
|
|
||||||
.with_lambda("i_1")
|
|
||||||
.with_int(1)
|
|
||||||
.build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
use super::*;
|
|
||||||
use crate::parser;
|
|
||||||
use crate::program_builder::constant::WithConstant;
|
|
||||||
use proptest::prelude::*;
|
|
||||||
|
|
||||||
prop_compose! {
|
|
||||||
fn arb_version()(
|
|
||||||
maj: isize,
|
|
||||||
min: isize,
|
|
||||||
patch: isize,
|
|
||||||
) -> (usize, usize, usize){
|
|
||||||
let maj = maj.unsigned_abs();
|
|
||||||
let min = min.unsigned_abs();
|
|
||||||
let patch = patch.unsigned_abs();
|
|
||||||
|
|
||||||
(maj, min, patch)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proptest! {
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_version(
|
|
||||||
(maj, min, patch) in arb_version(),
|
|
||||||
) {
|
|
||||||
let code = format!(r"(program
|
|
||||||
{maj}.{min}.{patch}
|
|
||||||
(con integer 11)
|
|
||||||
)");
|
|
||||||
let expected = parser::program(&code).unwrap();
|
|
||||||
let actual = Builder::start(maj, min, patch).with_int(11).build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
use crate::ast::Term;
|
|
||||||
use crate::program_builder::WithTerm;
|
|
||||||
|
|
||||||
pub trait WithVar: WithTerm {
|
|
||||||
fn with_var(self, name_str: &str) -> Self::Next {
|
|
||||||
let name = self.get_name(name_str);
|
|
||||||
let term = Term::Var(name.into());
|
|
||||||
self.next(term)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a naive blanket impl. If needed, we can control which states of the builder can
|
|
||||||
// call this by implementing manually.
|
|
||||||
impl<T: WithTerm> WithVar for T {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::parser;
|
|
||||||
use crate::program_builder::{Builder, WithLambda};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build_named__with_var() {
|
|
||||||
let var_name = "i_0";
|
|
||||||
let code = r"(program
|
|
||||||
1.2.3
|
|
||||||
(lam i_0 i_0)
|
|
||||||
)";
|
|
||||||
let expected = parser::program(code).unwrap();
|
|
||||||
let actual = Builder::start(1, 2, 3)
|
|
||||||
.with_lambda(var_name)
|
|
||||||
.with_var(var_name)
|
|
||||||
.build_named();
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue