diff --git a/crates/aiken-lang/src/air.rs b/crates/aiken-lang/src/air.rs index 150c5266..6b845114 100644 --- a/crates/aiken-lang/src/air.rs +++ b/crates/aiken-lang/src/air.rs @@ -125,6 +125,10 @@ pub enum Air { complex_clause: bool, }, + WrapClause { + scope: Vec, + }, + TupleClause { scope: Vec, tipo: Arc, @@ -250,6 +254,8 @@ impl Air { | Air::When { scope, .. } | Air::Clause { scope, .. } | Air::ListClause { scope, .. } + | Air::TupleClause { scope, .. } + | Air::WrapClause { scope } | Air::ClauseGuard { scope, .. } | Air::ListClauseGuard { scope, .. } | Air::Discard { scope } @@ -265,8 +271,7 @@ impl Air { | Air::UnOp { scope, .. } | Air::Trace { scope, .. } | Air::TupleAccessor { scope, .. } - | Air::TupleIndex { scope, .. } - | Air::TupleClause { scope, .. } => scope.to_vec(), + | Air::TupleIndex { scope, .. } => scope.to_vec(), } } diff --git a/crates/aiken-lang/src/builder.rs b/crates/aiken-lang/src/builder.rs index 4c791610..5f140886 100644 --- a/crates/aiken-lang/src/builder.rs +++ b/crates/aiken-lang/src/builder.rs @@ -61,7 +61,7 @@ pub enum ClauseProperties { needs_constr_var: bool, is_complex_clause: bool, original_subject_name: String, - current_index: usize, + current_index: i64, }, TupleClause { clause_var_name: String, @@ -80,7 +80,7 @@ impl ClauseProperties { needs_constr_var: false, is_complex_clause: false, original_subject_name: subject_name, - current_index: 0, + current_index: -1, } } else if t.is_tuple() { ClauseProperties::TupleClause { diff --git a/crates/aiken-lang/src/uplc.rs b/crates/aiken-lang/src/uplc.rs index 7a550f19..69df1453 100644 --- a/crates/aiken-lang/src/uplc.rs +++ b/crates/aiken-lang/src/uplc.rs @@ -645,7 +645,14 @@ impl<'a> CodeGenerator<'a> { current_index, .. } => { - let current_clause_index = *current_index; + let current_clause_index = + if let Pattern::List { elements, .. } = &clause.pattern[0] { + elements.len() + } else { + unreachable!() + }; + + let prev_index = *current_index; let subject_name = if current_clause_index == 0 { original_subject_name.clone() @@ -665,20 +672,36 @@ impl<'a> CodeGenerator<'a> { let next_tail = if index == clauses.len() - 1 { None } else { - Some(format!("__tail_{}", current_clause_index)) + let next_list_size = if let Pattern::List { elements, .. } = + &clauses[index + 1].pattern[0] + { + elements.len() + } else { + unreachable!() + }; + + if next_list_size == current_clause_index { + None + } else { + Some(format!("__tail_{}", current_clause_index)) + } }; - ir_stack.push(Air::ListClause { - scope, - tipo: subject_type.clone(), - tail_name: subject_name, - next_tail_name: next_tail, - complex_clause: *clause_properties.is_complex_clause(), - }); + if current_clause_index as i64 == prev_index { + ir_stack.push(Air::WrapClause { scope }); + } else { + ir_stack.push(Air::ListClause { + scope, + tipo: subject_type.clone(), + tail_name: subject_name, + next_tail_name: next_tail, + complex_clause: *clause_properties.is_complex_clause(), + }); + } match clause_properties { ClauseProperties::ListClause { current_index, .. } => { - *current_index += 1; + *current_index = current_clause_index as i64; } _ => unreachable!(), } @@ -1245,24 +1268,18 @@ impl<'a> CodeGenerator<'a> { needs_constr_var: false, is_complex_clause: false, original_subject_name: item_name.clone(), - current_index: index, + current_index: index as i64, }; let tail_name = format!("{}_{}", new_tail_name, index); if elements.len() - 1 == index { if tail.is_some() { - let tail_name = match *tail.clone().unwrap() { - Pattern::Var { name, .. } => name, - Pattern::Discard { .. } => "_".to_string(), - _ => unreachable!(), - }; - pattern_vec.push(Air::ListClauseGuard { scope: scope.clone(), tipo: pattern_type.clone(), tail_name: prev_tail_name, - next_tail_name: Some(tail_name), + next_tail_name: None, inverse: true, }); @@ -1331,7 +1348,6 @@ impl<'a> CodeGenerator<'a> { } } - // self.when_recursive_ir(a); Some(item_name) } a @ Pattern::Constructor { @@ -3796,6 +3812,25 @@ impl<'a> CodeGenerator<'a> { arg_stack.push(term); } + + Air::WrapClause { .. } => { + let _ = arg_stack.pop().unwrap(); + + let mut term = arg_stack.pop().unwrap(); + let arg = arg_stack.pop().unwrap(); + + term = apply_wrap( + Term::Lambda { + parameter_name: Name { + text: "__other_clauses_delayed".into(), + unique: 0.into(), + }, + body: term.into(), + }, + Term::Delay(arg.into()), + ); + arg_stack.push(term); + } Air::ClauseGuard { subject_name, tipo, .. } => { diff --git a/examples/acceptance_tests/046/lib/tests.ak b/examples/acceptance_tests/046/lib/tests.ak index 009e1272..71276553 100644 --- a/examples/acceptance_tests/046/lib/tests.ak +++ b/examples/acceptance_tests/046/lib/tests.ak @@ -1,9 +1,9 @@ test sort_by_1() { let xs = [[4, 3, 2, 1], [2, 3, 4, 5]] when xs is { - [[], ys] -> True - [xs, []] -> True + [[], ys] -> False + [xs, []] -> False [[x, ..xs2], [y, ..ys2]] -> True - _ -> True + _ -> False } }