DRY handlers generation from validator

This commit is contained in:
KtorZ 2024-08-16 18:19:23 +02:00
parent 047f422d0d
commit f9acbd3bcb
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
5 changed files with 321 additions and 506 deletions

View File

@ -472,6 +472,154 @@ impl TypedValidator {
] ]
} }
// Define a validator wrapper extracting and matching on script purpose for
// users.
pub fn into_script_context_handler(&self) -> TypedExpr {
let var_context = "__context__";
let var_transaction = "__transaction__";
let var_redeemer = "__redeemer__";
let var_purpose = "__purpose__";
let var_purpose_arg = "__purpose_arg__";
let var_datum = "__datum__";
TypedExpr::sequence(&[
TypedExpr::let_(
TypedExpr::local_var(var_context, Type::script_context()),
TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: well_known::SCRIPT_CONTEXT_CONSTRUCTORS[0].to_string(),
arguments: vec![
CallArg::var(var_transaction),
CallArg::var(var_redeemer),
CallArg::var(var_purpose),
],
module: None,
constructor: PatternConstructor::Record {
name: well_known::SCRIPT_CONTEXT_CONSTRUCTORS[0].to_string(),
field_map: None,
},
spread_location: None,
tipo: Type::function(
vec![Type::data(), Type::data(), Type::script_purpose()],
Type::data(),
),
},
Type::script_context(),
),
TypedExpr::When {
location: Span::empty(),
tipo: Type::bool(),
subject: TypedExpr::local_var(var_purpose, Type::script_purpose()).into(),
clauses: self
.handlers
.iter()
.map(|handler| {
let datum = if handler.name.as_str() == "spend" {
handler.arguments.first()
} else {
None
};
let redeemer = handler
.arguments
.get(if datum.is_some() { 1 } else { 0 })
.unwrap();
let purpose_arg = handler.arguments.iter().nth_back(1).unwrap();
let transaction = handler.arguments.last().unwrap();
let pattern = match handler.name.as_str() {
"spend" => TypedPattern::spend_purpose(var_purpose_arg, var_datum),
"mint" => TypedPattern::mint_purpose(var_purpose_arg),
"withdraw" => TypedPattern::withdraw_purpose(var_purpose_arg),
"publish" => TypedPattern::publish_purpose(var_purpose_arg),
"propose" => TypedPattern::propose_purpose(var_purpose_arg),
"vote" => TypedPattern::vote_purpose(var_purpose_arg),
purpose => {
unreachable!("unexpected/unknown purpose: {:?}", purpose)
}
};
let mut then = vec![];
// expect redeemer: tipo = __redeemer__
then.push(TypedExpr::flexible_expect(
TypedExpr::local_var(var_redeemer, Type::data()),
TypedPattern::var(redeemer.get_variable_name().unwrap_or("_")),
redeemer.tipo.clone(),
));
// Cast the datum, if any
if let Some(datum) = datum {
// expect datum: tipo = __datum__
then.push(TypedExpr::flexible_expect(
TypedExpr::local_var(var_datum, Type::option(Type::data())),
TypedPattern::var(datum.get_variable_name().unwrap_or("_")),
datum.tipo.clone(),
))
}
// let purpose_arg = __purpose_arg__
if let Some(arg_name) = purpose_arg.get_variable_name() {
then.push(TypedExpr::let_(
TypedExpr::local_var(var_purpose_arg, Type::data()),
TypedPattern::var(arg_name),
purpose_arg.tipo.clone(),
));
}
// let last_arg_name = __transaction__
if let Some(arg_name) = transaction.get_variable_name() {
then.push(TypedExpr::let_(
TypedExpr::local_var(var_transaction, Type::data()),
TypedPattern::var(arg_name),
Type::data(),
));
}
then.push(handler.body.clone());
TypedClause {
location: Span::empty(),
pattern,
then: TypedExpr::Sequence {
location: Span::empty(),
expressions: then,
},
}
})
// FIXME: This is only needed if there's non-exhaustive patterns
// above.
.chain(std::iter::once(&self.fallback).map(|fallback| {
let arg = fallback.arguments.first().unwrap();
let then = &[
TypedExpr::let_(
TypedExpr::local_var(var_context, arg.tipo.clone()),
arg.get_variable_name().map(TypedPattern::var).unwrap_or(
TypedPattern::Discard {
name: var_context.to_string(),
location: Span::empty(),
},
),
arg.tipo.clone(),
),
fallback.body.clone(),
];
TypedClause {
location: Span::empty(),
pattern: TypedPattern::var(var_context),
then: TypedExpr::sequence(then),
}
}))
.collect(),
},
])
}
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> { pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
self.params self.params
.iter() .iter()
@ -697,6 +845,19 @@ impl TypedCallArg {
} }
} }
impl CallArg<TypedPattern> {
pub fn var(name: &str) -> Self {
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
location: Span::empty(),
name: name.to_string(),
},
}
}
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct RecordConstructor<T> { pub struct RecordConstructor<T> {
pub location: Span, pub location: Span,
@ -823,6 +984,21 @@ pub struct TypedArg {
} }
impl TypedArg { impl TypedArg {
pub fn new(name: &str, tipo: Rc<Type>) -> Self {
TypedArg {
arg_name: ArgName::Named {
name: name.to_string(),
label: name.to_string(),
location: Span::empty(),
},
location: Span::empty(),
annotation: None,
doc: None,
is_validator_param: false,
tipo: tipo.clone(),
}
}
pub fn put_doc(&mut self, new_doc: String) { pub fn put_doc(&mut self, new_doc: String) {
self.doc = Some(new_doc); self.doc = Some(new_doc);
} }
@ -1217,6 +1393,88 @@ impl BinOp {
pub type UntypedPattern = Pattern<(), ()>; pub type UntypedPattern = Pattern<(), ()>;
pub type TypedPattern = Pattern<PatternConstructor, Rc<Type>>; pub type TypedPattern = Pattern<PatternConstructor, Rc<Type>>;
impl TypedPattern {
pub fn var(name: &str) -> Self {
TypedPattern::Var {
name: name.to_string(),
location: Span::empty(),
}
}
pub fn constructor(name: &str, arguments: &[CallArg<TypedPattern>], tipo: Rc<Type>) -> Self {
TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: name.to_string(),
arguments: arguments.to_vec(),
module: None,
constructor: PatternConstructor::Record {
name: name.to_string(),
field_map: None,
},
spread_location: None,
tipo: tipo.clone(),
}
}
pub fn mint_purpose(var_purpose_arg: &str) -> Self {
TypedPattern::constructor(
well_known::SCRIPT_PURPOSE_MINT,
&[CallArg::var(var_purpose_arg)],
Type::function(vec![Type::byte_array()], Type::script_purpose()),
)
}
pub fn spend_purpose(var_purpose_arg: &str, var_datum: &str) -> Self {
TypedPattern::constructor(
well_known::SCRIPT_PURPOSE_SPEND,
&[CallArg::var(var_purpose_arg), CallArg::var(var_datum)],
Type::function(
vec![Type::data(), Type::option(Type::data())],
Type::script_purpose(),
),
)
}
pub fn withdraw_purpose(var_purpose_arg: &str) -> Self {
TypedPattern::constructor(
well_known::SCRIPT_PURPOSE_WITHDRAW,
&[CallArg::var(var_purpose_arg)],
Type::function(vec![Type::data()], Type::script_purpose()),
)
}
pub fn publish_purpose(var_purpose_arg: &str) -> Self {
TypedPattern::constructor(
well_known::SCRIPT_PURPOSE_PUBLISH,
&[
CallArg::var("__discarded_purpose_ix__"),
CallArg::var(var_purpose_arg),
],
Type::function(vec![Type::int(), Type::data()], Type::script_purpose()),
)
}
pub fn vote_purpose(var_purpose_arg: &str) -> Self {
TypedPattern::constructor(
well_known::SCRIPT_PURPOSE_VOTE,
&[CallArg::var(var_purpose_arg)],
Type::function(vec![Type::data()], Type::script_purpose()),
)
}
pub fn propose_purpose(var_purpose_arg: &str) -> Self {
TypedPattern::constructor(
well_known::SCRIPT_PURPOSE_PROPOSE,
&[
CallArg::var("__discarded_purpose_ix__"),
CallArg::var(var_purpose_arg),
],
Type::function(vec![Type::int(), Type::data()], Type::script_purpose()),
)
}
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum Pattern<Constructor, Type> { pub enum Pattern<Constructor, Type> {
Int { Int {

View File

@ -1,16 +1,17 @@
pub(crate) use crate::{ pub(crate) use crate::{
ast::{ ast::{
self, Annotation, ArgBy, ArgName, AssignmentPattern, BinOp, Bls12_381Point, self, Annotation, ArgBy, ArgName, AssignmentKind, AssignmentPattern, BinOp, Bls12_381Point,
ByteArrayFormatPreference, CallArg, Curve, DataType, DataTypeKey, DefinitionLocation, ByteArrayFormatPreference, CallArg, Curve, DataType, DataTypeKey, DefinitionLocation,
Located, LogicalOpChainKind, ParsedCallArg, Pattern, RecordConstructorArg, Located, LogicalOpChainKind, ParsedCallArg, Pattern, RecordConstructorArg,
RecordUpdateSpread, Span, TraceKind, TypedArg, TypedAssignmentKind, TypedClause, RecordUpdateSpread, Span, TraceKind, TypedArg, TypedAssignmentKind, TypedClause,
TypedDataType, TypedIfBranch, TypedRecordUpdateArg, UnOp, UntypedArg, TypedDataType, TypedIfBranch, TypedPattern, TypedRecordUpdateArg, UnOp, UntypedArg,
UntypedAssignmentKind, UntypedClause, UntypedIfBranch, UntypedRecordUpdateArg, UntypedAssignmentKind, UntypedClause, UntypedIfBranch, UntypedRecordUpdateArg,
}, },
parser::token::Base, parser::token::Base,
tipo::{ tipo::{
check_replaceable_opaque_type, convert_opaque_type, lookup_data_type_by_tipo, check_replaceable_opaque_type, convert_opaque_type, lookup_data_type_by_tipo,
ModuleValueConstructor, PatternConstructor, Type, TypeVar, ValueConstructor, ModuleValueConstructor, PatternConstructor, Type, TypeVar, ValueConstructor,
ValueConstructorVariant,
}, },
}; };
use indexmap::IndexMap; use indexmap::IndexMap;
@ -199,6 +200,52 @@ impl<T> From<Vec1Ref<T>> for Vec1<T> {
} }
impl TypedExpr { impl TypedExpr {
pub fn sequence(exprs: &[TypedExpr]) -> Self {
TypedExpr::Sequence {
location: Span::empty(),
expressions: exprs.to_vec(),
}
}
pub fn let_(value: Self, pattern: TypedPattern, tipo: Rc<Type>) -> Self {
TypedExpr::Assignment {
location: Span::empty(),
tipo: tipo.clone(),
value: value.into(),
pattern,
kind: AssignmentKind::let_(),
}
}
// Create an expect assignment, unless the target type is `Data`; then fallback to a let.
pub fn flexible_expect(value: Self, pattern: TypedPattern, tipo: Rc<Type>) -> Self {
TypedExpr::Assignment {
location: Span::empty(),
tipo: tipo.clone(),
value: value.into(),
pattern,
kind: if tipo.is_data() {
AssignmentKind::let_()
} else {
AssignmentKind::expect()
},
}
}
pub fn local_var(name: &str, tipo: Rc<Type>) -> Self {
TypedExpr::Var {
location: Span::empty(),
constructor: ValueConstructor {
public: true,
variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
tipo: tipo.clone(),
},
name: name.to_string(),
}
}
pub fn tipo(&self) -> Rc<Type> { pub fn tipo(&self) -> Rc<Type> {
match self { match self {
Self::Var { constructor, .. } => constructor.tipo.clone(), Self::Var { constructor, .. } => constructor.tipo.clone(),

View File

@ -13,9 +13,9 @@ use self::{
}; };
use crate::{ use crate::{
ast::{ ast::{
well_known, ArgName, AssignmentKind, BinOp, Bls12_381Point, CallArg, Curve, DataTypeKey, AssignmentKind, BinOp, Bls12_381Point, Curve, DataTypeKey, FunctionAccessKey, Pattern,
FunctionAccessKey, OnTestFailure, Pattern, Span, TraceLevel, Tracing, TypedArg, Span, TraceLevel, Tracing, TypedArg, TypedClause, TypedDataType, TypedFunction,
TypedClause, TypedDataType, TypedFunction, TypedPattern, TypedValidator, UnOp, TypedPattern, TypedValidator, UnOp,
}, },
builtins::PRELUDE, builtins::PRELUDE,
expr::TypedExpr, expr::TypedExpr,
@ -114,501 +114,11 @@ impl<'a> CodeGenerator<'a> {
} }
} }
pub fn generate( pub fn generate(&mut self, validator: &TypedValidator, module_name: &str) -> Program<Name> {
&mut self, let air_tree_fun = wrap_validator_condition(
TypedValidator { self.build(&validator.into_script_context_handler(), module_name, &[]),
handlers, self.tracing,
fallback, );
params,
..
}: &TypedValidator,
module_name: &str,
) -> 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: Type::data(),
}],
body: TypedExpr::Sequence {
location: Span::empty(),
expressions: vec![
TypedExpr::Assignment {
location: Span::empty(),
tipo: Type::script_context(),
value: TypedExpr::Var {
location: Span::empty(),
constructor: ValueConstructor {
public: true,
variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
tipo: Type::script_context(),
},
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: "__transaction__".to_string(),
},
},
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
location: Span::empty(),
name: "__redeemer__".to_string(),
},
},
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
location: Span::empty(),
name: "__purpose__".to_string(),
},
},
],
module: None,
constructor: PatternConstructor::Record {
name: "ScriptContext".to_string(),
field_map: None,
},
spread_location: None,
tipo: Type::function(
vec![Type::data(), Type::data(), Type::script_purpose()],
Type::data(),
),
},
kind: AssignmentKind::let_(),
},
TypedExpr::When {
location: Span::empty(),
tipo: Type::bool(),
subject: TypedExpr::Var {
location: Span::empty(),
constructor: ValueConstructor {
public: true,
variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
tipo: Type::script_purpose(),
},
name: "__purpose__".to_string(),
}
.into(),
clauses: handlers
.iter()
.map(|handler| {
let datum = if handler.name.as_str() == "spend" {
handler.arguments.first()
} else {
None
};
let redeemer = handler
.arguments
.get(if datum.is_some() { 1 } else { 0 })
.unwrap();
let purpose_arg = handler.arguments.iter().nth_back(1).unwrap();
let transaction = handler.arguments.last().unwrap();
// handler
//
// spend(datum: Option<Datum>, redeemer, oref, anything) => Spend(datum, redeemer, oref, transaction)
// spend(datum: Datum) => Spend(datum, redeemer, oref, transaction)
// spend(redeemer) => Spend(__datum__, redeemer, oref, transaction)
let pattern = match handler.name.as_str() {
"spend" => TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: well_known::SCRIPT_PURPOSE_SPEND.to_string(),
arguments: vec![
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
name: "__purpose_arg__".to_string(),
location: Span::empty(),
},
},
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
name: "__datum__".to_string(),
location: Span::empty(),
},
},
],
module: None,
constructor: PatternConstructor::Record {
name: well_known::SCRIPT_PURPOSE_SPEND.to_string(),
field_map: None,
},
spread_location: None,
tipo: Type::function(
vec![Type::data(), Type::option(Type::data())],
Type::script_purpose(),
),
},
"mint" => TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: well_known::SCRIPT_PURPOSE_MINT.to_string(),
arguments: vec![CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
name: "__purpose_arg__".to_string(),
location: Span::empty(),
},
}],
module: None,
constructor: PatternConstructor::Record {
name: well_known::SCRIPT_PURPOSE_MINT.to_string(),
field_map: None,
},
spread_location: None,
tipo: Type::function(
vec![Type::byte_array()],
Type::script_purpose(),
),
},
"withdraw" => TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: well_known::SCRIPT_PURPOSE_WITHDRAW.to_string(),
arguments: vec![CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
name: "__purpose_arg__".to_string(),
location: Span::empty(),
},
}],
module: None,
constructor: PatternConstructor::Record {
name: well_known::SCRIPT_PURPOSE_WITHDRAW.to_string(),
field_map: None,
},
spread_location: None,
tipo: Type::function(
vec![Type::data()],
Type::script_purpose(),
),
},
"publish" => TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: well_known::SCRIPT_PURPOSE_PUBLISH.to_string(),
arguments: vec![
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
name: "__purpose_arg_ix__".to_string(),
location: Span::empty(),
},
},
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
name: "__purpose_arg__".to_string(),
location: Span::empty(),
},
},
],
module: None,
constructor: PatternConstructor::Record {
name: well_known::SCRIPT_PURPOSE_PUBLISH.to_string(),
field_map: None,
},
spread_location: None,
tipo: Type::function(
vec![Type::int(), Type::data()],
Type::script_purpose(),
),
},
"vote" => TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: well_known::SCRIPT_PURPOSE_VOTE.to_string(),
arguments: vec![CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
name: "__purpose_arg__".to_string(),
location: Span::empty(),
},
}],
module: None,
constructor: PatternConstructor::Record {
name: well_known::SCRIPT_PURPOSE_VOTE.to_string(),
field_map: None,
},
spread_location: None,
tipo: Type::function(
vec![Type::data()],
Type::script_purpose(),
),
},
"propose" => TypedPattern::Constructor {
is_record: false,
location: Span::empty(),
name: well_known::SCRIPT_PURPOSE_PROPOSE.to_string(),
arguments: vec![
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
name: "__purpose_arg_ix__".to_string(),
location: Span::empty(),
},
},
CallArg {
label: None,
location: Span::empty(),
value: TypedPattern::Var {
name: "__purpose_arg__".to_string(),
location: Span::empty(),
},
},
],
module: None,
constructor: PatternConstructor::Record {
name: well_known::SCRIPT_PURPOSE_PROPOSE.to_string(),
field_map: None,
},
spread_location: None,
tipo: Type::function(
vec![Type::int(), Type::data()],
Type::script_purpose(),
),
},
purpose => {
unreachable!("unexpected/unknown purpose: {:?}", purpose)
}
};
let mut then = vec![];
// expect redeemer: tipo = __redeemer__
then.push(TypedExpr::Assignment {
location: Span::empty(),
tipo: redeemer.tipo.clone(),
value: TypedExpr::Var {
location: Span::empty(),
constructor: ValueConstructor {
public: true,
variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
tipo: Type::data(),
},
name: "__redeemer__".to_string(),
}
.into(),
pattern: TypedPattern::Var {
location: Span::empty(),
name: redeemer
.get_variable_name()
.unwrap_or("_")
.to_string(),
},
kind: if redeemer.tipo.is_data() {
AssignmentKind::let_()
} else {
AssignmentKind::expect()
},
});
// Cast the datum, if any
if let Some(datum) = datum {
// expect datum: tipo = __datum__
then.push(TypedExpr::Assignment {
location: Span::empty(),
tipo: datum.tipo.clone(),
value: TypedExpr::Var {
location: Span::empty(),
constructor: ValueConstructor {
public: true,
variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
tipo: Type::option(Type::data()),
},
name: "__datum__".to_string(),
}
.into(),
pattern: TypedPattern::Var {
location: Span::empty(),
name: datum
.get_variable_name()
.unwrap_or("_")
.to_string(),
},
kind: if redeemer.tipo.is_data() {
AssignmentKind::let_()
} else {
AssignmentKind::expect()
},
});
}
// let purpose_arg = __purpose_arg__
if let Some(arg_name) = purpose_arg.get_variable_name() {
then.push(TypedExpr::Assignment {
location: Span::empty(),
tipo: purpose_arg.tipo.clone(),
value: TypedExpr::Var {
location: Span::empty(),
constructor: ValueConstructor {
public: true,
variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
tipo: Type::data(),
},
name: "__purpose_arg__".to_string(),
}
.into(),
pattern: TypedPattern::Var {
location: Span::empty(),
name: arg_name.to_string(),
},
kind: AssignmentKind::let_(),
});
}
// let last_arg_name = __transaction__
if let Some(arg_name) = transaction.get_variable_name() {
then.push(TypedExpr::Assignment {
location: Span::empty(),
tipo: transaction.tipo.clone(),
value: TypedExpr::Var {
location: Span::empty(),
constructor: ValueConstructor {
public: true,
variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
tipo: Type::data(),
},
name: "__transaction__".to_string(),
}
.into(),
pattern: TypedPattern::Var {
location: Span::empty(),
name: arg_name.to_string(),
},
kind: AssignmentKind::let_(),
});
}
then.push(handler.body.clone());
TypedClause {
location: Span::empty(),
pattern,
then: TypedExpr::Sequence {
location: Span::empty(),
expressions: then,
},
}
})
// FIXME: This is only needed if there's non-exhaustive patterns
// above.
.chain(std::iter::once(fallback).map(|fallback| {
let pattern = TypedPattern::Var {
location: Span::empty(),
name: "__context__".to_string(),
};
let arg = fallback.arguments.first().unwrap();
let then = vec![
TypedExpr::Assignment {
location: Span::empty(),
tipo: arg.tipo.clone(),
value: TypedExpr::Var {
location: Span::empty(),
constructor: ValueConstructor {
public: true,
variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
tipo: arg.tipo.clone(),
},
name: "__context__".to_string(),
}
.into(),
pattern: arg
.get_variable_name()
.map(|name| TypedPattern::Var {
location: Span::empty(),
name: name.to_string(),
})
.unwrap_or(TypedPattern::Discard {
name: "__context__".to_string(),
location: Span::empty(),
}),
kind: AssignmentKind::let_(),
},
fallback.body.clone(),
];
TypedClause {
location: Span::empty(),
pattern,
then: TypedExpr::Sequence {
location: Span::empty(),
expressions: then,
},
}
}))
.collect(),
},
],
},
doc: None,
location: Span::empty(),
name: "wrapper_validator".to_string(),
public: true,
return_annotation: None,
return_type: Type::bool(),
end_position: 0,
on_test_failure: OnTestFailure::FailImmediately,
};
let air_tree_fun =
wrap_validator_condition(self.build(&fun.body, module_name, &[]), self.tracing);
let air_tree_fun = AirTree::anon_func(vec!["__context__".to_string()], air_tree_fun, true); let air_tree_fun = AirTree::anon_func(vec!["__context__".to_string()], air_tree_fun, true);
@ -622,7 +132,7 @@ impl<'a> CodeGenerator<'a> {
let term = self.uplc_code_gen(full_vec); let term = self.uplc_code_gen(full_vec);
let term = cast_validator_args(term, params); let term = cast_validator_args(term, &validator.params);
self.finalize(term) self.finalize(term)
} }

View File

@ -1132,7 +1132,7 @@ impl ValueConstructor {
tipo: Rc<Type>, tipo: Rc<Type>,
constructors: &[&str], constructors: &[&str],
) -> Vec<String> { ) -> Vec<String> {
for constructor in &constructors[..] { for constructor in constructors {
values.insert( values.insert(
constructor.to_string(), constructor.to_string(),
ValueConstructor::public( ValueConstructor::public(
@ -1143,7 +1143,7 @@ impl ValueConstructor {
} }
constructors constructors
.into_iter() .iter()
.map(|constructor| constructor.to_string()) .map(|constructor| constructor.to_string())
.collect() .collect()
} }
@ -1152,7 +1152,7 @@ impl ValueConstructor {
values: &mut HashMap<String, Self>, values: &mut HashMap<String, Self>,
constructors: &[(&str, Rc<Type>)], constructors: &[(&str, Rc<Type>)],
) -> Vec<String> { ) -> Vec<String> {
for (constructor, tipo) in &constructors[..] { for (constructor, tipo) in constructors {
values.insert( values.insert(
constructor.to_string(), constructor.to_string(),
ValueConstructor::public( ValueConstructor::public(
@ -1167,7 +1167,7 @@ impl ValueConstructor {
} }
constructors constructors
.into_iter() .iter()
.map(|(constructor, _)| constructor.to_string()) .map(|(constructor, _)| constructor.to_string())
.collect() .collect()
} }

View File

@ -13,4 +13,4 @@ requirements = []
source = "github" source = "github"
[etags] [etags]
"aiken-lang/stdlib@v2" = [{ secs_since_epoch = 1723818477, nanos_since_epoch = 540444000 }, "cdbbce58b61deb385e7ea787a2e0fc2dc8fe94db9999e0e6275bc9c70e5796be"] "aiken-lang/stdlib@v2" = [{ secs_since_epoch = 1723824703, nanos_since_epoch = 979555000 }, "cdbbce58b61deb385e7ea787a2e0fc2dc8fe94db9999e0e6275bc9c70e5796be"]