add definition statement module

This commit is contained in:
collin 2020-07-08 01:58:45 -07:00
parent 51ee4894c7
commit 6d4a34d0ec
8 changed files with 143 additions and 101 deletions

View File

@ -0,0 +1,28 @@
//! Stores all defined names in a compiled Leo program.
use crate::{
program::{new_scope, ConstrainedProgram},
value::ConstrainedValue,
GroupType,
};
use leo_types::Variable;
use snarkos_models::curves::{Field, PrimeField};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn store_definition(
&mut self,
function_scope: String,
variable: Variable,
mut value: ConstrainedValue<F, G>,
) -> () {
// Store with given mutability
if variable.mutable {
value = ConstrainedValue::Mutable(Box::new(value));
}
let variable_program_identifier = new_scope(function_scope, variable.identifier.name);
self.store(variable_program_identifier, value);
}
}

View File

@ -12,11 +12,7 @@ use leo_types::Program;
use snarkos_models::curves::{Field, PrimeField};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub(crate) fn store_definitions(
&mut self,
program: Program,
imported_programs: &ImportParser,
) -> Result<(), ImportError> {
pub fn store_definitions(&mut self, program: Program, imported_programs: &ImportParser) -> Result<(), ImportError> {
let program_name = program.name.clone();
// evaluate all import statements and store imported definitions

View File

@ -1,2 +1,5 @@
pub mod definition;
pub use self::definition::*;
pub mod definitions;
pub use self::definitions::*;

View File

@ -0,0 +1,47 @@
//! Enforces a definition statement in a compiled Leo program.
use crate::{errors::StatementError, program::ConstrainedProgram, GroupType};
use leo_types::{Declare, Expression, Span, Variable};
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::r1cs::ConstraintSystem,
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn enforce_definition_statement<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
declare: Declare,
variable: Variable,
expression: Expression,
span: Span,
) -> Result<(), StatementError> {
let mut expected_types = vec![];
if let Some(ref _type) = variable._type {
expected_types.push(_type.clone());
}
let mut value = self.enforce_expression(
cs,
file_scope.clone(),
function_scope.clone(),
&expected_types,
expression,
)?;
match declare {
Declare::Let => value.allocate_value(cs, span)?,
Declare::Const => {
if variable.mutable {
return Err(StatementError::immutable_assign(variable.to_string(), span));
}
}
}
self.store_definition(function_scope, variable, value);
Ok(())
}
}

View File

@ -0,0 +1,7 @@
//! Methods to enforce constraints on definition statements in a compiled Leo program.
pub mod definition;
pub use self::definition::*;
pub mod multiple;
pub use self::multiple::*;

View File

@ -0,0 +1,54 @@
//! Enforces a multiple definition statement in a compiled Leo program.
use crate::{errors::StatementError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_types::{Expression, Span, Variable};
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::r1cs::ConstraintSystem,
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn enforce_multiple_definition_statement<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
variables: Vec<Variable>,
function: Expression,
span: Span,
) -> Result<(), StatementError> {
let mut expected_types = vec![];
for variable in variables.iter() {
if let Some(ref _type) = variable._type {
expected_types.push(_type.clone());
}
}
// Expect return values from function
let return_values = match self.enforce_expression(
cs,
file_scope.clone(),
function_scope.clone(),
&expected_types,
function,
)? {
ConstrainedValue::Return(values) => values,
value => unimplemented!("multiple assignment only implemented for functions, got {}", value),
};
if variables.len() != return_values.len() {
return Err(StatementError::invalid_number_of_definitions(
variables.len(),
return_values.len(),
span,
));
}
for (variable, value) in variables.into_iter().zip(return_values.into_iter()) {
self.store_definition(function_scope.clone(), variable, value);
}
Ok(())
}
}

View File

@ -1,3 +1,6 @@
pub mod definition;
pub use self::definition::*;
pub mod return_;
pub use self::return_::*;

View File

@ -12,14 +12,12 @@ use leo_types::{
Assignee,
ConditionalNestedOrEndStatement,
ConditionalStatement,
Declare,
Expression,
Identifier,
RangeOrExpression,
Span,
Statement,
Type,
Variable,
};
use snarkos_models::{
@ -237,100 +235,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
}
}
fn store_definition(
&mut self,
function_scope: String,
variable: Variable,
mut value: ConstrainedValue<F, G>,
) -> Result<(), StatementError> {
// Store with given mutability
if variable.mutable {
value = ConstrainedValue::Mutable(Box::new(value));
}
let variable_program_identifier = new_scope(function_scope, variable.identifier.name);
self.store(variable_program_identifier, value);
Ok(())
}
fn enforce_definition_statement<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
declare: Declare,
variable: Variable,
expression: Expression,
span: Span,
) -> Result<(), StatementError> {
let mut expected_types = vec![];
if let Some(ref _type) = variable._type {
expected_types.push(_type.clone());
}
let mut value = self.enforce_expression(
cs,
file_scope.clone(),
function_scope.clone(),
&expected_types,
expression,
)?;
match declare {
Declare::Let => value.allocate_value(cs, span)?,
Declare::Const => {
if variable.mutable {
return Err(StatementError::immutable_assign(variable.to_string(), span));
}
}
}
self.store_definition(function_scope, variable, value)
}
fn enforce_multiple_definition_statement<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
variables: Vec<Variable>,
function: Expression,
span: Span,
) -> Result<(), StatementError> {
let mut expected_types = vec![];
for variable in variables.iter() {
if let Some(ref _type) = variable._type {
expected_types.push(_type.clone());
}
}
// Expect return values from function
let return_values = match self.enforce_expression(
cs,
file_scope.clone(),
function_scope.clone(),
&expected_types,
function,
)? {
ConstrainedValue::Return(values) => values,
value => unimplemented!("multiple assignment only implemented for functions, got {}", value),
};
if variables.len() != return_values.len() {
return Err(StatementError::invalid_number_of_definitions(
variables.len(),
return_values.len(),
span,
));
}
for (variable, value) in variables.into_iter().zip(return_values.into_iter()) {
self.store_definition(function_scope.clone(), variable, value)?;
}
Ok(())
}
fn evaluate_branch<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,