From 1ca81ec13308dfd97dbeece1f90333f9e37e65ab Mon Sep 17 00:00:00 2001 From: KtorZ Date: Fri, 24 Nov 2023 09:44:02 +0100 Subject: [PATCH] Turn evaluation hints into strings earlier, to make project's Error thread-safe. --- crates/aiken-project/src/error.rs | 40 ++++-------------------- crates/aiken-project/src/lib.rs | 6 +++- crates/aiken-project/src/script.rs | 49 ++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 37 deletions(-) diff --git a/crates/aiken-project/src/error.rs b/crates/aiken-project/src/error.rs index 0dcd2653..cc0620bb 100644 --- a/crates/aiken-project/src/error.rs +++ b/crates/aiken-project/src/error.rs @@ -1,9 +1,6 @@ -use crate::{ - blueprint::error as blueprint, deps::manifest::Package, package_name::PackageName, pretty, - script::EvalHint, -}; +use crate::{blueprint::error as blueprint, deps::manifest::Package, package_name::PackageName}; use aiken_lang::{ - ast::{self, BinOp, Span}, + ast::{self, Span}, error::ExtraData, parser::error::ParseError, tipo, @@ -18,7 +15,6 @@ use std::{ ops::Deref, path::{Path, PathBuf}, }; -use uplc::machine::cost_model::ExBudget; use zip::result::ZipError; #[allow(dead_code)] @@ -97,7 +93,7 @@ pub enum Error { path: PathBuf, verbose: bool, src: String, - evaluation_hint: Option, + evaluation_hint: Option, }, #[error( @@ -313,33 +309,9 @@ impl Diagnostic for Error { Error::MissingManifest { .. } => Some(Box::new("Try running `aiken new ` to initialise a project with an example manifest.")), Error::TomlLoading { .. } => None, Error::Format { .. } => None, - 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.clone().eval(budget).result() { - Ok(term) => format!("{term}"), - Err(err) => format!("{err}"), - }); - let right = pretty::boxed("right", &match hint.right.clone().eval(budget).result() { - 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)) - } - } + Error::TestFailure { evaluation_hint, .. } => match evaluation_hint { + None => None, + Some(hint) => Some(Box::new(hint.to_string())) }, Error::Http(_) => None, Error::ZipExtract(_) => None, diff --git a/crates/aiken-project/src/lib.rs b/crates/aiken-project/src/lib.rs index b3f0d3ba..72f6a052 100644 --- a/crates/aiken-project/src/lib.rs +++ b/crates/aiken-project/src/lib.rs @@ -329,7 +329,11 @@ where Some(Error::TestFailure { name: e.script.name.clone(), path: e.script.input_path.clone(), - evaluation_hint: e.script.evaluation_hint.clone(), + evaluation_hint: e + .script + .evaluation_hint + .as_ref() + .map(|hint| hint.to_string()), src: e.script.program.to_pretty(), verbose, }) diff --git a/crates/aiken-project/src/script.rs b/crates/aiken-project/src/script.rs index 58b83882..ce3fc636 100644 --- a/crates/aiken-project/src/script.rs +++ b/crates/aiken-project/src/script.rs @@ -1,6 +1,9 @@ -use crate::{ExBudget, Term}; +use crate::{pretty, ExBudget, Term}; use aiken_lang::ast::BinOp; -use std::path::PathBuf; +use std::{ + fmt::{self, Display}, + path::PathBuf, +}; use uplc::ast::{NamedDeBruijn, Program}; #[derive(Debug, Clone)] @@ -42,6 +45,48 @@ pub struct EvalHint { pub right: Program, } +impl Display for EvalHint { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let unlimited_budget = ExBudget { + mem: i64::MAX, + cpu: i64::MAX, + }; + + let left = pretty::boxed( + "left", + &match self.left.clone().eval(unlimited_budget).result() { + Ok(term) => format!("{term}"), + Err(err) => format!("{err}"), + }, + ); + let right = pretty::boxed( + "right", + &match self.right.clone().eval(unlimited_budget).result() { + Ok(term) => format!("{term}"), + Err(err) => format!("{err}"), + }, + ); + let msg = match self.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, + } + .ok_or(fmt::Error::default())?; + + f.write_str(&msg) + } +} + #[derive(Debug)] pub struct EvalInfo { pub success: bool,