fix: multiple list cases of the same length weren't being handled

This commit is contained in:
Kasey White 2023-01-21 16:10:26 -05:00 committed by Lucas
parent a178cee7bf
commit e36f91c39c
4 changed files with 66 additions and 26 deletions

View File

@ -125,6 +125,10 @@ pub enum Air {
complex_clause: bool,
},
WrapClause {
scope: Vec<u64>,
},
TupleClause {
scope: Vec<u64>,
tipo: Arc<Type>,
@ -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(),
}
}

View File

@ -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 {

View File

@ -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, ..
} => {

View File

@ -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
}
}