Rework generate_raw to avoid need to intern in prop tests
Also, this commit makes `apply_term` automatically re-intern the program since it isn't safe to apply any term onto a UPLC program. In particular, terms that introduce new let-bindings (via lambdas) will mess with the already generated DeBruijn indices. The problem doesn't occur for pure constant terms like Data. So we still have a safe and fast version 'apply_data' when needed.
This commit is contained in:
parent
1134b8d7d0
commit
30841fe000
|
@ -184,8 +184,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
self.finalize(term)
|
self.finalize(term)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_raw(&mut self, test_body: &TypedExpr, module_name: &str) -> Program<Name> {
|
pub fn generate_raw(
|
||||||
let mut air_tree = self.build(test_body, module_name, &[]);
|
&mut self,
|
||||||
|
body: &TypedExpr,
|
||||||
|
args: &[TypedArg],
|
||||||
|
module_name: &str,
|
||||||
|
) -> Program<Name> {
|
||||||
|
let mut air_tree = self.build(body, module_name, &[]);
|
||||||
|
|
||||||
air_tree = AirTree::no_op(air_tree);
|
air_tree = AirTree::no_op(air_tree);
|
||||||
|
|
||||||
|
@ -194,7 +199,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
// optimizations on air tree
|
// optimizations on air tree
|
||||||
let full_vec = full_tree.to_vec();
|
let full_vec = full_tree.to_vec();
|
||||||
|
|
||||||
let term = self.uplc_code_gen(full_vec);
|
let mut term = self.uplc_code_gen(full_vec);
|
||||||
|
|
||||||
|
term = if args.is_empty() {
|
||||||
|
term
|
||||||
|
} else {
|
||||||
|
cast_validator_args(term, args)
|
||||||
|
};
|
||||||
|
|
||||||
self.finalize(term)
|
self.finalize(term)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use super::{
|
||||||
};
|
};
|
||||||
use std::{iter, ops::Deref};
|
use std::{iter, ops::Deref};
|
||||||
use uplc::{
|
use uplc::{
|
||||||
ast::{Constant, Data as UplcData, DeBruijn, Term},
|
ast::{Constant, Data as UplcData},
|
||||||
PlutusData,
|
PlutusData,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ impl Parameter {
|
||||||
pub fn validate(
|
pub fn validate(
|
||||||
&self,
|
&self,
|
||||||
definitions: &Definitions<Annotated<Schema>>,
|
definitions: &Definitions<Annotated<Schema>>,
|
||||||
term: &Term<DeBruijn>,
|
constant: &Constant,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let schema = &definitions
|
let schema = &definitions
|
||||||
.lookup(&self.schema)
|
.lookup(&self.schema)
|
||||||
|
@ -42,11 +42,7 @@ impl Parameter {
|
||||||
})?
|
})?
|
||||||
.annotated;
|
.annotated;
|
||||||
|
|
||||||
if let Term::Constant(constant) = term {
|
|
||||||
validate_schema(schema, definitions, constant)
|
validate_schema(schema, definitions, constant)
|
||||||
} else {
|
|
||||||
Err(Error::NonConstantParameter)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,11 +348,13 @@ fn expect_data_constr(term: &Constant, index: usize) -> Result<Vec<Constant>, Er
|
||||||
|
|
||||||
Err(mismatch(
|
Err(mismatch(
|
||||||
term,
|
term,
|
||||||
Schema::Data(Data::AnyOf(vec![Constructor {
|
Schema::Data(Data::AnyOf(vec![
|
||||||
|
Constructor {
|
||||||
index,
|
index,
|
||||||
fields: vec![],
|
fields: vec![],
|
||||||
}
|
}
|
||||||
.into()])),
|
.into(),
|
||||||
|
])),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ use aiken_lang::{
|
||||||
};
|
};
|
||||||
use miette::NamedSource;
|
use miette::NamedSource;
|
||||||
use serde;
|
use serde;
|
||||||
use std::{borrow::Borrow, rc::Rc};
|
use std::borrow::Borrow;
|
||||||
use uplc::{
|
use uplc::{
|
||||||
ast::{Constant, DeBruijn, Program, Term},
|
ast::{Constant, DeBruijn, Program},
|
||||||
PlutusData,
|
PlutusData,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,14 +198,14 @@ impl Validator {
|
||||||
pub fn apply(
|
pub fn apply(
|
||||||
self,
|
self,
|
||||||
definitions: &Definitions<Annotated<Schema>>,
|
definitions: &Definitions<Annotated<Schema>>,
|
||||||
arg: &Term<DeBruijn>,
|
arg: &PlutusData,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
match self.parameters.split_first() {
|
match self.parameters.split_first() {
|
||||||
None => Err(Error::NoParametersToApply),
|
None => Err(Error::NoParametersToApply),
|
||||||
Some((head, tail)) => {
|
Some((head, tail)) => {
|
||||||
head.validate(definitions, arg)?;
|
head.validate(definitions, &Constant::Data(arg.clone()))?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
program: self.program.apply_term(arg),
|
program: self.program.apply_data(arg.clone()),
|
||||||
parameters: tail.to_vec(),
|
parameters: tail.to_vec(),
|
||||||
..self
|
..self
|
||||||
})
|
})
|
||||||
|
@ -217,7 +217,7 @@ impl Validator {
|
||||||
&self,
|
&self,
|
||||||
definitions: &Definitions<Annotated<Schema>>,
|
definitions: &Definitions<Annotated<Schema>>,
|
||||||
ask: F,
|
ask: F,
|
||||||
) -> Result<Term<DeBruijn>, Error>
|
) -> Result<PlutusData, Error>
|
||||||
where
|
where
|
||||||
F: Fn(&Annotated<Schema>, &Definitions<Annotated<Schema>>) -> Result<PlutusData, Error>,
|
F: Fn(&Annotated<Schema>, &Definitions<Annotated<Schema>>) -> Result<PlutusData, Error>,
|
||||||
{
|
{
|
||||||
|
@ -241,7 +241,7 @@ impl Validator {
|
||||||
|
|
||||||
let data = ask(&schema, definitions)?;
|
let data = ask(&schema, definitions)?;
|
||||||
|
|
||||||
Ok(Term::Constant(Rc::new(Constant::Data(data.clone()))))
|
Ok(data.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -619,7 +619,7 @@ mod tests {
|
||||||
fn validate_arguments_integer() {
|
fn validate_arguments_integer() {
|
||||||
let definitions = fixture_definitions();
|
let definitions = fixture_definitions();
|
||||||
|
|
||||||
let term = Term::data(uplc_ast::Data::integer(42.into()));
|
let term = Constant::Data(uplc_ast::Data::integer(42.into()));
|
||||||
|
|
||||||
let param = Parameter {
|
let param = Parameter {
|
||||||
title: None,
|
title: None,
|
||||||
|
@ -633,7 +633,7 @@ mod tests {
|
||||||
fn validate_arguments_bytestring() {
|
fn validate_arguments_bytestring() {
|
||||||
let definitions = fixture_definitions();
|
let definitions = fixture_definitions();
|
||||||
|
|
||||||
let term = Term::data(uplc_ast::Data::bytestring(vec![102, 111, 111]));
|
let term = Constant::Data(uplc_ast::Data::bytestring(vec![102, 111, 111]));
|
||||||
|
|
||||||
let param = Parameter {
|
let param = Parameter {
|
||||||
title: None,
|
title: None,
|
||||||
|
@ -662,7 +662,7 @@ mod tests {
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let term = Term::data(uplc_ast::Data::list(vec![
|
let term = Constant::Data(uplc_ast::Data::list(vec![
|
||||||
uplc_ast::Data::integer(42.into()),
|
uplc_ast::Data::integer(42.into()),
|
||||||
uplc_ast::Data::integer(14.into()),
|
uplc_ast::Data::integer(14.into()),
|
||||||
]));
|
]));
|
||||||
|
@ -691,7 +691,7 @@ mod tests {
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let term = Term::data(uplc_ast::Data::list(vec![uplc_ast::Data::bytestring(
|
let term = Constant::Data(uplc_ast::Data::list(vec![uplc_ast::Data::bytestring(
|
||||||
vec![102, 111, 111],
|
vec![102, 111, 111],
|
||||||
)]));
|
)]));
|
||||||
|
|
||||||
|
@ -723,7 +723,7 @@ mod tests {
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let term = Term::data(uplc_ast::Data::list(vec![
|
let term = Constant::Data(uplc_ast::Data::list(vec![
|
||||||
uplc_ast::Data::integer(42.into()),
|
uplc_ast::Data::integer(42.into()),
|
||||||
uplc_ast::Data::bytestring(vec![102, 111, 111]),
|
uplc_ast::Data::bytestring(vec![102, 111, 111]),
|
||||||
]));
|
]));
|
||||||
|
@ -754,7 +754,7 @@ mod tests {
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let term = Term::data(uplc_ast::Data::map(vec![(
|
let term = Constant::Data(uplc_ast::Data::map(vec![(
|
||||||
uplc_ast::Data::bytestring(vec![102, 111, 111]),
|
uplc_ast::Data::bytestring(vec![102, 111, 111]),
|
||||||
uplc_ast::Data::integer(42.into()),
|
uplc_ast::Data::integer(42.into()),
|
||||||
)]));
|
)]));
|
||||||
|
@ -770,7 +770,7 @@ mod tests {
|
||||||
|
|
||||||
let definitions = fixture_definitions();
|
let definitions = fixture_definitions();
|
||||||
|
|
||||||
let term = Term::data(uplc_ast::Data::constr(1, vec![]));
|
let term = Constant::Data(uplc_ast::Data::constr(1, vec![]));
|
||||||
|
|
||||||
let param: Parameter = schema.into();
|
let param: Parameter = schema.into();
|
||||||
|
|
||||||
|
@ -807,7 +807,7 @@ mod tests {
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let term = Term::data(uplc_ast::Data::constr(
|
let term = Constant::Data(uplc_ast::Data::constr(
|
||||||
0,
|
0,
|
||||||
vec![uplc_ast::Data::constr(0, vec![])],
|
vec![uplc_ast::Data::constr(0, vec![])],
|
||||||
));
|
));
|
||||||
|
@ -863,7 +863,7 @@ mod tests {
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let term = Term::data(uplc_ast::Data::constr(
|
let term = Constant::Data(uplc_ast::Data::constr(
|
||||||
1,
|
1,
|
||||||
vec![
|
vec![
|
||||||
uplc_ast::Data::integer(14.into()),
|
uplc_ast::Data::integer(14.into()),
|
||||||
|
|
|
@ -59,7 +59,7 @@ use std::{
|
||||||
use telemetry::EventListener;
|
use telemetry::EventListener;
|
||||||
use test_framework::{Test, TestResult};
|
use test_framework::{Test, TestResult};
|
||||||
use uplc::{
|
use uplc::{
|
||||||
ast::{DeBruijn, Name, Program, Term},
|
ast::{Name, Program},
|
||||||
PlutusData,
|
PlutusData,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -445,7 +445,7 @@ where
|
||||||
&self,
|
&self,
|
||||||
title: Option<&String>,
|
title: Option<&String>,
|
||||||
ask: F,
|
ask: F,
|
||||||
) -> Result<Term<DeBruijn>, Error>
|
) -> Result<PlutusData, Error>
|
||||||
where
|
where
|
||||||
F: Fn(
|
F: Fn(
|
||||||
&Annotated<Schema>,
|
&Annotated<Schema>,
|
||||||
|
@ -462,19 +462,19 @@ where
|
||||||
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
|known_validators| Error::MoreThanOneValidatorFound { known_validators };
|
||||||
let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators };
|
let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators };
|
||||||
|
|
||||||
let term = blueprint.with_validator(title, when_too_many, when_missing, |validator| {
|
let data = blueprint.with_validator(title, when_too_many, when_missing, |validator| {
|
||||||
validator
|
validator
|
||||||
.ask_next_parameter(&blueprint.definitions, &ask)
|
.ask_next_parameter(&blueprint.definitions, &ask)
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(term)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_parameter(
|
pub fn apply_parameter(
|
||||||
&self,
|
&self,
|
||||||
title: Option<&String>,
|
title: Option<&String>,
|
||||||
param: &Term<DeBruijn>,
|
param: &PlutusData,
|
||||||
) -> Result<Blueprint, Error> {
|
) -> Result<Blueprint, Error> {
|
||||||
// Read blueprint
|
// Read blueprint
|
||||||
let blueprint = File::open(self.blueprint_path())
|
let blueprint = File::open(self.blueprint_path())
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
use crate::pretty;
|
use crate::pretty;
|
||||||
use aiken_lang::{
|
use aiken_lang::{
|
||||||
ast::{BinOp, DataTypeKey, Span, TypedDataType, TypedTest},
|
ast::{Arg, BinOp, DataTypeKey, TypedDataType, TypedTest},
|
||||||
expr::{TypedExpr, UntypedExpr},
|
expr::UntypedExpr,
|
||||||
gen_uplc::{
|
gen_uplc::{builder::convert_opaque_type, CodeGenerator},
|
||||||
builder::{convert_data_to_type, convert_opaque_type},
|
|
||||||
CodeGenerator,
|
|
||||||
},
|
|
||||||
tipo::Type,
|
tipo::Type,
|
||||||
};
|
};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
@ -22,7 +19,6 @@ use std::{
|
||||||
use uplc::{
|
use uplc::{
|
||||||
ast::{Constant, Data, Name, NamedDeBruijn, Program, Term},
|
ast::{Constant, Data, Name, NamedDeBruijn, Program, Term},
|
||||||
machine::{cost_model::ExBudget, eval_result::EvalResult},
|
machine::{cost_model::ExBudget, eval_result::EvalResult},
|
||||||
parser::interner::Interner,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ----- Test -----------------------------------------------------------------
|
/// ----- Test -----------------------------------------------------------------
|
||||||
|
@ -94,20 +90,20 @@ impl Test {
|
||||||
input_path: PathBuf,
|
input_path: PathBuf,
|
||||||
) -> Test {
|
) -> Test {
|
||||||
if test.arguments.is_empty() {
|
if test.arguments.is_empty() {
|
||||||
let program = generator.generate_raw(&test.body, &module_name);
|
let program = generator.generate_raw(&test.body, &[], &module_name);
|
||||||
|
|
||||||
// TODO: Check whether we really need to clone the _entire_ generator, or whether we
|
// TODO: Check whether we really need to clone the _entire_ generator, or whether we
|
||||||
// can mostly copy the generator and only clone parts that matters.
|
// can mostly copy the generator and only clone parts that matters.
|
||||||
let assertion = test.test_hint().map(|(bin_op, left_src, right_src)| {
|
let assertion = test.test_hint().map(|(bin_op, left_src, right_src)| {
|
||||||
let left = generator
|
let left = generator
|
||||||
.clone()
|
.clone()
|
||||||
.generate_raw(&left_src, &module_name)
|
.generate_raw(&left_src, &[], &module_name)
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let right = generator
|
let right = generator
|
||||||
.clone()
|
.clone()
|
||||||
.generate_raw(&right_src, &module_name)
|
.generate_raw(&right_src, &[], &module_name)
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -134,23 +130,21 @@ impl Test {
|
||||||
|
|
||||||
let type_info = parameter.tipo.clone();
|
let type_info = parameter.tipo.clone();
|
||||||
|
|
||||||
// TODO: Possibly refactor 'generate_raw' to accept arguments and do this wrapping
|
let stripped_type_info = convert_opaque_type(&type_info, generator.data_types(), true);
|
||||||
// itself.
|
|
||||||
let body = TypedExpr::Fn {
|
|
||||||
location: Span::empty(),
|
|
||||||
tipo: Rc::new(Type::Fn {
|
|
||||||
args: vec![type_info.clone()],
|
|
||||||
ret: test.body.tipo(),
|
|
||||||
}),
|
|
||||||
is_capture: false,
|
|
||||||
args: vec![parameter.into()],
|
|
||||||
body: Box::new(test.body),
|
|
||||||
return_annotation: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let program = generator.clone().generate_raw(&body, &module_name);
|
let program = generator.clone().generate_raw(
|
||||||
|
&test.body,
|
||||||
|
&[Arg {
|
||||||
|
tipo: stripped_type_info.clone(),
|
||||||
|
..parameter.clone().into()
|
||||||
|
}],
|
||||||
|
&module_name,
|
||||||
|
);
|
||||||
|
|
||||||
let fuzzer = generator.clone().generate_raw(&via, &module_name);
|
// NOTE: We need not to pass any parameter to the fuzzer here because the fuzzer
|
||||||
|
// argument is a Data constructor which needs not any conversion. So we can just safely
|
||||||
|
// apply onto it later.
|
||||||
|
let fuzzer = generator.clone().generate_raw(&via, &[], &module_name);
|
||||||
|
|
||||||
Self::property_test(
|
Self::property_test(
|
||||||
input_path,
|
input_path,
|
||||||
|
@ -160,11 +154,7 @@ impl Test {
|
||||||
program,
|
program,
|
||||||
Fuzzer {
|
Fuzzer {
|
||||||
program: fuzzer,
|
program: fuzzer,
|
||||||
stripped_type_info: convert_opaque_type(
|
stripped_type_info,
|
||||||
&type_info,
|
|
||||||
generator.data_types(),
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
type_info,
|
type_info,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -277,6 +267,8 @@ impl PropertyTest {
|
||||||
} = next_prng
|
} = next_prng
|
||||||
{
|
{
|
||||||
if result.failed(self.can_error) {
|
if result.failed(self.can_error) {
|
||||||
|
println!("{:#?}", result.result());
|
||||||
|
|
||||||
let mut counterexample = Counterexample {
|
let mut counterexample = Counterexample {
|
||||||
value,
|
value,
|
||||||
choices: next_prng.choices(),
|
choices: next_prng.choices(),
|
||||||
|
@ -297,12 +289,7 @@ impl PropertyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval(&self, value: &PlutusData) -> EvalResult {
|
pub fn eval(&self, value: &PlutusData) -> EvalResult {
|
||||||
let term: Term<Name> =
|
let program = self.program.apply_data(value.clone());
|
||||||
convert_data_to_type(Term::data(value.clone()), &self.fuzzer.stripped_type_info);
|
|
||||||
|
|
||||||
let mut program = self.program.apply_term(&term);
|
|
||||||
|
|
||||||
Interner::new().program(&mut program);
|
|
||||||
|
|
||||||
Program::<NamedDeBruijn>::try_from(program)
|
Program::<NamedDeBruijn>::try_from(program)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
@ -49,7 +49,7 @@ fn assert_uplc(source_code: &str, expected: Term<Name>, should_fail: bool) {
|
||||||
|
|
||||||
match &script.2 {
|
match &script.2 {
|
||||||
TestType::Func(Function { body: func, .. }) => {
|
TestType::Func(Function { body: func, .. }) => {
|
||||||
let program = generator.generate_raw(func, &script.1);
|
let program = generator.generate_raw(func, &[], &script.1);
|
||||||
|
|
||||||
let debruijn_program: Program<DeBruijn> = program.try_into().unwrap();
|
let debruijn_program: Program<DeBruijn> = program.try_into().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,8 @@ use num_bigint::BigInt;
|
||||||
use ordinal::Ordinal;
|
use ordinal::Ordinal;
|
||||||
use owo_colors::{OwoColorize, Stream::Stderr};
|
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||||
use pallas::ledger::primitives::alonzo::PlutusData;
|
use pallas::ledger::primitives::alonzo::PlutusData;
|
||||||
use std::str::FromStr;
|
use std::{fs, path::PathBuf, process, str::FromStr};
|
||||||
use std::{fs, path::PathBuf, process, rc::Rc};
|
use uplc::ast::Data as UplcData;
|
||||||
use uplc::ast::{Constant, Data as UplcData, DeBruijn, Term};
|
|
||||||
|
|
||||||
/// Apply a parameter to a parameterized validator.
|
/// Apply a parameter to a parameterized validator.
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
|
@ -68,7 +67,7 @@ pub fn exec(
|
||||||
.if_supports_color(Stderr, |s| s.bold()),
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let term: Term<DeBruijn> = match ¶meter {
|
let data: PlutusData = match ¶meter {
|
||||||
Some(param) => {
|
Some(param) => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"{} inputs",
|
"{} inputs",
|
||||||
|
@ -90,7 +89,7 @@ pub fn exec(
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
});
|
});
|
||||||
|
|
||||||
let data = uplc::plutus_data(&bytes)
|
uplc::plutus_data(&bytes)
|
||||||
.map_err::<Error, _>(|e| {
|
.map_err::<Error, _>(|e| {
|
||||||
blueprint::error::Error::MalformedParameter {
|
blueprint::error::Error::MalformedParameter {
|
||||||
hint: format!("Invalid Plutus data; malformed CBOR encoding: {e}"),
|
hint: format!("Invalid Plutus data; malformed CBOR encoding: {e}"),
|
||||||
|
@ -101,9 +100,7 @@ pub fn exec(
|
||||||
println!();
|
println!();
|
||||||
e.report();
|
e.report();
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
});
|
})
|
||||||
|
|
||||||
Term::Constant(Rc::new(Constant::Data(data)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None => p.construct_parameter_incrementally(title, ask_schema)?,
|
None => p.construct_parameter_incrementally(title, ask_schema)?,
|
||||||
|
@ -114,16 +111,13 @@ pub fn exec(
|
||||||
" Applying"
|
" Applying"
|
||||||
.if_supports_color(Stderr, |s| s.purple())
|
.if_supports_color(Stderr, |s| s.purple())
|
||||||
.if_supports_color(Stderr, |s| s.bold()),
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
match TryInto::<PlutusData>::try_into(term.clone()) {
|
{
|
||||||
Ok(data) => {
|
|
||||||
let padding = "\n ";
|
let padding = "\n ";
|
||||||
multiline(48, UplcData::to_hex(data)).join(padding)
|
multiline(48, UplcData::to_hex(data.clone())).join(padding)
|
||||||
}
|
|
||||||
Err(_) => term.to_pretty(),
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let blueprint = p.apply_parameter(title, &term)?;
|
let blueprint = p.apply_parameter(title, &data)?;
|
||||||
|
|
||||||
let json = serde_json::to_string_pretty(&blueprint).unwrap();
|
let json = serde_json::to_string_pretty(&blueprint).unwrap();
|
||||||
|
|
||||||
|
@ -179,16 +173,21 @@ fn ask_schema(
|
||||||
}
|
}
|
||||||
|
|
||||||
Schema::Data(Data::List(Items::Many(ref decls))) => {
|
Schema::Data(Data::List(Items::Many(ref decls))) => {
|
||||||
eprintln!(" {}", asking(schema, "Found", &format!("a {}-tuple", decls.len())));
|
eprintln!(
|
||||||
|
" {}",
|
||||||
|
asking(schema, "Found", &format!("a {}-tuple", decls.len()))
|
||||||
|
);
|
||||||
|
|
||||||
let mut elems = vec![];
|
let mut elems = vec![];
|
||||||
|
|
||||||
for (ix, decl) in decls.iter().enumerate() {
|
for (ix, decl) in decls.iter().enumerate() {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
" {} Tuple's {}{} element",
|
" {} Tuple's {}{} element",
|
||||||
"Asking".if_supports_color(Stderr, |s| s.purple()).if_supports_color(Stderr, |s| s.bold()),
|
"Asking"
|
||||||
ix+1,
|
.if_supports_color(Stderr, |s| s.purple())
|
||||||
Ordinal::<usize>(ix+1).suffix()
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
|
ix + 1,
|
||||||
|
Ordinal::<usize>(ix + 1).suffix()
|
||||||
);
|
);
|
||||||
let inner_schema = lookup_declaration(&decl.clone().into(), definitions);
|
let inner_schema = lookup_declaration(&decl.clone().into(), definitions);
|
||||||
elems.push(ask_schema(&inner_schema, definitions)?);
|
elems.push(ask_schema(&inner_schema, definitions)?);
|
||||||
|
@ -252,7 +251,9 @@ fn ask_schema(
|
||||||
Ok(UplcData::constr(ix.try_into().unwrap(), fields))
|
Ok(UplcData::constr(ix.try_into().unwrap(), fields))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => unimplemented!("Hey! You've found a case that we haven't implemented yet. Yes, we've been a bit lazy on that one... If that use-case is important to you, please let us know on Discord or on Github."),
|
_ => unimplemented!(
|
||||||
|
"Hey! You've found a case that we haven't implemented yet. Yes, we've been a bit lazy on that one... If that use-case is important to you, please let us know on Discord or on Github."
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,39 +30,41 @@ pub fn exec(
|
||||||
cbor,
|
cbor,
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
let mut program = if cbor {
|
let mut program: Program<Name> = if cbor {
|
||||||
let cbor_hex = std::fs::read_to_string(&script).into_diagnostic()?;
|
let cbor_hex = std::fs::read_to_string(&script).into_diagnostic()?;
|
||||||
|
|
||||||
let raw_cbor = hex::decode(cbor_hex.trim()).into_diagnostic()?;
|
let raw_cbor = hex::decode(cbor_hex.trim()).into_diagnostic()?;
|
||||||
|
|
||||||
let prog = Program::<FakeNamedDeBruijn>::from_cbor(&raw_cbor, &mut Vec::new())
|
let program = Program::<FakeNamedDeBruijn>::from_cbor(&raw_cbor, &mut Vec::new())
|
||||||
.into_diagnostic()?;
|
.into_diagnostic()?;
|
||||||
|
|
||||||
prog.into()
|
let program: Program<NamedDeBruijn> = program.into();
|
||||||
|
|
||||||
|
Program::<Name>::try_from(program).into_diagnostic()?
|
||||||
} else if flat {
|
} else if flat {
|
||||||
let bytes = std::fs::read(&script).into_diagnostic()?;
|
let bytes = std::fs::read(&script).into_diagnostic()?;
|
||||||
|
|
||||||
let prog = Program::<FakeNamedDeBruijn>::from_flat(&bytes).into_diagnostic()?;
|
let program = Program::<FakeNamedDeBruijn>::from_flat(&bytes).into_diagnostic()?;
|
||||||
|
|
||||||
prog.into()
|
let program: Program<NamedDeBruijn> = program.into();
|
||||||
|
|
||||||
|
Program::<Name>::try_from(program).into_diagnostic()?
|
||||||
} else {
|
} else {
|
||||||
let code = std::fs::read_to_string(&script).into_diagnostic()?;
|
let code = std::fs::read_to_string(&script).into_diagnostic()?;
|
||||||
|
|
||||||
let prog = parser::program(&code).into_diagnostic()?;
|
parser::program(&code).into_diagnostic()?
|
||||||
|
|
||||||
Program::<NamedDeBruijn>::try_from(prog).into_diagnostic()?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let term = parser::term(&arg).into_diagnostic()?;
|
let term = parser::term(&arg).into_diagnostic()?;
|
||||||
|
|
||||||
let term = Term::<NamedDeBruijn>::try_from(term).into_diagnostic()?;
|
program = program.apply_term(&term)
|
||||||
|
|
||||||
program = program.apply_term(&term);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let budget = ExBudget::default();
|
let budget = ExBudget::default();
|
||||||
|
|
||||||
|
let program = Program::<NamedDeBruijn>::try_from(program).into_diagnostic()?;
|
||||||
|
|
||||||
let mut eval_result = program.eval(budget);
|
let mut eval_result = program.eval(budget);
|
||||||
|
|
||||||
let cost = eval_result.cost();
|
let cost = eval_result.cost();
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
||||||
eval_result::EvalResult,
|
eval_result::EvalResult,
|
||||||
Machine,
|
Machine,
|
||||||
},
|
},
|
||||||
|
parser::interner::Interner,
|
||||||
};
|
};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
|
@ -18,7 +19,6 @@ use pallas::ledger::{
|
||||||
},
|
},
|
||||||
traverse::ComputeHash,
|
traverse::ComputeHash,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{
|
use serde::{
|
||||||
self,
|
self,
|
||||||
de::{self, Deserialize, Deserializer, MapAccess, Visitor},
|
de::{self, Deserialize, Deserializer, MapAccess, Visitor},
|
||||||
|
@ -58,21 +58,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We use this to apply the validator to Datum,
|
/// A convenient and faster version that `apply_term` since the program doesn't need to be
|
||||||
/// then redeemer, then ScriptContext. If datum is
|
/// re-interned (constant Data do not introduce new bindings).
|
||||||
/// even necessary (i.e. minting policy).
|
|
||||||
pub fn apply_term(&self, term: &Term<T>) -> Self {
|
|
||||||
let applied_term = Term::Apply {
|
|
||||||
function: Rc::new(self.term.clone()),
|
|
||||||
argument: Rc::new(term.clone()),
|
|
||||||
};
|
|
||||||
|
|
||||||
Program {
|
|
||||||
version: self.version,
|
|
||||||
term: applied_term,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn apply_data(&self, plutus_data: PlutusData) -> Self {
|
pub fn apply_data(&self, plutus_data: PlutusData) -> Self {
|
||||||
let applied_term = Term::Apply {
|
let applied_term = Term::Apply {
|
||||||
function: Rc::new(self.term.clone()),
|
function: Rc::new(self.term.clone()),
|
||||||
|
@ -86,6 +73,27 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Program<Name> {
|
||||||
|
/// We use this to apply the validator to Datum,
|
||||||
|
/// then redeemer, then ScriptContext. If datum is
|
||||||
|
/// even necessary (i.e. minting policy).
|
||||||
|
pub fn apply_term(&self, term: &Term<Name>) -> Self {
|
||||||
|
let applied_term = Term::Apply {
|
||||||
|
function: Rc::new(self.term.clone()),
|
||||||
|
argument: Rc::new(term.clone()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut program = Program {
|
||||||
|
version: self.version,
|
||||||
|
term: applied_term,
|
||||||
|
};
|
||||||
|
|
||||||
|
Interner::new().program(&mut program);
|
||||||
|
|
||||||
|
program
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, T> Display for Program<T>
|
impl<'a, T> Display for Program<T>
|
||||||
where
|
where
|
||||||
T: Binder<'a>,
|
T: Binder<'a>,
|
||||||
|
|
Loading…
Reference in New Issue