feat: transform TypedValidator in a function of handlers

This commit is contained in:
rvcas 2024-08-06 16:29:45 -04:00 committed by KtorZ
parent 466a4f0b39
commit 0d8d80e5a7
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
5 changed files with 182 additions and 51 deletions

View File

@ -557,8 +557,8 @@ impl TypedValidator {
.or_else(|| self.fallback.find_node(byte_index)) .or_else(|| self.fallback.find_node(byte_index))
} }
pub fn into_function_definitions<'a>( pub fn into_function_definitions(
&'a self, &self,
module_name: &str, module_name: &str,
) -> Vec<(FunctionAccessKey, TypedFunction)> { ) -> Vec<(FunctionAccessKey, TypedFunction)> {
self.handlers self.handlers

View File

@ -13,9 +13,9 @@ use self::{
}; };
use crate::{ use crate::{
ast::{ ast::{
AssignmentKind, BinOp, Bls12_381Point, Curve, DataTypeKey, FunctionAccessKey, Pattern, ArgName, AssignmentKind, BinOp, Bls12_381Point, CallArg, Curve, DataTypeKey,
Span, TraceLevel, Tracing, TypedArg, TypedClause, TypedDataType, TypedFunction, FunctionAccessKey, OnTestFailure, Pattern, Span, TraceLevel, Tracing, TypedArg,
TypedPattern, TypedValidator, UnOp, TypedClause, TypedDataType, TypedFunction, TypedPattern, TypedValidator, UnOp,
}, },
builtins::{bool, byte_array, data, int, list, pair, void, PRELUDE}, builtins::{bool, byte_array, data, int, list, pair, void, PRELUDE},
expr::TypedExpr, expr::TypedExpr,
@ -117,13 +117,184 @@ impl<'a> CodeGenerator<'a> {
pub fn generate( pub fn generate(
&mut self, &mut self,
TypedValidator { TypedValidator {
fun, handlers,
other_fun, fallback,
params, params,
.. ..
}: &TypedValidator, }: &TypedValidator,
module_name: &str, module_name: &str,
) -> Program<Name> { ) -> Program<Name> {
let fun = TypedFunction {
arguments: vec![TypedArg {
arg_name: ArgName::Named {
name: "__context__".to_string(),
label: "__context__".to_string(),
location: Span::empty(),
},
location: Span::empty(),
annotation: None,
doc: None,
is_validator_param: false,
tipo: data(),
}],
body: TypedExpr::Sequence {
location: Span::empty(),
expressions: vec![
TypedExpr::Assignment {
location: Span::empty(),
tipo: data(),
value: TypedExpr::Var {
location: Span::empty(),
constructor: ValueConstructor {
public: true,
variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
tipo: data(),
},
name: "__context__".to_string(),
}
.into(),
pattern: TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: "ScriptContext".to_string(),
arguments: vec![
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
location: Span::empty(),
name: "__purpose__".to_string(),
},
},
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
location: Span::empty(),
name: "transaction".to_string(),
},
},
],
module: None,
constructor: PatternConstructor::Record {
name: "ScriptContext".to_string(),
field_map: None,
},
spread_location: None,
tipo: data(),
},
kind: AssignmentKind::let_(),
},
TypedExpr::When {
location: Span::empty(),
tipo: bool(),
subject: TypedExpr::Var {
location: Span::empty(),
constructor: ValueConstructor {
public: true,
variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
tipo: data(),
},
name: "__purpose__".to_string(),
}
.into(),
clauses: handlers
.iter()
.chain(std::iter::once(fallback))
.map(|handler| {
let mut arguments = vec![];
for i in 0..(handler.arguments.len() - 1) {
let argument = &handler.arguments[i];
arguments.push(CallArg {
label: None,
location: Span::empty(),
value: argument
.get_variable_name()
.map(|name| TypedPattern::Var {
location: Span::empty(),
name: name.to_string(),
})
.unwrap_or(TypedPattern::Discard {
name: "_".to_string(),
location: Span::empty(),
}),
});
}
let pattern = match handler.name.as_str() {
"spend" => TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: "Spend".to_string(),
arguments: if handler.arguments.len() == 4 {
arguments
} else {
vec![CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Discard {
name: "_".to_string(),
location: Span::empty(),
},
}]
.into_iter()
.chain(arguments)
.collect()
},
module: None,
constructor: PatternConstructor::Record {
name: "Spend".to_string(),
field_map: None,
},
spread_location: None,
tipo: data(),
},
"mint" => TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: "Mint".to_string(),
arguments,
module: None,
constructor: PatternConstructor::Record {
name: "Mint".to_string(),
field_map: None,
},
spread_location: None,
tipo: data(),
},
_ => TypedPattern::Var {
location: Span::empty(),
name: "__context__".to_string(),
},
};
TypedClause {
location: Span::empty(),
pattern,
then: handler.body.clone(),
}
})
.collect(),
},
],
},
doc: None,
location: Span::empty(),
name: "wrapper_validator".to_string(),
public: true,
return_annotation: None,
return_type: bool(),
end_position: 0,
on_test_failure: OnTestFailure::FailImmediately,
};
let mut air_tree_fun = self.build(&fun.body, module_name, &[]); let mut air_tree_fun = self.build(&fun.body, module_name, &[]);
air_tree_fun = wrap_validator_condition(air_tree_fun, self.tracing); air_tree_fun = wrap_validator_condition(air_tree_fun, self.tracing);
@ -133,46 +304,6 @@ impl<'a> CodeGenerator<'a> {
let mut validator_args_tree = let mut validator_args_tree =
self.check_validator_args(&fun.arguments, true, air_tree_fun, src_code, lines); 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); validator_args_tree = AirTree::no_op(validator_args_tree);
let full_tree = self.hoist_functions_to_validator(validator_args_tree); let full_tree = self.hoist_functions_to_validator(validator_args_tree);

View File

@ -748,7 +748,7 @@ fn annotate_fuzzer(tipo: &Type, location: &Span) -> Result<Annotation, Error> {
fn put_params_in_scope(name: &str, environment: &mut Environment, params: &[UntypedArg]) { fn put_params_in_scope(name: &str, environment: &mut Environment, params: &[UntypedArg]) {
let preregistered_fn = environment let preregistered_fn = environment
.get_variable(&name) .get_variable(name)
.expect("Could not find preregistered type for function"); .expect("Could not find preregistered type for function");
let preregistered_type = preregistered_fn.tipo.clone(); let preregistered_type = preregistered_fn.tipo.clone();

View File

@ -62,7 +62,7 @@ impl Validator {
modules, modules,
module, module,
def, def,
hander, handler,
&mut program, &mut program,
plutus_version, plutus_version,
)); ));

View File

@ -479,12 +479,12 @@ impl CheckedModules {
( (
left.0.package.to_string(), left.0.package.to_string(),
left.0.name.to_string(), left.0.name.to_string(),
left.1.fun.name.to_string(), left.1.name.to_string(),
) )
.cmp(&( .cmp(&(
right.0.package.to_string(), right.0.package.to_string(),
right.0.name.to_string(), right.0.name.to_string(),
right.1.fun.name.to_string(), right.1.name.to_string(),
)) ))
}); });