mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-29 20:44:52 +03:00
Merge pull request #394 from ljedrz/pass_by_reference_compiler_overhaul
Pass by reference compiler overhaul
This commit is contained in:
commit
ae5f2f7b54
@ -155,10 +155,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Derive the package name.
|
// Derive the package name.
|
||||||
let package_name = self.package_name.clone();
|
let package_name = &self.package_name;
|
||||||
|
|
||||||
// Use the typed parser to construct the typed syntax tree.
|
// Use the typed parser to construct the typed syntax tree.
|
||||||
let typed_tree = LeoTypedAst::new(&package_name, &ast);
|
let typed_tree = LeoTypedAst::new(package_name, &ast);
|
||||||
|
|
||||||
self.program = typed_tree.into_repr();
|
self.program = typed_tree.into_repr();
|
||||||
self.imported_programs = ImportParser::parse(&self.program)?;
|
self.imported_programs = ImportParser::parse(&self.program)?;
|
||||||
|
@ -28,11 +28,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn evaluate_console_assert<CS: ConstraintSystem<F>>(
|
pub fn evaluate_console_assert<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<(), ConsoleError> {
|
) -> Result<(), ConsoleError> {
|
||||||
let expected_type = Some(Type::Boolean);
|
let expected_type = Some(Type::Boolean);
|
||||||
let expression_string = expression.to_string();
|
let expression_string = expression.to_string();
|
||||||
@ -53,12 +53,17 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
// Unwrap assertion value and handle errors
|
// Unwrap assertion value and handle errors
|
||||||
let result_option = match assert_expression {
|
let result_option = match assert_expression {
|
||||||
ConstrainedValue::Boolean(boolean) => boolean.get_value(),
|
ConstrainedValue::Boolean(boolean) => boolean.get_value(),
|
||||||
_ => return Err(ConsoleError::assertion_must_be_boolean(expression_string, span)),
|
_ => {
|
||||||
|
return Err(ConsoleError::assertion_must_be_boolean(
|
||||||
|
expression_string,
|
||||||
|
span.to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let result_bool = result_option.ok_or_else(|| ConsoleError::assertion_depends_on_input(span.clone()))?;
|
let result_bool = result_option.ok_or_else(|| ConsoleError::assertion_depends_on_input(span.to_owned()))?;
|
||||||
|
|
||||||
if !result_bool {
|
if !result_bool {
|
||||||
return Err(ConsoleError::assertion_failed(expression_string, span));
|
return Err(ConsoleError::assertion_failed(expression_string, span.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -28,14 +28,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn evaluate_console_function_call<CS: ConstraintSystem<F>>(
|
pub fn evaluate_console_function_call<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
console: ConsoleFunctionCall,
|
console: ConsoleFunctionCall,
|
||||||
) -> Result<(), ConsoleError> {
|
) -> Result<(), ConsoleError> {
|
||||||
match console.function {
|
match console.function {
|
||||||
ConsoleFunction::Assert(expression) => {
|
ConsoleFunction::Assert(expression) => {
|
||||||
self.evaluate_console_assert(cs, file_scope, function_scope, indicator, expression, console.span)?;
|
self.evaluate_console_assert(cs, file_scope, function_scope, indicator, expression, &console.span)?;
|
||||||
}
|
}
|
||||||
ConsoleFunction::Debug(string) => {
|
ConsoleFunction::Debug(string) => {
|
||||||
let string = self.format(cs, file_scope, function_scope, string)?;
|
let string = self.format(cs, file_scope, function_scope, string)?;
|
||||||
|
@ -28,8 +28,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn format<CS: ConstraintSystem<F>>(
|
pub fn format<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
formatted: FormattedString,
|
formatted: FormattedString,
|
||||||
) -> Result<String, ConsoleError> {
|
) -> Result<String, ConsoleError> {
|
||||||
// Check that containers and parameters match
|
// Check that containers and parameters match
|
||||||
@ -53,13 +53,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
let mut result = string.to_string();
|
let mut result = string.to_string();
|
||||||
|
|
||||||
for parameter in formatted.parameters.into_iter() {
|
for parameter in formatted.parameters.into_iter() {
|
||||||
let parameter_value = self.enforce_expression(
|
let parameter_value =
|
||||||
cs,
|
self.enforce_expression(cs, file_scope, function_scope, None, parameter.expression)?;
|
||||||
file_scope.clone(),
|
|
||||||
function_scope.clone(),
|
|
||||||
None,
|
|
||||||
parameter.expression,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
result = result.replacen("{}", ¶meter_value.to_string(), 1);
|
result = result.replacen("{}", ¶meter_value.to_string(), 1);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: Constrai
|
|||||||
) -> Result<OutputBytes, CompilerError> {
|
) -> Result<OutputBytes, CompilerError> {
|
||||||
let mut resolved_program = ConstrainedProgram::<F, G>::new();
|
let mut resolved_program = ConstrainedProgram::<F, G>::new();
|
||||||
let program_name = program.get_name();
|
let program_name = program.get_name();
|
||||||
let main_function_name = new_scope(program_name.clone(), "main".into());
|
let main_function_name = new_scope(&program_name, "main");
|
||||||
|
|
||||||
resolved_program.store_definitions(program, imported_programs)?;
|
resolved_program.store_definitions(program, imported_programs)?;
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: Constrai
|
|||||||
|
|
||||||
match main.clone() {
|
match main.clone() {
|
||||||
ConstrainedValue::Function(_circuit_identifier, function) => {
|
ConstrainedValue::Function(_circuit_identifier, function) => {
|
||||||
let result = resolved_program.enforce_main_function(cs, program_name, function, input)?;
|
let result = resolved_program.enforce_main_function(cs, &program_name, function, input)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
_ => Err(CompilerError::NoMainFunction),
|
_ => Err(CompilerError::NoMainFunction),
|
||||||
@ -87,7 +87,7 @@ pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>(
|
|||||||
|
|
||||||
for (test_name, test) in tests.into_iter() {
|
for (test_name, test) in tests.into_iter() {
|
||||||
let cs = &mut TestConstraintSystem::<F>::new();
|
let cs = &mut TestConstraintSystem::<F>::new();
|
||||||
let full_test_name = format!("{}::{}", program_name.clone(), test_name.to_string());
|
let full_test_name = format!("{}::{}", program_name, test_name);
|
||||||
let mut output_file_name = program_name.clone();
|
let mut output_file_name = program_name.clone();
|
||||||
|
|
||||||
// get input file name from annotation or use test_name
|
// get input file name from annotation or use test_name
|
||||||
@ -118,9 +118,9 @@ pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>(
|
|||||||
input.parse_state(state_ast)?;
|
input.parse_state(state_ast)?;
|
||||||
|
|
||||||
// run test function on new program with input
|
// run test function on new program with input
|
||||||
let result = resolved_program.clone().enforce_main_function(
|
let result = resolved_program.enforce_main_function(
|
||||||
cs,
|
cs,
|
||||||
program_name.clone(),
|
&program_name,
|
||||||
test.function,
|
test.function,
|
||||||
input, // pass program input into every test
|
input, // pass program input into every test
|
||||||
);
|
);
|
||||||
|
@ -28,7 +28,7 @@ use snarkos_models::curves::{Field, PrimeField};
|
|||||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||||
pub fn store_definition(
|
pub fn store_definition(
|
||||||
&mut self,
|
&mut self,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
mutable: bool,
|
mutable: bool,
|
||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
mut value: ConstrainedValue<F, G>,
|
mut value: ConstrainedValue<F, G>,
|
||||||
@ -38,7 +38,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
value = ConstrainedValue::Mutable(Box::new(value));
|
value = ConstrainedValue::Mutable(Box::new(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
let variable_program_identifier = new_scope(function_scope, identifier.name);
|
let variable_program_identifier = new_scope(function_scope, &identifier.name);
|
||||||
|
|
||||||
self.store(variable_program_identifier, value);
|
self.store(variable_program_identifier, value);
|
||||||
}
|
}
|
||||||
|
@ -35,18 +35,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
program
|
program
|
||||||
.imports
|
.imports
|
||||||
.iter()
|
.iter()
|
||||||
.map(|import| self.store_import(program_name.to_owned(), import, imported_programs))
|
.map(|import| self.store_import(&program_name, import, imported_programs))
|
||||||
.collect::<Result<Vec<_>, ImportError>>()?;
|
.collect::<Result<Vec<_>, ImportError>>()?;
|
||||||
|
|
||||||
// evaluate and store all circuit definitions
|
// evaluate and store all circuit definitions
|
||||||
program.circuits.into_iter().for_each(|(identifier, circuit)| {
|
program.circuits.into_iter().for_each(|(identifier, circuit)| {
|
||||||
let resolved_circuit_name = new_scope(program_name.to_owned(), identifier.to_string());
|
let resolved_circuit_name = new_scope(program_name, &identifier.name);
|
||||||
self.store(resolved_circuit_name, ConstrainedValue::CircuitDefinition(circuit));
|
self.store(resolved_circuit_name, ConstrainedValue::CircuitDefinition(circuit));
|
||||||
});
|
});
|
||||||
|
|
||||||
// evaluate and store all function definitions
|
// evaluate and store all function definitions
|
||||||
program.functions.into_iter().for_each(|(function_name, function)| {
|
program.functions.into_iter().for_each(|(function_name, function)| {
|
||||||
let resolved_function_name = new_scope(program_name.to_owned(), function_name.to_string());
|
let resolved_function_name = new_scope(program_name, &function_name.name);
|
||||||
self.store(resolved_function_name, ConstrainedValue::Function(None, function));
|
self.store(resolved_function_name, ConstrainedValue::Function(None, function));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ pub fn enforce_add<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||||
@ -41,16 +41,16 @@ pub fn enforce_add<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
Ok(ConstrainedValue::Group(point_1.add(cs, &point_2, span)?))
|
Ok(ConstrainedValue::Group(point_1.add(cs, &point_2, span)?))
|
||||||
}
|
}
|
||||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
let val_1 = ConstrainedValue::from_other(string, &val_2, span)?;
|
||||||
enforce_add(cs, val_1, val_2, span)
|
enforce_add(cs, val_1, val_2, span)
|
||||||
}
|
}
|
||||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
let val_2 = ConstrainedValue::from_other(string, &val_1, span)?;
|
||||||
enforce_add(cs, val_1, val_2, span)
|
enforce_add(cs, val_1, val_2, span)
|
||||||
}
|
}
|
||||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||||
format!("{} + {}", val_1, val_2),
|
format!("{} + {}", val_1, val_2),
|
||||||
span,
|
span.to_owned(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ pub fn enforce_div<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||||
@ -38,16 +38,16 @@ pub fn enforce_div<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
Ok(ConstrainedValue::Field(field_1.div(cs, &field_2, span)?))
|
Ok(ConstrainedValue::Field(field_1.div(cs, &field_2, span)?))
|
||||||
}
|
}
|
||||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
let val_1 = ConstrainedValue::from_other(string, &val_2, span)?;
|
||||||
enforce_div(cs, val_1, val_2, span)
|
enforce_div(cs, val_1, val_2, span)
|
||||||
}
|
}
|
||||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
let val_2 = ConstrainedValue::from_other(string, &val_1, span)?;
|
||||||
enforce_div(cs, val_1, val_2, span)
|
enforce_div(cs, val_1, val_2, span)
|
||||||
}
|
}
|
||||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||||
format!("{} / {}", val_1, val_2,),
|
format!("{} / {}", val_1, val_2,),
|
||||||
span,
|
span.to_owned(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ pub fn enforce_mul<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||||
@ -38,16 +38,16 @@ pub fn enforce_mul<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
Ok(ConstrainedValue::Field(field_1.mul(cs, &field_2, span)?))
|
Ok(ConstrainedValue::Field(field_1.mul(cs, &field_2, span)?))
|
||||||
}
|
}
|
||||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
let val_1 = ConstrainedValue::from_other(string, &val_2, span)?;
|
||||||
enforce_mul(cs, val_1, val_2, span)
|
enforce_mul(cs, val_1, val_2, span)
|
||||||
}
|
}
|
||||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
let val_2 = ConstrainedValue::from_other(string, &val_1, span)?;
|
||||||
enforce_mul(cs, val_1, val_2, span)
|
enforce_mul(cs, val_1, val_2, span)
|
||||||
}
|
}
|
||||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||||
format!("{} * {}", val_1, val_2),
|
format!("{} * {}", val_1, val_2),
|
||||||
span,
|
span.to_owned(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,15 @@ use snarkos_models::{
|
|||||||
pub fn enforce_negate<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
pub fn enforce_negate<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
value: ConstrainedValue<F, G>,
|
value: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
match value {
|
match value {
|
||||||
ConstrainedValue::Integer(integer) => Ok(ConstrainedValue::Integer(integer.negate(cs, span)?)),
|
ConstrainedValue::Integer(integer) => Ok(ConstrainedValue::Integer(integer.negate(cs, span)?)),
|
||||||
ConstrainedValue::Field(field) => Ok(ConstrainedValue::Field(field.negate(cs, span)?)),
|
ConstrainedValue::Field(field) => Ok(ConstrainedValue::Field(field.negate(cs, span)?)),
|
||||||
ConstrainedValue::Group(group) => Ok(ConstrainedValue::Group(group.negate(cs, span)?)),
|
ConstrainedValue::Group(group) => Ok(ConstrainedValue::Group(group.negate(cs, span)?)),
|
||||||
value => Err(ExpressionError::incompatible_types(format!("-{}", value), span)),
|
value => Err(ExpressionError::incompatible_types(
|
||||||
|
format!("-{}", value),
|
||||||
|
span.to_owned(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,23 +28,23 @@ pub fn enforce_pow<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||||
Ok(ConstrainedValue::Integer(num_1.pow(cs, num_2, span)?))
|
Ok(ConstrainedValue::Integer(num_1.pow(cs, num_2, span)?))
|
||||||
}
|
}
|
||||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
let val_1 = ConstrainedValue::from_other(string, &val_2, span)?;
|
||||||
enforce_pow(cs, val_1, val_2, span)
|
enforce_pow(cs, val_1, val_2, span)
|
||||||
}
|
}
|
||||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
let val_2 = ConstrainedValue::from_other(string, &val_1, span)?;
|
||||||
enforce_pow(cs, val_1, val_2, span)
|
enforce_pow(cs, val_1, val_2, span)
|
||||||
}
|
}
|
||||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||||
format!("{} ** {}", val_1, val_2,),
|
format!("{} ** {}", val_1, val_2,),
|
||||||
span,
|
span.to_owned(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ pub fn enforce_sub<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||||
@ -41,16 +41,16 @@ pub fn enforce_sub<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
Ok(ConstrainedValue::Group(point_1.sub(cs, &point_2, span)?))
|
Ok(ConstrainedValue::Group(point_1.sub(cs, &point_2, span)?))
|
||||||
}
|
}
|
||||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
let val_1 = ConstrainedValue::from_other(string, &val_2, &span)?;
|
||||||
enforce_sub(cs, val_1, val_2, span)
|
enforce_sub(cs, val_1, val_2, span)
|
||||||
}
|
}
|
||||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
let val_2 = ConstrainedValue::from_other(string, &val_1, &span)?;
|
||||||
enforce_sub(cs, val_1, val_2, span)
|
enforce_sub(cs, val_1, val_2, span)
|
||||||
}
|
}
|
||||||
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
(val_1, val_2) => Err(ExpressionError::incompatible_types(
|
||||||
format!("{} - {}", val_1, val_2),
|
format!("{} - {}", val_1, val_2),
|
||||||
span,
|
span.to_owned(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,31 +29,22 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_array_access<CS: ConstraintSystem<F>>(
|
pub fn enforce_array_access<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
array: Box<Expression>,
|
array: Box<Expression>,
|
||||||
index: RangeOrExpression,
|
index: RangeOrExpression,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
let array = match self.enforce_operand(
|
let array = match self.enforce_operand(cs, file_scope, function_scope, expected_type, *array, &span)? {
|
||||||
cs,
|
|
||||||
file_scope.clone(),
|
|
||||||
function_scope.clone(),
|
|
||||||
expected_type,
|
|
||||||
*array,
|
|
||||||
span.clone(),
|
|
||||||
)? {
|
|
||||||
ConstrainedValue::Array(array) => array,
|
ConstrainedValue::Array(array) => array,
|
||||||
value => return Err(ExpressionError::undefined_array(value.to_string(), span)),
|
value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())),
|
||||||
};
|
};
|
||||||
|
|
||||||
match index {
|
match index {
|
||||||
RangeOrExpression::Range(from, to) => {
|
RangeOrExpression::Range(from, to) => {
|
||||||
let from_resolved = match from {
|
let from_resolved = match from {
|
||||||
Some(from_index) => {
|
Some(from_index) => self.enforce_index(cs, file_scope, function_scope, from_index, span)?,
|
||||||
self.enforce_index(cs, file_scope.clone(), function_scope.clone(), from_index, span.clone())?
|
|
||||||
}
|
|
||||||
None => 0usize, // Array slice starts at index 0
|
None => 0usize, // Array slice starts at index 0
|
||||||
};
|
};
|
||||||
let to_resolved = match to {
|
let to_resolved = match to {
|
||||||
|
@ -34,8 +34,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_array<CS: ConstraintSystem<F>>(
|
pub fn enforce_array<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
mut expected_type: Option<Type>,
|
mut expected_type: Option<Type>,
|
||||||
array: Vec<SpreadOrExpression>,
|
array: Vec<SpreadOrExpression>,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -65,7 +65,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
match element {
|
match element {
|
||||||
SpreadOrExpression::Spread(spread) => match spread {
|
SpreadOrExpression::Spread(spread) => match spread {
|
||||||
Expression::Identifier(identifier) => {
|
Expression::Identifier(identifier) => {
|
||||||
let array_name = new_scope(function_scope.clone(), identifier.to_string());
|
let array_name = new_scope(&function_scope, &identifier.name);
|
||||||
match self.get(&array_name) {
|
match self.get(&array_name) {
|
||||||
Some(value) => match value {
|
Some(value) => match value {
|
||||||
ConstrainedValue::Array(array) => result.extend(array.clone()),
|
ConstrainedValue::Array(array) => result.extend(array.clone()),
|
||||||
@ -79,8 +79,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
SpreadOrExpression::Expression(expression) => {
|
SpreadOrExpression::Expression(expression) => {
|
||||||
result.push(self.enforce_expression(
|
result.push(self.enforce_expression(
|
||||||
cs,
|
cs,
|
||||||
file_scope.clone(),
|
file_scope,
|
||||||
function_scope.clone(),
|
function_scope,
|
||||||
expected_type.clone(),
|
expected_type.clone(),
|
||||||
expression,
|
expression,
|
||||||
)?);
|
)?);
|
||||||
|
@ -28,15 +28,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub(crate) fn enforce_index<CS: ConstraintSystem<F>>(
|
pub(crate) fn enforce_index<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
index: Expression,
|
index: Expression,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<usize, ExpressionError> {
|
) -> Result<usize, ExpressionError> {
|
||||||
let expected_type = Some(Type::IntegerType(IntegerType::U32));
|
let expected_type = Some(Type::IntegerType(IntegerType::U32));
|
||||||
match self.enforce_operand(cs, file_scope, function_scope, expected_type, index, span.clone())? {
|
match self.enforce_operand(cs, file_scope, function_scope, expected_type, index, &span)? {
|
||||||
ConstrainedValue::Integer(number) => Ok(number.to_usize(span)?),
|
ConstrainedValue::Integer(number) => Ok(number.to_usize(span)?),
|
||||||
value => Err(ExpressionError::invalid_index(value.to_string(), span)),
|
value => Err(ExpressionError::invalid_index(value.to_string(), span.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,29 +31,17 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_binary_expression<CS: ConstraintSystem<F>>(
|
pub fn enforce_binary_expression<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
left: Expression,
|
left: Expression,
|
||||||
right: Expression,
|
right: Expression,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValuePair<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValuePair<F, G>, ExpressionError> {
|
||||||
let mut resolved_left = self.enforce_operand(
|
let mut resolved_left =
|
||||||
cs,
|
self.enforce_operand(cs, file_scope, function_scope, expected_type.clone(), left, span)?;
|
||||||
file_scope.clone(),
|
let mut resolved_right =
|
||||||
function_scope.clone(),
|
self.enforce_operand(cs, file_scope, function_scope, expected_type.clone(), right, span)?;
|
||||||
expected_type.clone(),
|
|
||||||
left,
|
|
||||||
span.clone(),
|
|
||||||
)?;
|
|
||||||
let mut resolved_right = self.enforce_operand(
|
|
||||||
cs,
|
|
||||||
file_scope,
|
|
||||||
function_scope,
|
|
||||||
expected_type.clone(),
|
|
||||||
right,
|
|
||||||
span.clone(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
resolved_left.resolve_types(&mut resolved_right, expected_type, span)?;
|
resolved_left.resolve_types(&mut resolved_right, expected_type, span)?;
|
||||||
|
|
||||||
|
@ -31,11 +31,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_operand<CS: ConstraintSystem<F>>(
|
pub fn enforce_operand<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
let mut branch = self.enforce_expression(cs, file_scope, function_scope, expected_type.clone(), expression)?;
|
let mut branch = self.enforce_expression(cs, file_scope, function_scope, expected_type.clone(), expression)?;
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_circuit_access<CS: ConstraintSystem<F>>(
|
pub fn enforce_circuit_access<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
circuit_identifier: Box<Expression>,
|
circuit_identifier: Box<Expression>,
|
||||||
circuit_member: Identifier,
|
circuit_member: Identifier,
|
||||||
@ -46,11 +46,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
// access a circuit member using the `self` keyword
|
// access a circuit member using the `self` keyword
|
||||||
if let Expression::Identifier(ref identifier) = *circuit_identifier {
|
if let Expression::Identifier(ref identifier) = *circuit_identifier {
|
||||||
if identifier.is_self() {
|
if identifier.is_self() {
|
||||||
let self_file_scope = new_scope(file_scope, identifier.name.to_string());
|
let self_file_scope = new_scope(&file_scope, &identifier.name);
|
||||||
let self_function_scope = new_scope(self_file_scope.clone(), identifier.name.to_string());
|
let self_function_scope = new_scope(&self_file_scope, &identifier.name);
|
||||||
|
|
||||||
let member_value =
|
let member_value =
|
||||||
self.evaluate_identifier(self_file_scope, self_function_scope, None, circuit_member)?;
|
self.evaluate_identifier(&self_file_scope, &self_function_scope, None, circuit_member)?;
|
||||||
|
|
||||||
return Ok(member_value);
|
return Ok(member_value);
|
||||||
}
|
}
|
||||||
@ -58,11 +58,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
let (circuit_name, members) = match self.enforce_operand(
|
let (circuit_name, members) = match self.enforce_operand(
|
||||||
cs,
|
cs,
|
||||||
file_scope.clone(),
|
file_scope,
|
||||||
function_scope,
|
function_scope,
|
||||||
expected_type,
|
expected_type,
|
||||||
*circuit_identifier,
|
*circuit_identifier,
|
||||||
span.clone(),
|
&span,
|
||||||
)? {
|
)? {
|
||||||
ConstrainedValue::CircuitExpression(name, members) => (name, members),
|
ConstrainedValue::CircuitExpression(name, members) => (name, members),
|
||||||
value => return Err(ExpressionError::undefined_circuit(value.to_string(), span)),
|
value => return Err(ExpressionError::undefined_circuit(value.to_string(), span)),
|
||||||
@ -76,9 +76,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
ConstrainedValue::Function(ref _circuit_identifier, ref _function) => {
|
ConstrainedValue::Function(ref _circuit_identifier, ref _function) => {
|
||||||
// Pass circuit members into function call by value
|
// Pass circuit members into function call by value
|
||||||
for stored_member in members {
|
for stored_member in members {
|
||||||
let circuit_scope = new_scope(file_scope.clone(), circuit_name.to_string());
|
let circuit_scope = new_scope(&file_scope, &circuit_name.name);
|
||||||
let self_keyword = new_scope(circuit_scope, SELF_KEYWORD.to_string());
|
let self_keyword = new_scope(&circuit_scope, SELF_KEYWORD);
|
||||||
let variable = new_scope(self_keyword, stored_member.0.to_string());
|
let variable = new_scope(&self_keyword, &stored_member.0.name);
|
||||||
|
|
||||||
self.store(variable, stored_member.1.clone());
|
self.store(variable, stored_member.1.clone());
|
||||||
}
|
}
|
||||||
|
@ -33,22 +33,22 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_circuit<CS: ConstraintSystem<F>>(
|
pub fn enforce_circuit<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
members: Vec<CircuitVariableDefinition>,
|
members: Vec<CircuitVariableDefinition>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
// Circuit definitions are located at the minimum file scope
|
// Circuit definitions are located at the minimum file scope
|
||||||
let scopes: Vec<&str> = file_scope.split('_').collect();
|
let scopes: Vec<&str> = file_scope.split('_').collect();
|
||||||
let mut program_identifier = new_scope(scopes[0].to_string(), identifier.to_string());
|
let mut program_identifier = new_scope(scopes[0], &identifier.name);
|
||||||
|
|
||||||
if identifier.is_self() {
|
if identifier.is_self() {
|
||||||
program_identifier = file_scope.clone();
|
program_identifier = file_scope.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
let circuit = match self.get(&program_identifier) {
|
let circuit = match self.get(&program_identifier) {
|
||||||
Some(value) => value.clone().extract_circuit(span.clone())?,
|
Some(value) => value.clone().extract_circuit(&span)?,
|
||||||
None => return Err(ExpressionError::undefined_circuit(identifier.to_string(), span)),
|
None => return Err(ExpressionError::undefined_circuit(identifier.to_string(), span)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,8 +67,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
// Resolve and enforce circuit variable
|
// Resolve and enforce circuit variable
|
||||||
let mut variable_value = self.enforce_expression(
|
let mut variable_value = self.enforce_expression(
|
||||||
cs,
|
cs,
|
||||||
file_scope.clone(),
|
file_scope,
|
||||||
function_scope.clone(),
|
function_scope,
|
||||||
Some(type_.clone()),
|
Some(type_.clone()),
|
||||||
variable.expression,
|
variable.expression,
|
||||||
)?;
|
)?;
|
||||||
|
@ -29,8 +29,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_circuit_static_access<CS: ConstraintSystem<F>>(
|
pub fn enforce_circuit_static_access<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
circuit_identifier: Box<Expression>,
|
circuit_identifier: Box<Expression>,
|
||||||
circuit_member: Identifier,
|
circuit_member: Identifier,
|
||||||
@ -47,12 +47,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
circuit.to_owned()
|
circuit.to_owned()
|
||||||
} else {
|
} else {
|
||||||
self.evaluate_identifier(file_scope, function_scope, expected_type, identifier)?
|
self.evaluate_identifier(&file_scope, &function_scope, expected_type, identifier)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expression => self.enforce_expression(cs, file_scope, function_scope, expected_type, expression)?,
|
expression => self.enforce_expression(cs, file_scope, function_scope, expected_type, expression)?,
|
||||||
}
|
}
|
||||||
.extract_circuit(span.clone())?;
|
.extract_circuit(&span)?;
|
||||||
|
|
||||||
// Find static circuit function
|
// Find static circuit function
|
||||||
let matched_function = circuit.members.into_iter().find(|member| match member {
|
let matched_function = circuit.members.into_iter().find(|member| match member {
|
||||||
|
@ -30,35 +30,23 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_conditional_expression<CS: ConstraintSystem<F>>(
|
pub fn enforce_conditional_expression<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
conditional: Expression,
|
conditional: Expression,
|
||||||
first: Expression,
|
first: Expression,
|
||||||
second: Expression,
|
second: Expression,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
let conditional_value = match self.enforce_expression(
|
let conditional_value =
|
||||||
cs,
|
match self.enforce_expression(cs, file_scope, function_scope, Some(Type::Boolean), conditional)? {
|
||||||
file_scope.clone(),
|
ConstrainedValue::Boolean(resolved) => resolved,
|
||||||
function_scope.clone(),
|
value => return Err(ExpressionError::conditional_boolean(value.to_string(), span.to_owned())),
|
||||||
Some(Type::Boolean),
|
};
|
||||||
conditional,
|
|
||||||
)? {
|
|
||||||
ConstrainedValue::Boolean(resolved) => resolved,
|
|
||||||
value => return Err(ExpressionError::conditional_boolean(value.to_string(), span)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let first_value = self.enforce_operand(
|
let first_value = self.enforce_operand(cs, file_scope, function_scope, expected_type.clone(), first, span)?;
|
||||||
cs,
|
|
||||||
file_scope.clone(),
|
|
||||||
function_scope.clone(),
|
|
||||||
expected_type.clone(),
|
|
||||||
first,
|
|
||||||
span.clone(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let second_value = self.enforce_operand(cs, file_scope, function_scope, expected_type, second, span.clone())?;
|
let second_value = self.enforce_operand(cs, file_scope, function_scope, expected_type, second, span)?;
|
||||||
|
|
||||||
let unique_namespace = cs.ns(|| {
|
let unique_namespace = cs.ns(|| {
|
||||||
format!(
|
format!(
|
||||||
@ -68,6 +56,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ConstrainedValue::conditionally_select(unique_namespace, &conditional_value, &first_value, &second_value)
|
ConstrainedValue::conditionally_select(unique_namespace, &conditional_value, &first_value, &second_value)
|
||||||
.map_err(|e| ExpressionError::cannot_enforce("conditional select".to_string(), e, span))
|
.map_err(|e| ExpressionError::cannot_enforce("conditional select".to_string(), e, span.to_owned()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub(crate) fn enforce_expression<CS: ConstraintSystem<F>>(
|
pub(crate) fn enforce_expression<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
@ -51,21 +51,21 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Values
|
// Values
|
||||||
Expression::Address(address, span) => Ok(ConstrainedValue::Address(Address::constant(address, span)?)),
|
Expression::Address(address, span) => Ok(ConstrainedValue::Address(Address::constant(address, &span)?)),
|
||||||
Expression::Boolean(boolean, span) => Ok(ConstrainedValue::Boolean(new_bool_constant(boolean, span)?)),
|
Expression::Boolean(boolean, span) => Ok(ConstrainedValue::Boolean(new_bool_constant(boolean, &span)?)),
|
||||||
Expression::Field(field, span) => Ok(ConstrainedValue::Field(FieldType::constant(field, span)?)),
|
Expression::Field(field, span) => Ok(ConstrainedValue::Field(FieldType::constant(field, &span)?)),
|
||||||
Expression::Group(group_element) => Ok(ConstrainedValue::Group(G::constant(*group_element)?)),
|
Expression::Group(group_element) => Ok(ConstrainedValue::Group(G::constant(*group_element)?)),
|
||||||
Expression::Implicit(value, span) => Ok(enforce_number_implicit(expected_type, value, span)?),
|
Expression::Implicit(value, span) => Ok(enforce_number_implicit(expected_type, value, &span)?),
|
||||||
Expression::Integer(type_, integer, span) => {
|
Expression::Integer(type_, integer, span) => Ok(ConstrainedValue::Integer(Integer::new_constant(
|
||||||
Ok(ConstrainedValue::Integer(Integer::new_constant(&type_, integer, span)?))
|
&type_, integer, &span,
|
||||||
}
|
)?)),
|
||||||
|
|
||||||
// Binary operations
|
// Binary operations
|
||||||
Expression::Negate(expression, span) => {
|
Expression::Negate(expression, span) => {
|
||||||
let resolved_value =
|
let resolved_value =
|
||||||
self.enforce_expression(cs, file_scope, function_scope, expected_type, *expression)?;
|
self.enforce_expression(cs, file_scope, function_scope, expected_type, *expression)?;
|
||||||
|
|
||||||
enforce_negate(cs, resolved_value, span)
|
enforce_negate(cs, resolved_value, &span)
|
||||||
}
|
}
|
||||||
Expression::Add(left, right, span) => {
|
Expression::Add(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||||
@ -75,10 +75,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
expected_type,
|
expected_type,
|
||||||
*left,
|
*left,
|
||||||
*right,
|
*right,
|
||||||
span.clone(),
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
enforce_add(cs, resolved_left, resolved_right, span)
|
enforce_add(cs, resolved_left, resolved_right, &span)
|
||||||
}
|
}
|
||||||
Expression::Sub(left, right, span) => {
|
Expression::Sub(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||||
@ -88,10 +88,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
expected_type,
|
expected_type,
|
||||||
*left,
|
*left,
|
||||||
*right,
|
*right,
|
||||||
span.clone(),
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
enforce_sub(cs, resolved_left, resolved_right, span)
|
enforce_sub(cs, resolved_left, resolved_right, &span)
|
||||||
}
|
}
|
||||||
Expression::Mul(left, right, span) => {
|
Expression::Mul(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||||
@ -101,10 +101,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
expected_type,
|
expected_type,
|
||||||
*left,
|
*left,
|
||||||
*right,
|
*right,
|
||||||
span.clone(),
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
enforce_mul(cs, resolved_left, resolved_right, span)
|
enforce_mul(cs, resolved_left, resolved_right, &span)
|
||||||
}
|
}
|
||||||
Expression::Div(left, right, span) => {
|
Expression::Div(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||||
@ -114,10 +114,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
expected_type,
|
expected_type,
|
||||||
*left,
|
*left,
|
||||||
*right,
|
*right,
|
||||||
span.clone(),
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
enforce_div(cs, resolved_left, resolved_right, span)
|
enforce_div(cs, resolved_left, resolved_right, &span)
|
||||||
}
|
}
|
||||||
Expression::Pow(left, right, span) => {
|
Expression::Pow(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||||
@ -127,10 +127,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
expected_type,
|
expected_type,
|
||||||
*left,
|
*left,
|
||||||
*right,
|
*right,
|
||||||
span.clone(),
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
enforce_pow(cs, resolved_left, resolved_right, span)
|
enforce_pow(cs, resolved_left, resolved_right, &span)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boolean operations
|
// Boolean operations
|
||||||
@ -146,10 +146,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
expected_type,
|
expected_type,
|
||||||
*left,
|
*left,
|
||||||
*right,
|
*right,
|
||||||
span.clone(),
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(enforce_or(cs, resolved_left, resolved_right, span)?)
|
Ok(enforce_or(cs, resolved_left, resolved_right, &span)?)
|
||||||
}
|
}
|
||||||
Expression::And(left, right, span) => {
|
Expression::And(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||||
@ -159,40 +159,40 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
expected_type,
|
expected_type,
|
||||||
*left,
|
*left,
|
||||||
*right,
|
*right,
|
||||||
span.clone(),
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(enforce_and(cs, resolved_left, resolved_right, span)?)
|
Ok(enforce_and(cs, resolved_left, resolved_right, &span)?)
|
||||||
}
|
}
|
||||||
Expression::Eq(left, right, span) => {
|
Expression::Eq(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) =
|
let (resolved_left, resolved_right) =
|
||||||
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, span.clone())?;
|
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, &span)?;
|
||||||
|
|
||||||
Ok(evaluate_eq(cs, resolved_left, resolved_right, span)?)
|
Ok(evaluate_eq(cs, resolved_left, resolved_right, &span)?)
|
||||||
}
|
}
|
||||||
Expression::Ge(left, right, span) => {
|
Expression::Ge(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) =
|
let (resolved_left, resolved_right) =
|
||||||
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, span.clone())?;
|
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, &span)?;
|
||||||
|
|
||||||
Ok(evaluate_ge(cs, resolved_left, resolved_right, span)?)
|
Ok(evaluate_ge(cs, resolved_left, resolved_right, &span)?)
|
||||||
}
|
}
|
||||||
Expression::Gt(left, right, span) => {
|
Expression::Gt(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) =
|
let (resolved_left, resolved_right) =
|
||||||
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, span.clone())?;
|
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, &span)?;
|
||||||
|
|
||||||
Ok(evaluate_gt(cs, resolved_left, resolved_right, span)?)
|
Ok(evaluate_gt(cs, resolved_left, resolved_right, &span)?)
|
||||||
}
|
}
|
||||||
Expression::Le(left, right, span) => {
|
Expression::Le(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) =
|
let (resolved_left, resolved_right) =
|
||||||
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, span.clone())?;
|
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, &span)?;
|
||||||
|
|
||||||
Ok(evaluate_le(cs, resolved_left, resolved_right, span)?)
|
Ok(evaluate_le(cs, resolved_left, resolved_right, &span)?)
|
||||||
}
|
}
|
||||||
Expression::Lt(left, right, span) => {
|
Expression::Lt(left, right, span) => {
|
||||||
let (resolved_left, resolved_right) =
|
let (resolved_left, resolved_right) =
|
||||||
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, span.clone())?;
|
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, &span)?;
|
||||||
|
|
||||||
Ok(evaluate_lt(cs, resolved_left, resolved_right, span)?)
|
Ok(evaluate_lt(cs, resolved_left, resolved_right, &span)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conditionals
|
// Conditionals
|
||||||
@ -204,7 +204,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
*conditional,
|
*conditional,
|
||||||
*first,
|
*first,
|
||||||
*second,
|
*second,
|
||||||
span,
|
&span,
|
||||||
),
|
),
|
||||||
|
|
||||||
// Arrays
|
// Arrays
|
||||||
@ -212,7 +212,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
self.enforce_array(cs, file_scope, function_scope, expected_type, array, span)
|
self.enforce_array(cs, file_scope, function_scope, expected_type, array, span)
|
||||||
}
|
}
|
||||||
Expression::ArrayAccess(array, index, span) => {
|
Expression::ArrayAccess(array, index, span) => {
|
||||||
self.enforce_array_access(cs, file_scope, function_scope, expected_type, array, *index, span)
|
self.enforce_array_access(cs, file_scope, function_scope, expected_type, array, *index, &span)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tuples
|
// Tuples
|
||||||
@ -220,7 +220,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
self.enforce_tuple(cs, file_scope, function_scope, expected_type, tuple, span)
|
self.enforce_tuple(cs, file_scope, function_scope, expected_type, tuple, span)
|
||||||
}
|
}
|
||||||
Expression::TupleAccess(tuple, index, span) => {
|
Expression::TupleAccess(tuple, index, span) => {
|
||||||
self.enforce_tuple_access(cs, file_scope, function_scope, expected_type, tuple, index, span)
|
self.enforce_tuple_access(cs, file_scope, function_scope, expected_type, tuple, index, &span)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Circuits
|
// Circuits
|
||||||
|
@ -29,8 +29,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_core_circuit_call_expression<CS: ConstraintSystem<F>>(
|
pub fn enforce_core_circuit_call_expression<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
core_circuit: String,
|
core_circuit: String,
|
||||||
arguments: Vec<Expression>,
|
arguments: Vec<Expression>,
|
||||||
@ -39,8 +39,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
// Get the value of each core function argument
|
// Get the value of each core function argument
|
||||||
let mut argument_values = Vec::with_capacity(arguments.len());
|
let mut argument_values = Vec::with_capacity(arguments.len());
|
||||||
for argument in arguments.into_iter() {
|
for argument in arguments.into_iter() {
|
||||||
let argument_value =
|
let argument_value = self.enforce_expression(cs, file_scope, function_scope, None, argument)?;
|
||||||
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), None, argument)?;
|
|
||||||
let core_function_argument = argument_value.to_value();
|
let core_function_argument = argument_value.to_value();
|
||||||
|
|
||||||
argument_values.push(core_function_argument);
|
argument_values.push(core_function_argument);
|
||||||
@ -62,7 +61,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
// Check that function returns expected type
|
// Check that function returns expected type
|
||||||
if let Some(expected) = expected_type {
|
if let Some(expected) = expected_type {
|
||||||
let actual = return_value.to_type(span.clone())?;
|
let actual = return_value.to_type(&span)?;
|
||||||
if expected.ne(&actual) {
|
if expected.ne(&actual) {
|
||||||
return Err(ExpressionError::FunctionError(Box::new(
|
return Err(ExpressionError::FunctionError(Box::new(
|
||||||
FunctionError::return_argument_type(expected.to_string(), actual.to_string(), span),
|
FunctionError::return_argument_type(expected.to_string(), actual.to_string(), span),
|
||||||
|
@ -29,8 +29,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_function_call_expression<CS: ConstraintSystem<F>>(
|
pub fn enforce_function_call_expression<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
function: Box<Expression>,
|
function: Box<Expression>,
|
||||||
arguments: Vec<Expression>,
|
arguments: Vec<Expression>,
|
||||||
@ -41,15 +41,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
// Call a circuit function that can mutate self.
|
// Call a circuit function that can mutate self.
|
||||||
|
|
||||||
// Save a reference to the circuit we are mutating.
|
// Save a reference to the circuit we are mutating.
|
||||||
let circuit_id_string = format!("{}", circuit_identifier);
|
let circuit_id_string = circuit_identifier.to_string();
|
||||||
let declared_circuit_reference = new_scope(function_scope.clone(), circuit_id_string);
|
let declared_circuit_reference = new_scope(&function_scope, &circuit_id_string);
|
||||||
|
|
||||||
(
|
(
|
||||||
declared_circuit_reference,
|
declared_circuit_reference,
|
||||||
self.enforce_circuit_access(
|
self.enforce_circuit_access(
|
||||||
cs,
|
cs,
|
||||||
file_scope.clone(),
|
file_scope,
|
||||||
function_scope.clone(),
|
function_scope,
|
||||||
expected_type,
|
expected_type,
|
||||||
circuit_identifier,
|
circuit_identifier,
|
||||||
circuit_member,
|
circuit_member,
|
||||||
@ -58,12 +58,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
function => (
|
function => (
|
||||||
function_scope.clone(),
|
function_scope.to_string(),
|
||||||
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_type, function)?,
|
self.enforce_expression(cs, file_scope, function_scope, expected_type, function)?,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (outer_scope, function_call) = function_value.extract_function(file_scope, span.clone())?;
|
let (outer_scope, function_call) = function_value.extract_function(file_scope, &span)?;
|
||||||
|
|
||||||
let name_unique = format!(
|
let name_unique = format!(
|
||||||
"function call {} {}:{}",
|
"function call {} {}:{}",
|
||||||
@ -74,11 +74,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
self.enforce_function(
|
self.enforce_function(
|
||||||
&mut cs.ns(|| name_unique),
|
&mut cs.ns(|| name_unique),
|
||||||
outer_scope,
|
&outer_scope,
|
||||||
function_scope,
|
function_scope,
|
||||||
function_call,
|
function_call,
|
||||||
arguments,
|
arguments,
|
||||||
declared_circuit_reference,
|
&declared_circuit_reference,
|
||||||
)
|
)
|
||||||
.map_err(|error| ExpressionError::from(Box::new(error)))
|
.map_err(|error| ExpressionError::from(Box::new(error)))
|
||||||
}
|
}
|
||||||
|
@ -31,14 +31,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
/// Enforce a variable expression by getting the resolved value
|
/// Enforce a variable expression by getting the resolved value
|
||||||
pub fn evaluate_identifier(
|
pub fn evaluate_identifier(
|
||||||
&mut self,
|
&mut self,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
unresolved_identifier: Identifier,
|
unresolved_identifier: Identifier,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
// Evaluate the identifier name in the current function scope
|
// Evaluate the identifier name in the current function scope
|
||||||
let variable_name = new_scope(function_scope, unresolved_identifier.to_string());
|
let variable_name = new_scope(function_scope, &unresolved_identifier.name);
|
||||||
let identifier_name = new_scope(file_scope, unresolved_identifier.to_string());
|
let identifier_name = new_scope(file_scope, &unresolved_identifier.name);
|
||||||
|
|
||||||
let mut result_value = if let Some(value) = self.get(&variable_name) {
|
let mut result_value = if let Some(value) = self.get(&variable_name) {
|
||||||
// Reassigning variable to another variable
|
// Reassigning variable to another variable
|
||||||
@ -51,14 +51,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
value.clone()
|
value.clone()
|
||||||
} else if expected_type.is_some() && expected_type.unwrap() == Type::Address {
|
} else if expected_type.is_some() && expected_type.unwrap() == Type::Address {
|
||||||
// If we expect an address type, try to return an address
|
// If we expect an address type, try to return an address
|
||||||
let address = Address::constant(unresolved_identifier.name, unresolved_identifier.span)?;
|
let address = Address::constant(unresolved_identifier.name, &unresolved_identifier.span)?;
|
||||||
|
|
||||||
return Ok(ConstrainedValue::Address(address));
|
return Ok(ConstrainedValue::Address(address));
|
||||||
} else {
|
} else {
|
||||||
return Err(ExpressionError::undefined_identifier(unresolved_identifier));
|
return Err(ExpressionError::undefined_identifier(unresolved_identifier));
|
||||||
};
|
};
|
||||||
|
|
||||||
result_value.resolve_type(expected_type, unresolved_identifier.span)?;
|
result_value.resolve_type(expected_type, &unresolved_identifier.span)?;
|
||||||
|
|
||||||
Ok(result_value)
|
Ok(result_value)
|
||||||
}
|
}
|
||||||
|
@ -28,17 +28,17 @@ pub fn enforce_and<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
||||||
let name = format!("{} && {}", left, right);
|
let name = format!("{} && {}", left, right);
|
||||||
|
|
||||||
if let (ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) = (left, right) {
|
if let (ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) = (left, right) {
|
||||||
let name_unique = format!("{} {}:{}", name, span.line, span.start);
|
let name_unique = format!("{} {}:{}", name, span.line, span.start);
|
||||||
let result = Boolean::and(cs.ns(|| name_unique), &left_bool, &right_bool)
|
let result = Boolean::and(cs.ns(|| name_unique), &left_bool, &right_bool)
|
||||||
.map_err(|e| BooleanError::cannot_enforce("&&".to_string(), e, span))?;
|
.map_err(|e| BooleanError::cannot_enforce("&&".to_string(), e, span.to_owned()))?;
|
||||||
|
|
||||||
return Ok(ConstrainedValue::Boolean(result));
|
return Ok(ConstrainedValue::Boolean(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(BooleanError::cannot_evaluate(name, span))
|
Err(BooleanError::cannot_evaluate(name, span.to_owned()))
|
||||||
}
|
}
|
||||||
|
@ -28,17 +28,17 @@ pub fn enforce_or<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
||||||
let name = format!("{} || {}", left, right);
|
let name = format!("{} || {}", left, right);
|
||||||
|
|
||||||
if let (ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) = (left, right) {
|
if let (ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) = (left, right) {
|
||||||
let name_unique = format!("{} {}:{}", name, span.line, span.start);
|
let name_unique = format!("{} {}:{}", name, span.line, span.start);
|
||||||
let result = Boolean::or(cs.ns(|| name_unique), &left_bool, &right_bool)
|
let result = Boolean::or(cs.ns(|| name_unique), &left_bool, &right_bool)
|
||||||
.map_err(|e| BooleanError::cannot_enforce("||".to_string(), e, span))?;
|
.map_err(|e| BooleanError::cannot_enforce("||".to_string(), e, span.to_owned()))?;
|
||||||
|
|
||||||
return Ok(ConstrainedValue::Boolean(result));
|
return Ok(ConstrainedValue::Boolean(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(BooleanError::cannot_evaluate(name, span))
|
Err(BooleanError::cannot_evaluate(name, span.to_owned()))
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ pub fn evaluate_eq<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
let namespace_string = format!("evaluate {} == {} {}:{}", left, right, span.line, span.start);
|
let namespace_string = format!("evaluate {} == {} {}:{}", left, right, span.line, span.start);
|
||||||
let constraint_result = match (left, right) {
|
let constraint_result = match (left, right) {
|
||||||
@ -58,14 +58,9 @@ pub fn evaluate_eq<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
(ConstrainedValue::Array(arr_1), ConstrainedValue::Array(arr_2)) => {
|
(ConstrainedValue::Array(arr_1), ConstrainedValue::Array(arr_2)) => {
|
||||||
let mut current = ConstrainedValue::Boolean(Boolean::constant(true));
|
let mut current = ConstrainedValue::Boolean(Boolean::constant(true));
|
||||||
for (i, (left, right)) in arr_1.into_iter().zip(arr_2.into_iter()).enumerate() {
|
for (i, (left, right)) in arr_1.into_iter().zip(arr_2.into_iter()).enumerate() {
|
||||||
let next = evaluate_eq(&mut cs.ns(|| format!("array[{}]", i)), left, right, span.clone())?;
|
let next = evaluate_eq(&mut cs.ns(|| format!("array[{}]", i)), left, right, span)?;
|
||||||
|
|
||||||
current = enforce_and(
|
current = enforce_and(&mut cs.ns(|| format!("array result {}", i)), current, next, span)?;
|
||||||
&mut cs.ns(|| format!("array result {}", i)),
|
|
||||||
current,
|
|
||||||
next,
|
|
||||||
span.clone(),
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
return Ok(current);
|
return Ok(current);
|
||||||
}
|
}
|
||||||
@ -73,36 +68,31 @@ pub fn evaluate_eq<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
let mut current = ConstrainedValue::Boolean(Boolean::constant(true));
|
let mut current = ConstrainedValue::Boolean(Boolean::constant(true));
|
||||||
|
|
||||||
for (i, (left, right)) in tuple_1.into_iter().zip(tuple_2.into_iter()).enumerate() {
|
for (i, (left, right)) in tuple_1.into_iter().zip(tuple_2.into_iter()).enumerate() {
|
||||||
let next = evaluate_eq(&mut cs.ns(|| format!("tuple_index {}", i)), left, right, span.clone())?;
|
let next = evaluate_eq(&mut cs.ns(|| format!("tuple_index {}", i)), left, right, span)?;
|
||||||
|
|
||||||
current = enforce_and(
|
current = enforce_and(&mut cs.ns(|| format!("array result {}", i)), current, next, span)?;
|
||||||
&mut cs.ns(|| format!("array result {}", i)),
|
|
||||||
current,
|
|
||||||
next,
|
|
||||||
span.clone(),
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
return Ok(current);
|
return Ok(current);
|
||||||
}
|
}
|
||||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||||
let mut unique_namespace = cs.ns(|| namespace_string);
|
let mut unique_namespace = cs.ns(|| namespace_string);
|
||||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
let val_1 = ConstrainedValue::from_other(string, &val_2, span)?;
|
||||||
return evaluate_eq(&mut unique_namespace, val_1, val_2, span);
|
return evaluate_eq(&mut unique_namespace, val_1, val_2, span);
|
||||||
}
|
}
|
||||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||||
let mut unique_namespace = cs.ns(|| namespace_string);
|
let mut unique_namespace = cs.ns(|| namespace_string);
|
||||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
let val_2 = ConstrainedValue::from_other(string, &val_1, span)?;
|
||||||
return evaluate_eq(&mut unique_namespace, val_1, val_2, span);
|
return evaluate_eq(&mut unique_namespace, val_1, val_2, span);
|
||||||
}
|
}
|
||||||
(val_1, val_2) => {
|
(val_1, val_2) => {
|
||||||
return Err(ExpressionError::incompatible_types(
|
return Err(ExpressionError::incompatible_types(
|
||||||
format!("{} == {}", val_1, val_2,),
|
format!("{} == {}", val_1, val_2,),
|
||||||
span,
|
span.to_owned(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate("==".to_string(), span))?;
|
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate("==".to_string(), span.to_owned()))?;
|
||||||
|
|
||||||
Ok(ConstrainedValue::Boolean(boolean))
|
Ok(ConstrainedValue::Boolean(boolean))
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ pub fn evaluate_ge<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} >= {} {}:{}", left, right, span.line, span.start));
|
let mut unique_namespace = cs.ns(|| format!("evaluate {} >= {} {}:{}", left, right, span.line, span.start));
|
||||||
let constraint_result = match (left, right) {
|
let constraint_result = match (left, right) {
|
||||||
@ -37,22 +37,22 @@ pub fn evaluate_ge<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
num_1.greater_than_or_equal(unique_namespace, &num_2)
|
num_1.greater_than_or_equal(unique_namespace, &num_2)
|
||||||
}
|
}
|
||||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
let val_1 = ConstrainedValue::from_other(string, &val_2, span)?;
|
||||||
return evaluate_ge(&mut unique_namespace, val_1, val_2, span);
|
return evaluate_ge(&mut unique_namespace, val_1, val_2, span);
|
||||||
}
|
}
|
||||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
let val_2 = ConstrainedValue::from_other(string, &val_1, span)?;
|
||||||
return evaluate_ge(&mut unique_namespace, val_1, val_2, span);
|
return evaluate_ge(&mut unique_namespace, val_1, val_2, span);
|
||||||
}
|
}
|
||||||
(val_1, val_2) => {
|
(val_1, val_2) => {
|
||||||
return Err(ExpressionError::incompatible_types(
|
return Err(ExpressionError::incompatible_types(
|
||||||
format!("{} >= {}", val_1, val_2),
|
format!("{} >= {}", val_1, val_2),
|
||||||
span,
|
span.to_owned(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(">=".to_string(), span))?;
|
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(">=".to_string(), span.to_owned()))?;
|
||||||
|
|
||||||
Ok(ConstrainedValue::Boolean(boolean))
|
Ok(ConstrainedValue::Boolean(boolean))
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ pub fn evaluate_gt<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} > {} {}:{}", left, right, span.line, span.start));
|
let mut unique_namespace = cs.ns(|| format!("evaluate {} > {} {}:{}", left, right, span.line, span.start));
|
||||||
let constraint_result = match (left, right) {
|
let constraint_result = match (left, right) {
|
||||||
@ -37,22 +37,22 @@ pub fn evaluate_gt<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
num_1.greater_than(unique_namespace, &num_2)
|
num_1.greater_than(unique_namespace, &num_2)
|
||||||
}
|
}
|
||||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
let val_1 = ConstrainedValue::from_other(string, &val_2, span)?;
|
||||||
return evaluate_gt(&mut unique_namespace, val_1, val_2, span);
|
return evaluate_gt(&mut unique_namespace, val_1, val_2, span);
|
||||||
}
|
}
|
||||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
let val_2 = ConstrainedValue::from_other(string, &val_1, span)?;
|
||||||
return evaluate_gt(&mut unique_namespace, val_1, val_2, span);
|
return evaluate_gt(&mut unique_namespace, val_1, val_2, span);
|
||||||
}
|
}
|
||||||
(val_1, val_2) => {
|
(val_1, val_2) => {
|
||||||
return Err(ExpressionError::incompatible_types(
|
return Err(ExpressionError::incompatible_types(
|
||||||
format!("{} > {}", val_1, val_2),
|
format!("{} > {}", val_1, val_2),
|
||||||
span,
|
span.to_owned(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(">".to_string(), span))?;
|
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(">".to_string(), span.to_owned()))?;
|
||||||
|
|
||||||
Ok(ConstrainedValue::Boolean(boolean))
|
Ok(ConstrainedValue::Boolean(boolean))
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ pub fn evaluate_le<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} <= {} {}:{}", left, right, span.line, span.start));
|
let mut unique_namespace = cs.ns(|| format!("evaluate {} <= {} {}:{}", left, right, span.line, span.start));
|
||||||
let constraint_result = match (left, right) {
|
let constraint_result = match (left, right) {
|
||||||
@ -37,22 +37,22 @@ pub fn evaluate_le<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
num_1.less_than_or_equal(unique_namespace, &num_2)
|
num_1.less_than_or_equal(unique_namespace, &num_2)
|
||||||
}
|
}
|
||||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
let val_1 = ConstrainedValue::from_other(string, &val_2, span)?;
|
||||||
return evaluate_le(&mut unique_namespace, val_1, val_2, span);
|
return evaluate_le(&mut unique_namespace, val_1, val_2, span);
|
||||||
}
|
}
|
||||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
let val_2 = ConstrainedValue::from_other(string, &val_1, span)?;
|
||||||
return evaluate_le(&mut unique_namespace, val_1, val_2, span);
|
return evaluate_le(&mut unique_namespace, val_1, val_2, span);
|
||||||
}
|
}
|
||||||
(val_1, val_2) => {
|
(val_1, val_2) => {
|
||||||
return Err(ExpressionError::incompatible_types(
|
return Err(ExpressionError::incompatible_types(
|
||||||
format!("{} <= {}", val_1, val_2),
|
format!("{} <= {}", val_1, val_2),
|
||||||
span,
|
span.to_owned(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate("<=".to_string(), span))?;
|
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate("<=".to_string(), span.to_owned()))?;
|
||||||
|
|
||||||
Ok(ConstrainedValue::Boolean(boolean))
|
Ok(ConstrainedValue::Boolean(boolean))
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ pub fn evaluate_lt<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
left: ConstrainedValue<F, G>,
|
left: ConstrainedValue<F, G>,
|
||||||
right: ConstrainedValue<F, G>,
|
right: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} < {} {}:{}", left, right, span.line, span.start));
|
let mut unique_namespace = cs.ns(|| format!("evaluate {} < {} {}:{}", left, right, span.line, span.start));
|
||||||
let constraint_result = match (left, right) {
|
let constraint_result = match (left, right) {
|
||||||
@ -37,22 +37,22 @@ pub fn evaluate_lt<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
|
|||||||
num_1.less_than(unique_namespace, &num_2)
|
num_1.less_than(unique_namespace, &num_2)
|
||||||
}
|
}
|
||||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
let val_1 = ConstrainedValue::from_other(string, &val_2, span)?;
|
||||||
return evaluate_lt(&mut unique_namespace, val_1, val_2, span);
|
return evaluate_lt(&mut unique_namespace, val_1, val_2, span);
|
||||||
}
|
}
|
||||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
let val_2 = ConstrainedValue::from_other(string, &val_1, span)?;
|
||||||
return evaluate_lt(&mut unique_namespace, val_1, val_2, span);
|
return evaluate_lt(&mut unique_namespace, val_1, val_2, span);
|
||||||
}
|
}
|
||||||
(val_1, val_2) => {
|
(val_1, val_2) => {
|
||||||
return Err(ExpressionError::incompatible_types(
|
return Err(ExpressionError::incompatible_types(
|
||||||
format!("{} < {}", val_1, val_2),
|
format!("{} < {}", val_1, val_2),
|
||||||
span,
|
span.to_owned(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate("<".to_string(), span))?;
|
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate("<".to_string(), span.to_owned()))?;
|
||||||
|
|
||||||
Ok(ConstrainedValue::Boolean(boolean))
|
Ok(ConstrainedValue::Boolean(boolean))
|
||||||
}
|
}
|
||||||
|
@ -29,20 +29,20 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_tuple_access<CS: ConstraintSystem<F>>(
|
pub fn enforce_tuple_access<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
tuple: Box<Expression>,
|
tuple: Box<Expression>,
|
||||||
index: usize,
|
index: usize,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||||
let tuple = match self.enforce_operand(cs, file_scope, function_scope, expected_type, *tuple, span.clone())? {
|
let tuple = match self.enforce_operand(cs, file_scope, function_scope, expected_type, *tuple, &span)? {
|
||||||
ConstrainedValue::Tuple(tuple) => tuple,
|
ConstrainedValue::Tuple(tuple) => tuple,
|
||||||
value => return Err(ExpressionError::undefined_array(value.to_string(), span)),
|
value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())),
|
||||||
};
|
};
|
||||||
|
|
||||||
if index > tuple.len() - 1 {
|
if index > tuple.len() - 1 {
|
||||||
return Err(ExpressionError::index_out_of_bounds(index, span));
|
return Err(ExpressionError::index_out_of_bounds(index, span.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(tuple[index].to_owned())
|
Ok(tuple[index].to_owned())
|
||||||
|
@ -29,8 +29,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_tuple<CS: ConstraintSystem<F>>(
|
pub fn enforce_tuple<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
tuple: Vec<Expression>,
|
tuple: Vec<Expression>,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -60,7 +60,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
Some(expected_types[i].clone())
|
Some(expected_types[i].clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
result.push(self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), type_, expression)?);
|
result.push(self.enforce_expression(cs, file_scope, function_scope, type_, expression)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ConstrainedValue::Tuple(result))
|
Ok(ConstrainedValue::Tuple(result))
|
||||||
|
@ -30,10 +30,10 @@ use snarkos_models::{
|
|||||||
gadgets::r1cs::ConstraintSystem,
|
gadgets::r1cs::ConstraintSystem,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn check_arguments_length(expected: usize, actual: usize, span: Span) -> Result<(), FunctionError> {
|
pub fn check_arguments_length(expected: usize, actual: usize, span: &Span) -> Result<(), FunctionError> {
|
||||||
// Make sure we are given the correct number of arguments
|
// Make sure we are given the correct number of arguments
|
||||||
if expected != actual {
|
if expected != actual {
|
||||||
Err(FunctionError::arguments_length(expected, actual, span))
|
Err(FunctionError::arguments_length(expected, actual, span.to_owned()))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -43,39 +43,33 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub(crate) fn enforce_function<CS: ConstraintSystem<F>>(
|
pub(crate) fn enforce_function<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
scope: String,
|
scope: &str,
|
||||||
caller_scope: String,
|
caller_scope: &str,
|
||||||
function: Function,
|
function: Function,
|
||||||
input: Vec<Expression>,
|
input: Vec<Expression>,
|
||||||
declared_circuit_reference: String,
|
declared_circuit_reference: &str,
|
||||||
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
||||||
let function_name = new_scope(scope.clone(), function.get_name());
|
let function_name = new_scope(scope, function.get_name());
|
||||||
|
|
||||||
// Make sure we are given the correct number of input variables
|
// Make sure we are given the correct number of input variables
|
||||||
check_arguments_length(function.input.len(), input.len(), function.span.clone())?;
|
check_arguments_length(function.input.len(), input.len(), &function.span)?;
|
||||||
|
|
||||||
// Store input values as new variables in resolved program
|
// Store input values as new variables in resolved program
|
||||||
for (input_model, input_expression) in function.input.iter().zip(input.into_iter()) {
|
for (input_model, input_expression) in function.input.iter().zip(input.into_iter()) {
|
||||||
let (name, value) = match input_model {
|
let (name, value) = match input_model {
|
||||||
InputVariable::InputKeyword(identifier) => {
|
InputVariable::InputKeyword(identifier) => {
|
||||||
let input_value = self.enforce_function_input(
|
let input_value =
|
||||||
cs,
|
self.enforce_function_input(cs, scope, caller_scope, &function_name, None, input_expression)?;
|
||||||
scope.clone(),
|
|
||||||
caller_scope.clone(),
|
|
||||||
function_name.clone(),
|
|
||||||
None,
|
|
||||||
input_expression,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
(identifier.name.clone(), input_value)
|
(&identifier.name, input_value)
|
||||||
}
|
}
|
||||||
InputVariable::FunctionInput(input_model) => {
|
InputVariable::FunctionInput(input_model) => {
|
||||||
// First evaluate input expression
|
// First evaluate input expression
|
||||||
let mut input_value = self.enforce_function_input(
|
let mut input_value = self.enforce_function_input(
|
||||||
cs,
|
cs,
|
||||||
scope.clone(),
|
scope,
|
||||||
caller_scope.clone(),
|
caller_scope,
|
||||||
function_name.clone(),
|
&function_name,
|
||||||
Some(input_model.type_.clone()),
|
Some(input_model.type_.clone()),
|
||||||
input_expression,
|
input_expression,
|
||||||
)?;
|
)?;
|
||||||
@ -84,12 +78,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
input_value = ConstrainedValue::Mutable(Box::new(input_value))
|
input_value = ConstrainedValue::Mutable(Box::new(input_value))
|
||||||
}
|
}
|
||||||
|
|
||||||
(input_model.identifier.name.clone(), input_value)
|
(&input_model.identifier.name, input_value)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store input as variable with {function_name}_{input_name}
|
// Store input as variable with {function_name}_{input_name}
|
||||||
let input_program_identifier = new_scope(function_name.clone(), name);
|
let input_program_identifier = new_scope(&function_name, &name);
|
||||||
self.store(input_program_identifier, value);
|
self.store(input_program_identifier, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,12 +93,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
for statement in function.statements.iter() {
|
for statement in function.statements.iter() {
|
||||||
let mut result = self.enforce_statement(
|
let mut result = self.enforce_statement(
|
||||||
cs,
|
cs,
|
||||||
scope.clone(),
|
scope,
|
||||||
function_name.clone(),
|
&function_name,
|
||||||
None,
|
None,
|
||||||
statement.clone(),
|
statement.clone(),
|
||||||
function.returns.clone(),
|
function.returns.clone(),
|
||||||
declared_circuit_reference.clone(),
|
declared_circuit_reference,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
results.append(&mut result);
|
results.append(&mut result);
|
||||||
@ -113,7 +107,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
// Conditionally select a result based on returned indicators
|
// Conditionally select a result based on returned indicators
|
||||||
let mut return_values = ConstrainedValue::Tuple(vec![]);
|
let mut return_values = ConstrainedValue::Tuple(vec![]);
|
||||||
|
|
||||||
Self::conditionally_select_result(cs, &mut return_values, results, function.span.clone())?;
|
Self::conditionally_select_result(cs, &mut return_values, results, &function.span)?;
|
||||||
|
|
||||||
if let ConstrainedValue::Tuple(ref returns) = return_values {
|
if let ConstrainedValue::Tuple(ref returns) = return_values {
|
||||||
let return_types = match function.returns {
|
let return_types = match function.returns {
|
||||||
|
@ -34,11 +34,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn allocate_array<CS: ConstraintSystem<F>>(
|
pub fn allocate_array<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
name: String,
|
name: &str,
|
||||||
array_type: Type,
|
array_type: Type,
|
||||||
array_dimensions: Vec<usize>,
|
array_dimensions: Vec<usize>,
|
||||||
input_value: Option<InputValue>,
|
input_value: Option<InputValue>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
||||||
let expected_length = array_dimensions[0];
|
let expected_length = array_dimensions[0];
|
||||||
let mut array_value = vec![];
|
let mut array_value = vec![];
|
||||||
@ -47,34 +47,33 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
Some(InputValue::Array(arr)) => {
|
Some(InputValue::Array(arr)) => {
|
||||||
// Allocate each value in the current row
|
// Allocate each value in the current row
|
||||||
for (i, value) in arr.into_iter().enumerate() {
|
for (i, value) in arr.into_iter().enumerate() {
|
||||||
let value_name = new_scope(name.clone(), i.to_string());
|
let value_name = new_scope(&name, &i.to_string());
|
||||||
let value_type = array_type.outer_dimension(&array_dimensions);
|
let value_type = array_type.outer_dimension(&array_dimensions);
|
||||||
|
|
||||||
array_value.push(self.allocate_main_function_input(
|
array_value.push(self.allocate_main_function_input(
|
||||||
cs,
|
cs,
|
||||||
value_type,
|
value_type,
|
||||||
value_name,
|
&value_name,
|
||||||
Some(value),
|
Some(value),
|
||||||
span.clone(),
|
span,
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Allocate all row values as none
|
// Allocate all row values as none
|
||||||
for i in 0..expected_length {
|
for i in 0..expected_length {
|
||||||
let value_name = new_scope(name.clone(), i.to_string());
|
let value_name = new_scope(&name, &i.to_string());
|
||||||
let value_type = array_type.outer_dimension(&array_dimensions);
|
let value_type = array_type.outer_dimension(&array_dimensions);
|
||||||
|
|
||||||
array_value.push(self.allocate_main_function_input(
|
array_value.push(self.allocate_main_function_input(cs, value_type, &value_name, None, span)?);
|
||||||
cs,
|
|
||||||
value_type,
|
|
||||||
value_name,
|
|
||||||
None,
|
|
||||||
span.clone(),
|
|
||||||
)?);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return Err(FunctionError::invalid_array(input_value.unwrap().to_string(), span)),
|
_ => {
|
||||||
|
return Err(FunctionError::invalid_array(
|
||||||
|
input_value.unwrap().to_string(),
|
||||||
|
span.to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ConstrainedValue::Array(array_value))
|
Ok(ConstrainedValue::Array(array_value))
|
||||||
|
@ -29,9 +29,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_function_input<CS: ConstraintSystem<F>>(
|
pub fn enforce_function_input<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
scope: String,
|
scope: &str,
|
||||||
caller_scope: String,
|
caller_scope: &str,
|
||||||
function_name: String,
|
function_name: &str,
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
input: Expression,
|
input: Expression,
|
||||||
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
||||||
|
@ -39,9 +39,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
let member_value = self.allocate_main_function_input(
|
let member_value = self.allocate_main_function_input(
|
||||||
cs,
|
cs,
|
||||||
parameter.type_,
|
parameter.type_,
|
||||||
parameter.variable.name,
|
¶meter.variable.name,
|
||||||
option,
|
option,
|
||||||
parameter.span,
|
¶meter.span,
|
||||||
)?;
|
)?;
|
||||||
let member = ConstrainedCircuitMember(member_name, member_value);
|
let member = ConstrainedCircuitMember(member_name, member_value);
|
||||||
|
|
||||||
|
@ -42,9 +42,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
type_: Type,
|
type_: Type,
|
||||||
name: String,
|
name: &str,
|
||||||
input_option: Option<InputValue>,
|
input_option: Option<InputValue>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
||||||
match type_ {
|
match type_ {
|
||||||
Type::Address => Ok(Address::from_input(cs, name, input_option, span)?),
|
Type::Address => Ok(Address::from_input(cs, name, input_option, span)?),
|
||||||
@ -59,7 +59,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
span,
|
span,
|
||||||
)?)),
|
)?)),
|
||||||
Type::Array(type_, dimensions) => self.allocate_array(cs, name, *type_, dimensions, input_option, span),
|
Type::Array(type_, dimensions) => self.allocate_array(cs, name, *type_, dimensions, input_option, span),
|
||||||
Type::Tuple(types) => self.allocate_tuple(cs, name, types, input_option, span),
|
Type::Tuple(types) => self.allocate_tuple(cs, &name, types, input_option, span),
|
||||||
_ => unimplemented!("main function input not implemented for type"),
|
_ => unimplemented!("main function input not implemented for type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn allocate_tuple<CS: ConstraintSystem<F>>(
|
pub fn allocate_tuple<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
name: String,
|
name: &str,
|
||||||
types: Vec<Type>,
|
types: Vec<Type>,
|
||||||
input_value: Option<InputValue>,
|
input_value: Option<InputValue>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
||||||
let mut tuple_values = vec![];
|
let mut tuple_values = vec![];
|
||||||
|
|
||||||
@ -45,26 +45,25 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
Some(InputValue::Tuple(values)) => {
|
Some(InputValue::Tuple(values)) => {
|
||||||
// Allocate each value in the tuple
|
// Allocate each value in the tuple
|
||||||
for (i, (value, type_)) in values.into_iter().zip(types.into_iter()).enumerate() {
|
for (i, (value, type_)) in values.into_iter().zip(types.into_iter()).enumerate() {
|
||||||
let value_name = new_scope(name.clone(), i.to_string());
|
let value_name = new_scope(name, &i.to_string());
|
||||||
|
|
||||||
tuple_values.push(self.allocate_main_function_input(
|
tuple_values.push(self.allocate_main_function_input(cs, type_, &value_name, Some(value), span)?)
|
||||||
cs,
|
|
||||||
type_,
|
|
||||||
value_name,
|
|
||||||
Some(value),
|
|
||||||
span.clone(),
|
|
||||||
)?)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Allocate all tuple values as none
|
// Allocate all tuple values as none
|
||||||
for (i, type_) in types.into_iter().enumerate() {
|
for (i, type_) in types.into_iter().enumerate() {
|
||||||
let value_name = new_scope(name.clone(), i.to_string());
|
let value_name = new_scope(name, &i.to_string());
|
||||||
|
|
||||||
tuple_values.push(self.allocate_main_function_input(cs, type_, value_name, None, span.clone())?);
|
tuple_values.push(self.allocate_main_function_input(cs, type_, &value_name, None, span)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return Err(FunctionError::invalid_tuple(input_value.unwrap().to_string(), span)),
|
_ => {
|
||||||
|
return Err(FunctionError::invalid_tuple(
|
||||||
|
input_value.unwrap().to_string(),
|
||||||
|
span.to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ConstrainedValue::Tuple(tuple_values))
|
Ok(ConstrainedValue::Tuple(tuple_values))
|
||||||
|
@ -34,11 +34,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_main_function<CS: ConstraintSystem<F>>(
|
pub fn enforce_main_function<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
scope: String,
|
scope: &str,
|
||||||
function: Function,
|
function: Function,
|
||||||
input: Input,
|
input: Input,
|
||||||
) -> Result<OutputBytes, FunctionError> {
|
) -> Result<OutputBytes, FunctionError> {
|
||||||
let function_name = new_scope(scope.clone(), function.get_name());
|
let function_name = new_scope(scope, function.get_name());
|
||||||
let registers = input.get_registers();
|
let registers = input.get_registers();
|
||||||
|
|
||||||
// Iterate over main function input variables and allocate new values
|
// Iterate over main function input variables and allocate new values
|
||||||
@ -55,20 +55,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
let input_option = input
|
let input_option = input
|
||||||
.get(&name)
|
.get(&name)
|
||||||
.ok_or_else(|| FunctionError::input_not_found(name.clone(), function.span.clone()))?;
|
.ok_or_else(|| FunctionError::input_not_found(name.clone(), function.span.clone()))?;
|
||||||
let input_value = self.allocate_main_function_input(
|
let input_value =
|
||||||
cs,
|
self.allocate_main_function_input(cs, input_model.type_, &name, input_option, &function.span)?;
|
||||||
input_model.type_,
|
|
||||||
name.clone(),
|
|
||||||
input_option,
|
|
||||||
function.span.clone(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
(input_model.identifier, input_value)
|
(input_model.identifier, input_value)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store input as variable with {function_name}_{identifier_name}
|
// Store input as variable with {function_name}_{identifier_name}
|
||||||
let input_name = new_scope(function_name.clone(), identifier.name.clone());
|
let input_name = new_scope(&function_name, &identifier.name);
|
||||||
|
|
||||||
// Store a new variable for every allocated main function input
|
// Store a new variable for every allocated main function input
|
||||||
self.store(input_name, value);
|
self.store(input_name, value);
|
||||||
@ -77,7 +72,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let span = function.span.clone();
|
let span = function.span.clone();
|
||||||
let result_value = self.enforce_function(cs, scope, function_name, function, input_variables, "".to_owned())?;
|
let result_value = self.enforce_function(cs, scope, &function_name, function, input_variables, "")?;
|
||||||
let output_bytes = OutputBytes::new_from_constrained_value(registers, result_value, span)?;
|
let output_bytes = OutputBytes::new_from_constrained_value(registers, result_value, span)?;
|
||||||
|
|
||||||
Ok(output_bytes)
|
Ok(output_bytes)
|
||||||
|
@ -34,7 +34,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
return_value: &mut ConstrainedValue<F, G>,
|
return_value: &mut ConstrainedValue<F, G>,
|
||||||
results: Vec<(Option<Boolean>, ConstrainedValue<F, G>)>,
|
results: Vec<(Option<Boolean>, ConstrainedValue<F, G>)>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
// if there are no results, continue
|
// if there are no results, continue
|
||||||
if results.is_empty() {
|
if results.is_empty() {
|
||||||
@ -65,7 +65,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
let selected_value =
|
let selected_value =
|
||||||
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &result, return_value)
|
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &result, return_value)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
StatementError::select_fail(result.to_string(), return_value.to_string(), span.clone())
|
StatementError::select_fail(result.to_string(), return_value.to_string(), span.to_owned())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
*return_value = selected_value;
|
*return_value = selected_value;
|
||||||
|
@ -21,7 +21,7 @@ use leo_core::{CorePackageList, LeoCoreError};
|
|||||||
use snarkos_models::curves::{Field, PrimeField};
|
use snarkos_models::curves::{Field, PrimeField};
|
||||||
|
|
||||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||||
pub(crate) fn store_core_package(&mut self, scope: String, package: Package) -> Result<(), LeoCoreError> {
|
pub(crate) fn store_core_package(&mut self, scope: &str, package: Package) -> Result<(), LeoCoreError> {
|
||||||
// Create list of imported core packages.
|
// Create list of imported core packages.
|
||||||
let list = CorePackageList::from_package_access(package.access)?;
|
let list = CorePackageList::from_package_access(package.access)?;
|
||||||
|
|
||||||
@ -29,10 +29,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
let symbol_list = list.to_symbols()?;
|
let symbol_list = list.to_symbols()?;
|
||||||
|
|
||||||
for (symbol, circuit) in symbol_list.symbols() {
|
for (symbol, circuit) in symbol_list.symbols() {
|
||||||
let symbol_name = new_scope(scope.clone(), symbol);
|
let symbol_name = new_scope(scope, symbol);
|
||||||
|
|
||||||
// store packages
|
// store packages
|
||||||
self.store(symbol_name, ConstrainedValue::CircuitDefinition(circuit))
|
self.store(symbol_name, ConstrainedValue::CircuitDefinition(circuit.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -22,7 +22,7 @@ use snarkos_models::curves::{Field, PrimeField};
|
|||||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||||
pub(crate) fn store_import(
|
pub(crate) fn store_import(
|
||||||
&mut self,
|
&mut self,
|
||||||
scope: String,
|
scope: &str,
|
||||||
import: &Import,
|
import: &Import,
|
||||||
imported_programs: &ImportParser,
|
imported_programs: &ImportParser,
|
||||||
) -> Result<(), ImportError> {
|
) -> Result<(), ImportError> {
|
||||||
@ -51,7 +51,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
self.store_definitions(program.clone(), imported_programs)?;
|
self.store_definitions(program.clone(), imported_programs)?;
|
||||||
|
|
||||||
// Store the imported symbol
|
// Store the imported symbol
|
||||||
self.store_symbol(scope.clone(), package, &symbol, program)?;
|
self.store_symbol(scope, &package, &symbol, program)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -22,8 +22,8 @@ use snarkos_models::curves::{Field, PrimeField};
|
|||||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||||
pub(crate) fn store_symbol(
|
pub(crate) fn store_symbol(
|
||||||
&mut self,
|
&mut self,
|
||||||
scope: String,
|
scope: &str,
|
||||||
program_name: String,
|
program_name: &str,
|
||||||
symbol: &ImportSymbol,
|
symbol: &ImportSymbol,
|
||||||
program: &Program,
|
program: &Program,
|
||||||
) -> Result<(), ImportError> {
|
) -> Result<(), ImportError> {
|
||||||
@ -31,9 +31,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
if symbol.is_star() {
|
if symbol.is_star() {
|
||||||
// evaluate and store all circuit definitions
|
// evaluate and store all circuit definitions
|
||||||
program.circuits.iter().for_each(|(identifier, circuit)| {
|
program.circuits.iter().for_each(|(identifier, circuit)| {
|
||||||
let name = new_scope(scope.clone(), identifier.to_string());
|
let name = new_scope(scope, &identifier.name);
|
||||||
let value = ConstrainedValue::Import(
|
let value = ConstrainedValue::Import(
|
||||||
program_name.clone(),
|
program_name.to_owned(),
|
||||||
Box::new(ConstrainedValue::CircuitDefinition(circuit.clone())),
|
Box::new(ConstrainedValue::CircuitDefinition(circuit.clone())),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -42,9 +42,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
// evaluate and store all function definitions
|
// evaluate and store all function definitions
|
||||||
program.functions.iter().for_each(|(identifier, function)| {
|
program.functions.iter().for_each(|(identifier, function)| {
|
||||||
let name = new_scope(scope.clone(), identifier.to_string());
|
let name = new_scope(scope, &identifier.name);
|
||||||
let value = ConstrainedValue::Import(
|
let value = ConstrainedValue::Import(
|
||||||
program_name.clone(),
|
program_name.to_owned(),
|
||||||
Box::new(ConstrainedValue::Function(None, function.clone())),
|
Box::new(ConstrainedValue::Function(None, function.clone())),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
let value = match matched_circuit {
|
let value = match matched_circuit {
|
||||||
Some((_circuit_name, circuit)) => ConstrainedValue::Import(
|
Some((_circuit_name, circuit)) => ConstrainedValue::Import(
|
||||||
program_name,
|
program_name.to_owned(),
|
||||||
Box::new(ConstrainedValue::CircuitDefinition(circuit.clone())),
|
Box::new(ConstrainedValue::CircuitDefinition(circuit.clone())),
|
||||||
),
|
),
|
||||||
None => {
|
None => {
|
||||||
@ -71,17 +71,17 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
match matched_function {
|
match matched_function {
|
||||||
Some((_function_name, function)) => ConstrainedValue::Import(
|
Some((_function_name, function)) => ConstrainedValue::Import(
|
||||||
program_name,
|
program_name.to_owned(),
|
||||||
Box::new(ConstrainedValue::Function(None, function.clone())),
|
Box::new(ConstrainedValue::Function(None, function.clone())),
|
||||||
),
|
),
|
||||||
None => return Err(ImportError::unknown_symbol(symbol.to_owned(), program_name)),
|
None => return Err(ImportError::unknown_symbol(symbol.to_owned(), program_name.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// take the alias if it is present
|
// take the alias if it is present
|
||||||
let id = symbol.alias.clone().unwrap_or_else(|| symbol.symbol.clone());
|
let id = symbol.alias.clone().unwrap_or_else(|| symbol.symbol.clone());
|
||||||
let name = new_scope(scope, id.to_string());
|
let name = new_scope(scope, &id.name);
|
||||||
|
|
||||||
// store imported circuit under imported name
|
// store imported circuit under imported name
|
||||||
self.store(name, value);
|
self.store(name, value);
|
||||||
|
@ -22,7 +22,6 @@ use snarkos_models::curves::{Field, PrimeField};
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct ConstrainedProgram<F: Field + PrimeField, G: GroupType<F>> {
|
pub struct ConstrainedProgram<F: Field + PrimeField, G: GroupType<F>> {
|
||||||
pub identifiers: HashMap<String, ConstrainedValue<F, G>>,
|
pub identifiers: HashMap<String, ConstrainedValue<F, G>>,
|
||||||
}
|
}
|
||||||
@ -35,7 +34,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Default for ConstrainedProgram<F, G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_scope(outer: String, inner: String) -> String {
|
pub fn new_scope(outer: &str, inner: &str) -> String {
|
||||||
format!("{}_{}", outer, inner)
|
format!("{}_{}", outer, inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,25 +32,25 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn assign_array<CS: ConstraintSystem<F>>(
|
pub fn assign_array<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
name: String,
|
name: &str,
|
||||||
range_or_expression: RangeOrExpression,
|
range_or_expression: RangeOrExpression,
|
||||||
mut new_value: ConstrainedValue<F, G>,
|
mut new_value: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
||||||
|
|
||||||
// Resolve index so we know if we are assigning to a single value or a range of values
|
// Resolve index so we know if we are assigning to a single value or a range of values
|
||||||
match range_or_expression {
|
match range_or_expression {
|
||||||
RangeOrExpression::Expression(index) => {
|
RangeOrExpression::Expression(index) => {
|
||||||
let index = self.enforce_index(cs, file_scope, function_scope, index, span.clone())?;
|
let index = self.enforce_index(cs, file_scope, function_scope, index, span)?;
|
||||||
|
|
||||||
// Modify the single value of the array in place
|
// Modify the single value of the array in place
|
||||||
match self.get_mutable_assignee(name, span.clone())? {
|
match self.get_mutable_assignee(name, &span)? {
|
||||||
ConstrainedValue::Array(old) => {
|
ConstrainedValue::Array(old) => {
|
||||||
new_value.resolve_type(Some(old[index].to_type(span.clone())?), span.clone())?;
|
new_value.resolve_type(Some(old[index].to_type(&span)?), &span)?;
|
||||||
|
|
||||||
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
|
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
|
||||||
let selected_value = ConstrainedValue::conditionally_select(
|
let selected_value = ConstrainedValue::conditionally_select(
|
||||||
@ -60,28 +60,26 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
&old[index],
|
&old[index],
|
||||||
)
|
)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
StatementError::select_fail(new_value.to_string(), old[index].to_string(), span)
|
StatementError::select_fail(new_value.to_string(), old[index].to_string(), span.to_owned())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
old[index] = selected_value;
|
old[index] = selected_value;
|
||||||
}
|
}
|
||||||
_ => return Err(StatementError::array_assign_index(span)),
|
_ => return Err(StatementError::array_assign_index(span.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RangeOrExpression::Range(from, to) => {
|
RangeOrExpression::Range(from, to) => {
|
||||||
let from_index = match from {
|
let from_index = match from {
|
||||||
Some(integer) => {
|
Some(integer) => self.enforce_index(cs, file_scope, function_scope, integer, span)?,
|
||||||
self.enforce_index(cs, file_scope.clone(), function_scope.clone(), integer, span.clone())?
|
|
||||||
}
|
|
||||||
None => 0usize,
|
None => 0usize,
|
||||||
};
|
};
|
||||||
let to_index_option = match to {
|
let to_index_option = match to {
|
||||||
Some(integer) => Some(self.enforce_index(cs, file_scope, function_scope, integer, span.clone())?),
|
Some(integer) => Some(self.enforce_index(cs, file_scope, function_scope, integer, span)?),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Modify the range of values of the array
|
// Modify the range of values of the array
|
||||||
let old_array = self.get_mutable_assignee(name, span.clone())?;
|
let old_array = self.get_mutable_assignee(name, &span)?;
|
||||||
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());
|
||||||
@ -89,12 +87,14 @@ 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::array_assign_range(span)),
|
_ => return Err(StatementError::array_assign_range(span.to_owned())),
|
||||||
};
|
};
|
||||||
let name_unique = format!("select {} {}:{}", new_array, span.line, span.start);
|
let name_unique = format!("select {} {}:{}", new_array, span.line, span.start);
|
||||||
let selected_array =
|
let selected_array =
|
||||||
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &new_array, old_array)
|
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &new_array, old_array)
|
||||||
.map_err(|_| StatementError::select_fail(new_array.to_string(), old_array.to_string(), span))?;
|
.map_err(|_| {
|
||||||
|
StatementError::select_fail(new_array.to_string(), old_array.to_string(), span.to_owned())
|
||||||
|
})?;
|
||||||
|
|
||||||
*old_array = selected_array;
|
*old_array = selected_array;
|
||||||
}
|
}
|
||||||
|
@ -39,33 +39,34 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_assign_statement<CS: ConstraintSystem<F>>(
|
pub fn enforce_assign_statement<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
declared_circuit_reference: String,
|
declared_circuit_reference: &str,
|
||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
assignee: Assignee,
|
assignee: Assignee,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
span: Span,
|
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 = resolve_assignee(function_scope.clone(), assignee.clone());
|
let variable_name = resolve_assignee(function_scope, assignee.clone());
|
||||||
|
|
||||||
// Evaluate new value
|
// Evaluate new value
|
||||||
let mut new_value =
|
let mut new_value = self.enforce_expression(cs, file_scope, function_scope, None, expression)?;
|
||||||
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), None, expression)?;
|
|
||||||
|
|
||||||
// Mutate the old value into the new value
|
// Mutate the old value into the new value
|
||||||
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, span.clone())?;
|
let old_value = self.get_mutable_assignee(&variable_name, &span)?;
|
||||||
|
|
||||||
new_value.resolve_type(Some(old_value.to_type(span.clone())?), span.clone())?;
|
new_value.resolve_type(Some(old_value.to_type(&span)?), &span)?;
|
||||||
|
|
||||||
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
|
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
|
||||||
let selected_value =
|
let selected_value =
|
||||||
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &new_value, old_value)
|
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &new_value, old_value)
|
||||||
.map_err(|_| StatementError::select_fail(new_value.to_string(), old_value.to_string(), span))?;
|
.map_err(|_| {
|
||||||
|
StatementError::select_fail(new_value.to_string(), old_value.to_string(), span.to_owned())
|
||||||
|
})?;
|
||||||
|
|
||||||
*old_value = selected_value;
|
*old_value = selected_value;
|
||||||
|
|
||||||
@ -76,18 +77,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
file_scope,
|
file_scope,
|
||||||
function_scope,
|
function_scope,
|
||||||
indicator,
|
indicator,
|
||||||
variable_name,
|
&variable_name,
|
||||||
*range_or_expression,
|
*range_or_expression,
|
||||||
new_value,
|
new_value,
|
||||||
span,
|
span,
|
||||||
),
|
),
|
||||||
Assignee::Tuple(_tuple, index) => self.assign_tuple(cs, indicator, variable_name, index, new_value, span),
|
Assignee::Tuple(_tuple, index) => self.assign_tuple(cs, indicator, &variable_name, index, new_value, span),
|
||||||
Assignee::CircuitField(assignee, circuit_variable) => {
|
Assignee::CircuitField(assignee, circuit_variable) => {
|
||||||
// Mutate a circuit variable using the self keyword.
|
// Mutate a circuit variable using the self keyword.
|
||||||
if let Assignee::Identifier(circuit_name) = *assignee {
|
if let Assignee::Identifier(circuit_name) = *assignee {
|
||||||
if circuit_name.is_self() {
|
if circuit_name.is_self() {
|
||||||
let self_circuit_variable_name = new_scope(circuit_name.name, circuit_variable.name.clone());
|
let self_circuit_variable_name = new_scope(&circuit_name.name, &circuit_variable.name);
|
||||||
let self_variable_name = new_scope(file_scope, self_circuit_variable_name);
|
let self_variable_name = new_scope(file_scope, &self_circuit_variable_name);
|
||||||
let value = self.mutate_circuit_variable(
|
let value = self.mutate_circuit_variable(
|
||||||
cs,
|
cs,
|
||||||
indicator,
|
indicator,
|
||||||
@ -102,7 +103,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
let _value = self.mutate_circuit_variable(
|
let _value = self.mutate_circuit_variable(
|
||||||
cs,
|
cs,
|
||||||
indicator,
|
indicator,
|
||||||
variable_name,
|
&variable_name,
|
||||||
circuit_variable,
|
circuit_variable,
|
||||||
new_value,
|
new_value,
|
||||||
span,
|
span,
|
||||||
|
@ -21,9 +21,9 @@ use leo_typed::{Assignee, Span};
|
|||||||
|
|
||||||
use snarkos_models::curves::{Field, PrimeField};
|
use snarkos_models::curves::{Field, PrimeField};
|
||||||
|
|
||||||
pub fn resolve_assignee(scope: String, assignee: Assignee) -> String {
|
pub fn resolve_assignee(scope: &str, assignee: Assignee) -> String {
|
||||||
match assignee {
|
match assignee {
|
||||||
Assignee::Identifier(name) => new_scope(scope, name.to_string()),
|
Assignee::Identifier(name) => new_scope(scope, &name.name),
|
||||||
Assignee::Array(array, _index) => resolve_assignee(scope, *array),
|
Assignee::Array(array, _index) => resolve_assignee(scope, *array),
|
||||||
Assignee::Tuple(tuple, _index) => resolve_assignee(scope, *tuple),
|
Assignee::Tuple(tuple, _index) => resolve_assignee(scope, *tuple),
|
||||||
Assignee::CircuitField(circuit_name, _member) => resolve_assignee(scope, *circuit_name),
|
Assignee::CircuitField(circuit_name, _member) => resolve_assignee(scope, *circuit_name),
|
||||||
@ -33,16 +33,16 @@ pub fn resolve_assignee(scope: String, assignee: Assignee) -> String {
|
|||||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||||
pub fn get_mutable_assignee(
|
pub fn get_mutable_assignee(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: String,
|
name: &str,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<&mut ConstrainedValue<F, G>, StatementError> {
|
) -> 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::immutable_assign(name, span)),
|
_ => return Err(StatementError::immutable_assign(name.to_owned(), span.to_owned())),
|
||||||
},
|
},
|
||||||
None => return Err(StatementError::undefined_variable(name, span)),
|
None => return Err(StatementError::undefined_variable(name.to_owned(), span.to_owned())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,15 +32,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
circuit_name: String,
|
circuit_name: &str,
|
||||||
variable_name: Identifier,
|
variable_name: Identifier,
|
||||||
mut new_value: ConstrainedValue<F, G>,
|
mut new_value: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, StatementError> {
|
) -> Result<ConstrainedValue<F, G>, StatementError> {
|
||||||
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
||||||
|
|
||||||
// Get the mutable circuit by name
|
// Get the mutable circuit by name
|
||||||
match self.get_mutable_assignee(circuit_name, span.clone())? {
|
match self.get_mutable_assignee(circuit_name, span)? {
|
||||||
ConstrainedValue::CircuitExpression(_variable, members) => {
|
ConstrainedValue::CircuitExpression(_variable, members) => {
|
||||||
// Modify the circuit variable in place
|
// Modify the circuit variable in place
|
||||||
let matched_variable = members.iter_mut().find(|member| member.0 == variable_name);
|
let matched_variable = members.iter_mut().find(|member| member.0 == variable_name);
|
||||||
@ -51,18 +51,21 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
// Throw an error if we try to mutate a circuit function
|
// Throw an error if we try to mutate a circuit function
|
||||||
Err(StatementError::immutable_circuit_function(
|
Err(StatementError::immutable_circuit_function(
|
||||||
function.identifier.to_string(),
|
function.identifier.to_string(),
|
||||||
span,
|
span.to_owned(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
ConstrainedValue::Static(_circuit_function) => {
|
ConstrainedValue::Static(_circuit_function) => {
|
||||||
// Throw an error if we try to mutate a static circuit function
|
// Throw an error if we try to mutate a static circuit function
|
||||||
Err(StatementError::immutable_circuit_function("static".into(), span))
|
Err(StatementError::immutable_circuit_function(
|
||||||
|
"static".into(),
|
||||||
|
span.to_owned(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
ConstrainedValue::Mutable(value) => {
|
ConstrainedValue::Mutable(value) => {
|
||||||
// Mutate the circuit variable's value in place
|
// Mutate the circuit variable's value in place
|
||||||
|
|
||||||
// Check that the new value type == old value type
|
// Check that the new value type == old value type
|
||||||
new_value.resolve_type(Some(value.to_type(span.clone())?), span.clone())?;
|
new_value.resolve_type(Some(value.to_type(span)?), span)?;
|
||||||
|
|
||||||
// Conditionally select the value if this branch is executed.
|
// Conditionally select the value if this branch is executed.
|
||||||
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
|
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
|
||||||
@ -73,7 +76,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
&member.1,
|
&member.1,
|
||||||
)
|
)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
StatementError::select_fail(new_value.to_string(), member.1.to_string(), span)
|
StatementError::select_fail(
|
||||||
|
new_value.to_string(),
|
||||||
|
member.1.to_string(),
|
||||||
|
span.to_owned(),
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Make sure the new value is still mutable
|
// Make sure the new value is still mutable
|
||||||
@ -85,20 +92,26 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Throw an error if we try to mutate an immutable circuit variable
|
// Throw an error if we try to mutate an immutable circuit variable
|
||||||
Err(StatementError::immutable_circuit_variable(variable_name.name, span))
|
Err(StatementError::immutable_circuit_variable(
|
||||||
|
variable_name.name,
|
||||||
|
span.to_owned(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
// Throw an error if the circuit variable does not exist in the circuit
|
// Throw an error if the circuit variable does not exist in the circuit
|
||||||
Err(StatementError::undefined_circuit_variable(
|
Err(StatementError::undefined_circuit_variable(
|
||||||
variable_name.to_string(),
|
variable_name.to_string(),
|
||||||
span,
|
span.to_owned(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Throw an error if the circuit definition does not exist in the file
|
// Throw an error if the circuit definition does not exist in the file
|
||||||
_ => Err(StatementError::undefined_circuit(variable_name.to_string(), span)),
|
_ => Err(StatementError::undefined_circuit(
|
||||||
|
variable_name.to_string(),
|
||||||
|
span.to_owned(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,28 +32,28 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
name: String,
|
name: &str,
|
||||||
index: usize,
|
index: usize,
|
||||||
mut new_value: ConstrainedValue<F, G>,
|
mut new_value: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
let condition = indicator.unwrap_or(Boolean::Constant(true));
|
||||||
|
|
||||||
// Modify the single value of the tuple in place
|
// Modify the single value of the tuple in place
|
||||||
match self.get_mutable_assignee(name, span.clone())? {
|
match self.get_mutable_assignee(name, &span)? {
|
||||||
ConstrainedValue::Tuple(old) => {
|
ConstrainedValue::Tuple(old) => {
|
||||||
new_value.resolve_type(Some(old[index].to_type(span.clone())?), span.clone())?;
|
new_value.resolve_type(Some(old[index].to_type(&span)?), &span)?;
|
||||||
|
|
||||||
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
|
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
|
||||||
let selected_value =
|
let selected_value =
|
||||||
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &new_value, &old[index])
|
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &new_value, &old[index])
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
StatementError::select_fail(new_value.to_string(), old[index].to_string(), span)
|
StatementError::select_fail(new_value.to_string(), old[index].to_string(), span.to_owned())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
old[index] = selected_value;
|
old[index] = selected_value;
|
||||||
}
|
}
|
||||||
_ => return Err(StatementError::tuple_assign_index(span)),
|
_ => return Err(StatementError::tuple_assign_index(span.to_owned())),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -28,8 +28,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn evaluate_branch<CS: ConstraintSystem<F>>(
|
pub fn evaluate_branch<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
@ -39,12 +39,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
for statement in statements.into_iter() {
|
for statement in statements.into_iter() {
|
||||||
let mut value = self.enforce_statement(
|
let mut value = self.enforce_statement(
|
||||||
cs,
|
cs,
|
||||||
file_scope.clone(),
|
file_scope,
|
||||||
function_scope.clone(),
|
function_scope,
|
||||||
indicator,
|
indicator,
|
||||||
statement,
|
statement,
|
||||||
return_type.clone(),
|
return_type.clone(),
|
||||||
"".to_owned(),
|
"",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
results.append(&mut value);
|
results.append(&mut value);
|
||||||
|
@ -47,12 +47,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_conditional_statement<CS: ConstraintSystem<F>>(
|
pub fn enforce_conditional_statement<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
statement: ConditionalStatement,
|
statement: ConditionalStatement,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||||
let statement_string = statement.to_string();
|
let statement_string = statement.to_string();
|
||||||
|
|
||||||
@ -62,13 +62,13 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
// Evaluate the conditional boolean as the inner indicator
|
// Evaluate the conditional boolean as the inner indicator
|
||||||
let inner_indicator = match self.enforce_expression(
|
let inner_indicator = match self.enforce_expression(
|
||||||
cs,
|
cs,
|
||||||
file_scope.clone(),
|
file_scope,
|
||||||
function_scope.clone(),
|
function_scope,
|
||||||
Some(Type::Boolean),
|
Some(Type::Boolean),
|
||||||
statement.condition.clone(),
|
statement.condition.clone(),
|
||||||
)? {
|
)? {
|
||||||
ConstrainedValue::Boolean(resolved) => resolved,
|
ConstrainedValue::Boolean(resolved) => resolved,
|
||||||
value => return Err(StatementError::conditional_boolean(value.to_string(), span)),
|
value => return Err(StatementError::conditional_boolean(value.to_string(), span.to_owned())),
|
||||||
};
|
};
|
||||||
|
|
||||||
// If outer_indicator && inner_indicator, then select branch 1
|
// If outer_indicator && inner_indicator, then select branch 1
|
||||||
@ -83,15 +83,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
&outer_indicator,
|
&outer_indicator,
|
||||||
&inner_indicator,
|
&inner_indicator,
|
||||||
)
|
)
|
||||||
.map_err(|_| StatementError::indicator_calculation(branch_1_name, span.clone()))?;
|
.map_err(|_| StatementError::indicator_calculation(branch_1_name, span.to_owned()))?;
|
||||||
|
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
|
|
||||||
// Evaluate branch 1
|
// Evaluate branch 1
|
||||||
let mut branch_1_result = self.evaluate_branch(
|
let mut branch_1_result = self.evaluate_branch(
|
||||||
cs,
|
cs,
|
||||||
file_scope.clone(),
|
file_scope,
|
||||||
function_scope.clone(),
|
function_scope,
|
||||||
Some(branch_1_indicator),
|
Some(branch_1_indicator),
|
||||||
statement.statements,
|
statement.statements,
|
||||||
return_type.clone(),
|
return_type.clone(),
|
||||||
@ -111,7 +111,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
&outer_indicator,
|
&outer_indicator,
|
||||||
&inner_indicator,
|
&inner_indicator,
|
||||||
)
|
)
|
||||||
.map_err(|_| StatementError::indicator_calculation(branch_2_name, span.clone()))?;
|
.map_err(|_| StatementError::indicator_calculation(branch_2_name, span.to_owned()))?;
|
||||||
|
|
||||||
// Evaluate branch 2
|
// Evaluate branch 2
|
||||||
let mut branch_2_result = match statement.next {
|
let mut branch_2_result = match statement.next {
|
||||||
|
@ -28,14 +28,17 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
fn enforce_single_definition<CS: ConstraintSystem<F>>(
|
fn enforce_single_definition<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
is_constant: bool,
|
is_constant: bool,
|
||||||
variable_name: VariableName,
|
variable_name: VariableName,
|
||||||
mut value: ConstrainedValue<F, G>,
|
mut value: ConstrainedValue<F, G>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
if is_constant && variable_name.mutable {
|
if is_constant && variable_name.mutable {
|
||||||
return Err(StatementError::immutable_assign(variable_name.to_string(), span));
|
return Err(StatementError::immutable_assign(
|
||||||
|
variable_name.to_string(),
|
||||||
|
span.to_owned(),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
value.allocate_value(cs, span)?
|
value.allocate_value(cs, span)?
|
||||||
}
|
}
|
||||||
@ -48,15 +51,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
fn enforce_expressions<CS: ConstraintSystem<F>>(
|
fn enforce_expressions<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
type_: Option<Type>,
|
type_: Option<Type>,
|
||||||
expressions: Vec<Expression>,
|
expressions: Vec<Expression>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<Vec<ConstrainedValue<F, G>>, StatementError> {
|
) -> Result<Vec<ConstrainedValue<F, G>>, StatementError> {
|
||||||
let types = match type_ {
|
let types = match type_ {
|
||||||
Some(Type::Tuple(types)) => types,
|
Some(Type::Tuple(types)) => types,
|
||||||
Some(type_) => return Err(StatementError::tuple_type(type_.to_string(), span)),
|
Some(type_) => return Err(StatementError::tuple_type(type_.to_string(), span.to_owned())),
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -72,13 +75,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
let mut values = Vec::with_capacity(expressions.len());
|
let mut values = Vec::with_capacity(expressions.len());
|
||||||
|
|
||||||
for (expression, expected_type) in expressions.into_iter().zip(expected_types.into_iter()) {
|
for (expression, expected_type) in expressions.into_iter().zip(expected_types.into_iter()) {
|
||||||
let value = self.enforce_expression(
|
let value = self.enforce_expression(cs, file_scope, function_scope, expected_type, expression)?;
|
||||||
cs,
|
|
||||||
file_scope.clone(),
|
|
||||||
function_scope.clone(),
|
|
||||||
expected_type,
|
|
||||||
expression,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
values.push(value);
|
values.push(value);
|
||||||
}
|
}
|
||||||
@ -90,20 +87,20 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
fn enforce_tuple_definition<CS: ConstraintSystem<F>>(
|
fn enforce_tuple_definition<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
is_constant: bool,
|
is_constant: bool,
|
||||||
variables: Variables,
|
variables: Variables,
|
||||||
expressions: Vec<Expression>,
|
expressions: Vec<Expression>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
let values = self.enforce_expressions(
|
let values = self.enforce_expressions(
|
||||||
cs,
|
cs,
|
||||||
file_scope,
|
file_scope,
|
||||||
function_scope.clone(),
|
function_scope,
|
||||||
variables.type_.clone(),
|
variables.type_.clone(),
|
||||||
expressions,
|
expressions,
|
||||||
span.clone(),
|
span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let tuple = ConstrainedValue::Tuple(values);
|
let tuple = ConstrainedValue::Tuple(values);
|
||||||
@ -115,22 +112,22 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
fn enforce_multiple_definition<CS: ConstraintSystem<F>>(
|
fn enforce_multiple_definition<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
is_constant: bool,
|
is_constant: bool,
|
||||||
variables: Variables,
|
variables: Variables,
|
||||||
values: Vec<ConstrainedValue<F, G>>,
|
values: Vec<ConstrainedValue<F, G>>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
if values.len() != variables.names.len() {
|
if values.len() != variables.names.len() {
|
||||||
return Err(StatementError::invalid_number_of_definitions(
|
return Err(StatementError::invalid_number_of_definitions(
|
||||||
values.len(),
|
values.len(),
|
||||||
variables.names.len(),
|
variables.names.len(),
|
||||||
span,
|
span.to_owned(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (variable, value) in variables.names.into_iter().zip(values.into_iter()) {
|
for (variable, value) in variables.names.into_iter().zip(values.into_iter()) {
|
||||||
self.enforce_single_definition(cs, function_scope.clone(), is_constant, variable, value, span.clone())?;
|
self.enforce_single_definition(cs, function_scope, is_constant, variable, value, span)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -140,12 +137,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_definition_statement<CS: ConstraintSystem<F>>(
|
pub fn enforce_definition_statement<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
declare: Declare,
|
declare: Declare,
|
||||||
variables: Variables,
|
variables: Variables,
|
||||||
expressions: Vec<Expression>,
|
expressions: Vec<Expression>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<(), StatementError> {
|
) -> Result<(), StatementError> {
|
||||||
let num_variables = variables.names.len();
|
let num_variables = variables.names.len();
|
||||||
let num_values = expressions.len();
|
let num_values = expressions.len();
|
||||||
@ -157,13 +154,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
if num_variables == 1 && num_values == 1 {
|
if num_variables == 1 && num_values == 1 {
|
||||||
// Define a single variable with a single value
|
// Define a single variable with a single value
|
||||||
let variable = variables.names[0].clone();
|
let variable = variables.names[0].clone();
|
||||||
let expression = self.enforce_expression(
|
let expression =
|
||||||
cs,
|
self.enforce_expression(cs, file_scope, function_scope, variables.type_, expressions[0].clone())?;
|
||||||
file_scope,
|
|
||||||
function_scope.clone(),
|
|
||||||
variables.type_,
|
|
||||||
expressions[0].clone(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.enforce_single_definition(cs, function_scope, is_constant, variable, expression, span)
|
self.enforce_single_definition(cs, function_scope, is_constant, variable, expression, span)
|
||||||
} else if num_variables == 1 && num_values > 1 {
|
} else if num_variables == 1 && num_values > 1 {
|
||||||
@ -184,13 +176,13 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
let values = match self.enforce_expression(
|
let values = match self.enforce_expression(
|
||||||
cs,
|
cs,
|
||||||
file_scope,
|
file_scope,
|
||||||
function_scope.clone(),
|
function_scope,
|
||||||
variables.type_.clone(),
|
variables.type_.clone(),
|
||||||
expressions[0].clone(),
|
expressions[0].clone(),
|
||||||
)? {
|
)? {
|
||||||
// ConstrainedValue::Return(values) => values,
|
// ConstrainedValue::Return(values) => values,
|
||||||
ConstrainedValue::Tuple(values) => values,
|
ConstrainedValue::Tuple(values) => values,
|
||||||
value => return Err(StatementError::multiple_definition(value.to_string(), span)),
|
value => return Err(StatementError::multiple_definition(value.to_string(), span.to_owned())),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.enforce_multiple_definition(cs, function_scope, is_constant, variables, values, span)
|
self.enforce_multiple_definition(cs, function_scope, is_constant, variables, values, span)
|
||||||
@ -199,10 +191,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
let values = self.enforce_expressions(
|
let values = self.enforce_expressions(
|
||||||
cs,
|
cs,
|
||||||
file_scope,
|
file_scope,
|
||||||
function_scope.clone(),
|
function_scope,
|
||||||
variables.type_.clone(),
|
variables.type_.clone(),
|
||||||
expressions,
|
expressions,
|
||||||
span.clone(),
|
span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.enforce_multiple_definition(cs, function_scope, is_constant, variables, values, span)
|
self.enforce_multiple_definition(cs, function_scope, is_constant, variables, values, span)
|
||||||
|
@ -40,26 +40,26 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_iteration_statement<CS: ConstraintSystem<F>>(
|
pub fn enforce_iteration_statement<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
index: Identifier,
|
index: Identifier,
|
||||||
start: Expression,
|
start: Expression,
|
||||||
stop: Expression,
|
stop: Expression,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
|
|
||||||
let from = self.enforce_index(cs, file_scope.clone(), function_scope.clone(), start, span.clone())?;
|
let from = self.enforce_index(cs, file_scope, function_scope, start, span)?;
|
||||||
let to = self.enforce_index(cs, file_scope.clone(), function_scope.clone(), stop, span.clone())?;
|
let to = self.enforce_index(cs, file_scope, function_scope, stop, span)?;
|
||||||
|
|
||||||
for i in from..to {
|
for i in from..to {
|
||||||
// Store index in current function scope.
|
// Store index in current function scope.
|
||||||
// For loop scope is not implemented.
|
// For loop scope is not implemented.
|
||||||
|
|
||||||
let index_name = new_scope(function_scope.clone(), index.to_string());
|
let index_name = new_scope(function_scope, &index.name);
|
||||||
|
|
||||||
self.store(
|
self.store(
|
||||||
index_name,
|
index_name,
|
||||||
@ -70,8 +70,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
let name_unique = format!("for loop iteration {} {}:{}", i, span.line, span.start);
|
let name_unique = format!("for loop iteration {} {}:{}", i, span.line, span.start);
|
||||||
let mut result = self.evaluate_branch(
|
let mut result = self.evaluate_branch(
|
||||||
&mut cs.ns(|| name_unique),
|
&mut cs.ns(|| name_unique),
|
||||||
file_scope.clone(),
|
file_scope,
|
||||||
function_scope.clone(),
|
function_scope,
|
||||||
indicator,
|
indicator,
|
||||||
statements.clone(),
|
statements.clone(),
|
||||||
return_type.clone(),
|
return_type.clone(),
|
||||||
|
@ -24,14 +24,14 @@ use snarkos_models::{
|
|||||||
gadgets::r1cs::ConstraintSystem,
|
gadgets::r1cs::ConstraintSystem,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn check_return_type(expected: Option<Type>, actual: Type, span: Span) -> Result<(), StatementError> {
|
fn check_return_type(expected: Option<Type>, actual: Type, span: &Span) -> Result<(), StatementError> {
|
||||||
match expected {
|
match expected {
|
||||||
Some(expected) => {
|
Some(expected) => {
|
||||||
if expected.ne(&actual) {
|
if expected.ne(&actual) {
|
||||||
if (expected.is_self() && actual.is_circuit()) || expected.match_array_types(&actual) {
|
if (expected.is_self() && actual.is_circuit()) || expected.match_array_types(&actual) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
return Err(StatementError::arguments_type(&expected, &actual, span));
|
return Err(StatementError::arguments_type(&expected, &actual, span.to_owned()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -44,24 +44,17 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_return_statement<CS: ConstraintSystem<F>>(
|
pub fn enforce_return_statement<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
span: Span,
|
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
|
||||||
|
|
||||||
let result = self.enforce_operand(
|
let result = self.enforce_operand(cs, file_scope, function_scope, return_type.clone(), expression, span)?;
|
||||||
cs,
|
|
||||||
file_scope,
|
|
||||||
function_scope,
|
|
||||||
return_type.clone(),
|
|
||||||
expression,
|
|
||||||
span.clone(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
check_return_type(return_type, result.to_type(span.clone())?, span)?;
|
check_return_type(return_type, result.to_type(&span)?, span)?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
@ -37,12 +37,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn enforce_statement<CS: ConstraintSystem<F>>(
|
pub fn enforce_statement<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: &str,
|
||||||
function_scope: String,
|
function_scope: &str,
|
||||||
indicator: Option<Boolean>,
|
indicator: Option<Boolean>,
|
||||||
statement: Statement,
|
statement: Statement,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
declared_circuit_reference: String,
|
declared_circuit_reference: &str,
|
||||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
Statement::Return(expression, span) => {
|
Statement::Return(expression, span) => {
|
||||||
let return_value = (
|
let return_value = (
|
||||||
indicator,
|
indicator,
|
||||||
self.enforce_return_statement(cs, file_scope, function_scope, expression, return_type, span)?,
|
self.enforce_return_statement(cs, file_scope, function_scope, expression, return_type, &span)?,
|
||||||
);
|
);
|
||||||
|
|
||||||
results.push(return_value);
|
results.push(return_value);
|
||||||
@ -63,7 +63,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
declare,
|
declare,
|
||||||
variables,
|
variables,
|
||||||
expressions,
|
expressions,
|
||||||
span,
|
&span,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Statement::Assign(variable, expression, span) => {
|
Statement::Assign(variable, expression, span) => {
|
||||||
@ -75,7 +75,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
indicator,
|
indicator,
|
||||||
variable,
|
variable,
|
||||||
*expression,
|
*expression,
|
||||||
span,
|
&span,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Statement::Conditional(statement, span) => {
|
Statement::Conditional(statement, span) => {
|
||||||
@ -86,7 +86,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
indicator,
|
indicator,
|
||||||
statement,
|
statement,
|
||||||
return_type,
|
return_type,
|
||||||
span,
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
results.append(&mut result);
|
results.append(&mut result);
|
||||||
@ -102,7 +102,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
*stop,
|
*stop,
|
||||||
statements,
|
statements,
|
||||||
return_type,
|
return_type,
|
||||||
span,
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
results.append(&mut result);
|
results.append(&mut result);
|
||||||
|
@ -44,8 +44,9 @@ pub struct Address {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Address {
|
impl Address {
|
||||||
pub(crate) fn constant(address: String, span: Span) -> Result<Self, AddressError> {
|
pub(crate) fn constant(address: String, span: &Span) -> Result<Self, AddressError> {
|
||||||
let address = AccountAddress::from_str(&address).map_err(|error| AddressError::account_error(error, span))?;
|
let address =
|
||||||
|
AccountAddress::from_str(&address).map_err(|error| AddressError::account_error(error, span.to_owned()))?;
|
||||||
|
|
||||||
let mut address_bytes = vec![];
|
let mut address_bytes = vec![];
|
||||||
address.write(&mut address_bytes).unwrap();
|
address.write(&mut address_bytes).unwrap();
|
||||||
@ -70,9 +71,9 @@ impl Address {
|
|||||||
|
|
||||||
pub(crate) fn from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
pub(crate) fn from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
name: String,
|
name: &str,
|
||||||
input_value: Option<InputValue>,
|
input_value: Option<InputValue>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, AddressError> {
|
) -> Result<ConstrainedValue<F, G>, AddressError> {
|
||||||
// Check that the input value is the correct type
|
// Check that the input value is the correct type
|
||||||
let address_value = match input_value {
|
let address_value = match input_value {
|
||||||
@ -80,7 +81,7 @@ impl Address {
|
|||||||
if let InputValue::Address(string) = input {
|
if let InputValue::Address(string) = input {
|
||||||
Some(string)
|
Some(string)
|
||||||
} else {
|
} else {
|
||||||
return Err(AddressError::invalid_address(name, span));
|
return Err(AddressError::invalid_address(name.to_owned(), span.to_owned()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
@ -92,7 +93,7 @@ impl Address {
|
|||||||
let address = Address::alloc(cs.ns(|| address_namespace), || {
|
let address = Address::alloc(cs.ns(|| address_namespace), || {
|
||||||
address_value.ok_or(SynthesisError::AssignmentMissing)
|
address_value.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| AddressError::missing_address(span))?;
|
.map_err(|_| AddressError::missing_address(span.to_owned()))?;
|
||||||
|
|
||||||
Ok(ConstrainedValue::Address(address))
|
Ok(ConstrainedValue::Address(address))
|
||||||
}
|
}
|
||||||
|
@ -28,19 +28,19 @@ use snarkos_models::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn new_bool_constant(string: String, span: Span) -> Result<Boolean, BooleanError> {
|
pub(crate) fn new_bool_constant(string: String, span: &Span) -> Result<Boolean, BooleanError> {
|
||||||
let boolean = string
|
let boolean = string
|
||||||
.parse::<bool>()
|
.parse::<bool>()
|
||||||
.map_err(|_| BooleanError::invalid_boolean(string, span))?;
|
.map_err(|_| BooleanError::invalid_boolean(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Boolean::constant(boolean))
|
Ok(Boolean::constant(boolean))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn allocate_bool<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
pub(crate) fn allocate_bool<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
name: String,
|
name: &str,
|
||||||
option: Option<bool>,
|
option: Option<bool>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<Boolean, BooleanError> {
|
) -> Result<Boolean, BooleanError> {
|
||||||
let boolean_name = format!("{}: bool", name);
|
let boolean_name = format!("{}: bool", name);
|
||||||
let boolean_name_unique = format!("`{}` {}:{}", boolean_name, span.line, span.start);
|
let boolean_name_unique = format!("`{}` {}:{}", boolean_name, span.line, span.start);
|
||||||
@ -48,14 +48,14 @@ pub(crate) fn allocate_bool<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
|||||||
Boolean::alloc(cs.ns(|| boolean_name_unique), || {
|
Boolean::alloc(cs.ns(|| boolean_name_unique), || {
|
||||||
option.ok_or(SynthesisError::AssignmentMissing)
|
option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| BooleanError::missing_boolean(boolean_name, span))
|
.map_err(|_| BooleanError::missing_boolean(boolean_name.to_owned(), span.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn bool_from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
pub(crate) fn bool_from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
name: String,
|
name: &str,
|
||||||
input_value: Option<InputValue>,
|
input_value: Option<InputValue>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
) -> Result<ConstrainedValue<F, G>, BooleanError> {
|
||||||
// Check that the input value is the correct type
|
// Check that the input value is the correct type
|
||||||
let option = match input_value {
|
let option = match input_value {
|
||||||
@ -63,7 +63,7 @@ pub(crate) fn bool_from_input<F: Field + PrimeField, G: GroupType<F>, CS: Constr
|
|||||||
if let InputValue::Boolean(bool) = input {
|
if let InputValue::Boolean(bool) = input {
|
||||||
Some(bool)
|
Some(bool)
|
||||||
} else {
|
} else {
|
||||||
return Err(BooleanError::invalid_boolean(name, span));
|
return Err(BooleanError::invalid_boolean(name.to_owned(), span.to_owned()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
|
@ -53,24 +53,26 @@ impl<F: Field + PrimeField> FieldType<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn constant(string: String, span: Span) -> Result<Self, FieldError> {
|
pub fn constant(string: String, span: &Span) -> Result<Self, FieldError> {
|
||||||
let value = F::from_str(&string).map_err(|_| FieldError::invalid_field(string, span))?;
|
let value = F::from_str(&string).map_err(|_| FieldError::invalid_field(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(FieldType::Constant(value))
|
Ok(FieldType::Constant(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn negate<CS: ConstraintSystem<F>>(&self, cs: CS, span: Span) -> Result<Self, FieldError> {
|
pub fn negate<CS: ConstraintSystem<F>>(&self, cs: CS, span: &Span) -> Result<Self, FieldError> {
|
||||||
match self {
|
match self {
|
||||||
FieldType::Constant(field) => Ok(FieldType::Constant(field.neg())),
|
FieldType::Constant(field) => Ok(FieldType::Constant(field.neg())),
|
||||||
FieldType::Allocated(field) => {
|
FieldType::Allocated(field) => {
|
||||||
let result = field.negate(cs).map_err(|e| FieldError::negate_operation(e, span))?;
|
let result = field
|
||||||
|
.negate(cs)
|
||||||
|
.map_err(|e| FieldError::negate_operation(e, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(FieldType::Allocated(result))
|
Ok(FieldType::Allocated(result))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: Span) -> Result<Self, FieldError> {
|
pub fn add<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: &Span) -> Result<Self, FieldError> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
|
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
|
||||||
Ok(FieldType::Constant(self_value.add(other_value)))
|
Ok(FieldType::Constant(self_value.add(other_value)))
|
||||||
@ -79,7 +81,7 @@ impl<F: Field + PrimeField> FieldType<F> {
|
|||||||
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
|
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
|
||||||
let result = self_value
|
let result = self_value
|
||||||
.add(cs, other_value)
|
.add(cs, other_value)
|
||||||
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span))?;
|
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(FieldType::Allocated(result))
|
Ok(FieldType::Allocated(result))
|
||||||
}
|
}
|
||||||
@ -88,12 +90,12 @@ impl<F: Field + PrimeField> FieldType<F> {
|
|||||||
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
|
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
|
||||||
allocated_value
|
allocated_value
|
||||||
.add_constant(cs, constant_value)
|
.add_constant(cs, constant_value)
|
||||||
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span))?,
|
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span.to_owned()))?,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sub<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: Span) -> Result<Self, FieldError> {
|
pub fn sub<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: &Span) -> Result<Self, FieldError> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
|
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
|
||||||
Ok(FieldType::Constant(self_value.sub(other_value)))
|
Ok(FieldType::Constant(self_value.sub(other_value)))
|
||||||
@ -102,7 +104,7 @@ impl<F: Field + PrimeField> FieldType<F> {
|
|||||||
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
|
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
|
||||||
let result = self_value
|
let result = self_value
|
||||||
.sub(cs, other_value)
|
.sub(cs, other_value)
|
||||||
.map_err(|e| FieldError::binary_operation("-".to_string(), e, span))?;
|
.map_err(|e| FieldError::binary_operation("-".to_string(), e, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(FieldType::Allocated(result))
|
Ok(FieldType::Allocated(result))
|
||||||
}
|
}
|
||||||
@ -111,12 +113,12 @@ impl<F: Field + PrimeField> FieldType<F> {
|
|||||||
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
|
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
|
||||||
allocated_value
|
allocated_value
|
||||||
.sub_constant(cs, constant_value)
|
.sub_constant(cs, constant_value)
|
||||||
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span))?,
|
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span.to_owned()))?,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mul<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: Span) -> Result<Self, FieldError> {
|
pub fn mul<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: &Span) -> Result<Self, FieldError> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
|
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
|
||||||
Ok(FieldType::Constant(self_value.mul(other_value)))
|
Ok(FieldType::Constant(self_value.mul(other_value)))
|
||||||
@ -125,7 +127,7 @@ impl<F: Field + PrimeField> FieldType<F> {
|
|||||||
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
|
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
|
||||||
let result = self_value
|
let result = self_value
|
||||||
.mul(cs, other_value)
|
.mul(cs, other_value)
|
||||||
.map_err(|e| FieldError::binary_operation("*".to_string(), e, span))?;
|
.map_err(|e| FieldError::binary_operation("*".to_string(), e, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(FieldType::Allocated(result))
|
Ok(FieldType::Allocated(result))
|
||||||
}
|
}
|
||||||
@ -134,24 +136,24 @@ impl<F: Field + PrimeField> FieldType<F> {
|
|||||||
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
|
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
|
||||||
allocated_value
|
allocated_value
|
||||||
.mul_by_constant(cs, constant_value)
|
.mul_by_constant(cs, constant_value)
|
||||||
.map_err(|e| FieldError::binary_operation("*".to_string(), e, span))?,
|
.map_err(|e| FieldError::binary_operation("*".to_string(), e, span.to_owned()))?,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn div<CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self, span: Span) -> Result<Self, FieldError> {
|
pub fn div<CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self, span: &Span) -> Result<Self, FieldError> {
|
||||||
let inverse = match other {
|
let inverse = match other {
|
||||||
FieldType::Constant(constant) => {
|
FieldType::Constant(constant) => {
|
||||||
let constant_inverse = constant
|
let constant_inverse = constant
|
||||||
.inverse()
|
.inverse()
|
||||||
.ok_or_else(|| FieldError::no_inverse(constant.to_string(), span.clone()))?;
|
.ok_or_else(|| FieldError::no_inverse(constant.to_string(), span.to_owned()))?;
|
||||||
|
|
||||||
FieldType::Constant(constant_inverse)
|
FieldType::Constant(constant_inverse)
|
||||||
}
|
}
|
||||||
FieldType::Allocated(allocated) => {
|
FieldType::Allocated(allocated) => {
|
||||||
let allocated_inverse = allocated
|
let allocated_inverse = allocated
|
||||||
.inverse(&mut cs)
|
.inverse(&mut cs)
|
||||||
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span.clone()))?;
|
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span.to_owned()))?;
|
||||||
|
|
||||||
FieldType::Allocated(allocated_inverse)
|
FieldType::Allocated(allocated_inverse)
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@ use snarkos_models::{
|
|||||||
|
|
||||||
pub(crate) fn allocate_field<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
pub(crate) fn allocate_field<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
name: String,
|
name: &str,
|
||||||
option: Option<String>,
|
option: Option<String>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<FieldType<F>, FieldError> {
|
) -> Result<FieldType<F>, FieldError> {
|
||||||
let field_name = format!("{}: field", name);
|
let field_name = format!("{}: field", name);
|
||||||
let field_name_unique = format!("`{}` {}:{}", field_name, span.line, span.start);
|
let field_name_unique = format!("`{}` {}:{}", field_name, span.line, span.start);
|
||||||
@ -37,14 +37,14 @@ pub(crate) fn allocate_field<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
|||||||
FieldType::alloc(cs.ns(|| field_name_unique), || {
|
FieldType::alloc(cs.ns(|| field_name_unique), || {
|
||||||
option.ok_or(SynthesisError::AssignmentMissing)
|
option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| FieldError::missing_field(field_name, span))
|
.map_err(|_| FieldError::missing_field(field_name, span.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn field_from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
pub(crate) fn field_from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
name: String,
|
name: &str,
|
||||||
input_value: Option<InputValue>,
|
input_value: Option<InputValue>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, FieldError> {
|
) -> Result<ConstrainedValue<F, G>, FieldError> {
|
||||||
// Check that the parameter value is the correct type
|
// Check that the parameter value is the correct type
|
||||||
let option = match input_value {
|
let option = match input_value {
|
||||||
@ -52,7 +52,7 @@ pub(crate) fn field_from_input<F: Field + PrimeField, G: GroupType<F>, CS: Const
|
|||||||
if let InputValue::Field(string) = input {
|
if let InputValue::Field(string) = input {
|
||||||
Some(string)
|
Some(string)
|
||||||
} else {
|
} else {
|
||||||
return Err(FieldError::invalid_field(input.to_string(), span));
|
return Err(FieldError::invalid_field(input.to_string(), span.to_owned()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
|
@ -50,11 +50,11 @@ pub trait GroupType<F: Field>:
|
|||||||
{
|
{
|
||||||
fn constant(value: GroupValue) -> Result<Self, GroupError>;
|
fn constant(value: GroupValue) -> Result<Self, GroupError>;
|
||||||
|
|
||||||
fn to_allocated<CS: ConstraintSystem<F>>(&self, cs: CS, span: Span) -> Result<Self, GroupError>;
|
fn to_allocated<CS: ConstraintSystem<F>>(&self, cs: CS, span: &Span) -> Result<Self, GroupError>;
|
||||||
|
|
||||||
fn negate<CS: ConstraintSystem<F>>(&self, cs: CS, span: Span) -> Result<Self, GroupError>;
|
fn negate<CS: ConstraintSystem<F>>(&self, cs: CS, span: &Span) -> Result<Self, GroupError>;
|
||||||
|
|
||||||
fn add<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: Span) -> Result<Self, GroupError>;
|
fn add<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: &Span) -> Result<Self, GroupError>;
|
||||||
|
|
||||||
fn sub<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: Span) -> Result<Self, GroupError>;
|
fn sub<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: &Span) -> Result<Self, GroupError>;
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@ use snarkos_models::{
|
|||||||
|
|
||||||
pub(crate) fn allocate_group<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
pub(crate) fn allocate_group<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
name: String,
|
name: &str,
|
||||||
option: Option<GroupValue>,
|
option: Option<GroupValue>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<G, GroupError> {
|
) -> Result<G, GroupError> {
|
||||||
let group_name = format!("{}: group", name);
|
let group_name = format!("{}: group", name);
|
||||||
let group_name_unique = format!("`{}` {}:{}", group_name, span.line, span.start);
|
let group_name_unique = format!("`{}` {}:{}", group_name, span.line, span.start);
|
||||||
@ -37,14 +37,14 @@ pub(crate) fn allocate_group<F: Field + PrimeField, G: GroupType<F>, CS: Constra
|
|||||||
G::alloc(cs.ns(|| group_name_unique), || {
|
G::alloc(cs.ns(|| group_name_unique), || {
|
||||||
option.ok_or(SynthesisError::AssignmentMissing)
|
option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| GroupError::missing_group(group_name, span))
|
.map_err(|_| GroupError::missing_group(group_name, span.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn group_from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
pub(crate) fn group_from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
name: String,
|
name: &str,
|
||||||
input_value: Option<InputValue>,
|
input_value: Option<InputValue>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, GroupError> {
|
) -> Result<ConstrainedValue<F, G>, GroupError> {
|
||||||
// Check that the parameter value is the correct type
|
// Check that the parameter value is the correct type
|
||||||
let option = match input_value {
|
let option = match input_value {
|
||||||
@ -52,7 +52,7 @@ pub(crate) fn group_from_input<F: Field + PrimeField, G: GroupType<F>, CS: Const
|
|||||||
if let InputValue::Group(string) = input {
|
if let InputValue::Group(string) = input {
|
||||||
Some(string)
|
Some(string)
|
||||||
} else {
|
} else {
|
||||||
return Err(GroupError::invalid_group(input.to_string(), span));
|
return Err(GroupError::invalid_group(input.to_string(), span.to_owned()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
|
@ -58,25 +58,25 @@ impl GroupType<Fq> for EdwardsGroupType {
|
|||||||
Ok(EdwardsGroupType::Constant(value))
|
Ok(EdwardsGroupType::Constant(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_allocated<CS: ConstraintSystem<Fq>>(&self, mut cs: CS, span: Span) -> Result<Self, GroupError> {
|
fn to_allocated<CS: ConstraintSystem<Fq>>(&self, mut cs: CS, span: &Span) -> Result<Self, GroupError> {
|
||||||
self.allocated(cs.ns(|| format!("allocate affine point {}:{}", span.line, span.start)))
|
self.allocated(cs.ns(|| format!("allocate affine point {}:{}", span.line, span.start)))
|
||||||
.map(|ebg| EdwardsGroupType::Allocated(Box::new(ebg)))
|
.map(|ebg| EdwardsGroupType::Allocated(Box::new(ebg)))
|
||||||
.map_err(|error| GroupError::synthesis_error(error, span))
|
.map_err(|error| GroupError::synthesis_error(error, span.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn negate<CS: ConstraintSystem<Fq>>(&self, cs: CS, span: Span) -> Result<Self, GroupError> {
|
fn negate<CS: ConstraintSystem<Fq>>(&self, cs: CS, span: &Span) -> Result<Self, GroupError> {
|
||||||
match self {
|
match self {
|
||||||
EdwardsGroupType::Constant(group) => Ok(EdwardsGroupType::Constant(group.neg())),
|
EdwardsGroupType::Constant(group) => Ok(EdwardsGroupType::Constant(group.neg())),
|
||||||
EdwardsGroupType::Allocated(group) => {
|
EdwardsGroupType::Allocated(group) => {
|
||||||
let result = <EdwardsBlsGadget as GroupGadget<GroupAffine<EdwardsParameters>, Fq>>::negate(group, cs)
|
let result = <EdwardsBlsGadget as GroupGadget<GroupAffine<EdwardsParameters>, Fq>>::negate(group, cs)
|
||||||
.map_err(|e| GroupError::negate_operation(e, span))?;
|
.map_err(|e| GroupError::negate_operation(e, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(EdwardsGroupType::Allocated(Box::new(result)))
|
Ok(EdwardsGroupType::Allocated(Box::new(result)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add<CS: ConstraintSystem<Fq>>(&self, cs: CS, other: &Self, span: Span) -> Result<Self, GroupError> {
|
fn add<CS: ConstraintSystem<Fq>>(&self, cs: CS, other: &Self, span: &Span) -> Result<Self, GroupError> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(EdwardsGroupType::Constant(self_value), EdwardsGroupType::Constant(other_value)) => {
|
(EdwardsGroupType::Constant(self_value), EdwardsGroupType::Constant(other_value)) => {
|
||||||
Ok(EdwardsGroupType::Constant(self_value.add(other_value)))
|
Ok(EdwardsGroupType::Constant(self_value.add(other_value)))
|
||||||
@ -88,7 +88,7 @@ impl GroupType<Fq> for EdwardsGroupType {
|
|||||||
cs,
|
cs,
|
||||||
other_value,
|
other_value,
|
||||||
)
|
)
|
||||||
.map_err(|e| GroupError::binary_operation("+".to_string(), e, span))?;
|
.map_err(|e| GroupError::binary_operation("+".to_string(), e, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(EdwardsGroupType::Allocated(Box::new(result)))
|
Ok(EdwardsGroupType::Allocated(Box::new(result)))
|
||||||
}
|
}
|
||||||
@ -98,13 +98,13 @@ impl GroupType<Fq> for EdwardsGroupType {
|
|||||||
Ok(EdwardsGroupType::Allocated(Box::new(
|
Ok(EdwardsGroupType::Allocated(Box::new(
|
||||||
allocated_value
|
allocated_value
|
||||||
.add_constant(cs, constant_value)
|
.add_constant(cs, constant_value)
|
||||||
.map_err(|e| GroupError::binary_operation("+".to_string(), e, span))?,
|
.map_err(|e| GroupError::binary_operation("+".to_string(), e, span.to_owned()))?,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub<CS: ConstraintSystem<Fq>>(&self, cs: CS, other: &Self, span: Span) -> Result<Self, GroupError> {
|
fn sub<CS: ConstraintSystem<Fq>>(&self, cs: CS, other: &Self, span: &Span) -> Result<Self, GroupError> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(EdwardsGroupType::Constant(self_value), EdwardsGroupType::Constant(other_value)) => {
|
(EdwardsGroupType::Constant(self_value), EdwardsGroupType::Constant(other_value)) => {
|
||||||
Ok(EdwardsGroupType::Constant(self_value.sub(other_value)))
|
Ok(EdwardsGroupType::Constant(self_value.sub(other_value)))
|
||||||
@ -116,7 +116,7 @@ impl GroupType<Fq> for EdwardsGroupType {
|
|||||||
cs,
|
cs,
|
||||||
other_value,
|
other_value,
|
||||||
)
|
)
|
||||||
.map_err(|e| GroupError::binary_operation("-".to_string(), e, span))?;
|
.map_err(|e| GroupError::binary_operation("-".to_string(), e, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(EdwardsGroupType::Allocated(Box::new(result)))
|
Ok(EdwardsGroupType::Allocated(Box::new(result)))
|
||||||
}
|
}
|
||||||
@ -126,7 +126,7 @@ impl GroupType<Fq> for EdwardsGroupType {
|
|||||||
Ok(EdwardsGroupType::Allocated(Box::new(
|
Ok(EdwardsGroupType::Allocated(Box::new(
|
||||||
allocated_value
|
allocated_value
|
||||||
.sub_constant(cs, constant_value)
|
.sub_constant(cs, constant_value)
|
||||||
.map_err(|e| GroupError::binary_operation("-".to_string(), e, span))?,
|
.map_err(|e| GroupError::binary_operation("-".to_string(), e, span.to_owned()))?,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ use snarkos_models::curves::{Field, PrimeField};
|
|||||||
pub fn enforce_number_implicit<F: Field + PrimeField, G: GroupType<F>>(
|
pub fn enforce_number_implicit<F: Field + PrimeField, G: GroupType<F>>(
|
||||||
expected_type: Option<Type>,
|
expected_type: Option<Type>,
|
||||||
value: String,
|
value: String,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<ConstrainedValue<F, G>, ValueError> {
|
) -> Result<ConstrainedValue<F, G>, ValueError> {
|
||||||
match expected_type {
|
match expected_type {
|
||||||
Some(type_) => Ok(ConstrainedValue::from_type(value, &type_, span)?),
|
Some(type_) => Ok(ConstrainedValue::from_type(value, &type_, span)?),
|
||||||
|
@ -67,40 +67,40 @@ impl fmt::Display for Integer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Integer {
|
impl Integer {
|
||||||
pub fn new_constant(integer_type: &IntegerType, string: String, span: Span) -> Result<Self, IntegerError> {
|
pub fn new_constant(integer_type: &IntegerType, string: String, span: &Span) -> Result<Self, IntegerError> {
|
||||||
match integer_type {
|
match integer_type {
|
||||||
IntegerType::U8 => {
|
IntegerType::U8 => {
|
||||||
let number = string
|
let number = string
|
||||||
.parse::<u8>()
|
.parse::<u8>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(string, span))?;
|
.map_err(|_| IntegerError::invalid_integer(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Integer::U8(UInt8::constant(number)))
|
Ok(Integer::U8(UInt8::constant(number)))
|
||||||
}
|
}
|
||||||
IntegerType::U16 => {
|
IntegerType::U16 => {
|
||||||
let number = string
|
let number = string
|
||||||
.parse::<u16>()
|
.parse::<u16>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(string, span))?;
|
.map_err(|_| IntegerError::invalid_integer(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Integer::U16(UInt16::constant(number)))
|
Ok(Integer::U16(UInt16::constant(number)))
|
||||||
}
|
}
|
||||||
IntegerType::U32 => {
|
IntegerType::U32 => {
|
||||||
let number = string
|
let number = string
|
||||||
.parse::<u32>()
|
.parse::<u32>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(string, span))?;
|
.map_err(|_| IntegerError::invalid_integer(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Integer::U32(UInt32::constant(number)))
|
Ok(Integer::U32(UInt32::constant(number)))
|
||||||
}
|
}
|
||||||
IntegerType::U64 => {
|
IntegerType::U64 => {
|
||||||
let number = string
|
let number = string
|
||||||
.parse::<u64>()
|
.parse::<u64>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(string, span))?;
|
.map_err(|_| IntegerError::invalid_integer(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Integer::U64(UInt64::constant(number)))
|
Ok(Integer::U64(UInt64::constant(number)))
|
||||||
}
|
}
|
||||||
IntegerType::U128 => {
|
IntegerType::U128 => {
|
||||||
let number = string
|
let number = string
|
||||||
.parse::<u128>()
|
.parse::<u128>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(string, span))?;
|
.map_err(|_| IntegerError::invalid_integer(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Integer::U128(UInt128::constant(number)))
|
Ok(Integer::U128(UInt128::constant(number)))
|
||||||
}
|
}
|
||||||
@ -108,35 +108,35 @@ impl Integer {
|
|||||||
IntegerType::I8 => {
|
IntegerType::I8 => {
|
||||||
let number = string
|
let number = string
|
||||||
.parse::<i8>()
|
.parse::<i8>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(string, span))?;
|
.map_err(|_| IntegerError::invalid_integer(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Integer::I8(Int8::constant(number)))
|
Ok(Integer::I8(Int8::constant(number)))
|
||||||
}
|
}
|
||||||
IntegerType::I16 => {
|
IntegerType::I16 => {
|
||||||
let number = string
|
let number = string
|
||||||
.parse::<i16>()
|
.parse::<i16>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(string, span))?;
|
.map_err(|_| IntegerError::invalid_integer(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Integer::I16(Int16::constant(number)))
|
Ok(Integer::I16(Int16::constant(number)))
|
||||||
}
|
}
|
||||||
IntegerType::I32 => {
|
IntegerType::I32 => {
|
||||||
let number = string
|
let number = string
|
||||||
.parse::<i32>()
|
.parse::<i32>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(string, span))?;
|
.map_err(|_| IntegerError::invalid_integer(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Integer::I32(Int32::constant(number)))
|
Ok(Integer::I32(Int32::constant(number)))
|
||||||
}
|
}
|
||||||
IntegerType::I64 => {
|
IntegerType::I64 => {
|
||||||
let number = string
|
let number = string
|
||||||
.parse::<i64>()
|
.parse::<i64>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(string, span))?;
|
.map_err(|_| IntegerError::invalid_integer(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Integer::I64(Int64::constant(number)))
|
Ok(Integer::I64(Int64::constant(number)))
|
||||||
}
|
}
|
||||||
IntegerType::I128 => {
|
IntegerType::I128 => {
|
||||||
let number = string
|
let number = string
|
||||||
.parse::<i128>()
|
.parse::<i128>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(string, span))?;
|
.map_err(|_| IntegerError::invalid_integer(string, span.to_owned()))?;
|
||||||
|
|
||||||
Ok(Integer::I128(Int128::constant(number)))
|
Ok(Integer::I128(Int128::constant(number)))
|
||||||
}
|
}
|
||||||
@ -153,14 +153,14 @@ impl Integer {
|
|||||||
match_integer!(integer => integer.get_value())
|
match_integer!(integer => integer.get_value())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_usize(&self, span: Span) -> Result<usize, IntegerError> {
|
pub fn to_usize(&self, span: &Span) -> Result<usize, IntegerError> {
|
||||||
let unsigned_integer = self;
|
let unsigned_integer = self;
|
||||||
let value_option: Option<String> = match_unsigned_integer!(unsigned_integer => unsigned_integer.get_value());
|
let value_option: Option<String> = match_unsigned_integer!(unsigned_integer => unsigned_integer.get_value());
|
||||||
|
|
||||||
let value = value_option.ok_or_else(|| IntegerError::invalid_index(span.clone()))?;
|
let value = value_option.ok_or_else(|| IntegerError::invalid_index(span.to_owned()))?;
|
||||||
let value_usize = value
|
let value_usize = value
|
||||||
.parse::<usize>()
|
.parse::<usize>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(value, span))?;
|
.map_err(|_| IntegerError::invalid_integer(value, span.to_owned()))?;
|
||||||
Ok(value_usize)
|
Ok(value_usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,9 +183,9 @@ impl Integer {
|
|||||||
pub fn allocate_type<F: Field, CS: ConstraintSystem<F>>(
|
pub fn allocate_type<F: Field, CS: ConstraintSystem<F>>(
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
integer_type: IntegerType,
|
integer_type: IntegerType,
|
||||||
name: String,
|
name: &str,
|
||||||
option: Option<String>,
|
option: Option<String>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<Self, IntegerError> {
|
) -> Result<Self, IntegerError> {
|
||||||
Ok(match integer_type {
|
Ok(match integer_type {
|
||||||
IntegerType::U8 => {
|
IntegerType::U8 => {
|
||||||
@ -194,14 +194,14 @@ impl Integer {
|
|||||||
|
|
||||||
let u8_option = option.map(|s| {
|
let u8_option = option.map(|s| {
|
||||||
s.parse::<u8>()
|
s.parse::<u8>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(s, span.clone()))
|
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
let u8_result = UInt8::alloc(cs.ns(|| u8_name_unique), || {
|
let u8_result = UInt8::alloc(cs.ns(|| u8_name_unique), || {
|
||||||
u8_option.ok_or(SynthesisError::AssignmentMissing)
|
u8_option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| IntegerError::missing_integer(u8_name, span))?;
|
.map_err(|_| IntegerError::missing_integer(u8_name, span.to_owned()))?;
|
||||||
|
|
||||||
Integer::U8(u8_result)
|
Integer::U8(u8_result)
|
||||||
}
|
}
|
||||||
@ -210,13 +210,13 @@ impl Integer {
|
|||||||
let u16_name_unique = format!("`{}` {}:{}", u16_name, span.line, span.start);
|
let u16_name_unique = format!("`{}` {}:{}", u16_name, span.line, span.start);
|
||||||
let u16_option = option.map(|s| {
|
let u16_option = option.map(|s| {
|
||||||
s.parse::<u16>()
|
s.parse::<u16>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(s, span.clone()))
|
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
let u16_result = UInt16::alloc(cs.ns(|| u16_name_unique), || {
|
let u16_result = UInt16::alloc(cs.ns(|| u16_name_unique), || {
|
||||||
u16_option.ok_or(SynthesisError::AssignmentMissing)
|
u16_option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| IntegerError::missing_integer(u16_name, span))?;
|
.map_err(|_| IntegerError::missing_integer(u16_name, span.to_owned()))?;
|
||||||
|
|
||||||
Integer::U16(u16_result)
|
Integer::U16(u16_result)
|
||||||
}
|
}
|
||||||
@ -225,13 +225,13 @@ impl Integer {
|
|||||||
let u32_name_unique = format!("`{}` {}:{}", u32_name, span.line, span.start);
|
let u32_name_unique = format!("`{}` {}:{}", u32_name, span.line, span.start);
|
||||||
let u32_option = option.map(|s| {
|
let u32_option = option.map(|s| {
|
||||||
s.parse::<u32>()
|
s.parse::<u32>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(s, span.clone()))
|
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
let u32_result = UInt32::alloc(cs.ns(|| u32_name_unique), || {
|
let u32_result = UInt32::alloc(cs.ns(|| u32_name_unique), || {
|
||||||
u32_option.ok_or(SynthesisError::AssignmentMissing)
|
u32_option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| IntegerError::missing_integer(u32_name, span))?;
|
.map_err(|_| IntegerError::missing_integer(u32_name, span.to_owned()))?;
|
||||||
|
|
||||||
Integer::U32(u32_result)
|
Integer::U32(u32_result)
|
||||||
}
|
}
|
||||||
@ -240,13 +240,13 @@ impl Integer {
|
|||||||
let u64_name_unique = format!("`{}` {}:{}", u64_name, span.line, span.start);
|
let u64_name_unique = format!("`{}` {}:{}", u64_name, span.line, span.start);
|
||||||
let u64_option = option.map(|s| {
|
let u64_option = option.map(|s| {
|
||||||
s.parse::<u64>()
|
s.parse::<u64>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(s, span.clone()))
|
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
let u64_result = UInt64::alloc(cs.ns(|| u64_name_unique), || {
|
let u64_result = UInt64::alloc(cs.ns(|| u64_name_unique), || {
|
||||||
u64_option.ok_or(SynthesisError::AssignmentMissing)
|
u64_option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| IntegerError::missing_integer(u64_name, span))?;
|
.map_err(|_| IntegerError::missing_integer(u64_name, span.to_owned()))?;
|
||||||
|
|
||||||
Integer::U64(u64_result)
|
Integer::U64(u64_result)
|
||||||
}
|
}
|
||||||
@ -255,13 +255,13 @@ impl Integer {
|
|||||||
let u128_name_unique = format!("`{}` {}:{}", u128_name, span.line, span.start);
|
let u128_name_unique = format!("`{}` {}:{}", u128_name, span.line, span.start);
|
||||||
let u128_option = option.map(|s| {
|
let u128_option = option.map(|s| {
|
||||||
s.parse::<u128>()
|
s.parse::<u128>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(s, span.clone()))
|
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
let u128_result = UInt128::alloc(cs.ns(|| u128_name_unique), || {
|
let u128_result = UInt128::alloc(cs.ns(|| u128_name_unique), || {
|
||||||
u128_option.ok_or(SynthesisError::AssignmentMissing)
|
u128_option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| IntegerError::missing_integer(u128_name, span))?;
|
.map_err(|_| IntegerError::missing_integer(u128_name, span.to_owned()))?;
|
||||||
|
|
||||||
Integer::U128(u128_result)
|
Integer::U128(u128_result)
|
||||||
}
|
}
|
||||||
@ -271,13 +271,13 @@ impl Integer {
|
|||||||
let i8_name_unique = format!("`{}` {}:{}", i8_name, span.line, span.start);
|
let i8_name_unique = format!("`{}` {}:{}", i8_name, span.line, span.start);
|
||||||
let i8_option = option.map(|s| {
|
let i8_option = option.map(|s| {
|
||||||
s.parse::<i8>()
|
s.parse::<i8>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(s, span.clone()))
|
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
let i8_result = Int8::alloc(cs.ns(|| i8_name_unique), || {
|
let i8_result = Int8::alloc(cs.ns(|| i8_name_unique), || {
|
||||||
i8_option.ok_or(SynthesisError::AssignmentMissing)
|
i8_option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| IntegerError::missing_integer(i8_name, span))?;
|
.map_err(|_| IntegerError::missing_integer(i8_name, span.to_owned()))?;
|
||||||
|
|
||||||
Integer::I8(i8_result)
|
Integer::I8(i8_result)
|
||||||
}
|
}
|
||||||
@ -286,13 +286,13 @@ impl Integer {
|
|||||||
let i16_name_unique = format!("`{}` {}:{}", i16_name, span.line, span.start);
|
let i16_name_unique = format!("`{}` {}:{}", i16_name, span.line, span.start);
|
||||||
let i16_option = option.map(|s| {
|
let i16_option = option.map(|s| {
|
||||||
s.parse::<i16>()
|
s.parse::<i16>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(s, span.clone()))
|
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
let i16_result = Int16::alloc(cs.ns(|| i16_name_unique), || {
|
let i16_result = Int16::alloc(cs.ns(|| i16_name_unique), || {
|
||||||
i16_option.ok_or(SynthesisError::AssignmentMissing)
|
i16_option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| IntegerError::missing_integer(i16_name, span))?;
|
.map_err(|_| IntegerError::missing_integer(i16_name, span.to_owned()))?;
|
||||||
|
|
||||||
Integer::I16(i16_result)
|
Integer::I16(i16_result)
|
||||||
}
|
}
|
||||||
@ -301,13 +301,13 @@ impl Integer {
|
|||||||
let i32_name_unique = format!("`{}` {}:{}", i32_name, span.line, span.start);
|
let i32_name_unique = format!("`{}` {}:{}", i32_name, span.line, span.start);
|
||||||
let i32_option = option.map(|s| {
|
let i32_option = option.map(|s| {
|
||||||
s.parse::<i32>()
|
s.parse::<i32>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(s, span.clone()))
|
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
let i32_result = Int32::alloc(cs.ns(|| i32_name_unique), || {
|
let i32_result = Int32::alloc(cs.ns(|| i32_name_unique), || {
|
||||||
i32_option.ok_or(SynthesisError::AssignmentMissing)
|
i32_option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| IntegerError::missing_integer(i32_name, span))?;
|
.map_err(|_| IntegerError::missing_integer(i32_name, span.to_owned()))?;
|
||||||
|
|
||||||
Integer::I32(i32_result)
|
Integer::I32(i32_result)
|
||||||
}
|
}
|
||||||
@ -316,13 +316,13 @@ impl Integer {
|
|||||||
let i64_name_unique = format!("`{}` {}:{}", i64_name, span.line, span.start);
|
let i64_name_unique = format!("`{}` {}:{}", i64_name, span.line, span.start);
|
||||||
let i64_option = option.map(|s| {
|
let i64_option = option.map(|s| {
|
||||||
s.parse::<i64>()
|
s.parse::<i64>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(s, span.clone()))
|
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
let i64_result = Int64::alloc(cs.ns(|| i64_name_unique), || {
|
let i64_result = Int64::alloc(cs.ns(|| i64_name_unique), || {
|
||||||
i64_option.ok_or(SynthesisError::AssignmentMissing)
|
i64_option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| IntegerError::missing_integer(i64_name, span))?;
|
.map_err(|_| IntegerError::missing_integer(i64_name, span.to_owned()))?;
|
||||||
|
|
||||||
Integer::I64(i64_result)
|
Integer::I64(i64_result)
|
||||||
}
|
}
|
||||||
@ -331,13 +331,13 @@ impl Integer {
|
|||||||
let i128_name_unique = format!("`{}` {}:{}", i128_name, span.line, span.start);
|
let i128_name_unique = format!("`{}` {}:{}", i128_name, span.line, span.start);
|
||||||
let i128_option = option.map(|s| {
|
let i128_option = option.map(|s| {
|
||||||
s.parse::<i128>()
|
s.parse::<i128>()
|
||||||
.map_err(|_| IntegerError::invalid_integer(s, span.clone()))
|
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
let i128_result = Int128::alloc(cs.ns(|| i128_name_unique), || {
|
let i128_result = Int128::alloc(cs.ns(|| i128_name_unique), || {
|
||||||
i128_option.ok_or(SynthesisError::AssignmentMissing)
|
i128_option.ok_or(SynthesisError::AssignmentMissing)
|
||||||
})
|
})
|
||||||
.map_err(|_| IntegerError::missing_integer(i128_name, span))?;
|
.map_err(|_| IntegerError::missing_integer(i128_name, span.to_owned()))?;
|
||||||
|
|
||||||
Integer::I128(i128_result)
|
Integer::I128(i128_result)
|
||||||
}
|
}
|
||||||
@ -347,9 +347,9 @@ impl Integer {
|
|||||||
pub fn from_input<F: Field, CS: ConstraintSystem<F>>(
|
pub fn from_input<F: Field, CS: ConstraintSystem<F>>(
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
integer_type: IntegerType,
|
integer_type: IntegerType,
|
||||||
name: String,
|
name: &str,
|
||||||
integer_value: Option<InputValue>,
|
integer_value: Option<InputValue>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<Self, IntegerError> {
|
) -> Result<Self, IntegerError> {
|
||||||
// Check that the input value is the correct type
|
// Check that the input value is the correct type
|
||||||
let option = match integer_value {
|
let option = match integer_value {
|
||||||
@ -357,7 +357,7 @@ impl Integer {
|
|||||||
if let InputValue::Integer(_type_, number) = input {
|
if let InputValue::Integer(_type_, number) = input {
|
||||||
Some(number)
|
Some(number)
|
||||||
} else {
|
} else {
|
||||||
return Err(IntegerError::invalid_integer(input.to_string(), span));
|
return Err(IntegerError::invalid_integer(input.to_string(), span.to_owned()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
@ -369,101 +369,95 @@ impl Integer {
|
|||||||
pub fn negate<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
pub fn negate<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
self,
|
self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<Self, IntegerError> {
|
) -> Result<Self, IntegerError> {
|
||||||
let unique_namespace = format!("enforce -{} {}:{}", self, span.line, span.start);
|
let unique_namespace = format!("enforce -{} {}:{}", self, span.line, span.start);
|
||||||
|
|
||||||
let a = self;
|
let a = self;
|
||||||
let s = span.clone();
|
|
||||||
|
|
||||||
let result = match_signed_integer!(a, s => a.neg(cs.ns(|| unique_namespace)));
|
let result = match_signed_integer!(a, span => a.neg(cs.ns(|| unique_namespace)));
|
||||||
|
|
||||||
result.ok_or_else(|| IntegerError::negate_operation(span))
|
result.ok_or_else(|| IntegerError::negate_operation(span.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
pub fn add<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
self,
|
self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
other: Self,
|
other: Self,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<Self, IntegerError> {
|
) -> Result<Self, IntegerError> {
|
||||||
let unique_namespace = format!("enforce {} + {} {}:{}", self, other, span.line, span.start);
|
let unique_namespace = format!("enforce {} + {} {}:{}", self, other, span.line, span.start);
|
||||||
|
|
||||||
let a = self;
|
let a = self;
|
||||||
let b = other;
|
let b = other;
|
||||||
let s = span.clone();
|
|
||||||
|
|
||||||
let result = match_integers_span!((a, b), s => a.add(cs.ns(|| unique_namespace), &b));
|
let result = match_integers_span!((a, b), span => a.add(cs.ns(|| unique_namespace), &b));
|
||||||
|
|
||||||
result.ok_or_else(|| IntegerError::binary_operation("+".to_string(), span))
|
result.ok_or_else(|| IntegerError::binary_operation("+".to_string(), span.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sub<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
pub fn sub<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
self,
|
self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
other: Self,
|
other: Self,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<Self, IntegerError> {
|
) -> Result<Self, IntegerError> {
|
||||||
let unique_namespace = format!("enforce {} - {} {}:{}", self, other, span.line, span.start);
|
let unique_namespace = format!("enforce {} - {} {}:{}", self, other, span.line, span.start);
|
||||||
|
|
||||||
let a = self;
|
let a = self;
|
||||||
let b = other;
|
let b = other;
|
||||||
let s = span.clone();
|
|
||||||
|
|
||||||
let result = match_integers_span!((a, b), s => a.sub(cs.ns(|| unique_namespace), &b));
|
let result = match_integers_span!((a, b), span => a.sub(cs.ns(|| unique_namespace), &b));
|
||||||
|
|
||||||
result.ok_or_else(|| IntegerError::binary_operation("-".to_string(), span))
|
result.ok_or_else(|| IntegerError::binary_operation("-".to_string(), span.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mul<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
pub fn mul<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
self,
|
self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
other: Self,
|
other: Self,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<Self, IntegerError> {
|
) -> Result<Self, IntegerError> {
|
||||||
let unique_namespace = format!("enforce {} * {} {}:{}", self, other, span.line, span.start);
|
let unique_namespace = format!("enforce {} * {} {}:{}", self, other, span.line, span.start);
|
||||||
|
|
||||||
let a = self;
|
let a = self;
|
||||||
let b = other;
|
let b = other;
|
||||||
let s = span.clone();
|
|
||||||
|
|
||||||
let result = match_integers_span!((a, b), s => a.mul(cs.ns(|| unique_namespace), &b));
|
let result = match_integers_span!((a, b), span => a.mul(cs.ns(|| unique_namespace), &b));
|
||||||
|
|
||||||
result.ok_or_else(|| IntegerError::binary_operation("*".to_string(), span))
|
result.ok_or_else(|| IntegerError::binary_operation("*".to_string(), span.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn div<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
pub fn div<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
self,
|
self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
other: Self,
|
other: Self,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<Self, IntegerError> {
|
) -> Result<Self, IntegerError> {
|
||||||
let unique_namespace = format!("enforce {} ÷ {} {}:{}", self, other, span.line, span.start);
|
let unique_namespace = format!("enforce {} ÷ {} {}:{}", self, other, span.line, span.start);
|
||||||
|
|
||||||
let a = self;
|
let a = self;
|
||||||
let b = other;
|
let b = other;
|
||||||
let s = span.clone();
|
|
||||||
|
|
||||||
let result = match_integers_span!((a, b), s => a.div(cs.ns(|| unique_namespace), &b));
|
let result = match_integers_span!((a, b), span => a.div(cs.ns(|| unique_namespace), &b));
|
||||||
|
|
||||||
result.ok_or_else(|| IntegerError::binary_operation("÷".to_string(), span))
|
result.ok_or_else(|| IntegerError::binary_operation("÷".to_string(), span.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pow<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
pub fn pow<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
self,
|
self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
other: Self,
|
other: Self,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<Self, IntegerError> {
|
) -> Result<Self, IntegerError> {
|
||||||
let unique_namespace = format!("enforce {} ** {} {}:{}", self, other, span.line, span.start);
|
let unique_namespace = format!("enforce {} ** {} {}:{}", self, other, span.line, span.start);
|
||||||
|
|
||||||
let a = self;
|
let a = self;
|
||||||
let b = other;
|
let b = other;
|
||||||
let s = span.clone();
|
|
||||||
|
|
||||||
let result = match_integers_span!((a, b), s => a.pow(cs.ns(|| unique_namespace), &b));
|
let result = match_integers_span!((a, b), span => a.pow(cs.ns(|| unique_namespace), &b));
|
||||||
|
|
||||||
result.ok_or_else(|| IntegerError::binary_operation("**".to_string(), span))
|
result.ok_or_else(|| IntegerError::binary_operation("**".to_string(), span.to_owned()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,11 +84,21 @@ macro_rules! match_unsigned_integer {
|
|||||||
macro_rules! match_signed_integer {
|
macro_rules! match_signed_integer {
|
||||||
($integer: ident, $span: ident => $expression: expr) => {
|
($integer: ident, $span: ident => $expression: expr) => {
|
||||||
match $integer {
|
match $integer {
|
||||||
Integer::I8($integer) => Some(Integer::I8($expression.map_err(|e| IntegerError::signed(e, $span))?)),
|
Integer::I8($integer) => Some(Integer::I8(
|
||||||
Integer::I16($integer) => Some(Integer::I16($expression.map_err(|e| IntegerError::signed(e, $span))?)),
|
$expression.map_err(|e| IntegerError::signed(e, $span.to_owned()))?,
|
||||||
Integer::I32($integer) => Some(Integer::I32($expression.map_err(|e| IntegerError::signed(e, $span))?)),
|
)),
|
||||||
Integer::I64($integer) => Some(Integer::I64($expression.map_err(|e| IntegerError::signed(e, $span))?)),
|
Integer::I16($integer) => Some(Integer::I16(
|
||||||
Integer::I128($integer) => Some(Integer::I128($expression.map_err(|e| IntegerError::signed(e, $span))?)),
|
$expression.map_err(|e| IntegerError::signed(e, $span.to_owned()))?,
|
||||||
|
)),
|
||||||
|
Integer::I32($integer) => Some(Integer::I32(
|
||||||
|
$expression.map_err(|e| IntegerError::signed(e, $span.to_owned()))?,
|
||||||
|
)),
|
||||||
|
Integer::I64($integer) => Some(Integer::I64(
|
||||||
|
$expression.map_err(|e| IntegerError::signed(e, $span.to_owned()))?,
|
||||||
|
)),
|
||||||
|
Integer::I128($integer) => Some(Integer::I128(
|
||||||
|
$expression.map_err(|e| IntegerError::signed(e, $span.to_owned()))?,
|
||||||
|
)),
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@ -119,37 +129,37 @@ macro_rules! match_integers {
|
|||||||
macro_rules! match_integers_span {
|
macro_rules! match_integers_span {
|
||||||
(($a: ident, $b: ident), $span: ident => $expression:expr) => {
|
(($a: ident, $b: ident), $span: ident => $expression:expr) => {
|
||||||
match ($a, $b) {
|
match ($a, $b) {
|
||||||
(Integer::U8($a), Integer::U8($b)) => {
|
(Integer::U8($a), Integer::U8($b)) => Some(Integer::U8(
|
||||||
Some(Integer::U8($expression.map_err(|e| IntegerError::synthesis(e, $span))?))
|
$expression.map_err(|e| IntegerError::synthesis(e, $span.to_owned()))?,
|
||||||
}
|
)),
|
||||||
(Integer::U16($a), Integer::U16($b)) => Some(Integer::U16(
|
(Integer::U16($a), Integer::U16($b)) => Some(Integer::U16(
|
||||||
$expression.map_err(|e| IntegerError::synthesis(e, $span))?,
|
$expression.map_err(|e| IntegerError::synthesis(e, $span.to_owned()))?,
|
||||||
)),
|
)),
|
||||||
(Integer::U32($a), Integer::U32($b)) => Some(Integer::U32(
|
(Integer::U32($a), Integer::U32($b)) => Some(Integer::U32(
|
||||||
$expression.map_err(|e| IntegerError::synthesis(e, $span))?,
|
$expression.map_err(|e| IntegerError::synthesis(e, $span.to_owned()))?,
|
||||||
)),
|
)),
|
||||||
(Integer::U64($a), Integer::U64($b)) => Some(Integer::U64(
|
(Integer::U64($a), Integer::U64($b)) => Some(Integer::U64(
|
||||||
$expression.map_err(|e| IntegerError::synthesis(e, $span))?,
|
$expression.map_err(|e| IntegerError::synthesis(e, $span.to_owned()))?,
|
||||||
)),
|
)),
|
||||||
(Integer::U128($a), Integer::U128($b)) => Some(Integer::U128(
|
(Integer::U128($a), Integer::U128($b)) => Some(Integer::U128(
|
||||||
$expression.map_err(|e| IntegerError::synthesis(e, $span))?,
|
$expression.map_err(|e| IntegerError::synthesis(e, $span.to_owned()))?,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
(Integer::I8($a), Integer::I8($b)) => {
|
(Integer::I8($a), Integer::I8($b)) => Some(Integer::I8(
|
||||||
Some(Integer::I8($expression.map_err(|e| IntegerError::signed(e, $span))?))
|
$expression.map_err(|e| IntegerError::signed(e, $span.to_owned()))?,
|
||||||
}
|
)),
|
||||||
(Integer::I16($a), Integer::I16($b)) => {
|
(Integer::I16($a), Integer::I16($b)) => Some(Integer::I16(
|
||||||
Some(Integer::I16($expression.map_err(|e| IntegerError::signed(e, $span))?))
|
$expression.map_err(|e| IntegerError::signed(e, $span.to_owned()))?,
|
||||||
}
|
)),
|
||||||
(Integer::I32($a), Integer::I32($b)) => {
|
(Integer::I32($a), Integer::I32($b)) => Some(Integer::I32(
|
||||||
Some(Integer::I32($expression.map_err(|e| IntegerError::signed(e, $span))?))
|
$expression.map_err(|e| IntegerError::signed(e, $span.to_owned()))?,
|
||||||
}
|
)),
|
||||||
(Integer::I64($a), Integer::I64($b)) => {
|
(Integer::I64($a), Integer::I64($b)) => Some(Integer::I64(
|
||||||
Some(Integer::I64($expression.map_err(|e| IntegerError::signed(e, $span))?))
|
$expression.map_err(|e| IntegerError::signed(e, $span.to_owned()))?,
|
||||||
}
|
)),
|
||||||
(Integer::I128($a), Integer::I128($b)) => {
|
(Integer::I128($a), Integer::I128($b)) => Some(Integer::I128(
|
||||||
Some(Integer::I128($expression.map_err(|e| IntegerError::signed(e, $span))?))
|
$expression.map_err(|e| IntegerError::signed(e, $span.to_owned()))?,
|
||||||
}
|
)),
|
||||||
(_, _) => None,
|
(_, _) => None,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -74,19 +74,22 @@ pub enum ConstrainedValue<F: Field + PrimeField, G: GroupType<F>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||||
pub(crate) fn from_other(value: String, other: &ConstrainedValue<F, G>, span: Span) -> Result<Self, ValueError> {
|
pub(crate) fn from_other(value: String, other: &ConstrainedValue<F, G>, span: &Span) -> Result<Self, ValueError> {
|
||||||
let other_type = other.to_type(span.clone())?;
|
let other_type = other.to_type(span)?;
|
||||||
|
|
||||||
ConstrainedValue::from_type(value, &other_type, span)
|
ConstrainedValue::from_type(value, &other_type, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_type(value: String, type_: &Type, span: Span) -> Result<Self, ValueError> {
|
pub(crate) fn from_type(value: String, type_: &Type, span: &Span) -> Result<Self, ValueError> {
|
||||||
match type_ {
|
match type_ {
|
||||||
// Data types
|
// Data types
|
||||||
Type::Address => Ok(ConstrainedValue::Address(Address::constant(value, span)?)),
|
Type::Address => Ok(ConstrainedValue::Address(Address::constant(value, span)?)),
|
||||||
Type::Boolean => Ok(ConstrainedValue::Boolean(new_bool_constant(value, span)?)),
|
Type::Boolean => Ok(ConstrainedValue::Boolean(new_bool_constant(value, span)?)),
|
||||||
Type::Field => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)),
|
Type::Field => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)),
|
||||||
Type::Group => Ok(ConstrainedValue::Group(G::constant(GroupValue::Single(value, span))?)),
|
Type::Group => Ok(ConstrainedValue::Group(G::constant(GroupValue::Single(
|
||||||
|
value,
|
||||||
|
span.to_owned(),
|
||||||
|
))?)),
|
||||||
Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(Integer::new_constant(
|
Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(Integer::new_constant(
|
||||||
integer_type,
|
integer_type,
|
||||||
value,
|
value,
|
||||||
@ -99,7 +102,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_type(&self, span: Span) -> Result<Type, ValueError> {
|
pub(crate) fn to_type(&self, span: &Span) -> Result<Type, ValueError> {
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
// Data types
|
// Data types
|
||||||
ConstrainedValue::Address(_address) => Type::Address,
|
ConstrainedValue::Address(_address) => Type::Address,
|
||||||
@ -125,7 +128,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
let mut types = Vec::with_capacity(tuple.len());
|
let mut types = Vec::with_capacity(tuple.len());
|
||||||
|
|
||||||
for value in tuple {
|
for value in tuple {
|
||||||
let type_ = value.to_type(span.clone())?;
|
let type_ = value.to_type(span)?;
|
||||||
types.push(type_)
|
types.push(type_)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +136,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
}
|
}
|
||||||
ConstrainedValue::CircuitExpression(id, _members) => Type::Circuit(id.clone()),
|
ConstrainedValue::CircuitExpression(id, _members) => Type::Circuit(id.clone()),
|
||||||
ConstrainedValue::Mutable(value) => return value.to_type(span),
|
ConstrainedValue::Mutable(value) => return value.to_type(span),
|
||||||
value => return Err(ValueError::implicit(value.to_string(), span)),
|
value => return Err(ValueError::implicit(value.to_string(), span.to_owned())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +171,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn resolve_type(&mut self, type_: Option<Type>, span: Span) -> Result<(), ValueError> {
|
pub(crate) fn resolve_type(&mut self, type_: Option<Type>, span: &Span) -> Result<(), ValueError> {
|
||||||
if let ConstrainedValue::Unresolved(ref string) = self {
|
if let ConstrainedValue::Unresolved(ref string) = self {
|
||||||
if type_.is_some() {
|
if type_.is_some() {
|
||||||
*self = ConstrainedValue::from_type(string.clone(), &type_.unwrap(), span)?
|
*self = ConstrainedValue::from_type(string.clone(), &type_.unwrap(), span)?
|
||||||
@ -183,45 +186,45 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
other: &mut Self,
|
other: &mut Self,
|
||||||
type_: Option<Type>,
|
type_: Option<Type>,
|
||||||
span: Span,
|
span: &Span,
|
||||||
) -> Result<(), ValueError> {
|
) -> Result<(), ValueError> {
|
||||||
if type_.is_some() {
|
if type_.is_some() {
|
||||||
self.resolve_type(type_.clone(), span.clone())?;
|
self.resolve_type(type_.clone(), span)?;
|
||||||
return other.resolve_type(type_, span);
|
return other.resolve_type(type_, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
match (&self, &other) {
|
match (&self, &other) {
|
||||||
(ConstrainedValue::Unresolved(_), ConstrainedValue::Unresolved(_)) => Ok(()),
|
(ConstrainedValue::Unresolved(_), ConstrainedValue::Unresolved(_)) => Ok(()),
|
||||||
(ConstrainedValue::Unresolved(_), _) => self.resolve_type(Some(other.to_type(span.clone())?), span),
|
(ConstrainedValue::Unresolved(_), _) => self.resolve_type(Some(other.to_type(span)?), span),
|
||||||
(_, ConstrainedValue::Unresolved(_)) => other.resolve_type(Some(self.to_type(span.clone())?), span),
|
(_, ConstrainedValue::Unresolved(_)) => other.resolve_type(Some(self.to_type(span)?), span),
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn extract_function(self, scope: String, span: Span) -> Result<(String, Function), ExpressionError> {
|
pub(crate) fn extract_function(self, scope: &str, span: &Span) -> Result<(String, Function), ExpressionError> {
|
||||||
match self {
|
match self {
|
||||||
ConstrainedValue::Function(circuit_identifier, function) => {
|
ConstrainedValue::Function(circuit_identifier, function) => {
|
||||||
let mut outer_scope = scope.clone();
|
let mut outer_scope = scope.to_string();
|
||||||
// If this is a circuit function, evaluate inside the circuit scope
|
// If this is a circuit function, evaluate inside the circuit scope
|
||||||
if let Some(identifier) = circuit_identifier {
|
if let Some(identifier) = circuit_identifier {
|
||||||
// avoid creating recursive scope
|
// avoid creating recursive scope
|
||||||
if !is_in_scope(&scope, &identifier.name) {
|
if !is_in_scope(&scope, &identifier.name) {
|
||||||
outer_scope = new_scope(scope, identifier.name);
|
outer_scope = new_scope(scope, &identifier.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((outer_scope, function))
|
Ok((outer_scope, function))
|
||||||
}
|
}
|
||||||
ConstrainedValue::Import(import_scope, function) => function.extract_function(import_scope, span),
|
ConstrainedValue::Import(import_scope, function) => function.extract_function(&import_scope, span),
|
||||||
value => Err(ExpressionError::undefined_function(value.to_string(), span)),
|
value => Err(ExpressionError::undefined_function(value.to_string(), span.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn extract_circuit(self, span: Span) -> Result<Circuit, ExpressionError> {
|
pub(crate) fn extract_circuit(self, span: &Span) -> Result<Circuit, ExpressionError> {
|
||||||
match self {
|
match self {
|
||||||
ConstrainedValue::CircuitDefinition(circuit) => Ok(circuit),
|
ConstrainedValue::CircuitDefinition(circuit) => Ok(circuit),
|
||||||
ConstrainedValue::Import(_import_scope, circuit) => circuit.extract_circuit(span),
|
ConstrainedValue::Import(_import_scope, circuit) => circuit.extract_circuit(span),
|
||||||
value => Err(ExpressionError::undefined_circuit(value.to_string(), span)),
|
value => Err(ExpressionError::undefined_circuit(value.to_string(), span.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +234,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn allocate_value<CS: ConstraintSystem<F>>(&mut self, mut cs: CS, span: Span) -> Result<(), ValueError> {
|
pub(crate) fn allocate_value<CS: ConstraintSystem<F>>(
|
||||||
|
&mut self,
|
||||||
|
mut cs: CS,
|
||||||
|
span: &Span,
|
||||||
|
) -> Result<(), ValueError> {
|
||||||
match self {
|
match self {
|
||||||
// Data types
|
// Data types
|
||||||
ConstrainedValue::Address(_address) => {
|
ConstrainedValue::Address(_address) => {
|
||||||
@ -243,12 +250,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
.map(|b| b.to_string())
|
.map(|b| b.to_string())
|
||||||
.unwrap_or_else(|| "[allocated]".to_string());
|
.unwrap_or_else(|| "[allocated]".to_string());
|
||||||
|
|
||||||
*boolean = allocate_bool(&mut cs, name, option, span)?;
|
*boolean = allocate_bool(&mut cs, &name, option, span)?;
|
||||||
}
|
}
|
||||||
ConstrainedValue::Field(field) => {
|
ConstrainedValue::Field(field) => {
|
||||||
let gadget = field
|
let gadget = field
|
||||||
.allocated(cs.ns(|| format!("allocate field {}:{}", span.line, span.start)))
|
.allocated(cs.ns(|| format!("allocate field {}:{}", span.line, span.start)))
|
||||||
.map_err(|error| ValueError::FieldError(FieldError::synthesis_error(error, span)))?;
|
.map_err(|error| ValueError::FieldError(FieldError::synthesis_error(error, span.to_owned())))?;
|
||||||
|
|
||||||
*field = FieldType::Allocated(gadget)
|
*field = FieldType::Allocated(gadget)
|
||||||
}
|
}
|
||||||
@ -260,7 +267,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
let option = integer.get_value();
|
let option = integer.get_value();
|
||||||
let name = option.clone().unwrap_or_else(|| "[allocated]".to_string());
|
let name = option.clone().unwrap_or_else(|| "[allocated]".to_string());
|
||||||
|
|
||||||
*integer = Integer::allocate_type(&mut cs, integer_type, name, option, span)?;
|
*integer = Integer::allocate_type(&mut cs, integer_type, &name, option, span)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data type wrappers
|
// Data type wrappers
|
||||||
@ -271,7 +278,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
.map(|(i, value)| {
|
.map(|(i, value)| {
|
||||||
let unique_name = format!("allocate array member {} {}:{}", i, span.line, span.start);
|
let unique_name = format!("allocate array member {} {}:{}", i, span.line, span.start);
|
||||||
|
|
||||||
value.allocate_value(cs.ns(|| unique_name), span.clone())
|
value.allocate_value(cs.ns(|| unique_name), span)
|
||||||
})
|
})
|
||||||
.collect::<Result<(), ValueError>>()?;
|
.collect::<Result<(), ValueError>>()?;
|
||||||
}
|
}
|
||||||
@ -282,7 +289,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
.map(|(i, value)| {
|
.map(|(i, value)| {
|
||||||
let unique_name = format!("allocate tuple member {} {}:{}", i, span.line, span.start);
|
let unique_name = format!("allocate tuple member {} {}:{}", i, span.line, span.start);
|
||||||
|
|
||||||
value.allocate_value(cs.ns(|| unique_name), span.clone())
|
value.allocate_value(cs.ns(|| unique_name), span)
|
||||||
})
|
})
|
||||||
.collect::<Result<(), ValueError>>()?;
|
.collect::<Result<(), ValueError>>()?;
|
||||||
}
|
}
|
||||||
@ -293,7 +300,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
.map(|(i, member)| {
|
.map(|(i, member)| {
|
||||||
let unique_name = format!("allocate circuit member {} {}:{}", i, span.line, span.start);
|
let unique_name = format!("allocate circuit member {} {}:{}", i, span.line, span.start);
|
||||||
|
|
||||||
member.1.allocate_value(cs.ns(|| unique_name), span.clone())
|
member.1.allocate_value(cs.ns(|| unique_name), span)
|
||||||
})
|
})
|
||||||
.collect::<Result<(), ValueError>>()?;
|
.collect::<Result<(), ValueError>>()?;
|
||||||
}
|
}
|
||||||
@ -311,7 +318,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
|||||||
|
|
||||||
// Cannot allocate an unresolved value
|
// Cannot allocate an unresolved value
|
||||||
ConstrainedValue::Unresolved(value) => {
|
ConstrainedValue::Unresolved(value) => {
|
||||||
return Err(ValueError::implicit(value.to_string(), span));
|
return Err(ValueError::implicit(value.to_string(), span.to_owned()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ impl CoreCircuitStructList {
|
|||||||
self.symbols.push((name, circuit))
|
self.symbols.push((name, circuit))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn symbols(&self) -> Vec<(String, Circuit)> {
|
pub fn symbols(&self) -> impl Iterator<Item = &(String, Circuit)> {
|
||||||
self.symbols.clone()
|
self.symbols.iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,8 @@ impl<'ast> From<AstFunction<'ast>> for Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub fn get_name(&self) -> String {
|
pub fn get_name(&self) -> &str {
|
||||||
self.identifier.name.clone()
|
&self.identifier.name
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
Loading…
Reference in New Issue
Block a user