make circuit naming consistent. return proper errors

This commit is contained in:
collin 2020-05-14 13:32:16 -07:00
parent 5fb0b58b68
commit 44b4df2404
15 changed files with 191 additions and 202 deletions

View File

@ -1,14 +1,14 @@
circuit PedersenHash { circuit PedersenHash {
parameters: group[1] parameters: group[1]
static function new(b: u32) -> u32 { function new(b: u32) -> u32 {
return b return b
} }
} }
function main() -> u32{ function main() -> u32{
let parameters = [0group; 1]; let parameters = [0group; 1];
let pedersen = PedersenHash { parameters: parameters }; let mut pedersen = PedersenHash { parameters: parameters };
let b = PedersenHash::new(3); let b = PedersenHash::new(3);
return b return b

View File

@ -438,16 +438,16 @@ pub struct ArrayAccess<'ast> {
} }
#[derive(Clone, Debug, FromPest, PartialEq)] #[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::access_object))] #[pest_ast(rule(Rule::access_member))]
pub struct ObjectAccess<'ast> { pub struct MemberAccess<'ast> {
pub identifier: Identifier<'ast>, pub identifier: Identifier<'ast>,
#[pest_ast(outer())] #[pest_ast(outer())]
pub span: Span<'ast>, pub span: Span<'ast>,
} }
#[derive(Clone, Debug, FromPest, PartialEq)] #[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::access_static_object))] #[pest_ast(rule(Rule::access_static_member))]
pub struct StaticObjectAccess<'ast> { pub struct StaticMemberAccess<'ast> {
pub identifier: Identifier<'ast>, pub identifier: Identifier<'ast>,
#[pest_ast(outer())] #[pest_ast(outer())]
pub span: Span<'ast>, pub span: Span<'ast>,
@ -458,8 +458,8 @@ pub struct StaticObjectAccess<'ast> {
pub enum Access<'ast> { pub enum Access<'ast> {
Array(ArrayAccess<'ast>), Array(ArrayAccess<'ast>),
Call(CallAccess<'ast>), Call(CallAccess<'ast>),
Object(ObjectAccess<'ast>), Object(MemberAccess<'ast>),
StaticObject(StaticObjectAccess<'ast>), StaticObject(StaticMemberAccess<'ast>),
} }
#[derive(Clone, Debug, FromPest, PartialEq)] #[derive(Clone, Debug, FromPest, PartialEq)]
@ -475,7 +475,7 @@ pub struct PostfixExpression<'ast> {
#[pest_ast(rule(Rule::assignee_access))] #[pest_ast(rule(Rule::assignee_access))]
pub enum AssigneeAccess<'ast> { pub enum AssigneeAccess<'ast> {
Array(ArrayAccess<'ast>), Array(ArrayAccess<'ast>),
Member(ObjectAccess<'ast>), Member(MemberAccess<'ast>),
} }
impl<'ast> fmt::Display for AssigneeAccess<'ast> { impl<'ast> fmt::Display for AssigneeAccess<'ast> {
@ -561,8 +561,8 @@ pub struct ArrayInitializerExpression<'ast> {
// Circuits // Circuits
#[derive(Clone, Debug, FromPest, PartialEq)] #[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::circuit_value))] #[pest_ast(rule(Rule::circuit_field_definition))]
pub struct CircuitValue<'ast> { pub struct CircuitFieldDefinition<'ast> {
pub identifier: Identifier<'ast>, pub identifier: Identifier<'ast>,
pub _type: Type<'ast>, pub _type: Type<'ast>,
#[pest_ast(outer())] #[pest_ast(outer())]
@ -583,9 +583,9 @@ pub struct CircuitFunction<'ast> {
} }
#[derive(Clone, Debug, FromPest, PartialEq)] #[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::circuit_object))] #[pest_ast(rule(Rule::circuit_member))]
pub enum CircuitObject<'ast> { pub enum CircuitMember<'ast> {
CircuitValue(CircuitValue<'ast>), CircuitFieldDefinition(CircuitFieldDefinition<'ast>),
CircuitFunction(CircuitFunction<'ast>), CircuitFunction(CircuitFunction<'ast>),
} }
@ -593,14 +593,14 @@ pub enum CircuitObject<'ast> {
#[pest_ast(rule(Rule::circuit_definition))] #[pest_ast(rule(Rule::circuit_definition))]
pub struct Circuit<'ast> { pub struct Circuit<'ast> {
pub identifier: Identifier<'ast>, pub identifier: Identifier<'ast>,
pub fields: Vec<CircuitObject<'ast>>, pub members: Vec<CircuitMember<'ast>>,
#[pest_ast(outer())] #[pest_ast(outer())]
pub span: Span<'ast>, pub span: Span<'ast>,
} }
#[derive(Clone, Debug, FromPest, PartialEq)] #[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::inline_circuit_member))] #[pest_ast(rule(Rule::circuit_field))]
pub struct InlineCircuitMember<'ast> { pub struct CircuitField<'ast> {
pub identifier: Identifier<'ast>, pub identifier: Identifier<'ast>,
pub expression: Expression<'ast>, pub expression: Expression<'ast>,
#[pest_ast(outer())] #[pest_ast(outer())]
@ -608,10 +608,10 @@ pub struct InlineCircuitMember<'ast> {
} }
#[derive(Clone, Debug, FromPest, PartialEq)] #[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::expression_inline_circuit))] #[pest_ast(rule(Rule::expression_circuit_inline))]
pub struct CircuitInlineExpression<'ast> { pub struct CircuitInlineExpression<'ast> {
pub identifier: Identifier<'ast>, pub identifier: Identifier<'ast>,
pub members: Vec<InlineCircuitMember<'ast>>, pub members: Vec<CircuitField<'ast>>,
#[pest_ast(outer())] #[pest_ast(outer())]
pub span: Span<'ast>, pub span: Span<'ast>,
} }
@ -787,7 +787,7 @@ fn parse_term(pair: Pair<Rule>) -> Box<Expression> {
let next = clone.into_inner().next().unwrap(); let next = clone.into_inner().next().unwrap();
match next.as_rule() { match next.as_rule() {
Rule::expression => Expression::from_pest(&mut pair.into_inner()).unwrap(), // Parenthesis case Rule::expression => Expression::from_pest(&mut pair.into_inner()).unwrap(), // Parenthesis case
Rule::expression_inline_circuit => { Rule::expression_circuit_inline => {
Expression::CircuitInline( Expression::CircuitInline(
CircuitInlineExpression::from_pest(&mut pair.into_inner()).unwrap(), CircuitInlineExpression::from_pest(&mut pair.into_inner()).unwrap(),
) )

View File

@ -2,13 +2,14 @@
use crate::{ use crate::{
constraints::{ constraints::{
new_scope_from_variable, new_variable_from_variable, ConstrainedCircuitObject, new_scope_from_variable, new_variable_from_variable, ConstrainedCircuitMember,
ConstrainedProgram, ConstrainedValue, ConstrainedProgram, ConstrainedValue,
}, },
errors::ExpressionError, errors::ExpressionError,
new_scope, new_scope,
types::{ types::{
CircuitMember, CircuitObject, Expression, Identifier, RangeOrExpression, SpreadOrExpression, CircuitFieldDefinition, CircuitMember, Expression, Identifier, RangeOrExpression,
SpreadOrExpression,
}, },
}; };
@ -354,7 +355,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
file_scope: String, file_scope: String,
function_scope: String, function_scope: String,
variable: Identifier<F, G>, variable: Identifier<F, G>,
members: Vec<CircuitMember<F, G>>, members: Vec<CircuitFieldDefinition<F, G>>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let circuit_name = new_variable_from_variable(file_scope.clone(), &variable); let circuit_name = new_variable_from_variable(file_scope.clone(), &variable);
@ -362,28 +363,28 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
self.get_mut_variable(&circuit_name) self.get_mut_variable(&circuit_name)
{ {
let mut resolved_members = vec![]; let mut resolved_members = vec![];
for object in circuit_definition.objects.clone().into_iter() { for member in circuit_definition.members.clone().into_iter() {
match object { match member {
CircuitObject::CircuitValue(identifier, _type) => { CircuitMember::CircuitField(identifier, _type) => {
let matched_member = members let matched_field = members
.clone() .clone()
.into_iter() .into_iter()
.find(|member| member.identifier.eq(&identifier)); .find(|field| field.identifier.eq(&identifier));
match matched_member { match matched_field {
Some(member) => { Some(field) => {
// Resolve and enforce circuit object // Resolve and enforce circuit object
let member_value = self.enforce_expression( let field_value = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
member.expression, field.expression,
)?; )?;
// Check member type // Check field type
member_value.expect_type(&_type)?; field_value.expect_type(&_type)?;
resolved_members resolved_members
.push(ConstrainedCircuitObject(identifier, member_value)) .push(ConstrainedCircuitMember(identifier, field_value))
} }
None => { None => {
return Err(ExpressionError::ExpectedCircuitValue( return Err(ExpressionError::ExpectedCircuitValue(
@ -392,16 +393,16 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
} }
} }
CircuitObject::CircuitFunction(_static, function) => { CircuitMember::CircuitFunction(_static, function) => {
let identifier = function.function_name.clone(); let identifier = function.function_name.clone();
let mut constrained_function_value = ConstrainedValue::Function(function); let mut constrained_function_value = ConstrainedValue::Function(function);
if _static { if _static {
constrained_function_value = constrained_function_value =
ConstrainedValue::Mutable(Box::new(constrained_function_value)); ConstrainedValue::Static(Box::new(constrained_function_value));
} }
resolved_members.push(ConstrainedCircuitObject( resolved_members.push(ConstrainedCircuitMember(
identifier, identifier,
constrained_function_value, constrained_function_value,
)); ));
@ -472,14 +473,14 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
}; };
// Find static circuit function // Find static circuit function
let matched_function = circuit.objects.into_iter().find(|member| match member { let matched_function = circuit.members.into_iter().find(|member| match member {
CircuitObject::CircuitFunction(_static, _function) => *_static, CircuitMember::CircuitFunction(_static, _function) => *_static,
_ => false, _ => false,
}); });
// Return errors if no static function exists // Return errors if no static function exists
let function = match matched_function { let function = match matched_function {
Some(CircuitObject::CircuitFunction(_static, function)) => { Some(CircuitMember::CircuitFunction(_static, function)) => {
if _static { if _static {
function function
} else { } else {
@ -740,7 +741,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
circuit_name, circuit_name,
members, members,
), ),
Expression::CircuitObjectAccess(circuit_variable, circuit_member) => self Expression::CircuitMemberAccess(circuit_variable, circuit_member) => self
.enforce_circuit_access_expression( .enforce_circuit_access_expression(
cs, cs,
file_scope, file_scope,
@ -748,7 +749,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
circuit_variable, circuit_variable,
circuit_member, circuit_member,
), ),
Expression::CircuitStaticObjectAccess(circuit_identifier, circuit_member) => self Expression::CircuitStaticFunctionAccess(circuit_identifier, circuit_member) => self
.enforce_circuit_static_access_expression( .enforce_circuit_static_access_expression(
cs, cs,
file_scope, file_scope,

View File

@ -2,7 +2,7 @@
//! a resolved Leo program. //! a resolved Leo program.
use crate::{ use crate::{
constraints::{new_scope, new_variable_from_variables, ConstrainedProgram, ConstrainedValue}, constraints::{new_scope, ConstrainedProgram, ConstrainedValue},
errors::{FunctionError, ImportError}, errors::{FunctionError, ImportError},
types::{Expression, Function, Identifier, InputValue, Program, Type}, types::{Expression, Function, Identifier, InputValue, Program, Type},
}; };
@ -231,12 +231,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
program program
.circuits .circuits
.into_iter() .into_iter()
.for_each(|(variable, circuit_def)| { .for_each(|(identifier, circuit)| {
let resolved_circuit_name = let resolved_circuit_name =
new_variable_from_variables(&program_name.clone(), &variable); new_scope(program_name.to_string(), identifier.to_string());
self.store_variable( self.store(
resolved_circuit_name, resolved_circuit_name,
ConstrainedValue::CircuitDefinition(circuit_def), ConstrainedValue::CircuitDefinition(circuit),
); );
}); });
@ -246,7 +246,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
.into_iter() .into_iter()
.for_each(|(function_name, function)| { .for_each(|(function_name, function)| {
let resolved_function_name = let resolved_function_name =
new_scope(program_name.name.clone(), function_name.name); new_scope(program_name.to_string(), function_name.to_string());
self.store(resolved_function_name, ConstrainedValue::Function(function)); self.store(resolved_function_name, ConstrainedValue::Function(function));
}); });

View File

@ -1,7 +1,8 @@
use crate::{ use crate::{
ast, ast,
constraints::{new_variable_from_variables, ConstrainedProgram, ConstrainedValue}, constraints::{ConstrainedProgram, ConstrainedValue},
errors::constraints::ImportError, errors::constraints::ImportError,
new_scope,
types::Program, types::Program,
Import, Import,
}; };
@ -46,7 +47,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
let program_name = program.name.clone(); let program_name = program.name.clone();
// match each import symbol to a symbol in the imported file // match each import symbol to a symbol in the imported file
import.symbols.into_iter().for_each(|symbol| { for symbol in import.symbols.into_iter() {
// see if the imported symbol is a circuit // see if the imported symbol is a circuit
let matched_circuit = program let matched_circuit = program
.circuits .circuits
@ -54,18 +55,9 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
.into_iter() .into_iter()
.find(|(circuit_name, _circuit_def)| symbol.symbol == *circuit_name); .find(|(circuit_name, _circuit_def)| symbol.symbol == *circuit_name);
match matched_circuit { let value = match matched_circuit {
Some((_circuit_name, circuit_def)) => { Some((_circuit_name, circuit_def)) => {
// take the alias if it is present ConstrainedValue::CircuitDefinition(circuit_def)
let resolved_name = symbol.alias.unwrap_or(symbol.symbol);
let resolved_circuit_name =
new_variable_from_variables(&program_name.clone(), &resolved_name);
// store imported circuit under resolved name
self.store_variable(
resolved_circuit_name,
ConstrainedValue::CircuitDefinition(circuit_def),
);
} }
None => { None => {
// see if the imported symbol is a function // see if the imported symbol is a function
@ -75,18 +67,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
match matched_function { match matched_function {
Some((_function_name, function)) => { Some((_function_name, function)) => {
// take the alias if it is present ConstrainedValue::Function(function)
let resolved_name = symbol.alias.unwrap_or(symbol.symbol);
let resolved_function_name = new_variable_from_variables(
&program_name.clone(),
&resolved_name,
);
// store imported function under resolved name
self.store_variable(
resolved_function_name,
ConstrainedValue::Function(function),
)
} }
None => unimplemented!( None => unimplemented!(
"cannot find imported symbol {} in imported file {}", "cannot find imported symbol {} in imported file {}",
@ -95,8 +76,16 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
), ),
} }
} }
} };
});
// take the alias if it is present
let resolved_name = symbol.alias.unwrap_or(symbol.symbol);
let resolved_circuit_name =
new_scope(program_name.to_string(), resolved_name.to_string());
// store imported circuit under resolved name
self.store(resolved_circuit_name, value);
}
// evaluate all import statements in imported file // evaluate all import statements in imported file
program program

View File

@ -58,14 +58,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
self.identifiers.insert(name, value); self.identifiers.insert(name, value);
} }
pub(crate) fn store_variable(
&mut self,
variable: Identifier<F, G>,
value: ConstrainedValue<F, G>,
) {
self.store(variable.name, value);
}
pub(crate) fn get(&self, name: &String) -> Option<&ConstrainedValue<F, G>> { pub(crate) fn get(&self, name: &String) -> Option<&ConstrainedValue<F, G>> {
self.identifiers.get(name) self.identifiers.get(name)
} }

View File

@ -21,12 +21,26 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
match assignee { match assignee {
Assignee::Identifier(name) => new_scope_from_variable(scope, &name), Assignee::Identifier(name) => new_scope_from_variable(scope, &name),
Assignee::Array(array, _index) => self.resolve_assignee(scope, *array), Assignee::Array(array, _index) => self.resolve_assignee(scope, *array),
Assignee::CircuitMember(circuit_variable, _member) => { Assignee::CircuitField(circuit_name, _member) => {
self.resolve_assignee(scope, *circuit_variable) self.resolve_assignee(scope, *circuit_name)
} }
} }
} }
fn get_mutable_assignee(
&mut self,
name: String,
) -> Result<&mut ConstrainedValue<F, G>, StatementError> {
// Check that assignee exists and is mutable
Ok(match self.get_mut(&name) {
Some(value) => match value {
ConstrainedValue::Mutable(mutable_value) => mutable_value,
_ => return Err(StatementError::ImmutableAssign(name)),
},
None => return Err(StatementError::UndefinedVariable(name)),
})
}
fn mutate_array( fn mutate_array(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
@ -43,7 +57,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
self.enforce_index(cs, file_scope.clone(), function_scope.clone(), index)?; self.enforce_index(cs, file_scope.clone(), function_scope.clone(), index)?;
// Modify the single value of the array in place // Modify the single value of the array in place
match self.get_mutable_variable(name)? { match self.get_mutable_assignee(name)? {
ConstrainedValue::Array(old) => { ConstrainedValue::Array(old) => {
old[index] = new_value; old[index] = new_value;
} }
@ -61,7 +75,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
}; };
// Modify the range of values of the array in place // Modify the range of values of the array in place
match (self.get_mutable_variable(name)?, new_value) { match (self.get_mutable_assignee(name)?, new_value) {
(ConstrainedValue::Array(old), ConstrainedValue::Array(ref new)) => { (ConstrainedValue::Array(old), ConstrainedValue::Array(ref new)) => {
let to_index = to_index_option.unwrap_or(old.len()); let to_index = to_index_option.unwrap_or(old.len());
old.splice(from_index..to_index, new.iter().cloned()); old.splice(from_index..to_index, new.iter().cloned());
@ -74,19 +88,29 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
Ok(()) Ok(())
} }
fn mutute_circuit_object( fn mutute_circuit_field(
&mut self, &mut self,
circuit_name: String, circuit_name: String,
object_name: Identifier<F, G>, object_name: Identifier<F, G>,
new_value: ConstrainedValue<F, G>, new_value: ConstrainedValue<F, G>,
) -> Result<(), StatementError> { ) -> Result<(), StatementError> {
match self.get_mutable_variable(circuit_name)? { match self.get_mutable_assignee(circuit_name)? {
ConstrainedValue::CircuitExpression(_variable, objects) => { ConstrainedValue::CircuitExpression(_variable, members) => {
// Modify the circuit member in place // Modify the circuit field in place
let matched_object = objects.into_iter().find(|object| object.0 == object_name); let matched_field = members.into_iter().find(|object| object.0 == object_name);
match matched_object { match matched_field {
Some(mut object) => object.1 = new_value.to_owned(), Some(object) => match &object.1 {
ConstrainedValue::Function(function) => {
return Err(StatementError::ImmutableCircuitFunction(
function.function_name.to_string(),
))
}
ConstrainedValue::Static(_value) => {
return Err(StatementError::ImmutableCircuitFunction("static".into()))
}
_ => object.1 = new_value.to_owned(),
},
None => { None => {
return Err(StatementError::UndefinedCircuitObject( return Err(StatementError::UndefinedCircuitObject(
object_name.to_string(), object_name.to_string(),
@ -100,20 +124,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
Ok(()) Ok(())
} }
fn get_mutable_variable(
&mut self,
name: String,
) -> Result<&mut ConstrainedValue<F, G>, StatementError> {
// Check that assignee exists and is mutable
Ok(match self.get_mut(&name) {
Some(value) => match value {
ConstrainedValue::Mutable(mutable_value) => mutable_value,
_ => return Err(StatementError::ImmutableAssign(name)),
},
None => return Err(StatementError::UndefinedVariable(name)),
})
}
fn enforce_assign_statement( fn enforce_assign_statement(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
@ -132,7 +142,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
// 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 old_value = self.get_mutable_variable(variable_name.clone())?; let old_value = self.get_mutable_assignee(variable_name.clone())?;
*old_value = new_value; *old_value = new_value;
@ -146,8 +156,8 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
range_or_expression, range_or_expression,
new_value, new_value,
), ),
Assignee::CircuitMember(_assignee, object_name) => { Assignee::CircuitField(_assignee, object_name) => {
self.mutute_circuit_object(variable_name, object_name, new_value) self.mutute_circuit_field(variable_name, object_name, new_value)
} }
} }
} }

View File

@ -13,7 +13,7 @@ use snarkos_models::{
use std::fmt; use std::fmt;
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub struct ConstrainedCircuitObject<F: Field + PrimeField, G: Group>( pub struct ConstrainedCircuitMember<F: Field + PrimeField, G: Group>(
pub Identifier<F, G>, pub Identifier<F, G>,
pub ConstrainedValue<F, G>, pub ConstrainedValue<F, G>,
); );
@ -28,7 +28,7 @@ pub enum ConstrainedValue<F: Field + PrimeField, G: Group> {
Array(Vec<ConstrainedValue<F, G>>), Array(Vec<ConstrainedValue<F, G>>),
CircuitDefinition(Circuit<F, G>), CircuitDefinition(Circuit<F, G>),
CircuitExpression(Identifier<F, G>, Vec<ConstrainedCircuitObject<F, G>>), CircuitExpression(Identifier<F, G>, Vec<ConstrainedCircuitMember<F, G>>),
Function(Function<F, G>), Function(Function<F, G>),
Return(Vec<ConstrainedValue<F, G>>), Return(Vec<ConstrainedValue<F, G>>),
@ -68,10 +68,10 @@ impl<F: Field + PrimeField, G: Group> ConstrainedValue<F, G> {
Type::Circuit(ref expected_name), Type::Circuit(ref expected_name),
) => { ) => {
if expected_name != actual_name { if expected_name != actual_name {
return Err(ValueError::StructName(format!( return Err(ValueError::CircuitName(
"Expected struct name {} got {}", expected_name.to_string(),
expected_name, actual_name actual_name.to_string(),
))); ));
} }
} }
(ConstrainedValue::Return(ref values), _type) => { (ConstrainedValue::Return(ref values), _type) => {
@ -114,8 +114,8 @@ impl<F: Field + PrimeField, G: Group> fmt::Display for ConstrainedValue<F, G> {
} }
write!(f, "]") write!(f, "]")
} }
ConstrainedValue::CircuitExpression(ref variable, ref members) => { ConstrainedValue::CircuitExpression(ref identifier, ref members) => {
write!(f, "{} {{", variable)?; write!(f, "{} {{", identifier)?;
for (i, member) in members.iter().enumerate() { for (i, member) in members.iter().enumerate() {
write!(f, "{}: {}", member.0, member.1)?; write!(f, "{}: {}", member.0, member.1)?;
if i < members.len() - 1 { if i < members.len() - 1 {
@ -135,7 +135,7 @@ impl<F: Field + PrimeField, G: Group> fmt::Display for ConstrainedValue<F, G> {
write!(f, "]") write!(f, "]")
} }
ConstrainedValue::CircuitDefinition(ref _definition) => { ConstrainedValue::CircuitDefinition(ref _definition) => {
unimplemented!("cannot return struct definition in program") unimplemented!("cannot return circuit definition in program")
} }
ConstrainedValue::Function(ref function) => write!(f, "{}();", function.function_name), ConstrainedValue::Function(ref function) => write!(f, "{}();", function.function_name),
ConstrainedValue::Mutable(ref value) => write!(f, "mut {}", value), ConstrainedValue::Mutable(ref value) => write!(f, "mut {}", value),

View File

@ -51,12 +51,6 @@ pub enum ExpressionError {
#[error("Circuit object {} does not exist", _0)] #[error("Circuit object {} does not exist", _0)]
UndefinedCircuitObject(String), UndefinedCircuitObject(String),
#[error("Cannot assign to circuit functions")]
InvalidCircuitValue,
#[error("Expected circuit object {}, got {}", _0, _1)]
InvalidCircuitObject(String, String),
#[error("Cannot access circuit {}", _0)] #[error("Cannot access circuit {}", _0)]
InvalidCircuitAccess(String), InvalidCircuitAccess(String),

View File

@ -31,6 +31,9 @@ pub enum StatementError {
UndefinedArray(String), UndefinedArray(String),
// Circuits // Circuits
#[error("Cannot mutate circuit function, {}", _0)]
ImmutableCircuitFunction(String),
#[error("Attempted to assign to unknown circuit {}", _0)] #[error("Attempted to assign to unknown circuit {}", _0)]
UndefinedCircuit(String), UndefinedCircuit(String),

View File

@ -12,9 +12,9 @@ pub enum ValueError {
#[error("{}", _0)] #[error("{}", _0)]
IntegerError(IntegerError), IntegerError(IntegerError),
/// Unexpected struct name /// Unexpected circuit name
#[error("{}", _0)] #[error("Expected circuit name {} got {}", _0, _1)]
StructName(String), CircuitName(String, String),
/// Unexpected type /// Unexpected type
#[error("{}", _0)] #[error("{}", _0)]

View File

@ -111,13 +111,13 @@ range_or_expression = { range | expression }
access_array = { "[" ~ range_or_expression ~ "]" } access_array = { "[" ~ range_or_expression ~ "]" }
access_call = { "(" ~ expression_tuple ~ ")" } access_call = { "(" ~ expression_tuple ~ ")" }
access_object = { "." ~ identifier } access_member = { "." ~ identifier }
access_static_object = { "::" ~ identifier } access_static_member = { "::" ~ identifier }
access = { access_array | access_call | access_object | access_static_object} access = { access_array | access_call | access_member | access_static_member}
expression_postfix = { identifier ~ access+ } expression_postfix = { identifier ~ access+ }
assignee_access = { access_array | access_object } assignee_access = { access_array | access_member }
assignee = { identifier ~ assignee_access* } assignee = { identifier ~ assignee_access* }
spread = { "..." ~ expression } spread = { "..." ~ expression }
@ -131,19 +131,19 @@ expression_array_initializer = { "[" ~ spread_or_expression ~ ";" ~ value ~ "]"
/// Circuits /// Circuits
circuit_value = { identifier ~ ":" ~ _type } circuit_field_definition = { identifier ~ ":" ~ _type }
_static = {"static"} _static = {"static"}
circuit_function = {_static? ~ function_definition } circuit_function = {_static? ~ function_definition }
circuit_object = { circuit_value | circuit_function } circuit_member = { circuit_field_definition | circuit_function }
circuit_object_list = _{(circuit_object ~ (NEWLINE+ ~ circuit_object)*)? } circuit_member_list = _{(circuit_member ~ (NEWLINE+ ~ circuit_member)*)? }
circuit_definition = { "circuit" ~ identifier ~ "{" ~ NEWLINE* ~ circuit_object_list ~ NEWLINE* ~ "}" ~ NEWLINE* } circuit_definition = { "circuit" ~ identifier ~ "{" ~ NEWLINE* ~ circuit_member_list ~ NEWLINE* ~ "}" ~ NEWLINE* }
inline_circuit_member = { identifier ~ ":" ~ expression } circuit_field = { identifier ~ ":" ~ expression }
inline_circuit_member_list = _{(inline_circuit_member ~ ("," ~ NEWLINE* ~ inline_circuit_member)*)? ~ ","? } circuit_field_list = _{(circuit_field ~ ("," ~ NEWLINE* ~ circuit_field)*)? ~ ","? }
expression_inline_circuit = { identifier ~ "{" ~ NEWLINE* ~ inline_circuit_member_list ~ NEWLINE* ~ "}" } expression_circuit_inline = { identifier ~ "{" ~ NEWLINE* ~ circuit_field_list ~ NEWLINE* ~ "}" }
/// Conditionals /// Conditionals
@ -153,7 +153,7 @@ expression_conditional = { "if" ~ expression ~ "?" ~ expression ~ ":" ~ expressi
expression_term = { expression_term = {
("(" ~ expression ~ ")") ("(" ~ expression ~ ")")
| expression_inline_circuit | expression_circuit_inline
| expression_conditional | expression_conditional
| expression_postfix | expression_postfix
| expression_primitive | expression_primitive

View File

@ -1,4 +1,4 @@
//! A typed Leo program consists of import, struct, and function definitions. //! A typed Leo program consists of import, circuit, and function definitions.
//! Each defined type consists of typed statements and expressions. //! Each defined type consists of typed statements and expressions.
use crate::{errors::IntegerError, Import}; use crate::{errors::IntegerError, Import};
@ -153,9 +153,9 @@ pub enum Expression<F: Field + PrimeField, G: Group> {
ArrayAccess(Box<Expression<F, G>>, Box<RangeOrExpression<F, G>>), // (array name, range) ArrayAccess(Box<Expression<F, G>>, Box<RangeOrExpression<F, G>>), // (array name, range)
// Circuits // Circuits
Circuit(Identifier<F, G>, Vec<CircuitMember<F, G>>), Circuit(Identifier<F, G>, Vec<CircuitFieldDefinition<F, G>>),
CircuitObjectAccess(Box<Expression<F, G>>, Identifier<F, G>), // (declared circuit name, circuit object name) CircuitMemberAccess(Box<Expression<F, G>>, Identifier<F, G>), // (declared circuit name, circuit member name)
CircuitStaticObjectAccess(Box<Expression<F, G>>, Identifier<F, G>), // (defined circuit name, circuit staic object name) CircuitStaticFunctionAccess(Box<Expression<F, G>>, Identifier<F, G>), // (defined circuit name, circuit static member name)
// Functions // Functions
FunctionCall(Box<Expression<F, G>>, Vec<Expression<F, G>>), FunctionCall(Box<Expression<F, G>>, Vec<Expression<F, G>>),
@ -166,7 +166,7 @@ pub enum Expression<F: Field + PrimeField, G: Group> {
pub enum Assignee<F: Field + PrimeField, G: Group> { pub enum Assignee<F: Field + PrimeField, G: Group> {
Identifier(Identifier<F, G>), Identifier(Identifier<F, G>),
Array(Box<Assignee<F, G>>, RangeOrExpression<F, G>), Array(Box<Assignee<F, G>>, RangeOrExpression<F, G>),
CircuitMember(Box<Assignee<F, G>>, Identifier<F, G>), // (circuit name, circuit object name) CircuitField(Box<Assignee<F, G>>, Identifier<F, G>), // (circuit name, circuit field name)
} }
/// Explicit integer type /// Explicit integer type
@ -234,21 +234,21 @@ pub enum Statement<F: Field + PrimeField, G: Group> {
/// Circuits /// Circuits
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct CircuitMember<F: Field + PrimeField, G: Group> { pub struct CircuitFieldDefinition<F: Field + PrimeField, G: Group> {
pub identifier: Identifier<F, G>, pub identifier: Identifier<F, G>,
pub expression: Expression<F, G>, pub expression: Expression<F, G>,
} }
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub enum CircuitObject<F: Field + PrimeField, G: Group> { pub enum CircuitMember<F: Field + PrimeField, G: Group> {
CircuitValue(Identifier<F, G>, Type<F, G>), CircuitField(Identifier<F, G>, Type<F, G>),
CircuitFunction(bool, Function<F, G>), CircuitFunction(bool, Function<F, G>),
} }
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub struct Circuit<F: Field + PrimeField, G: Group> { pub struct Circuit<F: Field + PrimeField, G: Group> {
pub identifier: Identifier<F, G>, pub identifier: Identifier<F, G>,
pub objects: Vec<CircuitObject<F, G>>, pub members: Vec<CircuitMember<F, G>>,
} }
/// Function parameters /// Function parameters

View File

@ -1,7 +1,7 @@
//! Format display functions for Leo types. //! Format display functions for Leo types.
use crate::{ use crate::{
Assignee, Circuit, CircuitObject, ConditionalNestedOrEnd, ConditionalStatement, Expression, Assignee, Circuit, CircuitMember, ConditionalNestedOrEnd, ConditionalStatement, Expression,
FieldElement, Function, Identifier, InputModel, InputValue, Integer, IntegerType, FieldElement, Function, Identifier, InputModel, InputValue, Integer, IntegerType,
RangeOrExpression, SpreadOrExpression, Statement, Type, Variable, RangeOrExpression, SpreadOrExpression, Statement, Type, Variable,
}; };
@ -154,10 +154,10 @@ impl<'ast, F: Field + PrimeField, G: Group> fmt::Display for Expression<F, G> {
} }
write!(f, "}}") write!(f, "}}")
} }
Expression::CircuitObjectAccess(ref circuit_name, ref member) => { Expression::CircuitMemberAccess(ref circuit_name, ref member) => {
write!(f, "{}.{}", circuit_name, member) write!(f, "{}.{}", circuit_name, member)
} }
Expression::CircuitStaticObjectAccess(ref circuit_name, ref member) => { Expression::CircuitStaticFunctionAccess(ref circuit_name, ref member) => {
write!(f, "{}::{}", circuit_name, member) write!(f, "{}::{}", circuit_name, member)
} }
@ -181,7 +181,7 @@ impl<F: Field + PrimeField, G: Group> fmt::Display for Assignee<F, G> {
match *self { match *self {
Assignee::Identifier(ref variable) => write!(f, "{}", variable), Assignee::Identifier(ref variable) => write!(f, "{}", variable),
Assignee::Array(ref array, ref index) => write!(f, "{}[{}]", array, index), Assignee::Array(ref array, ref index) => write!(f, "{}[{}]", array, index),
Assignee::CircuitMember(ref circuit_variable, ref member) => { Assignee::CircuitField(ref circuit_variable, ref member) => {
write!(f, "{}.{}", circuit_variable, member) write!(f, "{}.{}", circuit_variable, member)
} }
} }
@ -292,13 +292,13 @@ impl<F: Field + PrimeField, G: Group> fmt::Display for Type<F, G> {
} }
} }
impl<F: Field + PrimeField, G: Group> fmt::Display for CircuitObject<F, G> { impl<F: Field + PrimeField, G: Group> fmt::Display for CircuitMember<F, G> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
CircuitObject::CircuitValue(ref identifier, ref _type) => { CircuitMember::CircuitField(ref identifier, ref _type) => {
write!(f, "{}: {}", identifier, _type) write!(f, "{}: {}", identifier, _type)
} }
CircuitObject::CircuitFunction(ref _static, ref function) => { CircuitMember::CircuitFunction(ref _static, ref function) => {
if *_static { if *_static {
write!(f, "static ")?; write!(f, "static ")?;
} }
@ -311,14 +311,14 @@ impl<F: Field + PrimeField, G: Group> fmt::Display for CircuitObject<F, G> {
impl<F: Field + PrimeField, G: Group> Circuit<F, G> { impl<F: Field + PrimeField, G: Group> Circuit<F, G> {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "circuit {} {{ \n", self.identifier)?; write!(f, "circuit {} {{ \n", self.identifier)?;
for field in self.objects.iter() { for field in self.members.iter() {
write!(f, " {}\n", field)?; write!(f, " {}\n", field)?;
} }
write!(f, "}}") write!(f, "}}")
} }
} }
// impl<F: Field + PrimeField, G: Group> fmt::Display for Struct<F, G> {// uncomment when we no longer print out Program // impl<F: Field + PrimeField, G: Group> fmt::Display for Circuit<F, G> {// uncomment when we no longer print out Program
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// self.format(f) // self.format(f)
// } // }

View File

@ -276,11 +276,11 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::ArrayInitializerExpression
} }
} }
impl<'ast, F: Field + PrimeField, G: Group> From<ast::InlineCircuitMember<'ast>> impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitField<'ast>>
for types::CircuitMember<F, G> for types::CircuitFieldDefinition<F, G>
{ {
fn from(member: ast::InlineCircuitMember<'ast>) -> Self { fn from(member: ast::CircuitField<'ast>) -> Self {
types::CircuitMember { types::CircuitFieldDefinition {
identifier: types::Identifier::from(member.identifier), identifier: types::Identifier::from(member.identifier),
expression: types::Expression::from(member.expression), expression: types::Expression::from(member.expression),
} }
@ -295,8 +295,8 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitInlineExpression<'a
let members = expression let members = expression
.members .members
.into_iter() .into_iter()
.map(|member| types::CircuitMember::from(member)) .map(|member| types::CircuitFieldDefinition::from(member))
.collect::<Vec<types::CircuitMember<F, G>>>(); .collect::<Vec<types::CircuitFieldDefinition<F, G>>>();
types::Expression::Circuit(variable, members) types::Expression::Circuit(variable, members)
} }
@ -334,12 +334,12 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::PostfixExpression<'ast>>
), ),
// Handle circuit member accesses // Handle circuit member accesses
ast::Access::Object(circuit_object) => types::Expression::CircuitObjectAccess( ast::Access::Object(circuit_object) => types::Expression::CircuitMemberAccess(
Box::new(acc), Box::new(acc),
types::Identifier::from(circuit_object.identifier), types::Identifier::from(circuit_object.identifier),
), ),
ast::Access::StaticObject(circuit_object) => { ast::Access::StaticObject(circuit_object) => {
types::Expression::CircuitStaticObjectAccess( types::Expression::CircuitStaticFunctionAccess(
Box::new(acc), Box::new(acc),
types::Identifier::from(circuit_object.identifier), types::Identifier::from(circuit_object.identifier),
) )
@ -389,10 +389,10 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::Assignee<'ast>> for types:
.accesses .accesses
.into_iter() .into_iter()
.fold(variable, |acc, access| match access { .fold(variable, |acc, access| match access {
ast::AssigneeAccess::Member(struct_member) => { ast::AssigneeAccess::Member(circuit_member) => {
types::Expression::CircuitObjectAccess( types::Expression::CircuitMemberAccess(
Box::new(acc), Box::new(acc),
types::Identifier::from(struct_member.identifier), types::Identifier::from(circuit_member.identifier),
) )
} }
ast::AssigneeAccess::Array(array) => types::Expression::ArrayAccess( ast::AssigneeAccess::Array(array) => types::Expression::ArrayAccess(
@ -424,9 +424,9 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::Assignee<'ast>> for types:
Box::new(acc), Box::new(acc),
types::RangeOrExpression::from(array.expression), types::RangeOrExpression::from(array.expression),
), ),
ast::AssigneeAccess::Member(struct_member) => types::Assignee::CircuitMember( ast::AssigneeAccess::Member(circuit_field) => types::Assignee::CircuitField(
Box::new(acc), Box::new(acc),
types::Identifier::from(struct_member.identifier), types::Identifier::from(circuit_field.identifier),
), ),
}) })
} }
@ -642,7 +642,7 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::Statement<'ast>> for types
} }
} }
/// pest ast -> Explicit types::Type for defining struct members and function params /// pest ast -> Explicit types::Type for defining circuit members and function params
impl From<ast::IntegerType> for types::IntegerType { impl From<ast::IntegerType> for types::IntegerType {
fn from(integer_type: ast::IntegerType) -> Self { fn from(integer_type: ast::IntegerType) -> Self {
@ -683,8 +683,8 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::ArrayType<'ast>> for types
} }
impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitType<'ast>> for types::Type<F, G> { impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitType<'ast>> for types::Type<F, G> {
fn from(struct_type: ast::CircuitType<'ast>) -> Self { fn from(circuit_type: ast::CircuitType<'ast>) -> Self {
types::Type::Circuit(types::Identifier::from(struct_type.identifier)) types::Type::Circuit(types::Identifier::from(circuit_type.identifier))
} }
} }
@ -698,13 +698,13 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::Type<'ast>> for types::Typ
} }
} }
/// pest ast -> types::Struct /// pest ast -> types::Circuit
impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitValue<'ast>> impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitFieldDefinition<'ast>>
for types::CircuitObject<F, G> for types::CircuitMember<F, G>
{ {
fn from(circuit_value: ast::CircuitValue<'ast>) -> Self { fn from(circuit_value: ast::CircuitFieldDefinition<'ast>) -> Self {
types::CircuitObject::CircuitValue( types::CircuitMember::CircuitField(
types::Identifier::from(circuit_value.identifier), types::Identifier::from(circuit_value.identifier),
types::Type::from(circuit_value._type), types::Type::from(circuit_value._type),
) )
@ -712,43 +712,43 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitValue<'ast>>
} }
impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitFunction<'ast>> impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitFunction<'ast>>
for types::CircuitObject<F, G> for types::CircuitMember<F, G>
{ {
fn from(circuit_function: ast::CircuitFunction<'ast>) -> Self { fn from(circuit_function: ast::CircuitFunction<'ast>) -> Self {
types::CircuitObject::CircuitFunction( types::CircuitMember::CircuitFunction(
circuit_function._static.is_some(), circuit_function._static.is_some(),
types::Function::from(circuit_function.function), types::Function::from(circuit_function.function),
) )
} }
} }
impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitObject<'ast>> impl<'ast, F: Field + PrimeField, G: Group> From<ast::CircuitMember<'ast>>
for types::CircuitObject<F, G> for types::CircuitMember<F, G>
{ {
fn from(object: ast::CircuitObject<'ast>) -> Self { fn from(object: ast::CircuitMember<'ast>) -> Self {
match object { match object {
ast::CircuitObject::CircuitValue(circuit_value) => { ast::CircuitMember::CircuitFieldDefinition(circuit_value) => {
types::CircuitObject::from(circuit_value) types::CircuitMember::from(circuit_value)
} }
ast::CircuitObject::CircuitFunction(circuit_function) => { ast::CircuitMember::CircuitFunction(circuit_function) => {
types::CircuitObject::from(circuit_function) types::CircuitMember::from(circuit_function)
} }
} }
} }
} }
impl<'ast, F: Field + PrimeField, G: Group> From<ast::Circuit<'ast>> for types::Circuit<F, G> { impl<'ast, F: Field + PrimeField, G: Group> From<ast::Circuit<'ast>> for types::Circuit<F, G> {
fn from(struct_definition: ast::Circuit<'ast>) -> Self { fn from(circuit: ast::Circuit<'ast>) -> Self {
let variable = types::Identifier::from(struct_definition.identifier); let variable = types::Identifier::from(circuit.identifier);
let fields = struct_definition let members = circuit
.fields .members
.into_iter() .into_iter()
.map(|struct_field| types::CircuitObject::from(struct_field)) .map(|member| types::CircuitMember::from(member))
.collect(); .collect();
types::Circuit { types::Circuit {
identifier: variable, identifier: variable,
objects: fields, members,
} }
} }
} }
@ -836,14 +836,14 @@ impl<'ast, F: Field + PrimeField, G: Group> types::Program<F, G> {
.map(|import| Import::from(import)) .map(|import| Import::from(import))
.collect::<Vec<Import<F, G>>>(); .collect::<Vec<Import<F, G>>>();
let mut structs = HashMap::new(); let mut circuits = HashMap::new();
let mut functions = HashMap::new(); let mut functions = HashMap::new();
let mut num_parameters = 0usize; let mut num_parameters = 0usize;
file.circuits.into_iter().for_each(|struct_def| { file.circuits.into_iter().for_each(|circuit| {
structs.insert( circuits.insert(
types::Identifier::from(struct_def.identifier.clone()), types::Identifier::from(circuit.identifier.clone()),
types::Circuit::from(struct_def), types::Circuit::from(circuit),
); );
}); });
file.functions.into_iter().for_each(|function_def| { file.functions.into_iter().for_each(|function_def| {
@ -861,7 +861,7 @@ impl<'ast, F: Field + PrimeField, G: Group> types::Program<F, G> {
name: types::Identifier::new(name), name: types::Identifier::new(name),
num_parameters, num_parameters,
imports, imports,
circuits: structs, circuits,
functions, functions,
} }
} }