Refactor unknown_data_to_type, break down into smaller functions.
This commit is contained in:
parent
c3a61706b5
commit
9610237616
|
@ -941,203 +941,79 @@ pub fn softcast_data_to_type_otherwise(
|
||||||
) -> Term<Name> {
|
) -> Term<Name> {
|
||||||
let uplc_type = field_type.get_uplc_type();
|
let uplc_type = field_type.get_uplc_type();
|
||||||
|
|
||||||
let then = then.lambda(name);
|
let just_then = then.clone();
|
||||||
|
|
||||||
match uplc_type {
|
let then_delayed = |v| then.lambda(name).apply(v).delay();
|
||||||
Some(UplcType::Integer) => Term::var("__val")
|
|
||||||
.choose_data(
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
then.apply(Term::un_i_data().apply(Term::var("__val")))
|
|
||||||
.delay(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
|
||||||
Some(UplcType::ByteString) => Term::var("__val")
|
|
||||||
.choose_data(
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
then.apply(Term::un_b_data().apply(Term::var("__val")))
|
|
||||||
.delay(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
|
||||||
Some(UplcType::String) => Term::var("__val")
|
|
||||||
.choose_data(
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
then.apply(Term::decode_utf8().apply(Term::un_b_data().apply(Term::var("__val"))))
|
|
||||||
.delay(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
|
||||||
|
|
||||||
Some(UplcType::List(_)) if field_type.is_map() => Term::var("__val")
|
value.as_var("__val", |val| match uplc_type {
|
||||||
.choose_data(
|
None => val
|
||||||
otherwise_delayed.clone(),
|
.choose_data_constr(then_delayed, &otherwise_delayed)
|
||||||
then.apply(Term::unmap_data().apply(Term::var("__val")))
|
.force(),
|
||||||
.delay(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
|
||||||
Some(UplcType::List(_)) => Term::var("__val")
|
|
||||||
.choose_data(
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
then.apply(Term::unlist_data().apply(Term::var("__val")))
|
|
||||||
.delay(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
|
||||||
|
|
||||||
Some(UplcType::Bls12_381G1Element) => Term::var("__val")
|
Some(UplcType::Data) => just_then,
|
||||||
.choose_data(
|
|
||||||
otherwise_delayed.clone(),
|
Some(UplcType::Bls12_381MlResult) => {
|
||||||
otherwise_delayed.clone(),
|
unreachable!("attempted to cast Data into Bls12_381MlResult ?!")
|
||||||
otherwise_delayed.clone(),
|
}
|
||||||
otherwise_delayed.clone(),
|
|
||||||
then.apply(
|
Some(UplcType::Integer) => val
|
||||||
Term::bls12_381_g1_uncompress()
|
.choose_data_integer(then_delayed, &otherwise_delayed)
|
||||||
.apply(Term::un_b_data().apply(Term::var("__val"))),
|
.force(),
|
||||||
)
|
|
||||||
.delay(),
|
Some(UplcType::ByteString) => val
|
||||||
)
|
.choose_data_bytearray(then_delayed, &otherwise_delayed)
|
||||||
.force()
|
.force(),
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
Some(UplcType::String) => val
|
||||||
Some(UplcType::Bls12_381G2Element) => Term::var("__val")
|
.choose_data_bytearray(
|
||||||
.choose_data(
|
|bytes| then_delayed(Term::decode_utf8().apply(bytes)),
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
then.apply(
|
|
||||||
Term::bls12_381_g2_uncompress()
|
|
||||||
.apply(Term::un_b_data().apply(Term::var("__val"))),
|
|
||||||
)
|
|
||||||
.delay(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
|
||||||
Some(UplcType::Bls12_381MlResult) => panic!("ML Result not supported"),
|
|
||||||
Some(UplcType::Pair(_, _)) => Term::var("__val")
|
|
||||||
.choose_data(
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
Term::var("__list_data")
|
|
||||||
.choose_list(
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
Term::var("__tail")
|
|
||||||
.choose_list(
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
Term::tail_list()
|
|
||||||
.apply(Term::var("__tail"))
|
|
||||||
.choose_list(
|
|
||||||
then.apply(
|
|
||||||
Term::mk_pair_data()
|
|
||||||
.apply(
|
|
||||||
Term::head_list()
|
|
||||||
.apply(Term::var("__list_data")),
|
|
||||||
)
|
|
||||||
.apply(
|
|
||||||
Term::head_list().apply(Term::var("__tail")),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.delay(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.delay(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__tail")
|
|
||||||
.apply(Term::tail_list().apply(Term::var("__list_data")))
|
|
||||||
.delay(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__list_data")
|
|
||||||
.apply(Term::unlist_data().apply(Term::var("__val")))
|
|
||||||
.delay(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
|
||||||
Some(UplcType::Bool) => Term::var("__val")
|
|
||||||
.choose_data(
|
|
||||||
Term::unwrap_bool_or(
|
|
||||||
Term::var("__val"),
|
|
||||||
|result| then.apply(result),
|
|
||||||
&otherwise_delayed,
|
&otherwise_delayed,
|
||||||
)
|
)
|
||||||
.delay(),
|
.force(),
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
|
||||||
Some(UplcType::Unit) => Term::var("__val")
|
|
||||||
.choose_data(
|
|
||||||
Term::equals_integer()
|
|
||||||
.apply(Term::integer(0.into()))
|
|
||||||
.apply(Term::fst_pair().apply(Term::unconstr_data().apply(Term::var("__val"))))
|
|
||||||
.if_then_else(
|
|
||||||
Term::snd_pair()
|
|
||||||
.apply(Term::unconstr_data().apply(Term::var("__val")))
|
|
||||||
.choose_list(
|
|
||||||
then.apply(Term::unit()).delay(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.delay(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.delay(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
|
||||||
)
|
|
||||||
.force()
|
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
|
||||||
|
|
||||||
Some(UplcType::Data) => then.apply(value),
|
Some(UplcType::List(_)) if field_type.is_map() => val
|
||||||
// constr type
|
.choose_data_map(then_delayed, &otherwise_delayed)
|
||||||
None => Term::var("__val")
|
.force(),
|
||||||
.choose_data(
|
|
||||||
then.apply(Term::var("__val")).delay(),
|
Some(UplcType::List(_)) => val
|
||||||
otherwise_delayed.clone(),
|
.choose_data_list(then_delayed, &otherwise_delayed)
|
||||||
otherwise_delayed.clone(),
|
.force(),
|
||||||
otherwise_delayed.clone(),
|
|
||||||
otherwise_delayed.clone(),
|
Some(UplcType::Bls12_381G1Element) => val
|
||||||
|
.choose_data_bytearray(
|
||||||
|
|bytes| then_delayed(Term::bls12_381_g1_uncompress().apply(bytes)),
|
||||||
|
&otherwise_delayed,
|
||||||
)
|
)
|
||||||
.force()
|
.force(),
|
||||||
.lambda("__val")
|
|
||||||
.apply(value),
|
Some(UplcType::Bls12_381G2Element) => val
|
||||||
}
|
.choose_data_bytearray(
|
||||||
|
|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::Bool) => val
|
||||||
|
.choose_data_constr(
|
||||||
|
|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(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_constants_to_data(constants: Vec<Rc<UplcConstant>>) -> Vec<UplcConstant> {
|
pub fn convert_constants_to_data(constants: Vec<Rc<UplcConstant>>) -> Vec<UplcConstant> {
|
||||||
|
|
|
@ -485,34 +485,190 @@ impl Term<Name> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Introduce a let-binding for a given term. The callback receives a Term::Var
|
||||||
|
/// whose name matches the given 'var_name'. Handy to re-use a same var across
|
||||||
|
/// multiple lambda expressions.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// value.as_var("__val", |val| {
|
||||||
|
/// val.do_something()
|
||||||
|
/// .do_another_thing()
|
||||||
|
/// })
|
||||||
|
/// ```
|
||||||
|
pub fn as_var<F>(self, var_name: &str, callback: F) -> Term<Name>
|
||||||
|
where
|
||||||
|
F: FnOnce(Term<Name>) -> Term<Name>,
|
||||||
|
{
|
||||||
|
callback(Term::var(var_name)).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<F>(self, callback: F, otherwise: &Term<Name>) -> Self
|
||||||
|
where
|
||||||
|
F: FnOnce(Term<Name>) -> Term<Name>,
|
||||||
|
{
|
||||||
|
self.clone().choose_data(
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
callback(Term::un_i_data().apply(self)),
|
||||||
|
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<F>(self, callback: F, otherwise: &Term<Name>) -> Self
|
||||||
|
where
|
||||||
|
F: FnOnce(Term<Name>) -> Term<Name>,
|
||||||
|
{
|
||||||
|
self.clone().choose_data(
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
callback(Term::un_b_data().apply(self)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<F>(self, callback: F, otherwise: &Term<Name>) -> Self
|
||||||
|
where
|
||||||
|
F: FnOnce(Term<Name>) -> Term<Name>,
|
||||||
|
{
|
||||||
|
self.clone().choose_data(
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
callback(Term::unlist_data().apply(self)),
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<F>(self, callback: F, otherwise: &Term<Name>) -> Self
|
||||||
|
where
|
||||||
|
F: FnOnce(Term<Name>) -> Term<Name>,
|
||||||
|
{
|
||||||
|
self.clone().choose_data(
|
||||||
|
otherwise.clone(),
|
||||||
|
callback(Term::unmap_data().apply(self)),
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<F>(self, callback: F, otherwise: &Term<Name>) -> Self
|
||||||
|
where
|
||||||
|
F: FnOnce(Term<Name>) -> Term<Name>,
|
||||||
|
{
|
||||||
|
self.clone().choose_data(
|
||||||
|
callback(self),
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
otherwise.clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert an arbitrary 'term' into a bool term and pass it into a 'callback'.
|
/// Convert an arbitrary 'term' into a bool term and pass it into a 'callback'.
|
||||||
/// Continue the execution 'otherwise' with a different branch.
|
/// Continue the execution 'otherwise' with a different branch.
|
||||||
///
|
///
|
||||||
/// Note that the 'otherwise' term as well as the callback's result are expected
|
/// Note that the 'otherwise' term as well as the callback's result are expected
|
||||||
/// to be delayed terms.
|
/// to be delayed terms.
|
||||||
pub fn unwrap_bool_or<F>(term: Term<Name>, callback: F, otherwise: &Term<Name>) -> Term<Name>
|
pub fn unwrap_bool_or<F>(self, callback: F, otherwise: &Term<Name>) -> Term<Name>
|
||||||
where
|
where
|
||||||
F: FnOnce(Term<Name>) -> Term<Name>,
|
F: FnOnce(Term<Name>) -> Term<Name>,
|
||||||
{
|
{
|
||||||
|
Term::unconstr_data()
|
||||||
|
.apply(self)
|
||||||
|
.as_var("__pair__", |pair| {
|
||||||
Term::snd_pair()
|
Term::snd_pair()
|
||||||
.apply(Term::var("__pair__"))
|
.apply(pair.clone())
|
||||||
.choose_list(
|
.choose_list(
|
||||||
Term::less_than_equals_integer()
|
Term::less_than_equals_integer()
|
||||||
.apply(Term::integer(2.into()))
|
.apply(Term::integer(2.into()))
|
||||||
.apply(Term::fst_pair().apply(Term::var("__pair__")))
|
.apply(Term::fst_pair().apply(pair.clone()))
|
||||||
.delayed_if_then_else(
|
.if_then_else(
|
||||||
otherwise.clone(),
|
otherwise.clone(),
|
||||||
callback(
|
callback(
|
||||||
Term::equals_integer()
|
Term::equals_integer()
|
||||||
.apply(Term::fst_pair().apply(Term::var("__pair__")))
|
.apply(Term::fst_pair().apply(pair))
|
||||||
.apply(Term::integer(1.into())),
|
.apply(Term::integer(1.into())),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
otherwise.clone(),
|
||||||
)
|
)
|
||||||
|
.force()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert an arbitrary 'term' into a unit term and pass it into a 'callback'.
|
||||||
|
/// Continue the execution 'otherwise' with a different branch.
|
||||||
|
///
|
||||||
|
/// Note that the 'otherwise' term as well as the callback's result are expected
|
||||||
|
/// to be delayed terms.
|
||||||
|
pub fn unwrap_void_or<F>(self, callback: F, otherwise: &Term<Name>) -> Term<Name>
|
||||||
|
where
|
||||||
|
F: FnOnce(Term<Name>) -> Term<Name>,
|
||||||
|
{
|
||||||
|
Term::equals_integer()
|
||||||
|
.apply(Term::integer(0.into()))
|
||||||
|
.apply(Term::fst_pair().apply(Term::unconstr_data().apply(self.clone())))
|
||||||
|
.if_then_else(
|
||||||
|
Term::snd_pair()
|
||||||
|
.apply(Term::unconstr_data().apply(self))
|
||||||
|
.choose_list(callback(Term::unit()), otherwise.clone())
|
||||||
|
.force()
|
||||||
.delay(),
|
.delay(),
|
||||||
otherwise.clone(),
|
otherwise.clone(),
|
||||||
)
|
)
|
||||||
.force()
|
.force()
|
||||||
.lambda("__pair__")
|
}
|
||||||
.apply(Term::unconstr_data().apply(term))
|
|
||||||
|
/// Convert an arbitrary 'term' into a pair and pass it into a 'callback'.
|
||||||
|
/// Continue the execution 'otherwise' with a different branch.
|
||||||
|
///
|
||||||
|
/// Note that the 'otherwise' term as well as the callback's result are expected
|
||||||
|
/// to be delayed terms.
|
||||||
|
pub fn unwrap_pair_or<F>(self, callback: F, otherwise: &Term<Name>) -> Term<Name>
|
||||||
|
where
|
||||||
|
F: FnOnce(Term<Name>) -> Term<Name>,
|
||||||
|
{
|
||||||
|
self.as_var("__list_data", |list| {
|
||||||
|
let left = Term::head_list().apply(list.clone());
|
||||||
|
list.unwrap_tail_or(
|
||||||
|
|tail| {
|
||||||
|
tail.as_var("__tail", |tail| {
|
||||||
|
let right = Term::head_list().apply(tail.clone());
|
||||||
|
tail.unwrap_tail_or(
|
||||||
|
|_| otherwise.clone(),
|
||||||
|
&callback(Term::mk_pair_data().apply(left).apply(right)),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
otherwise,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Continue with the tail of a list, if any; or fallback 'otherwise'.
|
||||||
|
///
|
||||||
|
/// Note that the 'otherwise' term as well as the callback's result are expected
|
||||||
|
/// to be delayed terms.
|
||||||
|
pub fn unwrap_tail_or<F>(self, callback: F, otherwise: &Term<Name>) -> Term<Name>
|
||||||
|
where
|
||||||
|
F: FnOnce(Term<Name>) -> Term<Name>,
|
||||||
|
{
|
||||||
|
self.clone()
|
||||||
|
.choose_list(otherwise.clone(), callback(Term::tail_list().apply(self)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue