From f79b37d5518c40d5d3f5dff7266bd4db43b3d60a Mon Sep 17 00:00:00 2001 From: microproofs Date: Wed, 17 Jan 2024 11:53:29 -0500 Subject: [PATCH] Replace 'bool' with 'TraceLevel' in codegen Co-authored-by: KtorZ --- crates/aiken-lang/src/gen_uplc.rs | 87 +++++++------- crates/aiken-lang/src/gen_uplc/builder.rs | 107 +++++++++--------- .../aiken-project/src/blueprint/validator.rs | 8 +- crates/aiken-project/src/lib.rs | 25 +--- crates/aiken-project/src/module.rs | 6 +- 5 files changed, 115 insertions(+), 118 deletions(-) diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index b4481f1e..678e29db 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -19,8 +19,8 @@ use uplc::{ use crate::{ ast::{ - AssignmentKind, BinOp, Bls12_381Point, Curve, Pattern, Span, TypedArg, TypedClause, - TypedDataType, TypedFunction, TypedPattern, TypedValidator, UnOp, + AssignmentKind, BinOp, Bls12_381Point, Curve, Pattern, Span, TraceLevel, TypedArg, + TypedClause, TypedDataType, TypedFunction, TypedPattern, TypedValidator, UnOp, }, builtins::{bool, data, int, list, string, void}, expr::TypedExpr, @@ -57,7 +57,7 @@ pub struct CodeGenerator<'a> { module_types: IndexMap<&'a String, &'a TypeInfo>, module_src: IndexMap, /// immutable option - tracing: bool, + tracing: TraceLevel, /// mutable index maps that are reset defined_functions: IndexMap, special_functions: CodeGenSpecialFuncs, @@ -75,7 +75,7 @@ impl<'a> CodeGenerator<'a> { data_types: IndexMap, module_types: IndexMap<&'a String, &'a TypeInfo>, module_src: IndexMap, - tracing: bool, + tracing: TraceLevel, ) -> Self { CodeGenerator { functions, @@ -478,10 +478,12 @@ impl<'a> CodeGenerator<'a> { string(), ); - let msg_func = if self.tracing && kind.is_expect() { - Some(self.special_functions.use_function_msg(msg_func_name)) - } else { - None + // TODO + let msg_func = match self.tracing { + TraceLevel::Verbose if kind.is_expect() => { + Some(self.special_functions.use_function_msg(msg_func_name)) + } + _ => None, }; self.assignment( @@ -1586,19 +1588,20 @@ 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) = if self.tracing { - let msg = AirMsg::LocalVar("__param_msg".to_string()); + let (msg_term, error_term) = match self.tracing { + TraceLevel::Verbose => { + let msg = AirMsg::LocalVar("__param_msg".to_string()); - ( - Some(msg.clone()), - AirTree::trace( - msg.to_air_tree(), - tipo.clone(), - AirTree::error(tipo.clone(), false), - ), - ) - } else { - (None, AirTree::error(tipo.clone(), false)) + ( + Some(msg.clone()), + AirTree::trace( + msg.to_air_tree(), + tipo.clone(), + AirTree::error(tipo.clone(), false), + ), + ) + } + TraceLevel::Silent => (None, AirTree::error(tipo.clone(), false)), }; defined_data_types.insert(data_type_name.clone(), 1); @@ -1717,16 +1720,15 @@ impl<'a> CodeGenerator<'a> { } } - let code_gen_func = if self.tracing { - CodeGenFunction::Function { + let code_gen_func = match self.tracing { + TraceLevel::Verbose => CodeGenFunction::Function { body: func_body, params: vec!["__param_0".to_string(), "__param_msg".to_string()], - } - } else { - CodeGenFunction::Function { + }, + TraceLevel::Silent => CodeGenFunction::Function { body: func_body, params: vec!["__param_0".to_string()], - } + }, }; self.code_gen_functions @@ -1737,15 +1739,14 @@ impl<'a> CodeGenerator<'a> { defined_data_types.insert(data_type_name.to_string(), 1); } - let args = if self.tracing { - vec![ + let args = match self.tracing { + TraceLevel::Silent => vec![value], + TraceLevel::Verbose => vec![ value, msg_func .expect("should be unreachable: no msg func with tracing enabled.") .to_air_tree(), - ] - } else { - vec![value] + ], }; let module_fn = ValueConstructorVariant::ModuleFn { @@ -2762,10 +2763,12 @@ impl<'a> CodeGenerator<'a> { string(), ); - let msg_func = if self.tracing && !actual_type.is_data() { - Some(self.special_functions.use_function_msg(msg_func_name)) - } else { - None + // TODO + let msg_func = match self.tracing { + TraceLevel::Verbose => { + Some(self.special_functions.use_function_msg(msg_func_name)) + } + _ => None, }; let assign = self.assignment( @@ -3721,14 +3724,14 @@ impl<'a> CodeGenerator<'a> { fn gen_uplc(&mut self, ir: Air, arg_stack: &mut Vec>) -> Option> { // Going to mark the changes made to code gen after air tree implementation - let error_term = if self.tracing && air_holds_msg(&ir) { - // In the case of an air that holds a msg and tracing is active - // we pop the msg off the stack first - let msg = arg_stack.pop().unwrap(); + // TODO + let error_term = match self.tracing { + TraceLevel::Verbose if air_holds_msg(&ir) => { + let msg = arg_stack.pop().unwrap(); - Term::Error.delayed_trace(msg) - } else { - Term::Error + Term::Error.delayed_trace(msg) + } + _ => Term::Error, }; match ir { diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index b5567d1a..1f47a4cb 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -15,8 +15,8 @@ use uplc::{ use crate::{ ast::{ - AssignmentKind, DataType, Pattern, Span, TypedArg, TypedClause, TypedClauseGuard, - TypedDataType, TypedPattern, + AssignmentKind, DataType, Pattern, Span, TraceLevel, TypedArg, TypedClause, + TypedClauseGuard, TypedDataType, TypedPattern, }, builtins::{bool, data, function, int, list, string, void}, expr::TypedExpr, @@ -1621,52 +1621,12 @@ pub fn special_case_builtin( pub fn wrap_as_multi_validator( spend: Term, mint: Term, - trace: bool, + trace: TraceLevel, spend_name: String, mint_name: String, ) -> Term { - if trace { - let trace_string = format!( - "Incorrect redeemer type for validator {}. - Double check you have wrapped the redeemer type as specified in your plutus.json", - spend_name - ); - - let error_term = Term::Error.delayed_trace(Term::var("__incorrect_second_arg_type")); - - 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!( - "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!( - "Running 3 arg validator {}", - spend_name - ))), - ), - error_term.clone(), - error_term.clone(), - error_term.clone(), - error_term, - ) - .lambda("__incorrect_second_arg_type") - .apply(Term::string(trace_string)) - .lambda("__second_arg") - .lambda("__first_arg") - } else { - Term::equals_integer() + match trace { + TraceLevel::Silent => Term::equals_integer() .apply(Term::integer(0.into())) .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("__second_arg"))) .delayed_if_then_else( @@ -1678,7 +1638,51 @@ pub fn wrap_as_multi_validator( ), ) .lambda("__second_arg") - .lambda("__first_arg") + .lambda("__first_arg"), + TraceLevel::Verbose => { + let trace_string = format!( + "Incorrect redeemer type for validator {}. + Double check you have wrapped the redeemer type as specified in your plutus.json", + spend_name + ); + + let error_term = Term::Error.delayed_trace(Term::var("__incorrect_second_arg_type")); + + 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!( + "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!( + "Running 3 arg validator {}", + spend_name + ))), + ), + error_term.clone(), + error_term.clone(), + error_term.clone(), + error_term, + ) + .lambda("__incorrect_second_arg_type") + .apply(Term::string(trace_string)) + .lambda("__second_arg") + .lambda("__first_arg") + } } } @@ -1717,16 +1721,15 @@ pub fn cast_validator_args(term: Term, arguments: &[TypedArg]) -> Term AirTree { +pub fn wrap_validator_condition(air_tree: AirTree, trace: TraceLevel) -> AirTree { let success_branch = vec![(air_tree, AirTree::void())]; - let otherwise = if trace { - AirTree::trace( + let otherwise = match trace { + TraceLevel::Silent => AirTree::error(void(), true), + TraceLevel::Verbose => AirTree::trace( AirTree::string("Validator returned false"), void(), AirTree::error(void(), true), - ) - } else { - AirTree::error(void(), true) + ), }; AirTree::if_branches(success_branch, void(), otherwise) diff --git a/crates/aiken-project/src/blueprint/validator.rs b/crates/aiken-project/src/blueprint/validator.rs index d86f71bc..cc4af084 100644 --- a/crates/aiken-project/src/blueprint/validator.rs +++ b/crates/aiken-project/src/blueprint/validator.rs @@ -217,7 +217,11 @@ impl Validator { mod tests { use std::collections::HashMap; - use aiken_lang::{self, builtins}; + use aiken_lang::{ + self, + ast::{TraceLevel, Tracing}, + builtins, + }; use uplc::ast as uplc_ast; use crate::tests::TestProject; @@ -240,7 +244,7 @@ mod tests { &project.functions, &project.data_types, &project.module_types, - true, + Tracing::All(TraceLevel::Verbose), ); let (validator, def) = modules diff --git a/crates/aiken-project/src/lib.rs b/crates/aiken-project/src/lib.rs index 2647c8fb..f6f74ff9 100644 --- a/crates/aiken-project/src/lib.rs +++ b/crates/aiken-project/src/lib.rs @@ -22,10 +22,7 @@ use crate::blueprint::{ Blueprint, }; use aiken_lang::{ - ast::{ - Definition, Function, ModuleKind, TraceLevel, Tracing, TypedDataType, TypedFunction, - Validator, - }, + ast::{Definition, Function, ModuleKind, Tracing, TypedDataType, TypedFunction, Validator}, builtins, gen_uplc::builder::{DataTypeKey, FunctionAccessKey}, tipo::TypeInfo, @@ -285,10 +282,7 @@ where &self.functions, &self.data_types, &self.module_types, - match options.tracing.trace_level(true) { - TraceLevel::Silent => false, - TraceLevel::Verbose => true, - }, + options.tracing, ); let blueprint = Blueprint::new(&self.config, &self.checked_modules, &mut generator) @@ -317,15 +311,8 @@ where verbose, exact_match, } => { - let tests = self.collect_tests( - verbose, - match_tests, - exact_match, - match options.tracing.trace_level(true) { - TraceLevel::Silent => false, - TraceLevel::Verbose => true, - }, - )?; + let tests = + self.collect_tests(verbose, match_tests, exact_match, options.tracing)?; if !tests.is_empty() { self.event_listener.handle_event(Event::RunningTests); @@ -688,7 +675,7 @@ where verbose: bool, match_tests: Option>, exact_match: bool, - code_gen_tracing: bool, + tracing: Tracing, ) -> Result, Error> { let mut scripts = Vec::new(); let mut testable_validators = Vec::new(); @@ -791,7 +778,7 @@ where &self.functions, &self.data_types, &self.module_types, - code_gen_tracing, + tracing, ); for (module_name, testable_validator) in &testable_validators { diff --git a/crates/aiken-project/src/module.rs b/crates/aiken-project/src/module.rs index 7fd3f68d..5737be52 100644 --- a/crates/aiken-project/src/module.rs +++ b/crates/aiken-project/src/module.rs @@ -1,7 +1,7 @@ use crate::error::Error; use aiken_lang::{ ast::{ - DataType, Definition, Function, Located, ModuleKind, TypedDataType, TypedFunction, + DataType, Definition, Function, Located, ModuleKind, Tracing, TypedDataType, TypedFunction, TypedModule, TypedValidator, UntypedModule, Validator, }, gen_uplc::{ @@ -358,7 +358,7 @@ impl CheckedModules { builtin_functions: &'a IndexMap, builtin_data_types: &'a IndexMap, module_types: &'a HashMap, - tracing: bool, + tracing: Tracing, ) -> CodeGenerator<'a> { let mut functions = IndexMap::new(); for (k, v) in builtin_functions { @@ -412,7 +412,7 @@ impl CheckedModules { data_types, module_types_index, module_src, - tracing, + tracing.trace_level(true), ) } }