Introduce 'compact' trace level verbosity

For now, it only shows the span start. We'll change that in the next commit to show a line number and a column.
This commit is contained in:
KtorZ 2024-01-18 11:43:07 +01:00
parent 627c6b576e
commit e67d5863a1
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
6 changed files with 251 additions and 201 deletions

View File

@ -1368,7 +1368,7 @@ pub enum Tracing {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TraceLevel {
Silent, // No traces
// Compact, // Line numbers only
Compact, // Line numbers only
Verbose, // Full verbose traces as provided by the user or the compiler
}
@ -1403,6 +1403,7 @@ impl Display for TraceLevel {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
match self {
TraceLevel::Silent => f.write_str("silent"),
TraceLevel::Compact => f.write_str("compact"),
TraceLevel::Verbose => f.write_str("verbose"),
}
}

View File

@ -468,7 +468,18 @@ impl<'a> CodeGenerator<'a> {
let air_value = self.build(value, module_name);
let msg = get_src_code_by_span(module_name, location, &self.module_src);
let msg_func = match self.tracing {
TraceLevel::Silent => None,
TraceLevel::Verbose | TraceLevel::Compact => {
if kind.is_expect() {
let msg = match self.tracing {
TraceLevel::Silent => unreachable!("excluded from pattern guards"),
// TODO: line number & col
TraceLevel::Compact => format!("{}", location.start),
TraceLevel::Verbose => {
get_src_code_by_span(module_name, location, &self.module_src)
}
};
let msg_func_name = msg.split_whitespace().join("");
@ -478,12 +489,11 @@ impl<'a> CodeGenerator<'a> {
string(),
);
// TODO
let msg_func = match self.tracing {
TraceLevel::Verbose if kind.is_expect() => {
Some(self.special_functions.use_function_msg(msg_func_name))
} else {
None
}
}
_ => None,
};
self.assignment(
@ -1589,9 +1599,9 @@ impl<'a> CodeGenerator<'a> {
// mutate code_gen_funcs and defined_data_types in this if branch
if function.is_none() && defined_data_types.get(&data_type_name).is_none() {
let (msg_term, error_term) = match self.tracing {
TraceLevel::Verbose => {
TraceLevel::Silent => (None, AirTree::error(tipo.clone(), false)),
TraceLevel::Compact | TraceLevel::Verbose => {
let msg = AirMsg::LocalVar("__param_msg".to_string());
(
Some(msg.clone()),
AirTree::trace(
@ -1601,7 +1611,6 @@ impl<'a> CodeGenerator<'a> {
),
)
}
TraceLevel::Silent => (None, AirTree::error(tipo.clone(), false)),
};
defined_data_types.insert(data_type_name.clone(), 1);
@ -1721,14 +1730,14 @@ impl<'a> CodeGenerator<'a> {
}
let code_gen_func = match self.tracing {
TraceLevel::Verbose => CodeGenFunction::Function {
body: func_body,
params: vec!["__param_0".to_string(), "__param_msg".to_string()],
},
TraceLevel::Silent => CodeGenFunction::Function {
body: func_body,
params: vec!["__param_0".to_string()],
},
TraceLevel::Compact | TraceLevel::Verbose => CodeGenFunction::Function {
body: func_body,
params: vec!["__param_0".to_string(), "__param_msg".to_string()],
},
};
self.code_gen_functions
@ -1741,7 +1750,7 @@ impl<'a> CodeGenerator<'a> {
let args = match self.tracing {
TraceLevel::Silent => vec![value],
TraceLevel::Verbose => vec![
TraceLevel::Compact | TraceLevel::Verbose => vec![
value,
msg_func
.expect("should be unreachable: no msg func with tracing enabled.")
@ -2750,10 +2759,18 @@ impl<'a> CodeGenerator<'a> {
let actual_type = convert_opaque_type(&arg.tipo, &self.data_types);
let msg = src_code
let msg_func = match self.tracing {
TraceLevel::Silent => None,
TraceLevel::Compact | TraceLevel::Verbose => {
let msg = match self.tracing {
TraceLevel::Silent => unreachable!("excluded from pattern guards"),
// TODO: Show line number + column
TraceLevel::Compact => format!("{}", arg_span.start),
TraceLevel::Verbose => src_code
.get(arg_span.start..arg_span.end)
.expect("Out of bounds span")
.to_string();
.to_string(),
};
let msg_func_name = msg.split_whitespace().join("");
@ -2763,12 +2780,8 @@ impl<'a> CodeGenerator<'a> {
string(),
);
// TODO
let msg_func = match self.tracing {
TraceLevel::Verbose => {
Some(self.special_functions.use_function_msg(msg_func_name))
}
_ => None,
};
let assign = self.assignment(
@ -3724,14 +3737,16 @@ impl<'a> CodeGenerator<'a> {
fn gen_uplc(&mut self, ir: Air, arg_stack: &mut Vec<Term<Name>>) -> Option<Term<Name>> {
// Going to mark the changes made to code gen after air tree implementation
// TODO
let error_term = match self.tracing {
TraceLevel::Verbose if air_holds_msg(&ir) => {
TraceLevel::Silent => Term::Error,
TraceLevel::Compact | TraceLevel::Verbose => {
if air_holds_msg(&ir) {
let msg = arg_stack.pop().unwrap();
Term::Error.delayed_trace(msg)
} else {
Term::Error
}
}
_ => Term::Error,
};
match ir {

View File

@ -1639,39 +1639,50 @@ pub fn wrap_as_multi_validator(
)
.lambda("__second_arg")
.lambda("__first_arg"),
TraceLevel::Verbose => {
let trace_string = format!(
TraceLevel::Verbose | TraceLevel::Compact => {
let trace_string = match trace {
TraceLevel::Verbose => format!(
"Incorrect redeemer type for validator {}.
Double check you have wrapped the redeemer type as specified in your plutus.json",
spend_name
);
),
TraceLevel::Compact => "RX".to_string(),
TraceLevel::Silent => unreachable!("Filtered-out from the pattern guards."),
};
let error_term = Term::Error.delayed_trace(Term::var("__incorrect_second_arg_type"));
let then_term = mint
.apply(Term::var("__first_arg"))
.apply(Term::var("__second_arg"));
let else_term = spend.apply(Term::var("__first_arg")).apply(
Term::head_list()
.apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(Term::var("__second_arg"))),
);
Term::var("__second_arg")
.delayed_choose_data(
Term::equals_integer()
.apply(Term::integer(0.into()))
.apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("__second_arg")))
.delayed_if_then_else(
mint.apply(Term::var("__first_arg"))
.apply(Term::var("__second_arg"))
.delayed_trace(Term::string(format!(
if trace == TraceLevel::Verbose {
then_term.delayed_trace(Term::string(format!(
"Running 2 arg validator {}",
mint_name
))),
spend
.apply(Term::var("__first_arg"))
.apply(
Term::head_list().apply(
Term::var(CONSTR_FIELDS_EXPOSER)
.apply(Term::var("__second_arg")),
),
)
.delayed_trace(Term::string(format!(
)))
} else {
then_term
},
if trace == TraceLevel::Verbose {
else_term.delayed_trace(Term::string(format!(
"Running 3 arg validator {}",
spend_name
))),
)))
} else {
else_term
},
),
error_term.clone(),
error_term.clone(),
@ -1725,6 +1736,9 @@ pub fn wrap_validator_condition(air_tree: AirTree, trace: TraceLevel) -> AirTree
let success_branch = vec![(air_tree, AirTree::void())];
let otherwise = match trace {
TraceLevel::Silent => AirTree::error(void(), true),
TraceLevel::Compact => {
AirTree::trace(AirTree::string("VX"), void(), AirTree::error(void(), true))
}
TraceLevel::Verbose => AirTree::trace(
AirTree::string("Validator returned false"),
void(),

View File

@ -421,7 +421,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
},
};
let text = TypedExpr::String {
let text = match self.tracing.trace_level(false) {
TraceLevel::Verbose => Some(TypedExpr::String {
location,
tipo: string(),
value: format!(
@ -430,6 +431,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
.expr(&value, false)
.to_pretty_string(999)
),
}),
TraceLevel::Compact => Some(TypedExpr::String {
location,
tipo: string(),
value: format!("{}", location.start),
}),
TraceLevel::Silent => None,
};
let typed_value = self.infer(value)?;
@ -438,7 +446,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
match self.tracing.trace_level(false) {
TraceLevel::Silent => Ok(typed_value),
TraceLevel::Verbose => Ok(TypedExpr::If {
TraceLevel::Verbose | TraceLevel::Compact => Ok(TypedExpr::If {
location,
branches: vec1::vec1![IfBranch {
condition: typed_value,
@ -448,7 +456,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
final_else: Box::new(TypedExpr::Trace {
location,
tipo: bool(),
text: Box::new(text),
text: Box::new(text.expect("TraceLevel::Silent excluded from pattern-guard")),
then: Box::new(var_false),
}),
tipo: bool(),
@ -1819,6 +1827,17 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
match self.tracing.trace_level(false) {
TraceLevel::Silent => Ok(then),
// TODO: use line numbers & cols
TraceLevel::Compact => Ok(TypedExpr::Trace {
location,
tipo,
then: Box::new(then),
text: Box::new(TypedExpr::String {
location,
tipo: string(),
value: format!("{}", location.start),
}),
}),
TraceLevel::Verbose => Ok(TypedExpr::Trace {
location,
tipo,

View File

@ -1,6 +1,6 @@
use pretty_assertions::assert_eq;
use aiken_lang::ast::{Definition, Function, TypedFunction, TypedValidator};
use aiken_lang::ast::{Definition, Function, TraceLevel, Tracing, TypedFunction, TypedValidator};
use uplc::{
ast::{Constant, Data, DeBruijn, Name, Program, Term, Type},
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER},
@ -26,7 +26,7 @@ fn assert_uplc(source_code: &str, expected: Term<Name>, should_fail: bool) {
&project.functions,
&project.data_types,
&project.module_types,
true,
Tracing::All(TraceLevel::Verbose),
);
let Some(checked_module) = modules.values().next() else {

View File

@ -86,8 +86,9 @@ pub fn keep_traces_parser(
#[allow(clippy::type_complexity)]
pub fn trace_level_parser() -> MapValueParser<PossibleValuesParser, fn(String) -> TraceLevel> {
PossibleValuesParser::new(["silent", "verbose"]).map(|s| match s.as_str() {
PossibleValuesParser::new(["silent", "compact", "verbose"]).map(|s| match s.as_str() {
"silent" => TraceLevel::Silent,
"compact" => TraceLevel::Compact,
"verbose" => TraceLevel::Verbose,
_ => unreachable!(),
})