fix list clauses with guards and add more tests
This commit is contained in:
		
							parent
							
								
									f4d0f231d7
								
							
						
					
					
						commit
						2456801b17
					
				| 
						 | 
				
			
			@ -24,9 +24,9 @@ use crate::{
 | 
			
		|||
    expr::TypedExpr,
 | 
			
		||||
    gen_uplc::builder::{
 | 
			
		||||
        convert_opaque_type, erase_opaque_type_operations, find_and_replace_generics,
 | 
			
		||||
        get_arg_type_name, get_generic_id_and_type, get_variant_name, monomorphize,
 | 
			
		||||
        pattern_has_conditions, wrap_as_multi_validator, wrap_validator_condition, CodeGenFunction,
 | 
			
		||||
        SpecificClause,
 | 
			
		||||
        find_list_clause_or_default_first, get_arg_type_name, get_generic_id_and_type,
 | 
			
		||||
        get_variant_name, monomorphize, pattern_has_conditions, wrap_as_multi_validator,
 | 
			
		||||
        wrap_validator_condition, CodeGenFunction, SpecificClause,
 | 
			
		||||
    },
 | 
			
		||||
    tipo::{
 | 
			
		||||
        ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
 | 
			
		||||
| 
						 | 
				
			
			@ -1703,8 +1703,12 @@ impl<'a> CodeGenerator<'a> {
 | 
			
		|||
                        );
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    assert!(!elements.is_empty() || tail.is_none());
 | 
			
		||||
                    let elements_len = elements.len() + usize::from(tail.is_none()) - 1;
 | 
			
		||||
                    let current_checked_index = *checked_index;
 | 
			
		||||
 | 
			
		||||
                    let tail_name = defined_tails
 | 
			
		||||
                        .last()
 | 
			
		||||
                        .get(elements_len)
 | 
			
		||||
                        .cloned()
 | 
			
		||||
                        .unwrap_or(props.original_subject_name.clone());
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1712,8 +1716,8 @@ impl<'a> CodeGenerator<'a> {
 | 
			
		|||
                        if rest_clauses.is_empty() {
 | 
			
		||||
                            None
 | 
			
		||||
                        } else {
 | 
			
		||||
                            let next_clause = &rest_clauses[0];
 | 
			
		||||
                            let mut next_clause_pattern = &rest_clauses[0].pattern;
 | 
			
		||||
                            let next_clause = find_list_clause_or_default_first(rest_clauses);
 | 
			
		||||
                            let mut next_clause_pattern = &next_clause.pattern;
 | 
			
		||||
 | 
			
		||||
                            if let Pattern::Assign { pattern, .. } = next_clause_pattern {
 | 
			
		||||
                                next_clause_pattern = pattern;
 | 
			
		||||
| 
						 | 
				
			
			@ -1729,6 +1733,7 @@ impl<'a> CodeGenerator<'a> {
 | 
			
		|||
 | 
			
		||||
                            if (*defined_tails_index as usize) < next_elements_len {
 | 
			
		||||
                                *defined_tails_index += 1;
 | 
			
		||||
                                let current_defined_tail = defined_tails.last().unwrap().clone();
 | 
			
		||||
 | 
			
		||||
                                defined_tails.push(format!(
 | 
			
		||||
                                    "tail_index_{}_span_{}_{}",
 | 
			
		||||
| 
						 | 
				
			
			@ -1737,11 +1742,14 @@ impl<'a> CodeGenerator<'a> {
 | 
			
		|||
                                    next_clause.pattern.location().end
 | 
			
		||||
                                ));
 | 
			
		||||
 | 
			
		||||
                                Some(format!(
 | 
			
		||||
                                Some((
 | 
			
		||||
                                    current_defined_tail,
 | 
			
		||||
                                    format!(
 | 
			
		||||
                                        "tail_index_{}_span_{}_{}",
 | 
			
		||||
                                        *defined_tails_index,
 | 
			
		||||
                                        next_clause.pattern.location().start,
 | 
			
		||||
                                        next_clause.pattern.location().end
 | 
			
		||||
                                    ),
 | 
			
		||||
                                ))
 | 
			
		||||
                            } else {
 | 
			
		||||
                                None
 | 
			
		||||
| 
						 | 
				
			
			@ -1754,9 +1762,6 @@ impl<'a> CodeGenerator<'a> {
 | 
			
		|||
                        is_wild_card_elems_clause =
 | 
			
		||||
                            is_wild_card_elems_clause && !pattern_has_conditions(element);
 | 
			
		||||
                    }
 | 
			
		||||
                    assert!(!elements.is_empty() || tail.is_none());
 | 
			
		||||
                    let elements_len = elements.len() + usize::from(tail.is_none()) - 1;
 | 
			
		||||
                    let current_checked_index = *checked_index;
 | 
			
		||||
 | 
			
		||||
                    if *checked_index < elements_len.try_into().unwrap()
 | 
			
		||||
                        && is_wild_card_elems_clause
 | 
			
		||||
| 
						 | 
				
			
			@ -1784,7 +1789,9 @@ impl<'a> CodeGenerator<'a> {
 | 
			
		|||
 | 
			
		||||
                    let complex_clause = props.complex_clause;
 | 
			
		||||
 | 
			
		||||
                    if current_checked_index < elements_len.try_into().unwrap() {
 | 
			
		||||
                    if current_checked_index < elements_len.try_into().unwrap()
 | 
			
		||||
                        || next_tail_name.is_some()
 | 
			
		||||
                    {
 | 
			
		||||
                        AirTree::list_clause(
 | 
			
		||||
                            tail_name,
 | 
			
		||||
                            subject_tipo.clone(),
 | 
			
		||||
| 
						 | 
				
			
			@ -3996,9 +4003,9 @@ impl<'a> CodeGenerator<'a> {
 | 
			
		|||
                let body = arg_stack.pop().unwrap();
 | 
			
		||||
                let mut term = arg_stack.pop().unwrap();
 | 
			
		||||
 | 
			
		||||
                let arg = if let Some(next_tail_name) = next_tail_name {
 | 
			
		||||
                let arg = if let Some((current_tail, next_tail_name)) = next_tail_name {
 | 
			
		||||
                    term.lambda(next_tail_name)
 | 
			
		||||
                        .apply(Term::tail_list().apply(Term::var(tail_name.clone())))
 | 
			
		||||
                        .apply(Term::tail_list().apply(Term::var(current_tail.clone())))
 | 
			
		||||
                } else {
 | 
			
		||||
                    term
 | 
			
		||||
                };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -97,7 +97,7 @@ pub enum Air {
 | 
			
		|||
    ListClause {
 | 
			
		||||
        subject_tipo: Arc<Type>,
 | 
			
		||||
        tail_name: String,
 | 
			
		||||
        next_tail_name: Option<String>,
 | 
			
		||||
        next_tail_name: Option<(String, String)>,
 | 
			
		||||
        complex_clause: bool,
 | 
			
		||||
    },
 | 
			
		||||
    WrapClause,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -810,7 +810,18 @@ pub fn rearrange_list_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
 | 
			
		|||
        .into_iter()
 | 
			
		||||
        .enumerate()
 | 
			
		||||
        .sorted_by(|(index1, clause1), (index2, clause2)| {
 | 
			
		||||
            let clause1_len = match &clause1.pattern {
 | 
			
		||||
            let mut clause_pattern1 = &clause1.pattern;
 | 
			
		||||
            let mut clause_pattern2 = &clause2.pattern;
 | 
			
		||||
 | 
			
		||||
            if let Pattern::Assign { pattern, .. } = clause_pattern1 {
 | 
			
		||||
                clause_pattern1 = pattern;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if let Pattern::Assign { pattern, .. } = clause_pattern2 {
 | 
			
		||||
                clause_pattern2 = pattern;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let clause1_len = match clause_pattern1 {
 | 
			
		||||
                Pattern::List { elements, tail, .. } => {
 | 
			
		||||
                    Some(elements.len() + usize::from(tail.is_some() && clause1.guard.is_none()))
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -818,7 +829,7 @@ pub fn rearrange_list_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
 | 
			
		|||
                _ => None,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            let clause2_len = match &clause2.pattern {
 | 
			
		||||
            let clause2_len = match clause_pattern2 {
 | 
			
		||||
                Pattern::List { elements, tail, .. } => {
 | 
			
		||||
                    Some(elements.len() + usize::from(tail.is_some() && clause2.guard.is_none()))
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -1013,6 +1024,19 @@ pub fn rearrange_list_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
 | 
			
		|||
    final_clauses
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn find_list_clause_or_default_first(clauses: &[TypedClause]) -> &TypedClause {
 | 
			
		||||
    assert!(!clauses.is_empty());
 | 
			
		||||
 | 
			
		||||
    clauses
 | 
			
		||||
        .iter()
 | 
			
		||||
        .find(|clause| match &clause.pattern {
 | 
			
		||||
            Pattern::List { .. } => true,
 | 
			
		||||
            Pattern::Assign { pattern, .. } if matches!(&**pattern, Pattern::List { .. }) => true,
 | 
			
		||||
            _ => false,
 | 
			
		||||
        })
 | 
			
		||||
        .unwrap_or(&clauses[0])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn convert_data_to_type(term: Term<Name>, field_type: &Arc<Type>) -> Term<Name> {
 | 
			
		||||
    if field_type.is_int() {
 | 
			
		||||
        Term::un_i_data().apply(term)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -282,7 +282,7 @@ pub enum AirExpression {
 | 
			
		|||
    ListClause {
 | 
			
		||||
        subject_tipo: Arc<Type>,
 | 
			
		||||
        tail_name: String,
 | 
			
		||||
        next_tail_name: Option<String>,
 | 
			
		||||
        next_tail_name: Option<(String, String)>,
 | 
			
		||||
        complex_clause: bool,
 | 
			
		||||
        then: Box<AirTree>,
 | 
			
		||||
        otherwise: Box<AirTree>,
 | 
			
		||||
| 
						 | 
				
			
			@ -546,7 +546,7 @@ impl AirTree {
 | 
			
		|||
        subject_tipo: Arc<Type>,
 | 
			
		||||
        then: AirTree,
 | 
			
		||||
        otherwise: AirTree,
 | 
			
		||||
        next_tail_name: Option<String>,
 | 
			
		||||
        next_tail_name: Option<(String, String)>,
 | 
			
		||||
        complex_clause: bool,
 | 
			
		||||
    ) -> AirTree {
 | 
			
		||||
        AirTree::Expression(AirExpression::ListClause {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4523,3 +4523,413 @@ fn list_clause_with_guard() {
 | 
			
		|||
        false,
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn list_clause_with_guard2() {
 | 
			
		||||
    let src = r#"
 | 
			
		||||
      fn do_init(self: List<Int>) -> List<Int> {
 | 
			
		||||
        when self is {
 | 
			
		||||
          [] -> fail @"unreachable"
 | 
			
		||||
          [_] ->
 | 
			
		||||
            []
 | 
			
		||||
          [a, x] -> {
 | 
			
		||||
            [a]
 | 
			
		||||
          }
 | 
			
		||||
          [a] if a > 10 -> []
 | 
			
		||||
          [a, b, ..c] -> {
 | 
			
		||||
            c
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      test init_3() {
 | 
			
		||||
        do_init([1, 3]) == [1]
 | 
			
		||||
      }
 | 
			
		||||
    "#;
 | 
			
		||||
 | 
			
		||||
    assert_uplc(
 | 
			
		||||
        src,
 | 
			
		||||
        Term::equals_data()
 | 
			
		||||
            .apply(
 | 
			
		||||
                Term::list_data().apply(
 | 
			
		||||
                    Term::var("do_init")
 | 
			
		||||
                        .lambda("do_init")
 | 
			
		||||
                        .apply(
 | 
			
		||||
                            Term::var("self")
 | 
			
		||||
                                .delayed_choose_list(
 | 
			
		||||
                                    Term::Error.trace(Term::string("unreachable")),
 | 
			
		||||
                                    Term::var("tail_1")
 | 
			
		||||
                                        .delayed_choose_list(
 | 
			
		||||
                                            Term::empty_list(),
 | 
			
		||||
                                            Term::var("tail_1")
 | 
			
		||||
                                                .choose_list(
 | 
			
		||||
                                                    Term::var("clause_guard")
 | 
			
		||||
                                                        .if_else(
 | 
			
		||||
                                                            Term::empty_list().delay(),
 | 
			
		||||
                                                            Term::var("clauses_delayed"),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .force()
 | 
			
		||||
                                                        .lambda("clause_guard")
 | 
			
		||||
                                                        .apply(
 | 
			
		||||
                                                            Term::less_than_integer()
 | 
			
		||||
                                                                .apply(Term::integer(10.into()))
 | 
			
		||||
                                                                .apply(Term::var("a")),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .lambda("a")
 | 
			
		||||
                                                        .apply(
 | 
			
		||||
                                                            Term::un_i_data().apply(
 | 
			
		||||
                                                                Term::head_list()
 | 
			
		||||
                                                                    .apply(Term::var("self")),
 | 
			
		||||
                                                            ),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .delay(),
 | 
			
		||||
                                                    Term::var("clauses_delayed"),
 | 
			
		||||
                                                )
 | 
			
		||||
                                                .force()
 | 
			
		||||
                                                .lambda("clauses_delayed")
 | 
			
		||||
                                                .apply(
 | 
			
		||||
                                                    Term::var("tail_2")
 | 
			
		||||
                                                        .delayed_choose_list(
 | 
			
		||||
                                                            Term::mk_cons()
 | 
			
		||||
                                                                .apply(
 | 
			
		||||
                                                                    Term::i_data()
 | 
			
		||||
                                                                        .apply(Term::var("a")),
 | 
			
		||||
                                                                )
 | 
			
		||||
                                                                .apply(Term::empty_list())
 | 
			
		||||
                                                                .lambda("x")
 | 
			
		||||
                                                                .apply(
 | 
			
		||||
                                                                    Term::un_i_data().apply(
 | 
			
		||||
                                                                        Term::head_list().apply(
 | 
			
		||||
                                                                            Term::var("tail_1"),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                                                )
 | 
			
		||||
                                                                .lambda("a")
 | 
			
		||||
                                                                .apply(
 | 
			
		||||
                                                                    Term::un_i_data().apply(
 | 
			
		||||
                                                                        Term::head_list().apply(
 | 
			
		||||
                                                                            Term::var("self"),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                                                ),
 | 
			
		||||
                                                            Term::var("c").lambda("c").apply(
 | 
			
		||||
                                                                Term::tail_list()
 | 
			
		||||
                                                                    .apply(Term::var("tail_1"))
 | 
			
		||||
                                                                    .lambda("b")
 | 
			
		||||
                                                                    .apply(Term::un_i_data().apply(
 | 
			
		||||
                                                                        Term::head_list().apply(
 | 
			
		||||
                                                                            Term::var("tail_1"),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ))
 | 
			
		||||
                                                                    .lambda("a")
 | 
			
		||||
                                                                    .apply(
 | 
			
		||||
                                                                        Term::un_i_data().apply(
 | 
			
		||||
                                                                            Term::head_list()
 | 
			
		||||
                                                                                .apply(Term::var(
 | 
			
		||||
                                                                                    "self",
 | 
			
		||||
                                                                                )),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                                            ),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .lambda("tail_2")
 | 
			
		||||
                                                        .apply(
 | 
			
		||||
                                                            Term::tail_list()
 | 
			
		||||
                                                                .apply(Term::var("tail_1")),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .delay(),
 | 
			
		||||
                                                ),
 | 
			
		||||
                                        )
 | 
			
		||||
                                        .lambda("tail_1")
 | 
			
		||||
                                        .apply(Term::tail_list().apply(Term::var("self"))),
 | 
			
		||||
                                )
 | 
			
		||||
                                .lambda("self"),
 | 
			
		||||
                        )
 | 
			
		||||
                        .apply(Term::list_values(vec![
 | 
			
		||||
                            Constant::Data(Data::integer(1.into())),
 | 
			
		||||
                            Constant::Data(Data::integer(3.into())),
 | 
			
		||||
                        ])),
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
            .apply(Term::data(Data::list(vec![Data::integer(1.into())]))),
 | 
			
		||||
        false,
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn list_clause_with_guard3() {
 | 
			
		||||
    let src = r#"
 | 
			
		||||
      fn do_init(self: List<Int>) -> List<Int> {
 | 
			
		||||
        when self is {
 | 
			
		||||
          [] -> fail @"unreachable"
 | 
			
		||||
          [_] ->
 | 
			
		||||
            []
 | 
			
		||||
          [a, x] -> {
 | 
			
		||||
            [a]
 | 
			
		||||
          }
 | 
			
		||||
          [a, ..g] if a > 10 -> g
 | 
			
		||||
          [a, b, ..c] -> {
 | 
			
		||||
            c
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      test init_3() {
 | 
			
		||||
        do_init([1, 3]) == [1]
 | 
			
		||||
      }
 | 
			
		||||
    "#;
 | 
			
		||||
 | 
			
		||||
    assert_uplc(
 | 
			
		||||
        src,
 | 
			
		||||
        Term::equals_data()
 | 
			
		||||
            .apply(
 | 
			
		||||
                Term::list_data().apply(
 | 
			
		||||
                    Term::var("do_init")
 | 
			
		||||
                        .lambda("do_init")
 | 
			
		||||
                        .apply(
 | 
			
		||||
                            Term::var("self")
 | 
			
		||||
                                .delayed_choose_list(
 | 
			
		||||
                                    Term::Error.trace(Term::string("unreachable")),
 | 
			
		||||
                                    Term::var("tail_1")
 | 
			
		||||
                                        .delayed_choose_list(
 | 
			
		||||
                                            Term::empty_list(),
 | 
			
		||||
                                            Term::var("self")
 | 
			
		||||
                                                .choose_list(
 | 
			
		||||
                                                    Term::var("clause_guard")
 | 
			
		||||
                                                        .if_else(
 | 
			
		||||
                                                            Term::var("g").delay(),
 | 
			
		||||
                                                            Term::var("clauses_delayed"),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .force()
 | 
			
		||||
                                                        .lambda("clause_guard")
 | 
			
		||||
                                                        .apply(
 | 
			
		||||
                                                            Term::less_than_integer()
 | 
			
		||||
                                                                .apply(Term::integer(10.into()))
 | 
			
		||||
                                                                .apply(Term::var("a")),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .lambda("g")
 | 
			
		||||
                                                        .apply(
 | 
			
		||||
                                                            Term::tail_list()
 | 
			
		||||
                                                                .apply(Term::var("self")),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .lambda("a")
 | 
			
		||||
                                                        .apply(
 | 
			
		||||
                                                            Term::un_i_data().apply(
 | 
			
		||||
                                                                Term::head_list()
 | 
			
		||||
                                                                    .apply(Term::var("self")),
 | 
			
		||||
                                                            ),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .delay(),
 | 
			
		||||
                                                    Term::var("clauses_delayed"),
 | 
			
		||||
                                                )
 | 
			
		||||
                                                .force()
 | 
			
		||||
                                                .lambda("clauses_delayed")
 | 
			
		||||
                                                .apply(
 | 
			
		||||
                                                    Term::var("tail_2")
 | 
			
		||||
                                                        .delayed_choose_list(
 | 
			
		||||
                                                            Term::mk_cons()
 | 
			
		||||
                                                                .apply(
 | 
			
		||||
                                                                    Term::i_data()
 | 
			
		||||
                                                                        .apply(Term::var("a")),
 | 
			
		||||
                                                                )
 | 
			
		||||
                                                                .apply(Term::empty_list())
 | 
			
		||||
                                                                .lambda("x")
 | 
			
		||||
                                                                .apply(
 | 
			
		||||
                                                                    Term::un_i_data().apply(
 | 
			
		||||
                                                                        Term::head_list().apply(
 | 
			
		||||
                                                                            Term::var("tail_1"),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                                                )
 | 
			
		||||
                                                                .lambda("a")
 | 
			
		||||
                                                                .apply(
 | 
			
		||||
                                                                    Term::un_i_data().apply(
 | 
			
		||||
                                                                        Term::head_list().apply(
 | 
			
		||||
                                                                            Term::var("self"),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                                                ),
 | 
			
		||||
                                                            Term::var("c").lambda("c").apply(
 | 
			
		||||
                                                                Term::tail_list()
 | 
			
		||||
                                                                    .apply(Term::var("tail_1"))
 | 
			
		||||
                                                                    .lambda("b")
 | 
			
		||||
                                                                    .apply(Term::un_i_data().apply(
 | 
			
		||||
                                                                        Term::head_list().apply(
 | 
			
		||||
                                                                            Term::var("tail_1"),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ))
 | 
			
		||||
                                                                    .lambda("a")
 | 
			
		||||
                                                                    .apply(
 | 
			
		||||
                                                                        Term::un_i_data().apply(
 | 
			
		||||
                                                                            Term::head_list()
 | 
			
		||||
                                                                                .apply(Term::var(
 | 
			
		||||
                                                                                    "self",
 | 
			
		||||
                                                                                )),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                                            ),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .lambda("tail_2")
 | 
			
		||||
                                                        .apply(
 | 
			
		||||
                                                            Term::tail_list()
 | 
			
		||||
                                                                .apply(Term::var("tail_1")),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .delay(),
 | 
			
		||||
                                                ),
 | 
			
		||||
                                        )
 | 
			
		||||
                                        .lambda("tail_1")
 | 
			
		||||
                                        .apply(Term::tail_list().apply(Term::var("self"))),
 | 
			
		||||
                                )
 | 
			
		||||
                                .lambda("self"),
 | 
			
		||||
                        )
 | 
			
		||||
                        .apply(Term::list_values(vec![
 | 
			
		||||
                            Constant::Data(Data::integer(1.into())),
 | 
			
		||||
                            Constant::Data(Data::integer(3.into())),
 | 
			
		||||
                        ])),
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
            .apply(Term::data(Data::list(vec![Data::integer(1.into())]))),
 | 
			
		||||
        false,
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn list_clause_with_assign() {
 | 
			
		||||
    let src = r#"
 | 
			
		||||
      fn do_init(self: List<Int>) -> List<Int> {
 | 
			
		||||
        when self is {
 | 
			
		||||
          [] -> fail @"unreachable"
 | 
			
		||||
          [_] as a ->
 | 
			
		||||
            a
 | 
			
		||||
          [a, x] if x > 2 -> {
 | 
			
		||||
            [a]
 | 
			
		||||
          }
 | 
			
		||||
          [a, x] -> {
 | 
			
		||||
            [a]
 | 
			
		||||
          }
 | 
			
		||||
          [a, b, ..c] -> {
 | 
			
		||||
            c
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      test init_3() {
 | 
			
		||||
        do_init([1, 3]) == [1]
 | 
			
		||||
      }
 | 
			
		||||
    "#;
 | 
			
		||||
 | 
			
		||||
    assert_uplc(
 | 
			
		||||
        src,
 | 
			
		||||
        Term::equals_data()
 | 
			
		||||
            .apply(
 | 
			
		||||
                Term::list_data().apply(
 | 
			
		||||
                    Term::var("do_init")
 | 
			
		||||
                        .lambda("do_init")
 | 
			
		||||
                        .apply(
 | 
			
		||||
                            Term::var("self")
 | 
			
		||||
                                .delayed_choose_list(
 | 
			
		||||
                                    Term::Error.trace(Term::string("unreachable")),
 | 
			
		||||
                                    Term::var("tail_1")
 | 
			
		||||
                                        .delayed_choose_list(
 | 
			
		||||
                                            Term::empty_list(),
 | 
			
		||||
                                            Term::var("tail_2")
 | 
			
		||||
                                                .choose_list(
 | 
			
		||||
                                                    Term::var("clause_guard")
 | 
			
		||||
                                                        .if_else(
 | 
			
		||||
                                                            Term::mk_cons()
 | 
			
		||||
                                                                .apply(
 | 
			
		||||
                                                                    Term::i_data()
 | 
			
		||||
                                                                        .apply(Term::var("a")),
 | 
			
		||||
                                                                )
 | 
			
		||||
                                                                .apply(Term::empty_list())
 | 
			
		||||
                                                                .delay(),
 | 
			
		||||
                                                            Term::var("clauses_delayed"),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .force()
 | 
			
		||||
                                                        .lambda("clause_guard")
 | 
			
		||||
                                                        .apply(
 | 
			
		||||
                                                            Term::less_than_integer()
 | 
			
		||||
                                                                .apply(Term::integer(2.into()))
 | 
			
		||||
                                                                .apply(Term::var("x")),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .lambda("x")
 | 
			
		||||
                                                        .apply(
 | 
			
		||||
                                                            Term::un_i_data().apply(
 | 
			
		||||
                                                                Term::head_list()
 | 
			
		||||
                                                                    .apply(Term::var("tail_1")),
 | 
			
		||||
                                                            ),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .lambda("a")
 | 
			
		||||
                                                        .apply(
 | 
			
		||||
                                                            Term::un_i_data().apply(
 | 
			
		||||
                                                                Term::head_list()
 | 
			
		||||
                                                                    .apply(Term::var("self")),
 | 
			
		||||
                                                            ),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .delay(),
 | 
			
		||||
                                                    Term::var("clauses_delayed"),
 | 
			
		||||
                                                )
 | 
			
		||||
                                                .force()
 | 
			
		||||
                                                .lambda("clauses_delayed")
 | 
			
		||||
                                                .apply(
 | 
			
		||||
                                                    Term::var("tail_2")
 | 
			
		||||
                                                        .delayed_choose_list(
 | 
			
		||||
                                                            Term::empty_list()
 | 
			
		||||
                                                                .lambda("b")
 | 
			
		||||
                                                                .apply(
 | 
			
		||||
                                                                    Term::un_i_data().apply(
 | 
			
		||||
                                                                        Term::head_list().apply(
 | 
			
		||||
                                                                            Term::var("tail_1"),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                                                )
 | 
			
		||||
                                                                .lambda("a")
 | 
			
		||||
                                                                .apply(
 | 
			
		||||
                                                                    Term::un_i_data().apply(
 | 
			
		||||
                                                                        Term::head_list().apply(
 | 
			
		||||
                                                                            Term::var("self"),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                                                ),
 | 
			
		||||
                                                            Term::var("c").lambda("c").apply(
 | 
			
		||||
                                                                Term::tail_list()
 | 
			
		||||
                                                                    .apply(Term::var("tail_1"))
 | 
			
		||||
                                                                    .lambda("b")
 | 
			
		||||
                                                                    .apply(Term::un_i_data().apply(
 | 
			
		||||
                                                                        Term::head_list().apply(
 | 
			
		||||
                                                                            Term::var("tail_1"),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ))
 | 
			
		||||
                                                                    .lambda("a")
 | 
			
		||||
                                                                    .apply(
 | 
			
		||||
                                                                        Term::un_i_data().apply(
 | 
			
		||||
                                                                            Term::head_list()
 | 
			
		||||
                                                                                .apply(Term::var(
 | 
			
		||||
                                                                                    "self",
 | 
			
		||||
                                                                                )),
 | 
			
		||||
                                                                        ),
 | 
			
		||||
                                                                    ),
 | 
			
		||||
                                                            ),
 | 
			
		||||
                                                        )
 | 
			
		||||
                                                        .delay(),
 | 
			
		||||
                                                )
 | 
			
		||||
                                                .lambda("tail_2")
 | 
			
		||||
                                                .apply(
 | 
			
		||||
                                                    Term::tail_list().apply(Term::var("tail_1")),
 | 
			
		||||
                                                ),
 | 
			
		||||
                                        )
 | 
			
		||||
                                        .lambda("tail_1")
 | 
			
		||||
                                        .apply(Term::tail_list().apply(Term::var("self"))),
 | 
			
		||||
                                )
 | 
			
		||||
                                .lambda("self"),
 | 
			
		||||
                        )
 | 
			
		||||
                        .apply(Term::list_values(vec![
 | 
			
		||||
                            Constant::Data(Data::integer(1.into())),
 | 
			
		||||
                            Constant::Data(Data::integer(3.into())),
 | 
			
		||||
                        ])),
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
            .apply(Term::data(Data::list(vec![Data::integer(1.into())]))),
 | 
			
		||||
        false,
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue