mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-24 07:48:04 +03:00
convert statements to span with error
This commit is contained in:
parent
6922d5dd73
commit
3d1fe9cc4b
@ -15,6 +15,7 @@ use leo_types::{
|
|||||||
Identifier,
|
Identifier,
|
||||||
Integer,
|
Integer,
|
||||||
RangeOrExpression,
|
RangeOrExpression,
|
||||||
|
Span,
|
||||||
Statement,
|
Statement,
|
||||||
Type,
|
Type,
|
||||||
Variable,
|
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
|
// Check that assignee exists and is mutable
|
||||||
Ok(match self.get_mut(&name) {
|
Ok(match self.get_mut(&name) {
|
||||||
Some(value) => match value {
|
Some(value) => match value {
|
||||||
ConstrainedValue::Mutable(mutable_value) => mutable_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,
|
name: String,
|
||||||
range_or_expression: RangeOrExpression,
|
range_or_expression: RangeOrExpression,
|
||||||
mut new_value: ConstrainedValue<F, G>,
|
mut new_value: ConstrainedValue<F, G>,
|
||||||
|
span: Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
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)?;
|
let index = self.enforce_index(cs, file_scope.clone(), function_scope.clone(), index)?;
|
||||||
|
|
||||||
// Modify the single value of the array in place
|
// 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) => {
|
ConstrainedValue::Array(old) => {
|
||||||
new_value.resolve_type(&vec![old[index].to_type()])?;
|
new_value.resolve_type(&vec![old[index].to_type()])?;
|
||||||
|
|
||||||
let selected_value =
|
let selected_value =
|
||||||
ConstrainedValue::conditionally_select(cs, &condition, &new_value, &old[index]).map_err(
|
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;
|
old[index] = selected_value;
|
||||||
}
|
}
|
||||||
_ => return Err(StatementError::ArrayAssignIndex),
|
_ => return Err(StatementError::array_assign_index(span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RangeOrExpression::Range(from, to) => {
|
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
|
// 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) {
|
let new_array = match (old_array.clone(), new_value) {
|
||||||
(ConstrainedValue::Array(mut mutable), ConstrainedValue::Array(new)) => {
|
(ConstrainedValue::Array(mut mutable), ConstrainedValue::Array(new)) => {
|
||||||
let to_index = to_index_option.unwrap_or(mutable.len());
|
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());
|
mutable.splice(from_index..to_index, new.iter().cloned());
|
||||||
ConstrainedValue::Array(mutable)
|
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)
|
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;
|
*old_array = selected_array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,10 +123,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
circuit_name: String,
|
circuit_name: String,
|
||||||
object_name: Identifier,
|
object_name: Identifier,
|
||||||
mut new_value: ConstrainedValue<F, G>,
|
mut new_value: ConstrainedValue<F, G>,
|
||||||
|
span: Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
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) => {
|
ConstrainedValue::CircuitExpression(_variable, members) => {
|
||||||
// Modify the circuit field in place
|
// Modify the circuit field in place
|
||||||
let matched_field = members.into_iter().find(|object| object.0 == object_name);
|
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 {
|
match matched_field {
|
||||||
Some(object) => match &object.1 {
|
Some(object) => match &object.1 {
|
||||||
ConstrainedValue::Function(_circuit_identifier, function) => {
|
ConstrainedValue::Function(_circuit_identifier, function) => {
|
||||||
return Err(StatementError::ImmutableCircuitFunction(
|
return Err(StatementError::immutable_circuit_function(
|
||||||
function.function_name.to_string(),
|
function.function_name.to_string(),
|
||||||
|
span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ConstrainedValue::Static(_value) => {
|
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()])?;
|
new_value.resolve_type(&vec![object.1.to_type()])?;
|
||||||
|
|
||||||
let selected_value = ConstrainedValue::conditionally_select(
|
let selected_value =
|
||||||
cs, &condition, &new_value, &object.1,
|
ConstrainedValue::conditionally_select(cs, &condition, &new_value, &object.1).map_err(
|
||||||
)
|
|_| StatementError::select_fail(new_value.to_string(), object.1.to_string(), span),
|
||||||
.map_err(|_| StatementError::SelectFail(new_value.to_string(), object.1.to_string()))?;
|
)?;
|
||||||
|
|
||||||
object.1 = selected_value.to_owned();
|
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(())
|
Ok(())
|
||||||
@ -163,6 +171,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
assignee: Assignee,
|
assignee: Assignee,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
|
span: Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
// Get the name of the variable we are assigning to
|
// Get the name of the variable we are assigning to
|
||||||
let variable_name = self.resolve_assignee(function_scope.clone(), assignee.clone());
|
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 {
|
match assignee {
|
||||||
Assignee::Identifier(_identifier) => {
|
Assignee::Identifier(_identifier) => {
|
||||||
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
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()])?;
|
new_value.resolve_type(&vec![old_value.to_type()])?;
|
||||||
let selected_value = ConstrainedValue::conditionally_select(cs, &condition, &new_value, old_value)
|
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;
|
*old_value = selected_value;
|
||||||
|
|
||||||
@ -192,9 +201,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
variable_name,
|
variable_name,
|
||||||
range_or_expression,
|
range_or_expression,
|
||||||
new_value,
|
new_value,
|
||||||
|
span,
|
||||||
),
|
),
|
||||||
Assignee::CircuitField(_assignee, object_name) => {
|
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,
|
declare: Declare,
|
||||||
variable: Variable,
|
variable: Variable,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
|
_span: Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
let mut expected_types = vec![];
|
let mut expected_types = vec![];
|
||||||
if let Some(ref _type) = variable._type {
|
if let Some(ref _type) = variable._type {
|
||||||
@ -252,6 +263,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
function_scope: String,
|
function_scope: String,
|
||||||
variables: Vec<Variable>,
|
variables: Vec<Variable>,
|
||||||
function: Expression,
|
function: Expression,
|
||||||
|
span: Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
let mut expected_types = vec![];
|
let mut expected_types = vec![];
|
||||||
for variable in variables.iter() {
|
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() {
|
if variables.len() != return_values.len() {
|
||||||
return Err(StatementError::InvalidNumberOfDefinitions(
|
return Err(StatementError::invalid_number_of_definitions(
|
||||||
variables.len(),
|
variables.len(),
|
||||||
return_values.len(),
|
return_values.len(),
|
||||||
|
span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,12 +305,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
function_scope: String,
|
function_scope: String,
|
||||||
expressions: Vec<Expression>,
|
expressions: Vec<Expression>,
|
||||||
return_types: Vec<Type>,
|
return_types: Vec<Type>,
|
||||||
|
span: Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, StatementError> {
|
) -> Result<ConstrainedValue<F, G>, StatementError> {
|
||||||
// Make sure we return the correct number of values
|
// Make sure we return the correct number of values
|
||||||
if return_types.len() != expressions.len() {
|
if return_types.len() != expressions.len() {
|
||||||
return Err(StatementError::InvalidNumberOfReturns(
|
return Err(StatementError::invalid_number_of_returns(
|
||||||
return_types.len(),
|
return_types.len(),
|
||||||
expressions.len(),
|
expressions.len(),
|
||||||
|
span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,6 +373,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
statement: ConditionalStatement,
|
statement: ConditionalStatement,
|
||||||
return_types: Vec<Type>,
|
return_types: Vec<Type>,
|
||||||
|
span: Span,
|
||||||
) -> Result<Option<ConstrainedValue<F, G>>, StatementError> {
|
) -> Result<Option<ConstrainedValue<F, G>>, StatementError> {
|
||||||
let statement_string = statement.to_string();
|
let statement_string = statement.to_string();
|
||||||
let outer_indicator = indicator.unwrap_or(Boolean::Constant(true));
|
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(),
|
statement.condition.clone(),
|
||||||
)? {
|
)? {
|
||||||
ConstrainedValue::Boolean(resolved) => resolved,
|
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
|
// Determine nested branch selection
|
||||||
@ -407,6 +423,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
Some(branch_2_indicator),
|
Some(branch_2_indicator),
|
||||||
*nested,
|
*nested,
|
||||||
return_types,
|
return_types,
|
||||||
|
span,
|
||||||
),
|
),
|
||||||
ConditionalNestedOrEndStatement::End(statements) => self.evaluate_branch(
|
ConditionalNestedOrEndStatement::End(statements) => self.evaluate_branch(
|
||||||
cs,
|
cs,
|
||||||
@ -432,6 +449,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
stop: Integer,
|
stop: Integer,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
return_types: Vec<Type>,
|
return_types: Vec<Type>,
|
||||||
|
_span: Span,
|
||||||
) -> Result<Option<ConstrainedValue<F, G>>, StatementError> {
|
) -> Result<Option<ConstrainedValue<F, G>>, StatementError> {
|
||||||
let mut res = None;
|
let mut res = None;
|
||||||
|
|
||||||
@ -469,11 +487,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
left: &ConstrainedValue<F, G>,
|
left: &ConstrainedValue<F, G>,
|
||||||
right: &ConstrainedValue<F, G>,
|
right: &ConstrainedValue<F, G>,
|
||||||
|
span: Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
||||||
let result = left.conditional_enforce_equal(cs, right, &condition);
|
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>>(
|
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> {
|
) -> Result<Option<ConstrainedValue<F, G>>, StatementError> {
|
||||||
let mut res = None;
|
let mut res = None;
|
||||||
match statement {
|
match statement {
|
||||||
Statement::Return(expressions) => {
|
Statement::Return(expressions, span) => {
|
||||||
res = Some(self.enforce_return_statement(cs, file_scope, function_scope, expressions, return_types)?);
|
res = Some(self.enforce_return_statement(
|
||||||
|
cs,
|
||||||
|
file_scope,
|
||||||
|
function_scope,
|
||||||
|
expressions,
|
||||||
|
return_types,
|
||||||
|
span,
|
||||||
|
)?);
|
||||||
}
|
}
|
||||||
Statement::Definition(declare, variable, expression) => {
|
Statement::Definition(declare, variable, expression, span) => {
|
||||||
self.enforce_definition_statement(cs, file_scope, function_scope, declare, variable, expression)?;
|
self.enforce_definition_statement(cs, file_scope, function_scope, declare, variable, expression, span)?;
|
||||||
}
|
}
|
||||||
Statement::Assign(variable, expression) => {
|
Statement::Assign(variable, expression, span) => {
|
||||||
self.enforce_assign_statement(cs, file_scope, function_scope, indicator, variable, expression)?;
|
self.enforce_assign_statement(cs, file_scope, function_scope, indicator, variable, expression, span)?;
|
||||||
}
|
}
|
||||||
Statement::MultipleAssign(variables, function) => {
|
Statement::MultipleAssign(variables, function, span) => {
|
||||||
self.enforce_multiple_definition_statement(cs, file_scope, function_scope, variables, function)?;
|
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(
|
if let Some(early_return) = self.enforce_conditional_statement(
|
||||||
cs,
|
cs,
|
||||||
file_scope,
|
file_scope,
|
||||||
@ -507,11 +533,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
indicator,
|
indicator,
|
||||||
statement,
|
statement,
|
||||||
return_types,
|
return_types,
|
||||||
|
span,
|
||||||
)? {
|
)? {
|
||||||
res = Some(early_return)
|
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(
|
if let Some(early_return) = self.enforce_for_statement(
|
||||||
cs,
|
cs,
|
||||||
file_scope,
|
file_scope,
|
||||||
@ -522,24 +549,25 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
stop,
|
stop,
|
||||||
statements,
|
statements,
|
||||||
return_types,
|
return_types,
|
||||||
|
span,
|
||||||
)? {
|
)? {
|
||||||
res = Some(early_return)
|
res = Some(early_return)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Statement::AssertEq(left, right) => {
|
Statement::AssertEq(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) =
|
let (resolved_left, resolved_right) =
|
||||||
self.enforce_binary_expression(cs, file_scope, function_scope, &vec![], left, 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())? {
|
match self.enforce_expression(cs, file_scope, function_scope, &vec![], expression.clone())? {
|
||||||
ConstrainedValue::Return(values) => {
|
ConstrainedValue::Return(values) => {
|
||||||
if !values.is_empty() {
|
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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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 leo_types::{Identifier, IntegerError, Span};
|
||||||
|
|
||||||
use snarkos_errors::gadgets::SynthesisError;
|
use snarkos_errors::gadgets::SynthesisError;
|
||||||
@ -6,8 +6,12 @@ use std::num::ParseIntError;
|
|||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ExpressionError {
|
pub enum ExpressionError {
|
||||||
|
// Identifiers
|
||||||
|
#[error("Identifier \"{}\" not found", _0)]
|
||||||
|
UndefinedIdentifier(String),
|
||||||
|
|
||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
Error(#[from] Error),
|
Error(#[from] FormattedError),
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
@ -89,7 +93,7 @@ pub enum ExpressionError {
|
|||||||
|
|
||||||
impl ExpressionError {
|
impl ExpressionError {
|
||||||
fn new_from_span(message: String, span: Span) -> Self {
|
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 {
|
pub fn undefined_identifier(identifier: Identifier) -> Self {
|
||||||
|
@ -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;
|
use snarkos_errors::gadgets::SynthesisError;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum StatementError {
|
pub enum StatementError {
|
||||||
|
#[error("{}", _0)]
|
||||||
|
Error(#[from] FormattedError),
|
||||||
|
|
||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
BooleanError(#[from] BooleanError),
|
BooleanError(#[from] BooleanError),
|
||||||
|
|
||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
ExpressionError(#[from] ExpressionError),
|
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)]
|
#[error("{}", _0)]
|
||||||
SynthesisError(#[from] SynthesisError),
|
SynthesisError(#[from] SynthesisError),
|
||||||
|
|
||||||
#[error("Expected assignment of return values for expression {}", _0)]
|
|
||||||
Unassigned(String),
|
|
||||||
|
|
||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
ValueError(#[from] ValueError),
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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 {
|
if start > end {
|
||||||
panic!("underline start column is greater than end column")
|
let tmp = start;
|
||||||
|
start = end;
|
||||||
|
end = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut underline = String::new();
|
let mut underline = String::new();
|
||||||
|
@ -7,6 +7,20 @@ use leo_inputs::syntax::SyntaxError;
|
|||||||
|
|
||||||
use crate::input_value_u32_one;
|
use crate::input_value_u32_one;
|
||||||
use snarkos_models::gadgets::utilities::boolean::Boolean;
|
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) {
|
pub fn output_expected_boolean(program: EdwardsTestCompiler, boolean: bool) {
|
||||||
let output = get_output(program);
|
let output = get_output(program);
|
||||||
|
@ -8,7 +8,7 @@ pub mod boolean;
|
|||||||
pub mod inputs;
|
pub mod inputs;
|
||||||
// pub mod integers;
|
// pub mod integers;
|
||||||
// pub mod mutability;
|
// pub mod mutability;
|
||||||
// pub mod statements;
|
pub mod statements;
|
||||||
pub mod syntax;
|
pub mod syntax;
|
||||||
|
|
||||||
use leo_compiler::{
|
use leo_compiler::{
|
||||||
@ -45,7 +45,7 @@ pub(crate) fn get_error(program: EdwardsTestCompiler) -> CompilerError {
|
|||||||
|
|
||||||
pub(crate) fn fail_enforce(program: EdwardsTestCompiler) {
|
pub(crate) fn fail_enforce(program: EdwardsTestCompiler) {
|
||||||
match get_error(program) {
|
match get_error(program) {
|
||||||
CompilerError::FunctionError(FunctionError::StatementError(StatementError::AssertionFailed(_, _))) => {}
|
CompilerError::FunctionError(FunctionError::StatementError(StatementError::Error(_))) => {}
|
||||||
error => panic!("Expected evaluate error, got {}", error),
|
error => panic!("Expected evaluate error, got {}", error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,60 +1,67 @@
|
|||||||
use crate::{
|
use crate::{get_error, parse_program};
|
||||||
integers::u32::{output_one, output_zero},
|
|
||||||
parse_program,
|
|
||||||
};
|
|
||||||
use leo_types::InputValue;
|
use leo_types::InputValue;
|
||||||
|
|
||||||
use snarkos_curves::edwards_bls12::Fq;
|
use snarkos_curves::edwards_bls12::Fq;
|
||||||
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
|
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
|
||||||
|
|
||||||
pub mod conditional;
|
// pub mod conditional;
|
||||||
|
|
||||||
// Ternary if {bool}? {expression} : {expression};
|
// Ternary if {bool}? {expression} : {expression};
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn test_ternary_basic() {
|
// fn test_ternary_basic() {
|
||||||
let bytes = include_bytes!("ternary_basic.leo");
|
// let bytes = include_bytes!("ternary_basic.leo");
|
||||||
let mut program_input_true = parse_program(bytes).unwrap();
|
// let mut program_input_true = parse_program(bytes).unwrap();
|
||||||
|
//
|
||||||
let mut program_input_false = program_input_true.clone();
|
// let mut program_input_false = program_input_true.clone();
|
||||||
|
//
|
||||||
program_input_true.set_inputs(vec![Some(InputValue::Boolean(true))]);
|
// program_input_true.set_inputs(vec![Some(input_value_bool(true))]);
|
||||||
output_one(program_input_true);
|
// output_one(program_input_true);
|
||||||
|
//
|
||||||
program_input_false.set_inputs(vec![Some(InputValue::Boolean(false))]);
|
// program_input_false.set_inputs(vec![Some(input_value_bool(false))]);
|
||||||
output_zero(program_input_false);
|
// output_zero(program_input_false);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Iteration for i {start}..{stop} { statements }
|
// // 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]
|
#[test]
|
||||||
fn test_iteration_basic() {
|
fn test_num_returns_fail() {
|
||||||
let bytes = include_bytes!("iteration_basic.leo");
|
let bytes = include_bytes!("num_returns_fail.leo");
|
||||||
let program = parse_program(bytes).unwrap();
|
let program = parse_program(bytes).unwrap();
|
||||||
|
|
||||||
output_one(program);
|
let error = get_error(program);
|
||||||
}
|
|
||||||
|
println!("{}", error);
|
||||||
// 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());
|
|
||||||
}
|
}
|
||||||
|
3
compiler/tests/statements/num_returns_fail.leo
Normal file
3
compiler/tests/statements/num_returns_fail.leo
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
function main() -> (bool, bool) {
|
||||||
|
return true
|
||||||
|
}
|
@ -74,7 +74,7 @@ impl CLI for BuildCommand {
|
|||||||
ct: vec![],
|
ct: vec![],
|
||||||
};
|
};
|
||||||
let temporary_program = program.clone();
|
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);
|
log::debug!("Compiled constraints - {:#?}", output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,8 @@ pub enum CLIError {
|
|||||||
|
|
||||||
impl From<leo_compiler::errors::CompilerError> for CLIError {
|
impl From<leo_compiler::errors::CompilerError> for CLIError {
|
||||||
fn from(error: leo_compiler::errors::CompilerError) -> Self {
|
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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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::{
|
use leo_ast::{
|
||||||
operations::AssignOperation,
|
operations::AssignOperation,
|
||||||
statements::{
|
statements::{
|
||||||
@ -18,14 +18,14 @@ use std::fmt;
|
|||||||
/// Program statement that defines some action (or expression) to be carried out.
|
/// Program statement that defines some action (or expression) to be carried out.
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Return(Vec<Expression>),
|
Return(Vec<Expression>, Span),
|
||||||
Definition(Declare, Variable, Expression),
|
Definition(Declare, Variable, Expression, Span),
|
||||||
Assign(Assignee, Expression),
|
Assign(Assignee, Expression, Span),
|
||||||
MultipleAssign(Vec<Variable>, Expression),
|
MultipleAssign(Vec<Variable>, Expression, Span),
|
||||||
Conditional(ConditionalStatement),
|
Conditional(ConditionalStatement, Span),
|
||||||
For(Identifier, Integer, Integer, Vec<Statement>),
|
For(Identifier, Integer, Integer, Vec<Statement>, Span),
|
||||||
AssertEq(Expression, Expression),
|
AssertEq(Expression, Expression, Span),
|
||||||
Expression(Expression),
|
Expression(Expression, Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> From<ReturnStatement<'ast>> for Statement {
|
impl<'ast> From<ReturnStatement<'ast>> for Statement {
|
||||||
@ -36,6 +36,7 @@ impl<'ast> From<ReturnStatement<'ast>> for Statement {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|expression| Expression::from(expression))
|
.map(|expression| Expression::from(expression))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
Span::from(statement.span),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,6 +47,7 @@ impl<'ast> From<DefinitionStatement<'ast>> for Statement {
|
|||||||
Declare::from(statement.declare),
|
Declare::from(statement.declare),
|
||||||
Variable::from(statement.variable),
|
Variable::from(statement.variable),
|
||||||
Expression::from(statement.expression),
|
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(
|
AssignOperation::Assign(ref _assign) => Statement::Assign(
|
||||||
Assignee::from(statement.assignee),
|
Assignee::from(statement.assignee),
|
||||||
Expression::from(statement.expression),
|
Expression::from(statement.expression),
|
||||||
|
Span::from(statement.span),
|
||||||
),
|
),
|
||||||
operation_assign => {
|
operation_assign => {
|
||||||
// convert assignee into postfix expression
|
// convert assignee into postfix expression
|
||||||
@ -65,22 +68,27 @@ impl<'ast> From<AssignStatement<'ast>> for Statement {
|
|||||||
AssignOperation::AddAssign(ref _assign) => Statement::Assign(
|
AssignOperation::AddAssign(ref _assign) => Statement::Assign(
|
||||||
Assignee::from(statement.assignee),
|
Assignee::from(statement.assignee),
|
||||||
Expression::Add(Box::new(converted), Box::new(Expression::from(statement.expression))),
|
Expression::Add(Box::new(converted), Box::new(Expression::from(statement.expression))),
|
||||||
|
Span::from(statement.span),
|
||||||
),
|
),
|
||||||
AssignOperation::SubAssign(ref _assign) => Statement::Assign(
|
AssignOperation::SubAssign(ref _assign) => Statement::Assign(
|
||||||
Assignee::from(statement.assignee),
|
Assignee::from(statement.assignee),
|
||||||
Expression::Sub(Box::new(converted), Box::new(Expression::from(statement.expression))),
|
Expression::Sub(Box::new(converted), Box::new(Expression::from(statement.expression))),
|
||||||
|
Span::from(statement.span),
|
||||||
),
|
),
|
||||||
AssignOperation::MulAssign(ref _assign) => Statement::Assign(
|
AssignOperation::MulAssign(ref _assign) => Statement::Assign(
|
||||||
Assignee::from(statement.assignee),
|
Assignee::from(statement.assignee),
|
||||||
Expression::Mul(Box::new(converted), Box::new(Expression::from(statement.expression))),
|
Expression::Mul(Box::new(converted), Box::new(Expression::from(statement.expression))),
|
||||||
|
Span::from(statement.span),
|
||||||
),
|
),
|
||||||
AssignOperation::DivAssign(ref _assign) => Statement::Assign(
|
AssignOperation::DivAssign(ref _assign) => Statement::Assign(
|
||||||
Assignee::from(statement.assignee),
|
Assignee::from(statement.assignee),
|
||||||
Expression::Div(Box::new(converted), Box::new(Expression::from(statement.expression))),
|
Expression::Div(Box::new(converted), Box::new(Expression::from(statement.expression))),
|
||||||
|
Span::from(statement.span),
|
||||||
),
|
),
|
||||||
AssignOperation::PowAssign(ref _assign) => Statement::Assign(
|
AssignOperation::PowAssign(ref _assign) => Statement::Assign(
|
||||||
Assignee::from(statement.assignee),
|
Assignee::from(statement.assignee),
|
||||||
Expression::Pow(Box::new(converted), Box::new(Expression::from(statement.expression))),
|
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"),
|
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)),
|
Box::new(Expression::from(statement.function_name)),
|
||||||
statement.arguments.into_iter().map(|e| Expression::from(e)).collect(),
|
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()
|
.into_iter()
|
||||||
.map(|statement| Statement::from(statement))
|
.map(|statement| Statement::from(statement))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
Span::from(statement.span),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,16 +146,18 @@ impl<'ast> From<ForStatement<'ast>> for Statement {
|
|||||||
impl<'ast> From<AssertStatement<'ast>> for Statement {
|
impl<'ast> From<AssertStatement<'ast>> for Statement {
|
||||||
fn from(statement: AssertStatement<'ast>) -> Self {
|
fn from(statement: AssertStatement<'ast>) -> Self {
|
||||||
match statement {
|
match statement {
|
||||||
AssertStatement::AssertEq(assert_eq) => {
|
AssertStatement::AssertEq(assert_eq) => Statement::AssertEq(
|
||||||
Statement::AssertEq(Expression::from(assert_eq.left), Expression::from(assert_eq.right))
|
Expression::from(assert_eq.left),
|
||||||
}
|
Expression::from(assert_eq.right),
|
||||||
|
Span::from(assert_eq.span),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> From<ExpressionStatement<'ast>> for Statement {
|
impl<'ast> From<ExpressionStatement<'ast>> for Statement {
|
||||||
fn from(statement: ExpressionStatement<'ast>) -> Self {
|
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::Definition(statement) => Statement::from(statement),
|
||||||
AstStatement::Assign(statement) => Statement::from(statement),
|
AstStatement::Assign(statement) => Statement::from(statement),
|
||||||
AstStatement::MultipleAssignment(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::Iteration(statement) => Statement::from(statement),
|
||||||
AstStatement::Assert(statement) => Statement::from(statement),
|
AstStatement::Assert(statement) => Statement::from(statement),
|
||||||
AstStatement::Expression(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 {
|
impl fmt::Display for Statement {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Statement::Return(ref statements) => {
|
Statement::Return(ref statements, ref _span) => {
|
||||||
write!(f, "return (")?;
|
write!(f, "return (")?;
|
||||||
for (i, value) in statements.iter().enumerate() {
|
for (i, value) in statements.iter().enumerate() {
|
||||||
write!(f, "{}", value)?;
|
write!(f, "{}", value)?;
|
||||||
@ -177,11 +192,11 @@ impl fmt::Display for Statement {
|
|||||||
}
|
}
|
||||||
write!(f, ")\n")
|
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)
|
write!(f, "{} {} = {};", declare, variable, expression)
|
||||||
}
|
}
|
||||||
Statement::Assign(ref variable, ref statement) => write!(f, "{} = {};", variable, statement),
|
Statement::Assign(ref variable, ref statement, ref _span) => write!(f, "{} = {};", variable, statement),
|
||||||
Statement::MultipleAssign(ref assignees, ref function) => {
|
Statement::MultipleAssign(ref assignees, ref function, ref _span) => {
|
||||||
write!(f, "let (")?;
|
write!(f, "let (")?;
|
||||||
for (i, id) in assignees.iter().enumerate() {
|
for (i, id) in assignees.iter().enumerate() {
|
||||||
write!(f, "{}", id)?;
|
write!(f, "{}", id)?;
|
||||||
@ -191,16 +206,16 @@ impl fmt::Display for Statement {
|
|||||||
}
|
}
|
||||||
write!(f, ") = {};", function)
|
write!(f, ") = {};", function)
|
||||||
}
|
}
|
||||||
Statement::Conditional(ref statement) => write!(f, "{}", statement),
|
Statement::Conditional(ref statement, ref _span) => write!(f, "{}", statement),
|
||||||
Statement::For(ref var, ref start, ref stop, ref list) => {
|
Statement::For(ref var, ref start, ref stop, ref list, ref _span) => {
|
||||||
write!(f, "for {} in {}..{} {{\n", var, start, stop)?;
|
write!(f, "for {} in {}..{} {{\n", var, start, stop)?;
|
||||||
for l in list {
|
for l in list {
|
||||||
write!(f, "\t\t{}\n", l)?;
|
write!(f, "\t\t{}\n", l)?;
|
||||||
}
|
}
|
||||||
write!(f, "\t}}")
|
write!(f, "\t}}")
|
||||||
}
|
}
|
||||||
Statement::AssertEq(ref left, ref right) => write!(f, "assert_eq({}, {});", left, right),
|
Statement::AssertEq(ref left, ref right, ref _span) => write!(f, "assert_eq({}, {});", left, right),
|
||||||
Statement::Expression(ref expression) => write!(f, "{};", expression),
|
Statement::Expression(ref expression, ref _span) => write!(f, "{};", expression),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user