From a0f9aa9d6d459ac309a44936d5b3efead4bf671d Mon Sep 17 00:00:00 2001 From: microproofs Date: Sat, 30 Mar 2024 13:35:42 -0400 Subject: [PATCH] feat: Do a major overhaul on how we check types to allow for match patterns instead of if statements Also fix one more test --- crates/aiken-lang/src/gen_uplc.rs | 381 ++++++++++----------- crates/aiken-lang/src/gen_uplc/builder.rs | 371 +++++++++----------- crates/aiken-lang/src/tipo.rs | 24 +- crates/aiken-project/src/tests/gen_uplc.rs | 144 +++++--- 4 files changed, 456 insertions(+), 464 deletions(-) diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 4c7df4d67..5c14c69ec 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -1516,6 +1516,7 @@ impl<'a> CodeGenerator<'a> { let uplc_type = tipo.get_uplc_type(); match uplc_type { + // primitives UplcType::Integer | UplcType::String | UplcType::Bool @@ -4609,138 +4610,100 @@ impl<'a> CodeGenerator<'a> { let left = arg_stack.pop().unwrap(); let right = arg_stack.pop().unwrap(); - let builtin = if tipo.is_int() { - 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 = - match name { - BinOp::And => left.delayed_if_then_else(right, Term::bool(false)), - BinOp::Or => left.delayed_if_then_else(Term::bool(true), right), - BinOp::Eq => { - if tipo.is_bool() { - let term = left.delayed_if_then_else( - right.clone(), - right.if_then_else(Term::bool(false), Term::bool(true)), - ); - - return Some(term); + let uplc_type = tipo.get_uplc_type(); + + let term = match name { + BinOp::And => left.delayed_if_then_else(right, Term::bool(false)), + BinOp::Or => left.delayed_if_then_else(Term::bool(true), right), + BinOp::Eq | BinOp::NotEq => { + let builtin = match &uplc_type { + 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() } - 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); + UplcType::Bls12_381MlResult => { + panic!("ML Result equality is not supported") } - 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 - .clone() - .if_then_else(Term::bool(false), Term::bool(true)), - right, - ); - - return Some(term); - } - if tipo.is_map() { - let term = builtin - .apply(Term::map_data().apply(left)) - .apply(Term::map_data().apply(right)) - .if_then_else(Term::bool(false), Term::bool(true)); + }; - return Some(term); + let binop_eq = match uplc_type { + UplcType::Bool => { + if matches!(name, BinOp::Eq) { + left.delayed_if_then_else( + right.clone(), + right.if_then_else(Term::bool(false), Term::bool(true)), + ) + } else { + left.delayed_if_then_else( + right + .clone() + .if_then_else(Term::bool(false), Term::bool(true)), + right, + ) + } } - if tipo.is_pair() { - let term = builtin + UplcType::List(_) if tipo.is_map() => builtin + .apply(Term::map_data().apply(left)) + .apply(Term::map_data().apply(right)), + UplcType::List(_) => builtin + .apply(Term::list_data().apply(left)) + .apply(Term::list_data().apply(right)), + UplcType::Pair(_, _) => { + 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()), )) - .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 - .apply(left) - .apply(right) - .if_then_else(Term::bool(false), Term::bool(true)) + if !tipo.is_bool() && matches!(name, BinOp::NotEq) { + binop_eq.if_then_else(Term::bool(false), Term::bool(true)) + } else { + binop_eq } - BinOp::LtInt => Term::Builtin(DefaultFunction::LessThanInteger) - .apply(left) - .apply(right), - BinOp::LtEqInt => Term::Builtin(DefaultFunction::LessThanEqualsInteger) - .apply(left) - .apply(right), - BinOp::GtEqInt => Term::Builtin(DefaultFunction::LessThanEqualsInteger) - .apply(right) - .apply(left), - BinOp::GtInt => Term::Builtin(DefaultFunction::LessThanInteger) - .apply(right) - .apply(left), - BinOp::AddInt => Term::add_integer().apply(left).apply(right), - BinOp::SubInt => Term::Builtin(DefaultFunction::SubtractInteger) - .apply(left) - .apply(right), - BinOp::MultInt => Term::Builtin(DefaultFunction::MultiplyInteger) - .apply(left) - .apply(right), - BinOp::DivInt => Term::Builtin(DefaultFunction::DivideInteger) - .apply(left) - .apply(right), - BinOp::ModInt => Term::Builtin(DefaultFunction::ModInteger) - .apply(left) - .apply(right), - }; + } + BinOp::LtInt => Term::Builtin(DefaultFunction::LessThanInteger) + .apply(left) + .apply(right), + BinOp::LtEqInt => Term::Builtin(DefaultFunction::LessThanEqualsInteger) + .apply(left) + .apply(right), + BinOp::GtEqInt => Term::Builtin(DefaultFunction::LessThanEqualsInteger) + .apply(right) + .apply(left), + BinOp::GtInt => Term::Builtin(DefaultFunction::LessThanInteger) + .apply(right) + .apply(left), + BinOp::AddInt => Term::add_integer().apply(left).apply(right), + BinOp::SubInt => Term::Builtin(DefaultFunction::SubtractInteger) + .apply(left) + .apply(right), + BinOp::MultInt => Term::Builtin(DefaultFunction::MultiplyInteger) + .apply(left) + .apply(right), + BinOp::DivInt => Term::Builtin(DefaultFunction::DivideInteger) + .apply(left) + .apply(right), + BinOp::ModInt => Term::Builtin(DefaultFunction::ModInteger) + .apply(left) + .apply(right), + }; Some(term) } Air::DefineFunc { @@ -4964,25 +4927,25 @@ impl<'a> CodeGenerator<'a> { } => { let subject = arg_stack.pop().unwrap(); - let subject = if tipo.is_int() - || tipo.is_bytearray() - || tipo.is_string() - || tipo.is_list() - || tipo.is_tuple() - || tipo.is_pair() - || tipo.is_bool() - || tipo.is_bls381_12_g1() - || tipo.is_bls381_12_g2() - { - subject - } else if tipo.is_ml_result() { - unreachable!() - } else { - Term::var( + let uplc_type = tipo.get_uplc_type(); + + let subject = match uplc_type { + UplcType::Bool + | UplcType::Integer + | UplcType::String + | UplcType::ByteString + | UplcType::Unit + | UplcType::List(_) + | UplcType::Pair(_, _) + | UplcType::Bls12_381G1Element + | UplcType::Bls12_381G2Element + | UplcType::Bls12_381MlResult => subject, + UplcType::Data if tipo.is_data() => subject, + UplcType::Data => Term::var( self.special_functions .use_function_uplc(CONSTR_INDEX_EXPOSER.to_string()), ) - .apply(subject) + .apply(subject), }; let mut term = arg_stack.pop().unwrap(); @@ -5000,67 +4963,66 @@ impl<'a> CodeGenerator<'a> { let clause = arg_stack.pop().unwrap(); // 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 - let mut term = arg_stack.pop().unwrap(); + let term = arg_stack.pop().unwrap(); - if tipo.is_bool() { - let other_clauses = if complex_clause { - Term::var("__other_clauses_delayed") - } else { - term.clone().delay() - }; + let other_clauses = if complex_clause { + Term::var("__other_clauses_delayed") + } else { + term.clone().delay() + }; + let body = if tipo.is_bool() { 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) - .force(); + .force() } else { - body = Term::var(subject_name) + Term::var(subject_name) .if_then_else(other_clauses, body.delay()) - .force(); - } - - if complex_clause { - term = body.lambda("__other_clauses_delayed").apply(term.delay()); - } else { - term = body; + .force() } } else { - let condition = if tipo.is_int() { - Term::equals_integer() + let uplc_type = tipo.get_uplc_type(); + + let condition = match uplc_type { + UplcType::Bool + | UplcType::Unit + | UplcType::List(_) + | UplcType::Pair(_, _) + | UplcType::Bls12_381MlResult => unreachable!("{:#?}", tipo), + UplcType::Integer => Term::equals_integer() + .apply(clause) + .apply(Term::var(subject_name)), + UplcType::String => Term::equals_string() .apply(clause) - .apply(Term::var(subject_name)) - } else if tipo.is_bytearray() { - Term::equals_bytestring() + .apply(Term::var(subject_name)), + UplcType::ByteString => Term::equals_bytestring() .apply(clause) - .apply(Term::var(subject_name)) - } else if tipo.is_string() { - Term::equals_string() + .apply(Term::var(subject_name)), + UplcType::Data if tipo.is_data() => unimplemented!(), + UplcType::Data => Term::equals_integer() .apply(clause) - .apply(Term::var(subject_name)) - } else if tipo.is_list() || tipo.is_tuple() || tipo.is_pair() { - unreachable!("{:#?}", tipo) - } else { - Term::equals_integer() + .apply(Term::var(subject_name)), + UplcType::Bls12_381G1Element => Term::bls12_381_g1_equal() .apply(clause) - .apply(Term::var(subject_name)) + .apply(Term::var(subject_name)), + UplcType::Bls12_381G2Element => Term::bls12_381_g2_equal() + .apply(clause) + .apply(Term::var(subject_name)), }; - if complex_clause { - term = condition - .if_then_else(body.delay(), Term::var("__other_clauses_delayed")) - .force() - .lambda("__other_clauses_delayed") - .apply(term.delay()); - } else { - term = condition.delayed_if_then_else(body, term); - } - } + condition.if_then_else(body.delay(), other_clauses).force() + }; - Some(term) + if complex_clause { + Some(body.lambda("__other_clauses_delayed").apply(term.delay())) + } else { + Some(body) + } } Air::ListClause { tail_name, @@ -5172,50 +5134,61 @@ impl<'a> CodeGenerator<'a> { let then = arg_stack.pop().unwrap(); + let term = Term::var("__other_clauses_delayed"); + 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))) { - term = Term::var(subject_name) - .if_then_else(then.delay(), term) - .force(); + Some( + Term::var(subject_name) + .if_then_else(then.delay(), term) + .force(), + ) } else { - term = Term::var(subject_name) - .if_then_else(term, then.delay()) - .force(); + Some( + Term::var(subject_name) + .if_then_else(term, then.delay()) + .force(), + ) } - Some(term) } else if tipo.is_void() { Some(then.lambda("_").apply(Term::var(subject_name))) } else { - let condition = if tipo.is_int() { - Term::equals_integer() + let uplc_type = tipo.get_uplc_type(); + + 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(Term::var(subject_name)) - } else if tipo.is_bytearray() { - Term::equals_bytestring() + .apply(Term::var(subject_name)), + UplcType::String => Term::equals_string() .apply(checker) - .apply(Term::var(subject_name)) - } else if tipo.is_string() { - Term::equals_string() + .apply(Term::var(subject_name)), + UplcType::ByteString => Term::equals_bytestring() .apply(checker) - .apply(Term::var(subject_name)) - } else if tipo.is_list() || tipo.is_tuple() { - unreachable!() - } else { - Term::equals_integer().apply(checker).apply( + .apply(Term::var(subject_name)), + + UplcType::Data if tipo.is_data() => unimplemented!(), + UplcType::Data => Term::equals_integer().apply(checker).apply( Term::var( self.special_functions .use_function_uplc(CONSTR_INDEX_EXPOSER.to_string()), ) .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 - .if_then_else(then.delay(), Term::var("__other_clauses_delayed")) - .force(); - Some(term) + Some(condition.if_then_else(then.delay(), term).force()) } } Air::ListClauseGuard { diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index 7da7e0596..b12cca27f 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -359,38 +359,25 @@ pub fn handle_clause_guard(clause_guard: &TypedClauseGuard) -> AirTree { } pub fn get_generic_variant_name(t: &Rc) -> String { - if t.is_string() { - "_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() { - panic!("FOUND A POLYMORPHIC TYPE. EXPECTED MONOMORPHIC TYPE"); + let uplc_type = t.get_uplc_type(); + + match uplc_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") } - - full_type + UplcType::Data => "_data".to_string(), } } @@ -958,62 +945,54 @@ pub fn find_list_clause_or_default_first(clauses: &[TypedClause]) -> &TypedClaus } pub fn known_data_to_type(term: Term, field_type: &Type) -> Term { - if field_type.is_int() { - Term::un_i_data().apply(term) - } else if field_type.is_bytearray() { - Term::un_b_data().apply(term) - } else if field_type.is_void() { - Term::unit().lambda("_").apply(term) - } else if field_type.is_map() { - Term::unmap_data().apply(term) - } else if field_type.is_string() { - Term::Builtin(DefaultFunction::DecodeUtf8).apply(Term::un_b_data().apply(term)) - } else if field_type.is_pair() { - Term::mk_pair_data() + let uplc_type = field_type.get_uplc_type(); + + match uplc_type { + UplcType::Integer => Term::un_i_data().apply(term), + UplcType::ByteString => Term::un_b_data().apply(term), + UplcType::Bool => Term::less_than_integer() + .apply(Term::integer(0.into())) + .apply(Term::fst_pair().apply(Term::unconstr_data().apply(term))), + UplcType::String => Term::decode_utf8().apply(Term::un_b_data().apply(term)), + UplcType::Unit => Term::unit().lambda("_").apply(term), + UplcType::List(_) if field_type.is_map() => Term::unmap_data().apply(term), + 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::tail_list().apply(Term::var("__list_data")))) .lambda("__list_data") - .apply(Term::unlist_data().apply(term)) - } else if field_type.is_list() || field_type.is_tuple() { - Term::unlist_data().apply(term) - } else if field_type.is_bool() { - 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)) - } else if field_type.is_bls381_12_g2() { - Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(term)) - } else if field_type.is_ml_result() { - panic!("ML Result not supported") - } else { - term + .apply(Term::unlist_data().apply(term)), + UplcType::Data if field_type.is_data() => term, + UplcType::Data => term, + UplcType::Bls12_381G1Element => { + Term::bls12_381_g1_uncompress().apply(Term::un_b_data().apply(term)) + } + UplcType::Bls12_381G2Element => { + Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(term)) + } + UplcType::Bls12_381MlResult => panic!("ML Result not supported"), } } pub fn unknown_data_to_type(term: Term, field_type: &Type) -> Term { - if field_type.is_int() { - Term::un_i_data().apply(term) - } else if field_type.is_bytearray() { - Term::un_b_data().apply(term) - } else if field_type.is_void() { - Term::equals_integer() - .apply(Term::integer(0.into())) - .apply(Term::fst_pair().apply(Term::var("__pair__"))) - .delayed_if_then_else( - Term::snd_pair() - .apply(Term::var("__pair__")) - .delayed_choose_list(Term::unit(), Term::Error), - Term::Error, - ) - .lambda("__pair__") - .apply(Term::unconstr_data().apply(term)) - } else if field_type.is_map() { - Term::unmap_data().apply(term) - } 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() + let uplc_type = field_type.get_uplc_type(); + + match uplc_type { + UplcType::Integer => Term::un_i_data().apply(term), + UplcType::ByteString => Term::un_b_data().apply(term), + UplcType::String => Term::decode_utf8().apply(Term::un_b_data().apply(term)), + UplcType::List(_) if field_type.is_map() => Term::unmap_data().apply(term), + UplcType::List(_) => Term::unlist_data().apply(term), + UplcType::Data if field_type.is_data() => term, + UplcType::Data => term, + UplcType::Bls12_381G1Element => { + Term::bls12_381_g1_uncompress().apply(Term::un_b_data().apply(term)) + } + UplcType::Bls12_381G2Element => { + Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(term)) + } + UplcType::Bls12_381MlResult => panic!("ML Result not supported"), + UplcType::Pair(_, _) => Term::tail_list() .apply(Term::tail_list().apply(Term::var("__list_data"))) .delayed_choose_list( Term::mk_pair_data() @@ -1024,11 +1003,8 @@ pub fn unknown_data_to_type(term: Term, field_type: &Type) -> Term { Term::Error, ) .lambda("__list_data") - .apply(Term::unlist_data().apply(term)) - } else if field_type.is_list() || field_type.is_tuple() { - Term::unlist_data().apply(term) - } else if field_type.is_bool() { - Term::snd_pair() + .apply(Term::unlist_data().apply(term)), + UplcType::Bool => Term::snd_pair() .apply(Term::var("__pair__")) .delayed_choose_list( Term::equals_integer() @@ -1044,25 +1020,33 @@ pub fn unknown_data_to_type(term: Term, field_type: &Type) -> Term { Term::Error, ) .lambda("__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)) - } else if field_type.is_bls381_12_g2() { - Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(term)) - } else if field_type.is_ml_result() { - panic!("ML Result not supported") - } else { - term + .apply(Term::unconstr_data().apply(term)), + UplcType::Unit => Term::equals_integer() + .apply(Term::integer(0.into())) + .apply(Term::fst_pair().apply(Term::var("__pair__"))) + .delayed_if_then_else( + Term::snd_pair() + .apply(Term::var("__pair__")) + .delayed_choose_list(Term::unit(), Term::Error), + 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( term: Term, field_type: &Type, error_term: Term, ) -> Term { - if field_type.is_int() { - Term::var("__val") + let uplc_type = field_type.get_uplc_type(); + + match uplc_type { + UplcType::Integer => Term::var("__val") .delayed_choose_data( error_term.clone(), error_term.clone(), @@ -1071,9 +1055,8 @@ pub fn unknown_data_to_type_debug( error_term.clone(), ) .lambda("__val") - .apply(term) - } else if field_type.is_bytearray() { - Term::var("__val") + .apply(term), + UplcType::ByteString => Term::var("__val") .delayed_choose_data( 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")), ) .lambda("__val") - .apply(term) - } else if field_type.is_void() { - Term::var("__val") + .apply(term), + UplcType::String => Term::var("__val") .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::decode_utf8().apply(Term::un_b_data().apply(Term::var("__val"))), ) .lambda("__val") - .apply(term) - } else if field_type.is_map() { - Term::var("__val") + .apply(term), + + UplcType::List(_) if field_type.is_map() => Term::var("__val") .delayed_choose_data( error_term.clone(), Term::unmap_data().apply(Term::var("__val")), @@ -1112,21 +1086,51 @@ pub fn unknown_data_to_type_debug( error_term.clone(), ) .lambda("__val") - .apply(term) - } else if field_type.is_string() { - Term::var("__val") + .apply(term), + UplcType::List(_) => 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(), - Term::Builtin(DefaultFunction::DecodeUtf8) - .apply(Term::un_b_data().apply(Term::var("__val"))), ) .lambda("__val") - .apply(term) - } else if field_type.is_pair() { - Term::var("__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( + 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), + UplcType::Bls12_381G2Element => 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( error_term.clone(), error_term.clone(), @@ -1156,20 +1160,8 @@ pub fn unknown_data_to_type_debug( error_term.clone(), ) .lambda("__val") - .apply(term) - } else if field_type.is_list() || field_type.is_tuple() { - 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") + .apply(term), + UplcType::Bool => Term::var("__val") .delayed_choose_data( Term::snd_pair() .apply(Term::var("__pair__")) @@ -1194,44 +1186,25 @@ pub fn unknown_data_to_type_debug( error_term.clone(), ) .lambda("__val") - .apply(term) - } else if field_type.is_bls381_12_g1() { - Term::var("__val") + .apply(term), + UplcType::Unit => Term::var("__val") .delayed_choose_data( - 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"), + 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(), ) .lambda("__val") - .apply(term) + .apply(term), } } @@ -1323,25 +1296,24 @@ pub fn convert_constants_to_data(constants: Vec>) -> Vec, field_type: &Rc) -> Term { - if field_type.is_bytearray() { - Term::b_data().apply(term) - } else if field_type.is_int() { - Term::i_data().apply(term) - } else if field_type.is_void() { - term.choose_unit(Term::Constant( - UplcConstant::Data(PlutusData::Constr(Constr { - tag: convert_constr_to_tag(0).unwrap(), - any_constructor: None, - fields: vec![], - })) - .into(), - )) - } else if field_type.is_map() { - Term::map_data().apply(term) - } else if field_type.is_string() { - Term::b_data().apply(Term::Builtin(DefaultFunction::EncodeUtf8).apply(term)) - } else if field_type.is_pair() { - Term::list_data() + let uplc_type = field_type.get_uplc_type(); + + match uplc_type { + UplcType::Integer => Term::i_data().apply(term), + UplcType::String => Term::b_data().apply(Term::encode_utf8().apply(term)), + UplcType::ByteString => Term::b_data().apply(term), + UplcType::List(_) if field_type.is_map() => Term::map_data().apply(term), + UplcType::List(_) => Term::list_data().apply(term), + UplcType::Data if field_type.is_data() => term, + UplcType::Data => term, + UplcType::Bls12_381G1Element => { + Term::b_data().apply(Term::bls12_381_g1_compress().apply(term)) + } + UplcType::Bls12_381G2Element => { + Term::b_data().apply(Term::bls12_381_g2_compress().apply(term)) + } + UplcType::Bls12_381MlResult => panic!("ML Result not supported"), + UplcType::Pair(_, _) => Term::list_data() .apply( Term::mk_cons() .apply(Term::fst_pair().apply(Term::var("__pair"))) @@ -1352,11 +1324,18 @@ pub fn convert_type_to_data(term: Term, field_type: &Rc) -> Term Term::Constant( + UplcConstant::Data(PlutusData::Constr(Constr { + tag: convert_constr_to_tag(0).unwrap(), + any_constructor: None, + fields: vec![], + })) + .into(), + ) + .lambda("_") + .apply(term), + UplcType::Bool => term.if_then_else( Term::Constant( UplcConstant::Data(PlutusData::Constr(Constr { tag: convert_constr_to_tag(1).unwrap(), @@ -1373,15 +1352,7 @@ pub fn convert_type_to_data(term: Term, field_type: &Rc) -> Term bool { - self.is_bool() - || self.is_bytearray() - || self.is_int() - || self.is_string() - || self.is_void() - || self.is_data() + let uplc_type = self.get_uplc_type(); + match uplc_type { + UplcType::Bool + | UplcType::Integer + | UplcType::String + | 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 { @@ -471,7 +480,6 @@ impl Type { } } - // TODO: THIS WILL CHANGE DUE TO PAIRS pub fn get_uplc_type(&self) -> UplcType { if self.is_int() { UplcType::Integer @@ -481,6 +489,8 @@ impl Type { UplcType::String } else if self.is_bool() { UplcType::Bool + } else if self.is_void() { + UplcType::Unit } else if self.is_map() { UplcType::List(UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()).into()) } else if self.is_list() { diff --git a/crates/aiken-project/src/tests/gen_uplc.rs b/crates/aiken-project/src/tests/gen_uplc.rs index cc96d8549..195d104b2 100644 --- a/crates/aiken-project/src/tests/gen_uplc.rs +++ b/crates/aiken-project/src/tests/gen_uplc.rs @@ -3304,7 +3304,7 @@ fn acceptance_test_29_union_tuple() { src, Term::equals_data() .apply( - Term::map_data().apply( + Term::list_data().apply( Term::var("union") .lambda("union") .apply( @@ -3332,18 +3332,22 @@ fn acceptance_test_29_union_tuple() { ) .lambda("v") .apply( - Term::un_i_data() - .apply(Term::snd_pair().apply(Term::var("pair"))), + Term::un_i_data().apply(Term::head_list().apply( + Term::tail_list().apply(Term::var("tuple")), + )), ) .lambda("k") .apply( Term::un_b_data() - .apply(Term::fst_pair().apply(Term::var("pair"))), + .apply(Term::head_list().apply(Term::var("tuple"))), ) .lambda("rest") .apply(Term::tail_list().apply(Term::var("left"))) - .lambda("pair") - .apply(Term::head_list().apply(Term::var("left"))), + .lambda("tuple") + .apply( + Term::unlist_data() + .apply(Term::head_list().apply(Term::var("left"))), + ), ) .lambda("right") .lambda("left") @@ -3360,41 +3364,75 @@ fn acceptance_test_29_union_tuple() { .delayed_choose_list( Term::mk_cons() .apply( - Term::mk_pair_data() - .apply(Term::b_data().apply(Term::var("k"))) - .apply( - Term::i_data().apply(Term::var("v")), - ), + Term::list_data().apply( + Term::mk_cons() + .apply( + 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() .apply(Term::var("k")) .apply(Term::var("k2")) .delayed_if_then_else( Term::mk_cons() .apply( - Term::mk_pair_data() - .apply( - Term::b_data() - .apply(Term::var("k")), - ) - .apply( - Term::i_data() - .apply(Term::var("v")), - ), + Term::list_data().apply( + Term::mk_cons() + .apply( + 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::var("rest")), Term::mk_cons() .apply( - Term::mk_pair_data() - .apply( - Term::b_data() - .apply(Term::var("k2")), - ) - .apply( - Term::i_data() - .apply(Term::var("v2")), - ), + Term::list_data().apply( + Term::mk_cons() + .apply( + Term::b_data() + .apply(Term::var("k2")), + ) + .apply( + Term::mk_cons() + .apply( + Term::i_data() + .apply( + Term::var( + "v2", + ), + ), + ) + .apply( + Term::empty_list(), + ), + ), + ), ) .apply( Term::var("do_insert") @@ -3404,16 +3442,20 @@ fn acceptance_test_29_union_tuple() { ) .lambda("v2") .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") .apply(Term::un_b_data().apply( - Term::fst_pair().apply(Term::var("pair")), + Term::head_list().apply(Term::var("tuple")), )) .lambda("rest") .apply(Term::tail_list().apply(Term::var("elems"))) - .lambda("pair") - .apply(Term::head_list().apply(Term::var("elems"))), + .lambda("tuple") + .apply(Term::unlist_data().apply( + Term::head_list().apply(Term::var("elems")), + )), ) .lambda("elems") .lambda("do_insert"), @@ -3422,32 +3464,28 @@ fn acceptance_test_29_union_tuple() { .lambda("k") .lambda("elems"), ) - .apply(Term::map_values(vec![ - Constant::ProtoPair( - 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::list_values(vec![ + Constant::Data(Data::list(vec![ + Data::bytestring("foo".as_bytes().to_vec()), + Data::integer(42.into()), + ])), + Constant::Data(Data::list(vec![ + Data::bytestring("bar".as_bytes().to_vec()), + Data::integer(14.into()), + ])), ])) - .apply(Term::empty_map()), + .apply(Term::empty_list()), ), ) - .apply(Term::data(Data::map(vec![ - ( + .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, );