From 45339154388e9d7cf65ff28ff190648074ffce21 Mon Sep 17 00:00:00 2001 From: collin Date: Sun, 16 Aug 2020 16:10:07 -0700 Subject: [PATCH] support conditional console functions --- compiler/src/console/assert.rs | 25 ++++++++++------ compiler/src/console/console.rs | 30 +++++++++++++++---- compiler/src/errors/console.rs | 8 ++++- compiler/src/function/function.rs | 3 +- compiler/src/macro_/mod.rs | 5 ---- compiler/src/statement/statement.rs | 2 +- compiler/tests/{macros => console}/debug.leo | 0 compiler/tests/{macros => console}/error.leo | 0 compiler/tests/{macros => console}/mod.rs | 0 compiler/tests/{macros => console}/print.leo | 0 .../tests/{macros => console}/print_fail.leo | 0 .../tests/{macros => console}/print_input.leo | 0 .../{macros => console}/print_parameter.leo | 0 .../print_parameter_fail_empty.leo | 0 .../print_parameter_fail_none.leo | 0 .../print_parameter_fail_unknown.leo | 0 .../print_parameter_many.leo | 0 compiler/tests/mod.rs | 2 +- 18 files changed, 52 insertions(+), 23 deletions(-) delete mode 100644 compiler/src/macro_/mod.rs rename compiler/tests/{macros => console}/debug.leo (100%) rename compiler/tests/{macros => console}/error.leo (100%) rename compiler/tests/{macros => console}/mod.rs (100%) rename compiler/tests/{macros => console}/print.leo (100%) rename compiler/tests/{macros => console}/print_fail.leo (100%) rename compiler/tests/{macros => console}/print_input.leo (100%) rename compiler/tests/{macros => console}/print_parameter.leo (100%) rename compiler/tests/{macros => console}/print_parameter_fail_empty.leo (100%) rename compiler/tests/{macros => console}/print_parameter_fail_none.leo (100%) rename compiler/tests/{macros => console}/print_parameter_fail_unknown.leo (100%) rename compiler/tests/{macros => console}/print_parameter_many.leo (100%) diff --git a/compiler/src/console/assert.rs b/compiler/src/console/assert.rs index b313d40f2b..0c7e00b2d8 100644 --- a/compiler/src/console/assert.rs +++ b/compiler/src/console/assert.rs @@ -1,6 +1,6 @@ //! Enforces an assert equals statement in a compiled Leo program. -use crate::{errors::ConsoleError, evaluate_eq, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; +use crate::{errors::ConsoleError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; use leo_typed::{Expression, Span, Type}; use snarkos_models::{ @@ -14,6 +14,7 @@ impl> ConstrainedProgram { cs: &mut CS, file_scope: String, function_scope: String, + indicator: Option, expression: Expression, span: Span, ) -> Result<(), ConsoleError> { @@ -23,21 +24,27 @@ impl> ConstrainedProgram { // Evaluate assert expression let assert_expression = self.enforce_expression(cs, file_scope, function_scope, expected_type, expression)?; - // Expect assert expression to evaluate to true - let expect_true = ConstrainedValue::Boolean(Boolean::Constant(true)); - let result = evaluate_eq(cs, expect_true, assert_expression, span.clone())?; + // If the indicator bit is false, do not evaluate the assertion + // This is okay since we are not enforcing any constraints + let false_boolean = Boolean::Constant(false); + + if let Some(indicator_bool) = indicator { + if indicator_bool.eq(&false_boolean) { + return Ok(()); // continue execution + } + } // Unwrap assertion value and handle errors - let result_option = match result { + let result_option = match assert_expression { ConstrainedValue::Boolean(boolean) => boolean.get_value(), - _ => unreachable!("evaluate_eq must return boolean"), + _ => return Err(ConsoleError::assertion_must_be_boolean(expression_string, span.clone())), }; let result_bool = result_option.ok_or(ConsoleError::assertion_depends_on_input(span.clone()))?; if !result_bool { - Err(ConsoleError::assertion_failed(expression_string, span)) - } else { - Ok(()) + return Err(ConsoleError::assertion_failed(expression_string, span)); } + + Ok(()) } } diff --git a/compiler/src/console/console.rs b/compiler/src/console/console.rs index 5f4134f520..1e2f8d2acf 100644 --- a/compiler/src/console/console.rs +++ b/compiler/src/console/console.rs @@ -5,7 +5,7 @@ use leo_typed::{ConsoleFunction, ConsoleFunctionCall}; use snarkos_models::{ curves::{Field, PrimeField}, - gadgets::r1cs::ConstraintSystem, + gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean}, }; impl> ConstrainedProgram { @@ -14,29 +14,49 @@ impl> ConstrainedProgram { cs: &mut CS, file_scope: String, function_scope: String, + indicator: Option, console: ConsoleFunctionCall, ) -> Result<(), ConsoleError> { match console.function { ConsoleFunction::Assert(expression) => { - self.evaluate_console_assert(cs, file_scope, function_scope, expression, console.span)?; + self.evaluate_console_assert(cs, file_scope, function_scope, indicator, expression, console.span)?; } ConsoleFunction::Debug(string) => { let string = self.format(cs, file_scope, function_scope, string)?; - log::debug!("{}", string); + if unwrap_indicator_value(indicator) { + log::debug!("{}", string); + } } ConsoleFunction::Error(string) => { let string = self.format(cs, file_scope, function_scope, string)?; - log::error!("{}", string); + if unwrap_indicator_value(indicator) { + log::error!("{}", string); + } } ConsoleFunction::Log(string) => { let string = self.format(cs, file_scope, function_scope, string)?; - println!("{}", string); + if unwrap_indicator_value(indicator) { + log::info!("{}", string); + } } } Ok(()) } } + +// Return the indicator boolean gadget value or true if it is None +// This is okay since we are not enforcing any constraints +fn unwrap_indicator_value(indicator: Option) -> bool { + let false_boolean = Boolean::constant(false); + + if let Some(indicator_bool) = indicator { + if indicator_bool.eq(&false_boolean) { + return false; + } + } + true +} diff --git a/compiler/src/errors/console.rs b/compiler/src/errors/console.rs index b363f6f49f..87a4d03970 100644 --- a/compiler/src/errors/console.rs +++ b/compiler/src/errors/console.rs @@ -40,7 +40,13 @@ impl ConsoleError { } pub fn assertion_failed(expression: String, span: Span) -> Self { - let message = format!("Assertion `true == {}` failed", expression); + let message = format!("Assertion `{}` failed", expression); + + Self::new_from_span(message, span) + } + + pub fn assertion_must_be_boolean(expression: String, span: Span) -> Self { + let message = format!("Assertion expression `{}` must evaluate to a boolean value", expression); Self::new_from_span(message, span) } diff --git a/compiler/src/function/function.rs b/compiler/src/function/function.rs index d266e1fa8a..07f0b041f6 100644 --- a/compiler/src/function/function.rs +++ b/compiler/src/function/function.rs @@ -11,7 +11,7 @@ use leo_typed::{Expression, Function, InputVariable, Span, Type}; use snarkos_models::{ curves::{Field, PrimeField}, - gadgets::r1cs::ConstraintSystem, + gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean}, }; pub fn check_arguments_length(expected: usize, actual: usize, span: Span) -> Result<(), FunctionError> { @@ -78,6 +78,7 @@ impl> ConstrainedProgram { // Evaluate every statement in the function and save all potential results let mut results = vec![]; + let indicator = Some(Boolean::constant(true)); for statement in function.statements.iter() { let mut result = self.enforce_statement( diff --git a/compiler/src/macro_/mod.rs b/compiler/src/macro_/mod.rs deleted file mode 100644 index 5b3801059c..0000000000 --- a/compiler/src/macro_/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod format; -pub use self::format::*; - -pub mod macro_; -pub use self::macro_::*; diff --git a/compiler/src/statement/statement.rs b/compiler/src/statement/statement.rs index d1c95a7f21..900120cd94 100644 --- a/compiler/src/statement/statement.rs +++ b/compiler/src/statement/statement.rs @@ -78,7 +78,7 @@ impl> ConstrainedProgram { results.append(&mut result); } Statement::Console(console) => { - self.evaluate_console_function_call(cs, file_scope, function_scope, console)?; + self.evaluate_console_function_call(cs, file_scope, function_scope, indicator, console)?; } Statement::Expression(expression, span) => { let expression_string = expression.to_string(); diff --git a/compiler/tests/macros/debug.leo b/compiler/tests/console/debug.leo similarity index 100% rename from compiler/tests/macros/debug.leo rename to compiler/tests/console/debug.leo diff --git a/compiler/tests/macros/error.leo b/compiler/tests/console/error.leo similarity index 100% rename from compiler/tests/macros/error.leo rename to compiler/tests/console/error.leo diff --git a/compiler/tests/macros/mod.rs b/compiler/tests/console/mod.rs similarity index 100% rename from compiler/tests/macros/mod.rs rename to compiler/tests/console/mod.rs diff --git a/compiler/tests/macros/print.leo b/compiler/tests/console/print.leo similarity index 100% rename from compiler/tests/macros/print.leo rename to compiler/tests/console/print.leo diff --git a/compiler/tests/macros/print_fail.leo b/compiler/tests/console/print_fail.leo similarity index 100% rename from compiler/tests/macros/print_fail.leo rename to compiler/tests/console/print_fail.leo diff --git a/compiler/tests/macros/print_input.leo b/compiler/tests/console/print_input.leo similarity index 100% rename from compiler/tests/macros/print_input.leo rename to compiler/tests/console/print_input.leo diff --git a/compiler/tests/macros/print_parameter.leo b/compiler/tests/console/print_parameter.leo similarity index 100% rename from compiler/tests/macros/print_parameter.leo rename to compiler/tests/console/print_parameter.leo diff --git a/compiler/tests/macros/print_parameter_fail_empty.leo b/compiler/tests/console/print_parameter_fail_empty.leo similarity index 100% rename from compiler/tests/macros/print_parameter_fail_empty.leo rename to compiler/tests/console/print_parameter_fail_empty.leo diff --git a/compiler/tests/macros/print_parameter_fail_none.leo b/compiler/tests/console/print_parameter_fail_none.leo similarity index 100% rename from compiler/tests/macros/print_parameter_fail_none.leo rename to compiler/tests/console/print_parameter_fail_none.leo diff --git a/compiler/tests/macros/print_parameter_fail_unknown.leo b/compiler/tests/console/print_parameter_fail_unknown.leo similarity index 100% rename from compiler/tests/macros/print_parameter_fail_unknown.leo rename to compiler/tests/console/print_parameter_fail_unknown.leo diff --git a/compiler/tests/macros/print_parameter_many.leo b/compiler/tests/console/print_parameter_many.leo similarity index 100% rename from compiler/tests/macros/print_parameter_many.leo rename to compiler/tests/console/print_parameter_many.leo diff --git a/compiler/tests/mod.rs b/compiler/tests/mod.rs index b58767e5d0..7da698282b 100644 --- a/compiler/tests/mod.rs +++ b/compiler/tests/mod.rs @@ -2,6 +2,7 @@ pub mod address; pub mod array; pub mod boolean; pub mod circuits; +pub mod console; pub mod definition; pub mod field; pub mod function; @@ -9,7 +10,6 @@ pub mod group; pub mod import; pub mod input_files; pub mod integers; -pub mod macros; pub mod mutability; pub mod statements; pub mod syntax;