1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00
ZoKrates/zokrates_core/src/static_analysis/mod.rs
2021-08-05 15:22:46 +02:00

114 lines
3.2 KiB
Rust

//! Module containing static analysis
//!
//! @file mod.rs
//! @author Thibaut Schaeffer <thibaut@schaeff.fr>
//! @date 2018
mod branch_isolator;
mod constant_argument_checker;
mod constant_inliner;
mod flat_propagation;
mod flatten_complex_types;
mod propagation;
mod reducer;
mod uint_optimizer;
mod unconstrained_vars;
mod variable_write_remover;
use self::branch_isolator::Isolator;
use self::constant_argument_checker::ConstantArgumentChecker;
use self::flatten_complex_types::Flattener;
use self::propagation::Propagator;
use self::reducer::reduce_program;
use self::uint_optimizer::UintOptimizer;
use self::unconstrained_vars::UnconstrainedVariableDetector;
use self::variable_write_remover::VariableWriteRemover;
use crate::compile::CompileConfig;
use crate::flat_absy::FlatProg;
use crate::ir::Prog;
use crate::static_analysis::constant_inliner::ConstantInliner;
use crate::typed_absy::{abi::Abi, TypedProgram};
use crate::zir::ZirProgram;
use std::fmt;
use zokrates_field::Field;
pub trait Analyse {
fn analyse(self) -> Self;
}
#[derive(Debug)]
pub enum Error {
Reducer(self::reducer::Error),
Propagation(self::propagation::Error),
NonConstantArgument(self::constant_argument_checker::Error),
}
impl From<reducer::Error> for Error {
fn from(e: self::reducer::Error) -> Self {
Error::Reducer(e)
}
}
impl From<propagation::Error> for Error {
fn from(e: propagation::Error) -> Self {
Error::Propagation(e)
}
}
impl From<constant_argument_checker::Error> for Error {
fn from(e: constant_argument_checker::Error) -> Self {
Error::NonConstantArgument(e)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::Reducer(e) => write!(f, "{}", e),
Error::Propagation(e) => write!(f, "{}", e),
Error::NonConstantArgument(e) => write!(f, "{}", e),
}
}
}
impl<'ast, T: Field> TypedProgram<'ast, T> {
pub fn analyse(self, config: &CompileConfig) -> Result<(ZirProgram<'ast, T>, Abi), Error> {
// inline user-defined constants
let r = ConstantInliner::inline(self);
// isolate branches
let r = if config.isolate_branches {
Isolator::isolate(r)
} else {
r
};
// reduce the program to a single function
let r = reduce_program(r).map_err(Error::from)?;
// generate abi
let abi = r.abi();
// propagate
let r = Propagator::propagate(r).map_err(Error::from)?;
// remove assignment to variable index
let r = VariableWriteRemover::apply(r);
// detect non constant shifts and constant lt bounds
let r = ConstantArgumentChecker::check(r).map_err(Error::from)?;
// convert to zir, removing complex types
let zir = Flattener::flatten(r);
// optimize uint expressions
let zir = UintOptimizer::optimize(zir);
Ok((zir, abi))
}
}
impl<T: Field> Analyse for FlatProg<T> {
fn analyse(self) -> Self {
self.propagate()
}
}
impl<T: Field> Analyse for Prog<T> {
fn analyse(self) -> Self {
UnconstrainedVariableDetector::detect(self)
}
}