diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index d5c4ccaa..e6f8b54d 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -813,38 +813,44 @@ impl<'a> CodeGenerator<'a> { clause_properties, ); - let data_type = - builder::lookup_data_type_by_tipo(self.data_types.clone(), subject_type); + if clause.pattern.is_var() || clause.pattern.is_discard() { + ir_stack.wrap_clause(clause_pattern_stack); + } else { + let data_type = builder::lookup_data_type_by_tipo( + self.data_types.clone(), + subject_type, + ); - if let Some(data_type) = data_type { - if data_type.constructors.len() > 1 { + if let Some(data_type) = data_type { + if data_type.constructors.len() > 1 { + ir_stack.clause( + subject_type.clone(), + subject_name, + *clause_properties.is_complex_clause(), + clause_pattern_stack, + ); + } else { + let mut condition_stack = ir_stack.empty_with_scope(); + + condition_stack.integer(0.to_string()); + + condition_stack.merge_child(clause_pattern_stack); + + ir_stack.clause( + subject_type.clone(), + subject_name, + *clause_properties.is_complex_clause(), + condition_stack, + ); + } + } else { ir_stack.clause( subject_type.clone(), subject_name, *clause_properties.is_complex_clause(), clause_pattern_stack, ); - } else { - let mut condition_stack = ir_stack.empty_with_scope(); - - condition_stack.integer(0.to_string()); - - condition_stack.merge_child(clause_pattern_stack); - - ir_stack.clause( - subject_type.clone(), - subject_name, - *clause_properties.is_complex_clause(), - condition_stack, - ); } - } else { - ir_stack.clause( - subject_type.clone(), - subject_name, - *clause_properties.is_complex_clause(), - clause_pattern_stack, - ); } } ClauseProperties::ListClause { diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index d803789c..0ed686b8 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -286,7 +286,11 @@ pub fn rearrange_clauses(clauses: Vec) -> Vec { // TODO: how shall tails be weighted? Since any clause after will not run sorted_clauses.sort_by(|clause1, clause2| { let clause1_len = match &clause1.pattern { - Pattern::List { elements, tail, .. } => elements.len() + usize::from(tail.is_some()), + Pattern::List { elements, tail, .. } => { + elements.len() * 3 + + usize::from(tail.is_some()) + + usize::from(clause1.guard.is_some()) + } _ => 10000000, }; let clause2_len = match &clause2.pattern { @@ -306,27 +310,44 @@ pub fn rearrange_clauses(clauses: Vec) -> Vec { // If we have a catch all, use that. Otherwise use todo which will result in error // TODO: fill in todo label with description - let plug_in_then = match &sorted_clauses[sorted_clauses.len() - 1].pattern { - Pattern::Var { name, .. } => { - assign_plug_in_name = Some(name); - sorted_clauses[sorted_clauses.len() - 1].clone().then - } - Pattern::Discard { .. } => sorted_clauses[sorted_clauses.len() - 1].clone().then, - _ => { - let tipo = sorted_clauses[sorted_clauses.len() - 1].then.tipo(); - TypedExpr::Trace { - location: Span::empty(), - tipo: tipo.clone(), - text: Box::new(TypedExpr::String { - location: Span::empty(), - tipo: crate::builtins::string(), - value: "Clause not filled".to_string(), - }), - then: Box::new(TypedExpr::ErrorTerm { - location: Span::empty(), - tipo, - }), + let plug_in_then = if sorted_clauses[sorted_clauses.len() - 1].guard.is_none() { + match &sorted_clauses[sorted_clauses.len() - 1].pattern { + Pattern::Var { name, .. } => { + assign_plug_in_name = Some(name); + sorted_clauses[sorted_clauses.len() - 1].clone().then } + Pattern::Discard { .. } => sorted_clauses[sorted_clauses.len() - 1].clone().then, + _ => { + let tipo = sorted_clauses[sorted_clauses.len() - 1].then.tipo(); + TypedExpr::Trace { + location: Span::empty(), + tipo: tipo.clone(), + text: Box::new(TypedExpr::String { + location: Span::empty(), + tipo: crate::builtins::string(), + value: "Clause not filled".to_string(), + }), + then: Box::new(TypedExpr::ErrorTerm { + location: Span::empty(), + tipo, + }), + } + } + } + } else { + let tipo = sorted_clauses[sorted_clauses.len() - 1].then.tipo(); + TypedExpr::Trace { + location: Span::empty(), + tipo: tipo.clone(), + text: Box::new(TypedExpr::String { + location: Span::empty(), + tipo: crate::builtins::string(), + value: "Clause not filled".to_string(), + }), + then: Box::new(TypedExpr::ErrorTerm { + location: Span::empty(), + tipo, + }), } }; @@ -379,33 +400,34 @@ pub fn rearrange_clauses(clauses: Vec) -> Vec { } // if we have a pattern with no clause guards and a tail then no lists will get past here to other clauses - match &clause.pattern { - Pattern::Var { .. } => { - last_clause_index = index + 1; - last_clause_set = true; - } - Pattern::Discard { .. } => { - last_clause_index = index + 1; - last_clause_set = true; - } - Pattern::List { - elements, - tail: Some(tail), - .. - } => { - let mut elements = elements.clone(); - elements.push(*tail.clone()); - if elements - .iter() - .all(|element| matches!(element, Pattern::Var { .. } | Pattern::Discard { .. })) - && !last_clause_set - && !elements.is_empty() - { + if clause.guard.is_none() { + match &clause.pattern { + Pattern::Var { .. } => { last_clause_index = index + 1; last_clause_set = true; } + Pattern::Discard { .. } => { + last_clause_index = index + 1; + last_clause_set = true; + } + Pattern::List { + elements, + tail: Some(tail), + .. + } => { + let mut elements = elements.clone(); + elements.push(*tail.clone()); + if elements.iter().all(|element| { + matches!(element, Pattern::Var { .. } | Pattern::Discard { .. }) + }) && !last_clause_set + && !elements.is_empty() + { + last_clause_index = index + 1; + last_clause_set = true; + } + } + _ => {} } - _ => {} } // If the last condition doesn't have a catch all or tail then add a catch all with a todo diff --git a/examples/acceptance_tests/048/lib/tests.ak b/examples/acceptance_tests/048/lib/tests.ak index 2f441bb3..a0ce78e5 100644 --- a/examples/acceptance_tests/048/lib/tests.ak +++ b/examples/acceptance_tests/048/lib/tests.ak @@ -46,27 +46,27 @@ test foo_4() { } } -// type Seasons { -// Winter -// Spring -// Summer -// Fall -// } +type Seasons { + Winter + Spring + Summer + Fall +} -// fn is_cold(season, hour) { -// when season is { -// Winter | Fall -> -// True -// _ if hour >= 18 -> -// True -// _ -> -// False -// } -// } +fn is_cold(season, hour) { + when season is { + Winter | Fall -> + True + _ if hour >= 18 -> + True + _ -> + False + } +} -// test foo_5() { -// !is_cold(Spring, 15) && is_cold(Summer, 22) -// } +test foo_5() { + !is_cold(Spring, 15) && is_cold(Summer, 22) +} fn when_tuple(a: (Int, Int)) -> Int { when a is { @@ -75,6 +75,6 @@ fn when_tuple(a: (Int, Int)) -> Int { } } -test spend() { +test foo_6() { when_tuple((4, 1)) == 4 }