feat: Do a major overhaul on how we check types to allow for match patterns instead of if statements

Also fix one more test
This commit is contained in:
microproofs 2024-03-30 13:35:42 -04:00 committed by Kasey
parent 3c332ca42a
commit 75b076552c
4 changed files with 467 additions and 475 deletions

View File

@ -1516,6 +1516,7 @@ impl<'a> CodeGenerator<'a> {
let uplc_type = tipo.get_uplc_type(); let uplc_type = tipo.get_uplc_type();
match uplc_type { match uplc_type {
// primitives
UplcType::Integer UplcType::Integer
| UplcType::String | UplcType::String
| UplcType::Bool | UplcType::Bool
@ -4618,111 +4619,73 @@ impl<'a> CodeGenerator<'a> {
let left = arg_stack.pop().unwrap(); let left = arg_stack.pop().unwrap();
let right = arg_stack.pop().unwrap(); let right = arg_stack.pop().unwrap();
let builtin = if tipo.is_int() { let uplc_type = tipo.get_uplc_type();
Term::equals_integer()
} else if tipo.is_string() {
Term::equals_string()
} else if tipo.is_bytearray() {
Term::equals_bytestring()
} else if tipo.is_bls381_12_g1() {
Term::bls12_381_g1_equal()
} else if tipo.is_bls381_12_g2() {
Term::bls12_381_g2_equal()
} else if tipo.is_ml_result() {
panic!("ML Result equality is not supported")
} else {
Term::equals_data()
};
let term = let term = match name {
match name {
BinOp::And => left.delayed_if_then_else(right, Term::bool(false)), BinOp::And => left.delayed_if_then_else(right, Term::bool(false)),
BinOp::Or => left.delayed_if_then_else(Term::bool(true), right), BinOp::Or => left.delayed_if_then_else(Term::bool(true), right),
BinOp::Eq => { BinOp::Eq | BinOp::NotEq => {
if tipo.is_bool() { let builtin = match &uplc_type {
let term = left.delayed_if_then_else( UplcType::Integer => Term::equals_integer(),
UplcType::String => Term::equals_string(),
UplcType::ByteString => Term::equals_bytestring(),
UplcType::Bls12_381G1Element => Term::bls12_381_g1_equal(),
UplcType::Bls12_381G2Element => Term::bls12_381_g2_equal(),
UplcType::Bool | UplcType::Unit => Term::unit(),
UplcType::List(_) | UplcType::Pair(_, _) | UplcType::Data => {
Term::equals_data()
}
UplcType::Bls12_381MlResult => {
panic!("ML Result equality is not supported")
}
};
let binop_eq = match uplc_type {
UplcType::Bool => {
if matches!(name, BinOp::Eq) {
left.delayed_if_then_else(
right.clone(), right.clone(),
right.if_then_else(Term::bool(false), Term::bool(true)), right.if_then_else(Term::bool(false), Term::bool(true)),
); )
} else {
return Some(term); left.delayed_if_then_else(
}
if tipo.is_map() {
let term = builtin
.apply(Term::map_data().apply(left))
.apply(Term::map_data().apply(right));
return Some(term);
}
if tipo.is_pair() {
let term = builtin
.apply(Term::map_data().apply(
Term::mk_cons().apply(left).apply(Term::empty_map()),
))
.apply(Term::map_data().apply(
Term::mk_cons().apply(right).apply(Term::empty_map()),
));
return Some(term);
}
if tipo.is_list() || tipo.is_tuple() {
let term = builtin
.apply(Term::list_data().apply(left))
.apply(Term::list_data().apply(right));
return Some(term);
}
if tipo.is_void() {
let term = left.choose_unit(right.choose_unit(Term::bool(true)));
return Some(term);
}
builtin.apply(left).apply(right)
}
BinOp::NotEq => {
if tipo.is_bool() {
let term = left.delayed_if_then_else(
right right
.clone() .clone()
.if_then_else(Term::bool(false), Term::bool(true)), .if_then_else(Term::bool(false), Term::bool(true)),
right, right,
); )
return Some(term);
} }
if tipo.is_map() { }
let term = builtin UplcType::List(_) if tipo.is_map() => builtin
.apply(Term::map_data().apply(left)) .apply(Term::map_data().apply(left))
.apply(Term::map_data().apply(right)) .apply(Term::map_data().apply(right)),
.if_then_else(Term::bool(false), Term::bool(true)); UplcType::List(_) => builtin
.apply(Term::list_data().apply(left))
return Some(term); .apply(Term::list_data().apply(right)),
} UplcType::Pair(_, _) => {
if tipo.is_pair() { builtin
let term = builtin
.apply(Term::map_data().apply( .apply(Term::map_data().apply(
Term::mk_cons().apply(left).apply(Term::empty_map()), Term::mk_cons().apply(left).apply(Term::empty_map()),
)) ))
.apply(Term::map_data().apply( .apply(Term::map_data().apply(
Term::mk_cons().apply(right).apply(Term::empty_map()), Term::mk_cons().apply(right).apply(Term::empty_map()),
)) ))
.if_then_else(Term::bool(false), Term::bool(true));
return Some(term);
}
if tipo.is_list() || tipo.is_tuple() {
let term = builtin
.apply(Term::list_data().apply(left))
.apply(Term::list_data().apply(right))
.if_then_else(Term::bool(false), Term::bool(true));
return Some(term);
}
if tipo.is_void() {
return Some(Term::bool(false));
} }
UplcType::Data
| UplcType::Bls12_381G1Element
| UplcType::Bls12_381G2Element
| UplcType::Bls12_381MlResult
| UplcType::Integer
| UplcType::String
| UplcType::ByteString => builtin.apply(left).apply(right),
UplcType::Unit => left.choose_unit(right.choose_unit(Term::bool(true))),
};
builtin if !tipo.is_bool() && matches!(name, BinOp::NotEq) {
.apply(left) binop_eq.if_then_else(Term::bool(false), Term::bool(true))
.apply(right) } else {
.if_then_else(Term::bool(false), Term::bool(true)) binop_eq
}
} }
BinOp::LtInt => Term::Builtin(DefaultFunction::LessThanInteger) BinOp::LtInt => Term::Builtin(DefaultFunction::LessThanInteger)
.apply(left) .apply(left)
@ -4973,25 +4936,25 @@ impl<'a> CodeGenerator<'a> {
} => { } => {
let subject = arg_stack.pop().unwrap(); let subject = arg_stack.pop().unwrap();
let subject = if tipo.is_int() let uplc_type = tipo.get_uplc_type();
|| tipo.is_bytearray()
|| tipo.is_string() let subject = match uplc_type {
|| tipo.is_list() UplcType::Bool
|| tipo.is_tuple() | UplcType::Integer
|| tipo.is_pair() | UplcType::String
|| tipo.is_bool() | UplcType::ByteString
|| tipo.is_bls381_12_g1() | UplcType::Unit
|| tipo.is_bls381_12_g2() | UplcType::List(_)
{ | UplcType::Pair(_, _)
subject | UplcType::Bls12_381G1Element
} else if tipo.is_ml_result() { | UplcType::Bls12_381G2Element
unreachable!() | UplcType::Bls12_381MlResult => subject,
} else { UplcType::Data if tipo.is_data() => subject,
Term::var( UplcType::Data => Term::var(
self.special_functions self.special_functions
.use_function_uplc(CONSTR_INDEX_EXPOSER.to_string()), .use_function_uplc(CONSTR_INDEX_EXPOSER.to_string()),
) )
.apply(subject) .apply(subject),
}; };
let mut term = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap();
@ -5009,68 +4972,67 @@ impl<'a> CodeGenerator<'a> {
let clause = arg_stack.pop().unwrap(); let clause = arg_stack.pop().unwrap();
// the body to be run if the clause matches // the body to be run if the clause matches
let mut body = arg_stack.pop().unwrap(); let body = arg_stack.pop().unwrap();
// the next branch in the when expression // the next branch in the when expression
let mut term = arg_stack.pop().unwrap(); let term = arg_stack.pop().unwrap();
if tipo.is_bool() {
let other_clauses = if complex_clause { let other_clauses = if complex_clause {
Term::var("__other_clauses_delayed") Term::var("__other_clauses_delayed")
} else { } else {
term.clone().delay() term.clone().delay()
}; };
let body = if tipo.is_bool() {
if matches!(clause, Term::Constant(boolean) if matches!(boolean.as_ref(), UplcConstant::Bool(true))) if matches!(clause, Term::Constant(boolean) if matches!(boolean.as_ref(), UplcConstant::Bool(true)))
{ {
body = Term::var(subject_name) Term::var(subject_name)
.if_then_else(body.delay(), other_clauses) .if_then_else(body.delay(), other_clauses)
.force(); .force()
} else { } else {
body = Term::var(subject_name) Term::var(subject_name)
.if_then_else(other_clauses, body.delay()) .if_then_else(other_clauses, body.delay())
.force(); .force()
} }
} else {
let uplc_type = tipo.get_uplc_type();
if complex_clause { let condition = match uplc_type {
term = body.lambda("__other_clauses_delayed").apply(term.delay()); UplcType::Bool
} else { | UplcType::Unit
term = body; | UplcType::List(_)
} | UplcType::Pair(_, _)
} else { | UplcType::Bls12_381MlResult => unreachable!("{:#?}", tipo),
let condition = if tipo.is_int() { UplcType::Integer => Term::equals_integer()
Term::equals_integer()
.apply(clause) .apply(clause)
.apply(Term::var(subject_name)) .apply(Term::var(subject_name)),
} else if tipo.is_bytearray() { UplcType::String => Term::equals_string()
Term::equals_bytestring()
.apply(clause) .apply(clause)
.apply(Term::var(subject_name)) .apply(Term::var(subject_name)),
} else if tipo.is_string() { UplcType::ByteString => Term::equals_bytestring()
Term::equals_string()
.apply(clause) .apply(clause)
.apply(Term::var(subject_name)) .apply(Term::var(subject_name)),
} else if tipo.is_list() || tipo.is_tuple() || tipo.is_pair() { UplcType::Data if tipo.is_data() => unimplemented!(),
unreachable!("{:#?}", tipo) UplcType::Data => Term::equals_integer()
} else {
Term::equals_integer()
.apply(clause) .apply(clause)
.apply(Term::var(subject_name)) .apply(Term::var(subject_name)),
UplcType::Bls12_381G1Element => Term::bls12_381_g1_equal()
.apply(clause)
.apply(Term::var(subject_name)),
UplcType::Bls12_381G2Element => Term::bls12_381_g2_equal()
.apply(clause)
.apply(Term::var(subject_name)),
};
condition.if_then_else(body.delay(), other_clauses).force()
}; };
if complex_clause { if complex_clause {
term = condition Some(body.lambda("__other_clauses_delayed").apply(term.delay()))
.if_then_else(body.delay(), Term::var("__other_clauses_delayed"))
.force()
.lambda("__other_clauses_delayed")
.apply(term.delay());
} else { } else {
term = condition.delayed_if_then_else(body, term); Some(body)
} }
} }
Some(term)
}
Air::ListClause { Air::ListClause {
tail_name, tail_name,
next_tail_name, next_tail_name,
@ -5181,50 +5143,61 @@ impl<'a> CodeGenerator<'a> {
let then = arg_stack.pop().unwrap(); let then = arg_stack.pop().unwrap();
let term = Term::var("__other_clauses_delayed");
if tipo.is_bool() { if tipo.is_bool() {
let mut term = Term::var("__other_clauses_delayed");
if matches!(checker, Term::Constant(boolean) if matches!(boolean.as_ref(), UplcConstant::Bool(true))) if matches!(checker, Term::Constant(boolean) if matches!(boolean.as_ref(), UplcConstant::Bool(true)))
{ {
term = Term::var(subject_name) Some(
Term::var(subject_name)
.if_then_else(then.delay(), term) .if_then_else(then.delay(), term)
.force(); .force(),
)
} else { } else {
term = Term::var(subject_name) Some(
Term::var(subject_name)
.if_then_else(term, then.delay()) .if_then_else(term, then.delay())
.force(); .force(),
)
} }
Some(term)
} else if tipo.is_void() { } else if tipo.is_void() {
Some(then.lambda("_").apply(Term::var(subject_name))) Some(then.lambda("_").apply(Term::var(subject_name)))
} else { } else {
let condition = if tipo.is_int() { let uplc_type = tipo.get_uplc_type();
Term::equals_integer()
let condition = match uplc_type {
UplcType::Bool
| UplcType::Unit
| UplcType::List(_)
| UplcType::Pair(_, _)
| UplcType::Bls12_381MlResult => unreachable!("{:#?}", tipo),
UplcType::Integer => Term::equals_integer()
.apply(checker) .apply(checker)
.apply(Term::var(subject_name)) .apply(Term::var(subject_name)),
} else if tipo.is_bytearray() { UplcType::String => Term::equals_string()
Term::equals_bytestring()
.apply(checker) .apply(checker)
.apply(Term::var(subject_name)) .apply(Term::var(subject_name)),
} else if tipo.is_string() { UplcType::ByteString => Term::equals_bytestring()
Term::equals_string()
.apply(checker) .apply(checker)
.apply(Term::var(subject_name)) .apply(Term::var(subject_name)),
} else if tipo.is_list() || tipo.is_tuple() {
unreachable!() UplcType::Data if tipo.is_data() => unimplemented!(),
} else { UplcType::Data => Term::equals_integer().apply(checker).apply(
Term::equals_integer().apply(checker).apply(
Term::var( Term::var(
self.special_functions self.special_functions
.use_function_uplc(CONSTR_INDEX_EXPOSER.to_string()), .use_function_uplc(CONSTR_INDEX_EXPOSER.to_string()),
) )
.apply(Term::var(subject_name)), .apply(Term::var(subject_name)),
) ),
UplcType::Bls12_381G1Element => Term::bls12_381_g1_equal()
.apply(checker)
.apply(Term::var(subject_name)),
UplcType::Bls12_381G2Element => Term::bls12_381_g2_equal()
.apply(checker)
.apply(Term::var(subject_name)),
}; };
let term = condition Some(condition.if_then_else(then.delay(), term).force())
.if_then_else(then.delay(), Term::var("__other_clauses_delayed"))
.force();
Some(term)
} }
} }
Air::ListClauseGuard { Air::ListClauseGuard {

View File

@ -359,38 +359,25 @@ pub fn handle_clause_guard(clause_guard: &TypedClauseGuard) -> AirTree {
} }
pub fn get_generic_variant_name(t: &Rc<Type>) -> String { pub fn get_generic_variant_name(t: &Rc<Type>) -> String {
if t.is_string() { let uplc_type = t.get_uplc_type();
"_string".to_string()
} else if t.is_int() {
"_int".to_string()
} else if t.is_bool() {
"_bool".to_string()
} else if t.is_bytearray() {
"_bytearray".to_string()
} else if t.is_bls381_12_g1() {
"_bls381_12_g1".to_string()
} else if t.is_bls381_12_g2() {
"_bls381_12_g2".to_string()
} else if t.is_ml_result() {
"_ml_result".to_string()
} else if t.is_map() {
"_map".to_string()
} else if t.is_pair() {
"_pair".to_string()
} else if t.is_list() {
"_list".to_string()
} else if t.is_tuple() {
"_tuple".to_string()
} else if t.is_unbound() {
"_unbound".to_string()
} else {
let full_type = "_data".to_string();
if t.is_generic() { match uplc_type {
panic!("FOUND A POLYMORPHIC TYPE. EXPECTED MONOMORPHIC TYPE"); UplcType::Bool => "_bool".to_string(),
UplcType::Integer => "_int".to_string(),
UplcType::String => "_string".to_string(),
UplcType::ByteString => "_bytearray".to_string(),
UplcType::Unit => "_void".to_string(),
UplcType::List(_) if t.is_map() => "_map".to_string(),
UplcType::List(_) => "_list".to_string(),
UplcType::Pair(_, _) => "_pair".to_string(),
UplcType::Bls12_381G1Element => "_bls381_12_g1".to_string(),
UplcType::Bls12_381G2Element => "_bls381_12_g2".to_string(),
UplcType::Bls12_381MlResult => "_ml_result".to_string(),
UplcType::Data if t.is_unbound() => "_unbound".to_string(),
UplcType::Data if t.is_generic() => {
unreachable!("FOUND A POLYMORPHIC TYPE. EXPECTED MONOMORPHIC TYPE")
} }
UplcType::Data => "_data".to_string(),
full_type
} }
} }
@ -958,62 +945,54 @@ pub fn find_list_clause_or_default_first(clauses: &[TypedClause]) -> &TypedClaus
} }
pub fn known_data_to_type(term: Term<Name>, field_type: &Type) -> Term<Name> { pub fn known_data_to_type(term: Term<Name>, field_type: &Type) -> Term<Name> {
if field_type.is_int() { let uplc_type = field_type.get_uplc_type();
Term::un_i_data().apply(term)
} else if field_type.is_bytearray() { match uplc_type {
Term::un_b_data().apply(term) UplcType::Integer => Term::un_i_data().apply(term),
} else if field_type.is_void() { UplcType::ByteString => Term::un_b_data().apply(term),
Term::unit().lambda("_").apply(term) UplcType::Bool => Term::less_than_integer()
} else if field_type.is_map() { .apply(Term::integer(0.into()))
Term::unmap_data().apply(term) .apply(Term::fst_pair().apply(Term::unconstr_data().apply(term))),
} else if field_type.is_string() { UplcType::String => Term::decode_utf8().apply(Term::un_b_data().apply(term)),
Term::Builtin(DefaultFunction::DecodeUtf8).apply(Term::un_b_data().apply(term)) UplcType::Unit => Term::unit().lambda("_").apply(term),
} else if field_type.is_pair() { UplcType::List(_) if field_type.is_map() => Term::unmap_data().apply(term),
Term::mk_pair_data() UplcType::List(_) => Term::unlist_data().apply(term),
UplcType::Pair(_, _) => Term::mk_pair_data()
.apply(Term::head_list().apply(Term::var("__list_data"))) .apply(Term::head_list().apply(Term::var("__list_data")))
.apply(Term::head_list().apply(Term::tail_list().apply(Term::var("__list_data")))) .apply(Term::head_list().apply(Term::tail_list().apply(Term::var("__list_data"))))
.lambda("__list_data") .lambda("__list_data")
.apply(Term::unlist_data().apply(term)) .apply(Term::unlist_data().apply(term)),
} else if field_type.is_list() || field_type.is_tuple() { UplcType::Data if field_type.is_data() => term,
Term::unlist_data().apply(term) UplcType::Data => term,
} else if field_type.is_bool() { UplcType::Bls12_381G1Element => {
Term::less_than_integer()
.apply(Term::integer(0.into()))
.apply(Term::fst_pair().apply(Term::unconstr_data().apply(term)))
} else if field_type.is_bls381_12_g1() {
Term::bls12_381_g1_uncompress().apply(Term::un_b_data().apply(term)) Term::bls12_381_g1_uncompress().apply(Term::un_b_data().apply(term))
} else if field_type.is_bls381_12_g2() { }
UplcType::Bls12_381G2Element => {
Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(term)) Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(term))
} else if field_type.is_ml_result() { }
panic!("ML Result not supported") UplcType::Bls12_381MlResult => panic!("ML Result not supported"),
} else {
term
} }
} }
pub fn unknown_data_to_type(term: Term<Name>, field_type: &Type) -> Term<Name> { pub fn unknown_data_to_type(term: Term<Name>, field_type: &Type) -> Term<Name> {
if field_type.is_int() { let uplc_type = field_type.get_uplc_type();
Term::un_i_data().apply(term)
} else if field_type.is_bytearray() { match uplc_type {
Term::un_b_data().apply(term) UplcType::Integer => Term::un_i_data().apply(term),
} else if field_type.is_void() { UplcType::ByteString => Term::un_b_data().apply(term),
Term::equals_integer() UplcType::String => Term::decode_utf8().apply(Term::un_b_data().apply(term)),
.apply(Term::integer(0.into())) UplcType::List(_) if field_type.is_map() => Term::unmap_data().apply(term),
.apply(Term::fst_pair().apply(Term::var("__pair__"))) UplcType::List(_) => Term::unlist_data().apply(term),
.delayed_if_then_else( UplcType::Data if field_type.is_data() => term,
Term::snd_pair() UplcType::Data => term,
.apply(Term::var("__pair__")) UplcType::Bls12_381G1Element => {
.delayed_choose_list(Term::unit(), Term::Error), Term::bls12_381_g1_uncompress().apply(Term::un_b_data().apply(term))
Term::Error, }
) UplcType::Bls12_381G2Element => {
.lambda("__pair__") Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(term))
.apply(Term::unconstr_data().apply(term)) }
} else if field_type.is_map() { UplcType::Bls12_381MlResult => panic!("ML Result not supported"),
Term::unmap_data().apply(term) UplcType::Pair(_, _) => Term::tail_list()
} else if field_type.is_string() {
Term::Builtin(DefaultFunction::DecodeUtf8).apply(Term::un_b_data().apply(term))
} else if field_type.is_pair() {
Term::tail_list()
.apply(Term::tail_list().apply(Term::var("__list_data"))) .apply(Term::tail_list().apply(Term::var("__list_data")))
.delayed_choose_list( .delayed_choose_list(
Term::mk_pair_data() Term::mk_pair_data()
@ -1024,11 +1003,8 @@ pub fn unknown_data_to_type(term: Term<Name>, field_type: &Type) -> Term<Name> {
Term::Error, Term::Error,
) )
.lambda("__list_data") .lambda("__list_data")
.apply(Term::unlist_data().apply(term)) .apply(Term::unlist_data().apply(term)),
} else if field_type.is_list() || field_type.is_tuple() { UplcType::Bool => Term::snd_pair()
Term::unlist_data().apply(term)
} else if field_type.is_bool() {
Term::snd_pair()
.apply(Term::var("__pair__")) .apply(Term::var("__pair__"))
.delayed_choose_list( .delayed_choose_list(
Term::equals_integer() Term::equals_integer()
@ -1044,25 +1020,33 @@ pub fn unknown_data_to_type(term: Term<Name>, field_type: &Type) -> Term<Name> {
Term::Error, Term::Error,
) )
.lambda("__pair__") .lambda("__pair__")
.apply(Term::unconstr_data().apply(term)) .apply(Term::unconstr_data().apply(term)),
} else if field_type.is_bls381_12_g1() { UplcType::Unit => Term::equals_integer()
Term::bls12_381_g1_uncompress().apply(Term::un_b_data().apply(term)) .apply(Term::integer(0.into()))
} else if field_type.is_bls381_12_g2() { .apply(Term::fst_pair().apply(Term::var("__pair__")))
Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(term)) .delayed_if_then_else(
} else if field_type.is_ml_result() { Term::snd_pair()
panic!("ML Result not supported") .apply(Term::var("__pair__"))
} else { .delayed_choose_list(Term::unit(), Term::Error),
term Term::Error,
)
.lambda("__pair__")
.apply(Term::unconstr_data().apply(term)),
} }
} }
/// Due to the nature of the types BLS12_381_G1Element and BLS12_381_G2Element and String coming from bytearray
/// We don't have error handling if the bytearray is not properly aligned to the type. Oh well lol
/// For BLS12_381_G1Element and BLS12_381_G2Element, hash to group exists so just adopt that.
pub fn unknown_data_to_type_debug( pub fn unknown_data_to_type_debug(
term: Term<Name>, term: Term<Name>,
field_type: &Type, field_type: &Type,
error_term: Term<Name>, error_term: Term<Name>,
) -> Term<Name> { ) -> Term<Name> {
if field_type.is_int() { let uplc_type = field_type.get_uplc_type();
Term::var("__val")
match uplc_type {
UplcType::Integer => Term::var("__val")
.delayed_choose_data( .delayed_choose_data(
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
@ -1071,9 +1055,8 @@ pub fn unknown_data_to_type_debug(
error_term.clone(), error_term.clone(),
) )
.lambda("__val") .lambda("__val")
.apply(term) .apply(term),
} else if field_type.is_bytearray() { UplcType::ByteString => Term::var("__val")
Term::var("__val")
.delayed_choose_data( .delayed_choose_data(
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
@ -1082,28 +1065,19 @@ pub fn unknown_data_to_type_debug(
Term::un_b_data().apply(Term::var("__val")), Term::un_b_data().apply(Term::var("__val")),
) )
.lambda("__val") .lambda("__val")
.apply(term) .apply(term),
} else if field_type.is_void() { UplcType::String => Term::var("__val")
Term::var("__val")
.delayed_choose_data( .delayed_choose_data(
Term::equals_integer()
.apply(Term::integer(0.into()))
.apply(Term::fst_pair().apply(Term::unconstr_data().apply(Term::var("__val"))))
.delayed_if_then_else(
Term::snd_pair()
.apply(Term::unconstr_data().apply(Term::var("__val")))
.delayed_choose_list(Term::unit(), error_term.clone()),
error_term.clone(),
),
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
Term::decode_utf8().apply(Term::un_b_data().apply(Term::var("__val"))),
) )
.lambda("__val") .lambda("__val")
.apply(term) .apply(term),
} else if field_type.is_map() {
Term::var("__val") UplcType::List(_) if field_type.is_map() => Term::var("__val")
.delayed_choose_data( .delayed_choose_data(
error_term.clone(), error_term.clone(),
Term::unmap_data().apply(Term::var("__val")), Term::unmap_data().apply(Term::var("__val")),
@ -1112,21 +1086,51 @@ pub fn unknown_data_to_type_debug(
error_term.clone(), error_term.clone(),
) )
.lambda("__val") .lambda("__val")
.apply(term) .apply(term),
} else if field_type.is_string() { UplcType::List(_) => Term::var("__val")
Term::var("__val") .delayed_choose_data(
error_term.clone(),
error_term.clone(),
Term::unlist_data().apply(Term::var("__val")),
error_term.clone(),
error_term.clone(),
)
.lambda("__val")
.apply(term),
UplcType::Data if field_type.is_data() => term,
// constr type
UplcType::Data => Term::var("__val")
.delayed_choose_data(
Term::var("__val"),
error_term.clone(),
error_term.clone(),
error_term.clone(),
error_term.clone(),
)
.lambda("__val")
.apply(term),
UplcType::Bls12_381G1Element => Term::var("__val")
.delayed_choose_data( .delayed_choose_data(
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
Term::Builtin(DefaultFunction::DecodeUtf8) Term::bls12_381_g1_uncompress().apply(Term::un_b_data().apply(Term::var("__val"))),
.apply(Term::un_b_data().apply(Term::var("__val"))),
) )
.lambda("__val") .lambda("__val")
.apply(term) .apply(term),
} else if field_type.is_pair() { UplcType::Bls12_381G2Element => Term::var("__val")
Term::var("__val") .delayed_choose_data(
error_term.clone(),
error_term.clone(),
error_term.clone(),
error_term.clone(),
Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(Term::var("__val"))),
)
.lambda("__val")
.apply(term),
UplcType::Bls12_381MlResult => panic!("ML Result not supported"),
UplcType::Pair(_, _) => Term::var("__val")
.delayed_choose_data( .delayed_choose_data(
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
@ -1156,20 +1160,8 @@ pub fn unknown_data_to_type_debug(
error_term.clone(), error_term.clone(),
) )
.lambda("__val") .lambda("__val")
.apply(term) .apply(term),
} else if field_type.is_list() || field_type.is_tuple() { UplcType::Bool => Term::var("__val")
Term::var("__val")
.delayed_choose_data(
error_term.clone(),
error_term.clone(),
Term::unlist_data().apply(Term::var("__val")),
error_term.clone(),
error_term.clone(),
)
.lambda("__val")
.apply(term)
} else if field_type.is_bool() {
Term::var("__val")
.delayed_choose_data( .delayed_choose_data(
Term::snd_pair() Term::snd_pair()
.apply(Term::var("__pair__")) .apply(Term::var("__pair__"))
@ -1194,44 +1186,25 @@ pub fn unknown_data_to_type_debug(
error_term.clone(), error_term.clone(),
) )
.lambda("__val") .lambda("__val")
.apply(term) .apply(term),
} else if field_type.is_bls381_12_g1() { UplcType::Unit => Term::var("__val")
Term::var("__val")
.delayed_choose_data( .delayed_choose_data(
Term::equals_integer()
.apply(Term::integer(0.into()))
.apply(Term::fst_pair().apply(Term::unconstr_data().apply(Term::var("__val"))))
.delayed_if_then_else(
Term::snd_pair()
.apply(Term::unconstr_data().apply(Term::var("__val")))
.delayed_choose_list(Term::unit(), error_term.clone()),
error_term.clone(), error_term.clone(),
error_term.clone(), ),
error_term.clone(),
error_term.clone(),
Term::bls12_381_g1_uncompress().apply(Term::un_b_data().apply(Term::var("__val"))),
)
.lambda("__val")
.apply(term)
} else if field_type.is_bls381_12_g2() {
Term::var("__val")
.delayed_choose_data(
error_term.clone(),
error_term.clone(),
error_term.clone(),
error_term.clone(),
Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(Term::var("__val"))),
)
.lambda("__val")
.apply(term)
} else if field_type.is_ml_result() {
panic!("ML Result not supported")
} else if field_type.is_data() {
term
} else {
Term::var("__val")
.delayed_choose_data(
Term::var("__val"),
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
error_term.clone(), error_term.clone(),
) )
.lambda("__val") .lambda("__val")
.apply(term) .apply(term),
} }
} }
@ -1323,25 +1296,24 @@ pub fn convert_constants_to_data(constants: Vec<Rc<UplcConstant>>) -> Vec<UplcCo
} }
pub fn convert_type_to_data(term: Term<Name>, field_type: &Rc<Type>) -> Term<Name> { pub fn convert_type_to_data(term: Term<Name>, field_type: &Rc<Type>) -> Term<Name> {
if field_type.is_bytearray() { let uplc_type = field_type.get_uplc_type();
Term::b_data().apply(term)
} else if field_type.is_int() { match uplc_type {
Term::i_data().apply(term) UplcType::Integer => Term::i_data().apply(term),
} else if field_type.is_void() { UplcType::String => Term::b_data().apply(Term::encode_utf8().apply(term)),
term.choose_unit(Term::Constant( UplcType::ByteString => Term::b_data().apply(term),
UplcConstant::Data(PlutusData::Constr(Constr { UplcType::List(_) if field_type.is_map() => Term::map_data().apply(term),
tag: convert_constr_to_tag(0).unwrap(), UplcType::List(_) => Term::list_data().apply(term),
any_constructor: None, UplcType::Data if field_type.is_data() => term,
fields: vec![], UplcType::Data => term,
})) UplcType::Bls12_381G1Element => {
.into(), Term::b_data().apply(Term::bls12_381_g1_compress().apply(term))
)) }
} else if field_type.is_map() { UplcType::Bls12_381G2Element => {
Term::map_data().apply(term) Term::b_data().apply(Term::bls12_381_g2_compress().apply(term))
} else if field_type.is_string() { }
Term::b_data().apply(Term::Builtin(DefaultFunction::EncodeUtf8).apply(term)) UplcType::Bls12_381MlResult => panic!("ML Result not supported"),
} else if field_type.is_pair() { UplcType::Pair(_, _) => Term::list_data()
Term::list_data()
.apply( .apply(
Term::mk_cons() Term::mk_cons()
.apply(Term::fst_pair().apply(Term::var("__pair"))) .apply(Term::fst_pair().apply(Term::var("__pair")))
@ -1352,11 +1324,18 @@ pub fn convert_type_to_data(term: Term<Name>, field_type: &Rc<Type>) -> Term<Nam
), ),
) )
.lambda("__pair") .lambda("__pair")
.apply(term) .apply(term),
} else if field_type.is_list() || field_type.is_tuple() { UplcType::Unit => Term::Constant(
Term::list_data().apply(term) UplcConstant::Data(PlutusData::Constr(Constr {
} else if field_type.is_bool() { tag: convert_constr_to_tag(0).unwrap(),
term.if_then_else( any_constructor: None,
fields: vec![],
}))
.into(),
)
.lambda("_")
.apply(term),
UplcType::Bool => term.if_then_else(
Term::Constant( Term::Constant(
UplcConstant::Data(PlutusData::Constr(Constr { UplcConstant::Data(PlutusData::Constr(Constr {
tag: convert_constr_to_tag(1).unwrap(), tag: convert_constr_to_tag(1).unwrap(),
@ -1373,15 +1352,7 @@ pub fn convert_type_to_data(term: Term<Name>, field_type: &Rc<Type>) -> Term<Nam
})) }))
.into(), .into(),
), ),
) ),
} else if field_type.is_bls381_12_g1() {
Term::b_data().apply(Term::bls12_381_g1_compress().apply(term))
} else if field_type.is_bls381_12_g2() {
Term::b_data().apply(Term::bls12_381_g2_compress().apply(term))
} else if field_type.is_ml_result() {
panic!("ML Result not supported")
} else {
term
} }
} }

View File

@ -267,12 +267,21 @@ impl Type {
} }
pub fn is_primitive(&self) -> bool { pub fn is_primitive(&self) -> bool {
self.is_bool() let uplc_type = self.get_uplc_type();
|| self.is_bytearray() match uplc_type {
|| self.is_int() UplcType::Bool
|| self.is_string() | UplcType::Integer
|| self.is_void() | UplcType::String
|| self.is_data() | UplcType::ByteString
| UplcType::Unit
| UplcType::Bls12_381G1Element
| UplcType::Bls12_381G2Element
| UplcType::Bls12_381MlResult => true,
UplcType::Data if self.is_data() => true,
UplcType::Data => false,
UplcType::List(_) | UplcType::Pair(_, _) => false,
}
} }
pub fn is_void(&self) -> bool { pub fn is_void(&self) -> bool {
@ -475,7 +484,6 @@ impl Type {
} }
} }
// TODO: THIS WILL CHANGE DUE TO PAIRS
pub fn get_uplc_type(&self) -> UplcType { pub fn get_uplc_type(&self) -> UplcType {
if self.is_int() { if self.is_int() {
UplcType::Integer UplcType::Integer
@ -485,6 +493,8 @@ impl Type {
UplcType::String UplcType::String
} else if self.is_bool() { } else if self.is_bool() {
UplcType::Bool UplcType::Bool
} else if self.is_void() {
UplcType::Unit
} else if self.is_map() { } else if self.is_map() {
UplcType::List(UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()).into()) UplcType::List(UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()).into())
} else if self.is_list() { } else if self.is_list() {

View File

@ -3304,7 +3304,7 @@ fn acceptance_test_29_union_tuple() {
src, src,
Term::equals_data() Term::equals_data()
.apply( .apply(
Term::map_data().apply( Term::list_data().apply(
Term::var("union") Term::var("union")
.lambda("union") .lambda("union")
.apply( .apply(
@ -3332,18 +3332,22 @@ fn acceptance_test_29_union_tuple() {
) )
.lambda("v") .lambda("v")
.apply( .apply(
Term::un_i_data() Term::un_i_data().apply(Term::head_list().apply(
.apply(Term::snd_pair().apply(Term::var("pair"))), Term::tail_list().apply(Term::var("tuple")),
)),
) )
.lambda("k") .lambda("k")
.apply( .apply(
Term::un_b_data() Term::un_b_data()
.apply(Term::fst_pair().apply(Term::var("pair"))), .apply(Term::head_list().apply(Term::var("tuple"))),
) )
.lambda("rest") .lambda("rest")
.apply(Term::tail_list().apply(Term::var("left"))) .apply(Term::tail_list().apply(Term::var("left")))
.lambda("pair") .lambda("tuple")
.apply(
Term::unlist_data()
.apply(Term::head_list().apply(Term::var("left"))), .apply(Term::head_list().apply(Term::var("left"))),
),
) )
.lambda("right") .lambda("right")
.lambda("left") .lambda("left")
@ -3360,40 +3364,74 @@ fn acceptance_test_29_union_tuple() {
.delayed_choose_list( .delayed_choose_list(
Term::mk_cons() Term::mk_cons()
.apply( .apply(
Term::mk_pair_data() Term::list_data().apply(
.apply(Term::b_data().apply(Term::var("k"))) Term::mk_cons()
.apply( .apply(
Term::i_data().apply(Term::var("v")), Term::b_data()
.apply(Term::var("k")),
)
.apply(
Term::mk_cons()
.apply(
Term::i_data()
.apply(Term::var("v")),
)
.apply(Term::empty_list()),
),
), ),
) )
.apply(Term::empty_map()), .apply(Term::empty_list()),
Term::equals_bytestring() Term::equals_bytestring()
.apply(Term::var("k")) .apply(Term::var("k"))
.apply(Term::var("k2")) .apply(Term::var("k2"))
.delayed_if_then_else( .delayed_if_then_else(
Term::mk_cons() Term::mk_cons()
.apply( .apply(
Term::mk_pair_data() Term::list_data().apply(
Term::mk_cons()
.apply( .apply(
Term::b_data() Term::b_data()
.apply(Term::var("k")), .apply(Term::var("k")),
) )
.apply(
Term::mk_cons()
.apply( .apply(
Term::i_data() Term::i_data()
.apply(Term::var("v")), .apply(
Term::var(
"v",
),
),
)
.apply(
Term::empty_list(),
),
),
), ),
) )
.apply(Term::var("rest")), .apply(Term::var("rest")),
Term::mk_cons() Term::mk_cons()
.apply( .apply(
Term::mk_pair_data() Term::list_data().apply(
Term::mk_cons()
.apply( .apply(
Term::b_data() Term::b_data()
.apply(Term::var("k2")), .apply(Term::var("k2")),
) )
.apply(
Term::mk_cons()
.apply( .apply(
Term::i_data() Term::i_data()
.apply(Term::var("v2")), .apply(
Term::var(
"v2",
),
),
)
.apply(
Term::empty_list(),
),
),
), ),
) )
.apply( .apply(
@ -3404,16 +3442,20 @@ fn acceptance_test_29_union_tuple() {
) )
.lambda("v2") .lambda("v2")
.apply(Term::un_i_data().apply( .apply(Term::un_i_data().apply(
Term::snd_pair().apply(Term::var("pair")), Term::head_list().apply(
Term::tail_list().apply(Term::var("tuple")),
),
)) ))
.lambda("k2") .lambda("k2")
.apply(Term::un_b_data().apply( .apply(Term::un_b_data().apply(
Term::fst_pair().apply(Term::var("pair")), Term::head_list().apply(Term::var("tuple")),
)) ))
.lambda("rest") .lambda("rest")
.apply(Term::tail_list().apply(Term::var("elems"))) .apply(Term::tail_list().apply(Term::var("elems")))
.lambda("pair") .lambda("tuple")
.apply(Term::head_list().apply(Term::var("elems"))), .apply(Term::unlist_data().apply(
Term::head_list().apply(Term::var("elems")),
)),
) )
.lambda("elems") .lambda("elems")
.lambda("do_insert"), .lambda("do_insert"),
@ -3422,32 +3464,28 @@ fn acceptance_test_29_union_tuple() {
.lambda("k") .lambda("k")
.lambda("elems"), .lambda("elems"),
) )
.apply(Term::map_values(vec![ .apply(Term::list_values(vec![
Constant::ProtoPair( Constant::Data(Data::list(vec![
Type::Data,
Type::Data,
Constant::Data(Data::bytestring("foo".as_bytes().to_vec())).into(),
Constant::Data(Data::integer(42.into())).into(),
),
Constant::ProtoPair(
Type::Data,
Type::Data,
Constant::Data(Data::bytestring("bar".as_bytes().to_vec())).into(),
Constant::Data(Data::integer(14.into())).into(),
),
]))
.apply(Term::empty_map()),
),
)
.apply(Term::data(Data::map(vec![
(
Data::bytestring("foo".as_bytes().to_vec()), Data::bytestring("foo".as_bytes().to_vec()),
Data::integer(42.into()), Data::integer(42.into()),
), ])),
( Constant::Data(Data::list(vec![
Data::bytestring("bar".as_bytes().to_vec()), Data::bytestring("bar".as_bytes().to_vec()),
Data::integer(14.into()), Data::integer(14.into()),
])),
]))
.apply(Term::empty_list()),
), ),
)
.apply(Term::data(Data::list(vec![
Data::list(vec![
Data::bytestring("foo".as_bytes().to_vec()),
Data::integer(42.into()),
]),
Data::list(vec![
Data::bytestring("bar".as_bytes().to_vec()),
Data::integer(14.into()),
]),
]))), ]))),
false, false,
); );