feat: Add multivalidator as an AIR tree opcode.
feat: Add uplc eval optimization
This commit is contained in:
@@ -132,6 +132,46 @@ impl<'a> CodeGenerator<'a> {
|
||||
let mut validator_args_tree =
|
||||
self.check_validator_args(&fun.arguments, true, air_tree_fun, src_code, lines);
|
||||
|
||||
if let Some(other) = other_fun {
|
||||
let mut air_tree_fun_other = self.build(&other.body, module_name, &[]);
|
||||
|
||||
air_tree_fun_other = wrap_validator_condition(air_tree_fun_other, self.tracing);
|
||||
|
||||
let validator_args_tree_other = self.check_validator_args(
|
||||
&other.arguments,
|
||||
true,
|
||||
air_tree_fun_other,
|
||||
src_code,
|
||||
lines,
|
||||
);
|
||||
|
||||
let (spend, spend_name, mint, mint_name) =
|
||||
if other.arguments.len() > fun.arguments.len() {
|
||||
(
|
||||
validator_args_tree_other,
|
||||
other.name.clone(),
|
||||
validator_args_tree,
|
||||
fun.name.clone(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
validator_args_tree,
|
||||
fun.name.clone(),
|
||||
validator_args_tree_other,
|
||||
other.name.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
validator_args_tree = AirTree::multi_validator(mint_name, mint, spend_name, spend);
|
||||
|
||||
// Special Case with multi_validators
|
||||
self.special_functions
|
||||
.use_function_uplc(CONSTR_FIELDS_EXPOSER.to_string());
|
||||
|
||||
self.special_functions
|
||||
.use_function_uplc(CONSTR_INDEX_EXPOSER.to_string());
|
||||
}
|
||||
|
||||
validator_args_tree = AirTree::no_op(validator_args_tree);
|
||||
|
||||
let full_tree = self.hoist_functions_to_validator(validator_args_tree);
|
||||
@@ -142,48 +182,6 @@ impl<'a> CodeGenerator<'a> {
|
||||
|
||||
let mut term = self.uplc_code_gen(full_vec);
|
||||
|
||||
if let Some(other) = other_fun {
|
||||
self.reset(false);
|
||||
|
||||
let mut air_tree_fun_other = self.build(&other.body, module_name, &[]);
|
||||
|
||||
air_tree_fun_other = wrap_validator_condition(air_tree_fun_other, self.tracing);
|
||||
|
||||
let mut validator_args_tree_other = self.check_validator_args(
|
||||
&other.arguments,
|
||||
true,
|
||||
air_tree_fun_other,
|
||||
src_code,
|
||||
lines,
|
||||
);
|
||||
|
||||
validator_args_tree_other = AirTree::no_op(validator_args_tree_other);
|
||||
|
||||
let full_tree_other = self.hoist_functions_to_validator(validator_args_tree_other);
|
||||
|
||||
// optimizations on air tree
|
||||
|
||||
let full_vec_other = full_tree_other.to_vec();
|
||||
|
||||
let other_term = self.uplc_code_gen(full_vec_other);
|
||||
|
||||
let (spend, spend_name, mint, mint_name) =
|
||||
if other.arguments.len() > fun.arguments.len() {
|
||||
(other_term, other.name.clone(), term, fun.name.clone())
|
||||
} else {
|
||||
(term, fun.name.clone(), other_term, other.name.clone())
|
||||
};
|
||||
|
||||
// Special Case with multi_validators
|
||||
self.special_functions
|
||||
.use_function_uplc(CONSTR_FIELDS_EXPOSER.to_string());
|
||||
|
||||
self.special_functions
|
||||
.use_function_uplc(CONSTR_INDEX_EXPOSER.to_string());
|
||||
|
||||
term = wrap_as_multi_validator(spend, mint, self.tracing, spend_name, mint_name);
|
||||
}
|
||||
|
||||
term = cast_validator_args(term, params);
|
||||
|
||||
self.finalize(term)
|
||||
@@ -5700,6 +5698,24 @@ impl<'a> CodeGenerator<'a> {
|
||||
}
|
||||
|
||||
Air::NoOp => None,
|
||||
Air::MultiValidator {
|
||||
two_arg_name,
|
||||
three_arg_name,
|
||||
} => {
|
||||
let two_arg = arg_stack.pop().unwrap();
|
||||
|
||||
let three_arg = arg_stack.pop().unwrap();
|
||||
|
||||
let term = wrap_as_multi_validator(
|
||||
three_arg,
|
||||
two_arg,
|
||||
self.tracing,
|
||||
three_arg_name,
|
||||
two_arg_name,
|
||||
);
|
||||
|
||||
Some(term)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,4 +224,8 @@ pub enum Air {
|
||||
NoOp,
|
||||
FieldsEmpty,
|
||||
ListEmpty,
|
||||
MultiValidator {
|
||||
two_arg_name: String,
|
||||
three_arg_name: String,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -402,6 +402,12 @@ pub enum AirTree {
|
||||
then: Box<AirTree>,
|
||||
},
|
||||
// End Expressions
|
||||
MultiValidator {
|
||||
two_arg_name: String,
|
||||
two_arg: Box<AirTree>,
|
||||
three_arg_name: String,
|
||||
three_arg: Box<AirTree>,
|
||||
},
|
||||
}
|
||||
|
||||
impl AirTree {
|
||||
@@ -1001,26 +1007,19 @@ impl AirTree {
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn hoist_over(mut self, next_exp: AirTree) -> AirTree {
|
||||
// match &mut self {
|
||||
// AirTree::Statement { hoisted_over, .. } => {
|
||||
// assert!(hoisted_over.is_none());
|
||||
// *hoisted_over = Some(next_exp.into());
|
||||
// self
|
||||
// }
|
||||
|
||||
// AirTree::Expression(_) => {
|
||||
// unreachable!("Trying to hoist an expression onto an expression.")
|
||||
// }
|
||||
// AirTree::UnhoistedSequence(seq) => {
|
||||
// let mut final_exp = next_exp;
|
||||
// while let Some(assign) = seq.pop() {
|
||||
// final_exp = assign.hoist_over(final_exp);
|
||||
// }
|
||||
// final_exp
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
pub fn multi_validator(
|
||||
two_arg_name: String,
|
||||
two_arg: AirTree,
|
||||
three_arg_name: String,
|
||||
three_arg: AirTree,
|
||||
) -> AirTree {
|
||||
AirTree::MultiValidator {
|
||||
two_arg_name,
|
||||
two_arg: two_arg.into(),
|
||||
three_arg_name,
|
||||
three_arg: three_arg.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_on_list() -> AirTree {
|
||||
let list_var = AirTree::local_var("__list_to_check", list(data()));
|
||||
@@ -1595,6 +1594,20 @@ impl AirTree {
|
||||
msg.create_air_vec(air_vec);
|
||||
then.create_air_vec(air_vec);
|
||||
}
|
||||
AirTree::MultiValidator {
|
||||
two_arg,
|
||||
three_arg,
|
||||
two_arg_name,
|
||||
three_arg_name,
|
||||
} => {
|
||||
air_vec.push(Air::MultiValidator {
|
||||
two_arg_name: two_arg_name.clone(),
|
||||
three_arg_name: three_arg_name.clone(),
|
||||
});
|
||||
|
||||
two_arg.create_air_vec(air_vec);
|
||||
three_arg.create_air_vec(air_vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1649,6 +1662,7 @@ impl AirTree {
|
||||
| AirTree::FieldsEmpty { then, .. }
|
||||
| AirTree::ListEmpty { then, .. }
|
||||
| AirTree::NoOp { then } => then.return_type(),
|
||||
AirTree::MultiValidator { .. } => void(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1725,7 +1739,8 @@ impl AirTree {
|
||||
| AirTree::Fn { .. }
|
||||
| AirTree::UnOp { .. }
|
||||
| AirTree::WrapClause { .. }
|
||||
| AirTree::Finally { .. } => vec![],
|
||||
| AirTree::Finally { .. }
|
||||
| AirTree::MultiValidator { .. } => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2055,7 +2070,8 @@ impl AirTree {
|
||||
| AirTree::Constr { .. }
|
||||
| AirTree::RecordUpdate { .. }
|
||||
| AirTree::ErrorTerm { .. }
|
||||
| AirTree::Trace { .. } => {}
|
||||
| AirTree::Trace { .. }
|
||||
| AirTree::MultiValidator { .. } => {}
|
||||
}
|
||||
|
||||
if !apply_with_func_last {
|
||||
@@ -2711,6 +2727,27 @@ impl AirTree {
|
||||
apply_with_func_last,
|
||||
);
|
||||
}
|
||||
AirTree::MultiValidator {
|
||||
two_arg_name: _,
|
||||
two_arg,
|
||||
three_arg_name: _,
|
||||
three_arg,
|
||||
} => {
|
||||
two_arg.do_traverse_tree_with(
|
||||
tree_path,
|
||||
current_depth + 1,
|
||||
Fields::SecondField,
|
||||
with,
|
||||
apply_with_func_last,
|
||||
);
|
||||
three_arg.do_traverse_tree_with(
|
||||
tree_path,
|
||||
current_depth + 1,
|
||||
Fields::FourthField,
|
||||
with,
|
||||
apply_with_func_last,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if apply_with_func_last {
|
||||
@@ -3077,6 +3114,16 @@ impl AirTree {
|
||||
| AirTree::ErrorTerm { .. } => {
|
||||
panic!("A tree node with no children was encountered with a longer tree path.")
|
||||
}
|
||||
AirTree::MultiValidator {
|
||||
two_arg_name: _,
|
||||
two_arg,
|
||||
three_arg_name: _,
|
||||
three_arg,
|
||||
} => match field {
|
||||
Fields::SecondField => two_arg.as_mut().do_find_air_tree_node(tree_path_iter),
|
||||
Fields::FourthField => three_arg.as_mut().do_find_air_tree_node(tree_path_iter),
|
||||
_ => panic!("Tree Path index outside tree children nodes"),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
self
|
||||
|
||||
Reference in New Issue
Block a user