diff --git a/crates/aiken-lang/src/uplc.rs b/crates/aiken-lang/src/uplc.rs index 1d8fd79c..c9817361 100644 --- a/crates/aiken-lang/src/uplc.rs +++ b/crates/aiken-lang/src/uplc.rs @@ -764,12 +764,12 @@ impl<'a> CodeGenerator<'a> { current_index, .. } => { - let current_clause_index = - if let Pattern::List { elements, .. } = &clause.pattern[0] { - elements.len() + let (current_clause_index, has_tail) = + if let Pattern::List { elements, tail, .. } = &clause.pattern[0] { + (elements.len(), tail.is_some()) } else if let Pattern::Assign { pattern, .. } = &clause.pattern[0] { - if let Pattern::List { elements, .. } = pattern.as_ref() { - elements.len() + if let Pattern::List { elements, tail, .. } = pattern.as_ref() { + (elements.len(), tail.is_some()) } else { unreachable!("{:#?}", pattern) } @@ -820,7 +820,9 @@ impl<'a> CodeGenerator<'a> { } }; - if current_clause_index as i64 == prev_index { + let minus_tail = if has_tail { 1 } else { 0 }; + + if current_clause_index as i64 - minus_tail == prev_index { ir_stack.push(Air::WrapClause { scope }); } else { ir_stack.push(Air::ListClause { @@ -1121,7 +1123,9 @@ impl<'a> CodeGenerator<'a> { Pattern::Var { name, .. } => { tail_name = name.clone(); } - Pattern::Discard { .. } => {} + Pattern::Discard { .. } => { + tail_name = "_".to_string(); + } _ => unreachable!("Patterns in tail of list should not allow this"), } } @@ -1149,11 +1153,17 @@ impl<'a> CodeGenerator<'a> { format!("__tail_{}", elements.len() - 2) }; + let tail = if &tail_name == "_" { + None + } else { + Some((tail_var, tail_name)) + }; + pattern_vec.push(Air::ListExpose { scope, tipo: tipo.clone().into(), tail_head_names, - tail: Some((tail_var, tail_name)), + tail, }); } else if !elements.is_empty() { pattern_vec.push(Air::ListExpose { diff --git a/examples/acceptance_tests/056/aiken.lock b/examples/acceptance_tests/056/aiken.lock new file mode 100644 index 00000000..3a78b1e7 --- /dev/null +++ b/examples/acceptance_tests/056/aiken.lock @@ -0,0 +1,5 @@ +# This file was generated by Aiken +# You typically do not need to edit this file + +requirements = [] +packages = [] diff --git a/examples/acceptance_tests/056/aiken.toml b/examples/acceptance_tests/056/aiken.toml new file mode 100644 index 00000000..016dcd85 --- /dev/null +++ b/examples/acceptance_tests/056/aiken.toml @@ -0,0 +1,3 @@ +name = "aiken-lang/acceptance_test_056" +version = "0.0.0" +dependencies = [] diff --git a/examples/acceptance_tests/056/lib/choice_a.ak b/examples/acceptance_tests/056/lib/choice_a.ak new file mode 100644 index 00000000..91a0fb0d --- /dev/null +++ b/examples/acceptance_tests/056/lib/choice_a.ak @@ -0,0 +1,24 @@ +// Could possibly be forbidden by the parser instead if we have no intent to support that. +pub fn choice(self: List>) -> Option { + when self is { + [] -> None + [Some(_) as result, ..] -> result + [None, ..others] -> choice(others) + } +} + +test choice_1() { + choice([Some(14), Some(42)]) == Some(14) +} + +test choice_2() { + choice([]) == None +} + +test choice_3() { + choice([None]) == None +} + +test choice_4() { + choice([None, Some(42)]) == Some(42) +} diff --git a/examples/acceptance_tests/056/lib/choice_b.ak b/examples/acceptance_tests/056/lib/choice_b.ak new file mode 100644 index 00000000..493a31b8 --- /dev/null +++ b/examples/acceptance_tests/056/lib/choice_b.ak @@ -0,0 +1,23 @@ +pub fn choice(self: List>) -> Option { + when self is { + [] -> None + [Some(x), ..] -> Some(x) + [None, ..others] -> choice(others) + } +} + +test choice_1() { + choice([Some(14), Some(42)]) == Some(14) +} + +test choice_2() { + choice([]) == None +} + +test choice_3() { + choice([None]) == None +} + +test choice_4() { + choice([None, Some(42)]) == Some(42) +} diff --git a/examples/acceptance_tests/056/lib/choice_c.ak b/examples/acceptance_tests/056/lib/choice_c.ak new file mode 100644 index 00000000..8f38ef31 --- /dev/null +++ b/examples/acceptance_tests/056/lib/choice_c.ak @@ -0,0 +1,23 @@ +pub fn choice(self: List>) -> Option { + when self is { + [] -> None + [None, ..others] -> choice(others) + [result, ..] -> result + } +} + +test choice_1() { + choice([Some(14), Some(42)]) == Some(14) +} + +test choice_2() { + choice([]) == None +} + +test choice_3() { + choice([None]) == None +} + +test choice_4() { + choice([None, Some(42)]) == Some(42) +}