mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-28 09:02:58 +03:00
convert expressions to span with error
This commit is contained in:
parent
3d1fe9cc4b
commit
f3e81184c1
@ -15,6 +15,7 @@ use leo_types::{
|
||||
Integer,
|
||||
IntegerType,
|
||||
RangeOrExpression,
|
||||
Span,
|
||||
SpreadOrExpression,
|
||||
Type,
|
||||
};
|
||||
@ -61,6 +62,7 @@ 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>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
@ -74,13 +76,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_add_expression(cs, val_1, val_2)
|
||||
self.enforce_add_expression(cs, val_1, val_2, span)
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
self.enforce_add_expression(cs, val_1, val_2)
|
||||
self.enforce_add_expression(cs, val_1, val_2, span)
|
||||
}
|
||||
(val_1, val_2) => Err(ExpressionError::IncompatibleTypes(format!("{} + {}", val_1, val_2,))),
|
||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||
format!("{} + {}", val_1, val_2),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +94,7 @@ 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>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
@ -102,13 +108,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_sub_expression(cs, val_1, val_2)
|
||||
self.enforce_sub_expression(cs, val_1, val_2, span)
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
self.enforce_sub_expression(cs, val_1, val_2)
|
||||
self.enforce_sub_expression(cs, val_1, val_2, span)
|
||||
}
|
||||
(val_1, val_2) => Err(ExpressionError::IncompatibleTypes(format!("{} - {}", val_1, val_2,))),
|
||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||
format!("{} - {}", val_1, val_2),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,6 +126,7 @@ 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>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
@ -127,13 +137,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_mul_expression(cs, val_1, val_2)
|
||||
self.enforce_mul_expression(cs, val_1, val_2, span)
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
self.enforce_mul_expression(cs, val_1, val_2)
|
||||
self.enforce_mul_expression(cs, val_1, val_2, span)
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} * {}", val_1, val_2),
|
||||
span,
|
||||
));
|
||||
}
|
||||
(val_1, val_2) => return Err(ExpressionError::IncompatibleTypes(format!("{} * {}", val_1, val_2,))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,6 +157,7 @@ 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>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
@ -152,13 +168,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_div_expression(cs, val_1, val_2)
|
||||
self.enforce_div_expression(cs, val_1, val_2, span)
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
self.enforce_div_expression(cs, val_1, val_2)
|
||||
self.enforce_div_expression(cs, val_1, val_2, span)
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} / {}", val_1, val_2,),
|
||||
span,
|
||||
));
|
||||
}
|
||||
(val_1, val_2) => return Err(ExpressionError::IncompatibleTypes(format!("{} / {}", val_1, val_2,))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,6 +188,7 @@ 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>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
@ -174,13 +196,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_pow_expression(cs, val_1, val_2)
|
||||
self.enforce_pow_expression(cs, val_1, val_2, span)
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
self.enforce_pow_expression(cs, val_1, val_2)
|
||||
self.enforce_pow_expression(cs, val_1, val_2, span)
|
||||
}
|
||||
(val_1, val_2) => Err(ExpressionError::IncompatibleTypes(format!("{} * {}", val_1, val_2,))),
|
||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||
format!("{} ** {}", val_1, val_2,),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,6 +215,7 @@ 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>, ExpressionError> {
|
||||
let mut expression_namespace = cs.ns(|| format!("evaluate {} == {}", left.to_string(), right.to_string()));
|
||||
let result_bool = match (left, right) {
|
||||
@ -207,13 +233,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
return self.evaluate_eq_expression(&mut expression_namespace, val_1, val_2);
|
||||
return self.evaluate_eq_expression(&mut expression_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
return self.evaluate_eq_expression(&mut expression_namespace, val_1, val_2);
|
||||
return self.evaluate_eq_expression(&mut expression_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} == {}", val_1, val_2,),
|
||||
span,
|
||||
));
|
||||
}
|
||||
(val_1, val_2) => return Err(ExpressionError::IncompatibleTypes(format!("{} == {}", val_1, val_2,))),
|
||||
};
|
||||
|
||||
Ok(ConstrainedValue::Boolean(result_bool))
|
||||
@ -224,6 +255,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
&mut self,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
@ -236,16 +268,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.evaluate_ge_expression(val_1, val_2)
|
||||
self.evaluate_ge_expression(val_1, val_2, span)
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
self.evaluate_ge_expression(val_1, val_2)
|
||||
self.evaluate_ge_expression(val_1, val_2, span)
|
||||
}
|
||||
(val_1, val_2) => Err(ExpressionError::IncompatibleTypes(format!(
|
||||
"{} >= {}, values must be fields",
|
||||
val_1, val_2
|
||||
))),
|
||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||
format!("{} >= {}", val_1, val_2),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,6 +286,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
&mut self,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
@ -266,16 +299,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.evaluate_gt_expression(val_1, val_2)
|
||||
self.evaluate_gt_expression(val_1, val_2, span)
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
self.evaluate_gt_expression(val_1, val_2)
|
||||
self.evaluate_gt_expression(val_1, val_2, span)
|
||||
}
|
||||
(val_1, val_2) => Err(ExpressionError::IncompatibleTypes(format!(
|
||||
"{} > {}, values must be fields",
|
||||
val_1, val_2
|
||||
))),
|
||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||
format!("{} > {}", val_1, val_2),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,6 +317,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
&mut self,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
@ -296,16 +330,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.evaluate_le_expression(val_1, val_2)
|
||||
self.evaluate_le_expression(val_1, val_2, span)
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
self.evaluate_le_expression(val_1, val_2)
|
||||
self.evaluate_le_expression(val_1, val_2, span)
|
||||
}
|
||||
(val_1, val_2) => Err(ExpressionError::IncompatibleTypes(format!(
|
||||
"{} <= {}, values must be fields",
|
||||
val_1, val_2
|
||||
))),
|
||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||
format!("{} <= {}", val_1, val_2),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,6 +348,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
&mut self,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
@ -326,16 +361,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.evaluate_lt_expression(val_1, val_2)
|
||||
self.evaluate_lt_expression(val_1, val_2, span)
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
self.evaluate_lt_expression(val_1, val_2)
|
||||
self.evaluate_lt_expression(val_1, val_2, span)
|
||||
}
|
||||
(val_1, val_2) => Err(ExpressionError::IncompatibleTypes(format!(
|
||||
"{} < {}, values must be fields",
|
||||
val_1, val_2,
|
||||
))),
|
||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||
format!("{} < {}", val_1, val_2,),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,6 +384,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
first: Expression,
|
||||
second: Expression,
|
||||
third: Expression,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let resolved_first = match self.enforce_expression(
|
||||
cs,
|
||||
@ -358,7 +394,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
first,
|
||||
)? {
|
||||
ConstrainedValue::Boolean(resolved) => resolved,
|
||||
value => return Err(ExpressionError::IfElseConditional(value.to_string())),
|
||||
value => return Err(ExpressionError::conditional_boolean(value.to_string(), span)),
|
||||
};
|
||||
|
||||
let resolved_second =
|
||||
@ -382,7 +418,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
let result = G::conditionally_select(cs, &resolved_first, &ge_1, &ge_2)?;
|
||||
Ok(ConstrainedValue::Group(result))
|
||||
}
|
||||
(_, _) => unimplemented!("statements.conditional select gadget not implemented between given types"),
|
||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||
format!("ternary between {} and {}", val_1, val_2),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -394,6 +433,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
function_scope: String,
|
||||
expected_types: &Vec<Type>,
|
||||
array: Vec<Box<SpreadOrExpression>>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
// Check explicit array type dimension if given
|
||||
let mut expected_types = expected_types.clone();
|
||||
@ -404,7 +444,13 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
Type::Array(ref _type, ref dimensions) => {
|
||||
expected_types = vec![expected_types[0].inner_dimension(dimensions)];
|
||||
}
|
||||
ref _type => return Err(ExpressionError::IncompatibleTypes(_type.to_string())),
|
||||
ref _type => {
|
||||
return Err(ExpressionError::unexpected_array(
|
||||
expected_types[0].to_string(),
|
||||
_type.to_string(),
|
||||
span,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -418,13 +464,13 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
Some(value) => match value {
|
||||
ConstrainedValue::Array(array) => result.extend(array.clone()),
|
||||
value => {
|
||||
return Err(ExpressionError::InvalidSpread(value.to_string()));
|
||||
return Err(ExpressionError::invalid_spread(value.to_string(), span));
|
||||
}
|
||||
},
|
||||
None => return Err(ExpressionError::UndefinedArray(identifier.name)),
|
||||
None => return Err(ExpressionError::undefined_array(identifier.name, span)),
|
||||
}
|
||||
}
|
||||
value => return Err(ExpressionError::InvalidSpread(value.to_string())),
|
||||
value => return Err(ExpressionError::invalid_spread(value.to_string(), span)),
|
||||
},
|
||||
SpreadOrExpression::Expression(expression) => {
|
||||
result.push(self.enforce_expression(
|
||||
@ -441,9 +487,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
// Check expected_dimensions if given
|
||||
if !expected_dimensions.is_empty() {
|
||||
if expected_dimensions[expected_dimensions.len() - 1] != result.len() {
|
||||
return Err(ExpressionError::InvalidLength(
|
||||
return Err(ExpressionError::invalid_length(
|
||||
expected_dimensions[expected_dimensions.len() - 1],
|
||||
result.len(),
|
||||
span,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -457,11 +504,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
index: Expression,
|
||||
span: Span,
|
||||
) -> Result<usize, ExpressionError> {
|
||||
let expected_types = vec![Type::IntegerType(IntegerType::U32)];
|
||||
match self.enforce_expression_value(cs, file_scope.clone(), function_scope.clone(), &expected_types, index)? {
|
||||
ConstrainedValue::Integer(number) => Ok(number.to_usize()),
|
||||
value => Err(ExpressionError::InvalidIndex(value.to_string())),
|
||||
value => Err(ExpressionError::invalid_index(value.to_string(), span)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,6 +521,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
expected_types: &Vec<Type>,
|
||||
array: Box<Expression>,
|
||||
index: RangeOrExpression,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let array = match self.enforce_expression_value(
|
||||
cs,
|
||||
@ -482,7 +531,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*array,
|
||||
)? {
|
||||
ConstrainedValue::Array(array) => array,
|
||||
value => return Err(ExpressionError::InvalidArrayAccess(value.to_string())),
|
||||
value => return Err(ExpressionError::undefined_array(value.to_string(), span)),
|
||||
};
|
||||
|
||||
match index {
|
||||
@ -498,7 +547,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
Ok(ConstrainedValue::Array(array[from_resolved..to_resolved].to_owned()))
|
||||
}
|
||||
RangeOrExpression::Expression(index) => {
|
||||
let index_resolved = self.enforce_index(cs, file_scope, function_scope, index)?;
|
||||
let index_resolved = self.enforce_index(cs, file_scope, function_scope, index, span)?;
|
||||
Ok(array[index_resolved].to_owned())
|
||||
}
|
||||
}
|
||||
@ -511,6 +560,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
function_scope: String,
|
||||
identifier: Identifier,
|
||||
members: Vec<CircuitFieldDefinition>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut program_identifier = new_scope(file_scope.clone(), identifier.to_string());
|
||||
|
||||
@ -541,7 +591,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
|
||||
resolved_members.push(ConstrainedCircuitMember(identifier, field_value))
|
||||
}
|
||||
None => return Err(ExpressionError::ExpectedCircuitMember(identifier.to_string())),
|
||||
None => return Err(ExpressionError::expected_circuit_member(identifier.to_string(), span)),
|
||||
}
|
||||
}
|
||||
CircuitMember::CircuitFunction(_static, function) => {
|
||||
@ -563,7 +613,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
resolved_members,
|
||||
))
|
||||
} else {
|
||||
Err(ExpressionError::UndefinedCircuit(identifier.to_string()))
|
||||
Err(ExpressionError::undefined_circuit(identifier.to_string(), span))
|
||||
}
|
||||
}
|
||||
|
||||
@ -575,6 +625,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
expected_types: &Vec<Type>,
|
||||
circuit_identifier: Box<Expression>,
|
||||
circuit_member: Identifier,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let (circuit_name, members) = match self.enforce_expression_value(
|
||||
cs,
|
||||
@ -584,7 +635,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*circuit_identifier.clone(),
|
||||
)? {
|
||||
ConstrainedValue::CircuitExpression(name, members) => (name, members),
|
||||
value => return Err(ExpressionError::InvalidCircuitAccess(value.to_string())),
|
||||
value => return Err(ExpressionError::undefined_circuit(value.to_string(), span)),
|
||||
};
|
||||
|
||||
let matched_member = members.clone().into_iter().find(|member| member.0 == circuit_member);
|
||||
@ -609,15 +660,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
}
|
||||
ConstrainedValue::Static(value) => {
|
||||
return Err(ExpressionError::InvalidStaticAccess(value.to_string()));
|
||||
return Err(ExpressionError::invalid_static_access(value.to_string(), span));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(member.1)
|
||||
}
|
||||
None => Err(ExpressionError::UndefinedMemberAccess(
|
||||
None => Err(ExpressionError::undefined_member_access(
|
||||
circuit_name.to_string(),
|
||||
circuit_member.to_string(),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -630,6 +682,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
expected_types: &Vec<Type>,
|
||||
circuit_identifier: Box<Expression>,
|
||||
circuit_member: Identifier,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
// Get defined circuit
|
||||
let circuit = match self.enforce_expression(
|
||||
@ -640,7 +693,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*circuit_identifier.clone(),
|
||||
)? {
|
||||
ConstrainedValue::CircuitDefinition(circuit_definition) => circuit_definition,
|
||||
value => return Err(ExpressionError::InvalidCircuitAccess(value.to_string())),
|
||||
value => return Err(ExpressionError::undefined_circuit(value.to_string(), span)),
|
||||
};
|
||||
|
||||
// Find static circuit function
|
||||
@ -655,13 +708,17 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
if _static {
|
||||
function
|
||||
} else {
|
||||
return Err(ExpressionError::InvalidMemberAccess(function.function_name.to_string()));
|
||||
return Err(ExpressionError::invalid_member_access(
|
||||
function.function_name.to_string(),
|
||||
span,
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(ExpressionError::UndefinedStaticAccess(
|
||||
return Err(ExpressionError::undefined_member_access(
|
||||
circuit.identifier.to_string(),
|
||||
circuit_member.to_string(),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
@ -677,6 +734,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
expected_types: &Vec<Type>,
|
||||
function: Box<Expression>,
|
||||
arguments: Vec<Expression>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let function_value = self.enforce_expression(
|
||||
cs,
|
||||
@ -696,7 +754,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
|
||||
(outer_scope, function.clone())
|
||||
}
|
||||
value => return Err(ExpressionError::UndefinedFunction(value.to_string())),
|
||||
value => return Err(ExpressionError::undefined_function(value.to_string(), span)),
|
||||
};
|
||||
|
||||
match self.enforce_function(cs, outer_scope, function_scope, function_call, arguments) {
|
||||
@ -707,7 +765,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
Ok(ConstrainedValue::Return(return_values))
|
||||
}
|
||||
}
|
||||
Ok(_) => Err(ExpressionError::FunctionDidNotReturn(function.to_string())),
|
||||
Ok(_) => Err(ExpressionError::function_no_return(function.to_string(), span)),
|
||||
Err(error) => Err(ExpressionError::from(Box::new(error))),
|
||||
}
|
||||
}
|
||||
@ -783,7 +841,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
Expression::Implicit(value) => Self::enforce_number_implicit(expected_types, value),
|
||||
|
||||
// Binary operations
|
||||
Expression::Add(left, right) => {
|
||||
Expression::Add(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -793,9 +851,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*right,
|
||||
)?;
|
||||
|
||||
self.enforce_add_expression(cs, resolved_left, resolved_right)
|
||||
self.enforce_add_expression(cs, resolved_left, resolved_right, span)
|
||||
}
|
||||
Expression::Sub(left, right) => {
|
||||
Expression::Sub(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -805,9 +863,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*right,
|
||||
)?;
|
||||
|
||||
self.enforce_sub_expression(cs, resolved_left, resolved_right)
|
||||
self.enforce_sub_expression(cs, resolved_left, resolved_right, span)
|
||||
}
|
||||
Expression::Mul(left, right) => {
|
||||
Expression::Mul(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -817,9 +875,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*right,
|
||||
)?;
|
||||
|
||||
self.enforce_mul_expression(cs, resolved_left, resolved_right)
|
||||
self.enforce_mul_expression(cs, resolved_left, resolved_right, span)
|
||||
}
|
||||
Expression::Div(left, right) => {
|
||||
Expression::Div(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -829,9 +887,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*right,
|
||||
)?;
|
||||
|
||||
self.enforce_div_expression(cs, resolved_left, resolved_right)
|
||||
self.enforce_div_expression(cs, resolved_left, resolved_right, span)
|
||||
}
|
||||
Expression::Pow(left, right) => {
|
||||
Expression::Pow(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -841,7 +899,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*right,
|
||||
)?;
|
||||
|
||||
self.enforce_pow_expression(cs, resolved_left, resolved_right)
|
||||
self.enforce_pow_expression(cs, resolved_left, resolved_right, span)
|
||||
}
|
||||
|
||||
// Boolean operations
|
||||
@ -852,7 +910,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
expected_types,
|
||||
*expression,
|
||||
)?)?),
|
||||
Expression::Or(left, right) => {
|
||||
Expression::Or(left, right, _span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -864,7 +922,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
|
||||
Ok(self.enforce_or(cs, resolved_left, resolved_right)?)
|
||||
}
|
||||
Expression::And(left, right) => {
|
||||
Expression::And(left, right, _span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -876,7 +934,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
|
||||
Ok(self.enforce_and(cs, resolved_left, resolved_right)?)
|
||||
}
|
||||
Expression::Eq(left, right) => {
|
||||
Expression::Eq(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -886,9 +944,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.evaluate_eq_expression(cs, resolved_left, resolved_right)?)
|
||||
Ok(self.evaluate_eq_expression(cs, resolved_left, resolved_right, span)?)
|
||||
}
|
||||
Expression::Ge(left, right) => {
|
||||
Expression::Ge(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -898,9 +956,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.evaluate_ge_expression(resolved_left, resolved_right)?)
|
||||
Ok(self.evaluate_ge_expression(resolved_left, resolved_right, span)?)
|
||||
}
|
||||
Expression::Gt(left, right) => {
|
||||
Expression::Gt(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -910,9 +968,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.evaluate_gt_expression(resolved_left, resolved_right)?)
|
||||
Ok(self.evaluate_gt_expression(resolved_left, resolved_right, span)?)
|
||||
}
|
||||
Expression::Le(left, right) => {
|
||||
Expression::Le(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -922,9 +980,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.evaluate_le_expression(resolved_left, resolved_right)?)
|
||||
Ok(self.evaluate_le_expression(resolved_left, resolved_right, span)?)
|
||||
}
|
||||
Expression::Lt(left, right) => {
|
||||
Expression::Lt(left, right, span) => {
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
@ -934,11 +992,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.evaluate_lt_expression(resolved_left, resolved_right)?)
|
||||
Ok(self.evaluate_lt_expression(resolved_left, resolved_right, span)?)
|
||||
}
|
||||
|
||||
// Conditionals
|
||||
Expression::IfElse(first, second, third) => self.enforce_conditional_expression(
|
||||
Expression::IfElse(first, second, third, span) => self.enforce_conditional_expression(
|
||||
cs,
|
||||
file_scope,
|
||||
function_scope,
|
||||
@ -946,21 +1004,28 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*first,
|
||||
*second,
|
||||
*third,
|
||||
span,
|
||||
),
|
||||
|
||||
// Arrays
|
||||
Expression::Array(array) => {
|
||||
self.enforce_array_expression(cs, file_scope, function_scope, expected_types, array)
|
||||
}
|
||||
Expression::ArrayAccess(array, index) => {
|
||||
self.enforce_array_access_expression(cs, file_scope, function_scope, expected_types, array, *index)
|
||||
Expression::Array(array, span) => {
|
||||
self.enforce_array_expression(cs, file_scope, function_scope, expected_types, array, span)
|
||||
}
|
||||
Expression::ArrayAccess(array, index, span) => self.enforce_array_access_expression(
|
||||
cs,
|
||||
file_scope,
|
||||
function_scope,
|
||||
expected_types,
|
||||
array,
|
||||
*index,
|
||||
span,
|
||||
),
|
||||
|
||||
// Circuits
|
||||
Expression::Circuit(circuit_name, members) => {
|
||||
self.enforce_circuit_expression(cs, file_scope, function_scope, circuit_name, members)
|
||||
Expression::Circuit(circuit_name, members, span) => {
|
||||
self.enforce_circuit_expression(cs, file_scope, function_scope, circuit_name, members, span)
|
||||
}
|
||||
Expression::CircuitMemberAccess(circuit_variable, circuit_member) => self
|
||||
Expression::CircuitMemberAccess(circuit_variable, circuit_member, span) => self
|
||||
.enforce_circuit_access_expression(
|
||||
cs,
|
||||
file_scope,
|
||||
@ -968,8 +1033,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
expected_types,
|
||||
circuit_variable,
|
||||
circuit_member,
|
||||
span,
|
||||
),
|
||||
Expression::CircuitStaticFunctionAccess(circuit_identifier, circuit_member) => self
|
||||
Expression::CircuitStaticFunctionAccess(circuit_identifier, circuit_member, span) => self
|
||||
.enforce_circuit_static_access_expression(
|
||||
cs,
|
||||
file_scope,
|
||||
@ -977,16 +1043,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
expected_types,
|
||||
circuit_identifier,
|
||||
circuit_member,
|
||||
span,
|
||||
),
|
||||
|
||||
// Functions
|
||||
Expression::FunctionCall(function, arguments) => self.enforce_function_call_expression(
|
||||
Expression::FunctionCall(function, arguments, span) => self.enforce_function_call_expression(
|
||||
cs,
|
||||
file_scope,
|
||||
function_scope,
|
||||
expected_types,
|
||||
function,
|
||||
arguments,
|
||||
span,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
// Resolve index so we know if we are assigning to a single value or a range of values
|
||||
match range_or_expression {
|
||||
RangeOrExpression::Expression(index) => {
|
||||
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, span.clone())?;
|
||||
|
||||
// Modify the single value of the array in place
|
||||
match self.get_mutable_assignee(name, span.clone())? {
|
||||
|
@ -6,20 +6,12 @@ use std::num::ParseIntError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExpressionError {
|
||||
// Identifiers
|
||||
#[error("Identifier \"{}\" not found", _0)]
|
||||
UndefinedIdentifier(String),
|
||||
|
||||
#[error("{}", _0)]
|
||||
Error(#[from] FormattedError),
|
||||
|
||||
// Types
|
||||
#[error("{}", _0)]
|
||||
BooleanError(#[from] BooleanError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
IncompatibleTypes(String),
|
||||
|
||||
#[error("{}", _0)]
|
||||
IntegerError(#[from] IntegerError),
|
||||
|
||||
@ -35,54 +27,8 @@ pub enum ExpressionError {
|
||||
#[error("{}", _0)]
|
||||
ValueError(#[from] ValueError),
|
||||
|
||||
// Arrays
|
||||
#[error("Cannot access array {}", _0)]
|
||||
InvalidArrayAccess(String),
|
||||
|
||||
#[error("Index must resolve to an integer, got {}", _0)]
|
||||
InvalidIndex(String),
|
||||
|
||||
#[error("Expected array length {}, got {}", _0, _1)]
|
||||
InvalidLength(usize, usize),
|
||||
|
||||
#[error("Spread should contain an array, got {}", _0)]
|
||||
InvalidSpread(String),
|
||||
|
||||
#[error("Array {} must be declared before it is used in an inline expression", _0)]
|
||||
UndefinedArray(String),
|
||||
|
||||
// Circuits
|
||||
#[error("Expected circuit member {}", _0)]
|
||||
ExpectedCircuitMember(String),
|
||||
|
||||
#[error("Cannot access circuit {}", _0)]
|
||||
InvalidCircuitAccess(String),
|
||||
|
||||
#[error("Non-static member {} must be accessed using `.` syntax", _0)]
|
||||
InvalidMemberAccess(String),
|
||||
|
||||
#[error("Static member {} must be accessed using `::` syntax", _0)]
|
||||
InvalidStaticAccess(String),
|
||||
|
||||
#[error("Circuit {} must be declared before it is used in an inline expression", _0)]
|
||||
UndefinedCircuit(String),
|
||||
|
||||
#[error("Circuit {} has no member {}", _0, _1)]
|
||||
UndefinedMemberAccess(String, String),
|
||||
|
||||
#[error("Circuit {} has no static member {}", _0, _1)]
|
||||
UndefinedStaticAccess(String, String),
|
||||
|
||||
// Functions
|
||||
#[error("Inline function call to {} did not return", _0)]
|
||||
FunctionDidNotReturn(String),
|
||||
|
||||
#[error("{}", _0)]
|
||||
FunctionError(#[from] Box<FunctionError>),
|
||||
|
||||
#[error("Function {} must be declared before it is used in an inline expression", _0)]
|
||||
UndefinedFunction(String),
|
||||
|
||||
// Conditionals
|
||||
#[error("If, else statements.conditional must resolve to a boolean, got {}", _0)]
|
||||
IfElseConditional(String),
|
||||
@ -96,9 +42,105 @@ impl ExpressionError {
|
||||
ExpressionError::Error(FormattedError::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, found `{}`", actual);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn expected_circuit_member(expected: String, span: Span) -> Self {
|
||||
let message = format!("Expected circuit member `{}`, not found", expected);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn unexpected_array(expected: String, actual: String, span: Span) -> Self {
|
||||
let message = format!("expected type `{}`, found array with elements `{}`", expected, actual);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn incompatible_types(operation: String, span: Span) -> Self {
|
||||
let message = format!("no implementation for `{}`", operation);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn invalid_index(actual: String, span: Span) -> Self {
|
||||
let message = format!("Index must resolve to an integer, found `{}`", actual);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn invalid_length(expected: usize, actual: usize, span: Span) -> Self {
|
||||
let message = format!("Expected array length {}, found one with length {}", expected, actual);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn invalid_spread(actual: String, span: Span) -> Self {
|
||||
let message = format!("Spread should contain an array, found `{}`", actual);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn invalid_member_access(member: String, span: Span) -> Self {
|
||||
let message = format!("Non-static member `{}` must be accessed using `.` syntax", member);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn invalid_static_access(member: String, span: Span) -> Self {
|
||||
let message = format!("Static member `{}` must be accessed using `::` syntax", member);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn function_no_return(function: String, span: Span) -> Self {
|
||||
let message = format!("Inline function call to `{}` did not return", function);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn undefined_array(actual: String, span: Span) -> Self {
|
||||
let message = format!("Array `{}` must be declared before it is used in an expression", actual);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn undefined_circuit(actual: String, span: Span) -> Self {
|
||||
let message = format!(
|
||||
"Circuit `{}` must be declared before it is used in an expression",
|
||||
actual
|
||||
);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn undefined_identifier(identifier: Identifier) -> Self {
|
||||
let message = format!("cannot find value `{}` in this scope", identifier.name);
|
||||
|
||||
Self::new_from_span(message, identifier.span)
|
||||
}
|
||||
|
||||
pub fn undefined_function(function: String, span: Span) -> Self {
|
||||
let message = format!(
|
||||
"Function `{}` must be declared before it is used in an inline expression",
|
||||
function
|
||||
);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn undefined_member_access(circuit: String, member: String, span: Span) -> Self {
|
||||
let message = format!("Circuit `{}` has no member `{}`", circuit, member);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn undefined_static_access(circuit: String, member: String, span: Span) -> Self {
|
||||
let message = format!("Circuit `{}` has no static member `{}`", circuit, member);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
}
|
||||
|
@ -39,20 +39,20 @@ impl StatementError {
|
||||
}
|
||||
|
||||
pub fn assertion_failed(left: String, right: String, span: Span) -> Self {
|
||||
let message = format!("Assertion {} == {} failed", left, right);
|
||||
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);
|
||||
let message = format!("If, else conditional must resolve to a boolean, found `{}`", 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 {}",
|
||||
"Multiple definition statement expected {} return values, found {} values",
|
||||
expected, actual
|
||||
);
|
||||
|
||||
@ -61,7 +61,7 @@ impl StatementError {
|
||||
|
||||
pub fn invalid_number_of_returns(expected: usize, actual: usize, span: Span) -> Self {
|
||||
let message = format!(
|
||||
"Function return statement expected {} return values, got {}",
|
||||
"Function return statement expected {} return values, found {} values",
|
||||
expected, actual
|
||||
);
|
||||
|
||||
@ -69,20 +69,20 @@ impl StatementError {
|
||||
}
|
||||
|
||||
pub fn immutable_assign(name: String, span: Span) -> Self {
|
||||
let message = format!("Cannot assign to immutable variable {}", name);
|
||||
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);
|
||||
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 {}",
|
||||
"Conditional select gadget failed to select between `{}` or `{}`",
|
||||
first, second
|
||||
);
|
||||
|
||||
@ -90,25 +90,25 @@ impl StatementError {
|
||||
}
|
||||
|
||||
pub fn unassigned(name: String, span: Span) -> Self {
|
||||
let message = format!("Expected assignment of return values for expression {}", name);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
let message = format!("Attempted to assign to unknown circuit object `{}`", name);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use pest::{Position, Span as AstSpan};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Span {
|
||||
/// text of input string
|
||||
pub text: String,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{CircuitFieldDefinition, Identifier, Integer, RangeOrExpression, SpreadOrExpression};
|
||||
use crate::{CircuitFieldDefinition, Identifier, Integer, RangeOrExpression, Span, SpreadOrExpression};
|
||||
use leo_ast::{
|
||||
access::{Access, AssigneeAccess},
|
||||
common::{Assignee, Identifier as AstIdentifier},
|
||||
@ -34,36 +34,36 @@ pub enum Expression {
|
||||
Implicit(String),
|
||||
|
||||
// Number operations
|
||||
Add(Box<Expression>, Box<Expression>),
|
||||
Sub(Box<Expression>, Box<Expression>),
|
||||
Mul(Box<Expression>, Box<Expression>),
|
||||
Div(Box<Expression>, Box<Expression>),
|
||||
Pow(Box<Expression>, Box<Expression>),
|
||||
Add(Box<Expression>, Box<Expression>, Span),
|
||||
Sub(Box<Expression>, Box<Expression>, Span),
|
||||
Mul(Box<Expression>, Box<Expression>, Span),
|
||||
Div(Box<Expression>, Box<Expression>, Span),
|
||||
Pow(Box<Expression>, Box<Expression>, Span),
|
||||
|
||||
// Boolean operations
|
||||
Not(Box<Expression>),
|
||||
Or(Box<Expression>, Box<Expression>),
|
||||
And(Box<Expression>, Box<Expression>),
|
||||
Eq(Box<Expression>, Box<Expression>),
|
||||
Ge(Box<Expression>, Box<Expression>),
|
||||
Gt(Box<Expression>, Box<Expression>),
|
||||
Le(Box<Expression>, Box<Expression>),
|
||||
Lt(Box<Expression>, Box<Expression>),
|
||||
Or(Box<Expression>, Box<Expression>, Span),
|
||||
And(Box<Expression>, Box<Expression>, Span),
|
||||
Eq(Box<Expression>, Box<Expression>, Span),
|
||||
Ge(Box<Expression>, Box<Expression>, Span),
|
||||
Gt(Box<Expression>, Box<Expression>, Span),
|
||||
Le(Box<Expression>, Box<Expression>, Span),
|
||||
Lt(Box<Expression>, Box<Expression>, Span),
|
||||
|
||||
// Conditionals
|
||||
IfElse(Box<Expression>, Box<Expression>, Box<Expression>),
|
||||
IfElse(Box<Expression>, Box<Expression>, Box<Expression>, Span),
|
||||
|
||||
// Arrays
|
||||
Array(Vec<Box<SpreadOrExpression>>),
|
||||
ArrayAccess(Box<Expression>, Box<RangeOrExpression>), // (array name, range)
|
||||
Array(Vec<Box<SpreadOrExpression>>, Span),
|
||||
ArrayAccess(Box<Expression>, Box<RangeOrExpression>, Span), // (array name, range)
|
||||
|
||||
// Circuits
|
||||
Circuit(Identifier, Vec<CircuitFieldDefinition>),
|
||||
CircuitMemberAccess(Box<Expression>, Identifier), // (declared circuit name, circuit member name)
|
||||
CircuitStaticFunctionAccess(Box<Expression>, Identifier), // (defined circuit name, circuit static member name)
|
||||
Circuit(Identifier, Vec<CircuitFieldDefinition>, Span),
|
||||
CircuitMemberAccess(Box<Expression>, Identifier, Span), // (declared circuit name, circuit member name)
|
||||
CircuitStaticFunctionAccess(Box<Expression>, Identifier, Span), // (defined circuit name, circuit static member name)
|
||||
|
||||
// Functions
|
||||
FunctionCall(Box<Expression>, Vec<Expression>),
|
||||
FunctionCall(Box<Expression>, Vec<Expression>, Span),
|
||||
}
|
||||
|
||||
impl<'ast> Expression {
|
||||
@ -94,29 +94,29 @@ impl<'ast> fmt::Display for Expression {
|
||||
Expression::Implicit(ref value) => write!(f, "{}", value),
|
||||
|
||||
// Number operations
|
||||
Expression::Add(ref left, ref right) => write!(f, "{} + {}", left, right),
|
||||
Expression::Sub(ref left, ref right) => write!(f, "{} - {}", left, right),
|
||||
Expression::Mul(ref left, ref right) => write!(f, "{} * {}", left, right),
|
||||
Expression::Div(ref left, ref right) => write!(f, "{} / {}", left, right),
|
||||
Expression::Pow(ref left, ref right) => write!(f, "{} ** {}", left, right),
|
||||
Expression::Add(ref left, ref right, ref _span) => write!(f, "{} + {}", left, right),
|
||||
Expression::Sub(ref left, ref right, ref _span) => write!(f, "{} - {}", left, right),
|
||||
Expression::Mul(ref left, ref right, ref _span) => write!(f, "{} * {}", left, right),
|
||||
Expression::Div(ref left, ref right, ref _span) => write!(f, "{} / {}", left, right),
|
||||
Expression::Pow(ref left, ref right, ref _span) => write!(f, "{} ** {}", left, right),
|
||||
|
||||
// Boolean operations
|
||||
Expression::Not(ref expression) => write!(f, "!{}", expression),
|
||||
Expression::Or(ref lhs, ref rhs) => write!(f, "{} || {}", lhs, rhs),
|
||||
Expression::And(ref lhs, ref rhs) => write!(f, "{} && {}", lhs, rhs),
|
||||
Expression::Eq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
Expression::Ge(ref lhs, ref rhs) => write!(f, "{} >= {}", lhs, rhs),
|
||||
Expression::Gt(ref lhs, ref rhs) => write!(f, "{} > {}", lhs, rhs),
|
||||
Expression::Le(ref lhs, ref rhs) => write!(f, "{} <= {}", lhs, rhs),
|
||||
Expression::Lt(ref lhs, ref rhs) => write!(f, "{} < {}", lhs, rhs),
|
||||
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),
|
||||
Expression::Ge(ref lhs, ref rhs, ref _span) => write!(f, "{} >= {}", lhs, rhs),
|
||||
Expression::Gt(ref lhs, ref rhs, ref _span) => write!(f, "{} > {}", lhs, rhs),
|
||||
Expression::Le(ref lhs, ref rhs, ref _span) => write!(f, "{} <= {}", lhs, rhs),
|
||||
Expression::Lt(ref lhs, ref rhs, ref _span) => write!(f, "{} < {}", lhs, rhs),
|
||||
|
||||
// Conditionals
|
||||
Expression::IfElse(ref first, ref second, ref third) => {
|
||||
Expression::IfElse(ref first, ref second, ref third, ref _span) => {
|
||||
write!(f, "if {} then {} else {} fi", first, second, third)
|
||||
}
|
||||
|
||||
// Arrays
|
||||
Expression::Array(ref array) => {
|
||||
Expression::Array(ref array, ref _span) => {
|
||||
write!(f, "[")?;
|
||||
for (i, e) in array.iter().enumerate() {
|
||||
write!(f, "{}", e)?;
|
||||
@ -126,10 +126,10 @@ impl<'ast> fmt::Display for Expression {
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
Expression::ArrayAccess(ref array, ref index) => write!(f, "{}[{}]", array, index),
|
||||
Expression::ArrayAccess(ref array, ref index, ref _span) => write!(f, "{}[{}]", array, index),
|
||||
|
||||
// Circuits
|
||||
Expression::Circuit(ref var, ref members) => {
|
||||
Expression::Circuit(ref var, ref members, ref _span) => {
|
||||
write!(f, "{} {{", var)?;
|
||||
for (i, member) in members.iter().enumerate() {
|
||||
write!(f, "{}: {}", member.identifier, member.expression)?;
|
||||
@ -139,13 +139,15 @@ impl<'ast> fmt::Display for Expression {
|
||||
}
|
||||
write!(f, "}}")
|
||||
}
|
||||
Expression::CircuitMemberAccess(ref circuit_name, ref member) => write!(f, "{}.{}", circuit_name, member),
|
||||
Expression::CircuitStaticFunctionAccess(ref circuit_name, ref member) => {
|
||||
Expression::CircuitMemberAccess(ref circuit_name, ref member, ref _span) => {
|
||||
write!(f, "{}.{}", circuit_name, member)
|
||||
}
|
||||
Expression::CircuitStaticFunctionAccess(ref circuit_name, ref member, ref _span) => {
|
||||
write!(f, "{}::{}", circuit_name, member)
|
||||
}
|
||||
|
||||
// Function calls
|
||||
Expression::FunctionCall(ref function, ref arguments) => {
|
||||
Expression::FunctionCall(ref function, ref arguments, ref _span) => {
|
||||
write!(f, "{}(", function,)?;
|
||||
for (i, param) in arguments.iter().enumerate() {
|
||||
write!(f, "{}", param)?;
|
||||
@ -168,7 +170,7 @@ impl<'ast> From<CircuitInlineExpression<'ast>> for Expression {
|
||||
.map(|member| CircuitFieldDefinition::from(member))
|
||||
.collect::<Vec<CircuitFieldDefinition>>();
|
||||
|
||||
Expression::Circuit(variable, members)
|
||||
Expression::Circuit(variable, members, Span::from(expression.span))
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,9 +187,11 @@ impl<'ast> From<PostfixExpression<'ast>> for Expression {
|
||||
.into_iter()
|
||||
.fold(variable, |acc, access| match access {
|
||||
// Handle array accesses
|
||||
Access::Array(array) => {
|
||||
Expression::ArrayAccess(Box::new(acc), Box::new(RangeOrExpression::from(array.expression)))
|
||||
}
|
||||
Access::Array(array) => Expression::ArrayAccess(
|
||||
Box::new(acc),
|
||||
Box::new(RangeOrExpression::from(array.expression)),
|
||||
Span::from(array.span),
|
||||
),
|
||||
|
||||
// Handle function calls
|
||||
Access::Call(function) => Expression::FunctionCall(
|
||||
@ -197,15 +201,20 @@ impl<'ast> From<PostfixExpression<'ast>> for Expression {
|
||||
.into_iter()
|
||||
.map(|expression| Expression::from(expression))
|
||||
.collect(),
|
||||
Span::from(function.span),
|
||||
),
|
||||
|
||||
// Handle circuit member accesses
|
||||
Access::Object(circuit_object) => {
|
||||
Expression::CircuitMemberAccess(Box::new(acc), Identifier::from(circuit_object.identifier))
|
||||
}
|
||||
Access::StaticObject(circuit_object) => {
|
||||
Expression::CircuitStaticFunctionAccess(Box::new(acc), Identifier::from(circuit_object.identifier))
|
||||
}
|
||||
Access::Object(circuit_object) => Expression::CircuitMemberAccess(
|
||||
Box::new(acc),
|
||||
Identifier::from(circuit_object.identifier),
|
||||
Span::from(circuit_object.span),
|
||||
),
|
||||
Access::StaticObject(circuit_object) => Expression::CircuitStaticFunctionAccess(
|
||||
Box::new(acc),
|
||||
Identifier::from(circuit_object.identifier),
|
||||
Span::from(circuit_object.span),
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -236,12 +245,16 @@ impl<'ast> From<Assignee<'ast>> for Expression {
|
||||
.accesses
|
||||
.into_iter()
|
||||
.fold(variable, |acc, access| match access {
|
||||
AssigneeAccess::Member(circuit_member) => {
|
||||
Expression::CircuitMemberAccess(Box::new(acc), Identifier::from(circuit_member.identifier))
|
||||
}
|
||||
AssigneeAccess::Array(array) => {
|
||||
Expression::ArrayAccess(Box::new(acc), Box::new(RangeOrExpression::from(array.expression)))
|
||||
}
|
||||
AssigneeAccess::Member(circuit_member) => Expression::CircuitMemberAccess(
|
||||
Box::new(acc),
|
||||
Identifier::from(circuit_member.identifier),
|
||||
Span::from(circuit_member.span),
|
||||
),
|
||||
AssigneeAccess::Array(array) => Expression::ArrayAccess(
|
||||
Box::new(acc),
|
||||
Box::new(RangeOrExpression::from(array.expression)),
|
||||
Span::from(array.span),
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -253,52 +266,64 @@ impl<'ast> From<BinaryExpression<'ast>> for Expression {
|
||||
BinaryOperation::Or => Expression::Or(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::And => Expression::And(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Eq => Expression::Eq(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Ne => Expression::Not(Box::new(Expression::from(expression))),
|
||||
BinaryOperation::Ge => Expression::Ge(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Gt => Expression::Gt(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Le => Expression::Le(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Lt => Expression::Lt(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
// Number operations
|
||||
BinaryOperation::Add => Expression::Add(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Sub => Expression::Sub(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Mul => Expression::Mul(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Div => Expression::Div(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
BinaryOperation::Pow => Expression::Pow(
|
||||
Box::new(Expression::from(*expression.left)),
|
||||
Box::new(Expression::from(*expression.right)),
|
||||
Span::from(expression.span),
|
||||
),
|
||||
}
|
||||
}
|
||||
@ -310,6 +335,7 @@ impl<'ast> From<TernaryExpression<'ast>> for Expression {
|
||||
Box::new(Expression::from(*expression.first)),
|
||||
Box::new(Expression::from(*expression.second)),
|
||||
Box::new(Expression::from(*expression.third)),
|
||||
Span::from(expression.span),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -322,6 +348,7 @@ impl<'ast> From<ArrayInlineExpression<'ast>> for Expression {
|
||||
.into_iter()
|
||||
.map(|s_or_e| Box::new(SpreadOrExpression::from(s_or_e)))
|
||||
.collect(),
|
||||
Span::from(array.span),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -331,7 +358,7 @@ impl<'ast> From<ArrayInitializerExpression<'ast>> for Expression {
|
||||
let count = Expression::get_count(array.count);
|
||||
let expression = Box::new(SpreadOrExpression::from(*array.expression));
|
||||
|
||||
Expression::Array(vec![expression; count])
|
||||
Expression::Array(vec![expression; count], Span::from(array.span))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,27 +67,47 @@ impl<'ast> From<AssignStatement<'ast>> for Statement {
|
||||
match operation_assign {
|
||||
AssignOperation::AddAssign(ref _assign) => Statement::Assign(
|
||||
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.clone()),
|
||||
),
|
||||
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))),
|
||||
Expression::Sub(
|
||||
Box::new(converted),
|
||||
Box::new(Expression::from(statement.expression)),
|
||||
Span::from(statement.span.clone()),
|
||||
),
|
||||
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))),
|
||||
Expression::Mul(
|
||||
Box::new(converted),
|
||||
Box::new(Expression::from(statement.expression)),
|
||||
Span::from(statement.span.clone()),
|
||||
),
|
||||
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))),
|
||||
Expression::Div(
|
||||
Box::new(converted),
|
||||
Box::new(Expression::from(statement.expression)),
|
||||
Span::from(statement.span.clone()),
|
||||
),
|
||||
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))),
|
||||
Expression::Pow(
|
||||
Box::new(converted),
|
||||
Box::new(Expression::from(statement.expression)),
|
||||
Span::from(statement.span.clone()),
|
||||
),
|
||||
Span::from(statement.span),
|
||||
),
|
||||
AssignOperation::Assign(ref _assign) => unimplemented!("cannot assign twice to assign statement"),
|
||||
@ -110,6 +130,7 @@ impl<'ast> From<MultipleAssignmentStatement<'ast>> for Statement {
|
||||
Expression::FunctionCall(
|
||||
Box::new(Expression::from(statement.function_name)),
|
||||
statement.arguments.into_iter().map(|e| Expression::from(e)).collect(),
|
||||
Span::from(statement.span.clone()),
|
||||
),
|
||||
Span::from(statement.span),
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user