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

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

View File

@ -468,22 +468,32 @@ impl<'a> CodeGenerator<'a> {
let air_value = self.build(value, module_name); let air_value = self.build(value, module_name);
let msg = get_src_code_by_span(module_name, location, &self.module_src);
let msg_func_name = msg.split_whitespace().join("");
self.special_functions.insert_new_function(
msg_func_name.clone(),
Term::string(msg),
string(),
);
// TODO
let msg_func = match self.tracing { let msg_func = match self.tracing {
TraceLevel::Verbose if kind.is_expect() => { TraceLevel::Silent => None,
Some(self.special_functions.use_function_msg(msg_func_name)) 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("");
self.special_functions.insert_new_function(
msg_func_name.clone(),
Term::string(msg),
string(),
);
Some(self.special_functions.use_function_msg(msg_func_name))
} else {
None
}
} }
_ => None,
}; };
self.assignment( self.assignment(
@ -1589,9 +1599,9 @@ impl<'a> CodeGenerator<'a> {
// mutate code_gen_funcs and defined_data_types in this if branch // 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() { if function.is_none() && defined_data_types.get(&data_type_name).is_none() {
let (msg_term, error_term) = match self.tracing { 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()); let msg = AirMsg::LocalVar("__param_msg".to_string());
( (
Some(msg.clone()), Some(msg.clone()),
AirTree::trace( 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); defined_data_types.insert(data_type_name.clone(), 1);
@ -1721,14 +1730,14 @@ impl<'a> CodeGenerator<'a> {
} }
let code_gen_func = match self.tracing { 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 { TraceLevel::Silent => CodeGenFunction::Function {
body: func_body, body: func_body,
params: vec!["__param_0".to_string()], 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 self.code_gen_functions
@ -1741,7 +1750,7 @@ impl<'a> CodeGenerator<'a> {
let args = match self.tracing { let args = match self.tracing {
TraceLevel::Silent => vec![value], TraceLevel::Silent => vec![value],
TraceLevel::Verbose => vec![ TraceLevel::Compact | TraceLevel::Verbose => vec![
value, value,
msg_func msg_func
.expect("should be unreachable: no msg func with tracing enabled.") .expect("should be unreachable: no msg func with tracing enabled.")
@ -2750,25 +2759,29 @@ impl<'a> CodeGenerator<'a> {
let actual_type = convert_opaque_type(&arg.tipo, &self.data_types); let actual_type = convert_opaque_type(&arg.tipo, &self.data_types);
let msg = src_code
.get(arg_span.start..arg_span.end)
.expect("Out of bounds span")
.to_string();
let msg_func_name = msg.split_whitespace().join("");
self.special_functions.insert_new_function(
msg_func_name.to_string(),
Term::string(msg),
string(),
);
// TODO
let msg_func = match self.tracing { let msg_func = match self.tracing {
TraceLevel::Verbose => { 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(),
};
let msg_func_name = msg.split_whitespace().join("");
self.special_functions.insert_new_function(
msg_func_name.to_string(),
Term::string(msg),
string(),
);
Some(self.special_functions.use_function_msg(msg_func_name)) Some(self.special_functions.use_function_msg(msg_func_name))
} }
_ => None,
}; };
let assign = self.assignment( 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>> { 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 // Going to mark the changes made to code gen after air tree implementation
// TODO
let error_term = match self.tracing { let error_term = match self.tracing {
TraceLevel::Verbose if air_holds_msg(&ir) => { TraceLevel::Silent => Term::Error,
let msg = arg_stack.pop().unwrap(); TraceLevel::Compact | TraceLevel::Verbose => {
if air_holds_msg(&ir) {
Term::Error.delayed_trace(msg) let msg = arg_stack.pop().unwrap();
Term::Error.delayed_trace(msg)
} else {
Term::Error
}
} }
_ => Term::Error,
}; };
match ir { match ir {

View File

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

View File

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

View File

@ -1,6 +1,6 @@
use pretty_assertions::assert_eq; 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::{ use uplc::{
ast::{Constant, Data, DeBruijn, Name, Program, Term, Type}, ast::{Constant, Data, DeBruijn, Name, Program, Term, Type},
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER}, 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.functions,
&project.data_types, &project.data_types,
&project.module_types, &project.module_types,
true, Tracing::All(TraceLevel::Verbose),
); );
let Some(checked_module) = modules.values().next() else { let Some(checked_module) = modules.values().next() else {
@ -115,7 +115,7 @@ fn acceptance_test_1_length() {
1 + length(rest) 1 + length(rest)
} }
} }
test length_1() { test length_1() {
length([1, 2, 3]) == 3 length([1, 2, 3]) == 3
} }
@ -167,7 +167,7 @@ fn acceptance_test_2_repeat() {
[x, ..repeat(x, n - 1)] [x, ..repeat(x, n - 1)]
} }
} }
test repeat_1() { test repeat_1() {
repeat("aiken", 2) == ["aiken", "aiken"] repeat("aiken", 2) == ["aiken", "aiken"]
} }
@ -232,11 +232,11 @@ fn acceptance_test_3_concat() {
f(x, foldr(rest, f, zero)) f(x, foldr(rest, f, zero))
} }
} }
pub fn concat(left: List<a>, right: List<a>) -> List<a> { pub fn concat(left: List<a>, right: List<a>) -> List<a> {
foldr(left, fn(x, xs) { [x, ..xs] }, right) foldr(left, fn(x, xs) { [x, ..xs] }, right)
} }
test concat_1() { test concat_1() {
concat([1, 2, 3], [4, 5, 6]) == [1, 2, 3, 4, 5, 6] concat([1, 2, 3], [4, 5, 6]) == [1, 2, 3, 4, 5, 6]
} }
@ -329,15 +329,15 @@ fn acceptance_test_4_concat_no_anon_func() {
f(x, foldr(rest, f, zero)) f(x, foldr(rest, f, zero))
} }
} }
pub fn prepend(x: a, xs: List<a>) -> List<a> { pub fn prepend(x: a, xs: List<a>) -> List<a> {
[x, ..xs] [x, ..xs]
} }
pub fn concat(left: List<a>, right: List<a>) -> List<a> { pub fn concat(left: List<a>, right: List<a>) -> List<a> {
foldr(left, prepend, right) foldr(left, prepend, right)
} }
test concat_1() { test concat_1() {
concat([1, 2, 3], [4, 5, 6]) == [1, 2, 3, 4, 5, 6] concat([1, 2, 3], [4, 5, 6]) == [1, 2, 3, 4, 5, 6]
} }
@ -425,7 +425,7 @@ fn acceptance_test_4_concat_no_anon_func() {
fn acceptance_test_5_direct_head() { fn acceptance_test_5_direct_head() {
let src = r#" let src = r#"
use aiken/builtin.{head_list} use aiken/builtin.{head_list}
test head_1() { test head_1() {
let head = fn(xs){ let head = fn(xs){
when xs is { when xs is {
@ -433,9 +433,9 @@ fn acceptance_test_5_direct_head() {
_ -> Some(head_list(xs)) _ -> Some(head_list(xs))
} }
} }
head([1, 2, 3]) == Some(1) head([1, 2, 3]) == Some(1)
} }
"#; "#;
assert_uplc( assert_uplc(
@ -473,7 +473,7 @@ fn acceptance_test_5_direct_head() {
fn acceptance_test_5_direct_2_heads() { fn acceptance_test_5_direct_2_heads() {
let src = r#" let src = r#"
use aiken/builtin.{head_list} use aiken/builtin.{head_list}
test head_2() { test head_2() {
let head = fn(xs: List<Int>){ let head = fn(xs: List<Int>){
when xs is { when xs is {
@ -482,9 +482,9 @@ fn acceptance_test_5_direct_2_heads() {
[a, b, ..] -> Some([a,b]) [a, b, ..] -> Some([a,b])
} }
} }
head([1, 2, 3]) == Some([1, 2]) head([1, 2, 3]) == Some([1, 2])
} }
"#; "#;
assert_uplc( assert_uplc(
@ -583,10 +583,10 @@ fn acceptance_test_5_head_not_empty() {
_ -> Some(head_list(xs)) _ -> Some(head_list(xs))
} }
} }
test head_1() { test head_1() {
head([1, 2, 3]) == Some(1) head([1, 2, 3]) == Some(1)
} }
"#; "#;
assert_uplc( assert_uplc(
@ -631,10 +631,10 @@ fn acceptance_test_5_head_empty() {
_ -> Some(head_list(xs)) _ -> Some(head_list(xs))
} }
} }
test head_1() { test head_1() {
head([]) == None head([]) == None
} }
"#; "#;
assert_uplc( assert_uplc(
@ -744,10 +744,10 @@ fn acceptance_test_7_unzip() {
} }
} }
} }
test unzip1() { test unzip1() {
let x = [(3, #"55"), (4, #"7799")] let x = [(3, #"55"), (4, #"7799")]
unzip(x) == ([3, 4], [#"55", #"7799"]) unzip(x) == ([3, 4], [#"55", #"7799"])
} }
"#; "#;
@ -869,7 +869,7 @@ fn acceptance_test_8_is_empty() {
pub fn is_empty(bytes: ByteArray) -> Bool { pub fn is_empty(bytes: ByteArray) -> Bool {
builtin.length_of_bytearray(bytes) == 0 builtin.length_of_bytearray(bytes) == 0
} }
test is_empty_1() { test is_empty_1() {
is_empty(#"") == True is_empty(#"") == True
} }
@ -902,7 +902,7 @@ fn acceptance_test_8_is_not_empty() {
pub fn is_empty(bytes: ByteArray) -> Bool { pub fn is_empty(bytes: ByteArray) -> Bool {
builtin.length_of_bytearray(bytes) == 0 builtin.length_of_bytearray(bytes) == 0
} }
test is_empty_1() { test is_empty_1() {
is_empty(#"01") == False is_empty(#"01") == False
} }
@ -935,7 +935,7 @@ fn acceptance_test_9_is_empty() {
pub fn is_empty(bytes: ByteArray) -> Bool { pub fn is_empty(bytes: ByteArray) -> Bool {
length_of_bytearray(bytes) == 0 length_of_bytearray(bytes) == 0
} }
test is_empty_1() { test is_empty_1() {
is_empty(#"") == True is_empty(#"") == True
} }
@ -971,14 +971,14 @@ fn acceptance_test_10_map_none() {
Some(f(a)) Some(f(a))
} }
} }
fn add_one(n: Int) -> Int { fn add_one(n: Int) -> Int {
n + 1 n + 1
} }
test map_1() { test map_1() {
map(None, add_one) == None map(None, add_one) == None
} }
"#; "#;
assert_uplc( assert_uplc(
@ -1053,14 +1053,14 @@ fn acceptance_test_10_map_some() {
Some(f(a)) Some(f(a))
} }
} }
fn add_one(n: Int) -> Int { fn add_one(n: Int) -> Int {
n + 1 n + 1
} }
test map_1() { test map_1() {
map(Some(1), add_one) == Some(2) map(Some(1), add_one) == Some(2)
} }
"#; "#;
assert_uplc( assert_uplc(
@ -1135,10 +1135,10 @@ fn acceptance_test_11_map_empty() {
[f(x), ..map(rest, f)] [f(x), ..map(rest, f)]
} }
} }
test map_1() { test map_1() {
map([], fn(n) { n + 1 }) == [] map([], fn(n) { n + 1 }) == []
} }
"#; "#;
assert_uplc( assert_uplc(
@ -1206,10 +1206,10 @@ fn acceptance_test_11_map_filled() {
[f(x), ..map(rest, f)] [f(x), ..map(rest, f)]
} }
} }
test map_1() { test map_1() {
map([6, 7, 8], fn(n) { n + 1 }) == [7, 8, 9] map([6, 7, 8], fn(n) { n + 1 }) == [7, 8, 9]
} }
"#; "#;
assert_uplc( assert_uplc(
@ -1291,7 +1291,7 @@ fn acceptance_test_12_filter_even() {
} }
} }
} }
test filter_1() { test filter_1() {
filter([1, 2, 3, 4, 5, 6], fn(x) { builtin.mod_integer(x, 2) == 0 }) == [2, 4, 6] filter([1, 2, 3, 4, 5, 6], fn(x) { builtin.mod_integer(x, 2) == 0 }) == [2, 4, 6]
} }
@ -1776,10 +1776,10 @@ fn acceptance_test_20_map_some() {
Some(f(a)) Some(f(a))
} }
} }
test map_1() { test map_1() {
map(Some(14), fn(n){ n + 1 }) == Some(15) map(Some(14), fn(n){ n + 1 }) == Some(15)
} }
"#; "#;
assert_uplc( assert_uplc(
@ -1967,15 +1967,15 @@ fn acceptance_test_23_to_list() {
pub opaque type AssocList<key, value> { pub opaque type AssocList<key, value> {
inner: List<(key, value)>, inner: List<(key, value)>,
} }
pub fn new() -> AssocList<key, value> { pub fn new() -> AssocList<key, value> {
AssocList { inner: [] } AssocList { inner: [] }
} }
pub fn to_list(m: AssocList<key, value>) -> List<(key, value)> { pub fn to_list(m: AssocList<key, value>) -> List<(key, value)> {
m.inner m.inner
} }
pub fn insert( pub fn insert(
in m: AssocList<key, value>, in m: AssocList<key, value>,
key k: key, key k: key,
@ -1983,7 +1983,7 @@ fn acceptance_test_23_to_list() {
) -> AssocList<key, value> { ) -> AssocList<key, value> {
AssocList { inner: do_insert(m.inner, k, v) } AssocList { inner: do_insert(m.inner, k, v) }
} }
fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> { fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> {
when elems is { when elems is {
[] -> [] ->
@ -1996,13 +1996,13 @@ fn acceptance_test_23_to_list() {
} }
} }
} }
fn fixture_1() { fn fixture_1() {
new() new()
|> insert("foo", 42) |> insert("foo", 42)
|> insert("bar", 14) |> insert("bar", 14)
} }
test to_list_2() { test to_list_2() {
to_list(fixture_1()) == [("foo", 42), ("bar", 14)] to_list(fixture_1()) == [("foo", 42), ("bar", 14)]
} }
@ -2063,10 +2063,10 @@ fn acceptance_test_24_map2() {
} }
} }
} }
test map2_3() { test map2_3() {
map2(Some(14), Some(42), fn(a, b) { (a, b) }) == Some((14, 42)) map2(Some(14), Some(42), fn(a, b) { (a, b) }) == Some((14, 42))
} }
"#; "#;
assert_uplc( assert_uplc(
@ -2191,7 +2191,7 @@ fn acceptance_test_25_void_equal() {
let src = r#" let src = r#"
test nil_1() { test nil_1() {
Void == Void Void == Void
} }
"#; "#;
assert_uplc( assert_uplc(
@ -2212,11 +2212,11 @@ fn acceptance_test_26_foldr() {
f(x, foldr(rest, f, zero)) f(x, foldr(rest, f, zero))
} }
} }
pub fn concat(left: List<a>, right: List<a>) -> List<a> { pub fn concat(left: List<a>, right: List<a>) -> List<a> {
foldr(left, fn(x, xs) { [x, ..xs] }, right) foldr(left, fn(x, xs) { [x, ..xs] }, right)
} }
pub fn flat_map(xs: List<a>, f: fn(a) -> List<b>) -> List<b> { pub fn flat_map(xs: List<a>, f: fn(a) -> List<b>) -> List<b> {
when xs is { when xs is {
[] -> [] ->
@ -2225,7 +2225,7 @@ fn acceptance_test_26_foldr() {
concat(f(x), flat_map(rest, f)) concat(f(x), flat_map(rest, f))
} }
} }
test flat_map_2() { test flat_map_2() {
flat_map([1, 2, 3], fn(a) { [a, a] }) == [1, 1, 2, 2, 3, 3] flat_map([1, 2, 3], fn(a) { [a, a] }) == [1, 1, 2, 2, 3, 3]
} }
@ -2353,11 +2353,11 @@ fn acceptance_test_27_flat_map() {
f(x, foldr(rest, f, zero)) f(x, foldr(rest, f, zero))
} }
} }
pub fn concat(left: List<a>, right: List<a>) -> List<a> { pub fn concat(left: List<a>, right: List<a>) -> List<a> {
foldr(left, fn(x, xs) { [x, ..xs] }, right) foldr(left, fn(x, xs) { [x, ..xs] }, right)
} }
pub fn flat_map(xs: List<a>, f: fn(a) -> List<b>) -> List<b> { pub fn flat_map(xs: List<a>, f: fn(a) -> List<b>) -> List<b> {
when xs is { when xs is {
[] -> [] ->
@ -2366,7 +2366,7 @@ fn acceptance_test_27_flat_map() {
concat(f(x), flat_map(rest, f)) concat(f(x), flat_map(rest, f))
} }
} }
test flat_map_2() { test flat_map_2() {
flat_map([1, 2, 3], fn(a) { [a, a] }) == [1, 1, 2, 2, 3, 3] flat_map([1, 2, 3], fn(a) { [a, a] }) == [1, 1, 2, 2, 3, 3]
} }
@ -2498,7 +2498,7 @@ fn acceptance_test_28_unique_empty_list() {
} }
} }
} }
pub fn unique(xs: List<a>) -> List<a> { pub fn unique(xs: List<a>) -> List<a> {
when xs is { when xs is {
[] -> [] ->
@ -2507,10 +2507,10 @@ fn acceptance_test_28_unique_empty_list() {
[x, ..unique(filter(rest, fn(y) { y != x }))] [x, ..unique(filter(rest, fn(y) { y != x }))]
} }
} }
test unique_1() { test unique_1() {
unique([]) == [] unique([]) == []
} }
"#; "#;
assert_uplc( assert_uplc(
@ -2606,7 +2606,7 @@ fn acceptance_test_28_unique_list() {
} }
} }
} }
pub fn unique(xs: List<a>) -> List<a> { pub fn unique(xs: List<a>) -> List<a> {
when xs is { when xs is {
[] -> [] ->
@ -2615,10 +2615,10 @@ fn acceptance_test_28_unique_list() {
[x, ..unique(filter(rest, fn(y) { y != x }))] [x, ..unique(filter(rest, fn(y) { y != x }))]
} }
} }
test unique_1() { test unique_1() {
unique([1,2,3,1]) == [1,2,3] unique([1,2,3,1]) == [1,2,3]
} }
"#; "#;
assert_uplc( assert_uplc(
@ -2721,15 +2721,15 @@ fn acceptance_test_29_union() {
pub opaque type AssocList<key, value> { pub opaque type AssocList<key, value> {
inner: List<(key, value)>, inner: List<(key, value)>,
} }
pub fn new() -> AssocList<key, value> { pub fn new() -> AssocList<key, value> {
AssocList { inner: [] } AssocList { inner: [] }
} }
pub fn from_list(xs: List<(key, value)>) -> AssocList<key, value> { pub fn from_list(xs: List<(key, value)>) -> AssocList<key, value> {
AssocList { inner: do_from_list(xs) } AssocList { inner: do_from_list(xs) }
} }
fn do_from_list(xs: List<(key, value)>) -> List<(key, value)> { fn do_from_list(xs: List<(key, value)>) -> List<(key, value)> {
when xs is { when xs is {
[] -> [] ->
@ -2738,7 +2738,7 @@ fn acceptance_test_29_union() {
do_insert(do_from_list(rest), k, v) do_insert(do_from_list(rest), k, v)
} }
} }
pub fn insert( pub fn insert(
in m: AssocList<key, value>, in m: AssocList<key, value>,
key k: key, key k: key,
@ -2746,7 +2746,7 @@ fn acceptance_test_29_union() {
) -> AssocList<key, value> { ) -> AssocList<key, value> {
AssocList { inner: do_insert(m.inner, k, v) } AssocList { inner: do_insert(m.inner, k, v) }
} }
fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> { fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> {
when elems is { when elems is {
[] -> [] ->
@ -2759,14 +2759,14 @@ fn acceptance_test_29_union() {
} }
} }
} }
pub fn union( pub fn union(
left: AssocList<key, value>, left: AssocList<key, value>,
right: AssocList<key, value>, right: AssocList<key, value>,
) -> AssocList<key, value> { ) -> AssocList<key, value> {
AssocList { inner: do_union(left.inner, right.inner) } AssocList { inner: do_union(left.inner, right.inner) }
} }
fn do_union( fn do_union(
left: List<(key, value)>, left: List<(key, value)>,
right: List<(key, value)>, right: List<(key, value)>,
@ -2778,17 +2778,17 @@ fn acceptance_test_29_union() {
do_union(rest, do_insert(right, k, v)) do_union(rest, do_insert(right, k, v))
} }
} }
fn fixture_1() { fn fixture_1() {
new() new()
|> insert("foo", 42) |> insert("foo", 42)
|> insert("bar", 14) |> insert("bar", 14)
} }
test union_1() { test union_1() {
union(fixture_1(), new()) == fixture_1() union(fixture_1(), new()) == fixture_1()
} }
"#; "#;
assert_uplc( assert_uplc(
@ -2954,7 +2954,7 @@ fn acceptance_test_30_abs() {
a a
} }
} }
test abs_1() { test abs_1() {
abs(-14) == 14 abs(-14) == 14
} }
@ -2987,13 +2987,13 @@ fn acceptance_test_30_abs() {
#[test] #[test]
fn expect_empty_list_on_filled_list() { fn expect_empty_list_on_filled_list() {
let src = r#" let src = r#"
test empty_list1() { test empty_list1() {
let x = [1,2] let x = [1,2]
expect [] = x expect [] = x
True True
} }
"#; "#;
assert_uplc( assert_uplc(
@ -3014,13 +3014,13 @@ fn expect_empty_list_on_filled_list() {
#[test] #[test]
fn expect_empty_list_on_new_list() { fn expect_empty_list_on_new_list() {
let src = r#" let src = r#"
test empty_list1() { test empty_list1() {
let x = [] let x = []
expect [] = x expect [] = x
True True
} }
"#; "#;
assert_uplc( assert_uplc(
@ -3038,7 +3038,7 @@ fn expect_empty_list_on_new_list() {
#[test] #[test]
fn when_bool_is_true() { fn when_bool_is_true() {
let src = r#" let src = r#"
test it() { test it() {
when True is { when True is {
True -> True ->
@ -3046,7 +3046,7 @@ fn when_bool_is_true() {
False -> False ->
fail fail
} }
} }
"#; "#;
assert_uplc( assert_uplc(
@ -3061,7 +3061,7 @@ fn when_bool_is_true() {
#[test] #[test]
fn when_bool_is_true_switched_cases() { fn when_bool_is_true_switched_cases() {
let src = r#" let src = r#"
test it() { test it() {
when True is { when True is {
False -> False ->
@ -3069,7 +3069,7 @@ fn when_bool_is_true_switched_cases() {
True -> True ->
True True
} }
} }
"#; "#;
assert_uplc( assert_uplc(
@ -3084,7 +3084,7 @@ fn when_bool_is_true_switched_cases() {
#[test] #[test]
fn when_bool_is_false() { fn when_bool_is_false() {
let src = r#" let src = r#"
test it() { test it() {
when False is { when False is {
False -> False ->
@ -3092,7 +3092,7 @@ fn when_bool_is_false() {
True -> True ->
True True
} }
} }
"#; "#;
assert_uplc( assert_uplc(
@ -3607,15 +3607,15 @@ fn pass_constr_as_function() {
a: Int, a: Int,
b: SubMake b: SubMake
} }
type SubMake { type SubMake {
c: Int c: Int
} }
fn hi(sm: SubMake, to_make: fn (Int, SubMake) -> Make) -> Make { fn hi(sm: SubMake, to_make: fn (Int, SubMake) -> Make) -> Make {
to_make(3, sm) to_make(3, sm)
} }
test cry() { test cry() {
Make(3, SubMake(1)) == hi(SubMake(1), Make) Make(3, SubMake(1)) == hi(SubMake(1), Make)
} }
@ -3668,23 +3668,23 @@ fn record_update_output_2_vals() {
type Address { type Address {
thing: ByteArray, thing: ByteArray,
} }
type Datum { type Datum {
NoDatum NoDatum
InlineDatum(Data) InlineDatum(Data)
} }
type Output { type Output {
address: Address, address: Address,
value: List<(ByteArray, List<(ByteArray, Int)>)>, value: List<(ByteArray, List<(ByteArray, Int)>)>,
datum: Datum, datum: Datum,
script_ref: Option<ByteArray>, script_ref: Option<ByteArray>,
} }
type MyDatum { type MyDatum {
a: Int, a: Int,
} }
test huh() { test huh() {
let prev_output = let prev_output =
Output { Output {
@ -3693,10 +3693,10 @@ fn record_update_output_2_vals() {
datum: InlineDatum(MyDatum{a: 3}), datum: InlineDatum(MyDatum{a: 3}),
script_ref: None, script_ref: None,
} }
let next_output = let next_output =
Output { ..prev_output, value: [], datum: prev_output.datum } Output { ..prev_output, value: [], datum: prev_output.datum }
prev_output == next_output prev_output == next_output
} }
"#; "#;
@ -3770,23 +3770,23 @@ fn record_update_output_1_val() {
type Address { type Address {
thing: ByteArray, thing: ByteArray,
} }
type Datum { type Datum {
NoDatum NoDatum
InlineDatum(Data) InlineDatum(Data)
} }
type Output { type Output {
address: Address, address: Address,
value: List<(ByteArray, List<(ByteArray, Int)>)>, value: List<(ByteArray, List<(ByteArray, Int)>)>,
datum: Datum, datum: Datum,
script_ref: Option<ByteArray>, script_ref: Option<ByteArray>,
} }
type MyDatum { type MyDatum {
a: Int, a: Int,
} }
test huh() { test huh() {
let prev_output = let prev_output =
Output { Output {
@ -3795,10 +3795,10 @@ fn record_update_output_1_val() {
datum: InlineDatum(MyDatum{a: 3}), datum: InlineDatum(MyDatum{a: 3}),
script_ref: None, script_ref: None,
} }
let next_output = let next_output =
Output { ..prev_output, datum: prev_output.datum } Output { ..prev_output, datum: prev_output.datum }
prev_output == next_output prev_output == next_output
} }
"#; "#;
@ -3871,23 +3871,23 @@ fn record_update_output_first_last_val() {
type Address { type Address {
thing: ByteArray, thing: ByteArray,
} }
type Datum { type Datum {
NoDatum NoDatum
InlineDatum(Data) InlineDatum(Data)
} }
type Output { type Output {
address: Address, address: Address,
value: List<(ByteArray, List<(ByteArray, Int)>)>, value: List<(ByteArray, List<(ByteArray, Int)>)>,
datum: Datum, datum: Datum,
script_ref: Option<ByteArray>, script_ref: Option<ByteArray>,
} }
type MyDatum { type MyDatum {
a: Int, a: Int,
} }
test huh() { test huh() {
let prev_output = let prev_output =
Output { Output {
@ -3896,10 +3896,10 @@ fn record_update_output_first_last_val() {
datum: InlineDatum(MyDatum{a: 3}), datum: InlineDatum(MyDatum{a: 3}),
script_ref: None, script_ref: None,
} }
let next_output = let next_output =
Output { ..prev_output, script_ref: None, address: Address{thing: "script_hash_0"} } Output { ..prev_output, script_ref: None, address: Address{thing: "script_hash_0"} }
prev_output == next_output prev_output == next_output
} }
"#; "#;
@ -3969,14 +3969,14 @@ fn list_fields_unwrap() {
a: ByteArray, a: ByteArray,
b: Int, b: Int,
} }
fn data_fields(){ fn data_fields(){
[ [
Fields{a: #"", b: 14}, Fields{a: #"", b: 14},
Fields{a: #"AA", b: 0} Fields{a: #"AA", b: 0}
] ]
} }
test list_fields_unwr_0() { test list_fields_unwr_0() {
when data_fields() is { when data_fields() is {
[Fields { b, .. }, ..] -> [Fields { b, .. }, ..] ->
@ -4035,27 +4035,27 @@ fn foldl_type_mismatch() {
payment_credential: ByteArray, payment_credential: ByteArray,
stake_credential: Option<ByteArray>, stake_credential: Option<ByteArray>,
} }
type Output { type Output {
address: Address, address: Address,
value: List<Int>, value: List<Int>,
datum: Option<Int>, datum: Option<Int>,
reference_script: Option<Int>, reference_script: Option<Int>,
} }
pub fn foldl(self: List<a>, with: fn(a, b) -> b, zero: b) -> b { pub fn foldl(self: List<a>, with: fn(a, b) -> b, zero: b) -> b {
when self is { when self is {
[] -> zero [] -> zero
[x, ..xs] -> foldl(xs, with, with(x, zero)) [x, ..xs] -> foldl(xs, with, with(x, zero))
} }
} }
test hi() { test hi() {
let addr1 = Address { payment_credential: "adff", stake_credential: None } let addr1 = Address { payment_credential: "adff", stake_credential: None }
let out = let out =
Output { address: addr1, value: [], datum: None, reference_script: None } Output { address: addr1, value: [], datum: None, reference_script: None }
let outputs: List<Output> = let outputs: List<Output> =
[out, out, out] [out, out, out]
let cry = let cry =
@ -4074,7 +4074,7 @@ fn foldl_type_mismatch() {
}, },
None, None,
) )
cry == cry cry == cry
} }
"#; "#;
@ -4466,14 +4466,14 @@ fn expect_head_cast_data_with_tail() {
#[test] #[test]
fn test_init_3() { fn test_init_3() {
let src = r#" let src = r#"
pub fn init(self: List<a>) -> Option<List<a>> { pub fn init(self: List<a>) -> Option<List<a>> {
when self is { when self is {
[] -> None [] -> None
_ -> Some(do_init(self)) _ -> Some(do_init(self))
} }
} }
fn do_init(self: List<a>) -> List<a> { fn do_init(self: List<a>) -> List<a> {
when self is { when self is {
[] -> fail @"unreachable" [] -> fail @"unreachable"
@ -4483,7 +4483,7 @@ fn test_init_3() {
[x, ..do_init(xs)] [x, ..do_init(xs)]
} }
} }
test init_3() { test init_3() {
init([1, 2, 3, 4]) == Some([1, 2, 3]) init([1, 2, 3, 4]) == Some([1, 2, 3])
} }
@ -4579,7 +4579,7 @@ fn list_clause_with_guard() {
} }
} }
} }
test init_3() { test init_3() {
do_init([1, 3]) == [1] do_init([1, 3]) == [1]
} }
@ -4718,7 +4718,7 @@ fn list_clause_with_guard2() {
} }
} }
} }
test init_3() { test init_3() {
do_init([1, 3]) == [1] do_init([1, 3]) == [1]
} }
@ -4850,7 +4850,7 @@ fn list_clause_with_guard3() {
} }
} }
} }
test init_3() { test init_3() {
do_init([1, 3]) == [1] do_init([1, 3]) == [1]
} }
@ -4989,7 +4989,7 @@ fn list_clause_with_assign() {
} }
} }
} }
test init_3() { test init_3() {
do_init([1, 3]) == [1] do_init([1, 3]) == [1]
} }
@ -5135,7 +5135,7 @@ fn list_clause_with_assign2() {
} }
} }
} }
test init_3() { test init_3() {
do_init([Some(1), None]) == [Some(1)] do_init([Some(1), None]) == [Some(1)]
} }
@ -5262,10 +5262,10 @@ fn opaque_value_in_datum() {
a: Value a: Value
} }
validator { validator {
fn spend(dat: Dat, red: Data, ctx: Data) { fn spend(dat: Dat, red: Data, ctx: Data) {
let val = dat.a let val = dat.a
expect [(_, amount)] = val.inner.inner expect [(_, amount)] = val.inner.inner
@ -5452,22 +5452,22 @@ fn opaque_value_in_test() {
pub fn dat_new() -> Dat { pub fn dat_new() -> Dat {
let v = Value { inner: Dict { inner: [("", [(#"aa", 4)] |> Dict)] } } let v = Value { inner: Dict { inner: [("", [(#"aa", 4)] |> Dict)] } }
Dat { Dat {
c: 0, c: 0,
a: v a: v
} }
} }
test spend() { test spend() {
let dat = dat_new() let dat = dat_new()
let val = dat.a let val = dat.a
expect [(_, amount)] = val.inner.inner expect [(_, amount)] = val.inner.inner
let final_amount = [(#"AA", 4)] |> Dict let final_amount = [(#"AA", 4)] |> Dict
final_amount == amount final_amount == amount
} }
"#; "#;

View File

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