convert statements to span with error

This commit is contained in:
collin 2020-06-19 19:04:13 -07:00
parent 6922d5dd73
commit 3d1fe9cc4b
11 changed files with 290 additions and 164 deletions

View File

@ -15,6 +15,7 @@ use leo_types::{
Identifier,
Integer,
RangeOrExpression,
Span,
Statement,
Type,
Variable,
@ -37,14 +38,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
}
}
fn get_mutable_assignee(&mut self, name: String) -> Result<&mut ConstrainedValue<F, G>, StatementError> {
fn get_mutable_assignee(
&mut self,
name: String,
span: Span,
) -> Result<&mut ConstrainedValue<F, G>, StatementError> {
// Check that assignee exists and is mutable
Ok(match self.get_mut(&name) {
Some(value) => match value {
ConstrainedValue::Mutable(mutable_value) => mutable_value,
_ => return Err(StatementError::ImmutableAssign(name)),
_ => return Err(StatementError::immutable_assign(name, span)),
},
None => return Err(StatementError::UndefinedVariable(name)),
None => return Err(StatementError::undefined_variable(name, span)),
})
}
@ -57,6 +62,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
name: String,
range_or_expression: RangeOrExpression,
mut new_value: ConstrainedValue<F, G>,
span: Span,
) -> Result<(), StatementError> {
let condition = indicator.unwrap_or(Boolean::Constant(true));
@ -66,18 +72,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let index = self.enforce_index(cs, file_scope.clone(), function_scope.clone(), index)?;
// Modify the single value of the array in place
match self.get_mutable_assignee(name)? {
match self.get_mutable_assignee(name, span.clone())? {
ConstrainedValue::Array(old) => {
new_value.resolve_type(&vec![old[index].to_type()])?;
let selected_value =
ConstrainedValue::conditionally_select(cs, &condition, &new_value, &old[index]).map_err(
|_| StatementError::SelectFail(new_value.to_string(), old[index].to_string()),
|_| StatementError::select_fail(new_value.to_string(), old[index].to_string(), span),
)?;
old[index] = selected_value;
}
_ => return Err(StatementError::ArrayAssignIndex),
_ => return Err(StatementError::array_assign_index(span)),
}
}
RangeOrExpression::Range(from, to) => {
@ -91,7 +97,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
};
// Modify the range of values of the array
let old_array = self.get_mutable_assignee(name)?;
let old_array = self.get_mutable_assignee(name, span.clone())?;
let new_array = match (old_array.clone(), new_value) {
(ConstrainedValue::Array(mut mutable), ConstrainedValue::Array(new)) => {
let to_index = to_index_option.unwrap_or(mutable.len());
@ -99,10 +105,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
mutable.splice(from_index..to_index, new.iter().cloned());
ConstrainedValue::Array(mutable)
}
_ => return Err(StatementError::ArrayAssignRange),
_ => return Err(StatementError::array_assign_range(span)),
};
let selected_array = ConstrainedValue::conditionally_select(cs, &condition, &new_array, old_array)
.map_err(|_| StatementError::SelectFail(new_array.to_string(), old_array.to_string()))?;
.map_err(|_| StatementError::select_fail(new_array.to_string(), old_array.to_string(), span))?;
*old_array = selected_array;
}
}
@ -117,10 +123,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
circuit_name: String,
object_name: Identifier,
mut new_value: ConstrainedValue<F, G>,
span: Span,
) -> Result<(), StatementError> {
let condition = indicator.unwrap_or(Boolean::Constant(true));
match self.get_mutable_assignee(circuit_name)? {
match self.get_mutable_assignee(circuit_name, span.clone())? {
ConstrainedValue::CircuitExpression(_variable, members) => {
// Modify the circuit field in place
let matched_field = members.into_iter().find(|object| object.0 == object_name);
@ -128,28 +135,29 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
match matched_field {
Some(object) => match &object.1 {
ConstrainedValue::Function(_circuit_identifier, function) => {
return Err(StatementError::ImmutableCircuitFunction(
return Err(StatementError::immutable_circuit_function(
function.function_name.to_string(),
span,
));
}
ConstrainedValue::Static(_value) => {
return Err(StatementError::ImmutableCircuitFunction("static".into()));
return Err(StatementError::immutable_circuit_function("static".into(), span));
}
_ => {
new_value.resolve_type(&vec![object.1.to_type()])?;
let selected_value = ConstrainedValue::conditionally_select(
cs, &condition, &new_value, &object.1,
)
.map_err(|_| StatementError::SelectFail(new_value.to_string(), object.1.to_string()))?;
let selected_value =
ConstrainedValue::conditionally_select(cs, &condition, &new_value, &object.1).map_err(
|_| StatementError::select_fail(new_value.to_string(), object.1.to_string(), span),
)?;
object.1 = selected_value.to_owned();
}
},
None => return Err(StatementError::UndefinedCircuitObject(object_name.to_string())),
None => return Err(StatementError::undefined_circuit_object(object_name.to_string(), span)),
}
}
_ => return Err(StatementError::UndefinedCircuit(object_name.to_string())),
_ => return Err(StatementError::undefined_circuit(object_name.to_string(), span)),
}
Ok(())
@ -163,6 +171,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
indicator: Option<Boolean>,
assignee: Assignee,
expression: Expression,
span: Span,
) -> Result<(), StatementError> {
// Get the name of the variable we are assigning to
let variable_name = self.resolve_assignee(function_scope.clone(), assignee.clone());
@ -175,10 +184,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
match assignee {
Assignee::Identifier(_identifier) => {
let condition = indicator.unwrap_or(Boolean::Constant(true));
let old_value = self.get_mutable_assignee(variable_name.clone())?;
let old_value = self.get_mutable_assignee(variable_name.clone(), span.clone())?;
new_value.resolve_type(&vec![old_value.to_type()])?;
let selected_value = ConstrainedValue::conditionally_select(cs, &condition, &new_value, old_value)
.map_err(|_| StatementError::SelectFail(new_value.to_string(), old_value.to_string()))?;
.map_err(|_| StatementError::select_fail(new_value.to_string(), old_value.to_string(), span))?;
*old_value = selected_value;
@ -192,9 +201,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
variable_name,
range_or_expression,
new_value,
span,
),
Assignee::CircuitField(_assignee, object_name) => {
self.mutute_circuit_field(cs, indicator, variable_name, object_name, new_value)
self.mutute_circuit_field(cs, indicator, variable_name, object_name, new_value, span)
}
}
}
@ -225,6 +235,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
declare: Declare,
variable: Variable,
expression: Expression,
_span: Span,
) -> Result<(), StatementError> {
let mut expected_types = vec![];
if let Some(ref _type) = variable._type {
@ -252,6 +263,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
function_scope: String,
variables: Vec<Variable>,
function: Expression,
span: Span,
) -> Result<(), StatementError> {
let mut expected_types = vec![];
for variable in variables.iter() {
@ -273,9 +285,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
};
if variables.len() != return_values.len() {
return Err(StatementError::InvalidNumberOfDefinitions(
return Err(StatementError::invalid_number_of_definitions(
variables.len(),
return_values.len(),
span,
));
}
@ -292,12 +305,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
function_scope: String,
expressions: Vec<Expression>,
return_types: Vec<Type>,
span: Span,
) -> Result<ConstrainedValue<F, G>, StatementError> {
// Make sure we return the correct number of values
if return_types.len() != expressions.len() {
return Err(StatementError::InvalidNumberOfReturns(
return Err(StatementError::invalid_number_of_returns(
return_types.len(),
expressions.len(),
span,
));
}
@ -358,6 +373,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
indicator: Option<Boolean>,
statement: ConditionalStatement,
return_types: Vec<Type>,
span: Span,
) -> Result<Option<ConstrainedValue<F, G>>, StatementError> {
let statement_string = statement.to_string();
let outer_indicator = indicator.unwrap_or(Boolean::Constant(true));
@ -371,7 +387,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
statement.condition.clone(),
)? {
ConstrainedValue::Boolean(resolved) => resolved,
value => return Err(StatementError::IfElseConditional(value.to_string())),
value => return Err(StatementError::conditional_boolean(value.to_string(), span)),
};
// Determine nested branch selection
@ -407,6 +423,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Some(branch_2_indicator),
*nested,
return_types,
span,
),
ConditionalNestedOrEndStatement::End(statements) => self.evaluate_branch(
cs,
@ -432,6 +449,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
stop: Integer,
statements: Vec<Statement>,
return_types: Vec<Type>,
_span: Span,
) -> Result<Option<ConstrainedValue<F, G>>, StatementError> {
let mut res = None;
@ -469,11 +487,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
indicator: Option<Boolean>,
left: &ConstrainedValue<F, G>,
right: &ConstrainedValue<F, G>,
span: Span,
) -> Result<(), StatementError> {
let condition = indicator.unwrap_or(Boolean::Constant(true));
let result = left.conditional_enforce_equal(cs, right, &condition);
Ok(result.map_err(|_| StatementError::AssertionFailed(left.to_string(), right.to_string()))?)
Ok(result.map_err(|_| StatementError::assertion_failed(left.to_string(), right.to_string(), span))?)
}
pub(crate) fn enforce_statement<CS: ConstraintSystem<F>>(
@ -487,19 +506,26 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
) -> Result<Option<ConstrainedValue<F, G>>, StatementError> {
let mut res = None;
match statement {
Statement::Return(expressions) => {
res = Some(self.enforce_return_statement(cs, file_scope, function_scope, expressions, return_types)?);
Statement::Return(expressions, span) => {
res = Some(self.enforce_return_statement(
cs,
file_scope,
function_scope,
expressions,
return_types,
span,
)?);
}
Statement::Definition(declare, variable, expression) => {
self.enforce_definition_statement(cs, file_scope, function_scope, declare, variable, expression)?;
Statement::Definition(declare, variable, expression, span) => {
self.enforce_definition_statement(cs, file_scope, function_scope, declare, variable, expression, span)?;
}
Statement::Assign(variable, expression) => {
self.enforce_assign_statement(cs, file_scope, function_scope, indicator, variable, expression)?;
Statement::Assign(variable, expression, span) => {
self.enforce_assign_statement(cs, file_scope, function_scope, indicator, variable, expression, span)?;
}
Statement::MultipleAssign(variables, function) => {
self.enforce_multiple_definition_statement(cs, file_scope, function_scope, variables, function)?;
Statement::MultipleAssign(variables, function, span) => {
self.enforce_multiple_definition_statement(cs, file_scope, function_scope, variables, function, span)?;
}
Statement::Conditional(statement) => {
Statement::Conditional(statement, span) => {
if let Some(early_return) = self.enforce_conditional_statement(
cs,
file_scope,
@ -507,11 +533,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
indicator,
statement,
return_types,
span,
)? {
res = Some(early_return)
}
}
Statement::For(index, start, stop, statements) => {
Statement::For(index, start, stop, statements, span) => {
if let Some(early_return) = self.enforce_for_statement(
cs,
file_scope,
@ -522,24 +549,25 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
stop,
statements,
return_types,
span,
)? {
res = Some(early_return)
}
}
Statement::AssertEq(left, right) => {
Statement::AssertEq(left, right, span) => {
let (resolved_left, resolved_right) =
self.enforce_binary_expression(cs, file_scope, function_scope, &vec![], left, right)?;
self.enforce_assert_eq_statement(cs, indicator, &resolved_left, &resolved_right)?;
self.enforce_assert_eq_statement(cs, indicator, &resolved_left, &resolved_right, span)?;
}
Statement::Expression(expression) => {
Statement::Expression(expression, span) => {
match self.enforce_expression(cs, file_scope, function_scope, &vec![], expression.clone())? {
ConstrainedValue::Return(values) => {
if !values.is_empty() {
return Err(StatementError::Unassigned(expression.to_string()));
return Err(StatementError::unassigned(expression.to_string(), span));
}
}
_ => return Err(StatementError::Unassigned(expression.to_string())),
_ => return Err(StatementError::unassigned(expression.to_string(), span)),
}
}
};

View File

@ -1,4 +1,4 @@
use crate::errors::{BooleanError, Error, FieldError, FunctionError, GroupError, ValueError};
use crate::errors::{BooleanError, Error as FormattedError, FieldError, FunctionError, GroupError, ValueError};
use leo_types::{Identifier, IntegerError, Span};
use snarkos_errors::gadgets::SynthesisError;
@ -6,8 +6,12 @@ use std::num::ParseIntError;
#[derive(Debug, Error)]
pub enum ExpressionError {
// Identifiers
#[error("Identifier \"{}\" not found", _0)]
UndefinedIdentifier(String),
#[error("{}", _0)]
Error(#[from] Error),
Error(#[from] FormattedError),
// Types
#[error("{}", _0)]
@ -89,7 +93,7 @@ pub enum ExpressionError {
impl ExpressionError {
fn new_from_span(message: String, span: Span) -> Self {
ExpressionError::Error(Error::new_from_span(message, span))
ExpressionError::Error(FormattedError::new_from_span(message, span))
}
pub fn undefined_identifier(identifier: Identifier) -> Self {

View File

@ -1,63 +1,115 @@
use crate::errors::{BooleanError, ExpressionError, ValueError};
use crate::errors::{BooleanError, Error as FormattedError, ExpressionError, ValueError};
use leo_types::Span;
use snarkos_errors::gadgets::SynthesisError;
#[derive(Debug, Error)]
pub enum StatementError {
#[error("{}", _0)]
Error(#[from] FormattedError),
#[error("{}", _0)]
BooleanError(#[from] BooleanError),
#[error("{}", _0)]
ExpressionError(#[from] ExpressionError),
#[error("Attempted to assign to unknown variable {}", _0)]
UndefinedVariable(String),
// Arrays
#[error("Cannot assign single index to array of values")]
ArrayAssignIndex,
#[error("Cannot assign range of array values to single value")]
ArrayAssignRange,
// Circuits
#[error("Cannot mutate circuit function, {}", _0)]
ImmutableCircuitFunction(String),
#[error("Attempted to assign to unknown circuit {}", _0)]
UndefinedCircuit(String),
#[error("Attempted to assign to unknown circuit {}", _0)]
UndefinedCircuitObject(String),
// Statements
#[error("Cannot assert equality between {} == {}", _0, _1)]
AssertEq(String, String),
#[error("Assertion {:?} == {:?} failed", _0, _1)]
AssertionFailed(String, String),
#[error("If, else statements.conditional must resolve to a boolean, got {}", _0)]
IfElseConditional(String),
#[error("Cannot assign to immutable variable {}", _0)]
ImmutableAssign(String),
#[error("Multiple definition statement expected {} return values, got {}", _0, _1)]
InvalidNumberOfDefinitions(usize, usize),
#[error("Function return statement expected {} return values, got {}", _0, _1)]
InvalidNumberOfReturns(usize, usize),
#[error("Conditional select gadget failed to select between {} or {}", _0, _1)]
SelectFail(String, String),
#[error("{}", _0)]
SynthesisError(#[from] SynthesisError),
#[error("Expected assignment of return values for expression {}", _0)]
Unassigned(String),
#[error("{}", _0)]
ValueError(#[from] ValueError),
}
impl StatementError {
fn new_from_span(message: String, span: Span) -> Self {
StatementError::Error(FormattedError::new_from_span(message, span))
}
pub fn array_assign_index(span: Span) -> Self {
let message = format!("Cannot assign single index to array of values");
Self::new_from_span(message, span)
}
pub fn array_assign_range(span: Span) -> Self {
let message = format!("Cannot assign range of array values to single value");
Self::new_from_span(message, span)
}
pub fn assertion_failed(left: String, right: String, span: Span) -> Self {
let message = format!("Assertion {} == {} failed", left, right);
Self::new_from_span(message, span)
}
pub fn conditional_boolean(actual: String, span: Span) -> Self {
let message = format!("If, else conditional must resolve to a boolean, got {}", actual);
Self::new_from_span(message, span)
}
pub fn invalid_number_of_definitions(expected: usize, actual: usize, span: Span) -> Self {
let message = format!(
"Multiple definition statement expected {} return values, got {}",
expected, actual
);
Self::new_from_span(message, span)
}
pub fn invalid_number_of_returns(expected: usize, actual: usize, span: Span) -> Self {
let message = format!(
"Function return statement expected {} return values, got {}",
expected, actual
);
Self::new_from_span(message, span)
}
pub fn immutable_assign(name: String, span: Span) -> Self {
let message = format!("Cannot assign to immutable variable {}", name);
Self::new_from_span(message, span)
}
pub fn immutable_circuit_function(name: String, span: Span) -> Self {
let message = format!("Cannot mutate circuit function, {}", name);
Self::new_from_span(message, span)
}
pub fn select_fail(first: String, second: String, span: Span) -> Self {
let message = format!(
"Conditional select gadget failed to select between {} or {}",
first, second
);
Self::new_from_span(message, span)
}
pub fn unassigned(name: String, span: Span) -> Self {
let message = format!("Expected assignment of return values for expression {}", name);
Self::new_from_span(message, span)
}
pub fn undefined_variable(name: String, span: Span) -> Self {
let message = format!("Attempted to assign to unknown variable {}", name);
Self::new_from_span(message, span)
}
pub fn undefined_circuit(name: String, span: Span) -> Self {
let message = format!("Attempted to assign to unknown circuit {}", name);
Self::new_from_span(message, span)
}
pub fn undefined_circuit_object(name: String, span: Span) -> Self {
let message = format!("Attempted to assign to unknown circuit object {}", name);
Self::new_from_span(message, span)
}
}

View File

@ -61,9 +61,11 @@ impl Error {
}
}
fn underline(start: usize, mut end: usize) -> String {
fn underline(mut start: usize, mut end: usize) -> String {
if start > end {
panic!("underline start column is greater than end column")
let tmp = start;
start = end;
end = tmp;
}
let mut underline = String::new();

View File

@ -7,6 +7,20 @@ use leo_inputs::syntax::SyntaxError;
use crate::input_value_u32_one;
use snarkos_models::gadgets::utilities::boolean::Boolean;
// use leo_types::InputValue;
// use pest::Span;
// use leo_inputs::types::BooleanType;
// use leo_inputs::values::BooleanValue;
//
// pub fn input_value_bool(bool: bool) -> InputValue<'static> {
// let input = bool.to_string();
// let span = Span::new(&input, 0, input.len()).unwrap();
//
// InputValue::Boolean(BooleanValue {
// value: input,
// span,
// })
// }
pub fn output_expected_boolean(program: EdwardsTestCompiler, boolean: bool) {
let output = get_output(program);

View File

@ -8,7 +8,7 @@ pub mod boolean;
pub mod inputs;
// pub mod integers;
// pub mod mutability;
// pub mod statements;
pub mod statements;
pub mod syntax;
use leo_compiler::{
@ -45,7 +45,7 @@ pub(crate) fn get_error(program: EdwardsTestCompiler) -> CompilerError {
pub(crate) fn fail_enforce(program: EdwardsTestCompiler) {
match get_error(program) {
CompilerError::FunctionError(FunctionError::StatementError(StatementError::AssertionFailed(_, _))) => {}
CompilerError::FunctionError(FunctionError::StatementError(StatementError::Error(_))) => {}
error => panic!("Expected evaluate error, got {}", error),
}
}

View File

@ -1,60 +1,67 @@
use crate::{
integers::u32::{output_one, output_zero},
parse_program,
};
use crate::{get_error, parse_program};
use leo_types::InputValue;
use snarkos_curves::edwards_bls12::Fq;
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
pub mod conditional;
// pub mod conditional;
// Ternary if {bool}? {expression} : {expression};
#[test]
fn test_ternary_basic() {
let bytes = include_bytes!("ternary_basic.leo");
let mut program_input_true = parse_program(bytes).unwrap();
let mut program_input_false = program_input_true.clone();
program_input_true.set_inputs(vec![Some(InputValue::Boolean(true))]);
output_one(program_input_true);
program_input_false.set_inputs(vec![Some(InputValue::Boolean(false))]);
output_zero(program_input_false);
}
// Iteration for i {start}..{stop} { statements }
// #[test]
// fn test_ternary_basic() {
// let bytes = include_bytes!("ternary_basic.leo");
// let mut program_input_true = parse_program(bytes).unwrap();
//
// let mut program_input_false = program_input_true.clone();
//
// program_input_true.set_inputs(vec![Some(input_value_bool(true))]);
// output_one(program_input_true);
//
// program_input_false.set_inputs(vec![Some(input_value_bool(false))]);
// output_zero(program_input_false);
// }
//
// // Iteration for i {start}..{stop} { statements }
//
// #[test]
// fn test_iteration_basic() {
// let bytes = include_bytes!("iteration_basic.leo");
// let program = parse_program(bytes).unwrap();
//
// output_one(program);
// }
//
// // Assertion
//
// #[test]
// fn test_assertion_basic() {
// let bytes = include_bytes!("assertion_basic.leo");
// let program = parse_program(bytes).unwrap();
//
// let mut program_input_true = program.clone();
// let mut cs_satisfied = TestConstraintSystem::<Fq>::new();
//
// program_input_true.set_inputs(vec![Some(input_value_bool(true))]);
// let _output = program_input_true.compile_constraints(&mut cs_satisfied).unwrap();
//
// assert!(cs_satisfied.is_satisfied());
//
// let mut program_input_false = program.clone();
// let mut cs_unsatisfied = TestConstraintSystem::<Fq>::new();
//
// program_input_false.set_inputs(vec![Some(input_value_bool(false))]);
// let _output = program_input_false.compile_constraints(&mut cs_unsatisfied).unwrap();
//
// assert!(!cs_unsatisfied.is_satisfied());
// }
#[test]
fn test_iteration_basic() {
let bytes = include_bytes!("iteration_basic.leo");
fn test_num_returns_fail() {
let bytes = include_bytes!("num_returns_fail.leo");
let program = parse_program(bytes).unwrap();
output_one(program);
}
// Assertion
#[test]
fn test_assertion_basic() {
let bytes = include_bytes!("assertion_basic.leo");
let program = parse_program(bytes).unwrap();
let mut program_input_true = program.clone();
let mut cs_satisfied = TestConstraintSystem::<Fq>::new();
program_input_true.set_inputs(vec![Some(InputValue::Boolean(true))]);
let _output = program_input_true.compile_constraints(&mut cs_satisfied).unwrap();
assert!(cs_satisfied.is_satisfied());
let mut program_input_false = program.clone();
let mut cs_unsatisfied = TestConstraintSystem::<Fq>::new();
program_input_false.set_inputs(vec![Some(InputValue::Boolean(false))]);
let _output = program_input_false.compile_constraints(&mut cs_unsatisfied).unwrap();
assert!(!cs_unsatisfied.is_satisfied());
let error = get_error(program);
println!("{}", error);
}

View File

@ -0,0 +1,3 @@
function main() -> (bool, bool) {
return true
}

View File

@ -74,7 +74,7 @@ impl CLI for BuildCommand {
ct: vec![],
};
let temporary_program = program.clone();
let output = temporary_program.compile_constraints(&mut cs).unwrap();
let output = temporary_program.compile_constraints(&mut cs)?;
log::debug!("Compiled constraints - {:#?}", output);
}

View File

@ -53,7 +53,8 @@ pub enum CLIError {
impl From<leo_compiler::errors::CompilerError> for CLIError {
fn from(error: leo_compiler::errors::CompilerError) -> Self {
CLIError::Crate("leo_compiler", format!("{}", error))
log::error!("{}", error);
CLIError::Crate("leo_compiler", "Program failed due to previous error".into())
}
}

View File

@ -1,4 +1,4 @@
use crate::{Assignee, ConditionalStatement, Declare, Expression, Identifier, Integer, Variable};
use crate::{Assignee, ConditionalStatement, Declare, Expression, Identifier, Integer, Span, Variable};
use leo_ast::{
operations::AssignOperation,
statements::{
@ -18,14 +18,14 @@ use std::fmt;
/// Program statement that defines some action (or expression) to be carried out.
#[derive(Clone, PartialEq, Eq)]
pub enum Statement {
Return(Vec<Expression>),
Definition(Declare, Variable, Expression),
Assign(Assignee, Expression),
MultipleAssign(Vec<Variable>, Expression),
Conditional(ConditionalStatement),
For(Identifier, Integer, Integer, Vec<Statement>),
AssertEq(Expression, Expression),
Expression(Expression),
Return(Vec<Expression>, Span),
Definition(Declare, Variable, Expression, Span),
Assign(Assignee, Expression, Span),
MultipleAssign(Vec<Variable>, Expression, Span),
Conditional(ConditionalStatement, Span),
For(Identifier, Integer, Integer, Vec<Statement>, Span),
AssertEq(Expression, Expression, Span),
Expression(Expression, Span),
}
impl<'ast> From<ReturnStatement<'ast>> for Statement {
@ -36,6 +36,7 @@ impl<'ast> From<ReturnStatement<'ast>> for Statement {
.into_iter()
.map(|expression| Expression::from(expression))
.collect(),
Span::from(statement.span),
)
}
}
@ -46,6 +47,7 @@ impl<'ast> From<DefinitionStatement<'ast>> for Statement {
Declare::from(statement.declare),
Variable::from(statement.variable),
Expression::from(statement.expression),
Span::from(statement.span),
)
}
}
@ -56,6 +58,7 @@ impl<'ast> From<AssignStatement<'ast>> for Statement {
AssignOperation::Assign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::from(statement.expression),
Span::from(statement.span),
),
operation_assign => {
// convert assignee into postfix expression
@ -65,22 +68,27 @@ impl<'ast> From<AssignStatement<'ast>> for Statement {
AssignOperation::AddAssign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::Add(Box::new(converted), Box::new(Expression::from(statement.expression))),
Span::from(statement.span),
),
AssignOperation::SubAssign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::Sub(Box::new(converted), Box::new(Expression::from(statement.expression))),
Span::from(statement.span),
),
AssignOperation::MulAssign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::Mul(Box::new(converted), Box::new(Expression::from(statement.expression))),
Span::from(statement.span),
),
AssignOperation::DivAssign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::Div(Box::new(converted), Box::new(Expression::from(statement.expression))),
Span::from(statement.span),
),
AssignOperation::PowAssign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::Pow(Box::new(converted), Box::new(Expression::from(statement.expression))),
Span::from(statement.span),
),
AssignOperation::Assign(ref _assign) => unimplemented!("cannot assign twice to assign statement"),
}
@ -103,6 +111,7 @@ impl<'ast> From<MultipleAssignmentStatement<'ast>> for Statement {
Box::new(Expression::from(statement.function_name)),
statement.arguments.into_iter().map(|e| Expression::from(e)).collect(),
),
Span::from(statement.span),
)
}
}
@ -129,6 +138,7 @@ impl<'ast> From<ForStatement<'ast>> for Statement {
.into_iter()
.map(|statement| Statement::from(statement))
.collect(),
Span::from(statement.span),
)
}
}
@ -136,16 +146,18 @@ impl<'ast> From<ForStatement<'ast>> for Statement {
impl<'ast> From<AssertStatement<'ast>> for Statement {
fn from(statement: AssertStatement<'ast>) -> Self {
match statement {
AssertStatement::AssertEq(assert_eq) => {
Statement::AssertEq(Expression::from(assert_eq.left), Expression::from(assert_eq.right))
}
AssertStatement::AssertEq(assert_eq) => Statement::AssertEq(
Expression::from(assert_eq.left),
Expression::from(assert_eq.right),
Span::from(assert_eq.span),
),
}
}
}
impl<'ast> From<ExpressionStatement<'ast>> for Statement {
fn from(statement: ExpressionStatement<'ast>) -> Self {
Statement::Expression(Expression::from(statement.expression))
Statement::Expression(Expression::from(statement.expression), Span::from(statement.span))
}
}
@ -156,7 +168,10 @@ impl<'ast> From<AstStatement<'ast>> for Statement {
AstStatement::Definition(statement) => Statement::from(statement),
AstStatement::Assign(statement) => Statement::from(statement),
AstStatement::MultipleAssignment(statement) => Statement::from(statement),
AstStatement::Conditional(statement) => Statement::Conditional(ConditionalStatement::from(statement)),
AstStatement::Conditional(statement) => {
let span = Span::from(statement.span.clone());
Statement::Conditional(ConditionalStatement::from(statement), span)
}
AstStatement::Iteration(statement) => Statement::from(statement),
AstStatement::Assert(statement) => Statement::from(statement),
AstStatement::Expression(statement) => Statement::from(statement),
@ -167,7 +182,7 @@ impl<'ast> From<AstStatement<'ast>> for Statement {
impl fmt::Display for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Statement::Return(ref statements) => {
Statement::Return(ref statements, ref _span) => {
write!(f, "return (")?;
for (i, value) in statements.iter().enumerate() {
write!(f, "{}", value)?;
@ -177,11 +192,11 @@ impl fmt::Display for Statement {
}
write!(f, ")\n")
}
Statement::Definition(ref declare, ref variable, ref expression) => {
Statement::Definition(ref declare, ref variable, ref expression, ref _span) => {
write!(f, "{} {} = {};", declare, variable, expression)
}
Statement::Assign(ref variable, ref statement) => write!(f, "{} = {};", variable, statement),
Statement::MultipleAssign(ref assignees, ref function) => {
Statement::Assign(ref variable, ref statement, ref _span) => write!(f, "{} = {};", variable, statement),
Statement::MultipleAssign(ref assignees, ref function, ref _span) => {
write!(f, "let (")?;
for (i, id) in assignees.iter().enumerate() {
write!(f, "{}", id)?;
@ -191,16 +206,16 @@ impl fmt::Display for Statement {
}
write!(f, ") = {};", function)
}
Statement::Conditional(ref statement) => write!(f, "{}", statement),
Statement::For(ref var, ref start, ref stop, ref list) => {
Statement::Conditional(ref statement, ref _span) => write!(f, "{}", statement),
Statement::For(ref var, ref start, ref stop, ref list, ref _span) => {
write!(f, "for {} in {}..{} {{\n", var, start, stop)?;
for l in list {
write!(f, "\t\t{}\n", l)?;
}
write!(f, "\t}}")
}
Statement::AssertEq(ref left, ref right) => write!(f, "assert_eq({}, {});", left, right),
Statement::Expression(ref expression) => write!(f, "{};", expression),
Statement::AssertEq(ref left, ref right, ref _span) => write!(f, "assert_eq({}, {});", left, right),
Statement::Expression(ref expression, ref _span) => write!(f, "{};", expression),
}
}
}