fixing list condition edge cases and clean up rearrange list clauses
This commit is contained in:
parent
e8fa8f5423
commit
03dd13dc7d
|
@ -25,7 +25,8 @@ use crate::{
|
|||
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,
|
||||
wrap_as_multi_validator, wrap_validator_condition, CodeGenFunction, SpecificClause,
|
||||
pattern_has_conditions, wrap_as_multi_validator, wrap_validator_condition, CodeGenFunction,
|
||||
SpecificClause,
|
||||
},
|
||||
tipo::{
|
||||
ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
|
||||
|
@ -1680,7 +1681,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
let next_elements_len = match next_clause_pattern {
|
||||
Pattern::List { elements, tail, .. } => {
|
||||
elements.len() - usize::from(tail.is_some())
|
||||
elements.len() + usize::from(tail.is_none())
|
||||
}
|
||||
_ => 0,
|
||||
};
|
||||
|
@ -1708,16 +1709,11 @@ impl<'a> CodeGenerator<'a> {
|
|||
};
|
||||
|
||||
let mut is_wild_card_elems_clause = clause.guard.is_none();
|
||||
for elements in elements.iter() {
|
||||
if let Pattern::Constructor { .. }
|
||||
| Pattern::Tuple { .. }
|
||||
| Pattern::List { .. }
|
||||
| Pattern::Assign { .. } = elements
|
||||
{
|
||||
is_wild_card_elems_clause = false;
|
||||
}
|
||||
for element in elements.iter() {
|
||||
is_wild_card_elems_clause =
|
||||
is_wild_card_elems_clause && !pattern_has_conditions(element);
|
||||
}
|
||||
let elements_len = elements.len() - usize::from(tail.is_some());
|
||||
let elements_len = elements.len() + usize::from(tail.is_none());
|
||||
let current_checked_index = *checked_index;
|
||||
|
||||
if *checked_index < elements_len.try_into().unwrap()
|
||||
|
@ -2360,8 +2356,8 @@ impl<'a> CodeGenerator<'a> {
|
|||
is_record,
|
||||
..
|
||||
} => {
|
||||
props.complex_clause = true;
|
||||
if subject_tipo.is_bool() {
|
||||
props.complex_clause = true;
|
||||
AirTree::clause_guard(
|
||||
&props.original_subject_name,
|
||||
AirTree::bool(constr_name == "True"),
|
||||
|
@ -2373,6 +2369,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
if *is_record {
|
||||
assign
|
||||
} else {
|
||||
props.complex_clause = true;
|
||||
AirTree::UnhoistedSequence(vec![
|
||||
AirTree::clause_guard(
|
||||
&props.original_subject_name,
|
||||
|
@ -2385,7 +2382,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
}
|
||||
}
|
||||
Pattern::Tuple { .. } => {
|
||||
props.complex_clause = true;
|
||||
let (_, assign) = self.clause_pattern(pattern, subject_tipo, props);
|
||||
|
||||
let defined_indices = match &props.specific_clause {
|
||||
|
|
|
@ -14,7 +14,9 @@ use uplc::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
ast::{AssignmentKind, DataType, Pattern, Span, TypedArg, TypedClause, TypedDataType},
|
||||
ast::{
|
||||
AssignmentKind, DataType, Pattern, Span, TypedArg, TypedClause, TypedDataType, TypedPattern,
|
||||
},
|
||||
builtins::{bool, void},
|
||||
expr::TypedExpr,
|
||||
tipo::{PatternConstructor, TypeVar, ValueConstructor, ValueConstructorVariant},
|
||||
|
@ -521,7 +523,6 @@ pub fn get_variant_name(t: &Arc<Type>) -> String {
|
|||
let full_type = "_data".to_string();
|
||||
|
||||
if t.is_generic() {
|
||||
println!("FULL TYPE: {:#?}", t);
|
||||
panic!("FOUND A POLYMORPHIC TYPE. EXPECTED MONOMORPHIC TYPE");
|
||||
}
|
||||
|
||||
|
@ -601,6 +602,25 @@ pub fn modify_self_calls(air_tree: &mut AirTree, func_key: &FunctionAccessKey, v
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pattern_has_conditions(pattern: &TypedPattern) -> bool {
|
||||
match pattern {
|
||||
Pattern::Constructor {
|
||||
is_record: false, ..
|
||||
}
|
||||
| Pattern::List { .. }
|
||||
| Pattern::Int { .. } => true,
|
||||
Pattern::Tuple { elems, .. } => elems.iter().any(pattern_has_conditions),
|
||||
Pattern::Constructor {
|
||||
is_record: true,
|
||||
arguments,
|
||||
..
|
||||
} => arguments
|
||||
.iter()
|
||||
.any(|arg| pattern_has_conditions(&arg.value)),
|
||||
Pattern::Var { .. } | Pattern::Discard { .. } | Pattern::Assign { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: write some tests
|
||||
pub fn rearrange_list_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
||||
let mut sorted_clauses = clauses;
|
||||
|
@ -695,8 +715,6 @@ pub fn rearrange_list_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
|||
None
|
||||
};
|
||||
|
||||
println!("sorted clauses: {:#?}", sorted_clauses);
|
||||
|
||||
for (index, clause) in sorted_clauses.iter().enumerate() {
|
||||
if last_clause_set {
|
||||
continue;
|
||||
|
@ -710,15 +728,12 @@ pub fn rearrange_list_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
|||
|
||||
assert!(matches!(
|
||||
clause_pattern,
|
||||
Pattern::List { .. }
|
||||
| Pattern::Var { .. }
|
||||
| Pattern::Discard { .. }
|
||||
| Pattern::Assign { .. }
|
||||
Pattern::List { .. } | Pattern::Var { .. } | Pattern::Discard { .. }
|
||||
));
|
||||
|
||||
if let Pattern::List { elements, tail, .. } = &clause.pattern {
|
||||
if let Pattern::List { elements, tail, .. } = clause_pattern {
|
||||
// found a hole and now we plug it
|
||||
while wild_card_clause_elems < elements.len() - usize::from(tail.is_some()) {
|
||||
while wild_card_clause_elems < elements.len() {
|
||||
let mut discard_elems = vec![];
|
||||
|
||||
for _ in 0..wild_card_clause_elems {
|
||||
|
@ -764,17 +779,14 @@ pub fn rearrange_list_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
|||
|
||||
let mut is_wild_card_elems_clause = clause.guard.is_none();
|
||||
|
||||
for elements in elements.iter() {
|
||||
if let Pattern::Constructor { .. }
|
||||
| Pattern::Tuple { .. }
|
||||
| Pattern::List { .. }
|
||||
| Pattern::Assign { .. } = elements
|
||||
{
|
||||
is_wild_card_elems_clause = false;
|
||||
}
|
||||
for element in elements.iter() {
|
||||
is_wild_card_elems_clause =
|
||||
is_wild_card_elems_clause && !pattern_has_conditions(element);
|
||||
}
|
||||
|
||||
if is_wild_card_elems_clause {
|
||||
if is_wild_card_elems_clause
|
||||
&& wild_card_clause_elems < elements.len() + usize::from(tail.is_none())
|
||||
{
|
||||
wild_card_clause_elems += 1;
|
||||
if clause.guard.is_none() && tail.is_some() && !elements.is_empty() {
|
||||
last_clause_index = index;
|
||||
|
@ -808,7 +820,7 @@ pub fn rearrange_list_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
|||
|
||||
// Encountered a tail so stop there with that as last clause
|
||||
if last_clause_set {
|
||||
final_clauses = final_clauses[0..last_clause_index + 1].to_vec();
|
||||
final_clauses = final_clauses[0..last_clause_index].to_vec();
|
||||
}
|
||||
|
||||
// insert hole fillers into clauses
|
||||
|
|
|
@ -103,6 +103,8 @@ fn assert_uplc(source_code: &str, expected: Term<Name>, should_fail: bool) {
|
|||
term: expected,
|
||||
};
|
||||
|
||||
println!("expected: {}", expected.to_pretty());
|
||||
|
||||
let expected = optimize::aiken_optimize_and_intern(expected);
|
||||
|
||||
let expected: Program<DeBruijn> = expected.try_into().unwrap();
|
||||
|
@ -2898,6 +2900,52 @@ fn when_tuple_deconstruction() {
|
|||
.apply(Term::var("red")),
|
||||
)
|
||||
.delayed_if_else(Term::unit(), Term::Error)
|
||||
.lambda("red")
|
||||
.apply(
|
||||
Term::var("red").lambda("_").apply(
|
||||
Term::var("expect_RedSpend")
|
||||
.lambda("expect_RedSpend")
|
||||
.apply(
|
||||
Term::equals_integer()
|
||||
.apply(Term::integer(0.into()))
|
||||
.apply(Term::var("subject"))
|
||||
.delayed_if_else(
|
||||
Term::tail_list()
|
||||
.apply(Term::var("red_constr_fields"))
|
||||
.delayed_choose_list(
|
||||
Term::unit(),
|
||||
Term::Error.trace(Term::string("List/Tuple/Constr contains more items than expected")),
|
||||
)
|
||||
.lambda("field_1")
|
||||
.apply(Term::un_i_data().apply(
|
||||
Term::head_list().apply(Term::var("red_constr_fields")),
|
||||
))
|
||||
.lambda("red_constr_fields")
|
||||
.apply(
|
||||
Term::var(CONSTR_FIELDS_EXPOSER)
|
||||
.apply(Term::var("red")),
|
||||
),
|
||||
Term::equals_integer()
|
||||
.apply(Term::integer(1.into()))
|
||||
.apply(Term::var("subject"))
|
||||
.delayed_if_else(
|
||||
Term::var(CONSTR_FIELDS_EXPOSER)
|
||||
.apply(Term::var("red"))
|
||||
.delayed_choose_list(
|
||||
Term::unit(),
|
||||
Term::Error
|
||||
.trace(Term::string("Expected no fields for Constr"))
|
||||
),
|
||||
Term::Error.trace(Term::string("Constr index did not match any type variant")),
|
||||
),
|
||||
)
|
||||
.lambda("subject")
|
||||
.apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("red")))
|
||||
.lambda("red"),
|
||||
)
|
||||
.apply(Term::var("red")),
|
||||
),
|
||||
)
|
||||
.lambda("dat")
|
||||
.apply(
|
||||
Term::var("dat").lambda("_").apply(
|
||||
|
@ -2981,52 +3029,6 @@ fn when_tuple_deconstruction() {
|
|||
.apply(Term::var("dat")),
|
||||
),
|
||||
)
|
||||
.lambda("red")
|
||||
.apply(
|
||||
Term::var("red").lambda("_").apply(
|
||||
Term::var("expect_RedSpend")
|
||||
.lambda("expect_RedSpend")
|
||||
.apply(
|
||||
Term::equals_integer()
|
||||
.apply(Term::integer(0.into()))
|
||||
.apply(Term::var("subject"))
|
||||
.delayed_if_else(
|
||||
Term::tail_list()
|
||||
.apply(Term::var("red_constr_fields"))
|
||||
.delayed_choose_list(
|
||||
Term::unit(),
|
||||
Term::Error.trace(Term::string("List/Tuple/Constr contains more items than expected")),
|
||||
)
|
||||
.lambda("field_1")
|
||||
.apply(Term::un_i_data().apply(
|
||||
Term::head_list().apply(Term::var("red_constr_fields")),
|
||||
))
|
||||
.lambda("red_constr_fields")
|
||||
.apply(
|
||||
Term::var(CONSTR_FIELDS_EXPOSER)
|
||||
.apply(Term::var("red")),
|
||||
),
|
||||
Term::equals_integer()
|
||||
.apply(Term::integer(1.into()))
|
||||
.apply(Term::var("subject"))
|
||||
.delayed_if_else(
|
||||
Term::var(CONSTR_FIELDS_EXPOSER)
|
||||
.apply(Term::var("red"))
|
||||
.delayed_choose_list(
|
||||
Term::unit(),
|
||||
Term::Error
|
||||
.trace(Term::string("Expected no fields for Constr"))
|
||||
),
|
||||
Term::Error.trace(Term::string("Constr index did not match any type variant")),
|
||||
),
|
||||
)
|
||||
.lambda("subject")
|
||||
.apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("red")))
|
||||
.lambda("red"),
|
||||
)
|
||||
.apply(Term::var("red")),
|
||||
),
|
||||
)
|
||||
.lambda("ctx")
|
||||
.lambda("red")
|
||||
.lambda("dat")
|
||||
|
@ -3771,10 +3773,7 @@ fn list_fields_unwrap() {
|
|||
.apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(Term::var("item_1")))
|
||||
.lambda("item_1")
|
||||
.apply(Term::head_list().apply(Term::var("field_list")))
|
||||
.lambda("clauses_delayed")
|
||||
.apply(Term::bool(false).delay())
|
||||
.lambda("tail_1")
|
||||
.apply(Term::tail_list().apply(Term::var("field_list"))),
|
||||
|
||||
)
|
||||
.lambda("field_list")
|
||||
.apply(Term::list_values(vec![
|
||||
|
|
Loading…
Reference in New Issue