checkpoint
This commit is contained in:
parent
4e0aaf970f
commit
c6ef37cc5c
|
@ -420,10 +420,6 @@ impl Unique {
|
||||||
pub fn increment(&mut self) {
|
pub fn increment(&mut self) {
|
||||||
self.0 += 1;
|
self.0 += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn large_offset(&mut self) {
|
|
||||||
self.0 += 5_000_000;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<isize> for Unique {
|
impl From<isize> for Unique {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Constant, Name, Term, Type, Unique},
|
ast::{Constant, Name, Term, Type},
|
||||||
builtins::DefaultFunction,
|
builtins::DefaultFunction,
|
||||||
};
|
};
|
||||||
use pallas::ledger::primitives::alonzo::PlutusData;
|
use pallas::ledger::primitives::alonzo::PlutusData;
|
||||||
|
@ -464,31 +464,10 @@ impl Term<Name> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lambda_unique(self, parameter_name: impl ToString, unique: Unique) -> Self {
|
|
||||||
Term::Lambda {
|
|
||||||
parameter_name: Name {
|
|
||||||
text: parameter_name.to_string(),
|
|
||||||
unique,
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
body: self.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn var(name: impl ToString) -> Self {
|
pub fn var(name: impl ToString) -> Self {
|
||||||
Term::Var(Name::text(name).into())
|
Term::Var(Name::text(name).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn var_unique(name: impl ToString, unique: Unique) -> Self {
|
|
||||||
Term::Var(
|
|
||||||
Name {
|
|
||||||
text: name.to_string(),
|
|
||||||
unique,
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Misc.
|
// Misc.
|
||||||
pub fn constr_fields_exposer(self) -> Self {
|
pub fn constr_fields_exposer(self) -> Self {
|
||||||
self.lambda(CONSTR_FIELDS_EXPOSER).apply(
|
self.lambda(CONSTR_FIELDS_EXPOSER).apply(
|
||||||
|
|
|
@ -1,23 +1,28 @@
|
||||||
use crate::ast::{Name, Program};
|
use crate::ast::{Name, Program};
|
||||||
|
|
||||||
|
mod interner;
|
||||||
pub mod shrinker;
|
pub mod shrinker;
|
||||||
|
|
||||||
pub fn aiken_optimize_and_intern(program: Program<Name>) -> Program<Name> {
|
pub fn aiken_optimize_and_intern(program: Program<Name>) -> Program<Name> {
|
||||||
let (program, mut current_unique) = program.builtin_force_reducer();
|
let w = program
|
||||||
current_unique.large_offset();
|
.builtin_force_reducer()
|
||||||
|
|
||||||
program
|
|
||||||
.lambda_reducer()
|
.lambda_reducer()
|
||||||
.inline_reducer()
|
.inline_reducer()
|
||||||
.lambda_reducer()
|
.lambda_reducer()
|
||||||
.inline_reducer()
|
.inline_reducer()
|
||||||
.force_delay_reducer()
|
.force_delay_reducer()
|
||||||
.cast_data_reducer()
|
.cast_data_reducer()
|
||||||
.convert_arithmetic_ops()
|
.convert_arithmetic_ops();
|
||||||
.builtin_curry_reducer(&mut current_unique)
|
|
||||||
.lambda_reducer()
|
// println!("{:#?}", w);
|
||||||
.inline_reducer()
|
|
||||||
.builtin_curry_reducer(&mut current_unique)
|
let x = w.builtin_curry_reducer();
|
||||||
.lambda_reducer()
|
|
||||||
.inline_reducer()
|
// println!("{:#?}", x);
|
||||||
|
|
||||||
|
let y = x.lambda_reducer().inline_reducer().builtin_curry_reducer();
|
||||||
|
|
||||||
|
// println!("{:#?}", y);
|
||||||
|
|
||||||
|
y.lambda_reducer().inline_reducer()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
use std::{collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
|
use crate::ast::{Name, Program, Term, Unique};
|
||||||
|
|
||||||
|
#[derive(Eq, Hash, PartialEq, Clone)]
|
||||||
|
pub struct InternKey {
|
||||||
|
name: String,
|
||||||
|
previous_unique: Unique,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CodeGenInterner {
|
||||||
|
identifiers: HashMap<InternKey, Unique>,
|
||||||
|
current: Unique,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CodeGenInterner {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Interner that uses previous uniques to prevent future unique collisions
|
||||||
|
/// when performing optimizations
|
||||||
|
impl CodeGenInterner {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
identifiers: HashMap::new(),
|
||||||
|
current: Unique::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn program(&mut self, program: &mut Program<Name>) {
|
||||||
|
self.term(&mut program.term);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn term(&mut self, term: &mut Term<Name>) {
|
||||||
|
match term {
|
||||||
|
Term::Var(name) => {
|
||||||
|
let name = Rc::make_mut(name);
|
||||||
|
name.unique = self.intern(name.text.clone(), name.unique);
|
||||||
|
}
|
||||||
|
Term::Delay(term) => self.term(Rc::make_mut(term)),
|
||||||
|
Term::Lambda {
|
||||||
|
parameter_name,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
|
let parameter_name = Rc::make_mut(parameter_name);
|
||||||
|
parameter_name.unique =
|
||||||
|
self.intern(parameter_name.text.clone(), parameter_name.unique);
|
||||||
|
self.term(Rc::make_mut(body));
|
||||||
|
}
|
||||||
|
Term::Apply { function, argument } => {
|
||||||
|
self.term(Rc::make_mut(function));
|
||||||
|
self.term(Rc::make_mut(argument));
|
||||||
|
}
|
||||||
|
Term::Constant(_) => (),
|
||||||
|
Term::Force(term) => self.term(Rc::make_mut(term)),
|
||||||
|
Term::Error => (),
|
||||||
|
Term::Builtin(_) => (),
|
||||||
|
Term::Constr { fields, .. } => {
|
||||||
|
for field in fields {
|
||||||
|
self.term(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Term::Case { constr, branches } => {
|
||||||
|
self.term(Rc::make_mut(constr));
|
||||||
|
|
||||||
|
for branch in branches {
|
||||||
|
self.term(branch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn intern(&mut self, text: String, previous_unique: Unique) -> Unique {
|
||||||
|
let key = InternKey {
|
||||||
|
name: text,
|
||||||
|
previous_unique,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(u) = self.identifiers.get(&key) {
|
||||||
|
*u
|
||||||
|
} else {
|
||||||
|
let unique = self.current;
|
||||||
|
|
||||||
|
self.identifiers.insert(key, self.current_unique());
|
||||||
|
|
||||||
|
self.current.increment();
|
||||||
|
|
||||||
|
unique
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_unique(&self) -> Unique {
|
||||||
|
self.current
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,12 @@ use itertools::Itertools;
|
||||||
use pallas::ledger::primitives::babbage::{BigInt, PlutusData};
|
use pallas::ledger::primitives::babbage::{BigInt, PlutusData};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Constant, Data, Name, NamedDeBruijn, Program, Term, Type, Unique},
|
ast::{Constant, Data, Name, NamedDeBruijn, Program, Term, Type},
|
||||||
builtins::DefaultFunction,
|
builtins::DefaultFunction,
|
||||||
parser::interner::Interner,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::interner::CodeGenInterner;
|
||||||
|
|
||||||
#[derive(Eq, Hash, PartialEq, Clone, Debug, PartialOrd)]
|
#[derive(Eq, Hash, PartialEq, Clone, Debug, PartialOrd)]
|
||||||
pub enum ScopePath {
|
pub enum ScopePath {
|
||||||
FUNC,
|
FUNC,
|
||||||
|
@ -310,6 +311,7 @@ pub struct CurriedNode {
|
||||||
term: Term<Name>,
|
term: Term<Name>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub struct UplcNode {
|
pub struct UplcNode {
|
||||||
applied_id: usize,
|
applied_id: usize,
|
||||||
curried_id: usize,
|
curried_id: usize,
|
||||||
|
@ -640,6 +642,22 @@ impl CurriedArgs {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_flipped(&self, path: &BuiltinArgs) -> bool {
|
||||||
|
match (self, path) {
|
||||||
|
(CurriedArgs::TwoArgs { fst_args, .. }, BuiltinArgs::TwoArgsAnyOrder { fst, snd }) => {
|
||||||
|
if fst_args.iter().any(|item| item.term == fst.1) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
fst_args.iter().any(|item| match &snd {
|
||||||
|
Some(snd) => item.term == snd.1,
|
||||||
|
None => false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub struct CurriedBuiltin {
|
pub struct CurriedBuiltin {
|
||||||
|
@ -660,6 +678,10 @@ impl CurriedBuiltin {
|
||||||
pub fn get_id_args(&self, path: &BuiltinArgs) -> Option<Vec<UplcNode>> {
|
pub fn get_id_args(&self, path: &BuiltinArgs) -> Option<Vec<UplcNode>> {
|
||||||
self.args.get_id_args(path)
|
self.args.get_id_args(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_flipped(&self, path: &BuiltinArgs) -> bool {
|
||||||
|
self.args.is_flipped(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Term<Name> {
|
impl Term<Name> {
|
||||||
|
@ -798,7 +820,7 @@ impl Program<Name> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn builtin_force_reducer(self) -> (Self, Unique) {
|
pub fn builtin_force_reducer(self) -> Self {
|
||||||
let mut builtin_map = IndexMap::new();
|
let mut builtin_map = IndexMap::new();
|
||||||
|
|
||||||
let program = self.traverse_uplc_with(&mut |_id, term, _arg_stack, _scope| {
|
let program = self.traverse_uplc_with(&mut |_id, term, _arg_stack, _scope| {
|
||||||
|
@ -850,16 +872,13 @@ impl Program<Name> {
|
||||||
term,
|
term,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut interner = Interner::new();
|
let mut interner = CodeGenInterner::new();
|
||||||
|
|
||||||
interner.program(&mut program);
|
interner.program(&mut program);
|
||||||
|
|
||||||
let program = Program::<NamedDeBruijn>::try_from(program).unwrap();
|
let program = Program::<NamedDeBruijn>::try_from(program).unwrap();
|
||||||
|
|
||||||
(
|
Program::<Name>::try_from(program).unwrap()
|
||||||
Program::<Name>::try_from(program).unwrap(),
|
|
||||||
interner.current_unique(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inline_reducer(self) -> Self {
|
pub fn inline_reducer(self) -> Self {
|
||||||
|
@ -1147,15 +1166,17 @@ impl Program<Name> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn builtin_curry_reducer(self, current: &mut Unique) -> 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)> =
|
||||||
IndexMap::new();
|
IndexMap::new();
|
||||||
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 flipped_terms: IndexMap<Scope, bool> = IndexMap::new();
|
||||||
|
|
||||||
let mut final_ids: IndexMap<Vec<usize>, ()> = IndexMap::new();
|
let mut final_ids: IndexMap<Vec<usize>, ()> = IndexMap::new();
|
||||||
let mut unique_map: IndexMap<String, Unique> = IndexMap::new();
|
|
||||||
|
|
||||||
let step_a = self.traverse_uplc_with(&mut |_id, term, arg_stack, scope| match term {
|
let step_a = self.traverse_uplc_with(&mut |_id, term, arg_stack, scope| match term {
|
||||||
Term::Builtin(func) => {
|
Term::Builtin(func) => {
|
||||||
|
@ -1168,31 +1189,40 @@ impl Program<Name> {
|
||||||
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);
|
||||||
|
|
||||||
// Get upper scope of the function plus args
|
|
||||||
// So for example if the scope is [.., ARG, ARG, FUNC]
|
|
||||||
// we want to pop off the last 3 to get the scope right above the function applications
|
|
||||||
|
|
||||||
// First we see if we have already curried this builtin before
|
// First we see if we have already curried this builtin before
|
||||||
let mut id_vec = if let Some(curried_builtin) = curried_terms
|
let mut id_vec = if let Some((index, _)) =
|
||||||
.iter_mut()
|
curried_terms.iter_mut().find_position(
|
||||||
.find(|curried_term: &&mut CurriedBuiltin| curried_term.func == *func)
|
|curried_term: &&mut CurriedBuiltin| curried_term.func == *func,
|
||||||
{
|
) {
|
||||||
// We found it the builtin was curried before
|
// We found it the builtin was curried before
|
||||||
// So now we merge the new args into the existing curried builtin
|
// So now we merge the new args into the existing curried builtin
|
||||||
*curried_builtin = (*curried_builtin)
|
|
||||||
.clone()
|
let curried_builtin = curried_terms.remove(index);
|
||||||
.merge_node_by_path(builtin_args.clone());
|
|
||||||
|
let curried_builtin =
|
||||||
|
curried_builtin.merge_node_by_path(builtin_args.clone());
|
||||||
|
|
||||||
let Some(id_vec) = curried_builtin.get_id_args(&builtin_args) else {
|
let Some(id_vec) = curried_builtin.get_id_args(&builtin_args) else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
flipped_terms
|
||||||
|
.insert(scope.clone(), curried_builtin.is_flipped(&builtin_args));
|
||||||
|
|
||||||
|
curried_terms.push(curried_builtin);
|
||||||
|
|
||||||
id_vec
|
id_vec
|
||||||
} else {
|
} else {
|
||||||
// Brand new buitlin so we add it to the list
|
// Brand new buitlin so we add it to the list
|
||||||
curried_terms.push(builtin_args.clone().args_to_curried_args(*func));
|
let curried_builtin = builtin_args.clone().args_to_curried_args(*func);
|
||||||
|
|
||||||
builtin_args.get_id_args()
|
let Some(id_vec) = curried_builtin.get_id_args(&builtin_args) else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
|
||||||
|
curried_terms.push(curried_builtin);
|
||||||
|
|
||||||
|
id_vec
|
||||||
};
|
};
|
||||||
|
|
||||||
while let Some(node) = id_vec.pop() {
|
while let Some(node) = id_vec.pop() {
|
||||||
|
@ -1201,8 +1231,6 @@ impl Program<Name> {
|
||||||
|
|
||||||
id_only_vec.push(node.curried_id);
|
id_only_vec.push(node.curried_id);
|
||||||
|
|
||||||
let id_var_name = id_vec_function_to_var(&func.aiken_name(), &id_only_vec);
|
|
||||||
|
|
||||||
let curry_name = CurriedName {
|
let curry_name = CurriedName {
|
||||||
func_name: func.aiken_name(),
|
func_name: func.aiken_name(),
|
||||||
id_vec: id_only_vec,
|
id_vec: id_only_vec,
|
||||||
|
@ -1214,33 +1242,19 @@ impl Program<Name> {
|
||||||
*map_scope = map_scope.common_ancestor(scope);
|
*map_scope = map_scope.common_ancestor(scope);
|
||||||
*multi_occurrences = true;
|
*multi_occurrences = true;
|
||||||
} else if id_vec.is_empty() {
|
} else if id_vec.is_empty() {
|
||||||
unique_map.insert(id_var_name, *current);
|
|
||||||
|
|
||||||
current.increment();
|
|
||||||
|
|
||||||
id_mapped_curry_terms.insert(
|
id_mapped_curry_terms.insert(
|
||||||
curry_name,
|
curry_name,
|
||||||
(scope.clone(), Term::Builtin(*func).apply(node.term), false),
|
(scope.clone(), Term::Builtin(*func).apply(node.term), false),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
unique_map.insert(id_var_name, *current);
|
|
||||||
|
|
||||||
current.increment();
|
|
||||||
|
|
||||||
let var_name = id_vec_function_to_var(
|
let var_name = id_vec_function_to_var(
|
||||||
&func.aiken_name(),
|
&func.aiken_name(),
|
||||||
&id_vec.iter().map(|item| item.curried_id).collect_vec(),
|
&id_vec.iter().map(|item| item.curried_id).collect_vec(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let unique = *unique_map.get(&var_name).unwrap_or(current);
|
|
||||||
|
|
||||||
id_mapped_curry_terms.insert(
|
id_mapped_curry_terms.insert(
|
||||||
curry_name,
|
curry_name,
|
||||||
(
|
(scope.clone(), Term::var(var_name).apply(node.term), false),
|
||||||
scope.clone(),
|
|
||||||
Term::var_unique(var_name, unique).apply(node.term),
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1272,104 +1286,91 @@ impl Program<Name> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
step_a.traverse_uplc_with(&mut |id, term, arg_stack, scope| match term {
|
let mut step_b =
|
||||||
Term::Builtin(func) => {
|
step_a.traverse_uplc_with(&mut |id, term, mut arg_stack, scope| match term {
|
||||||
if func.can_curry_builtin() && arg_stack.len() == func.arity() {
|
Term::Builtin(func) => {
|
||||||
let Some(curried_builtin) =
|
if func.can_curry_builtin() && arg_stack.len() == func.arity() {
|
||||||
curried_terms.iter().find(|curry| curry.func == *func)
|
let Some(curried_builtin) =
|
||||||
else {
|
curried_terms.iter().find(|curry| curry.func == *func)
|
||||||
return;
|
else {
|
||||||
};
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let builtin_args = BuiltinArgs::args_from_arg_stack(
|
if let Some(true) = flipped_terms.get(scope) {
|
||||||
arg_stack,
|
arg_stack.reverse();
|
||||||
func.is_order_agnostic_builtin(),
|
|
||||||
);
|
|
||||||
|
|
||||||
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() {
|
let builtin_args = BuiltinArgs::args_from_arg_stack(
|
||||||
return;
|
arg_stack,
|
||||||
}
|
func.is_order_agnostic_builtin(),
|
||||||
|
);
|
||||||
|
|
||||||
let name = id_vec_function_to_var(
|
let Some(mut id_vec) = curried_builtin.get_id_args(&builtin_args) else {
|
||||||
&func.aiken_name(),
|
return;
|
||||||
&id_vec.iter().map(|item| item.curried_id).collect_vec(),
|
};
|
||||||
);
|
|
||||||
|
|
||||||
id_vec.iter().for_each(|item| {
|
while !id_vec.is_empty() {
|
||||||
curry_applied_ids.push(item.applied_id);
|
let id_lookup = id_vec.iter().map(|item| item.curried_id).collect_vec();
|
||||||
});
|
|
||||||
|
|
||||||
let unique = *unique_map.get(&name).unwrap();
|
if final_ids.contains_key(&id_lookup) {
|
||||||
|
break;
|
||||||
*term = Term::var_unique(name, unique);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Term::Apply { function, .. } => {
|
|
||||||
let id = id.unwrap();
|
|
||||||
|
|
||||||
if curry_applied_ids.contains(&id) {
|
|
||||||
*term = function.as_ref().clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(insert_list) = scope_mapped_to_term.remove(scope) {
|
|
||||||
for (key, val) in insert_list.into_iter().rev() {
|
|
||||||
let name = id_vec_function_to_var(&key.func_name, &key.id_vec);
|
|
||||||
|
|
||||||
let unique = *unique_map.get(&name).unwrap();
|
|
||||||
|
|
||||||
if var_occurrences(
|
|
||||||
term,
|
|
||||||
Name {
|
|
||||||
text: name.clone(),
|
|
||||||
unique,
|
|
||||||
}
|
}
|
||||||
.into(),
|
id_vec.pop();
|
||||||
)
|
|
||||||
.found
|
|
||||||
{
|
|
||||||
*term = term.clone().lambda_unique(name, unique).apply(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if id_vec.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = id_vec_function_to_var(
|
||||||
|
&func.aiken_name(),
|
||||||
|
&id_vec.iter().map(|item| item.curried_id).collect_vec(),
|
||||||
|
);
|
||||||
|
|
||||||
|
id_vec.iter().for_each(|item| {
|
||||||
|
curry_applied_ids.push(item.applied_id);
|
||||||
|
});
|
||||||
|
|
||||||
|
*term = Term::var(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Term::Apply { function, .. } => {
|
||||||
Term::Constr { .. } => todo!(),
|
let id = id.unwrap();
|
||||||
Term::Case { .. } => todo!(),
|
|
||||||
_ => {
|
|
||||||
if let Some(insert_list) = scope_mapped_to_term.remove(scope) {
|
|
||||||
for (key, val) in insert_list.into_iter().rev() {
|
|
||||||
let name = id_vec_function_to_var(&key.func_name, &key.id_vec);
|
|
||||||
|
|
||||||
let unique = *unique_map.get(&name).unwrap();
|
if curry_applied_ids.contains(&id) {
|
||||||
|
*term = function.as_ref().clone();
|
||||||
|
}
|
||||||
|
|
||||||
if var_occurrences(
|
if let Some(insert_list) = scope_mapped_to_term.remove(scope) {
|
||||||
term,
|
for (key, val) in insert_list.into_iter().rev() {
|
||||||
Name {
|
let name = id_vec_function_to_var(&key.func_name, &key.id_vec);
|
||||||
text: name.clone(),
|
|
||||||
unique,
|
if var_occurrences(term, Name::text(&name).into()).found {
|
||||||
|
*term = term.clone().lambda(name).apply(val);
|
||||||
}
|
}
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
.found
|
|
||||||
{
|
|
||||||
*term = term.clone().lambda_unique(name, unique).apply(val);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Term::Constr { .. } => todo!(),
|
||||||
})
|
Term::Case { .. } => todo!(),
|
||||||
|
_ => {
|
||||||
|
if let Some(insert_list) = scope_mapped_to_term.remove(scope) {
|
||||||
|
for (key, val) in insert_list.into_iter().rev() {
|
||||||
|
let name = id_vec_function_to_var(&key.func_name, &key.id_vec);
|
||||||
|
|
||||||
|
if var_occurrences(term, Name::text(&name).into()).found {
|
||||||
|
*term = term.clone().lambda(name).apply(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut interner = CodeGenInterner::new();
|
||||||
|
|
||||||
|
interner.program(&mut step_b);
|
||||||
|
|
||||||
|
step_b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1776,7 +1777,7 @@ mod tests {
|
||||||
|
|
||||||
let expected: Program<NamedDeBruijn> = expected.try_into().unwrap();
|
let expected: Program<NamedDeBruijn> = expected.try_into().unwrap();
|
||||||
|
|
||||||
let (mut actual, _) = program.builtin_force_reducer();
|
let mut actual = program.builtin_force_reducer();
|
||||||
|
|
||||||
let mut interner = Interner::new();
|
let mut interner = Interner::new();
|
||||||
|
|
||||||
|
@ -1835,7 +1836,7 @@ mod tests {
|
||||||
|
|
||||||
let expected: Program<NamedDeBruijn> = expected.try_into().unwrap();
|
let expected: Program<NamedDeBruijn> = expected.try_into().unwrap();
|
||||||
|
|
||||||
let (mut actual, _) = program.builtin_force_reducer();
|
let mut actual = program.builtin_force_reducer();
|
||||||
|
|
||||||
let mut interner = Interner::new();
|
let mut interner = Interner::new();
|
||||||
|
|
||||||
|
@ -2001,13 +2002,9 @@ mod tests {
|
||||||
|
|
||||||
interner.program(&mut expected);
|
interner.program(&mut expected);
|
||||||
|
|
||||||
let mut unique = interner.current_unique();
|
|
||||||
|
|
||||||
unique.large_offset();
|
|
||||||
|
|
||||||
let expected: Program<NamedDeBruijn> = expected.try_into().unwrap();
|
let expected: Program<NamedDeBruijn> = expected.try_into().unwrap();
|
||||||
|
|
||||||
let actual = program.builtin_curry_reducer(&mut unique);
|
let actual = program.builtin_curry_reducer();
|
||||||
|
|
||||||
let actual: Program<NamedDeBruijn> = actual.try_into().unwrap();
|
let actual: Program<NamedDeBruijn> = actual.try_into().unwrap();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue