feat: Add multivalidator as an AIR tree opcode.
feat: Add uplc eval optimization
This commit is contained in:
@@ -9,6 +9,7 @@ use crate::{
|
||||
ast::{Constant, Data, Name, NamedDeBruijn, Program, Term, Type},
|
||||
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER},
|
||||
builtins::DefaultFunction,
|
||||
machine::cost_model::ExBudget,
|
||||
};
|
||||
|
||||
use super::interner::CodeGenInterner;
|
||||
@@ -360,7 +361,7 @@ pub enum BuiltinArgs {
|
||||
|
||||
impl BuiltinArgs {
|
||||
fn args_from_arg_stack(stack: Vec<(usize, Term<Name>)>, func: DefaultFunction) -> Self {
|
||||
let error_safe = func.is_error_safe(&stack.iter().map(|(_, term)| term).collect_vec());
|
||||
let error_safe = false;
|
||||
|
||||
let mut ordered_arg_stack = stack.into_iter().sorted_by(|(_, arg1), (_, arg2)| {
|
||||
// sort by constant first if the builtin is order agnostic
|
||||
@@ -986,6 +987,27 @@ impl Term<Name> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pierce_no_inlines<'a>(&'a self) -> &'a Self {
|
||||
let mut term = self;
|
||||
loop {
|
||||
match term {
|
||||
Term::Lambda {
|
||||
parameter_name,
|
||||
body,
|
||||
} => {
|
||||
if parameter_name.as_ref().text == NO_INLINE {
|
||||
term = body;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
term
|
||||
}
|
||||
}
|
||||
|
||||
impl Program<Name> {
|
||||
@@ -1708,6 +1730,56 @@ impl Program<Name> {
|
||||
|
||||
step_b
|
||||
}
|
||||
|
||||
pub fn builtin_eval_reducer(self) -> Self {
|
||||
let mut applied_ids = vec![];
|
||||
|
||||
self.traverse_uplc_with(false, &mut |id, term, arg_stack, _scope| match term {
|
||||
Term::Builtin(func) => {
|
||||
let args = arg_stack
|
||||
.iter()
|
||||
.map(|(_, term)| term.pierce_no_inlines())
|
||||
.collect_vec();
|
||||
if func.can_curry_builtin()
|
||||
&& arg_stack.len() == func.arity()
|
||||
&& func.is_error_safe(&args)
|
||||
{
|
||||
let applied_term =
|
||||
arg_stack
|
||||
.into_iter()
|
||||
.fold(Term::Builtin(*func), |acc, item| {
|
||||
applied_ids.push(item.0);
|
||||
acc.apply(item.1.pierce_no_inlines().clone())
|
||||
});
|
||||
|
||||
// Check above for is error safe
|
||||
let eval_term: Term<Name> = Program {
|
||||
version: (1, 0, 0),
|
||||
term: applied_term,
|
||||
}
|
||||
.to_named_debruijn()
|
||||
.unwrap()
|
||||
.eval(ExBudget::max())
|
||||
.result()
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
|
||||
*term = eval_term;
|
||||
}
|
||||
}
|
||||
Term::Apply { function, .. } => {
|
||||
let id = id.unwrap();
|
||||
|
||||
if applied_ids.contains(&id) {
|
||||
*term = function.as_ref().clone();
|
||||
}
|
||||
}
|
||||
Term::Constr { .. } => todo!(),
|
||||
Term::Case { .. } => todo!(),
|
||||
_ => {}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn id_vec_function_to_var(func_name: &str, id_vec: &[usize]) -> String {
|
||||
|
||||
Reference in New Issue
Block a user