mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-24 18:52:58 +03:00
retrieve import definitions at program execution
This commit is contained in:
parent
14f5f448be
commit
c30a50c5dc
@ -23,28 +23,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
.map(|import| self.store_import(program_name.clone(), import, imported_programs))
|
||||
.collect::<Result<Vec<_>, ImportError>>()?;
|
||||
|
||||
self.store_all(program_name.clone(), &program);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn store_all(&mut self, scope: String, program: &Program) {
|
||||
// evaluate and store all circuit definitions
|
||||
program.circuits.iter().for_each(|(identifier, circuit)| {
|
||||
let resolved_circuit_name = new_scope(scope.clone(), identifier.to_string());
|
||||
self.store(
|
||||
resolved_circuit_name,
|
||||
ConstrainedValue::CircuitDefinition(circuit.clone()),
|
||||
);
|
||||
program.circuits.into_iter().for_each(|(identifier, circuit)| {
|
||||
let resolved_circuit_name = new_scope(program_name.clone(), identifier.to_string());
|
||||
self.store(resolved_circuit_name, ConstrainedValue::CircuitDefinition(circuit));
|
||||
});
|
||||
|
||||
// evaluate and store all function definitions
|
||||
program.functions.iter().for_each(|(function_name, function)| {
|
||||
let resolved_function_name = new_scope(scope.clone(), function_name.to_string());
|
||||
self.store(
|
||||
resolved_function_name,
|
||||
ConstrainedValue::Function(None, function.clone()),
|
||||
);
|
||||
program.functions.into_iter().for_each(|(function_name, function)| {
|
||||
let resolved_function_name = new_scope(program_name.clone(), function_name.to_string());
|
||||
self.store(resolved_function_name, ConstrainedValue::Function(None, function));
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -10,14 +10,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
import: &Import,
|
||||
imported_programs: &ImportedPrograms,
|
||||
) -> Result<(), ImportError> {
|
||||
println!("program name {}", scope);
|
||||
println!("import {}", import);
|
||||
|
||||
// get imported program name from import
|
||||
// get imported symbols from from import
|
||||
let imported_symbols = ImportedSymbols::from(import);
|
||||
let program_name = imported_symbols.name.clone();
|
||||
println!("symbols {:?}", imported_symbols);
|
||||
|
||||
// get imported program from hashmap
|
||||
let program = imported_programs
|
||||
@ -35,7 +31,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
imported_symbols
|
||||
.symbols
|
||||
.iter()
|
||||
.map(|symbol| self.store_symbol(scope.clone(), symbol, program))
|
||||
.map(|symbol| self.store_symbol(scope.clone(), program_name.clone(), symbol, program))
|
||||
.collect::<Result<Vec<()>, ImportError>>()?;
|
||||
|
||||
Ok(())
|
||||
|
@ -7,19 +7,44 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
pub(crate) fn store_symbol(
|
||||
&mut self,
|
||||
scope: String,
|
||||
program_name: String,
|
||||
symbol: &ImportSymbol,
|
||||
program: &Program,
|
||||
) -> Result<(), ImportError> {
|
||||
if symbol.is_star() {
|
||||
self.store_all(scope, program);
|
||||
// evaluate and store all circuit definitions
|
||||
program.circuits.iter().for_each(|(identifier, circuit)| {
|
||||
let name = new_scope(scope.clone(), identifier.to_string());
|
||||
let value = ConstrainedValue::Import(
|
||||
program_name.clone(),
|
||||
Box::new(ConstrainedValue::CircuitDefinition(circuit.clone())),
|
||||
);
|
||||
|
||||
self.store(name, value);
|
||||
});
|
||||
|
||||
// evaluate and store all function definitions
|
||||
program.functions.iter().for_each(|(identifier, function)| {
|
||||
let name = new_scope(scope.clone(), identifier.to_string());
|
||||
let value = ConstrainedValue::Import(
|
||||
program_name.clone(),
|
||||
Box::new(ConstrainedValue::Function(None, function.clone())),
|
||||
);
|
||||
|
||||
self.store(name, value);
|
||||
});
|
||||
} else {
|
||||
// see if the imported symbol is a circuit
|
||||
let matched_circuit = program
|
||||
.circuits
|
||||
.iter()
|
||||
.find(|(circuit_name, _circuit_def)| symbol.symbol == **circuit_name);
|
||||
|
||||
let value = match matched_circuit {
|
||||
Some((_circuit_name, circuit_def)) => ConstrainedValue::CircuitDefinition(circuit_def.clone()),
|
||||
Some((_circuit_name, circuit)) => ConstrainedValue::Import(
|
||||
program_name.clone(),
|
||||
Box::new(ConstrainedValue::CircuitDefinition(circuit.clone())),
|
||||
),
|
||||
None => {
|
||||
// see if the imported symbol is a function
|
||||
let matched_function = program
|
||||
@ -28,18 +53,21 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
.find(|(function_name, _function)| symbol.symbol == **function_name);
|
||||
|
||||
match matched_function {
|
||||
Some((_function_name, function)) => ConstrainedValue::Function(None, function.clone()),
|
||||
Some((_function_name, function)) => ConstrainedValue::Import(
|
||||
program_name.clone(),
|
||||
Box::new(ConstrainedValue::Function(None, function.clone())),
|
||||
),
|
||||
None => return Err(ImportError::unknown_symbol(symbol.to_owned(), scope)),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// take the alias if it is present
|
||||
let name = symbol.alias.clone().unwrap_or(symbol.symbol.clone());
|
||||
let resolved_name = new_scope(scope, name.to_string());
|
||||
let id = symbol.alias.clone().unwrap_or(symbol.symbol.clone());
|
||||
let name = new_scope(scope, id.to_string());
|
||||
|
||||
// store imported circuit under resolved name
|
||||
self.store(resolved_name, value);
|
||||
// store imported circuit under imported name
|
||||
self.store(name, value);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -51,6 +51,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
} else if let Some(value) = self.get(&identifier_name) {
|
||||
// Check global scope (function and circuit names)
|
||||
value.clone()
|
||||
} else if let Some(value) = self.get(&unresolved_identifier.name) {
|
||||
// Check imported file scope
|
||||
value.clone()
|
||||
} else {
|
||||
return Err(ExpressionError::undefined_identifier(unresolved_identifier));
|
||||
};
|
||||
@ -609,53 +612,55 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
program_identifier = file_scope.clone();
|
||||
}
|
||||
|
||||
if let Some(ConstrainedValue::CircuitDefinition(circuit_definition)) = self.get_mut(&program_identifier) {
|
||||
let circuit_identifier = circuit_definition.circuit_name.clone();
|
||||
let mut resolved_members = vec![];
|
||||
for member in circuit_definition.members.clone().into_iter() {
|
||||
match member {
|
||||
CircuitMember::CircuitField(identifier, _type) => {
|
||||
let matched_field = members
|
||||
.clone()
|
||||
.into_iter()
|
||||
.find(|field| field.identifier.eq(&identifier));
|
||||
match matched_field {
|
||||
Some(field) => {
|
||||
// Resolve and enforce circuit object
|
||||
let field_value = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
&vec![_type.clone()],
|
||||
field.expression,
|
||||
)?;
|
||||
let circuit = match self.get(&program_identifier) {
|
||||
Some(value) => value.clone().extract_circuit(span.clone())?,
|
||||
None => return Err(ExpressionError::undefined_circuit(identifier.to_string(), span)),
|
||||
};
|
||||
|
||||
resolved_members.push(ConstrainedCircuitMember(identifier, field_value))
|
||||
}
|
||||
None => return Err(ExpressionError::expected_circuit_member(identifier.to_string(), span)),
|
||||
let circuit_identifier = circuit.circuit_name.clone();
|
||||
let mut resolved_members = vec![];
|
||||
|
||||
for member in circuit.members.clone().into_iter() {
|
||||
match member {
|
||||
CircuitMember::CircuitField(identifier, _type) => {
|
||||
let matched_field = members
|
||||
.clone()
|
||||
.into_iter()
|
||||
.find(|field| field.identifier.eq(&identifier));
|
||||
match matched_field {
|
||||
Some(field) => {
|
||||
// Resolve and enforce circuit object
|
||||
let field_value = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
&vec![_type.clone()],
|
||||
field.expression,
|
||||
)?;
|
||||
|
||||
resolved_members.push(ConstrainedCircuitMember(identifier, field_value))
|
||||
}
|
||||
None => return Err(ExpressionError::expected_circuit_member(identifier.to_string(), span)),
|
||||
}
|
||||
CircuitMember::CircuitFunction(_static, function) => {
|
||||
let identifier = function.function_name.clone();
|
||||
let mut constrained_function_value =
|
||||
ConstrainedValue::Function(Some(circuit_identifier.clone()), function);
|
||||
}
|
||||
CircuitMember::CircuitFunction(_static, function) => {
|
||||
let identifier = function.function_name.clone();
|
||||
let mut constrained_function_value =
|
||||
ConstrainedValue::Function(Some(circuit_identifier.clone()), function);
|
||||
|
||||
if _static {
|
||||
constrained_function_value = ConstrainedValue::Static(Box::new(constrained_function_value));
|
||||
}
|
||||
|
||||
resolved_members.push(ConstrainedCircuitMember(identifier, constrained_function_value));
|
||||
if _static {
|
||||
constrained_function_value = ConstrainedValue::Static(Box::new(constrained_function_value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(ConstrainedValue::CircuitExpression(
|
||||
circuit_identifier.clone(),
|
||||
resolved_members,
|
||||
))
|
||||
} else {
|
||||
Err(ExpressionError::undefined_circuit(identifier.to_string(), span))
|
||||
resolved_members.push(ConstrainedCircuitMember(identifier, constrained_function_value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(ConstrainedValue::CircuitExpression(
|
||||
circuit_identifier.clone(),
|
||||
resolved_members,
|
||||
))
|
||||
}
|
||||
|
||||
fn enforce_circuit_access_expression<CS: ConstraintSystem<F>>(
|
||||
@ -786,18 +791,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
*function.clone(),
|
||||
)?;
|
||||
|
||||
let (outer_scope, function_call) = match function_value {
|
||||
ConstrainedValue::Function(circuit_identifier, function) => {
|
||||
let mut outer_scope = file_scope.clone();
|
||||
// If this is a circuit function, evaluate inside the circuit scope
|
||||
if circuit_identifier.is_some() {
|
||||
outer_scope = new_scope(file_scope, circuit_identifier.unwrap().to_string());
|
||||
}
|
||||
|
||||
(outer_scope, function.clone())
|
||||
}
|
||||
value => return Err(ExpressionError::undefined_function(value.to_string(), span)),
|
||||
};
|
||||
let (outer_scope, function_call) = function_value.extract_function(file_scope, span.clone())?;
|
||||
|
||||
let name_unique = format!(
|
||||
"function call {} {}:{}",
|
||||
|
@ -6,11 +6,13 @@ use crate::{
|
||||
allocate_group,
|
||||
errors::ValueError,
|
||||
new_bool_constant,
|
||||
new_scope,
|
||||
FieldType,
|
||||
GroupType,
|
||||
};
|
||||
use leo_types::{Circuit, Function, Identifier, Integer, Span, Type};
|
||||
|
||||
use crate::errors::ExpressionError;
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
@ -41,6 +43,7 @@ pub enum ConstrainedValue<F: Field + PrimeField, G: GroupType<F>> {
|
||||
|
||||
Mutable(Box<ConstrainedValue<F, G>>),
|
||||
Static(Box<ConstrainedValue<F, G>>),
|
||||
Import(String, Box<ConstrainedValue<F, G>>),
|
||||
Unresolved(String),
|
||||
}
|
||||
|
||||
@ -115,6 +118,30 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn extract_function(self, scope: String, span: Span) -> Result<(String, Function), ExpressionError> {
|
||||
match self {
|
||||
ConstrainedValue::Function(circuit_identifier, function) => {
|
||||
let mut outer_scope = scope.clone();
|
||||
// If this is a circuit function, evaluate inside the circuit scope
|
||||
if circuit_identifier.is_some() {
|
||||
outer_scope = new_scope(scope, circuit_identifier.unwrap().to_string());
|
||||
}
|
||||
|
||||
Ok((outer_scope, function.clone()))
|
||||
}
|
||||
ConstrainedValue::Import(import_scope, function) => function.extract_function(import_scope, span),
|
||||
value => return Err(ExpressionError::undefined_function(value.to_string(), span)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn extract_circuit(self, span: Span) -> Result<Circuit, ExpressionError> {
|
||||
match self {
|
||||
ConstrainedValue::CircuitDefinition(circuit) => Ok(circuit),
|
||||
ConstrainedValue::Import(_import_scope, circuit) => circuit.extract_circuit(span),
|
||||
value => return Err(ExpressionError::undefined_circuit(value.to_string(), span)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_inner_mut(&mut self) {
|
||||
if let ConstrainedValue::Mutable(inner) = self {
|
||||
*self = *inner.clone()
|
||||
@ -192,6 +219,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
// empty wrappers
|
||||
ConstrainedValue::CircuitDefinition(_) => {}
|
||||
ConstrainedValue::Function(_, _) => {}
|
||||
ConstrainedValue::Import(_, _) => {}
|
||||
|
||||
ConstrainedValue::Unresolved(value) => {
|
||||
return Err(ValueError::implicit(value.to_string(), span));
|
||||
}
|
||||
@ -249,6 +278,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> fmt::Display for ConstrainedValue<F
|
||||
ConstrainedValue::Function(ref _circuit_option, ref function) => {
|
||||
write!(f, "function {{ {}() }}", function.function_name)
|
||||
}
|
||||
ConstrainedValue::Import(_, ref value) => write!(f, "{}", value),
|
||||
ConstrainedValue::Mutable(ref value) => write!(f, "mut {}", value),
|
||||
ConstrainedValue::Static(ref value) => write!(f, "static {}", value),
|
||||
ConstrainedValue::Unresolved(ref value) => write!(f, "unresolved {}", value),
|
||||
|
@ -17,7 +17,6 @@ impl ImportedPrograms {
|
||||
|
||||
pub(crate) fn store(&mut self, file_name: String, program: Program) {
|
||||
// todo: handle conflicting versions for duplicate imports here
|
||||
println!("storing: {},\n {:?}", file_name, program);
|
||||
let _res = self.imports.insert(file_name, program);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user