Merge pull request #847 from Zokrates/fix-complex-type-side-effects
Remove side effects on complex types
This commit is contained in:
commit
d4494cb9c2
8 changed files with 28 additions and 78 deletions
1
changelogs/unreleased/847-schaeff
Normal file
1
changelogs/unreleased/847-schaeff
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Remove side effects on complex types (bug)
|
|
@ -9,7 +9,6 @@ mod constant_inliner;
|
||||||
mod flat_propagation;
|
mod flat_propagation;
|
||||||
mod flatten_complex_types;
|
mod flatten_complex_types;
|
||||||
mod propagation;
|
mod propagation;
|
||||||
mod redefinition;
|
|
||||||
mod reducer;
|
mod reducer;
|
||||||
mod shift_checker;
|
mod shift_checker;
|
||||||
mod uint_optimizer;
|
mod uint_optimizer;
|
||||||
|
@ -20,7 +19,6 @@ mod variable_write_remover;
|
||||||
use self::bounds_checker::BoundsChecker;
|
use self::bounds_checker::BoundsChecker;
|
||||||
use self::flatten_complex_types::Flattener;
|
use self::flatten_complex_types::Flattener;
|
||||||
use self::propagation::Propagator;
|
use self::propagation::Propagator;
|
||||||
use self::redefinition::RedefinitionOptimizer;
|
|
||||||
use self::reducer::reduce_program;
|
use self::reducer::reduce_program;
|
||||||
use self::shift_checker::ShiftChecker;
|
use self::shift_checker::ShiftChecker;
|
||||||
use self::uint_optimizer::UintOptimizer;
|
use self::uint_optimizer::UintOptimizer;
|
||||||
|
@ -84,8 +82,6 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
|
||||||
|
|
||||||
// propagate
|
// propagate
|
||||||
let r = Propagator::propagate(r).map_err(Error::from)?;
|
let r = Propagator::propagate(r).map_err(Error::from)?;
|
||||||
// optimize redefinitions
|
|
||||||
let r = RedefinitionOptimizer::optimize(r);
|
|
||||||
// remove assignment to variable index
|
// remove assignment to variable index
|
||||||
let r = VariableWriteRemover::apply(r);
|
let r = VariableWriteRemover::apply(r);
|
||||||
// remove variable access to complex types
|
// remove variable access to complex types
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
use crate::typed_absy::folder::*;
|
|
||||||
use crate::typed_absy::*;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use zokrates_field::Field;
|
|
||||||
|
|
||||||
pub struct RedefinitionOptimizer<'ast> {
|
|
||||||
identifiers: HashMap<Identifier<'ast>, Identifier<'ast>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ast> RedefinitionOptimizer<'ast> {
|
|
||||||
fn new() -> Self {
|
|
||||||
RedefinitionOptimizer {
|
|
||||||
identifiers: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn optimize<T: Field>(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> {
|
|
||||||
RedefinitionOptimizer::new().fold_program(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_id<'ast, T: Field>(e: &TypedExpression<'ast, T>) -> Option<Identifier<'ast>> {
|
|
||||||
match e {
|
|
||||||
TypedExpression::FieldElement(FieldElementExpression::Identifier(id)) => Some(id.clone()),
|
|
||||||
TypedExpression::Boolean(BooleanExpression::Identifier(id)) => Some(id.clone()),
|
|
||||||
TypedExpression::Array(a) => match a.as_inner() {
|
|
||||||
ArrayExpressionInner::Identifier(id) => Some(id.clone()),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
TypedExpression::Struct(a) => match a.as_inner() {
|
|
||||||
StructExpressionInner::Identifier(id) => Some(id.clone()),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
TypedExpression::Uint(a) => match a.as_inner() {
|
|
||||||
UExpressionInner::Identifier(id) => Some(id.clone()),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ast, T: Field> Folder<'ast, T> for RedefinitionOptimizer<'ast> {
|
|
||||||
fn fold_function(&mut self, f: TypedFunction<'ast, T>) -> TypedFunction<'ast, T> {
|
|
||||||
self.identifiers = HashMap::new();
|
|
||||||
fold_function(self, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec<TypedStatement<'ast, T>> {
|
|
||||||
match s {
|
|
||||||
TypedStatement::Definition(TypedAssignee::Identifier(var), expr) => {
|
|
||||||
let expr = self.fold_expression(expr);
|
|
||||||
|
|
||||||
match try_id(&expr) {
|
|
||||||
Some(id) => {
|
|
||||||
let target = self.identifiers.get(&id).unwrap_or(&id).clone();
|
|
||||||
|
|
||||||
self.identifiers.insert(var.id, target);
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
None => vec![TypedStatement::Definition(
|
|
||||||
TypedAssignee::Identifier(var),
|
|
||||||
expr,
|
|
||||||
)],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s => fold_statement(self, s),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fold_name(&mut self, s: Identifier<'ast>) -> Identifier<'ast> {
|
|
||||||
self.identifiers.get(&s).cloned().unwrap_or(s)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"entry_point": "./tests/tests/structs/identity.code",
|
"entry_point": "./tests/tests/structs/identity.zok",
|
||||||
"curves": ["Bn128", "Bls12_381", "Bls12_377", "Bw6_761"],
|
"curves": ["Bn128", "Bls12_381", "Bls12_377", "Bw6_761"],
|
||||||
"tests": [
|
"tests": [
|
||||||
{
|
{
|
||||||
|
|
16
zokrates_core_test/tests/tests/structs/mutate_argument.json
Normal file
16
zokrates_core_test/tests/tests/structs/mutate_argument.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"entry_point": "./tests/tests/structs/mutate_argument.zok",
|
||||||
|
"curves": ["Bn128", "Bls12_381", "Bls12_377", "Bw6_761"],
|
||||||
|
"tests": [
|
||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"values": ["1"]
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"Ok": {
|
||||||
|
"values": ["2", "1"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
10
zokrates_core_test/tests/tests/structs/mutate_argument.zok
Normal file
10
zokrates_core_test/tests/tests/structs/mutate_argument.zok
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
struct Foo {
|
||||||
|
field a
|
||||||
|
}
|
||||||
|
|
||||||
|
def mutate(field[1] f) -> field[1]:
|
||||||
|
f[0] = f[0] + 1
|
||||||
|
return f
|
||||||
|
|
||||||
|
def main(field[1] f) -> (field[1], field[1]):
|
||||||
|
return mutate(f), f
|
Loading…
Reference in a new issue