now currying works

This commit is contained in:
microproofs 2024-02-16 11:27:22 -05:00 committed by Kasey
parent 3b55a32583
commit 258b5abf23
2 changed files with 87 additions and 25 deletions

View File

@ -24,6 +24,7 @@ pub fn aiken_optimize_and_intern(program: Program<Name>) -> Program<Name> {
.inline_reducer()
.force_delay_reducer()
.cast_data_reducer()
.builtin_curry_reducer()
.lambda_reducer()
.inline_reducer()
.lambda_reducer()

View File

@ -153,17 +153,19 @@ pub enum BuiltinArgs {
impl BuiltinArgs {
fn args_from_arg_stack(stack: Vec<(usize, Term<Name>)>, is_order_agnostic: bool) -> Self {
let mut ordered_arg_stack = stack.into_iter().rev().sorted_by(|(_, arg1), (_, arg2)| {
let mut ordered_arg_stack = stack.into_iter().sorted_by(|(_, arg1), (_, arg2)| {
// sort by constant first if the builtin is order agnostic
if matches!(arg1, Term::Constant(_)) == matches!(arg2, Term::Constant(_))
&& is_order_agnostic
{
if is_order_agnostic {
if matches!(arg1, Term::Constant(_)) == matches!(arg2, Term::Constant(_)) {
Ordering::Equal
} else if matches!(arg1, Term::Constant(_)) {
Ordering::Less
} else {
Ordering::Greater
}
} else {
Ordering::Equal
}
});
if ordered_arg_stack.len() == 2 && is_order_agnostic {
@ -1071,7 +1073,6 @@ impl Program<Name> {
})
}
// WIP
pub fn builtin_curry_reducer(self) -> Self {
let mut curried_terms = vec![];
let mut id_mapped_curry_terms: IndexMap<CurriedName, (Scope, Term<Name>, bool)> =
@ -1079,6 +1080,7 @@ impl Program<Name> {
let mut curry_applied_ids = vec![];
let mut scope_mapped_to_term: IndexMap<Scope, Vec<(CurriedName, Term<Name>)>> =
IndexMap::new();
let mut final_ids: IndexMap<Vec<usize>, ()> = IndexMap::new();
let a = self.traverse_uplc_with(&mut |_id, term, arg_stack, scope| match term {
Term::Builtin(func) => {
@ -1087,6 +1089,7 @@ impl Program<Name> {
// In the case of order agnostic builtins we want to sort the args by constant first
// This gives us the opportunity to curry constants that often pop up in the code
let builtin_args =
BuiltinArgs::args_from_arg_stack(arg_stack, is_order_agnostic);
@ -1167,15 +1170,13 @@ impl Program<Name> {
_ => {}
});
println!("CURRIED ARGS");
for (index, curried_term) in curried_terms.iter().enumerate() {
println!("index is {:#?}, term is {:#?}", index, curried_term);
}
id_mapped_curry_terms
.into_iter()
.filter(|(_, (_, _, multi_occurrence))| *multi_occurrence)
.for_each(|(key, val)| match scope_mapped_to_term.get_mut(&val.0) {
.for_each(|(key, val)| {
final_ids.insert(key.id_vec.clone(), ());
match scope_mapped_to_term.get_mut(&val.0) {
Some(list) => {
let insert_position = list
.iter()
@ -1187,6 +1188,7 @@ impl Program<Name> {
None => {
scope_mapped_to_term.insert(val.0, vec![(key, val.1)]);
}
}
});
let mut b = a.traverse_uplc_with(&mut |id, term, arg_stack, scope| match term {
@ -1203,10 +1205,23 @@ impl Program<Name> {
func.is_order_agnostic_builtin(),
);
let Some(id_vec) = curried_builtin.get_id_args(&builtin_args) else {
let Some(mut id_vec) = curried_builtin.get_id_args(&builtin_args) else {
return;
};
while !id_vec.is_empty() {
let id_lookup = id_vec.iter().map(|item| item.curried_id).collect_vec();
if final_ids.contains_key(&id_lookup) {
break;
}
id_vec.pop();
}
if id_vec.is_empty() {
return;
}
let id_str = id_vec
.iter()
.map(|item| item.curried_id.to_string())
@ -1873,4 +1888,50 @@ mod tests {
assert_eq!(actual, expected);
}
#[test]
fn curry_reducer_test_1() {
let mut program: Program<Name> = Program {
version: (1, 0, 0),
term: Term::add_integer()
.apply(Term::var("x"))
.apply(Term::integer(1.into()))
.lambda("x")
.apply(
Term::add_integer()
.apply(Term::integer(1.into()))
.apply(Term::var("y")),
)
.lambda("y")
.apply(Term::integer(5.into())),
};
let mut interner = Interner::new();
interner.program(&mut program);
let mut expected = Program {
version: (1, 0, 0),
term: Term::var("add_one_curried")
.apply(Term::var("x"))
.lambda("x")
.apply(Term::var("add_one_curried").apply(Term::var("y")))
.lambda("add_one_curried")
.apply(Term::add_integer().apply(Term::integer(1.into())))
.lambda("y")
.apply(Term::integer(5.into())),
};
let mut interner = Interner::new();
interner.program(&mut expected);
let expected: Program<NamedDeBruijn> = expected.try_into().unwrap();
let actual = program.builtin_curry_reducer();
let actual: Program<NamedDeBruijn> = actual.try_into().unwrap();
assert_eq!(actual, expected);
}
}