Add 'eval' command to evaluate target aiken function
Pretty useful for debbugging. Though, on second-thoughts, this is something we may want to review later and maybe have that done by default for tests. At the moment, we expects tests to unify to `bool`, and treat `false` values as failing tests. Yet, on failures, this gives little information about what's wrong with the test. It'd be nice to either have better way to assert in tests, or, to simply accept non-bool tests, and show whatever the test evaluates to as a debug output.
This commit is contained in:
27
crates/cli/src/cmd/eval.rs
Normal file
27
crates/cli/src/cmd/eval.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use aiken_project::options::{CodeGenMode, Options};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(clap::Args)]
|
||||
/// Evaluate a chosen function with no argument.
|
||||
pub struct Args {
|
||||
/// Path to project
|
||||
#[clap(short, long)]
|
||||
directory: Option<PathBuf>,
|
||||
|
||||
/// Evaluate the given function
|
||||
#[clap(short, long)]
|
||||
function_name: String,
|
||||
}
|
||||
|
||||
pub fn exec(
|
||||
Args {
|
||||
directory,
|
||||
function_name,
|
||||
}: Args,
|
||||
) -> miette::Result<()> {
|
||||
crate::with_project(directory, |p| {
|
||||
p.compile(Options {
|
||||
code_gen_mode: CodeGenMode::Eval(function_name.clone()),
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
pub mod build;
|
||||
pub mod check;
|
||||
pub mod error;
|
||||
pub mod eval;
|
||||
pub mod fmt;
|
||||
pub mod lsp;
|
||||
pub mod new;
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{env, path::PathBuf};
|
||||
|
||||
use aiken_project::{
|
||||
config::Config,
|
||||
telemetry::{self, TestInfo},
|
||||
telemetry::{self, EvalInfo},
|
||||
Project,
|
||||
};
|
||||
use miette::IntoDiagnostic;
|
||||
@@ -76,37 +76,30 @@ impl telemetry::EventListener for Terminal {
|
||||
output_path.to_str().unwrap_or("").bright_blue()
|
||||
);
|
||||
}
|
||||
telemetry::Event::EvaluatingFunction { results } => {
|
||||
println!("{}\n", "...Evaluating function".bold().purple());
|
||||
|
||||
let (max_mem, max_cpu) = find_max_execution_units(&results);
|
||||
|
||||
for eval_info in &results {
|
||||
println!("{}", fmt_eval(eval_info, max_mem, max_cpu))
|
||||
}
|
||||
}
|
||||
telemetry::Event::RunningTests => {
|
||||
println!("{}\n", "...Running tests".bold().purple());
|
||||
}
|
||||
telemetry::Event::FinishedTests { tests } => {
|
||||
let (max_mem, max_cpu) = tests.iter().fold(
|
||||
(0, 0),
|
||||
|(max_mem, max_cpu), TestInfo { spent_budget, .. }| {
|
||||
if spent_budget.mem >= max_mem && spent_budget.cpu >= max_cpu {
|
||||
(spent_budget.mem, spent_budget.cpu)
|
||||
} else if spent_budget.mem > max_mem {
|
||||
(spent_budget.mem, max_cpu)
|
||||
} else if spent_budget.cpu > max_cpu {
|
||||
(max_mem, spent_budget.cpu)
|
||||
} else {
|
||||
(max_mem, max_cpu)
|
||||
}
|
||||
},
|
||||
);
|
||||
let (max_mem, max_cpu) = find_max_execution_units(&tests);
|
||||
|
||||
let max_mem = max_mem.to_string().len() as i32;
|
||||
let max_cpu = max_cpu.to_string().len() as i32;
|
||||
|
||||
for test_info in &tests {
|
||||
println!("{}", fmt_test(test_info, max_mem, max_cpu))
|
||||
for eval_info in &tests {
|
||||
println!("{}", fmt_test(eval_info, max_mem, max_cpu))
|
||||
}
|
||||
|
||||
let (n_passed, n_failed) =
|
||||
tests
|
||||
.iter()
|
||||
.fold((0, 0), |(n_passed, n_failed), test_info| {
|
||||
if test_info.is_passing {
|
||||
if test_info.success {
|
||||
(n_passed + 1, n_failed)
|
||||
} else {
|
||||
(n_passed, n_failed + 1)
|
||||
@@ -128,26 +121,72 @@ impl telemetry::EventListener for Terminal {
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt_test(test_info: &TestInfo, max_mem: i32, max_cpu: i32) -> String {
|
||||
let TestInfo {
|
||||
is_passing,
|
||||
test,
|
||||
fn fmt_test(eval_info: &EvalInfo, max_mem: i32, max_cpu: i32) -> String {
|
||||
let EvalInfo {
|
||||
success,
|
||||
script,
|
||||
spent_budget,
|
||||
} = test_info;
|
||||
..
|
||||
} = eval_info;
|
||||
|
||||
let ExBudget { mem, cpu } = spent_budget;
|
||||
|
||||
format!(
|
||||
" [{}] [mem: {}, cpu: {}] {}::{}",
|
||||
if *is_passing {
|
||||
if *success {
|
||||
"PASS".bold().green().to_string()
|
||||
} else {
|
||||
"FAIL".bold().red().to_string()
|
||||
},
|
||||
pad_left(mem.to_string(), max_mem, " "),
|
||||
pad_left(cpu.to_string(), max_cpu, " "),
|
||||
test.module.blue(),
|
||||
test.name.bright_blue()
|
||||
script.module.blue(),
|
||||
script.name.bright_blue()
|
||||
)
|
||||
}
|
||||
|
||||
fn fmt_eval(eval_info: &EvalInfo, max_mem: i32, max_cpu: i32) -> String {
|
||||
let EvalInfo {
|
||||
output,
|
||||
script,
|
||||
spent_budget,
|
||||
..
|
||||
} = eval_info;
|
||||
|
||||
let ExBudget { mem, cpu } = spent_budget;
|
||||
|
||||
format!(
|
||||
" {}::{} [mem: {}, cpu: {}]\n │\n ╰─▶ {}",
|
||||
script.module.blue(),
|
||||
script.name.bright_blue(),
|
||||
pad_left(mem.to_string(), max_mem, " "),
|
||||
pad_left(cpu.to_string(), max_cpu, " "),
|
||||
output
|
||||
.as_ref()
|
||||
.map(|x| format!("{}", x))
|
||||
.unwrap_or("Error.".to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
fn find_max_execution_units(xs: &Vec<EvalInfo>) -> (i32, i32) {
|
||||
let (max_mem, max_cpu) = xs.iter().fold(
|
||||
(0, 0),
|
||||
|(max_mem, max_cpu), EvalInfo { spent_budget, .. }| {
|
||||
if spent_budget.mem >= max_mem && spent_budget.cpu >= max_cpu {
|
||||
(spent_budget.mem, spent_budget.cpu)
|
||||
} else if spent_budget.mem > max_mem {
|
||||
(spent_budget.mem, max_cpu)
|
||||
} else if spent_budget.cpu > max_cpu {
|
||||
(max_mem, spent_budget.cpu)
|
||||
} else {
|
||||
(max_mem, max_cpu)
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
(
|
||||
max_mem.to_string().len() as i32,
|
||||
max_cpu.to_string().len() as i32,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use aiken::cmd::{build, check, fmt, lsp, new, tx, uplc};
|
||||
use aiken::cmd::{build, check, eval, fmt, lsp, new, tx, uplc};
|
||||
use clap::Parser;
|
||||
|
||||
/// Aiken: a smart-contract language and toolchain for Cardano
|
||||
@@ -11,6 +11,7 @@ pub enum Cmd {
|
||||
Fmt(fmt::Args),
|
||||
Build(build::Args),
|
||||
Check(check::Args),
|
||||
Eval(eval::Args),
|
||||
|
||||
#[clap(hide = true)]
|
||||
Lsp(lsp::Args),
|
||||
@@ -35,6 +36,7 @@ fn main() -> miette::Result<()> {
|
||||
Cmd::Fmt(args) => fmt::exec(args),
|
||||
Cmd::Build(args) => build::exec(args),
|
||||
Cmd::Check(args) => check::exec(args),
|
||||
Cmd::Eval(args) => eval::exec(args),
|
||||
Cmd::Lsp(args) => lsp::exec(args),
|
||||
Cmd::Tx(sub_cmd) => tx::exec(sub_cmd),
|
||||
Cmd::Uplc(sub_cmd) => uplc::exec(sub_cmd),
|
||||
|
||||
Reference in New Issue
Block a user