feat: Add wrap data reduce which helps prevent unnecessary wrap to unwrap and vice versa.

fix: in inline_reduce the wrong arg name was used. arg instead of argument

refactor var occurences
This commit is contained in:
microproofs 2023-04-18 13:58:55 -04:00 committed by Kasey
parent 022d557906
commit 9de713803a
2 changed files with 122 additions and 49 deletions

View File

@ -22,4 +22,8 @@ pub fn aiken_optimize_and_intern(program: Program<Name>) -> Program<Name> {
.inline_reduce() .inline_reduce()
.lambda_reduce() .lambda_reduce()
.inline_reduce() .inline_reduce()
.force_delay_reduce()
.wrap_data_reduce()
.lambda_reduce()
.inline_reduce()
} }

View File

@ -7,7 +7,6 @@ use crate::{
ast::{Name, Program, Term}, ast::{Name, Program, Term},
builtins::DefaultFunction, builtins::DefaultFunction,
}; };
// use crate::builtins::{DefaultFunction};
#[derive(Eq, Hash, PartialEq, Clone)] #[derive(Eq, Hash, PartialEq, Clone)]
pub struct Occurrence { pub struct Occurrence {
@ -17,7 +16,7 @@ pub struct Occurrence {
impl Program<Name> { impl Program<Name> {
pub fn lambda_reduce(self) -> Program<Name> { pub fn lambda_reduce(self) -> Program<Name> {
let mut term = self.term.clone(); let mut term = self.term;
lambda_reduce(&mut term); lambda_reduce(&mut term);
Program { Program {
version: self.version, version: self.version,
@ -26,7 +25,7 @@ impl Program<Name> {
} }
pub fn builtin_force_reduce(self) -> Program<Name> { pub fn builtin_force_reduce(self) -> Program<Name> {
let mut term = self.term.clone(); let mut term = self.term;
let mut builtin_map = IndexMap::new(); let mut builtin_map = IndexMap::new();
builtin_force_reduce(&mut term, &mut builtin_map); builtin_force_reduce(&mut term, &mut builtin_map);
@ -49,7 +48,7 @@ impl Program<Name> {
} }
pub fn inline_reduce(self) -> Program<Name> { pub fn inline_reduce(self) -> Program<Name> {
let mut term = self.term.clone(); let mut term = self.term;
inline_basic_reduce(&mut term); inline_basic_reduce(&mut term);
Program { Program {
version: self.version, version: self.version,
@ -58,13 +57,22 @@ impl Program<Name> {
} }
pub fn force_delay_reduce(self) -> Program<Name> { pub fn force_delay_reduce(self) -> Program<Name> {
let mut term = self.term.clone(); let mut term = self.term;
force_delay_reduce(&mut term); force_delay_reduce(&mut term);
Program { Program {
version: self.version, version: self.version,
term, term,
} }
} }
pub fn wrap_data_reduce(self) -> Program<Name> {
let mut term = self.term;
wrap_data_reduce(&mut term);
Program {
version: self.version,
term,
}
}
} }
fn builtin_force_reduce(term: &mut Term<Name>, builtin_map: &mut IndexMap<u8, ()>) { fn builtin_force_reduce(term: &mut Term<Name>, builtin_map: &mut IndexMap<u8, ()>) {
@ -128,6 +136,7 @@ fn force_delay_reduce(term: &mut Term<Name>) {
if let Term::Delay(body) = f { if let Term::Delay(body) = f {
*term = body.as_ref().clone(); *term = body.as_ref().clone();
force_delay_reduce(term);
} else { } else {
force_delay_reduce(f); force_delay_reduce(f);
} }
@ -173,14 +182,14 @@ fn inline_basic_reduce(term: &mut Term<Name>) {
body, body,
} = func } = func
{ {
let mut occurrences = 0; let occurrences = var_occurrences(body, parameter_name.clone());
var_occurrences(body, parameter_name.clone(), &mut occurrences);
if occurrences == 1 { if occurrences == 1 {
if let replace_term @ (Term::Var(_) if let replace_term @ (Term::Var(_)
| Term::Constant(_) | Term::Constant(_)
| Term::Error | Term::Error
| Term::Delay(_) | Term::Delay(_)
| Term::Lambda { .. }) = argument.as_ref() | Term::Lambda { .. }
| Term::Builtin(_)) = arg
{ {
*term = *term =
substitute_term(body.as_ref(), parameter_name.clone(), replace_term); substitute_term(body.as_ref(), parameter_name.clone(), replace_term);
@ -196,56 +205,116 @@ fn inline_basic_reduce(term: &mut Term<Name>) {
} }
} }
fn var_occurrences(term: &Term<Name>, search_for: Rc<Name>, occurrences: &mut usize) { fn wrap_data_reduce(term: &mut Term<Name>) {
match term { match term {
Term::Var(name) => { Term::Delay(d) => {
if name.as_ref() == search_for.as_ref() { wrap_data_reduce(Rc::make_mut(d));
*occurrences += 1;
}
} }
Term::Delay(body) => { Term::Lambda { body, .. } => {
var_occurrences(body.as_ref(), search_for, occurrences); wrap_data_reduce(Rc::make_mut(body));
}
Term::Lambda {
parameter_name,
body,
} => {
if parameter_name.clone() != search_for {
var_occurrences(body.as_ref(), search_for, occurrences);
}
} }
Term::Apply { function, argument } => { Term::Apply { function, argument } => {
var_occurrences(function.as_ref(), search_for.clone(), occurrences); let Term::Builtin(
var_occurrences(argument.as_ref(), search_for, occurrences); first_action
) = function.as_ref()
else {
wrap_data_reduce(Rc::make_mut(function));
wrap_data_reduce(Rc::make_mut(argument));
return;
};
let Term::Apply { function: inner_func, argument: inner_arg } = Rc::make_mut(argument)
else {
wrap_data_reduce(Rc::make_mut(argument));
return;
};
let Term::Builtin(second_action) = inner_func.as_ref()
else {
wrap_data_reduce(Rc::make_mut(inner_func));
wrap_data_reduce(Rc::make_mut(inner_arg));
return;
};
match (first_action, second_action) {
(DefaultFunction::UnIData, DefaultFunction::IData) => {
*term = argument.as_ref().clone();
wrap_data_reduce(term);
}
(DefaultFunction::IData, DefaultFunction::UnIData) => {
*term = argument.as_ref().clone();
wrap_data_reduce(term);
}
(DefaultFunction::BData, DefaultFunction::UnBData) => {
*term = argument.as_ref().clone();
wrap_data_reduce(term);
}
(DefaultFunction::UnBData, DefaultFunction::BData) => {
*term = argument.as_ref().clone();
wrap_data_reduce(term);
}
(DefaultFunction::ListData, DefaultFunction::UnListData) => {
*term = argument.as_ref().clone();
wrap_data_reduce(term);
}
(DefaultFunction::UnListData, DefaultFunction::ListData) => {
*term = argument.as_ref().clone();
wrap_data_reduce(term);
}
(DefaultFunction::MapData, DefaultFunction::UnMapData) => {
*term = argument.as_ref().clone();
wrap_data_reduce(term);
}
(DefaultFunction::UnMapData, DefaultFunction::MapData) => {
*term = argument.as_ref().clone();
wrap_data_reduce(term);
}
(DefaultFunction::UnConstrData, DefaultFunction::ConstrData) => {
*term = argument.as_ref().clone();
wrap_data_reduce(term);
}
(DefaultFunction::ConstrData, DefaultFunction::UnConstrData) => {
*term = argument.as_ref().clone();
wrap_data_reduce(term);
}
_ => {}
}
} }
Term::Force(x) => { Term::Force(f) => {
var_occurrences(x.as_ref(), search_for, occurrences); wrap_data_reduce(Rc::make_mut(f));
} }
_ => {} _ => {}
} }
} }
// fn error_occurrences(term: &Term<Name>, occurrences: &mut usize) { fn var_occurrences(term: &Term<Name>, search_for: Rc<Name>) -> usize {
// match term { match term {
// Term::Delay(body) => { Term::Var(name) => {
// error_occurrences(body.as_ref(), occurrences); if name.as_ref() == search_for.as_ref() {
// } 1
// Term::Lambda { body, .. } => { } else {
// error_occurrences(body.as_ref(), occurrences); 0
// } }
// Term::Apply { function, argument } => { }
// error_occurrences(function.as_ref(), occurrences); Term::Delay(body) => var_occurrences(body.as_ref(), search_for),
// error_occurrences(argument.as_ref(), occurrences); Term::Lambda {
// } parameter_name,
// Term::Force(x) => { body,
// error_occurrences(x.as_ref(), occurrences); } => {
// } if parameter_name.clone() != search_for {
// Term::Error => { var_occurrences(body.as_ref(), search_for)
// *occurrences += 1; } else {
// } 0
// _ => {} }
// } }
// } Term::Apply { function, argument } => {
var_occurrences(function.as_ref(), search_for.clone())
+ var_occurrences(argument.as_ref(), search_for)
}
Term::Force(x) => var_occurrences(x.as_ref(), search_for),
_ => 0,
}
}
fn lambda_reduce(term: &mut Term<Name>) { fn lambda_reduce(term: &mut Term<Name>) {
match term { match term {
@ -261,7 +330,7 @@ fn lambda_reduce(term: &mut Term<Name>) {
body, body,
} = func } = func
{ {
if let replace_term @ (Term::Var(_) | Term::Constant(_)) = arg { if let replace_term @ (Term::Var(_) | Term::Constant(_) | Term::Builtin(_)) = arg {
let body = Rc::make_mut(body); let body = Rc::make_mut(body);
*term = substitute_term(body, parameter_name.clone(), replace_term); *term = substitute_term(body, parameter_name.clone(), replace_term);
} }