mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-24 18:52:58 +03:00
fix boolean namespaces and errors
This commit is contained in:
parent
03c6af2d46
commit
d1dfdcb878
@ -5,7 +5,7 @@ use crate::{
|
||||
errors::BooleanError,
|
||||
GroupType,
|
||||
};
|
||||
use leo_types::InputValue;
|
||||
use leo_types::{InputValue, Span};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
@ -22,6 +22,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
cs: &mut CS,
|
||||
name: String,
|
||||
input_value: Option<InputValue>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
||||
// Check that the input value is the correct type
|
||||
let bool_value = match input_value {
|
||||
@ -29,21 +30,29 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
if let InputValue::Boolean(bool) = input {
|
||||
Some(bool)
|
||||
} else {
|
||||
return Err(BooleanError::SynthesisError(SynthesisError::AssignmentMissing));
|
||||
return Err(BooleanError::invalid_boolean(name, span));
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
let number = Boolean::alloc(cs.ns(|| name), || bool_value.ok_or(SynthesisError::AssignmentMissing))?;
|
||||
let boolean_name = format!("{}: bool", name);
|
||||
let boolean_name_unique = format!("`{}` {}:{}", boolean_name, span.line, span.start);
|
||||
let number = Boolean::alloc(cs.ns(|| boolean_name_unique), || {
|
||||
bool_value.ok_or(SynthesisError::AssignmentMissing)
|
||||
})
|
||||
.map_err(|_| BooleanError::missing_boolean(boolean_name, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(number))
|
||||
}
|
||||
|
||||
pub(crate) fn evaluate_not(value: ConstrainedValue<F, G>) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
||||
pub(crate) fn evaluate_not(
|
||||
value: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
||||
match value {
|
||||
ConstrainedValue::Boolean(boolean) => Ok(ConstrainedValue::Boolean(boolean.not())),
|
||||
value => Err(BooleanError::CannotEvaluate(format!("!{}", value))),
|
||||
value => Err(BooleanError::cannot_evaluate(format!("!{}", value), span)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,15 +61,19 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) => {
|
||||
Ok(ConstrainedValue::Boolean(Boolean::or(cs, &left_bool, &right_bool)?))
|
||||
Ok(ConstrainedValue::Boolean(
|
||||
Boolean::or(cs, &left_bool, &right_bool)
|
||||
.map_err(|e| BooleanError::cannot_enforce(format!("||"), e, span))?,
|
||||
))
|
||||
}
|
||||
(left_value, right_value) => Err(BooleanError::CannotEnforce(format!(
|
||||
"{} || {}",
|
||||
left_value, right_value
|
||||
))),
|
||||
(left_value, right_value) => Err(BooleanError::cannot_evaluate(
|
||||
format!("{} || {}", left_value, right_value),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,15 +82,19 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) => {
|
||||
Ok(ConstrainedValue::Boolean(Boolean::and(cs, &left_bool, &right_bool)?))
|
||||
Ok(ConstrainedValue::Boolean(
|
||||
Boolean::and(cs, &left_bool, &right_bool)
|
||||
.map_err(|e| BooleanError::cannot_enforce(format!("&&"), e, span))?,
|
||||
))
|
||||
}
|
||||
(left_value, right_value) => Err(BooleanError::CannotEnforce(format!(
|
||||
"{} && {}",
|
||||
left_value, right_value
|
||||
))),
|
||||
(left_value, right_value) => Err(BooleanError::cannot_evaluate(
|
||||
format!("{} && {}", left_value, right_value),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -939,13 +939,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
|
||||
// Boolean operations
|
||||
Expression::Not(expression) => Ok(Self::evaluate_not(self.enforce_expression(
|
||||
cs,
|
||||
file_scope,
|
||||
function_scope,
|
||||
expected_types,
|
||||
*expression,
|
||||
)?)?),
|
||||
Expression::Not(expression, span) => Ok(Self::evaluate_not(
|
||||
self.enforce_expression(cs, file_scope, function_scope, expected_types, *expression)?,
|
||||
span,
|
||||
)?),
|
||||
Expression::Or(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
@ -957,7 +954,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
span.clone(),
|
||||
)?;
|
||||
|
||||
Ok(self.enforce_or(cs, resolved_left, resolved_right)?)
|
||||
Ok(self.enforce_or(cs, resolved_left, resolved_right, span)?)
|
||||
}
|
||||
Expression::And(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
@ -970,7 +967,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
span.clone(),
|
||||
)?;
|
||||
|
||||
Ok(self.enforce_and(cs, resolved_left, resolved_right)?)
|
||||
Ok(self.enforce_and(cs, resolved_left, resolved_right, span)?)
|
||||
}
|
||||
Expression::Eq(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
|
@ -173,7 +173,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
)?)),
|
||||
Type::Field => Ok(field_from_input(cs, name, input_value, span)?),
|
||||
Type::Group => Ok(group_from_input(cs, name, input_value, span)?),
|
||||
Type::Boolean => Ok(self.bool_from_input(cs, name, input_value)?),
|
||||
Type::Boolean => Ok(self.bool_from_input(cs, name, input_value, span)?),
|
||||
Type::Array(_type, dimensions) => self.allocate_array(cs, name, *_type, dimensions, input_value, span),
|
||||
_ => unimplemented!("main function input not implemented for type"),
|
||||
}
|
||||
|
@ -1,9 +1,14 @@
|
||||
use leo_types::{Error as FormattedError, Span};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
|
||||
use std::str::ParseBoolError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum BooleanError {
|
||||
#[error("{}", _0)]
|
||||
Error(#[from] FormattedError),
|
||||
|
||||
#[error("Cannot evaluate {}", _0)]
|
||||
CannotEvaluate(String),
|
||||
|
||||
@ -16,3 +21,36 @@ pub enum BooleanError {
|
||||
#[error("{}", _0)]
|
||||
SynthesisError(#[from] SynthesisError),
|
||||
}
|
||||
|
||||
impl BooleanError {
|
||||
fn new_from_span(message: String, span: Span) -> Self {
|
||||
BooleanError::Error(FormattedError::new_from_span(message, span))
|
||||
}
|
||||
|
||||
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
|
||||
let message = format!(
|
||||
"the boolean operation `{}` failed due to the synthesis error `{}`",
|
||||
operation, error,
|
||||
);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn cannot_evaluate(operation: String, span: Span) -> Self {
|
||||
let message = format!("no implementation found for `{}`", operation);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn invalid_boolean(actual: String, span: Span) -> Self {
|
||||
let message = format!("expected boolean input type, found `{}`", actual);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn missing_boolean(expected: String, span: Span) -> Self {
|
||||
let message = format!("expected boolean input `{}` not found", expected);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
}
|
||||
|
@ -23,35 +23,19 @@ pub fn output_false(program: EdwardsTestCompiler) {
|
||||
output_expected_boolean(program, false)
|
||||
}
|
||||
|
||||
fn fail_evaluate(program: EdwardsTestCompiler) {
|
||||
match get_error(program) {
|
||||
CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError(
|
||||
ExpressionError::BooleanError(BooleanError::CannotEvaluate(_string)),
|
||||
))) => {}
|
||||
error => panic!("Expected evaluate error, got {}", error),
|
||||
}
|
||||
}
|
||||
|
||||
fn fail_enforce(program: EdwardsTestCompiler) {
|
||||
match get_error(program) {
|
||||
CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError(
|
||||
ExpressionError::BooleanError(BooleanError::CannotEnforce(_string)),
|
||||
))) => {}
|
||||
error => panic!("Expected evaluate error, got {}", error),
|
||||
}
|
||||
}
|
||||
|
||||
fn fail_boolean(program: EdwardsTestCompiler) {
|
||||
match get_error(program) {
|
||||
CompilerError::FunctionError(FunctionError::BooleanError(BooleanError::SynthesisError(_))) => {}
|
||||
error => panic!("Expected invalid boolean error, got {}", error),
|
||||
CompilerError::FunctionError(FunctionError::BooleanError(BooleanError::Error(_))) => {}
|
||||
error => panic!("Expected boolean error, got {}", error),
|
||||
}
|
||||
}
|
||||
|
||||
fn fail_synthesis(program: EdwardsTestCompiler) {
|
||||
fn fail_boolean_statement(program: EdwardsTestCompiler) {
|
||||
match get_error(program) {
|
||||
CompilerError::FunctionError(FunctionError::BooleanError(BooleanError::SynthesisError(_string))) => {}
|
||||
error => panic!("Expected synthesis error, got {}", error),
|
||||
CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError(
|
||||
ExpressionError::BooleanError(BooleanError::Error(_)),
|
||||
))) => {}
|
||||
_ => panic!("Expected boolean error, got {}"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +72,7 @@ fn test_input_bool_none() {
|
||||
|
||||
program.set_inputs(vec![None]);
|
||||
|
||||
fail_synthesis(program);
|
||||
fail_boolean(program);
|
||||
}
|
||||
|
||||
// Boolean not !
|
||||
@ -114,7 +98,7 @@ fn test_not_u32() {
|
||||
let bytes = include_bytes!("not_u32.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
fail_evaluate(program);
|
||||
fail_boolean_statement(program)
|
||||
}
|
||||
|
||||
// Boolean or ||
|
||||
@ -148,7 +132,7 @@ fn test_true_or_u32() {
|
||||
let bytes = include_bytes!("true_or_u32.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
fail_enforce(program);
|
||||
fail_boolean_statement(program);
|
||||
}
|
||||
|
||||
// Boolean and &&
|
||||
@ -182,7 +166,7 @@ fn test_true_and_u32() {
|
||||
let bytes = include_bytes!("true_and_u32.leo");
|
||||
let program = parse_program(bytes).unwrap();
|
||||
|
||||
fail_enforce(program);
|
||||
fail_boolean_statement(program);
|
||||
}
|
||||
|
||||
// All
|
||||
|
@ -41,7 +41,7 @@ pub enum Expression {
|
||||
Pow(Box<Expression>, Box<Expression>, Span),
|
||||
|
||||
// Boolean operations
|
||||
Not(Box<Expression>),
|
||||
Not(Box<Expression>, Span),
|
||||
Or(Box<Expression>, Box<Expression>, Span),
|
||||
And(Box<Expression>, Box<Expression>, Span),
|
||||
Eq(Box<Expression>, Box<Expression>, Span),
|
||||
@ -78,6 +78,7 @@ impl Expression {
|
||||
Expression::Div(_, _, old_span) => *old_span = new_span.clone(),
|
||||
Expression::Pow(_, _, old_span) => *old_span = new_span.clone(),
|
||||
|
||||
Expression::Not(_, old_span) => *old_span = new_span.clone(),
|
||||
Expression::Or(_, _, old_span) => *old_span = new_span.clone(),
|
||||
Expression::And(_, _, old_span) => *old_span = new_span.clone(),
|
||||
Expression::Eq(_, _, old_span) => *old_span = new_span.clone(),
|
||||
@ -135,7 +136,7 @@ impl<'ast> fmt::Display for Expression {
|
||||
Expression::Pow(ref left, ref right, ref _span) => write!(f, "{} ** {}", left, right),
|
||||
|
||||
// Boolean operations
|
||||
Expression::Not(ref expression) => write!(f, "!{}", expression),
|
||||
Expression::Not(ref expression, ref _span) => write!(f, "!{}", expression),
|
||||
Expression::Or(ref lhs, ref rhs, ref _span) => write!(f, "{} || {}", lhs, rhs),
|
||||
Expression::And(ref lhs, ref rhs, ref _span) => write!(f, "{} && {}", lhs, rhs),
|
||||
Expression::Eq(ref lhs, ref rhs, ref _span) => write!(f, "{} == {}", lhs, rhs),
|
||||
@ -312,7 +313,10 @@ impl<'ast> From<BinaryExpression<'ast>> for Expression {
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Ne => Expression::Not(Box::new(Expression::from(expression))),
|
||||
BinaryOperation::Ne => Expression::Not(
|
||||
Box::new(Expression::from(expression.clone())),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Ge => Expression::Ge(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
@ -410,7 +414,10 @@ impl<'ast> From<Value<'ast>> for Expression {
|
||||
|
||||
impl<'ast> From<NotExpression<'ast>> for Expression {
|
||||
fn from(expression: NotExpression<'ast>) -> Self {
|
||||
Expression::Not(Box::new(Expression::from(*expression.expression)))
|
||||
Expression::Not(
|
||||
Box::new(Expression::from(*expression.expression)),
|
||||
Span::from(expression.span),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user