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() .inline_reducer()
.force_delay_reducer() .force_delay_reducer()
.cast_data_reducer() .cast_data_reducer()
.builtin_curry_reducer()
.lambda_reducer() .lambda_reducer()
.inline_reducer() .inline_reducer()
.lambda_reducer() .lambda_reducer()

View File

@ -153,16 +153,18 @@ pub enum BuiltinArgs {
impl BuiltinArgs { impl BuiltinArgs {
fn args_from_arg_stack(stack: Vec<(usize, Term<Name>)>, is_order_agnostic: bool) -> Self { 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 // sort by constant first if the builtin is order agnostic
if matches!(arg1, Term::Constant(_)) == matches!(arg2, Term::Constant(_)) if is_order_agnostic {
&& is_order_agnostic if matches!(arg1, Term::Constant(_)) == matches!(arg2, Term::Constant(_)) {
{ Ordering::Equal
Ordering::Equal } else if matches!(arg1, Term::Constant(_)) {
} else if matches!(arg1, Term::Constant(_)) { Ordering::Less
Ordering::Less } else {
Ordering::Greater
}
} else { } else {
Ordering::Greater Ordering::Equal
} }
}); });
@ -1071,7 +1073,6 @@ impl Program<Name> {
}) })
} }
// WIP
pub fn builtin_curry_reducer(self) -> Self { pub fn builtin_curry_reducer(self) -> Self {
let mut curried_terms = vec![]; let mut curried_terms = vec![];
let mut id_mapped_curry_terms: IndexMap<CurriedName, (Scope, Term<Name>, bool)> = 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 curry_applied_ids = vec![];
let mut scope_mapped_to_term: IndexMap<Scope, Vec<(CurriedName, Term<Name>)>> = let mut scope_mapped_to_term: IndexMap<Scope, Vec<(CurriedName, Term<Name>)>> =
IndexMap::new(); 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 { let a = self.traverse_uplc_with(&mut |_id, term, arg_stack, scope| match term {
Term::Builtin(func) => { 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 // 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 // This gives us the opportunity to curry constants that often pop up in the code
let builtin_args = let builtin_args =
BuiltinArgs::args_from_arg_stack(arg_stack, is_order_agnostic); BuiltinArgs::args_from_arg_stack(arg_stack, is_order_agnostic);
@ -1167,25 +1170,24 @@ 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 id_mapped_curry_terms
.into_iter() .into_iter()
.filter(|(_, (_, _, multi_occurrence))| *multi_occurrence) .filter(|(_, (_, _, multi_occurrence))| *multi_occurrence)
.for_each(|(key, val)| match scope_mapped_to_term.get_mut(&val.0) { .for_each(|(key, val)| {
Some(list) => { final_ids.insert(key.id_vec.clone(), ());
let insert_position = list
.iter()
.position(|(list_key, _)| key.len() <= list_key.len())
.unwrap_or(list.len());
list.insert(insert_position, (key, val.1)); match scope_mapped_to_term.get_mut(&val.0) {
} Some(list) => {
None => { let insert_position = list
scope_mapped_to_term.insert(val.0, vec![(key, val.1)]); .iter()
.position(|(list_key, _)| key.len() <= list_key.len())
.unwrap_or(list.len());
list.insert(insert_position, (key, val.1));
}
None => {
scope_mapped_to_term.insert(val.0, vec![(key, val.1)]);
}
} }
}); });
@ -1203,10 +1205,23 @@ impl Program<Name> {
func.is_order_agnostic_builtin(), 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; 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 let id_str = id_vec
.iter() .iter()
.map(|item| item.curried_id.to_string()) .map(|item| item.curried_id.to_string())
@ -1873,4 +1888,50 @@ mod tests {
assert_eq!(actual, expected); 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);
}
} }