Define ScriptPurpose & ScriptContext types in prelude, fix codegen new v3 wrapper.
This commit is contained in:
parent
03a348040b
commit
972e9bd763
|
@ -389,6 +389,53 @@ impl TypedDataType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn script_purpose() -> Self {
|
||||||
|
DataType {
|
||||||
|
constructors: vec![
|
||||||
|
RecordConstructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
name: "__Spend".to_string(),
|
||||||
|
arguments: vec![],
|
||||||
|
doc: None,
|
||||||
|
sugar: false,
|
||||||
|
},
|
||||||
|
RecordConstructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
name: "__Mint".to_string(),
|
||||||
|
arguments: vec![],
|
||||||
|
doc: None,
|
||||||
|
sugar: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
doc: None,
|
||||||
|
location: Span::empty(),
|
||||||
|
name: "__ScriptPurpose".to_string(),
|
||||||
|
opaque: false,
|
||||||
|
parameters: vec![],
|
||||||
|
public: true,
|
||||||
|
typed_parameters: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn script_context() -> Self {
|
||||||
|
DataType {
|
||||||
|
constructors: vec![RecordConstructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
name: "__ScriptContext".to_string(),
|
||||||
|
arguments: vec![],
|
||||||
|
doc: None,
|
||||||
|
sugar: false,
|
||||||
|
}],
|
||||||
|
doc: None,
|
||||||
|
location: Span::empty(),
|
||||||
|
name: "__ScriptContext".to_string(),
|
||||||
|
opaque: false,
|
||||||
|
parameters: vec![],
|
||||||
|
public: true,
|
||||||
|
typed_parameters: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn prng() -> Self {
|
pub fn prng() -> Self {
|
||||||
DataType {
|
DataType {
|
||||||
constructors: vec![
|
constructors: vec![
|
||||||
|
|
|
@ -37,6 +37,16 @@ pub const REDEEMER_WRAPPER: &str = "RedeemerWrapper";
|
||||||
pub const PRNG: &str = "PRNG";
|
pub const PRNG: &str = "PRNG";
|
||||||
pub const FUZZER: &str = "Fuzzer";
|
pub const FUZZER: &str = "Fuzzer";
|
||||||
|
|
||||||
|
pub const SCRIPT_PURPOSE: &str = "__ScriptPurpose";
|
||||||
|
pub const SCRIPT_PURPOSE_SPEND: &str = "__Spend";
|
||||||
|
pub const SCRIPT_PURPOSE_MINT: &str = "__Mint";
|
||||||
|
pub const SCRIPT_PURPOSES_COUNT: u16 = 6;
|
||||||
|
|
||||||
|
pub const SCRIPT_CONTEXT: &str = "__ScriptContext";
|
||||||
|
pub const SCRIPT_CONTEXT_TRANSACTION: &str = "__Transaction";
|
||||||
|
pub const SCRIPT_CONTEXT_REDEEMER: &str = "__Redeemer";
|
||||||
|
pub const SCRIPT_CONTEXT_PURPOSE: &str = "__ScriptPurpose";
|
||||||
|
|
||||||
/// Build a prelude that can be injected
|
/// Build a prelude that can be injected
|
||||||
/// into a compiler pipeline
|
/// into a compiler pipeline
|
||||||
pub fn prelude(id_gen: &IdGenerator) -> TypeInfo {
|
pub fn prelude(id_gen: &IdGenerator) -> TypeInfo {
|
||||||
|
@ -630,6 +640,77 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Cardano ScriptContext
|
||||||
|
prelude.types_constructors.insert(
|
||||||
|
SCRIPT_CONTEXT.to_string(),
|
||||||
|
vec![
|
||||||
|
SCRIPT_CONTEXT_TRANSACTION.to_string(),
|
||||||
|
SCRIPT_CONTEXT_REDEEMER.to_string(),
|
||||||
|
SCRIPT_CONTEXT_PURPOSE.to_string(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
prelude.types.insert(
|
||||||
|
SCRIPT_CONTEXT.to_string(),
|
||||||
|
TypeConstructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
public: true,
|
||||||
|
module: "".to_string(),
|
||||||
|
parameters: vec![],
|
||||||
|
tipo: script_context(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Cardano ScriptPurpose
|
||||||
|
prelude.types_constructors.insert(
|
||||||
|
SCRIPT_PURPOSE.to_string(),
|
||||||
|
vec![
|
||||||
|
SCRIPT_PURPOSE_SPEND.to_string(),
|
||||||
|
SCRIPT_PURPOSE_MINT.to_string(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
prelude.values.insert(
|
||||||
|
SCRIPT_PURPOSE_SPEND.to_string(),
|
||||||
|
ValueConstructor::public(
|
||||||
|
function(vec![data(), option(data())], script_purpose()),
|
||||||
|
ValueConstructorVariant::Record {
|
||||||
|
module: "".into(),
|
||||||
|
name: SCRIPT_PURPOSE_SPEND.to_string(),
|
||||||
|
field_map: None::<FieldMap>,
|
||||||
|
arity: 2,
|
||||||
|
location: Span::empty(),
|
||||||
|
constructors_count: SCRIPT_PURPOSES_COUNT,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
prelude.values.insert(
|
||||||
|
SCRIPT_PURPOSE_MINT.to_string(),
|
||||||
|
ValueConstructor::public(
|
||||||
|
function(vec![data()], script_purpose()),
|
||||||
|
ValueConstructorVariant::Record {
|
||||||
|
module: "".into(),
|
||||||
|
name: SCRIPT_PURPOSE_MINT.to_string(),
|
||||||
|
field_map: None::<FieldMap>,
|
||||||
|
arity: 1,
|
||||||
|
location: Span::empty(),
|
||||||
|
constructors_count: SCRIPT_PURPOSES_COUNT,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
prelude.types.insert(
|
||||||
|
SCRIPT_PURPOSE.to_string(),
|
||||||
|
TypeConstructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
public: true,
|
||||||
|
module: "".to_string(),
|
||||||
|
parameters: vec![],
|
||||||
|
tipo: script_purpose(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
prelude
|
prelude
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1619,6 +1700,26 @@ pub fn prelude_data_types(id_gen: &IdGenerator) -> IndexMap<DataTypeKey, TypedDa
|
||||||
prng_data_type,
|
prng_data_type,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// __ScriptPurpose
|
||||||
|
let script_purpose_data_type = TypedDataType::script_purpose();
|
||||||
|
data_types.insert(
|
||||||
|
DataTypeKey {
|
||||||
|
module_name: "".to_string(),
|
||||||
|
defined_type: SCRIPT_PURPOSE.to_string(),
|
||||||
|
},
|
||||||
|
script_purpose_data_type,
|
||||||
|
);
|
||||||
|
|
||||||
|
// __ScriptContext
|
||||||
|
let script_context_data_type = TypedDataType::script_context();
|
||||||
|
data_types.insert(
|
||||||
|
DataTypeKey {
|
||||||
|
module_name: "".to_string(),
|
||||||
|
defined_type: SCRIPT_CONTEXT.to_string(),
|
||||||
|
},
|
||||||
|
script_context_data_type,
|
||||||
|
);
|
||||||
|
|
||||||
data_types
|
data_types
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1711,6 +1812,28 @@ pub fn bool() -> Rc<Type> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn script_purpose() -> Rc<Type> {
|
||||||
|
Rc::new(Type::App {
|
||||||
|
args: vec![],
|
||||||
|
public: true,
|
||||||
|
contains_opaque: false,
|
||||||
|
name: SCRIPT_PURPOSE.to_string(),
|
||||||
|
module: "".to_string(),
|
||||||
|
alias: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn script_context() -> Rc<Type> {
|
||||||
|
Rc::new(Type::App {
|
||||||
|
args: vec![],
|
||||||
|
public: true,
|
||||||
|
contains_opaque: false,
|
||||||
|
name: SCRIPT_CONTEXT.to_string(),
|
||||||
|
module: "".to_string(),
|
||||||
|
alias: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn prng() -> Rc<Type> {
|
pub fn prng() -> Rc<Type> {
|
||||||
Rc::new(Type::App {
|
Rc::new(Type::App {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
|
|
@ -17,7 +17,10 @@ use crate::{
|
||||||
FunctionAccessKey, OnTestFailure, Pattern, Span, TraceLevel, Tracing, TypedArg,
|
FunctionAccessKey, OnTestFailure, Pattern, Span, TraceLevel, Tracing, TypedArg,
|
||||||
TypedClause, TypedDataType, TypedFunction, TypedPattern, TypedValidator, UnOp,
|
TypedClause, TypedDataType, TypedFunction, TypedPattern, TypedValidator, UnOp,
|
||||||
},
|
},
|
||||||
builtins::{bool, byte_array, data, int, list, option, pair, void, PRELUDE},
|
builtins::{
|
||||||
|
bool, byte_array, data, function, int, list, option, pair, script_context, script_purpose,
|
||||||
|
void, PRELUDE, SCRIPT_PURPOSE_MINT, SCRIPT_PURPOSE_SPEND,
|
||||||
|
},
|
||||||
expr::TypedExpr,
|
expr::TypedExpr,
|
||||||
gen_uplc::{
|
gen_uplc::{
|
||||||
air::ExpectLevel,
|
air::ExpectLevel,
|
||||||
|
@ -142,7 +145,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
expressions: vec![
|
expressions: vec![
|
||||||
TypedExpr::Assignment {
|
TypedExpr::Assignment {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
tipo: data(),
|
tipo: script_context(),
|
||||||
value: TypedExpr::Var {
|
value: TypedExpr::Var {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
constructor: ValueConstructor {
|
constructor: ValueConstructor {
|
||||||
|
@ -150,7 +153,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
variant: ValueConstructorVariant::LocalVariable {
|
variant: ValueConstructorVariant::LocalVariable {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
},
|
},
|
||||||
tipo: data(),
|
tipo: script_context(),
|
||||||
},
|
},
|
||||||
name: "__context__".to_string(),
|
name: "__context__".to_string(),
|
||||||
}
|
}
|
||||||
|
@ -165,7 +168,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
value: TypedPattern::Var {
|
value: TypedPattern::Var {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
name: "__purpose__".to_string(),
|
name: "__transaction__".to_string(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
CallArg {
|
CallArg {
|
||||||
|
@ -173,7 +176,15 @@ impl<'a> CodeGenerator<'a> {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
value: TypedPattern::Var {
|
value: TypedPattern::Var {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
name: "__transaction__".to_string(),
|
name: "__redeemer__".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
CallArg {
|
||||||
|
label: None,
|
||||||
|
location: Span::empty(),
|
||||||
|
value: TypedPattern::Var {
|
||||||
|
location: Span::empty(),
|
||||||
|
name: "__purpose__".to_string(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -183,7 +194,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
field_map: None,
|
field_map: None,
|
||||||
},
|
},
|
||||||
spread_location: None,
|
spread_location: None,
|
||||||
tipo: data(),
|
tipo: function(vec![data(), data(), script_purpose()], data()),
|
||||||
},
|
},
|
||||||
kind: AssignmentKind::let_(),
|
kind: AssignmentKind::let_(),
|
||||||
},
|
},
|
||||||
|
@ -197,37 +208,31 @@ impl<'a> CodeGenerator<'a> {
|
||||||
variant: ValueConstructorVariant::LocalVariable {
|
variant: ValueConstructorVariant::LocalVariable {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
},
|
},
|
||||||
tipo: data(),
|
tipo: script_purpose(),
|
||||||
},
|
},
|
||||||
name: "__purpose__".to_string(),
|
name: "__purpose__".to_string(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
clauses: handlers
|
clauses: handlers
|
||||||
.iter()
|
.iter()
|
||||||
.chain(std::iter::once(fallback))
|
|
||||||
.map(|handler| {
|
.map(|handler| {
|
||||||
let mut arguments = vec![];
|
let datum = if handler.name.as_str() == "spend" {
|
||||||
|
handler.arguments.first()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
for i in 0..(handler.arguments.len() - 1) {
|
let redeemer = handler
|
||||||
let argument = &handler.arguments[i];
|
.arguments
|
||||||
|
.get(if datum.is_some() { 1 } else { 0 })
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
arguments.push(CallArg {
|
let purpose_arg = handler.arguments.iter().nth_back(1).unwrap();
|
||||||
label: None,
|
|
||||||
location: Span::empty(),
|
let transaction = handler.arguments.last().unwrap();
|
||||||
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(),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// handler
|
// handler
|
||||||
|
//
|
||||||
// spend(datum: Option<Datum>, redeemer, oref, anything) => Spend(datum, redeemer, oref, transaction)
|
// spend(datum: Option<Datum>, redeemer, oref, anything) => Spend(datum, redeemer, oref, transaction)
|
||||||
// spend(datum: Datum) => Spend(datum, redeemer, oref, transaction)
|
// spend(datum: Datum) => Spend(datum, redeemer, oref, transaction)
|
||||||
// spend(redeemer) => Spend(__datum__, redeemer, oref, transaction)
|
// spend(redeemer) => Spend(__datum__, redeemer, oref, transaction)
|
||||||
|
@ -236,59 +241,133 @@ impl<'a> CodeGenerator<'a> {
|
||||||
"spend" => TypedPattern::Constructor {
|
"spend" => TypedPattern::Constructor {
|
||||||
is_record: false,
|
is_record: false,
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
name: "Spend".to_string(),
|
name: SCRIPT_PURPOSE_SPEND.to_string(),
|
||||||
arguments: if handler.arguments.len() == 4 {
|
arguments: vec![
|
||||||
arguments
|
CallArg {
|
||||||
} else {
|
label: None,
|
||||||
vec![CallArg {
|
location: Span::empty(),
|
||||||
|
value: TypedPattern::Var {
|
||||||
|
name: "__purpose_arg__".to_string(),
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
CallArg {
|
||||||
label: None,
|
label: None,
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
value: TypedPattern::Var {
|
value: TypedPattern::Var {
|
||||||
name: "__datum__".to_string(),
|
name: "__datum__".to_string(),
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
},
|
},
|
||||||
}]
|
|
||||||
.into_iter()
|
|
||||||
.chain(arguments)
|
|
||||||
.collect()
|
|
||||||
},
|
},
|
||||||
|
],
|
||||||
module: None,
|
module: None,
|
||||||
constructor: PatternConstructor::Record {
|
constructor: PatternConstructor::Record {
|
||||||
name: "Spend".to_string(),
|
name: SCRIPT_PURPOSE_SPEND.to_string(),
|
||||||
field_map: None,
|
field_map: None,
|
||||||
},
|
},
|
||||||
spread_location: None,
|
spread_location: None,
|
||||||
tipo: data(),
|
tipo: function(
|
||||||
|
vec![data(), option(data())],
|
||||||
|
script_purpose(),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
"mint" => TypedPattern::Constructor {
|
"mint" => TypedPattern::Constructor {
|
||||||
is_record: false,
|
is_record: false,
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
name: "Mint".to_string(),
|
name: SCRIPT_PURPOSE_MINT.to_string(),
|
||||||
arguments,
|
arguments: vec![CallArg {
|
||||||
|
label: None,
|
||||||
|
location: Span::empty(),
|
||||||
|
value: TypedPattern::Var {
|
||||||
|
name: "__purpose_arg__".to_string(),
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
}],
|
||||||
module: None,
|
module: None,
|
||||||
constructor: PatternConstructor::Record {
|
constructor: PatternConstructor::Record {
|
||||||
name: "Mint".to_string(),
|
name: SCRIPT_PURPOSE_MINT.to_string(),
|
||||||
field_map: None,
|
field_map: None,
|
||||||
},
|
},
|
||||||
spread_location: None,
|
spread_location: None,
|
||||||
tipo: data(),
|
tipo: function(vec![data()], script_purpose()),
|
||||||
},
|
|
||||||
_ => TypedPattern::Var {
|
|
||||||
location: Span::empty(),
|
|
||||||
name: "__context__".to_string(),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
purpose => {
|
||||||
|
unreachable!("unexpected/unknown purpose: {:?}", purpose)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut then = vec![];
|
let mut then = vec![];
|
||||||
|
|
||||||
let last_arg = handler.arguments.last().unwrap();
|
// expect redeemer: tipo = __redeemer__
|
||||||
|
|
||||||
// let last_arg_name = __transaction__
|
|
||||||
if let Some(last_arg_name) = last_arg.get_variable_name() {
|
|
||||||
then.push(TypedExpr::Assignment {
|
then.push(TypedExpr::Assignment {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
|
tipo: redeemer.tipo.clone(),
|
||||||
|
value: TypedExpr::Var {
|
||||||
|
location: Span::empty(),
|
||||||
|
constructor: ValueConstructor {
|
||||||
|
public: true,
|
||||||
|
variant: ValueConstructorVariant::LocalVariable {
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
tipo: data(),
|
tipo: 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: option(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 last_arg_name = __transaction__
|
||||||
|
if let Some(arg_name) = transaction.get_variable_name() {
|
||||||
|
then.push(TypedExpr::Assignment {
|
||||||
|
location: Span::empty(),
|
||||||
|
tipo: purpose_arg.tipo.clone(),
|
||||||
value: TypedExpr::Var {
|
value: TypedExpr::Var {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
constructor: ValueConstructor {
|
constructor: ValueConstructor {
|
||||||
|
@ -303,97 +382,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.into(),
|
.into(),
|
||||||
pattern: TypedPattern::Var {
|
pattern: TypedPattern::Var {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
name: last_arg_name.to_string(),
|
name: arg_name.to_string(),
|
||||||
},
|
},
|
||||||
kind: AssignmentKind::let_(),
|
kind: AssignmentKind::let_(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let first_arg = handler.arguments.first().unwrap();
|
|
||||||
|
|
||||||
if handler.name.as_str() == "spend" {
|
|
||||||
if handler.arguments.len() == 3 {
|
|
||||||
// implicit None
|
|
||||||
then.push(TypedExpr::Assignment {
|
|
||||||
location: Span::empty(),
|
|
||||||
tipo: option(data()),
|
|
||||||
value: TypedExpr::Var {
|
|
||||||
location: Span::empty(),
|
|
||||||
constructor: ValueConstructor {
|
|
||||||
public: true,
|
|
||||||
variant:
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
tipo: option(data()),
|
|
||||||
},
|
|
||||||
name: "__datum__".to_string(),
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
pattern: TypedPattern::Constructor {
|
|
||||||
is_record: false,
|
|
||||||
location: Span::empty(),
|
|
||||||
name: "None".to_string(),
|
|
||||||
arguments: vec![],
|
|
||||||
module: None,
|
|
||||||
constructor: PatternConstructor::Record {
|
|
||||||
name: "None".to_string(),
|
|
||||||
field_map: None,
|
|
||||||
},
|
|
||||||
spread_location: None,
|
|
||||||
tipo: option(data()),
|
|
||||||
},
|
|
||||||
kind: AssignmentKind::expect(),
|
|
||||||
})
|
|
||||||
} else if !first_arg.tipo.is_option() {
|
|
||||||
// implicit Some
|
|
||||||
then.push(TypedExpr::Assignment {
|
|
||||||
location: Span::empty(),
|
|
||||||
tipo: option(data()),
|
|
||||||
value: TypedExpr::Var {
|
|
||||||
location: Span::empty(),
|
|
||||||
constructor: ValueConstructor {
|
|
||||||
public: true,
|
|
||||||
variant:
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
tipo: option(data()),
|
|
||||||
},
|
|
||||||
name: first_arg.get_name(),
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
pattern: TypedPattern::Constructor {
|
|
||||||
is_record: false,
|
|
||||||
location: Span::empty(),
|
|
||||||
name: "Some".to_string(),
|
|
||||||
arguments: vec![CallArg {
|
|
||||||
label: None,
|
|
||||||
location: Span::empty(),
|
|
||||||
value: first_arg
|
|
||||||
.get_variable_name()
|
|
||||||
.map(|name| TypedPattern::Var {
|
|
||||||
location: Span::empty(),
|
|
||||||
name: name.to_string(),
|
|
||||||
})
|
|
||||||
.unwrap_or(TypedPattern::Discard {
|
|
||||||
name: "_".to_string(),
|
|
||||||
location: Span::empty(),
|
|
||||||
}),
|
|
||||||
}],
|
|
||||||
module: None,
|
|
||||||
constructor: PatternConstructor::Record {
|
|
||||||
name: "Some".to_string(),
|
|
||||||
field_map: None,
|
|
||||||
},
|
|
||||||
spread_location: None,
|
|
||||||
tipo: option(first_arg.tipo.clone()),
|
|
||||||
},
|
|
||||||
kind: AssignmentKind::expect(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
then.push(handler.body.clone());
|
then.push(handler.body.clone());
|
||||||
|
|
||||||
TypedClause {
|
TypedClause {
|
||||||
|
@ -405,6 +399,56 @@ impl<'a> CodeGenerator<'a> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// 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(),
|
.collect(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -419,16 +463,15 @@ impl<'a> CodeGenerator<'a> {
|
||||||
on_test_failure: OnTestFailure::FailImmediately,
|
on_test_failure: OnTestFailure::FailImmediately,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut air_tree_fun = self.build(&fun.body, module_name, &[]);
|
let mut air_tree_fun = AirTree::anon_func(
|
||||||
|
vec!["__context__".to_string()],
|
||||||
|
self.build(&fun.body, module_name, &[]),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
air_tree_fun = wrap_validator_condition(air_tree_fun, self.tracing);
|
air_tree_fun = wrap_validator_condition(air_tree_fun, self.tracing);
|
||||||
|
|
||||||
let (src_code, lines) = self.module_src.get(module_name).unwrap();
|
let validator_args_tree = AirTree::no_op(air_tree_fun);
|
||||||
|
|
||||||
let mut validator_args_tree =
|
|
||||||
self.check_validator_args(&fun.arguments, true, air_tree_fun, src_code, lines);
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
@ -1624,7 +1667,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
type_map.insert(index, field_type);
|
type_map.insert(index, field_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(type_map.len() >= arguments.len());
|
assert!(
|
||||||
|
type_map.len() >= arguments.len(),
|
||||||
|
"type map len: {}, arguments len: {}; for constructor {:?}",
|
||||||
|
type_map.len(),
|
||||||
|
arguments.len(),
|
||||||
|
name,
|
||||||
|
);
|
||||||
|
|
||||||
let mut fields = vec![];
|
let mut fields = vec![];
|
||||||
|
|
||||||
|
@ -1752,7 +1801,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
} else {
|
} else {
|
||||||
assert!(
|
assert!(
|
||||||
data_type.constructors.len() == 1,
|
data_type.constructors.len() == 1,
|
||||||
"data_type={data_type:#?}"
|
"attempted expect on a type with more or less than 1 constructor: \nis_expect? {}\nfull_check? {}\ndata_type={data_type:#?}\n{}",
|
||||||
|
props.kind.is_expect(),
|
||||||
|
props.full_check,
|
||||||
|
name,
|
||||||
);
|
);
|
||||||
then
|
then
|
||||||
};
|
};
|
||||||
|
@ -3030,7 +3082,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(!data_type.constructors.is_empty());
|
assert!(
|
||||||
|
!data_type.constructors.is_empty(),
|
||||||
|
"{}\n{constructor:#?}\n{data_type:#?}",
|
||||||
|
subject_tipo.to_pretty(0)
|
||||||
|
);
|
||||||
|
|
||||||
let (constr_index, _) = data_type
|
let (constr_index, _) = data_type
|
||||||
.constructors
|
.constructors
|
||||||
|
|
|
@ -294,7 +294,7 @@ mod tests {
|
||||||
|
|
||||||
let validators = Validator::from_checked_module(&modules, &mut generator, validator, def, &PlutusVersion::default());
|
let validators = Validator::from_checked_module(&modules, &mut generator, validator, def, &PlutusVersion::default());
|
||||||
|
|
||||||
if validators.len() > 1 {
|
if validators.len() > 2 {
|
||||||
panic!("Multi-validator given to test bench. Don't do that.")
|
panic!("Multi-validator given to test bench. Don't do that.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +395,7 @@ mod tests {
|
||||||
assert_validator!(
|
assert_validator!(
|
||||||
r#"
|
r#"
|
||||||
validator thing {
|
validator thing {
|
||||||
mint(redeemer: Data, ctx: Data) {
|
mint(redeemer: Data, policy_id: Data, transaction: Data) {
|
||||||
True
|
True
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue