Merge pull request #166 from aiken-lang/some-interesting-test-cases
Include generics to get test cases working
This commit is contained in:
@@ -1,13 +1,18 @@
|
||||
use crate::{pretty, script::EvalHint};
|
||||
use aiken_lang::{
|
||||
ast::{BinOp, Span},
|
||||
parser::error::ParseError,
|
||||
tipo,
|
||||
};
|
||||
use miette::{
|
||||
Diagnostic, EyreContext, LabeledSpan, MietteHandlerOpts, NamedSource, RgbColors, SourceCode,
|
||||
};
|
||||
use std::{
|
||||
fmt::{Debug, Display},
|
||||
io,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use aiken_lang::{ast::Span, parser::error::ParseError, tipo};
|
||||
use miette::{
|
||||
Diagnostic, EyreContext, LabeledSpan, MietteHandlerOpts, NamedSource, RgbColors, SourceCode,
|
||||
};
|
||||
use uplc::machine::cost_model::ExBudget;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(thiserror::Error)]
|
||||
@@ -28,7 +33,7 @@ pub enum Error {
|
||||
#[error(transparent)]
|
||||
StandardIo(#[from] io::Error),
|
||||
|
||||
#[error("Syclical module imports")]
|
||||
#[error("Cyclical module imports")]
|
||||
ImportCycle { modules: Vec<String> },
|
||||
|
||||
/// Useful for returning many [`Error::Parse`] at once
|
||||
@@ -73,6 +78,15 @@ pub enum Error {
|
||||
src: String,
|
||||
named: NamedSource,
|
||||
},
|
||||
|
||||
#[error("{name} failed{}", if *verbose { format!("\n{src}") } else { String::new() } )]
|
||||
TestFailure {
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
verbose: bool,
|
||||
src: String,
|
||||
evaluation_hint: Option<EvalHint>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Error {
|
||||
@@ -148,6 +162,7 @@ impl Error {
|
||||
Error::Type { path, .. } => Some(path.to_path_buf()),
|
||||
Error::ValidatorMustReturnBool { path, .. } => Some(path.to_path_buf()),
|
||||
Error::WrongValidatorArity { path, .. } => Some(path.to_path_buf()),
|
||||
Error::TestFailure { path, .. } => Some(path.to_path_buf()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +178,7 @@ impl Error {
|
||||
Error::Type { src, .. } => Some(src.to_string()),
|
||||
Error::ValidatorMustReturnBool { src, .. } => Some(src.to_string()),
|
||||
Error::WrongValidatorArity { src, .. } => Some(src.to_string()),
|
||||
Error::TestFailure { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,6 +219,7 @@ impl Diagnostic for Error {
|
||||
Error::Format { .. } => None,
|
||||
Error::ValidatorMustReturnBool { .. } => Some(Box::new("aiken::scripts")),
|
||||
Error::WrongValidatorArity { .. } => Some(Box::new("aiken::validators")),
|
||||
Error::TestFailure { path, .. } => Some(Box::new(path.to_str().unwrap_or(""))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,6 +242,34 @@ impl Diagnostic for Error {
|
||||
Error::Format { .. } => None,
|
||||
Error::ValidatorMustReturnBool { .. } => Some(Box::new("Try annotating the validator's return type with Bool")),
|
||||
Error::WrongValidatorArity { .. } => Some(Box::new("Validators require a minimum number of arguments please add the missing arguments.\nIf you don't need one of the required arguments use an underscore `_datum`.")),
|
||||
Error::TestFailure { evaluation_hint, .. } =>{
|
||||
match evaluation_hint {
|
||||
None => None,
|
||||
Some(hint) => {
|
||||
let budget = ExBudget { mem: i64::MAX, cpu: i64::MAX, };
|
||||
let left = pretty::boxed("left", match hint.left.eval(budget) {
|
||||
(Ok(term), _, _) => format!("{term}"),
|
||||
(Err(err), _, _) => format!("{err}"),
|
||||
});
|
||||
let right = pretty::boxed("right", match hint.right.eval(budget) {
|
||||
(Ok(term), _, _) => format!("{term}"),
|
||||
(Err(err), _, _) => format!("{err}"),
|
||||
});
|
||||
let msg = match hint.bin_op {
|
||||
BinOp::And => Some(format!("{left}\n\nand\n\n{right}\n\nshould both be true.")),
|
||||
BinOp::Or => Some(format!("{left}\n\nor\n\n{right}\n\nshould be true.")),
|
||||
BinOp::Eq => Some(format!("{left}\n\nshould be equal to\n\n{right}")),
|
||||
BinOp::NotEq => Some(format!("{left}\n\nshould not be equal to\n\n{right}")),
|
||||
BinOp::LtInt => Some(format!("{left}\n\nshould be lower than\n\n{right}")),
|
||||
BinOp::LtEqInt => Some(format!("{left}\n\nshould be lower than or equal to\n\n{right}")),
|
||||
BinOp::GtEqInt => Some(format!("{left}\n\nshould be greater than\n\n{right}")),
|
||||
BinOp::GtInt => Some(format!("{left}\n\nshould be greater than or equal to\n\n{right}")),
|
||||
_ => None
|
||||
}?;
|
||||
Some(Box::new(msg))
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,6 +289,7 @@ impl Diagnostic for Error {
|
||||
Error::WrongValidatorArity { location, .. } => Some(Box::new(
|
||||
vec![LabeledSpan::new_with_span(None, *location)].into_iter(),
|
||||
)),
|
||||
Error::TestFailure { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,6 +305,7 @@ impl Diagnostic for Error {
|
||||
Error::Format { .. } => None,
|
||||
Error::ValidatorMustReturnBool { named, .. } => Some(named),
|
||||
Error::WrongValidatorArity { named, .. } => Some(named),
|
||||
Error::TestFailure { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod format;
|
||||
pub mod module;
|
||||
pub mod options;
|
||||
pub mod pretty;
|
||||
pub mod script;
|
||||
pub mod telemetry;
|
||||
|
||||
use aiken_lang::{
|
||||
ast::{Definition, Function, ModuleKind, TypedFunction},
|
||||
builtins,
|
||||
ast::{
|
||||
Annotation, DataType, Definition, Function, ModuleKind, RecordConstructor,
|
||||
RecordConstructorArg, Span, TypedDataType, TypedDefinition, TypedFunction,
|
||||
},
|
||||
builder::{DataTypeKey, FunctionAccessKey},
|
||||
builtins::{self, generic_var},
|
||||
tipo::TypeInfo,
|
||||
uplc::{CodeGenerator, DataTypeKey, FunctionAccessKey},
|
||||
uplc::CodeGenerator,
|
||||
IdGenerator,
|
||||
};
|
||||
use miette::NamedSource;
|
||||
@@ -26,11 +25,16 @@ use pallas::{
|
||||
ledger::{addresses::Address, primitives::babbage},
|
||||
};
|
||||
use pallas_traverse::ComputeHash;
|
||||
use script::Script;
|
||||
use script::{EvalHint, EvalInfo, Script};
|
||||
use serde_json::json;
|
||||
use telemetry::{EventListener, TestInfo};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use telemetry::EventListener;
|
||||
use uplc::{
|
||||
ast::{DeBruijn, Program},
|
||||
ast::{Constant, DeBruijn, Program, Term},
|
||||
machine::cost_model::ExBudget,
|
||||
};
|
||||
|
||||
@@ -101,12 +105,20 @@ where
|
||||
self.compile(options)
|
||||
}
|
||||
|
||||
pub fn check(&mut self, skip_tests: bool, match_tests: Option<String>) -> Result<(), Error> {
|
||||
pub fn check(
|
||||
&mut self,
|
||||
skip_tests: bool,
|
||||
match_tests: Option<String>,
|
||||
verbose: bool,
|
||||
) -> Result<(), Error> {
|
||||
let options = Options {
|
||||
code_gen_mode: if skip_tests {
|
||||
CodeGenMode::NoOp
|
||||
} else {
|
||||
CodeGenMode::Test(match_tests)
|
||||
CodeGenMode::Test {
|
||||
match_tests,
|
||||
verbose,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -140,19 +152,47 @@ where
|
||||
self.event_listener.handle_event(Event::GeneratingUPLC {
|
||||
output_path: self.output_path(),
|
||||
});
|
||||
|
||||
let programs = self.code_gen(validators, &checked_modules)?;
|
||||
|
||||
self.write_build_outputs(programs, uplc_dump)?;
|
||||
Ok(())
|
||||
}
|
||||
CodeGenMode::Test(match_tests) => {
|
||||
let tests = self.test_gen(&checked_modules)?;
|
||||
self.run_tests(tests, match_tests);
|
||||
}
|
||||
CodeGenMode::NoOp => (),
|
||||
}
|
||||
CodeGenMode::Test {
|
||||
match_tests,
|
||||
verbose,
|
||||
} => {
|
||||
let tests = self
|
||||
.collect_scripts(&checked_modules, |def| matches!(def, Definition::Test(..)))?;
|
||||
if !tests.is_empty() {
|
||||
self.event_listener.handle_event(Event::RunningTests);
|
||||
}
|
||||
let results = self.eval_scripts(tests, match_tests);
|
||||
let errors: Vec<Error> = results
|
||||
.iter()
|
||||
.filter_map(|e| {
|
||||
if e.success {
|
||||
None
|
||||
} else {
|
||||
Some(Error::TestFailure {
|
||||
name: e.script.name.clone(),
|
||||
path: e.script.input_path.clone(),
|
||||
evaluation_hint: e.script.evaluation_hint.clone(),
|
||||
src: e.script.program.to_pretty(),
|
||||
verbose,
|
||||
})
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(())
|
||||
self.event_listener
|
||||
.handle_event(Event::FinishedTests { tests: results });
|
||||
if !errors.is_empty() {
|
||||
Err(Error::List(errors))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
CodeGenMode::NoOp => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_source_files(&mut self) -> Result<(), Error> {
|
||||
@@ -290,7 +330,7 @@ where
|
||||
fn validate_validators(
|
||||
&self,
|
||||
checked_modules: &mut CheckedModules,
|
||||
) -> Result<Vec<(String, TypedFunction)>, Error> {
|
||||
) -> Result<Vec<(PathBuf, String, TypedFunction)>, Error> {
|
||||
let mut errors = Vec::new();
|
||||
let mut validators = Vec::new();
|
||||
let mut indices_to_remove = Vec::new();
|
||||
@@ -344,7 +384,11 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
validators.push((module.name.clone(), func_def.clone()));
|
||||
validators.push((
|
||||
module.input_path.clone(),
|
||||
module.name.clone(),
|
||||
func_def.clone(),
|
||||
));
|
||||
indices_to_remove.push(index);
|
||||
}
|
||||
}
|
||||
@@ -364,7 +408,7 @@ where
|
||||
|
||||
fn code_gen(
|
||||
&mut self,
|
||||
validators: Vec<(String, TypedFunction)>,
|
||||
validators: Vec<(PathBuf, String, TypedFunction)>,
|
||||
checked_modules: &CheckedModules,
|
||||
) -> Result<Vec<Script>, Error> {
|
||||
let mut programs = Vec::new();
|
||||
@@ -374,6 +418,16 @@ where
|
||||
let mut imports = HashMap::new();
|
||||
let mut constants = HashMap::new();
|
||||
|
||||
let option_data_type = make_option();
|
||||
|
||||
data_types.insert(
|
||||
DataTypeKey {
|
||||
module_name: "".to_string(),
|
||||
defined_type: "Option".to_string(),
|
||||
},
|
||||
&option_data_type,
|
||||
);
|
||||
|
||||
for module in checked_modules.values() {
|
||||
for def in module.ast.definitions() {
|
||||
match def {
|
||||
@@ -382,6 +436,7 @@ where
|
||||
FunctionAccessKey {
|
||||
module_name: module.name.clone(),
|
||||
function_name: func.name.clone(),
|
||||
variant_name: String::new(),
|
||||
},
|
||||
func,
|
||||
);
|
||||
@@ -409,7 +464,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
for (module_name, func_def) in validators {
|
||||
for (input_path, module_name, func_def) in validators {
|
||||
let Function {
|
||||
arguments,
|
||||
name,
|
||||
@@ -426,9 +481,15 @@ where
|
||||
&self.module_types,
|
||||
);
|
||||
|
||||
let program = generator.generate(body, arguments);
|
||||
let program = generator.generate(body, arguments, true);
|
||||
|
||||
let script = Script::new(module_name, name, program.try_into().unwrap());
|
||||
let script = Script::new(
|
||||
input_path,
|
||||
module_name,
|
||||
name,
|
||||
program.try_into().unwrap(),
|
||||
None,
|
||||
);
|
||||
|
||||
programs.push(script);
|
||||
}
|
||||
@@ -437,7 +498,11 @@ where
|
||||
}
|
||||
|
||||
// TODO: revisit ownership and lifetimes of data in this function
|
||||
fn test_gen(&mut self, checked_modules: &CheckedModules) -> Result<Vec<Script>, Error> {
|
||||
fn collect_scripts(
|
||||
&mut self,
|
||||
checked_modules: &CheckedModules,
|
||||
should_collect: fn(&TypedDefinition) -> bool,
|
||||
) -> Result<Vec<Script>, Error> {
|
||||
let mut programs = Vec::new();
|
||||
let mut functions = HashMap::new();
|
||||
let mut type_aliases = HashMap::new();
|
||||
@@ -445,8 +510,18 @@ where
|
||||
let mut imports = HashMap::new();
|
||||
let mut constants = HashMap::new();
|
||||
|
||||
let option_data_type = make_option();
|
||||
|
||||
data_types.insert(
|
||||
DataTypeKey {
|
||||
module_name: "".to_string(),
|
||||
defined_type: "Option".to_string(),
|
||||
},
|
||||
&option_data_type,
|
||||
);
|
||||
|
||||
// let mut indices_to_remove = Vec::new();
|
||||
let mut tests = Vec::new();
|
||||
let mut scripts = Vec::new();
|
||||
|
||||
for module in checked_modules.values() {
|
||||
for (_index, def) in module.ast.definitions().enumerate() {
|
||||
@@ -456,12 +531,18 @@ where
|
||||
FunctionAccessKey {
|
||||
module_name: module.name.clone(),
|
||||
function_name: func.name.clone(),
|
||||
variant_name: String::new(),
|
||||
},
|
||||
func,
|
||||
);
|
||||
if should_collect(def) {
|
||||
scripts.push((module.input_path.clone(), module.name.clone(), func));
|
||||
}
|
||||
}
|
||||
Definition::Test(func) => {
|
||||
tests.push((module.name.clone(), func));
|
||||
if should_collect(def) {
|
||||
scripts.push((module.input_path.clone(), module.name.clone(), func));
|
||||
}
|
||||
// indices_to_remove.push(index);
|
||||
}
|
||||
Definition::TypeAlias(ta) => {
|
||||
@@ -490,7 +571,7 @@ where
|
||||
// }
|
||||
}
|
||||
|
||||
for (module_name, func_def) in tests {
|
||||
for (input_path, module_name, func_def) in scripts {
|
||||
let Function {
|
||||
arguments,
|
||||
name,
|
||||
@@ -507,9 +588,34 @@ where
|
||||
&self.module_types,
|
||||
);
|
||||
|
||||
let program = generator.generate(body.clone(), arguments.clone());
|
||||
let evaluation_hint = if let Some((bin_op, left_src, right_src)) = func_def.test_hint()
|
||||
{
|
||||
let left = CodeGenerator::new(&functions, &data_types, &self.module_types)
|
||||
.generate(*left_src, vec![], false)
|
||||
.try_into()
|
||||
.unwrap();
|
||||
let right = CodeGenerator::new(&functions, &data_types, &self.module_types)
|
||||
.generate(*right_src, vec![], false)
|
||||
.try_into()
|
||||
.unwrap();
|
||||
Some(EvalHint {
|
||||
bin_op,
|
||||
left,
|
||||
right,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let script = Script::new(module_name, name.to_string(), program.try_into().unwrap());
|
||||
let program = generator.generate(body.clone(), arguments.clone(), false);
|
||||
|
||||
let script = Script::new(
|
||||
input_path,
|
||||
module_name,
|
||||
name.to_string(),
|
||||
program.try_into().unwrap(),
|
||||
evaluation_hint,
|
||||
);
|
||||
|
||||
programs.push(script);
|
||||
}
|
||||
@@ -517,7 +623,7 @@ where
|
||||
Ok(programs)
|
||||
}
|
||||
|
||||
fn run_tests(&self, tests: Vec<Script>, match_tests: Option<String>) {
|
||||
fn eval_scripts(&self, scripts: Vec<Script>, match_name: Option<String>) -> Vec<EvalInfo> {
|
||||
// TODO: in the future we probably just want to be able to
|
||||
// tell the machine to not explode on budget consumption.
|
||||
let initial_budget = ExBudget {
|
||||
@@ -525,43 +631,41 @@ where
|
||||
cpu: i64::MAX,
|
||||
};
|
||||
|
||||
if !tests.is_empty() {
|
||||
self.event_listener.handle_event(Event::RunningTests);
|
||||
}
|
||||
|
||||
let mut results = Vec::new();
|
||||
|
||||
for test in tests {
|
||||
let path = format!("{}{}", test.module, test.name);
|
||||
for script in scripts {
|
||||
let path = format!("{}{}", script.module, script.name);
|
||||
|
||||
if matches!(&match_tests, Some(search_str) if !path.to_string().contains(search_str)) {
|
||||
if matches!(&match_name, Some(search_str) if !path.to_string().contains(search_str)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match test.program.eval(initial_budget) {
|
||||
(Ok(..), remaining_budget, _) => {
|
||||
let test_info = TestInfo {
|
||||
is_passing: true,
|
||||
test,
|
||||
match script.program.eval(initial_budget) {
|
||||
(Ok(result), remaining_budget, _) => {
|
||||
let eval_info = EvalInfo {
|
||||
success: result != Term::Error
|
||||
&& result != Term::Constant(Constant::Bool(false)),
|
||||
script,
|
||||
spent_budget: initial_budget - remaining_budget,
|
||||
output: Some(result),
|
||||
};
|
||||
|
||||
results.push(test_info);
|
||||
results.push(eval_info);
|
||||
}
|
||||
(Err(_), remaining_budget, _) => {
|
||||
let test_info = TestInfo {
|
||||
is_passing: false,
|
||||
test,
|
||||
(Err(..), remaining_budget, _) => {
|
||||
let eval_info = EvalInfo {
|
||||
success: false,
|
||||
script,
|
||||
spent_budget: initial_budget - remaining_budget,
|
||||
output: None,
|
||||
};
|
||||
|
||||
results.push(test_info);
|
||||
results.push(eval_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.event_listener
|
||||
.handle_event(Event::FinishedTests { tests: results });
|
||||
results
|
||||
}
|
||||
|
||||
fn output_path(&self) -> PathBuf {
|
||||
@@ -722,3 +826,40 @@ fn is_aiken_path(path: &Path, dir: impl AsRef<Path>) -> bool {
|
||||
.expect("is_aiken_path(): to_str"),
|
||||
)
|
||||
}
|
||||
|
||||
fn make_option() -> TypedDataType {
|
||||
DataType {
|
||||
constructors: vec![
|
||||
RecordConstructor {
|
||||
location: Span::empty(),
|
||||
name: "Some".to_string(),
|
||||
arguments: vec![RecordConstructorArg {
|
||||
label: None,
|
||||
annotation: Annotation::Var {
|
||||
location: Span::empty(),
|
||||
name: "a".to_string(),
|
||||
},
|
||||
location: Span::empty(),
|
||||
tipo: generic_var(0),
|
||||
doc: None,
|
||||
}],
|
||||
documentation: None,
|
||||
sugar: false,
|
||||
},
|
||||
RecordConstructor {
|
||||
location: Span::empty(),
|
||||
name: "None".to_string(),
|
||||
arguments: vec![],
|
||||
documentation: None,
|
||||
sugar: false,
|
||||
},
|
||||
],
|
||||
doc: None,
|
||||
location: Span::empty(),
|
||||
name: "Option".to_string(),
|
||||
opaque: false,
|
||||
parameters: vec!["a".to_string()],
|
||||
public: true,
|
||||
typed_parameters: vec![generic_var(0)],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ pub struct Options {
|
||||
}
|
||||
|
||||
pub enum CodeGenMode {
|
||||
Test(Option<String>),
|
||||
Test {
|
||||
match_tests: Option<String>,
|
||||
verbose: bool,
|
||||
},
|
||||
Build(bool),
|
||||
NoOp,
|
||||
}
|
||||
|
||||
48
crates/project/src/pretty.rs
Normal file
48
crates/project/src/pretty.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
pub fn boxed(title: &str, content: String) -> String {
|
||||
let n = content.lines().fold(0, |max, l| {
|
||||
let n = l.len();
|
||||
if n > max {
|
||||
n
|
||||
} else {
|
||||
max
|
||||
}
|
||||
});
|
||||
|
||||
let content = content
|
||||
.lines()
|
||||
.map(|line| format!("│ {} │", pad_right(line.to_string(), n, " ")))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
|
||||
let top = format!("┍━ {}┑", pad_right(format!("{title} "), n, "━"));
|
||||
let bottom = format!("┕{}┙", pad_right(String::new(), n + 2, "━"));
|
||||
format!("{top}\n{content}\n{bottom}")
|
||||
}
|
||||
|
||||
pub fn pad_left(mut text: String, n: usize, delimiter: &str) -> String {
|
||||
let diff = n as i32 - text.len() as i32;
|
||||
if diff.is_positive() {
|
||||
for _ in 0..diff {
|
||||
text.insert_str(0, delimiter);
|
||||
}
|
||||
}
|
||||
text
|
||||
}
|
||||
|
||||
pub fn pad_right(mut text: String, n: usize, delimiter: &str) -> String {
|
||||
let diff = n as i32 - text.len() as i32;
|
||||
if diff.is_positive() {
|
||||
for _ in 0..diff {
|
||||
text.push_str(delimiter);
|
||||
}
|
||||
}
|
||||
text
|
||||
}
|
||||
|
||||
pub fn style_if(styled: bool, s: String, apply_style: fn(String) -> String) -> String {
|
||||
if styled {
|
||||
apply_style(s)
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,46 @@
|
||||
use crate::{ExBudget, Term};
|
||||
use aiken_lang::ast::BinOp;
|
||||
use std::path::PathBuf;
|
||||
use uplc::ast::{NamedDeBruijn, Program};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Script {
|
||||
pub input_path: PathBuf,
|
||||
pub module: String,
|
||||
pub name: String,
|
||||
pub program: Program<NamedDeBruijn>,
|
||||
pub evaluation_hint: Option<EvalHint>,
|
||||
}
|
||||
|
||||
impl Script {
|
||||
pub fn new(module: String, name: String, program: Program<NamedDeBruijn>) -> Script {
|
||||
pub fn new(
|
||||
input_path: PathBuf,
|
||||
module: String,
|
||||
name: String,
|
||||
program: Program<NamedDeBruijn>,
|
||||
evaluation_hint: Option<EvalHint>,
|
||||
) -> Script {
|
||||
Script {
|
||||
input_path,
|
||||
module,
|
||||
name,
|
||||
program,
|
||||
evaluation_hint,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EvalHint {
|
||||
pub bin_op: BinOp,
|
||||
pub left: Program<NamedDeBruijn>,
|
||||
pub right: Program<NamedDeBruijn>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EvalInfo {
|
||||
pub success: bool,
|
||||
pub script: Script,
|
||||
pub spent_budget: ExBudget,
|
||||
pub output: Option<Term<NamedDeBruijn>>,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::script::Script;
|
||||
use crate::script::EvalInfo;
|
||||
use std::path::PathBuf;
|
||||
use uplc::machine::cost_model::ExBudget;
|
||||
|
||||
pub trait EventListener: std::fmt::Debug {
|
||||
fn handle_event(&self, event: Event);
|
||||
@@ -17,14 +16,11 @@ pub enum Event {
|
||||
GeneratingUPLC {
|
||||
output_path: PathBuf,
|
||||
},
|
||||
EvaluatingFunction {
|
||||
results: Vec<EvalInfo>,
|
||||
},
|
||||
RunningTests,
|
||||
FinishedTests {
|
||||
tests: Vec<TestInfo>,
|
||||
tests: Vec<EvalInfo>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct TestInfo {
|
||||
pub is_passing: bool,
|
||||
pub test: Script,
|
||||
pub spent_budget: ExBudget,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user