1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00
This commit is contained in:
schaeff 2020-08-26 15:29:17 +02:00
parent 2e56d2f1cf
commit 14c845fe9c
20 changed files with 1814 additions and 1132 deletions

View file

@ -213,10 +213,8 @@ fn check_with_arena<'ast, T: Field, E: Into<imports::Error>>(
CompileErrors(errors.into_iter().map(|e| CompileError::from(e)).collect())
})?;
let abi = typed_ast.abi();
// analyse (unroll and constant propagation)
let typed_ast = typed_ast.analyse();
let (typed_ast, abi) = typed_ast.analyse();
Ok((typed_ast, abi))
}

View file

@ -4,7 +4,7 @@ use flat_absy::{
FlatVariable,
};
use std::collections::HashMap;
use typed_absy::types::{FunctionKey, Signature, Type};
use typed_absy::types::{ConcreteFunctionKey, ConcreteSignature, ConcreteType};
use zokrates_field::Field;
/// A low level function that contains non-deterministic introduction of variables. It is carried out as is until
@ -21,34 +21,34 @@ pub enum FlatEmbed {
}
impl FlatEmbed {
pub fn signature(&self) -> Signature {
pub fn signature(&self) -> ConcreteSignature {
match self {
FlatEmbed::Unpack(bitwidth) => Signature::new()
.inputs(vec![Type::FieldElement])
.outputs(vec![Type::array(Type::Boolean, *bitwidth)]),
FlatEmbed::U8ToBits => Signature::new()
.inputs(vec![Type::uint(8)])
.outputs(vec![Type::array(Type::Boolean, 8)]),
FlatEmbed::U16ToBits => Signature::new()
.inputs(vec![Type::uint(16)])
.outputs(vec![Type::array(Type::Boolean, 16)]),
FlatEmbed::U32ToBits => Signature::new()
.inputs(vec![Type::uint(32)])
.outputs(vec![Type::array(Type::Boolean, 32)]),
FlatEmbed::U8FromBits => Signature::new()
.outputs(vec![Type::uint(8)])
.inputs(vec![Type::array(Type::Boolean, 8)]),
FlatEmbed::U16FromBits => Signature::new()
.outputs(vec![Type::uint(16)])
.inputs(vec![Type::array(Type::Boolean, 16)]),
FlatEmbed::U32FromBits => Signature::new()
.outputs(vec![Type::uint(32)])
.inputs(vec![Type::array(Type::Boolean, 32)]),
FlatEmbed::Unpack(bitwidth) => ConcreteSignature::new()
.inputs(vec![ConcreteType::FieldElement])
.outputs(vec![ConcreteType::array(ConcreteType::Boolean, *bitwidth)]),
FlatEmbed::U8ToBits => ConcreteSignature::new()
.inputs(vec![ConcreteType::uint(8)])
.outputs(vec![ConcreteType::array(ConcreteType::Boolean, 8usize)]),
FlatEmbed::U16ToBits => ConcreteSignature::new()
.inputs(vec![ConcreteType::uint(16)])
.outputs(vec![ConcreteType::array(ConcreteType::Boolean, 16usize)]),
FlatEmbed::U32ToBits => ConcreteSignature::new()
.inputs(vec![ConcreteType::uint(32)])
.outputs(vec![ConcreteType::array(ConcreteType::Boolean, 32usize)]),
FlatEmbed::U8FromBits => ConcreteSignature::new()
.outputs(vec![ConcreteType::uint(8)])
.inputs(vec![ConcreteType::array(ConcreteType::Boolean, 8usize)]),
FlatEmbed::U16FromBits => ConcreteSignature::new()
.outputs(vec![ConcreteType::uint(16)])
.inputs(vec![ConcreteType::array(ConcreteType::Boolean, 16usize)]),
FlatEmbed::U32FromBits => ConcreteSignature::new()
.outputs(vec![ConcreteType::uint(32)])
.inputs(vec![ConcreteType::array(ConcreteType::Boolean, 32usize)]),
}
}
pub fn key<T: Field>(&self) -> FunctionKey<'static> {
FunctionKey::with_id(self.id()).signature(self.signature())
pub fn key<T: Field>(&self) -> ConcreteFunctionKey<'static> {
ConcreteFunctionKey::with_id(self.id()).signature(self.signature())
}
pub fn id(&self) -> &'static str {

File diff suppressed because it is too large Load diff

View file

@ -4,28 +4,30 @@ use typed_absy::types::{StructType, UBitwidth};
use zir;
use zokrates_field::Field;
use std::convert::{TryFrom, TryInto};
pub struct Flattener<T: Field> {
phantom: PhantomData<T>,
}
fn flatten_identifier_rec<'a>(
id: zir::SourceIdentifier<'a>,
ty: typed_absy::Type,
) -> Vec<zir::Variable> {
fn flatten_identifier_rec<'ast>(
id: zir::SourceIdentifier<'ast>,
ty: typed_absy::types::ConcreteType,
) -> Vec<zir::Variable<'ast>> {
match ty {
typed_absy::Type::FieldElement => vec![zir::Variable {
typed_absy::types::ConcreteType::FieldElement => vec![zir::Variable {
id: zir::Identifier::Source(id),
_type: zir::Type::FieldElement,
}],
typed_absy::Type::Boolean => vec![zir::Variable {
typed_absy::types::ConcreteType::Boolean => vec![zir::Variable {
id: zir::Identifier::Source(id),
_type: zir::Type::Boolean,
}],
typed_absy::Type::Uint(bitwidth) => vec![zir::Variable {
typed_absy::types::ConcreteType::Uint(bitwidth) => vec![zir::Variable {
id: zir::Identifier::Source(id),
_type: zir::Type::uint(bitwidth.to_usize()),
}],
typed_absy::Type::Array(array_type) => (0..array_type.size)
typed_absy::types::ConcreteType::Array(array_type) => (0..array_type.size)
.flat_map(|i| {
flatten_identifier_rec(
zir::SourceIdentifier::Select(box id.clone(), i),
@ -33,7 +35,7 @@ fn flatten_identifier_rec<'a>(
)
})
.collect(),
typed_absy::Type::Struct(members) => members
typed_absy::types::ConcreteType::Struct(members) => members
.into_iter()
.flat_map(|struct_member| {
flatten_identifier_rec(
@ -75,9 +77,12 @@ impl<'ast, T: Field> Flattener<T> {
fold_function(self, f)
}
fn fold_parameter(&mut self, p: typed_absy::Parameter<'ast>) -> Vec<zir::Parameter<'ast>> {
fn fold_declaration_parameter(
&mut self,
p: typed_absy::DeclarationParameter<'ast>,
) -> Vec<zir::Parameter<'ast>> {
let private = p.private;
self.fold_variable(p.id)
self.fold_variable(p.id.try_into().unwrap())
.into_iter()
.map(|v| zir::Parameter { id: v, private })
.collect()
@ -87,10 +92,12 @@ impl<'ast, T: Field> Flattener<T> {
zir::SourceIdentifier::Basic(n)
}
fn fold_variable(&mut self, v: typed_absy::Variable<'ast>) -> Vec<zir::Variable<'ast>> {
fn fold_variable(&mut self, v: typed_absy::Variable<'ast, T>) -> Vec<zir::Variable<'ast>> {
let id = self.fold_name(v.id.clone());
let ty = v.get_type();
let ty = typed_absy::types::ConcreteType::try_from(ty).unwrap();
flatten_identifier_rec(id, ty)
}
@ -146,6 +153,8 @@ impl<'ast, T: Field> Flattener<T> {
) -> zir::ZirExpressionList<'ast, T> {
match es {
typed_absy::TypedExpressionList::FunctionCall(id, arguments, _) => {
let id = typed_absy::types::ConcreteFunctionKey::try_from(id).unwrap();
zir::ZirExpressionList::FunctionCall(
self.fold_function_key(id),
arguments
@ -160,7 +169,7 @@ impl<'ast, T: Field> Flattener<T> {
fn fold_function_key(
&mut self,
k: typed_absy::types::FunctionKey<'ast>,
k: typed_absy::types::ConcreteFunctionKey<'ast>,
) -> zir::types::FunctionKey<'ast> {
k.into()
}
@ -194,7 +203,7 @@ impl<'ast, T: Field> Flattener<T> {
fn fold_array_expression_inner(
&mut self,
ty: &typed_absy::Type,
ty: &typed_absy::types::ConcreteType,
size: usize,
e: typed_absy::ArrayExpressionInner<'ast, T>,
) -> Vec<zir::ZirExpression<'ast, T>> {
@ -202,7 +211,7 @@ impl<'ast, T: Field> Flattener<T> {
}
fn fold_struct_expression_inner(
&mut self,
ty: &StructType,
ty: &typed_absy::types::ConcreteStructType,
e: typed_absy::StructExpressionInner<'ast, T>,
) -> Vec<zir::ZirExpression<'ast, T>> {
fold_struct_expression_inner(self, ty, e)
@ -217,7 +226,12 @@ pub fn fold_module<'ast, T: Field>(
functions: p
.functions
.into_iter()
.map(|(key, fun)| (f.fold_function_key(key), f.fold_function_symbol(fun)))
.map(|(key, fun)| {
(
f.fold_function_key(key.try_into().unwrap()),
f.fold_function_symbol(fun),
)
})
.collect(),
}
}
@ -267,14 +281,16 @@ pub fn fold_statement<'ast, T: Field>(
pub fn fold_array_expression_inner<'ast, T: Field>(
f: &mut Flattener<T>,
t: &typed_absy::Type,
t: &typed_absy::types::ConcreteType,
size: usize,
e: typed_absy::ArrayExpressionInner<'ast, T>,
) -> Vec<zir::ZirExpression<'ast, T>> {
match e {
typed_absy::ArrayExpressionInner::Identifier(id) => {
let variables =
flatten_identifier_rec(f.fold_name(id), typed_absy::Type::array(t.clone(), size));
let variables = flatten_identifier_rec(
f.fold_name(id),
typed_absy::types::ConcreteType::array(t.clone(), size),
);
variables
.into_iter()
.map(|v| match v._type {
@ -329,7 +345,11 @@ pub fn fold_array_expression_inner<'ast, T: Field>(
let offset: usize = members
.iter()
.take_while(|member| member.id != id)
.map(|member| member.ty.get_primitive_count())
.map(|member| {
typed_absy::types::ConcreteType::try_from(*member.ty)
.unwrap()
.get_primitive_count()
})
.sum();
// we also need the size of this member
@ -339,12 +359,15 @@ pub fn fold_array_expression_inner<'ast, T: Field>(
}
typed_absy::ArrayExpressionInner::Select(box array, box index) => {
let array = f.fold_array_expression(array);
let index = f.fold_field_expression(index);
let index = f.fold_uint_expression(index);
match index {
zir::FieldElementExpression::Number(i) => {
let size = t.get_primitive_count() * size;
let start = i.to_dec_string().parse::<usize>().unwrap() * size;
match index.into_inner() {
zir::UExpressionInner::Value(i) => {
let size = typed_absy::types::ConcreteType::try_from(*t)
.unwrap()
.get_primitive_count()
* size;
let start = i as usize * size;
let end = start + size;
array[start..end].to_vec()
}
@ -356,13 +379,15 @@ pub fn fold_array_expression_inner<'ast, T: Field>(
pub fn fold_struct_expression_inner<'ast, T: Field>(
f: &mut Flattener<T>,
t: &StructType,
t: &typed_absy::types::ConcreteStructType,
e: typed_absy::StructExpressionInner<'ast, T>,
) -> Vec<zir::ZirExpression<'ast, T>> {
match e {
typed_absy::StructExpressionInner::Identifier(id) => {
let variables =
flatten_identifier_rec(f.fold_name(id), typed_absy::Type::struc(t.clone()));
let variables = flatten_identifier_rec(
f.fold_name(id),
typed_absy::types::ConcreteType::struc(t.clone()),
);
variables
.into_iter()
.map(|v| match v._type {
@ -417,30 +442,33 @@ pub fn fold_struct_expression_inner<'ast, T: Field>(
let offset: usize = members
.iter()
.take_while(|member| member.id != id)
.map(|member| member.ty.get_primitive_count())
.map(|member| {
typed_absy::types::ConcreteType::try_from(*member.ty)
.unwrap()
.get_primitive_count()
})
.sum();
// we also need the size of this member
let size = t
.iter()
.find(|member| member.id == id)
.unwrap()
.ty
.get_primitive_count();
let size = typed_absy::types::ConcreteType::try_from(
*t.iter().find(|member| member.id == id).unwrap().ty,
)
.unwrap()
.get_primitive_count();
s[offset..offset + size].to_vec()
}
typed_absy::StructExpressionInner::Select(box array, box index) => {
let array = f.fold_array_expression(array);
let index = f.fold_field_expression(index);
let index = f.fold_uint_expression(index);
match index {
zir::FieldElementExpression::Number(i) => {
match index.into_inner() {
zir::UExpressionInner::Value(i) => {
let size = t
.iter()
.map(|m| m.ty.get_primitive_count())
.fold(0, |acc, current| acc + current);
let start = i.to_dec_string().parse::<usize>().unwrap() * size;
let start = i as usize * size;
let end = start + size;
array[start..end].to_vec()
}
@ -458,9 +486,12 @@ pub fn fold_field_expression<'ast, T: Field>(
typed_absy::FieldElementExpression::Number(n) => zir::FieldElementExpression::Number(n),
typed_absy::FieldElementExpression::Identifier(id) => {
zir::FieldElementExpression::Identifier(
flatten_identifier_rec(f.fold_name(id), typed_absy::Type::FieldElement)[0]
.id
.clone(),
flatten_identifier_rec(
f.fold_name(id),
typed_absy::types::ConcreteType::FieldElement,
)[0]
.id
.clone(),
)
}
typed_absy::FieldElementExpression::Add(box e1, box e2) => {
@ -503,26 +534,22 @@ pub fn fold_field_expression<'ast, T: Field>(
let offset: usize = members
.iter()
.take_while(|member| member.id != id)
.map(|member| member.ty.get_primitive_count())
.map(|member| {
typed_absy::types::ConcreteType::try_from(*member.ty)
.unwrap()
.get_primitive_count()
})
.sum();
use std::convert::TryInto;
s[offset].clone().try_into().unwrap()
}
typed_absy::FieldElementExpression::Select(box array, box index) => {
let array = f.fold_array_expression(array);
let index = f.fold_field_expression(index);
let index = f.fold_uint_expression(index);
use std::convert::TryInto;
match index {
zir::FieldElementExpression::Number(i) => array
[i.to_dec_string().parse::<usize>().unwrap()]
.clone()
.try_into()
.unwrap(),
match index.into_inner() {
zir::UExpressionInner::Value(i) => array[i as usize].clone().try_into().unwrap(),
_ => unreachable!(""),
}
}
@ -536,7 +563,7 @@ pub fn fold_boolean_expression<'ast, T: Field>(
match e {
typed_absy::BooleanExpression::Value(v) => zir::BooleanExpression::Value(v),
typed_absy::BooleanExpression::Identifier(id) => zir::BooleanExpression::Identifier(
flatten_identifier_rec(f.fold_name(id), typed_absy::Type::Boolean)[0]
flatten_identifier_rec(f.fold_name(id), typed_absy::types::ConcreteType::Boolean)[0]
.id
.clone(),
),
@ -661,25 +688,21 @@ pub fn fold_boolean_expression<'ast, T: Field>(
let offset: usize = members
.iter()
.take_while(|member| member.id != id)
.map(|member| member.ty.get_primitive_count())
.map(|member| {
typed_absy::types::ConcreteType::try_from(*member.ty)
.unwrap()
.get_primitive_count()
})
.sum();
use std::convert::TryInto;
s[offset].clone().try_into().unwrap()
}
typed_absy::BooleanExpression::Select(box array, box index) => {
let array = f.fold_array_expression(array);
let index = f.fold_field_expression(index);
let index = f.fold_uint_expression(index);
use std::convert::TryInto;
match index {
zir::FieldElementExpression::Number(i) => array
[i.to_dec_string().parse::<usize>().unwrap()]
.clone()
.try_into()
.unwrap(),
match index.into_inner() {
zir::UExpressionInner::Value(i) => array[i as usize].clone().try_into().unwrap(),
_ => unreachable!(),
}
}
@ -702,9 +725,12 @@ pub fn fold_uint_expression_inner<'ast, T: Field>(
match e {
typed_absy::UExpressionInner::Value(v) => zir::UExpressionInner::Value(v),
typed_absy::UExpressionInner::Identifier(id) => zir::UExpressionInner::Identifier(
flatten_identifier_rec(f.fold_name(id), typed_absy::Type::Uint(bitwidth))[0]
.id
.clone(),
flatten_identifier_rec(
f.fold_name(id),
typed_absy::types::ConcreteType::Uint(bitwidth),
)[0]
.id
.clone(),
),
typed_absy::UExpressionInner::Add(box left, box right) => {
let left = f.fold_uint_expression(left);
@ -764,16 +790,11 @@ pub fn fold_uint_expression_inner<'ast, T: Field>(
}
typed_absy::UExpressionInner::Select(box array, box index) => {
let array = f.fold_array_expression(array);
let index = f.fold_field_expression(index);
let index = f.fold_uint_expression(index);
use std::convert::TryInto;
match index {
zir::FieldElementExpression::Number(i) => {
let e: zir::UExpression<_> = array[i.to_dec_string().parse::<usize>().unwrap()]
.clone()
.try_into()
.unwrap();
match index.into_inner() {
zir::UExpressionInner::Value(i) => {
let e: zir::UExpression<_> = array[i as usize].clone().try_into().unwrap();
e.into_inner()
}
_ => unreachable!(),
@ -787,11 +808,13 @@ pub fn fold_uint_expression_inner<'ast, T: Field>(
let offset: usize = members
.iter()
.take_while(|member| member.id != id)
.map(|member| member.ty.get_primitive_count())
.map(|member| {
typed_absy::types::ConcreteType::try_from(*member.ty)
.unwrap()
.get_primitive_count()
})
.sum();
use std::convert::TryInto;
let res: zir::UExpression<'ast, T> = s[offset].clone().try_into().unwrap();
res.into_inner()
@ -813,14 +836,16 @@ pub fn fold_function<'ast, T: Field>(
arguments: fun
.arguments
.into_iter()
.flat_map(|a| f.fold_parameter(a))
.flat_map(|a| f.fold_declaration_parameter(a))
.collect(),
statements: fun
.statements
.into_iter()
.flat_map(|s| f.fold_statement(s))
.collect(),
signature: fun.signature.into(),
signature: typed_absy::types::ConcreteSignature::try_from(fun.signature)
.unwrap()
.into(),
}
}
@ -828,14 +853,25 @@ pub fn fold_array_expression<'ast, T: Field>(
f: &mut Flattener<T>,
e: typed_absy::ArrayExpression<'ast, T>,
) -> Vec<zir::ZirExpression<'ast, T>> {
f.fold_array_expression_inner(&e.inner_type().clone(), e.size(), e.into_inner())
let size = match e.size().into_inner() {
typed_absy::UExpressionInner::Value(v) => v,
_ => unreachable!(),
} as usize;
f.fold_array_expression_inner(
&typed_absy::types::ConcreteType::try_from(e.inner_type().clone()).unwrap(),
size,
e.into_inner(),
)
}
pub fn fold_struct_expression<'ast, T: Field>(
f: &mut Flattener<T>,
e: typed_absy::StructExpression<'ast, T>,
) -> Vec<zir::ZirExpression<'ast, T>> {
f.fold_struct_expression_inner(&e.ty().clone(), e.into_inner())
f.fold_struct_expression_inner(
&typed_absy::types::ConcreteStructType::try_from(e.ty().clone()).unwrap(),
e.into_inner(),
)
}
pub fn fold_function_symbol<'ast, T: Field>(
@ -846,9 +882,10 @@ pub fn fold_function_symbol<'ast, T: Field>(
typed_absy::TypedFunctionSymbol::Here(fun) => {
zir::ZirFunctionSymbol::Here(f.fold_function(fun))
}
typed_absy::TypedFunctionSymbol::There(key, module) => {
zir::ZirFunctionSymbol::There(f.fold_function_key(key), module)
} // by default, do not fold modules recursively
typed_absy::TypedFunctionSymbol::There(key, module) => zir::ZirFunctionSymbol::There(
f.fold_function_key(typed_absy::types::ConcreteFunctionKey::try_from(key).unwrap()),
module,
), // by default, do not fold modules recursively
typed_absy::TypedFunctionSymbol::Flat(flat) => zir::ZirFunctionSymbol::Flat(flat),
}
}

View file

@ -18,6 +18,8 @@
use static_analysis::propagate_unroll::{Blocked, Output};
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use typed_absy::types::ConcreteFunctionKey;
use typed_absy::types::{FunctionKey, Type, UBitwidth};
use typed_absy::{folder::*, *};
use zokrates_field::Field;
@ -25,7 +27,7 @@ use zokrates_field::Field;
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
struct Location<'ast> {
module: TypedModuleId,
key: FunctionKey<'ast>,
key: ConcreteFunctionKey<'ast>,
}
impl<'ast> Location<'ast> {
@ -37,11 +39,16 @@ impl<'ast> Location<'ast> {
type CallCache<'ast, T> = HashMap<
Location<'ast>,
HashMap<
FunctionKey<'ast>,
ConcreteFunctionKey<'ast>,
HashMap<Vec<TypedExpression<'ast, T>>, Vec<TypedExpression<'ast, T>>>,
>,
>;
enum InlineError<'ast, T> {
Flat(FunctionKey<'ast, T>, Vec<TypedExpression<'ast, T>>),
NonConstant(FunctionKey<'ast, T>, Vec<TypedExpression<'ast, T>>),
}
/// An inliner
#[derive(Debug)]
pub struct Inliner<'ast, T: Field> {
@ -52,9 +59,9 @@ pub struct Inliner<'ast, T: Field> {
/// a buffer of statements to be added to the inlined statements
statement_buffer: Vec<TypedStatement<'ast, T>>,
/// the current call stack
stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>,
stack: Vec<(TypedModuleId, ConcreteFunctionKey<'ast>, usize)>,
/// the call count for each function
call_count: HashMap<(TypedModuleId, FunctionKey<'ast>), usize>,
call_count: HashMap<(TypedModuleId, ConcreteFunctionKey<'ast>), usize>,
/// the cache for memoization: for each function body, tracks function calls
call_cache: CallCache<'ast, T>,
/// whether the inliner is blocked, and why
@ -65,7 +72,7 @@ impl<'ast, T: Field> Inliner<'ast, T> {
fn with_modules_and_module_id_and_key<S: Into<TypedModuleId>>(
modules: TypedModules<'ast, T>,
module_id: S,
key: FunctionKey<'ast>,
key: ConcreteFunctionKey<'ast>,
) -> Self {
Inliner {
modules,
@ -95,7 +102,11 @@ impl<'ast, T: Field> Inliner<'ast, T> {
.0;
// initialize an inliner over all modules, starting from the main module
Inliner::with_modules_and_module_id_and_key(p.modules, main_module_id, main_key.clone())
Inliner::with_modules_and_module_id_and_key(
p.modules,
main_module_id,
main_key.clone().try_into().unwrap(),
)
}
pub fn inline(&mut self, p: TypedProgram<'ast, T>) -> Output<'ast, T> {
@ -162,22 +173,47 @@ impl<'ast, T: Field> Inliner<'ast, T> {
}
}
fn get_concrete_function(
&self,
key: ConcreteFunctionKey<'ast>,
) -> TypedFunctionSymbol<'ast, T> {
unimplemented!()
}
fn try_inline_call(
&mut self,
key: FunctionKey<'ast, T>,
expressions: Vec<TypedExpression<'ast, T>>,
) -> Result<Vec<TypedExpression<'ast, T>>, InlineError<'ast, T>> {
match ConcreteFunctionKey::try_from(key) {
Ok(key) => self
.try_inline_concrete_call(key, expressions)
.map_err(|e| InlineError::Flat(e.0.into(), e.1)),
Err(()) => {
self.blocked = Some(Blocked::Inline);
Err(InlineError::NonConstant(key, expressions))
}
}
}
/// try to inline a call to function with key `key` in the stack of `self`
/// if inlining succeeds, return the expressions returned by the function call
/// if inlining fails (as in the case of flat function symbols), return the arguments to the function call for further processing
fn try_inline_call(
fn try_inline_concrete_call(
&mut self,
key: &FunctionKey<'ast>,
key: ConcreteFunctionKey<'ast>,
expressions: Vec<TypedExpression<'ast, T>>,
) -> Result<Vec<TypedExpression<'ast, T>>, (FunctionKey<'ast>, Vec<TypedExpression<'ast, T>>)>
{
match self.call_cache().get(key).map(|m| m.get(&expressions)) {
) -> Result<
Vec<TypedExpression<'ast, T>>,
(ConcreteFunctionKey<'ast>, Vec<TypedExpression<'ast, T>>),
> {
match self.call_cache().get(&key).map(|m| m.get(&expressions)) {
Some(Some(exprs)) => return Ok(exprs.clone()),
_ => {}
};
// here we clone a function symbol, which is cheap except when it contains the function body, in which case we'd clone anyways
let res = match self.module().functions.get(&key).unwrap().clone() {
let res = match self.get_concrete_function(key) {
// if the function called is in the same module, we can go ahead and inline in this module
TypedFunctionSymbol::Here(function) => {
let (current_module, current_key) =
@ -200,7 +236,7 @@ impl<'ast, T: Field> Inliner<'ast, T> {
.zip(expressions.clone())
.map(|(a, e)| {
TypedStatement::Definition(
self.fold_assignee(TypedAssignee::Identifier(a.id.clone())),
self.fold_assignee(TypedAssignee::Identifier(a.id.clone().into())),
e,
)
})
@ -233,24 +269,31 @@ impl<'ast, T: Field> Inliner<'ast, T> {
}
// if the function called is in some other module, we switch focus to that module and call the function locally there
TypedFunctionSymbol::There(function_key, module_id) => {
// switch focus to `module_id`
let (current_module, current_key) =
self.change_context(module_id, function_key.clone());
// inline the call there
let res = self.try_inline_call(&function_key, expressions.clone())?;
// switch back focus
self.change_context(current_module, current_key);
Ok(res)
unimplemented!()
// let function_key = function_key.try_into().unwrap();
// // switch focus to `module_id`
// let (current_module, current_key) =
// self.change_context(module_id, function_key.clone());
// // inline the call there
// let res = self.try_inline_call(&function_key, expressions.clone())?;
// // switch back focus
// self.change_context(current_module, current_key);
// Ok(res)
}
// if the function is a flat symbol, replace the call with a call to the local function we provide so it can be inlined in flattening
TypedFunctionSymbol::Flat(embed) => {
// increase the number of calls for this function by one
let _ = self
.call_count
.entry((self.module_id().clone(), embed.key::<T>().clone()))
.entry((
self.module_id().clone(),
embed.key::<T>().clone().try_into().unwrap(),
))
.and_modify(|i| *i += 1)
.or_insert(1);
Err((embed.key::<T>(), expressions.clone()))
Err((embed.key::<T>().try_into().unwrap(), expressions.clone()))
}
};
@ -267,8 +310,8 @@ impl<'ast, T: Field> Inliner<'ast, T> {
fn change_context(
&mut self,
module_id: TypedModuleId,
function_key: FunctionKey<'ast>,
) -> (TypedModuleId, FunctionKey<'ast>) {
function_key: ConcreteFunctionKey<'ast>,
) -> (TypedModuleId, ConcreteFunctionKey<'ast>) {
let current_module = std::mem::replace(&mut self.location.module, module_id);
let current_key = std::mem::replace(&mut self.location.key, function_key);
(current_module, current_key)
@ -281,7 +324,7 @@ impl<'ast, T: Field> Inliner<'ast, T> {
fn call_cache(
&mut self,
) -> &HashMap<
FunctionKey<'ast>,
ConcreteFunctionKey<'ast>,
HashMap<Vec<TypedExpression<'ast, T>>, Vec<TypedExpression<'ast, T>>>,
> {
self.call_cache
@ -292,7 +335,7 @@ impl<'ast, T: Field> Inliner<'ast, T> {
fn call_cache_mut(
&mut self,
) -> &mut HashMap<
FunctionKey<'ast>,
ConcreteFunctionKey<'ast>,
HashMap<Vec<TypedExpression<'ast, T>>, Vec<TypedExpression<'ast, T>>>,
> {
self.call_cache.get_mut(&self.location).unwrap()
@ -305,7 +348,10 @@ impl<'ast, T: Field> Inliner<'ast, T> {
impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> {
// add extra statements before the modified statement
fn fold_statement(&mut self, s: TypedStatement<'ast, T>) -> Vec<TypedStatement<'ast, T>> {
fn fold_statement<'a>(
&'a mut self,
s: TypedStatement<'ast, T>,
) -> Vec<TypedStatement<'ast, T>> {
let folded = match s {
TypedStatement::For(v, from, to, statements) => {
self.blocked = Some(Blocked::Unroll);
@ -319,7 +365,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> {
.collect();
let exps: Vec<_> = exps.into_iter().map(|e| self.fold_expression(e)).collect();
match self.try_inline_call(&key, exps) {
match self.try_inline_call(key, exps) {
Ok(ret) => variables
.into_iter()
.zip(ret.into_iter())
@ -327,16 +373,22 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> {
TypedStatement::Definition(TypedAssignee::Identifier(v), e)
})
.collect(),
Err((key, expressions)) => vec![TypedStatement::MultipleDefinition(
variables,
TypedExpressionList::FunctionCall(key, expressions, types),
)],
Err(e) => match e {
InlineError::Flat(key, expressions)
| InlineError::NonConstant(key, expressions) => {
vec![TypedStatement::MultipleDefinition(
variables,
TypedExpressionList::FunctionCall(key, expressions, types),
)]
}
},
}
}
},
s => fold_statement(self, s),
};
self.statement_buffer.drain(..).chain(folded).collect()
unimplemented!()
//self.statement_buffer.drain(..).chain(folded).collect()
}
// prefix all names with the stack
@ -356,28 +408,50 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> {
FieldElementExpression::FunctionCall(key, exps) => {
let exps: Vec<_> = exps.into_iter().map(|e| self.fold_expression(e)).collect();
match self.try_inline_call(&key, exps) {
match self.try_inline_call(key, exps) {
Ok(mut ret) => match ret.pop().unwrap() {
TypedExpression::FieldElement(e) => e,
_ => unreachable!(),
},
Err((key, expressions)) => {
let tys = key.signature.outputs.clone();
let id = Identifier {
id: CoreIdentifier::Call(key.clone()),
version: *self
.call_count
.get(&(self.module_id().clone(), key.clone()))
.unwrap(),
stack: self.stack.clone(),
};
self.statement_buffer
.push(TypedStatement::MultipleDefinition(
vec![Variable::with_id_and_type(id.clone(), tys[0].clone())],
TypedExpressionList::FunctionCall(key, expressions, tys),
));
FieldElementExpression::Identifier(id)
}
Err(e) => match e {
InlineError::Flat(key, expressions) => {
let key = ConcreteFunctionKey::try_from(key).unwrap();
let tys = key.signature.outputs.clone();
let id = Identifier {
id: CoreIdentifier::Call(key.clone()),
version: *self
.call_count
.get(&(self.module_id().clone(), key.clone()))
.unwrap(),
stack: self.stack.clone(),
};
self.statement_buffer
.push(TypedStatement::MultipleDefinition(
vec![Variable::with_id_and_type(
id.clone(),
tys[0].clone().into(),
)],
TypedExpressionList::FunctionCall(
key.into(),
expressions,
tys.into_iter().map(|t| t.into()).collect(),
),
));
self.call_cache_mut()
.entry(key.clone())
.or_insert_with(|| HashMap::new())
.insert(
expressions,
vec![FieldElementExpression::Identifier(id.clone()).into()],
);
FieldElementExpression::Identifier(id)
}
InlineError::NonConstant(key, expressions) => {
FieldElementExpression::FunctionCall(key, expressions)
}
},
}
}
e => fold_field_expression(self, e),
@ -393,41 +467,51 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> {
BooleanExpression::FunctionCall(key, exps) => {
let exps: Vec<_> = exps.into_iter().map(|e| self.fold_expression(e)).collect();
match self.try_inline_call(&key, exps) {
match self.try_inline_call(key, exps) {
Ok(mut ret) => match ret.pop().unwrap() {
TypedExpression::Boolean(e) => e,
_ => unreachable!(),
},
Err((key, expressions)) => {
let tys = key.signature.outputs.clone();
let id = Identifier {
id: CoreIdentifier::Call(key.clone()),
version: *self
.call_count
.get(&(self.module_id().clone(), key.clone()))
.unwrap(),
stack: self.stack.clone(),
};
self.statement_buffer
.push(TypedStatement::MultipleDefinition(
vec![Variable::with_id_and_type(id.clone(), tys[0].clone())],
TypedExpressionList::FunctionCall(
key.clone(),
expressions.clone(),
tys,
),
));
Err(e) => match e {
InlineError::Flat(key, expressions) => {
let key = ConcreteFunctionKey::try_from(key).unwrap();
self.call_cache_mut()
.entry(key.clone())
.or_insert_with(|| HashMap::new())
.insert(
expressions,
vec![BooleanExpression::Identifier(id.clone()).into()],
);
let tys = key.signature.outputs.clone();
let id = Identifier {
id: CoreIdentifier::Call(key.clone()),
version: *self
.call_count
.get(&(self.module_id().clone(), key.clone()))
.unwrap(),
stack: self.stack.clone(),
};
self.statement_buffer
.push(TypedStatement::MultipleDefinition(
vec![Variable::with_id_and_type(
id.clone(),
tys[0].clone().into(),
)],
TypedExpressionList::FunctionCall(
key.into(),
expressions,
tys.into_iter().map(|t| t.into()).collect(),
),
));
BooleanExpression::Identifier(id)
}
self.call_cache_mut()
.entry(key.clone())
.or_insert_with(|| HashMap::new())
.insert(
expressions,
vec![BooleanExpression::Identifier(id.clone()).into()],
);
BooleanExpression::Identifier(id)
}
InlineError::NonConstant(key, expressions) => {
BooleanExpression::FunctionCall(key, expressions)
}
},
}
}
e => fold_boolean_expression(self, e),
@ -437,51 +521,61 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> {
// inline calls which return an array
fn fold_array_expression_inner(
&mut self,
ty: &Type,
size: usize,
ty: &Type<'ast, T>,
size: UExpression<'ast, T>,
e: ArrayExpressionInner<'ast, T>,
) -> ArrayExpressionInner<'ast, T> {
match e {
ArrayExpressionInner::FunctionCall(key, exps) => {
let exps: Vec<_> = exps.into_iter().map(|e| self.fold_expression(e)).collect();
match self.try_inline_call(&key, exps) {
match self.try_inline_call(key, exps) {
Ok(mut ret) => match ret.pop().unwrap() {
TypedExpression::Array(e) => e.into_inner(),
_ => unreachable!(),
},
Err((embed_key, expressions)) => {
let tys = key.signature.outputs.clone();
let id = Identifier {
id: CoreIdentifier::Call(key.clone()),
version: *self
.call_count
.get(&(self.module_id().clone(), embed_key.clone()))
.unwrap(),
stack: self.stack.clone(),
};
self.statement_buffer
.push(TypedStatement::MultipleDefinition(
vec![Variable::with_id_and_type(id.clone(), tys[0].clone())],
TypedExpressionList::FunctionCall(
embed_key.clone(),
expressions.clone(),
tys,
),
));
Err(e) => match e {
InlineError::Flat(key, expressions) => {
let key = ConcreteFunctionKey::try_from(key).unwrap();
let out = ArrayExpressionInner::Identifier(id);
let tys = key.signature.outputs.clone();
let id = Identifier {
id: CoreIdentifier::Call(key.clone()),
version: *self
.call_count
.get(&(self.module_id().clone(), key.clone()))
.unwrap(),
stack: self.stack.clone(),
};
self.statement_buffer
.push(TypedStatement::MultipleDefinition(
vec![Variable::with_id_and_type(
id.clone(),
tys[0].clone().into(),
)],
TypedExpressionList::FunctionCall(
key.into(),
expressions.clone(),
tys.into_iter().map(|t| t.into()).collect(),
),
));
self.call_cache_mut()
.entry(key.clone())
.or_insert_with(|| HashMap::new())
.insert(
expressions,
vec![out.clone().annotate(ty.clone(), size).into()],
);
let out = ArrayExpressionInner::Identifier(id);
out
}
self.call_cache_mut()
.entry(key.clone())
.or_insert_with(|| HashMap::new())
.insert(
expressions,
vec![out.clone().annotate(ty.clone().into(), size).into()],
);
out
}
InlineError::NonConstant(key, expressions) => {
ArrayExpressionInner::FunctionCall(key, expressions)
}
},
}
}
// default
@ -491,35 +585,57 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> {
fn fold_struct_expression_inner(
&mut self,
ty: &StructType,
ty: &StructType<'ast, T>,
e: StructExpressionInner<'ast, T>,
) -> StructExpressionInner<'ast, T> {
match e {
StructExpressionInner::FunctionCall(key, exps) => {
let exps: Vec<_> = exps.into_iter().map(|e| self.fold_expression(e)).collect();
match self.try_inline_call(&key, exps) {
match self.try_inline_call(key, exps) {
Ok(mut ret) => match ret.pop().unwrap() {
TypedExpression::Struct(e) => e.into_inner(),
_ => unreachable!(),
},
Err((key, expressions)) => {
let tys = key.signature.outputs.clone();
let id = Identifier {
id: CoreIdentifier::Call(key.clone()),
version: *self
.call_count
.get(&(self.module_id().clone(), key.clone()))
.unwrap(),
stack: self.stack.clone(),
};
self.statement_buffer
.push(TypedStatement::MultipleDefinition(
vec![Variable::with_id_and_type(id.clone(), tys[0].clone())],
TypedExpressionList::FunctionCall(key, expressions, tys),
));
StructExpressionInner::Identifier(id)
}
Err(e) => match e {
InlineError::Flat(key, expressions) => {
let key = ConcreteFunctionKey::try_from(key).unwrap();
let tys = key.signature.outputs.clone();
let id = Identifier {
id: CoreIdentifier::Call(key.clone()),
version: *self
.call_count
.get(&(self.module_id().clone(), key.clone()))
.unwrap(),
stack: self.stack.clone(),
};
self.statement_buffer
.push(TypedStatement::MultipleDefinition(
vec![Variable::with_id_and_type(
id.clone(),
tys[0].clone().into(),
)],
TypedExpressionList::FunctionCall(
key.into(),
expressions,
tys.into_iter().map(|t| t.into()).collect(),
),
));
let out = StructExpressionInner::Identifier(id);
self.call_cache_mut()
.entry(key.clone())
.or_insert_with(|| HashMap::new())
.insert(expressions, vec![out.clone().annotate(ty.clone()).into()]);
out
}
InlineError::NonConstant(key, expressions) => {
StructExpressionInner::FunctionCall(key, expressions)
}
},
}
}
// default
@ -536,40 +652,50 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> {
UExpressionInner::FunctionCall(key, exps) => {
let exps: Vec<_> = exps.into_iter().map(|e| self.fold_expression(e)).collect();
match self.try_inline_call(&key, exps) {
match self.try_inline_call(key, exps) {
Ok(mut ret) => match ret.pop().unwrap() {
TypedExpression::Uint(e) => e.into_inner(),
_ => unreachable!(),
},
Err((embed_key, expressions)) => {
let tys = key.signature.outputs.clone();
let id = Identifier {
id: CoreIdentifier::Call(key.clone()),
version: *self
.call_count
.get(&(self.module_id().clone(), embed_key.clone()))
.unwrap(),
stack: self.stack.clone(),
};
self.statement_buffer
.push(TypedStatement::MultipleDefinition(
vec![Variable::with_id_and_type(id.clone(), tys[0].clone())],
TypedExpressionList::FunctionCall(
embed_key.clone(),
expressions.clone(),
tys,
),
));
Err(e) => match e {
InlineError::Flat(embed_key, expressions) => {
let key = ConcreteFunctionKey::try_from(key).unwrap();
let out = UExpressionInner::Identifier(id);
let tys = key.signature.outputs.clone();
let id = Identifier {
id: CoreIdentifier::Call(key.clone()),
version: *self
.call_count
.get(&(self.module_id().clone(), key.clone().into()))
.unwrap(),
stack: self.stack.clone(),
};
self.statement_buffer
.push(TypedStatement::MultipleDefinition(
vec![Variable::with_id_and_type(
id.clone(),
tys[0].clone().into(),
)],
TypedExpressionList::FunctionCall(
embed_key.clone().into(),
expressions.clone(),
tys.into_iter().map(|t| t.into()).collect(),
),
));
self.call_cache_mut()
.entry(key.clone())
.or_insert_with(|| HashMap::new())
.insert(expressions, vec![out.clone().annotate(size).into()]);
let out = UExpressionInner::Identifier(id);
out
}
self.call_cache_mut()
.entry(key.clone())
.or_insert_with(|| HashMap::new())
.insert(expressions, vec![out.clone().annotate(size).into()]);
out
}
InlineError::NonConstant(key, expressions) => {
UExpressionInner::FunctionCall(key, expressions)
}
},
}
}
// default

View file

@ -17,9 +17,7 @@ mod unroll;
mod variable_access_remover;
use self::flatten_complex_types::Flattener;
use self::inline::Inliner;
use self::propagate_unroll::PropagatedUnroller;
use self::propagation::Propagator;
use self::redefinition::RedefinitionOptimizer;
use self::return_binder::ReturnBinder;
use self::uint_optimizer::UintOptimizer;
@ -27,7 +25,7 @@ use self::unconstrained_vars::UnconstrainedVariableDetector;
use self::variable_access_remover::VariableAccessRemover;
use crate::flat_absy::FlatProg;
use crate::ir::Prog;
use crate::typed_absy::TypedProgram;
use crate::typed_absy::{abi::Abi, TypedProgram};
use zir::ZirProgram;
use zokrates_field::Field;
@ -36,9 +34,12 @@ pub trait Analyse {
}
impl<'ast, T: Field> TypedProgram<'ast, T> {
pub fn analyse(self) -> ZirProgram<'ast, T> {
pub fn analyse(self) -> (ZirProgram<'ast, T>, Abi) {
// propagated unrolling
let r = PropagatedUnroller::unroll(self).unwrap_or_else(|e| panic!(e));
let abi = r.abi().unwrap();
// return binding
let r = ReturnBinder::bind(r);
@ -60,7 +61,7 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
// optimize uint expressions
let zir = UintOptimizer::optimize(zir);
zir
(zir, abi)
}
}

View file

@ -139,7 +139,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
.collect();
fn process_u_from_bits<'ast, T: Field>(
variables: Vec<Variable<'ast>>,
variables: Vec<Variable<'ast, T>>,
arguments: Vec<TypedExpression<'ast, T>>,
bitwidth: UBitwidth,
) -> TypedExpression<'ast, T> {
@ -183,7 +183,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
}
fn process_u_to_bits<'ast, T: Field>(
variables: Vec<Variable<'ast>>,
variables: Vec<Variable<'ast, T>>,
arguments: Vec<TypedExpression<'ast, T>>,
bitwidth: UBitwidth,
) -> TypedExpression<'ast, T> {
@ -213,7 +213,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
.map(|v| BooleanExpression::Value(v).into())
.collect(),
)
.annotate(Type::Boolean, bitwidth.to_usize())
.annotate(Type::Boolean, bitwidth.to_usize() as u32)
.into()
}
_ => unreachable!("should be a uint value"),
@ -282,7 +282,10 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
})
.collect(),
)
.annotate(Type::Boolean, T::get_required_bits())
.annotate(
Type::Boolean,
T::get_required_bits() as u32,
)
.into(),
)
}
@ -505,45 +508,59 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
}
UExpressionInner::Select(box array, box index) => {
let array = self.fold_array_expression(array);
let index = self.fold_field_expression(index);
let index = self.fold_uint_expression(index);
let inner_type = array.inner_type().clone();
let size = array.size();
match (array.into_inner(), index) {
(ArrayExpressionInner::Value(v), FieldElementExpression::Number(n)) => {
let n_as_usize = n.to_dec_string().parse::<usize>().unwrap();
if n_as_usize < size {
UExpression::try_from(v[n_as_usize].clone())
.unwrap()
.into_inner()
} else {
unreachable!(
match size.into_inner() {
UExpressionInner::Value(size) => {
match (array.into_inner(), index.into_inner()) {
(ArrayExpressionInner::Value(v), UExpressionInner::Value(n)) => {
if n < size {
UExpression::try_from(v[n as usize].clone())
.unwrap()
.into_inner()
} else {
unreachable!(
"out of bounds index ({} >= {}) found during static analysis",
n_as_usize, size
n, size
);
}
}
(ArrayExpressionInner::Identifier(id), FieldElementExpression::Number(n)) => {
match self.constants.get(&TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array(
id.clone(),
inner_type.clone(),
size,
)),
box FieldElementExpression::Number(n.clone()).into(),
)) {
Some(e) => match e {
TypedExpression::Uint(e) => e.clone().into_inner(),
_ => unreachable!(""),
},
None => UExpressionInner::Select(
box ArrayExpressionInner::Identifier(id).annotate(inner_type, size),
box FieldElementExpression::Number(n),
}
}
(ArrayExpressionInner::Identifier(id), UExpressionInner::Value(n)) => {
match self.constants.get(&TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array(
id.clone(),
inner_type.clone(),
(size as u32).into(),
)),
box UExpressionInner::Value(n.clone())
.annotate(UBitwidth::B32)
.into(),
)) {
Some(e) => match e {
TypedExpression::Uint(e) => e.clone().into_inner(),
_ => unreachable!(""),
},
None => UExpressionInner::Select(
box ArrayExpressionInner::Identifier(id)
.annotate(inner_type, size as u32),
box UExpressionInner::Value(n).annotate(UBitwidth::B32),
),
}
}
(a, i) => UExpressionInner::Select(
box a.annotate(inner_type, size as u32),
box i.annotate(UBitwidth::B32),
),
}
}
(a, i) => UExpressionInner::Select(box a.annotate(inner_type, size), box i),
size => fold_uint_expression_inner(
self,
bitwidth,
UExpressionInner::Select(box array, box index),
),
}
}
UExpressionInner::FunctionCall(key, arguments) => {
@ -647,45 +664,54 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
}
FieldElementExpression::Select(box array, box index) => {
let array = self.fold_array_expression(array);
let index = self.fold_field_expression(index);
let index = self.fold_uint_expression(index);
let inner_type = array.inner_type().clone();
let size = array.size();
match (array.into_inner(), index) {
(ArrayExpressionInner::Value(v), FieldElementExpression::Number(n)) => {
let n_as_usize = n.to_dec_string().parse::<usize>().unwrap();
if n_as_usize < size {
FieldElementExpression::try_from(v[n_as_usize].clone()).unwrap()
} else {
unreachable!(
match size.into_inner() {
UExpressionInner::Value(size) => {
match (array.into_inner(), index.into_inner()) {
(ArrayExpressionInner::Value(v), UExpressionInner::Value(n)) => {
if n < size {
FieldElementExpression::try_from(v[n as usize].clone()).unwrap()
} else {
unreachable!(
"out of bounds index ({} >= {}) found during static analysis",
n_as_usize, size
n, size
);
}
}
(ArrayExpressionInner::Identifier(id), FieldElementExpression::Number(n)) => {
match self.constants.get(&TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array(
id.clone(),
inner_type.clone(),
size,
)),
box FieldElementExpression::Number(n.clone()).into(),
)) {
Some(e) => match e {
TypedExpression::FieldElement(e) => e.clone(),
_ => unreachable!("??"),
},
None => FieldElementExpression::Select(
box ArrayExpressionInner::Identifier(id).annotate(inner_type, size),
box FieldElementExpression::Number(n),
}
}
(ArrayExpressionInner::Identifier(id), UExpressionInner::Value(n)) => {
match self.constants.get(&TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array(
id.clone(),
inner_type.clone(),
(size as u32).into(),
)),
box UExpressionInner::Value(n.clone()).annotate(UBitwidth::B32),
)) {
Some(e) => match e {
TypedExpression::FieldElement(e) => e.clone(),
_ => unreachable!("??"),
},
None => FieldElementExpression::Select(
box ArrayExpressionInner::Identifier(id)
.annotate(inner_type, size as u32),
box UExpressionInner::Value(n).annotate(UBitwidth::B32),
),
}
}
(a, i) => FieldElementExpression::Select(
box a.annotate(inner_type, size as u32),
box i.annotate(UBitwidth::B32),
),
}
}
(a, i) => {
FieldElementExpression::Select(box a.annotate(inner_type, size), box i)
}
size => fold_field_expression(
self,
FieldElementExpression::Select(box array, box index),
),
}
}
FieldElementExpression::Member(box s, m) => {
@ -725,8 +751,8 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
fn fold_array_expression_inner(
&mut self,
ty: &Type,
size: usize,
ty: &Type<'ast, T>,
size: UExpression<'ast, T>,
e: ArrayExpressionInner<'ast, T>,
) -> ArrayExpressionInner<'ast, T> {
match e {
@ -747,45 +773,52 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
}
ArrayExpressionInner::Select(box array, box index) => {
let array = self.fold_array_expression(array);
let index = self.fold_field_expression(index);
let index = self.fold_uint_expression(index);
let inner_type = array.inner_type().clone();
let size = array.size();
match (array.into_inner(), index) {
(ArrayExpressionInner::Value(v), FieldElementExpression::Number(n)) => {
let n_as_usize = n.to_dec_string().parse::<usize>().unwrap();
if n_as_usize < size {
ArrayExpression::try_from(v[n_as_usize].clone())
.unwrap()
.into_inner()
} else {
unreachable!(
"out of bounds index ({} >= {}) found during static analysis",
n_as_usize, size
);
match size.into_inner() {
UExpressionInner::Value(size) => match (array.into_inner(), index.into_inner())
{
(ArrayExpressionInner::Value(v), UExpressionInner::Value(n)) => {
if n < size {
ArrayExpression::try_from(v[n as usize].clone())
.unwrap()
.into_inner()
} else {
unreachable!(
"out of bounds index ({} >= {}) found during static analysis",
n, size
);
}
}
}
(ArrayExpressionInner::Identifier(id), FieldElementExpression::Number(n)) => {
match self.constants.get(&TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array(
id.clone(),
inner_type.clone(),
size,
)),
box FieldElementExpression::Number(n.clone()).into(),
)) {
Some(e) => match e {
TypedExpression::Array(e) => e.clone().into_inner(),
_ => unreachable!("should be an array"),
},
None => ArrayExpressionInner::Select(
box ArrayExpressionInner::Identifier(id).annotate(inner_type, size),
box FieldElementExpression::Number(n),
),
(ArrayExpressionInner::Identifier(id), UExpressionInner::Value(n)) => {
match self.constants.get(&TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array(
id.clone(),
inner_type.clone(),
(size as u32).into(),
)),
box UExpressionInner::Value(n).annotate(UBitwidth::B32).into(),
)) {
Some(e) => match e {
TypedExpression::Array(e) => e.clone().into_inner(),
_ => unreachable!("should be an array"),
},
None => ArrayExpressionInner::Select(
box ArrayExpressionInner::Identifier(id)
.annotate(inner_type, size as u32),
box (n as u32).into(),
),
}
}
}
(a, i) => ArrayExpressionInner::Select(box a.annotate(inner_type, size), box i),
(a, i) => ArrayExpressionInner::Select(
box a.annotate(inner_type, size as u32),
box i.annotate(UBitwidth::B32),
),
},
size => fold_array_expression_inner(self, ty, size.annotate(UBitwidth::B32), e),
}
}
ArrayExpressionInner::IfElse(box condition, box consequence, box alternative) => {
@ -839,7 +872,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
fn fold_struct_expression_inner(
&mut self,
ty: &StructType,
ty: &StructType<'ast, T>,
e: StructExpressionInner<'ast, T>,
) -> StructExpressionInner<'ast, T> {
match e {
@ -859,47 +892,58 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
}
StructExpressionInner::Select(box array, box index) => {
let array = self.fold_array_expression(array);
let index = self.fold_field_expression(index);
let index = self.fold_uint_expression(index);
let inner_type = array.inner_type().clone();
let size = array.size();
match (array.into_inner(), index) {
(ArrayExpressionInner::Value(v), FieldElementExpression::Number(n)) => {
let n_as_usize = n.to_dec_string().parse::<usize>().unwrap();
if n_as_usize < size {
StructExpression::try_from(v[n_as_usize].clone())
.unwrap()
.into_inner()
} else {
unreachable!(
"out of bounds index ({} >= {}) found during static analysis",
n_as_usize, size
);
match size.into_inner() {
UExpressionInner::Value(size) => match (array.into_inner(), index.into_inner())
{
(ArrayExpressionInner::Value(v), UExpressionInner::Value(n)) => {
if n < size {
StructExpression::try_from(v[n as usize].clone())
.unwrap()
.into_inner()
} else {
unreachable!(
"out of bounds index ({} >= {}) found during static analysis",
n, size
);
}
}
}
(ArrayExpressionInner::Identifier(id), FieldElementExpression::Number(n)) => {
match self.constants.get(&TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array(
id.clone(),
inner_type.clone(),
size,
)),
box FieldElementExpression::Number(n.clone()).into(),
)) {
Some(e) => match e {
TypedExpression::Struct(e) => e.clone().into_inner(),
_ => unreachable!("should be a struct"),
},
None => StructExpressionInner::Select(
box ArrayExpressionInner::Identifier(id).annotate(inner_type, size),
box FieldElementExpression::Number(n),
),
(ArrayExpressionInner::Identifier(id), UExpressionInner::Value(n)) => {
match self.constants.get(&TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array(
id.clone(),
inner_type.clone(),
(size as u32).into(),
)),
box UExpressionInner::Value(n.clone())
.annotate(UBitwidth::B32)
.into(),
)) {
Some(e) => match e {
TypedExpression::Struct(e) => e.clone().into_inner(),
_ => unreachable!("should be a struct"),
},
None => StructExpressionInner::Select(
box ArrayExpressionInner::Identifier(id)
.annotate(inner_type, size as u32),
box UExpressionInner::Value(n).annotate(UBitwidth::B32),
),
}
}
}
(a, i) => {
StructExpressionInner::Select(box a.annotate(inner_type, size), box i)
}
(a, i) => StructExpressionInner::Select(
box a.annotate(inner_type, size as u32),
box i.annotate(UBitwidth::B32),
),
},
size => fold_struct_expression_inner(
self,
ty,
StructExpressionInner::Select(box array, box index),
),
}
}
StructExpressionInner::IfElse(box condition, box consequence, box alternative) => {
@ -1092,43 +1136,55 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
}
BooleanExpression::Select(box array, box index) => {
let array = self.fold_array_expression(array);
let index = self.fold_field_expression(index);
let index = self.fold_uint_expression(index);
let inner_type = array.inner_type().clone();
let size = array.size();
match (array.into_inner(), index) {
(ArrayExpressionInner::Value(v), FieldElementExpression::Number(n)) => {
let n_as_usize = n.to_dec_string().parse::<usize>().unwrap();
if n_as_usize < size {
BooleanExpression::try_from(v[n_as_usize].clone()).unwrap()
} else {
unreachable!(
"out of bounds index ({} >= {}) found during static analysis",
n_as_usize, size
);
match size.into_inner() {
UExpressionInner::Value(size) => match (array.into_inner(), index.into_inner())
{
(ArrayExpressionInner::Value(v), UExpressionInner::Value(n)) => {
if n < size {
BooleanExpression::try_from(v[n as usize].clone()).unwrap()
} else {
unreachable!(
"out of bounds index ({} >= {}) found during static analysis",
n, size
);
}
}
}
(ArrayExpressionInner::Identifier(id), FieldElementExpression::Number(n)) => {
match self.constants.get(&TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array(
id.clone(),
inner_type.clone(),
size,
)),
box FieldElementExpression::Number(n.clone()).into(),
)) {
Some(e) => match e {
TypedExpression::Boolean(e) => e.clone(),
_ => unreachable!("Should be a boolean"),
},
None => BooleanExpression::Select(
box ArrayExpressionInner::Identifier(id).annotate(inner_type, size),
box FieldElementExpression::Number(n),
),
(ArrayExpressionInner::Identifier(id), UExpressionInner::Value(n)) => {
match self.constants.get(&TypedAssignee::Select(
box TypedAssignee::Identifier(Variable::array(
id.clone(),
inner_type.clone(),
(size as u32).into(),
)),
box UExpressionInner::Value(n.clone())
.annotate(UBitwidth::B32)
.into(),
)) {
Some(e) => match e {
TypedExpression::Boolean(e) => e.clone(),
_ => unreachable!("Should be a boolean"),
},
None => BooleanExpression::Select(
box ArrayExpressionInner::Identifier(id)
.annotate(inner_type, size as u32),
box UExpressionInner::Value(n.clone()).annotate(UBitwidth::B32),
),
}
}
}
(a, i) => BooleanExpression::Select(box a.annotate(inner_type, size), box i),
(a, i) => BooleanExpression::Select(
box a.annotate(inner_type, size as u32),
box i.annotate(UBitwidth::B32),
),
},
size => fold_boolean_expression(
self,
BooleanExpression::Select(box array, box index),
),
}
}
BooleanExpression::Member(box s, m) => {

View file

@ -31,7 +31,7 @@ impl<'ast> Unroller<'ast> {
}
}
fn issue_next_ssa_variable(&mut self, v: Variable<'ast>) -> Variable<'ast> {
fn issue_next_ssa_variable<T: Field>(&mut self, v: Variable<'ast, T>) -> Variable<'ast, T> {
let res = match self.substitution.get(&v.id.id) {
Some(i) => Variable {
id: Identifier {
@ -79,162 +79,164 @@ impl<'ast> Unroller<'ast> {
let head = indices.remove(0);
let tail = indices;
match head {
Access::Select(head) => {
statements.insert(TypedStatement::Assertion(
BooleanExpression::Lt(
box head.clone(),
box FieldElementExpression::Number(T::from(size)),
)
.into(),
));
unimplemented!()
ArrayExpressionInner::Value(
(0..size)
.map(|i| match inner_ty {
Type::Array(..) => ArrayExpression::if_else(
BooleanExpression::FieldEq(
box FieldElementExpression::Number(T::from(i)),
box head.clone(),
),
match Self::choose_many(
ArrayExpression::select(
base.clone(),
FieldElementExpression::Number(T::from(i)),
)
.into(),
tail.clone(),
new_expression.clone(),
statements,
) {
TypedExpression::Array(e) => e,
e => unreachable!(
"the interior was expected to be an array, was {}",
e.get_type()
),
},
ArrayExpression::select(
base.clone(),
FieldElementExpression::Number(T::from(i)),
),
)
.into(),
Type::Struct(..) => StructExpression::if_else(
BooleanExpression::FieldEq(
box FieldElementExpression::Number(T::from(i)),
box head.clone(),
),
match Self::choose_many(
StructExpression::select(
base.clone(),
FieldElementExpression::Number(T::from(i)),
)
.into(),
tail.clone(),
new_expression.clone(),
statements,
) {
TypedExpression::Struct(e) => e,
e => unreachable!(
"the interior was expected to be a struct, was {}",
e.get_type()
),
},
StructExpression::select(
base.clone(),
FieldElementExpression::Number(T::from(i)),
),
)
.into(),
Type::FieldElement => FieldElementExpression::if_else(
BooleanExpression::FieldEq(
box FieldElementExpression::Number(T::from(i)),
box head.clone(),
),
match Self::choose_many(
FieldElementExpression::select(
base.clone(),
FieldElementExpression::Number(T::from(i)),
)
.into(),
tail.clone(),
new_expression.clone(),
statements,
) {
TypedExpression::FieldElement(e) => e,
e => unreachable!(
"the interior was expected to be a field, was {}",
e.get_type()
),
},
FieldElementExpression::select(
base.clone(),
FieldElementExpression::Number(T::from(i)),
),
)
.into(),
Type::Boolean => BooleanExpression::if_else(
BooleanExpression::FieldEq(
box FieldElementExpression::Number(T::from(i)),
box head.clone(),
),
match Self::choose_many(
BooleanExpression::select(
base.clone(),
FieldElementExpression::Number(T::from(i)),
)
.into(),
tail.clone(),
new_expression.clone(),
statements,
) {
TypedExpression::Boolean(e) => e,
e => unreachable!(
"the interior was expected to be a boolean, was {}",
e.get_type()
),
},
BooleanExpression::select(
base.clone(),
FieldElementExpression::Number(T::from(i)),
),
)
.into(),
Type::Uint(..) => UExpression::if_else(
BooleanExpression::FieldEq(
box FieldElementExpression::Number(T::from(i)),
box head.clone(),
),
match Self::choose_many(
UExpression::select(
base.clone(),
FieldElementExpression::Number(T::from(i)),
)
.into(),
tail.clone(),
new_expression.clone(),
statements,
) {
TypedExpression::Uint(e) => e,
e => unreachable!(
"the interior was expected to be a uint, was {}",
e.get_type()
),
},
UExpression::select(
base.clone(),
FieldElementExpression::Number(T::from(i)),
),
)
.into(),
})
.collect(),
)
.annotate(inner_ty.clone(), size)
.into()
}
Access::Member(..) => unreachable!("can't get a member from an array"),
}
// match head {
// Access::Select(head) => {
// statements.insert(TypedStatement::Assertion(
// BooleanExpression::Lt(
// box head.clone(),
// box FieldElementExpression::Number(T::from(size)),
// )
// .into(),
// ));
// ArrayExpressionInner::Value(
// (0..size)
// .map(|i| match inner_ty {
// Type::Array(..) => ArrayExpression::if_else(
// BooleanExpression::FieldEq(
// box FieldElementExpression::Number(T::from(i)),
// box head.clone(),
// ),
// match Self::choose_many(
// ArrayExpression::select(
// base.clone(),
// FieldElementExpression::Number(T::from(i)),
// )
// .into(),
// tail.clone(),
// new_expression.clone(),
// statements,
// ) {
// TypedExpression::Array(e) => e,
// e => unreachable!(
// "the interior was expected to be an array, was {}",
// e.get_type()
// ),
// },
// ArrayExpression::select(
// base.clone(),
// FieldElementExpression::Number(T::from(i)),
// ),
// )
// .into(),
// Type::Struct(..) => StructExpression::if_else(
// BooleanExpression::FieldEq(
// box FieldElementExpression::Number(T::from(i)),
// box head.clone(),
// ),
// match Self::choose_many(
// StructExpression::select(
// base.clone(),
// FieldElementExpression::Number(T::from(i)),
// )
// .into(),
// tail.clone(),
// new_expression.clone(),
// statements,
// ) {
// TypedExpression::Struct(e) => e,
// e => unreachable!(
// "the interior was expected to be a struct, was {}",
// e.get_type()
// ),
// },
// StructExpression::select(
// base.clone(),
// FieldElementExpression::Number(T::from(i)),
// ),
// )
// .into(),
// Type::FieldElement => FieldElementExpression::if_else(
// BooleanExpression::FieldEq(
// box FieldElementExpression::Number(T::from(i)),
// box head.clone(),
// ),
// match Self::choose_many(
// FieldElementExpression::select(
// base.clone(),
// FieldElementExpression::Number(T::from(i)),
// )
// .into(),
// tail.clone(),
// new_expression.clone(),
// statements,
// ) {
// TypedExpression::FieldElement(e) => e,
// e => unreachable!(
// "the interior was expected to be a field, was {}",
// e.get_type()
// ),
// },
// FieldElementExpression::select(
// base.clone(),
// FieldElementExpression::Number(T::from(i)),
// ),
// )
// .into(),
// Type::Boolean => BooleanExpression::if_else(
// BooleanExpression::FieldEq(
// box FieldElementExpression::Number(T::from(i)),
// box head.clone(),
// ),
// match Self::choose_many(
// BooleanExpression::select(
// base.clone(),
// FieldElementExpression::Number(T::from(i)),
// )
// .into(),
// tail.clone(),
// new_expression.clone(),
// statements,
// ) {
// TypedExpression::Boolean(e) => e,
// e => unreachable!(
// "the interior was expected to be a boolean, was {}",
// e.get_type()
// ),
// },
// BooleanExpression::select(
// base.clone(),
// FieldElementExpression::Number(T::from(i)),
// ),
// )
// .into(),
// Type::Uint(..) => UExpression::if_else(
// BooleanExpression::FieldEq(
// box FieldElementExpression::Number(T::from(i)),
// box head.clone(),
// ),
// match Self::choose_many(
// UExpression::select(
// base.clone(),
// FieldElementExpression::Number(T::from(i)),
// )
// .into(),
// tail.clone(),
// new_expression.clone(),
// statements,
// ) {
// TypedExpression::Uint(e) => e,
// e => unreachable!(
// "the interior was expected to be a uint, was {}",
// e.get_type()
// ),
// },
// UExpression::select(
// base.clone(),
// FieldElementExpression::Number(T::from(i)),
// ),
// )
// .into(),
// })
// .collect(),
// )
// .annotate(inner_ty.clone(), size)
// .into()
// }
// Access::Member(..) => unreachable!("can't get a member from an array"),
// }
}
TypedExpression::Struct(base) => {
let members = match base.get_type() {
@ -355,12 +357,12 @@ impl<'ast> Unroller<'ast> {
#[derive(Clone, Debug)]
enum Access<'ast, T: Field> {
Select(FieldElementExpression<'ast, T>),
Select(UExpression<'ast, T>),
Member(MemberId),
}
/// Turn an assignee into its representation as a base variable and a list accesses
/// a[2][3][4] -> (a, [2, 3, 4])
fn linear<'ast, T: Field>(a: TypedAssignee<'ast, T>) -> (Variable, Vec<Access<'ast, T>>) {
fn linear<'ast, T: Field>(a: TypedAssignee<'ast, T>) -> (Variable<'ast, T>, Vec<Access<'ast, T>>) {
match a {
TypedAssignee::Identifier(v) => (v, vec![]),
TypedAssignee::Select(box array, box index) => {
@ -415,7 +417,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Unroller<'ast> {
let indices = indices
.into_iter()
.map(|a| match a {
Access::Select(i) => Access::Select(self.fold_field_expression(i)),
Access::Select(i) => Access::Select(self.fold_uint_expression(i)),
a => a,
})
.collect();

View file

@ -29,22 +29,27 @@ impl<'ast, T: Field> VariableAccessRemover<'ast, T> {
fn select<U: Select<'ast, T> + IfElse<'ast, T>>(
&mut self,
a: ArrayExpression<'ast, T>,
i: FieldElementExpression<'ast, T>,
i: UExpression<'ast, T>,
) -> U {
match i {
FieldElementExpression::Number(i) => U::select(a, FieldElementExpression::Number(i)),
match i.into_inner() {
UExpressionInner::Value(i) => {
U::select(a, UExpressionInner::Value(i).annotate(UBitwidth::B32))
}
i => {
let size = match a.get_type().clone() {
Type::Array(array_ty) => array_ty.size,
Type::Array(array_ty) => match array_ty.size.into_inner() {
UExpressionInner::Value(size) => size as u32,
_ => unreachable!(),
},
_ => unreachable!(),
};
self.statements.push(TypedStatement::Assertion(
(0..size)
.map(|index| {
BooleanExpression::FieldEq(
box i.clone(),
box FieldElementExpression::Number(index.into()).into(),
BooleanExpression::UintEq(
box i.clone().annotate(UBitwidth::B32),
box index.into(),
)
})
.fold(None, |acc, e| match acc {
@ -56,14 +61,19 @@ impl<'ast, T: Field> VariableAccessRemover<'ast, T> {
));
(0..size)
.map(|i| U::select(a.clone(), FieldElementExpression::Number(i.into())))
.map(|i| {
U::select(
a.clone(),
UExpressionInner::Value(i.into()).annotate(UBitwidth::B32),
)
})
.enumerate()
.rev()
.fold(None, |acc, (index, res)| match acc {
Some(acc) => Some(U::if_else(
BooleanExpression::FieldEq(
box i.clone(),
box FieldElementExpression::Number(index.into()),
BooleanExpression::UintEq(
box i.clone().annotate(UBitwidth::B32),
box (index as u32).into(),
),
res,
acc,
@ -99,8 +109,8 @@ impl<'ast, T: Field> Folder<'ast, T> for VariableAccessRemover<'ast, T> {
fn fold_array_expression_inner(
&mut self,
ty: &Type,
size: usize,
ty: &Type<'ast, T>,
size: UExpression<'ast, T>,
e: ArrayExpressionInner<'ast, T>,
) -> ArrayExpressionInner<'ast, T> {
match e {
@ -113,7 +123,7 @@ impl<'ast, T: Field> Folder<'ast, T> for VariableAccessRemover<'ast, T> {
fn fold_struct_expression_inner(
&mut self,
ty: &StructType,
ty: &StructType<'ast, T>,
e: StructExpressionInner<'ast, T>,
) -> StructExpressionInner<'ast, T> {
match e {

View file

@ -1,15 +1,16 @@
use typed_absy::types::ConcreteSignature;
use typed_absy::types::ConcreteType;
use typed_absy::types::Signature;
use typed_absy::Type;
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct AbiInput {
pub name: String,
pub public: bool,
#[serde(flatten)]
pub ty: Type,
pub ty: ConcreteType,
}
pub type AbiOutput = Type;
pub type AbiOutput = ConcreteType;
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct Abi {
@ -18,7 +19,7 @@ pub struct Abi {
}
impl Abi {
pub fn signature(&self) -> Signature {
pub fn signature(&self) -> ConcreteSignature {
Signature {
inputs: self.inputs.iter().map(|i| i.ty.clone()).collect(),
outputs: self.outputs.clone(),

View file

@ -23,9 +23,9 @@ pub trait Folder<'ast, T: Field>: Sized {
fold_function(self, f)
}
fn fold_parameter(&mut self, p: Parameter<'ast>) -> Parameter<'ast> {
fn fold_parameter(&mut self, p: DeclarationParameter<'ast>) -> DeclarationParameter<'ast> {
Parameter {
id: self.fold_variable(p.id),
id: self.fold_declaration_variable(p.id),
..p
}
}
@ -34,19 +34,34 @@ pub trait Folder<'ast, T: Field>: Sized {
n
}
fn fold_variable(&mut self, v: Variable<'ast>) -> Variable<'ast> {
fn fold_variable(&mut self, v: Variable<'ast, T>) -> Variable<'ast, T> {
Variable {
id: self.fold_name(v.id),
..v
ty: self.fold_type(v.ty),
}
}
fn fold_declaration_variable(&mut self, v: Variable<'ast, T>) -> Variable<'ast, T> {
DeclarationVariable {
id: self.fold_name(v.id),
ty: self.fold_declaration_type(v.ty),
}
}
fn fold_type(&mut self, t: Type<T>) -> Type<T> {
unimplemented!()
}
fn fold_declaration_type(&mut self, t: DeclarationType) -> DeclarationType {
unimplemented!()
}
fn fold_assignee(&mut self, a: TypedAssignee<'ast, T>) -> TypedAssignee<'ast, T> {
match a {
TypedAssignee::Identifier(v) => TypedAssignee::Identifier(self.fold_variable(v)),
TypedAssignee::Select(box a, box index) => TypedAssignee::Select(
box self.fold_assignee(a),
box self.fold_field_expression(index),
box self.fold_uint_expression(index),
),
TypedAssignee::Member(box s, m) => TypedAssignee::Member(box self.fold_assignee(s), m),
}
@ -121,15 +136,15 @@ pub trait Folder<'ast, T: Field>: Sized {
fn fold_array_expression_inner(
&mut self,
ty: &Type,
size: usize,
ty: &Type<'ast, T>,
size: UExpression<'ast, T>,
e: ArrayExpressionInner<'ast, T>,
) -> ArrayExpressionInner<'ast, T> {
fold_array_expression_inner(self, ty, size, e)
}
fn fold_struct_expression_inner(
&mut self,
ty: &StructType,
ty: &StructType<'ast, T>,
e: StructExpressionInner<'ast, T>,
) -> StructExpressionInner<'ast, T> {
fold_struct_expression_inner(self, ty, e)
@ -185,8 +200,8 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
pub fn fold_array_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
_: &Type,
_: usize,
_: &Type<'ast, T>,
_: UExpression<'ast, T>,
e: ArrayExpressionInner<'ast, T>,
) -> ArrayExpressionInner<'ast, T> {
match e {
@ -211,7 +226,7 @@ pub fn fold_array_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
}
ArrayExpressionInner::Select(box array, box index) => {
let array = f.fold_array_expression(array);
let index = f.fold_field_expression(index);
let index = f.fold_uint_expression(index);
ArrayExpressionInner::Select(box array, box index)
}
}
@ -219,7 +234,7 @@ pub fn fold_array_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
pub fn fold_struct_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
_: &StructType,
_: &StructType<'ast, T>,
e: StructExpressionInner<'ast, T>,
) -> StructExpressionInner<'ast, T> {
match e {
@ -244,7 +259,7 @@ pub fn fold_struct_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
}
StructExpressionInner::Select(box array, box index) => {
let array = f.fold_array_expression(array);
let index = f.fold_field_expression(index);
let index = f.fold_uint_expression(index);
StructExpressionInner::Select(box array, box index)
}
}
@ -300,7 +315,7 @@ pub fn fold_field_expression<'ast, T: Field, F: Folder<'ast, T>>(
}
FieldElementExpression::Select(box array, box index) => {
let array = f.fold_array_expression(array);
let index = f.fold_field_expression(index);
let index = f.fold_uint_expression(index);
FieldElementExpression::Select(box array, box index)
}
}
@ -388,7 +403,7 @@ pub fn fold_boolean_expression<'ast, T: Field, F: Folder<'ast, T>>(
}
BooleanExpression::Select(box array, box index) => {
let array = f.fold_array_expression(array);
let index = f.fold_field_expression(index);
let index = f.fold_uint_expression(index);
BooleanExpression::Select(box array, box index)
}
}
@ -471,7 +486,7 @@ pub fn fold_uint_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
}
UExpressionInner::Select(box array, box index) => {
let array = f.fold_array_expression(array);
let index = f.fold_field_expression(index);
let index = f.fold_uint_expression(index);
UExpressionInner::Select(box array, box index)
}
UExpressionInner::IfElse(box cond, box cons, box alt) => {
@ -510,8 +525,11 @@ pub fn fold_array_expression<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
e: ArrayExpression<'ast, T>,
) -> ArrayExpression<'ast, T> {
let size = f.fold_uint_expression(e.size);
ArrayExpression {
inner: f.fold_array_expression_inner(&e.ty, e.size, e.inner),
inner: f.fold_array_expression_inner(&e.ty, size, e.inner),
size,
..e
}
}

View file

@ -1,12 +1,12 @@
use std::fmt;
use typed_absy::types::FunctionKey;
use typed_absy::types::ConcreteFunctionKey;
use typed_absy::TypedModuleId;
#[derive(Debug, PartialEq, Clone, Hash, Eq)]
pub enum CoreIdentifier<'ast> {
Source(&'ast str),
Internal(&'static str, usize),
Call(FunctionKey<'ast>),
Call(ConcreteFunctionKey<'ast>),
}
impl<'ast> fmt::Display for CoreIdentifier<'ast> {
@ -27,7 +27,7 @@ pub struct Identifier<'ast> {
/// the version of the variable, used after SSA transformation
pub version: usize,
/// the call stack of the variable, used when inlining
pub stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>,
pub stack: Vec<(TypedModuleId, ConcreteFunctionKey<'ast>, usize)>,
}
impl<'ast> fmt::Display for Identifier<'ast> {
@ -78,7 +78,7 @@ impl<'ast> Identifier<'ast> {
self
}
pub fn stack(mut self, stack: Vec<(TypedModuleId, FunctionKey<'ast>, usize)>) -> Self {
pub fn stack(mut self, stack: Vec<(TypedModuleId, ConcreteFunctionKey<'ast>, usize)>) -> Self {
self.stack = stack;
self
}

View file

@ -15,16 +15,18 @@ mod uint;
mod variable;
pub use self::identifier::CoreIdentifier;
pub use self::parameter::Parameter;
pub use self::types::{Signature, StructType, Type, UBitwidth};
pub use self::variable::Variable;
pub use self::parameter::{DeclarationParameter, GParameter, Parameter};
use self::types::{DeclarationFunctionKey, DeclarationSignature, GSignature, GStructType, GType};
pub use self::types::{DeclarationType, Signature, StructType, Type, UBitwidth};
pub use self::variable::{DeclarationVariable, GVariable, Variable};
use std::path::PathBuf;
pub use typed_absy::uint::{bitwidth, UExpression, UExpressionInner, UMetadata};
use crate::typed_absy::types::{FunctionKey, MemberId};
use embed::FlatEmbed;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::convert::{TryFrom, TryInto};
use std::fmt;
use zokrates_field::Field;
@ -43,7 +45,8 @@ pub type TypedModules<'ast, T> = HashMap<TypedModuleId, TypedModule<'ast, T>>;
/// # Remarks
/// * It is the role of the semantic checker to make sure there are no duplicates for a given `FunctionKey`
/// in a given `TypedModule`, hence the use of a HashMap
pub type TypedFunctionSymbols<'ast, T> = HashMap<FunctionKey<'ast>, TypedFunctionSymbol<'ast, T>>;
pub type TypedFunctionSymbols<'ast, T> =
HashMap<DeclarationFunctionKey<'ast>, TypedFunctionSymbol<'ast, T>>;
/// A typed program as a collection of modules, one of them being the main
#[derive(PartialEq, Debug, Clone)]
@ -53,7 +56,7 @@ pub struct TypedProgram<'ast, T> {
}
impl<'ast, T: Field> TypedProgram<'ast, T> {
pub fn abi(&self) -> Abi {
pub fn abi(&self) -> Result<Abi, ()> {
let main = self.modules[&self.main]
.functions
.iter()
@ -65,18 +68,25 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
_ => unreachable!(),
};
Abi {
Ok(Abi {
inputs: main
.arguments
.iter()
.map(|p| AbiInput {
public: !p.private,
name: p.id.id.to_string(),
ty: p.id._type.clone(),
.map(|p| {
types::ConcreteType::try_from(p.id._type.clone()).map(|ty| AbiInput {
public: !p.private,
name: p.id.id.to_string(),
ty,
})
})
.collect(),
outputs: main.signature.outputs.clone(),
}
.collect::<Result<_, ()>>()?,
outputs: main
.signature
.outputs
.iter()
.map(|ty| types::ConcreteType::try_from(ty.clone()))
.collect::<Result<_, ()>>()?,
})
}
}
@ -112,7 +122,7 @@ pub struct TypedModule<'ast, T> {
#[derive(Clone, PartialEq)]
pub enum TypedFunctionSymbol<'ast, T> {
Here(TypedFunction<'ast, T>),
There(FunctionKey<'ast>, TypedModuleId),
There(DeclarationFunctionKey<'ast>, TypedModuleId),
Flat(FlatEmbed),
}
@ -128,7 +138,10 @@ impl<'ast, T: fmt::Debug> fmt::Debug for TypedFunctionSymbol<'ast, T> {
}
impl<'ast, T: Field> TypedFunctionSymbol<'ast, T> {
pub fn signature<'a>(&'a self, modules: &'a TypedModules<T>) -> Signature {
pub fn signature<'a>(
&'a self,
modules: &'a TypedModules<'ast, T>,
) -> DeclarationSignature<'ast> {
match self {
TypedFunctionSymbol::Here(f) => f.signature.clone(),
TypedFunctionSymbol::There(key, module_id) => modules
@ -139,7 +152,7 @@ impl<'ast, T: Field> TypedFunctionSymbol<'ast, T> {
.unwrap()
.signature(&modules)
.clone(),
TypedFunctionSymbol::Flat(flat_fun) => flat_fun.signature(),
TypedFunctionSymbol::Flat(flat_fun) => flat_fun.signature().try_into().unwrap(),
}
}
}
@ -185,11 +198,11 @@ impl<'ast, T: fmt::Debug> fmt::Debug for TypedModule<'ast, T> {
#[derive(Clone, PartialEq)]
pub struct TypedFunction<'ast, T> {
/// Arguments of the function
pub arguments: Vec<Parameter<'ast>>,
pub arguments: Vec<DeclarationParameter<'ast>>,
/// Vector of statements that are executed when running the function
pub statements: Vec<TypedStatement<'ast, T>>,
/// function signature
pub signature: Signature,
pub signature: DeclarationSignature<'ast>,
}
impl<'ast, T: fmt::Display> fmt::Display for TypedFunction<'ast, T> {
@ -251,16 +264,13 @@ impl<'ast, T: fmt::Debug> fmt::Debug for TypedFunction<'ast, T> {
/// Something we can assign to.
#[derive(Clone, PartialEq, Hash, Eq)]
pub enum TypedAssignee<'ast, T> {
Identifier(Variable<'ast>),
Select(
Box<TypedAssignee<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Identifier(Variable<'ast, T>),
Select(Box<TypedAssignee<'ast, T>>, Box<UExpression<'ast, T>>),
Member(Box<TypedAssignee<'ast, T>>, MemberId),
}
impl<'ast, T> Typed for TypedAssignee<'ast, T> {
fn get_type(&self) -> Type {
impl<'ast, T> Typed<'ast, T> for TypedAssignee<'ast, T> {
fn get_type(&self) -> Type<'ast, T> {
match *self {
TypedAssignee::Identifier(ref v) => v.get_type(),
TypedAssignee::Select(ref a, _) => {
@ -311,15 +321,15 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedAssignee<'ast, T> {
pub enum TypedStatement<'ast, T> {
Return(Vec<TypedExpression<'ast, T>>),
Definition(TypedAssignee<'ast, T>, TypedExpression<'ast, T>),
Declaration(Variable<'ast>),
Declaration(Variable<'ast, T>),
Assertion(BooleanExpression<'ast, T>),
For(
Variable<'ast>,
Variable<'ast, T>,
UExpression<'ast, T>,
UExpression<'ast, T>,
Vec<TypedStatement<'ast, T>>,
),
MultipleDefinition(Vec<Variable<'ast>>, TypedExpressionList<'ast, T>),
MultipleDefinition(Vec<Variable<'ast, T>>, TypedExpressionList<'ast, T>),
}
impl<'ast, T: fmt::Debug> fmt::Debug for TypedStatement<'ast, T> {
@ -407,8 +417,8 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> {
}
}
pub trait Typed {
fn get_type(&self) -> Type;
pub trait Typed<'ast, T> {
fn get_type(&self) -> Type<'ast, T>;
}
/// A typed expression
@ -531,8 +541,8 @@ impl<'ast, T: fmt::Debug> fmt::Debug for StructExpression<'ast, T> {
}
}
impl<'ast, T> Typed for TypedExpression<'ast, T> {
fn get_type(&self) -> Type {
impl<'ast, T> Typed<'ast, T> for TypedExpression<'ast, T> {
fn get_type(&self) -> Type<'ast, T> {
match *self {
TypedExpression::Boolean(ref e) => e.get_type(),
TypedExpression::FieldElement(ref e) => e.get_type(),
@ -543,47 +553,51 @@ impl<'ast, T> Typed for TypedExpression<'ast, T> {
}
}
impl<'ast, T> Typed for ArrayExpression<'ast, T> {
fn get_type(&self) -> Type {
impl<'ast, T> Typed<'ast, T> for ArrayExpression<'ast, T> {
fn get_type(&self) -> Type<'ast, T> {
Type::array(self.ty.clone(), self.size)
}
}
impl<'ast, T> Typed for StructExpression<'ast, T> {
fn get_type(&self) -> Type {
impl<'ast, T> Typed<'ast, T> for StructExpression<'ast, T> {
fn get_type(&self) -> Type<'ast, T> {
Type::Struct(self.ty.clone())
}
}
impl<'ast, T> Typed for FieldElementExpression<'ast, T> {
fn get_type(&self) -> Type {
impl<'ast, T> Typed<'ast, T> for FieldElementExpression<'ast, T> {
fn get_type(&self) -> Type<'ast, T> {
Type::FieldElement
}
}
impl<'ast, T> Typed for UExpression<'ast, T> {
fn get_type(&self) -> Type {
impl<'ast, T> Typed<'ast, T> for UExpression<'ast, T> {
fn get_type(&self) -> Type<'ast, T> {
Type::Uint(self.bitwidth)
}
}
impl<'ast, T> Typed for BooleanExpression<'ast, T> {
fn get_type(&self) -> Type {
impl<'ast, T> Typed<'ast, T> for BooleanExpression<'ast, T> {
fn get_type(&self) -> Type<'ast, T> {
Type::Boolean
}
}
pub trait MultiTyped {
fn get_types(&self) -> &Vec<Type>;
pub trait MultiTyped<'ast, T> {
fn get_types(&self) -> &Vec<Type<'ast, T>>;
}
#[derive(Clone, PartialEq, Hash, Eq)]
pub enum TypedExpressionList<'ast, T> {
FunctionCall(FunctionKey<'ast>, Vec<TypedExpression<'ast, T>>, Vec<Type>),
FunctionCall(
FunctionKey<'ast, T>,
Vec<TypedExpression<'ast, T>>,
Vec<Type<'ast, T>>,
),
}
impl<'ast, T> MultiTyped for TypedExpressionList<'ast, T> {
fn get_types(&self) -> &Vec<Type> {
impl<'ast, T> MultiTyped<'ast, T> for TypedExpressionList<'ast, T> {
fn get_types(&self) -> &Vec<Type<'ast, T>> {
match *self {
TypedExpressionList::FunctionCall(_, _, ref types) => types,
}
@ -620,12 +634,9 @@ pub enum FieldElementExpression<'ast, T> {
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
FunctionCall(FunctionKey<'ast>, Vec<TypedExpression<'ast, T>>),
FunctionCall(FunctionKey<'ast, T>, Vec<TypedExpression<'ast, T>>),
Member(Box<StructExpression<'ast, T>>, MemberId),
Select(
Box<ArrayExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Select(Box<ArrayExpression<'ast, T>>, Box<UExpression<'ast, T>>),
}
/// An expression of type `bool`
@ -678,11 +689,8 @@ pub enum BooleanExpression<'ast, T> {
Box<BooleanExpression<'ast, T>>,
),
Member(Box<StructExpression<'ast, T>>, MemberId),
FunctionCall(FunctionKey<'ast>, Vec<TypedExpression<'ast, T>>),
Select(
Box<ArrayExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
FunctionCall(FunctionKey<'ast, T>, Vec<TypedExpression<'ast, T>>),
Select(Box<ArrayExpression<'ast, T>>, Box<UExpression<'ast, T>>),
}
/// An expression of type `array`
@ -692,8 +700,8 @@ pub enum BooleanExpression<'ast, T> {
/// type checking
#[derive(Clone, PartialEq, Hash, Eq)]
pub struct ArrayExpression<'ast, T> {
size: usize,
ty: Type,
size: UExpression<'ast, T>,
ty: Type<'ast, T>,
inner: ArrayExpressionInner<'ast, T>,
}
@ -701,23 +709,24 @@ pub struct ArrayExpression<'ast, T> {
pub enum ArrayExpressionInner<'ast, T> {
Identifier(Identifier<'ast>),
Value(Vec<TypedExpression<'ast, T>>),
FunctionCall(FunctionKey<'ast>, Vec<TypedExpression<'ast, T>>),
FunctionCall(FunctionKey<'ast, T>, Vec<TypedExpression<'ast, T>>),
IfElse(
Box<BooleanExpression<'ast, T>>,
Box<ArrayExpression<'ast, T>>,
Box<ArrayExpression<'ast, T>>,
),
Member(Box<StructExpression<'ast, T>>, MemberId),
Select(
Box<ArrayExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Select(Box<ArrayExpression<'ast, T>>, Box<UExpression<'ast, T>>),
}
impl<'ast, T> ArrayExpressionInner<'ast, T> {
pub fn annotate(self, ty: Type, size: usize) -> ArrayExpression<'ast, T> {
pub fn annotate<S: Into<UExpression<'ast, T>>>(
self,
ty: Type<'ast, T>,
size: S,
) -> ArrayExpression<'ast, T> {
ArrayExpression {
size,
size: size.into(),
ty,
inner: self,
}
@ -725,11 +734,11 @@ impl<'ast, T> ArrayExpressionInner<'ast, T> {
}
impl<'ast, T> ArrayExpression<'ast, T> {
pub fn inner_type(&self) -> &Type {
pub fn inner_type(&self) -> &Type<'ast, T> {
&self.ty
}
pub fn size(&self) -> usize {
pub fn size(&self) -> UExpression<'ast, T> {
self.size
}
@ -744,12 +753,12 @@ impl<'ast, T> ArrayExpression<'ast, T> {
#[derive(Clone, PartialEq, Hash, Eq)]
pub struct StructExpression<'ast, T> {
ty: StructType,
ty: StructType<'ast, T>,
inner: StructExpressionInner<'ast, T>,
}
impl<'ast, T> StructExpression<'ast, T> {
pub fn ty(&self) -> &StructType {
pub fn ty(&self) -> &StructType<'ast, T> {
&self.ty
}
@ -766,21 +775,18 @@ impl<'ast, T> StructExpression<'ast, T> {
pub enum StructExpressionInner<'ast, T> {
Identifier(Identifier<'ast>),
Value(Vec<TypedExpression<'ast, T>>),
FunctionCall(FunctionKey<'ast>, Vec<TypedExpression<'ast, T>>),
FunctionCall(FunctionKey<'ast, T>, Vec<TypedExpression<'ast, T>>),
IfElse(
Box<BooleanExpression<'ast, T>>,
Box<StructExpression<'ast, T>>,
Box<StructExpression<'ast, T>>,
),
Member(Box<StructExpression<'ast, T>>, MemberId),
Select(
Box<ArrayExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Select(Box<ArrayExpression<'ast, T>>, Box<UExpression<'ast, T>>),
}
impl<'ast, T> StructExpressionInner<'ast, T> {
pub fn annotate(self, ty: StructType) -> StructExpression<'ast, T> {
pub fn annotate(self, ty: StructType<'ast, T>) -> StructExpression<'ast, T> {
StructExpression { ty, inner: self }
}
}
@ -1212,23 +1218,23 @@ impl<'ast, T> IfElse<'ast, T> for StructExpression<'ast, T> {
}
pub trait Select<'ast, T> {
fn select(array: ArrayExpression<'ast, T>, index: FieldElementExpression<'ast, T>) -> Self;
fn select(array: ArrayExpression<'ast, T>, index: UExpression<'ast, T>) -> Self;
}
impl<'ast, T> Select<'ast, T> for FieldElementExpression<'ast, T> {
fn select(array: ArrayExpression<'ast, T>, index: FieldElementExpression<'ast, T>) -> Self {
fn select(array: ArrayExpression<'ast, T>, index: UExpression<'ast, T>) -> Self {
FieldElementExpression::Select(box array, box index)
}
}
impl<'ast, T> Select<'ast, T> for BooleanExpression<'ast, T> {
fn select(array: ArrayExpression<'ast, T>, index: FieldElementExpression<'ast, T>) -> Self {
fn select(array: ArrayExpression<'ast, T>, index: UExpression<'ast, T>) -> Self {
BooleanExpression::Select(box array, box index)
}
}
impl<'ast, T> Select<'ast, T> for UExpression<'ast, T> {
fn select(array: ArrayExpression<'ast, T>, index: FieldElementExpression<'ast, T>) -> Self {
fn select(array: ArrayExpression<'ast, T>, index: UExpression<'ast, T>) -> Self {
let bitwidth = match array.inner_type().clone() {
Type::Uint(bitwidth) => bitwidth,
_ => unreachable!(),
@ -1239,7 +1245,7 @@ impl<'ast, T> Select<'ast, T> for UExpression<'ast, T> {
}
impl<'ast, T> Select<'ast, T> for ArrayExpression<'ast, T> {
fn select(array: ArrayExpression<'ast, T>, index: FieldElementExpression<'ast, T>) -> Self {
fn select(array: ArrayExpression<'ast, T>, index: UExpression<'ast, T>) -> Self {
let (ty, size) = match array.inner_type() {
Type::Array(array_type) => (array_type.ty.clone(), array_type.size.clone()),
_ => unreachable!(),
@ -1250,7 +1256,7 @@ impl<'ast, T> Select<'ast, T> for ArrayExpression<'ast, T> {
}
impl<'ast, T> Select<'ast, T> for StructExpression<'ast, T> {
fn select(array: ArrayExpression<'ast, T>, index: FieldElementExpression<'ast, T>) -> Self {
fn select(array: ArrayExpression<'ast, T>, index: UExpression<'ast, T>) -> Self {
let members = match array.inner_type().clone() {
Type::Struct(members) => members,
_ => unreachable!(),

View file

@ -1,15 +1,18 @@
use crate::typed_absy::Variable;
use crate::typed_absy::GVariable;
use std::fmt;
use typed_absy::types::Constant;
use typed_absy::TryFrom;
use typed_absy::UExpression;
#[derive(Clone, PartialEq)]
pub struct Parameter<'ast> {
pub id: Variable<'ast>,
pub struct GParameter<'ast, S> {
pub id: GVariable<'ast, S>,
pub private: bool,
}
impl<'ast> Parameter<'ast> {
impl<'ast, S> GParameter<'ast, S> {
#[cfg(test)]
pub fn private(v: Variable<'ast>) -> Self {
pub fn private(v: GVariable<'ast, S>) -> Self {
Parameter {
id: v,
private: true,
@ -17,14 +20,32 @@ impl<'ast> Parameter<'ast> {
}
}
impl<'ast> fmt::Display for Parameter<'ast> {
pub type DeclarationParameter<'ast> = GParameter<'ast, Constant<'ast>>;
pub type ConcreteParameter<'ast> = GParameter<'ast, usize>;
pub type Parameter<'ast, T> = GParameter<'ast, UExpression<'ast, T>>;
impl<'ast, T> TryFrom<Parameter<'ast, T>> for ConcreteParameter<'ast> {
type Error = ();
fn try_from(t: Parameter<'ast, T>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast, T> From<ConcreteParameter<'ast>> for Parameter<'ast, T> {
fn from(t: ConcreteParameter<'ast>) -> Self {
unimplemented!()
}
}
impl<'ast, S> fmt::Display for GParameter<'ast, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let visibility = if self.private { "private " } else { "" };
write!(f, "{}{} {}", visibility, self.id.get_type(), self.id.id)
}
}
impl<'ast> fmt::Debug for Parameter<'ast> {
impl<'ast, S> fmt::Debug for GParameter<'ast, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Parameter(variable: {:?})", self.id)
}

View file

@ -1,49 +1,119 @@
use std::cmp::Ordering;
use std::fmt;
use std::path::PathBuf;
use typed_absy::TryFrom;
use typed_absy::UExpression;
pub type Identifier<'ast> = &'ast str;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Constant<'ast> {
Generic(Identifier<'ast>),
Concrete(u32),
}
impl<'ast> From<u32> for Constant<'ast> {
fn from(e: u32) -> Self {
Constant::Concrete(e)
}
}
impl<'ast> From<Identifier<'ast>> for Constant<'ast> {
fn from(e: Identifier<'ast>) -> Self {
Constant::Generic(e)
}
}
pub type MemberId = String;
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct StructMember {
pub struct GStructMember<S> {
#[serde(rename = "name")]
pub id: MemberId,
#[serde(flatten)]
pub ty: Box<Type>,
pub ty: Box<GType<S>>,
}
pub type DeclarationStructMember<'ast> = GStructMember<Constant<'ast>>;
pub type ConcreteStructMember = GStructMember<usize>;
pub type StructMember<'ast, T> = GStructMember<UExpression<'ast, T>>;
impl<'ast, T> TryFrom<StructMember<'ast, T>> for ConcreteStructMember {
type Error = ();
fn try_from(t: StructMember<'ast, T>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast, T> From<ConcreteStructMember> for StructMember<'ast, T> {
fn from(t: ConcreteStructMember) -> Self {
unimplemented!()
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct GArrayType<S> {
pub size: S,
#[serde(flatten)]
pub ty: Box<Type>,
pub ty: Box<GType<S>>,
}
pub type ArrayType = GArrayType<usize>;
pub type DeclarationArrayType<'ast> = GArrayType<Constant<'ast>>;
pub type ConcreteArrayType = GArrayType<usize>;
pub type ArrayType<'ast, T> = GArrayType<UExpression<'ast, T>>;
pub type UArrayType<'ast, T> = GArrayType<UExpression<'ast, T>>;
impl<'ast, T> TryFrom<ArrayType<'ast, T>> for ConcreteArrayType {
type Error = ();
fn try_from(t: ArrayType<'ast, T>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast, T> From<ConcreteArrayType> for ArrayType<'ast, T> {
fn from(t: ConcreteArrayType) -> Self {
unimplemented!()
}
}
#[derive(Clone, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct StructType {
pub struct GStructType<S> {
#[serde(skip)]
pub module: PathBuf,
pub name: String,
pub members: Vec<StructMember>,
pub members: Vec<GStructMember<S>>,
}
impl PartialEq for StructType {
pub type DeclarationStructType<'ast> = GStructType<Constant<'ast>>;
pub type ConcreteStructType = GStructType<usize>;
pub type StructType<'ast, T> = GStructType<UExpression<'ast, T>>;
impl<'ast, T> TryFrom<StructType<'ast, T>> for ConcreteStructType {
type Error = ();
fn try_from(t: StructType<'ast, T>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast, T> From<ConcreteStructType> for StructType<'ast, T> {
fn from(t: ConcreteStructType) -> Self {
unimplemented!()
}
}
impl<S> PartialEq for GStructType<S> {
fn eq(&self, other: &Self) -> bool {
self.members.eq(&other.members)
}
}
impl Eq for StructType {}
impl<S> Eq for GStructType<S> {}
impl StructType {
pub fn new(module: PathBuf, name: String, members: Vec<StructMember>) -> Self {
StructType {
impl<S> GStructType<S> {
pub fn new(module: PathBuf, name: String, members: Vec<GStructMember<S>>) -> Self {
GStructType {
module,
name,
members,
@ -54,13 +124,13 @@ impl StructType {
self.members.len()
}
pub fn iter(&self) -> std::slice::Iter<StructMember> {
pub fn iter(&self) -> std::slice::Iter<GStructMember<S>> {
self.members.iter()
}
}
impl IntoIterator for StructType {
type Item = StructMember;
impl<S> IntoIterator for GStructType<S> {
type Item = GStructMember<S>;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
@ -101,47 +171,120 @@ impl fmt::Display for UBitwidth {
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
#[derive(Clone, Hash, Serialize, Deserialize)]
#[serde(tag = "type", content = "components")]
pub enum Type {
pub enum GType<S> {
#[serde(rename = "field")]
FieldElement,
#[serde(rename = "bool")]
Boolean,
#[serde(rename = "array")]
Array(ArrayType),
Array(GArrayType<S>),
#[serde(rename = "struct")]
Struct(StructType),
Struct(GStructType<S>),
#[serde(rename = "u")]
Uint(UBitwidth),
}
pub type DeclarationType<'ast> = GType<Constant<'ast>>;
pub type ConcreteType = GType<usize>;
pub type Type<'ast, T> = GType<UExpression<'ast, T>>;
// we have a looser equality relationship for generic types: an array of unknown size of a given type is equal to any arrays of that type
impl<'ast, T> PartialEq for Type<'ast, T> {
fn eq(&self, other: &Self) -> bool {
unimplemented!()
}
}
impl PartialEq for ConcreteType {
fn eq(&self, other: &Self) -> bool {
unimplemented!()
}
}
impl<'ast, T> Eq for Type<'ast, T> {}
impl Eq for ConcreteType {}
impl<'ast, T> PartialOrd for Type<'ast, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
unimplemented!()
}
}
impl PartialOrd for ConcreteType {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
unimplemented!()
}
}
impl<'ast, T> Ord for Type<'ast, T> {
fn cmp(&self, other: &Self) -> Ordering {
unimplemented!()
}
}
impl Ord for ConcreteType {
fn cmp(&self, other: &Self) -> Ordering {
unimplemented!()
}
}
impl<'ast, T> TryFrom<Type<'ast, T>> for ConcreteType {
type Error = ();
fn try_from(t: Type<'ast, T>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast> TryFrom<DeclarationType<'ast>> for ConcreteType {
type Error = ();
fn try_from(t: DeclarationType<'ast>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast, T> From<ConcreteType> for Type<'ast, T> {
fn from(t: ConcreteType) -> Self {
unimplemented!()
}
}
impl<'ast, T> From<DeclarationType<'ast>> for Type<'ast, T> {
fn from(t: DeclarationType<'ast>) -> Self {
unimplemented!()
}
}
impl<S> GArrayType<S> {
pub fn new(ty: Type, size: S) -> Self {
GArrayType {
pub fn new(ty: GType<S>, size: S) -> Self {
ArrayType {
ty: Box::new(ty),
size,
}
}
}
impl StructMember {
pub fn new(id: String, ty: Type) -> Self {
StructMember {
impl<S> GStructMember<S> {
pub fn new(id: String, ty: GType<S>) -> Self {
GStructMember {
id,
ty: Box::new(ty),
}
}
}
impl fmt::Display for Type {
impl<S> fmt::Display for GType<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Type::FieldElement => write!(f, "field"),
Type::Boolean => write!(f, "bool"),
Type::Uint(ref bitwidth) => write!(f, "u{}", bitwidth),
Type::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size),
Type::Struct(ref struct_type) => write!(
GType::FieldElement => write!(f, "field"),
GType::Boolean => write!(f, "bool"),
GType::Uint(ref bitwidth) => write!(f, "u{}", bitwidth),
GType::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size),
GType::Struct(ref struct_type) => write!(
f,
"{} {{{}}}",
struct_type.name,
@ -156,14 +299,14 @@ impl fmt::Display for Type {
}
}
impl fmt::Debug for Type {
impl<S> fmt::Debug for GType<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Type::FieldElement => write!(f, "field"),
Type::Boolean => write!(f, "bool"),
Type::Uint(ref bitwidth) => write!(f, "u{}", bitwidth),
Type::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size),
Type::Struct(ref struct_type) => write!(
GType::FieldElement => write!(f, "field"),
GType::Boolean => write!(f, "bool"),
GType::Uint(ref bitwidth) => write!(f, "u{}", bitwidth),
GType::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size),
GType::Struct(ref struct_type) => write!(
f,
"{} {{{}}}",
struct_type.name,
@ -178,26 +321,26 @@ impl fmt::Debug for Type {
}
}
impl Type {
pub fn array(ty: Type, size: usize) -> Self {
Type::Array(ArrayType::new(ty, size))
impl<S> GType<S> {
pub fn array<U: Into<S>>(ty: GType<S>, size: U) -> Self {
GType::Array(ArrayType::new(ty, size.into()))
}
pub fn struc(struct_ty: StructType) -> Self {
Type::Struct(struct_ty)
pub fn struc(struct_ty: GStructType<S>) -> Self {
GType::Struct(struct_ty)
}
pub fn uint<W: Into<UBitwidth>>(b: W) -> Self {
Type::Uint(b.into())
GType::Uint(b.into())
}
fn to_slug(&self) -> String {
match self {
Type::FieldElement => String::from("f"),
Type::Boolean => String::from("b"),
Type::Uint(bitwidth) => format!("u{}", bitwidth),
Type::Array(array_type) => format!("{}[{}]", array_type.ty.to_slug(), array_type.size),
Type::Struct(struct_type) => format!(
GType::FieldElement => String::from("f"),
GType::Boolean => String::from("b"),
GType::Uint(bitwidth) => format!("u{}", bitwidth),
GType::Array(array_type) => format!("{}[{}]", array_type.ty.to_slug(), array_type.size),
GType::Struct(struct_type) => format!(
"{{{}}}",
struct_type
.iter()
@ -207,15 +350,17 @@ impl Type {
),
}
}
}
impl ConcreteType {
// the number of field elements the type maps to
pub fn get_primitive_count(&self) -> usize {
match self {
Type::FieldElement => 1,
Type::Boolean => 1,
Type::Uint(_) => 1,
Type::Array(array_type) => array_type.size * array_type.ty.get_primitive_count(),
Type::Struct(struct_type) => struct_type
GType::FieldElement => 1,
GType::Boolean => 1,
GType::Uint(_) => 1,
GType::Array(array_type) => array_type.size * array_type.ty.get_primitive_count(),
GType::Struct(struct_type) => struct_type
.iter()
.map(|member| member.ty.get_primitive_count())
.sum(),
@ -226,25 +371,51 @@ impl Type {
pub type FunctionIdentifier<'ast> = &'ast str;
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub struct FunctionKey<'ast> {
pub struct GFunctionKey<'ast, S> {
pub id: FunctionIdentifier<'ast>,
pub signature: Signature,
pub signature: GSignature<S>,
}
impl<'ast> FunctionKey<'ast> {
pub fn with_id<S: Into<Identifier<'ast>>>(id: S) -> Self {
FunctionKey {
pub type DeclarationFunctionKey<'ast> = GFunctionKey<'ast, Constant<'ast>>;
pub type ConcreteFunctionKey<'ast> = GFunctionKey<'ast, usize>;
pub type FunctionKey<'ast, T> = GFunctionKey<'ast, UExpression<'ast, T>>;
impl<'ast, T> TryFrom<FunctionKey<'ast, T>> for ConcreteFunctionKey<'ast> {
type Error = ();
fn try_from(t: FunctionKey<'ast, T>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast> TryFrom<DeclarationFunctionKey<'ast>> for ConcreteFunctionKey<'ast> {
type Error = ();
fn try_from(t: DeclarationFunctionKey<'ast>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast, T> From<ConcreteFunctionKey<'ast>> for FunctionKey<'ast, T> {
fn from(t: ConcreteFunctionKey<'ast>) -> Self {
unimplemented!()
}
}
impl<'ast, S> GFunctionKey<'ast, S> {
pub fn with_id<U: Into<Identifier<'ast>>>(id: U) -> Self {
GFunctionKey {
id: id.into(),
signature: Signature::new(),
signature: GSignature::new(),
}
}
pub fn signature(mut self, signature: Signature) -> Self {
pub fn signature(mut self, signature: GSignature<S>) -> Self {
self.signature = signature;
self
}
pub fn id<S: Into<Identifier<'ast>>>(mut self, id: S) -> Self {
pub fn id<U: Into<Identifier<'ast>>>(mut self, id: U) -> Self {
self.id = id.into();
self
}
@ -254,19 +425,81 @@ impl<'ast> FunctionKey<'ast> {
}
}
pub use self::signature::Signature;
pub use self::signature::{ConcreteSignature, DeclarationSignature, GSignature, Signature};
pub mod signature {
use super::*;
use std::cmp::Ordering;
use std::fmt;
use std::hash::Hasher;
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Ord, PartialOrd)]
pub struct Signature {
pub inputs: Vec<Type>,
pub outputs: Vec<Type>,
#[derive(Clone, Serialize, Deserialize)]
pub struct GSignature<S> {
pub inputs: Vec<GType<S>>,
pub outputs: Vec<GType<S>>,
}
impl fmt::Debug for Signature {
impl<S> PartialOrd for GSignature<S> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
unimplemented!()
}
}
impl<S> Ord for GSignature<S> {
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
impl<S> PartialEq for GSignature<S> {
fn eq(&self, other: &Self) -> bool {
unimplemented!()
}
}
impl<S> Eq for GSignature<S> {}
impl<S> std::hash::Hash for GSignature<S> {
fn hash<H: Hasher>(&self, state: &mut H) {
unimplemented!()
}
}
pub type DeclarationSignature<'ast> = GSignature<Constant<'ast>>;
pub type ConcreteSignature = GSignature<usize>;
pub type Signature<'ast, T> = GSignature<UExpression<'ast, T>>;
impl<'ast> TryFrom<ConcreteSignature> for DeclarationSignature<'ast> {
type Error = ();
fn try_from(t: ConcreteSignature) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast, T> TryFrom<Signature<'ast, T>> for ConcreteSignature {
type Error = ();
fn try_from(t: Signature<'ast, T>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast> TryFrom<DeclarationSignature<'ast>> for ConcreteSignature {
type Error = ();
fn try_from(t: DeclarationSignature<'ast>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast, T> From<ConcreteSignature> for Signature<'ast, T> {
fn from(t: ConcreteSignature) -> Self {
unimplemented!()
}
}
impl<S> fmt::Debug for GSignature<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
@ -276,7 +509,7 @@ pub mod signature {
}
}
impl fmt::Display for Signature {
impl<S> fmt::Display for GSignature<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(")?;
for (i, t) in self.inputs.iter().enumerate() {
@ -303,7 +536,7 @@ pub mod signature {
}
}
impl Signature {
impl<S> GSignature<S> {
/// Returns a slug for a signature, with the following encoding:
/// i{inputs}o{outputs} where {inputs} and {outputs} each encode a list of types.
/// A list of types is encoded by compressing sequences of the same type like so:
@ -347,19 +580,19 @@ pub mod signature {
format!("i{}o{}", to_slug(&self.inputs), to_slug(&self.outputs))
}
pub fn new() -> Signature {
Signature {
pub fn new() -> GSignature<S> {
Self {
inputs: vec![],
outputs: vec![],
}
}
pub fn inputs(mut self, inputs: Vec<Type>) -> Self {
pub fn inputs(mut self, inputs: Vec<GType<S>>) -> Self {
self.inputs = inputs;
self
}
pub fn outputs(mut self, outputs: Vec<Type>) -> Self {
pub fn outputs(mut self, outputs: Vec<GType<S>>) -> Self {
self.outputs = outputs;
self
}

View file

@ -82,6 +82,12 @@ pub struct UExpression<'ast, T> {
pub inner: UExpressionInner<'ast, T>,
}
impl<'ast, T> From<u32> for UExpression<'ast, T> {
fn from(u: u32) -> Self {
UExpressionInner::Value(u).annotate(UBitwidth::B32)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum UExpressionInner<'ast, T> {
Identifier(Identifier<'ast>),
@ -101,17 +107,14 @@ pub enum UExpressionInner<'ast, T> {
Box<UExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
FunctionCall(FunctionKey<'ast>, Vec<TypedExpression<'ast, T>>),
FunctionCall(FunctionKey<'ast, T>, Vec<TypedExpression<'ast, T>>),
IfElse(
Box<BooleanExpression<'ast, T>>,
Box<UExpression<'ast, T>>,
Box<UExpression<'ast, T>>,
),
Member(Box<StructExpression<'ast, T>>, MemberId),
Select(
Box<ArrayExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Select(Box<ArrayExpression<'ast, T>>, Box<UExpression<'ast, T>>),
}
impl<'ast, T> UExpressionInner<'ast, T> {

View file

@ -1,76 +1,94 @@
use crate::typed_absy::types::Type;
use crate::typed_absy::types::GType;
use crate::typed_absy::Identifier;
use std::fmt;
use typed_absy::types::{StructType, UBitwidth};
use typed_absy::types::{Constant, GStructType, UBitwidth};
use typed_absy::TryFrom;
use typed_absy::UExpression;
#[derive(Clone, PartialEq, Hash, Eq)]
pub struct Variable<'ast> {
pub struct GVariable<'ast, S> {
pub id: Identifier<'ast>,
pub _type: Type,
pub _type: GType<S>,
}
impl<'ast> Variable<'ast> {
pub fn field_element<I: Into<Identifier<'ast>>>(id: I) -> Variable<'ast> {
Self::with_id_and_type(id, Type::FieldElement)
pub type DeclarationVariable<'ast> = GVariable<'ast, Constant<'ast>>;
pub type ConcreteVariable<'ast> = GVariable<'ast, usize>;
pub type Variable<'ast, T> = GVariable<'ast, UExpression<'ast, T>>;
impl<'ast, T> TryFrom<Variable<'ast, T>> for ConcreteVariable<'ast> {
type Error = ();
fn try_from(t: Variable<'ast, T>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast> TryFrom<DeclarationVariable<'ast>> for ConcreteVariable<'ast> {
type Error = ();
fn try_from(t: DeclarationVariable<'ast>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<'ast, T> From<ConcreteVariable<'ast>> for Variable<'ast, T> {
fn from(t: ConcreteVariable<'ast>) -> Self {
unimplemented!()
}
}
impl<'ast, T> From<DeclarationVariable<'ast>> for Variable<'ast, T> {
fn from(t: DeclarationVariable<'ast>) -> Self {
unimplemented!()
}
}
impl<'ast, S> GVariable<'ast, S> {
pub fn field_element<I: Into<Identifier<'ast>>>(id: I) -> Self {
Self::with_id_and_type(id, GType::FieldElement)
}
pub fn boolean<I: Into<Identifier<'ast>>>(id: I) -> Variable<'ast> {
Self::with_id_and_type(id, Type::Boolean)
pub fn boolean<I: Into<Identifier<'ast>>>(id: I) -> Self {
Self::with_id_and_type(id, GType::Boolean)
}
pub fn uint<I: Into<Identifier<'ast>>, W: Into<UBitwidth>>(
id: I,
bitwidth: W,
) -> Variable<'ast> {
Self::with_id_and_type(id, Type::uint(bitwidth))
pub fn uint<I: Into<Identifier<'ast>>, W: Into<UBitwidth>>(id: I, bitwidth: W) -> Self {
Self::with_id_and_type(id, GType::uint(bitwidth))
}
#[cfg(test)]
pub fn field_array<I: Into<Identifier<'ast>>>(id: I, size: usize) -> Variable<'ast> {
Self::array(id, Type::FieldElement, size)
pub fn field_array<I: Into<Identifier<'ast>>>(id: I, size: S) -> Self {
Self::array(id, GType::FieldElement, size)
}
pub fn array<I: Into<Identifier<'ast>>>(id: I, ty: Type, size: usize) -> Variable<'ast> {
Self::with_id_and_type(id, Type::array(ty, size))
pub fn array<I: Into<Identifier<'ast>>>(id: I, ty: GType<S>, size: S) -> Self {
Self::with_id_and_type(id, GType::array(ty, size))
}
pub fn struc<I: Into<Identifier<'ast>>>(id: I, ty: StructType) -> Variable<'ast> {
Self::with_id_and_type(id, Type::Struct(ty))
pub fn struc<I: Into<Identifier<'ast>>>(id: I, ty: GStructType<S>) -> Self {
Self::with_id_and_type(id, GType::Struct(ty))
}
pub fn with_id_and_type<I: Into<Identifier<'ast>>>(id: I, _type: Type) -> Variable<'ast> {
Variable {
pub fn with_id_and_type<I: Into<Identifier<'ast>>>(id: I, _type: GType<S>) -> Self {
GVariable {
id: id.into(),
_type,
}
}
pub fn get_type(&self) -> Type {
pub fn get_type(&self) -> GType<S> {
self._type.clone()
}
}
impl<'ast> fmt::Display for Variable<'ast> {
impl<'ast, S> fmt::Display for GVariable<'ast, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", self._type, self.id,)
}
}
impl<'ast> fmt::Debug for Variable<'ast> {
impl<'ast, S> fmt::Debug for GVariable<'ast, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Variable(type: {:?}, id: {:?})", self._type, self.id,)
}
}
// impl<'ast> From<absy::Variable<'ast>> for Variable<'ast> {
// fn from(v: absy::Variable) -> Variable {
// Variable::with_id_and_type(
// Identifier {
// id: v.id,
// version: 0,
// stack: vec![],
// },
// v._type,
// )
// }
// }

View file

@ -1,16 +1,16 @@
use typed_absy;
use zir;
impl<'ast> From<typed_absy::types::FunctionKey<'ast>> for zir::types::FunctionKey<'ast> {
fn from(k: typed_absy::types::FunctionKey<'ast>) -> zir::types::FunctionKey<'ast> {
impl<'ast> From<typed_absy::types::ConcreteFunctionKey<'ast>> for zir::types::FunctionKey<'ast> {
fn from(k: typed_absy::types::ConcreteFunctionKey<'ast>) -> zir::types::FunctionKey<'ast> {
zir::types::FunctionKey {
id: k.id,
signature: k.signature.into(),
}
}
}
impl From<typed_absy::types::Signature> for zir::types::Signature {
fn from(s: typed_absy::types::Signature) -> zir::types::Signature {
impl From<typed_absy::types::ConcreteSignature> for zir::types::Signature {
fn from(s: typed_absy::types::ConcreteSignature) -> zir::types::Signature {
zir::types::Signature {
inputs: s.inputs.into_iter().flat_map(|t| from_type(t)).collect(),
outputs: s.outputs.into_iter().flat_map(|t| from_type(t)).collect(),
@ -18,16 +18,18 @@ impl From<typed_absy::types::Signature> for zir::types::Signature {
}
}
fn from_type(t: typed_absy::types::Type) -> Vec<zir::types::Type> {
fn from_type(t: typed_absy::types::ConcreteType) -> Vec<zir::types::Type> {
match t {
typed_absy::Type::FieldElement => vec![zir::Type::FieldElement],
typed_absy::Type::Boolean => vec![zir::Type::Boolean],
typed_absy::Type::Uint(bitwidth) => vec![zir::Type::uint(bitwidth.to_usize())],
typed_absy::Type::Array(array_type) => {
typed_absy::types::ConcreteType::FieldElement => vec![zir::Type::FieldElement],
typed_absy::types::ConcreteType::Boolean => vec![zir::Type::Boolean],
typed_absy::types::ConcreteType::Uint(bitwidth) => {
vec![zir::Type::uint(bitwidth.to_usize())]
}
typed_absy::types::ConcreteType::Array(array_type) => {
let inner = from_type(*array_type.ty);
(0..array_type.size).flat_map(|_| inner.clone()).collect()
}
typed_absy::Type::Struct(members) => members
typed_absy::types::ConcreteType::Struct(members) => members
.into_iter()
.flat_map(|struct_member| from_type(*struct_member.ty))
.collect(),

View file

@ -14,7 +14,7 @@ pub use zir::uint::{ShouldReduce, UExpression, UExpressionInner, UMetadata};
use embed::FlatEmbed;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::convert::{TryFrom, TryInto};
use std::fmt;
use zir::types::{FunctionKey, Signature};
use zokrates_field::Field;
@ -90,7 +90,7 @@ impl<'ast, T> ZirFunctionSymbol<'ast, T> {
.unwrap()
.signature(&modules)
.clone(),
ZirFunctionSymbol::Flat(flat_fun) => flat_fun.signature().into(),
ZirFunctionSymbol::Flat(flat_fun) => flat_fun.signature().try_into().unwrap(),
}
}
}

View file

@ -35,6 +35,8 @@ pub trait Field:
+ Ord
+ Display
+ Debug
+ Default
+ Hash
+ Add<Self, Output = Self>
+ for<'a> Add<&'a Self, Output = Self>
+ Sub<Self, Output = Self>