diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index 4eb9472b..6f640034 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -946,9 +946,7 @@ pub fn softcast_data_to_type_otherwise( let then_delayed = |v| then.lambda(name).apply(v).delay(); value.as_var("__val", |val| match uplc_type { - None => val - .choose_data_constr(then_delayed, &otherwise_delayed) - .force(), + None => Term::choose_data_constr(val, then_delayed, &otherwise_delayed).force(), Some(UplcType::Data) => just_then, @@ -956,63 +954,63 @@ pub fn softcast_data_to_type_otherwise( unreachable!("attempted to cast Data into Bls12_381MlResult ?!") } - Some(UplcType::Integer) => val - .choose_data_integer(then_delayed, &otherwise_delayed) - .force(), + Some(UplcType::Integer) => { + Term::choose_data_integer(val, then_delayed, &otherwise_delayed).force() + } - Some(UplcType::ByteString) => val - .choose_data_bytearray(then_delayed, &otherwise_delayed) - .force(), + Some(UplcType::ByteString) => { + Term::choose_data_bytearray(val, then_delayed, &otherwise_delayed).force() + } - Some(UplcType::String) => val - .choose_data_bytearray( - |bytes| then_delayed(Term::decode_utf8().apply(bytes)), - &otherwise_delayed, - ) - .force(), + Some(UplcType::String) => Term::choose_data_bytearray( + val, + |bytes| then_delayed(Term::decode_utf8().apply(bytes)), + &otherwise_delayed, + ) + .force(), - Some(UplcType::List(_)) if field_type.is_map() => val - .choose_data_map(then_delayed, &otherwise_delayed) - .force(), + Some(UplcType::List(_)) if field_type.is_map() => { + Term::choose_data_map(val, then_delayed, &otherwise_delayed).force() + } - Some(UplcType::List(_)) => val - .choose_data_list(then_delayed, &otherwise_delayed) - .force(), + Some(UplcType::List(_)) => { + Term::choose_data_list(val, then_delayed, &otherwise_delayed).force() + } - Some(UplcType::Bls12_381G1Element) => val - .choose_data_bytearray( - |bytes| then_delayed(Term::bls12_381_g1_uncompress().apply(bytes)), - &otherwise_delayed, - ) - .force(), + Some(UplcType::Bls12_381G1Element) => Term::choose_data_bytearray( + val, + |bytes| then_delayed(Term::bls12_381_g1_uncompress().apply(bytes)), + &otherwise_delayed, + ) + .force(), - Some(UplcType::Bls12_381G2Element) => val - .choose_data_bytearray( - |bytes| then_delayed(Term::bls12_381_g2_uncompress().apply(bytes)), - &otherwise_delayed, - ) - .force(), + Some(UplcType::Bls12_381G2Element) => Term::choose_data_bytearray( + val, + |bytes| then_delayed(Term::bls12_381_g2_uncompress().apply(bytes)), + &otherwise_delayed, + ) + .force(), - Some(UplcType::Pair(_, _)) => val - .choose_data_list( - |list| list.unwrap_pair_or(then_delayed, &otherwise_delayed), - &otherwise_delayed, - ) - .force(), + Some(UplcType::Pair(_, _)) => Term::choose_data_list( + val, + |list| list.unwrap_pair_or(then_delayed, &otherwise_delayed), + &otherwise_delayed, + ) + .force(), - Some(UplcType::Bool) => val - .choose_data_constr( - |constr| constr.unwrap_bool_or(then_delayed, &otherwise_delayed), - &otherwise_delayed, - ) - .force(), + Some(UplcType::Bool) => Term::choose_data_constr( + val, + |constr| constr.unwrap_bool_or(then_delayed, &otherwise_delayed), + &otherwise_delayed, + ) + .force(), - Some(UplcType::Unit) => val - .choose_data_constr( - |constr| constr.unwrap_void_or(then_delayed, &otherwise_delayed), - &otherwise_delayed, - ) - .force(), + Some(UplcType::Unit) => Term::choose_data_constr( + val, + |constr| constr.unwrap_void_or(then_delayed, &otherwise_delayed), + &otherwise_delayed, + ) + .force(), }) } diff --git a/crates/uplc/src/builder.rs b/crates/uplc/src/builder.rs index 787568cc..0147a294 100644 --- a/crates/uplc/src/builder.rs +++ b/crates/uplc/src/builder.rs @@ -3,6 +3,7 @@ use crate::{ builtins::DefaultFunction, }; use pallas_primitives::alonzo::PlutusData; +use std::rc::Rc; pub const CONSTR_FIELDS_EXPOSER: &str = "__constr_fields_exposer"; pub const CONSTR_INDEX_EXPOSER: &str = "__constr_index_exposer"; @@ -499,51 +500,53 @@ impl Term { /// ``` pub fn as_var(self, var_name: &str, callback: F) -> Term where - F: FnOnce(Term) -> Term, + F: FnOnce(Rc) -> Term, { - callback(Term::var(var_name)).lambda(var_name).apply(self) + callback(Name::text(var_name).into()) + .lambda(var_name) + .apply(self) } /// Continue a computation provided that the current term is a Data-wrapped integer. /// The 'callback' receives an integer constant Term as argument. - pub fn choose_data_integer(self, callback: F, otherwise: &Term) -> Self + pub fn choose_data_integer(var: Rc, callback: F, otherwise: &Term) -> Self where F: FnOnce(Term) -> Term, { - self.clone().choose_data( + Term::Var(var.clone()).choose_data( otherwise.clone(), otherwise.clone(), otherwise.clone(), - callback(Term::un_i_data().apply(self)), + callback(Term::un_i_data().apply(Term::Var(var))), otherwise.clone(), ) } /// Continue a computation provided that the current term is a Data-wrapped /// bytearray. The 'callback' receives a bytearray constant Term as argument. - pub fn choose_data_bytearray(self, callback: F, otherwise: &Term) -> Self + pub fn choose_data_bytearray(var: Rc, callback: F, otherwise: &Term) -> Self where F: FnOnce(Term) -> Term, { - self.clone().choose_data( + Term::Var(var.clone()).choose_data( otherwise.clone(), otherwise.clone(), otherwise.clone(), otherwise.clone(), - callback(Term::un_b_data().apply(self)), + callback(Term::un_b_data().apply(Term::Var(var))), ) } /// Continue a computation provided that the current term is a Data-wrapped /// list. The 'callback' receives a ProtoList Term as argument. - pub fn choose_data_list(self, callback: F, otherwise: &Term) -> Self + pub fn choose_data_list(var: Rc, callback: F, otherwise: &Term) -> Self where F: FnOnce(Term) -> Term, { - self.clone().choose_data( + Term::Var(var.clone()).choose_data( otherwise.clone(), otherwise.clone(), - callback(Term::unlist_data().apply(self)), + callback(Term::unlist_data().apply(Term::Var(var))), otherwise.clone(), otherwise.clone(), ) @@ -551,13 +554,13 @@ impl Term { /// Continue a computation provided that the current term is a Data-wrapped /// list. The 'callback' receives a ProtoMap Term as argument. - pub fn choose_data_map(self, callback: F, otherwise: &Term) -> Self + pub fn choose_data_map(var: Rc, callback: F, otherwise: &Term) -> Self where F: FnOnce(Term) -> Term, { - self.clone().choose_data( + Term::Var(var.clone()).choose_data( otherwise.clone(), - callback(Term::unmap_data().apply(self)), + callback(Term::unmap_data().apply(Term::Var(var))), otherwise.clone(), otherwise.clone(), otherwise.clone(), @@ -566,12 +569,12 @@ impl Term { /// Continue a computation provided that the current term is a Data-wrapped /// constr. The 'callback' receives a Data as argument. - pub fn choose_data_constr(self, callback: F, otherwise: &Term) -> Self + pub fn choose_data_constr(var: Rc, callback: F, otherwise: &Term) -> Self where F: FnOnce(Term) -> Term, { - self.clone().choose_data( - callback(self), + Term::Var(var.clone()).choose_data( + callback(Term::Var(var)), otherwise.clone(), otherwise.clone(), otherwise.clone(), @@ -591,21 +594,21 @@ impl Term { Term::unconstr_data() .apply(self) .as_var("__pair__", |pair| { - Term::snd_pair().apply(pair.clone()).choose_list( + Term::snd_pair().apply(Term::Var(pair.clone())).choose_list( Term::less_than_equals_integer() .apply(Term::integer(2.into())) - .apply(Term::fst_pair().apply(pair.clone())) + .apply(Term::fst_pair().apply(Term::Var(pair.clone()))) .if_then_else( otherwise.clone(), Term::less_than_integer() - .apply(Term::fst_pair().apply(pair.clone())) + .apply(Term::fst_pair().apply(Term::Var(pair.clone()))) .apply(Term::integer(0.into())) .if_then_else( otherwise.clone(), callback( Term::equals_integer() .apply(Term::integer(1.into())) - .apply(Term::fst_pair().apply(pair)), + .apply(Term::fst_pair().apply(Term::Var(pair))), ), ), ), @@ -647,12 +650,14 @@ impl Term { F: FnOnce(Term) -> Term, { self.as_var("__list_data", |list| { - let left = Term::head_list().apply(list.clone()); - list.unwrap_tail_or( + let left = Term::head_list().apply(Term::Var(list.clone())); + Term::unwrap_tail_or( + list, |tail| { tail.as_var("__tail", |tail| { - let right = Term::head_list().apply(tail.clone()); - tail.unwrap_tail_or( + let right = Term::head_list().apply(Term::Var(tail.clone())); + Term::unwrap_tail_or( + tail, |leftovers| { leftovers .choose_list( @@ -674,12 +679,14 @@ impl Term { } /// Continue with the tail of a list, if any; or fallback 'otherwise'. - pub fn unwrap_tail_or(self, callback: F, otherwise: &Term) -> Term + pub fn unwrap_tail_or(var: Rc, callback: F, otherwise: &Term) -> Term where F: FnOnce(Term) -> Term, { - self.clone() - .choose_list(otherwise.clone(), callback(Term::tail_list().apply(self))) + Term::Var(var.clone()).choose_list( + otherwise.clone(), + callback(Term::tail_list().apply(Term::Var(var))), + ) } } @@ -749,11 +756,9 @@ mod tests { #[test] fn unwrap_tail_or_0_elems() { - let result = quick_eval( - Term::list_values(vec![]) - .unwrap_tail_or(|p| p.delay(), &Term::Error.delay()) - .force(), - ); + let result = quick_eval(Term::list_values(vec![]).as_var("__tail", |tail| { + Term::unwrap_tail_or(tail, |p| p.delay(), &Term::Error.delay()).force() + })); assert_eq!(result, Err(Error::EvaluationFailure)); } @@ -762,8 +767,9 @@ mod tests { fn unwrap_tail_or_1_elem() { let result = quick_eval( Term::list_values(vec![Constant::Data(Data::integer(1.into()))]) - .unwrap_tail_or(|p| p.delay(), &Term::Error.delay()) - .force(), + .as_var("__tail", |tail| { + Term::unwrap_tail_or(tail, |p| p.delay(), &Term::Error.delay()).force() + }), ); assert_eq!(result, Ok(Term::list_values(vec![])),); @@ -776,8 +782,9 @@ mod tests { Constant::Data(Data::integer(1.into())), Constant::Data(Data::integer(2.into())), ]) - .unwrap_tail_or(|p| p.delay(), &Term::Error.delay()) - .force(), + .as_var("__tail", |tail| { + Term::unwrap_tail_or(tail, |p| p.delay(), &Term::Error.delay()).force() + }), ); assert_eq!(