1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

merge dev

This commit is contained in:
schaeff 2020-06-05 14:09:53 +02:00
commit e2b2fd86d6
19 changed files with 590 additions and 319 deletions

View file

@ -404,7 +404,7 @@ mod tests {
mod strict { mod strict {
use super::*; use super::*;
use zokrates_core::typed_absy::types::StructMember; use zokrates_core::typed_absy::types::{StructMember, StructType};
#[test] #[test]
fn fields() { fn fields() {
@ -449,10 +449,11 @@ mod tests {
assert_eq!( assert_eq!(
parse_strict::<Bn128Field>( parse_strict::<Bn128Field>(
s, s,
vec![Type::Struct(vec![StructMember::new( vec![Type::Struct(StructType::new(
"a".into(), "".into(),
Type::FieldElement "".into(),
)])] vec![StructMember::new("a".into(), Type::FieldElement)]
))]
) )
.unwrap(), .unwrap(),
CheckedValues(vec![CheckedValue::Struct( CheckedValues(vec![CheckedValue::Struct(
@ -466,10 +467,11 @@ mod tests {
assert_eq!( assert_eq!(
parse_strict::<Bn128Field>( parse_strict::<Bn128Field>(
s, s,
vec![Type::Struct(vec![StructMember::new( vec![Type::Struct(StructType::new(
"a".into(), "".into(),
Type::FieldElement "".into(),
)])] vec![StructMember::new("a".into(), Type::FieldElement)]
))]
) )
.unwrap_err(), .unwrap_err(),
Error::Type("Member with id `a` not found".into()) Error::Type("Member with id `a` not found".into())
@ -479,10 +481,11 @@ mod tests {
assert_eq!( assert_eq!(
parse_strict::<Bn128Field>( parse_strict::<Bn128Field>(
s, s,
vec![Type::Struct(vec![StructMember::new( vec![Type::Struct(StructType::new(
"a".into(), "".into(),
Type::FieldElement "".into(),
)])] vec![StructMember::new("a".into(), Type::FieldElement)]
))]
) )
.unwrap_err(), .unwrap_err(),
Error::Type("Expected 1 member(s), found 0".into()) Error::Type("Expected 1 member(s), found 0".into())
@ -492,10 +495,11 @@ mod tests {
assert_eq!( assert_eq!(
parse_strict::<Bn128Field>( parse_strict::<Bn128Field>(
s, s,
vec![Type::Struct(vec![StructMember::new( vec![Type::Struct(StructType::new(
"a".into(), "".into(),
Type::FieldElement "".into(),
)])] vec![StructMember::new("a".into(), Type::FieldElement)]
))]
) )
.unwrap_err(), .unwrap_err(),
Error::Type("Value `false` doesn't match expected type `field`".into()) Error::Type("Value `false` doesn't match expected type `field`".into())

View file

@ -5,17 +5,7 @@ In order to interact programatically with compiled ZoKrates programs, ZoKrates s
To illustrate this, we'll use the following example program: To illustrate this, we'll use the following example program:
``` ```
struct Bar { {{#include ../../../zokrates_cli/examples/book/abi.zok}}
field a
}
struct Foo {
field a
Bar b
}
def main(private Foo foo, bool[2] bar, field num) -> (field):
return 42
``` ```
## ABI specification ## ABI specification
@ -26,48 +16,54 @@ In this example, the ABI specification is:
```json ```json
{ {
"inputs": [ "inputs":[
{ {
"name": "foo", "name":"foo",
"public": false, "public":true,
"type": "struct", "type":"struct",
"components": [ "components":{
{ "name":"Foo",
"name": "a", "members":[
"type": "field" {
}, "name":"a",
{ "type":"field"
"name": "b", },
"type": "struct", {
"components": [ "name":"b",
"type":"struct",
"components":{
"name":"Bar",
"members":[
{ {
"name": "a", "name":"a",
"type": "field" "type":"field"
} }
] ]
} }
}
] ]
}, }
{ },
"name": "bar", {
"public": "true", "name":"bar",
"type": "array", "public":true,
"components": { "type":"array",
"size": 2, "components":{
"type": "bool" "size":2,
} "type":"bool"
}, }
{ },
"name": "num", {
"public": "true", "name":"num",
"type": "field" "public":true,
} "type":"field"
], }
"outputs": [ ],
{ "outputs":[
"type": "field" {
} "type":"field"
] }
]
} }
``` ```
@ -78,19 +74,20 @@ When executing a program, arguments can be passed as a JSON object of the follow
```json ```json
[ [
{ {
"a": "42", "a":"42",
"b": "b":{
{ "a":"42"
"a": "42" }
} },
}, [
[ true,
true, false
false ],
], "42"
"42"
] ]
``` ```
Note that field elements are passed as JSON strings in order to support arbitrary large numbers. Note the following:
- Field elements are passed as JSON strings in order to support arbitrary large numbers.
- Structs are passed as JSON objects, ignoring the struct name

View file

@ -0,0 +1,11 @@
struct Bar {
field a
}
struct Foo {
field a
Bar b
}
def main(Foo foo, bool[2] bar, field num) -> (field):
return 42

View file

@ -0,0 +1,5 @@
struct Foo {}
struct Bar {}
def main() -> (Foo):
return Bar {}

View file

@ -33,7 +33,12 @@ impl<'ast> From<pest::ImportDirective<'ast>> for absy::ImportNode<'ast> {
Some(import.symbol.span.as_str()), Some(import.symbol.span.as_str()),
std::path::Path::new(import.source.span.as_str()), std::path::Path::new(import.source.span.as_str()),
) )
.alias(import.alias.map(|a| a.span.as_str())) .alias(
import
.alias
.map(|a| a.span.as_str())
.or(Some(import.symbol.span.as_str())),
)
.span(import.span), .span(import.span),
} }
} }
@ -47,11 +52,11 @@ impl<'ast, T: Field> From<pest::StructDefinition<'ast>> for absy::SymbolDeclarat
let id = definition.id.span.as_str(); let id = definition.id.span.as_str();
let ty = absy::StructType { let ty = absy::StructDefinition {
fields: definition fields: definition
.fields .fields
.into_iter() .into_iter()
.map(|f| absy::StructFieldNode::from(f)) .map(|f| absy::StructDefinitionFieldNode::from(f))
.collect(), .collect(),
} }
.span(span.clone()); .span(span.clone());
@ -64,8 +69,8 @@ impl<'ast, T: Field> From<pest::StructDefinition<'ast>> for absy::SymbolDeclarat
} }
} }
impl<'ast> From<pest::StructField<'ast>> for absy::StructFieldNode<'ast> { impl<'ast> From<pest::StructField<'ast>> for absy::StructDefinitionFieldNode<'ast> {
fn from(field: pest::StructField<'ast>) -> absy::StructFieldNode { fn from(field: pest::StructField<'ast>) -> absy::StructDefinitionFieldNode {
use absy::NodeValue; use absy::NodeValue;
let span = field.span; let span = field.span;
@ -74,7 +79,7 @@ impl<'ast> From<pest::StructField<'ast>> for absy::StructFieldNode<'ast> {
let ty = absy::UnresolvedTypeNode::from(field.ty); let ty = absy::UnresolvedTypeNode::from(field.ty);
absy::StructField { id, ty }.span(span) absy::StructDefinitionField { id, ty }.span(span)
} }
} }

View file

@ -51,7 +51,7 @@ pub struct SymbolDeclaration<'ast, T> {
#[derive(PartialEq, Clone)] #[derive(PartialEq, Clone)]
pub enum Symbol<'ast, T> { pub enum Symbol<'ast, T> {
HereType(StructTypeNode<'ast>), HereType(StructDefinitionNode<'ast>),
HereFunction(FunctionNode<'ast, T>), HereFunction(FunctionNode<'ast, T>),
There(SymbolImportNode<'ast>), There(SymbolImportNode<'ast>),
Flat(FlatEmbed), Flat(FlatEmbed),
@ -109,11 +109,11 @@ pub type UnresolvedTypeNode = Node<UnresolvedType>;
/// A struct type definition /// A struct type definition
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct StructType<'ast> { pub struct StructDefinition<'ast> {
pub fields: Vec<StructFieldNode<'ast>>, pub fields: Vec<StructDefinitionFieldNode<'ast>>,
} }
impl<'ast> fmt::Display for StructType<'ast> { impl<'ast> fmt::Display for StructDefinition<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
f, f,
@ -127,22 +127,22 @@ impl<'ast> fmt::Display for StructType<'ast> {
} }
} }
pub type StructTypeNode<'ast> = Node<StructType<'ast>>; pub type StructDefinitionNode<'ast> = Node<StructDefinition<'ast>>;
/// A struct type definition /// A struct type definition
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct StructField<'ast> { pub struct StructDefinitionField<'ast> {
pub id: Identifier<'ast>, pub id: Identifier<'ast>,
pub ty: UnresolvedTypeNode, pub ty: UnresolvedTypeNode,
} }
impl<'ast> fmt::Display for StructField<'ast> { impl<'ast> fmt::Display for StructDefinitionField<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {},", self.id, self.ty) write!(f, "{}: {},", self.id, self.ty)
} }
} }
type StructFieldNode<'ast> = Node<StructField<'ast>>; type StructDefinitionFieldNode<'ast> = Node<StructDefinitionField<'ast>>;
/// An import /// An import
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]

View file

@ -82,8 +82,8 @@ impl<'ast, T: fmt::Display + fmt::Debug + PartialEq> NodeValue for Assignee<'ast
impl<'ast, T: fmt::Display + fmt::Debug + PartialEq> NodeValue for Statement<'ast, T> {} impl<'ast, T: fmt::Display + fmt::Debug + PartialEq> NodeValue for Statement<'ast, T> {}
impl<'ast, T: Field> NodeValue for SymbolDeclaration<'ast, T> {} impl<'ast, T: Field> NodeValue for SymbolDeclaration<'ast, T> {}
impl NodeValue for UnresolvedType {} impl NodeValue for UnresolvedType {}
impl<'ast> NodeValue for StructType<'ast> {} impl<'ast> NodeValue for StructDefinition<'ast> {}
impl<'ast> NodeValue for StructField<'ast> {} impl<'ast> NodeValue for StructDefinitionField<'ast> {}
impl<'ast, T: fmt::Display + fmt::Debug + PartialEq> NodeValue for Function<'ast, T> {} impl<'ast, T: fmt::Display + fmt::Debug + PartialEq> NodeValue for Function<'ast, T> {}
impl<'ast, T: Field> NodeValue for Module<'ast, T> {} impl<'ast, T: Field> NodeValue for Module<'ast, T> {}
impl<'ast> NodeValue for SymbolImport<'ast> {} impl<'ast> NodeValue for SymbolImport<'ast> {}

View file

@ -285,4 +285,111 @@ mod test {
); );
assert!(res.is_ok()); assert!(res.is_ok());
} }
mod abi {
use super::*;
use typed_absy::abi::*;
use typed_absy::types::*;
#[test]
fn use_struct_declaration_types() {
// when importing types and renaming them, we use the top-most renaming in the ABI
// // main.zok
// from foo import Foo as FooMain
//
// // foo.zok
// from bar import Bar as BarFoo
// struct Foo { BarFoo b }
//
// // bar.zok
// struct Bar { field a }
// Expected resolved type for FooMain:
// FooMain { BarFoo b }
let main = r#"
from "foo" import Foo as FooMain
def main(FooMain f) -> ():
return
"#;
struct CustomResolver;
impl<E> Resolver<E> for CustomResolver {
fn resolve(
&self,
_: PathBuf,
import_location: PathBuf,
) -> Result<(String, PathBuf), E> {
let loc = import_location.display().to_string();
if loc == "main" {
Ok((
r#"
from "foo" import Foo as FooMain
def main(FooMain f) -> ():
return
"#
.into(),
"main".into(),
))
} else if loc == "foo" {
Ok((
r#"
from "bar" import Bar as BarFoo
struct Foo {
BarFoo b
}
"#
.into(),
"foo".into(),
))
} else if loc == "bar" {
Ok((
r#"
struct Bar { field a }
"#
.into(),
"bar".into(),
))
} else {
unreachable!()
}
}
}
let artifacts = compile::<Bn128Field, io::Error>(
main.to_string(),
"main".into(),
Some(&CustomResolver),
)
.unwrap();
assert_eq!(
artifacts.abi,
Abi {
inputs: vec![AbiInput {
name: "f".into(),
public: true,
ty: Type::Struct(StructType {
module: "main".into(),
name: "FooMain".into(),
members: vec![StructMember {
id: "b".into(),
ty: box Type::Struct(StructType {
module: "foo".into(),
name: "BarFoo".into(),
members: vec![StructMember {
id: "a".into(),
ty: box Type::FieldElement
}]
})
}]
})
}],
outputs: vec![]
}
);
}
}
} }

View file

@ -268,7 +268,8 @@ impl<'ast> Checker<'ast> {
fn check_struct_type_declaration( fn check_struct_type_declaration(
&mut self, &mut self,
s: StructTypeNode<'ast>, id: String,
s: StructDefinitionNode<'ast>,
module_id: &ModuleId, module_id: &ModuleId,
types: &TypeMap, types: &TypeMap,
) -> Result<Type, Vec<ErrorInner>> { ) -> Result<Type, Vec<ErrorInner>> {
@ -302,12 +303,14 @@ impl<'ast> Checker<'ast> {
return Err(errors); return Err(errors);
} }
Ok(Type::Struct( Ok(Type::Struct(StructType::new(
module_id.into(),
id,
fields fields
.iter() .iter()
.map(|f| StructMember::new(f.0.clone(), f.1.clone())) .map(|f| StructMember::new(f.0.clone(), f.1.clone()))
.collect(), .collect(),
)) )))
} }
fn check_symbol_declaration<T: Field>( fn check_symbol_declaration<T: Field>(
@ -323,9 +326,14 @@ impl<'ast> Checker<'ast> {
let pos = declaration.pos(); let pos = declaration.pos();
let declaration = declaration.value; let declaration = declaration.value;
match declaration.symbol { match declaration.symbol.clone() {
Symbol::HereType(t) => { Symbol::HereType(t) => {
match self.check_struct_type_declaration(t.clone(), module_id, &state.types) { match self.check_struct_type_declaration(
declaration.id.to_string(),
t.clone(),
module_id,
&state.types,
) {
Ok(ty) => { Ok(ty) => {
match symbol_unifier.insert_type(declaration.id) { match symbol_unifier.insert_type(declaration.id) {
false => errors.push( false => errors.push(
@ -412,6 +420,17 @@ impl<'ast> Checker<'ast> {
match (function_candidates.len(), type_candidate) { match (function_candidates.len(), type_candidate) {
(0, Some(t)) => { (0, Some(t)) => {
// rename the type to the declared symbol
let t = match t {
Type::Struct(t) => Type::Struct(StructType {
module: module_id.clone(),
name: declaration.id.into(),
..t
}),
_ => unreachable!()
};
// we imported a type, so the symbol it gets bound to should not already exist // we imported a type, so the symbol it gets bound to should not already exist
match symbol_unifier.insert_type(declaration.id) { match symbol_unifier.insert_type(declaration.id) {
false => { false => {
@ -431,7 +450,7 @@ impl<'ast> Checker<'ast> {
.types .types
.entry(module_id.clone()) .entry(module_id.clone())
.or_default() .or_default()
.insert(import.symbol_id.to_string(), t.clone()); .insert(declaration.id.to_string(), t.clone());
} }
(0, None) => { (0, None) => {
errors.push(ErrorInner { errors.push(ErrorInner {
@ -1359,12 +1378,8 @@ impl<'ast> Checker<'ast> {
Ok(ArrayExpressionInner::IfElse(box condition, box consequence, box alternative).annotate(inner_type, size).into()) Ok(ArrayExpressionInner::IfElse(box condition, box consequence, box alternative).annotate(inner_type, size).into())
}, },
(TypedExpression::Struct(consequence), TypedExpression::Struct(alternative)) => { (TypedExpression::Struct(consequence), TypedExpression::Struct(alternative)) => {
if consequence.get_type() == alternative.get_type() { let ty = consequence.ty().clone();
let ty = consequence.ty().clone(); Ok(StructExpressionInner::IfElse(box condition, box consequence, box alternative).annotate(ty).into())
Ok(StructExpressionInner::IfElse(box condition, box consequence, box alternative).annotate(ty).into())
} else {
unimplemented!("handle consequence alternative inner type mismatch")
}
}, },
(TypedExpression::Uint(consequence), TypedExpression::Uint(alternative)) => { (TypedExpression::Uint(consequence), TypedExpression::Uint(alternative)) => {
let bitwidth = consequence.bitwidth(); let bitwidth = consequence.bitwidth();
@ -1937,21 +1952,20 @@ impl<'ast> Checker<'ast> {
module_id, module_id,
&types, &types,
)?; )?;
let members = match ty { let struct_type = match ty {
Type::Struct(members) => members, Type::Struct(struct_type) => struct_type,
_ => unreachable!(), _ => unreachable!(),
}; };
// check that we provided the required number of values // check that we provided the required number of values
if members.len() != inline_members.len() { if struct_type.len() != inline_members.len() {
return Err(ErrorInner { return Err(ErrorInner {
pos: Some(pos), pos: Some(pos),
message: format!( message: format!(
"Inline struct {} does not match {} : {}", "Inline struct {} does not match {}",
Expression::InlineStruct(id.clone(), inline_members), Expression::InlineStruct(id.clone(), inline_members),
id, Type::Struct(struct_type)
Type::Struct(members)
), ),
}); });
} }
@ -1966,7 +1980,7 @@ impl<'ast> Checker<'ast> {
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
let mut result: Vec<TypedExpression<'ast, T>> = vec![]; let mut result: Vec<TypedExpression<'ast, T>> = vec![];
for member in &members { for member in struct_type.iter() {
match inline_members_map.remove(member.id.as_str()) { match inline_members_map.remove(member.id.as_str()) {
Some(value) => { Some(value) => {
let expression_checked = let expression_checked =
@ -1992,10 +2006,9 @@ impl<'ast> Checker<'ast> {
return Err(ErrorInner { return Err(ErrorInner {
pos: Some(pos), pos: Some(pos),
message: format!( message: format!(
"Member {} of struct {} : {} not found in value {}", "Member {} of struct {} not found in value {}",
member.id, member.id,
id.clone(), Type::Struct(struct_type.clone()),
Type::Struct(members.clone()),
Expression::InlineStruct(id.clone(), inline_members), Expression::InlineStruct(id.clone(), inline_members),
), ),
}) })
@ -2004,7 +2017,7 @@ impl<'ast> Checker<'ast> {
} }
Ok(StructExpressionInner::Value(result) Ok(StructExpressionInner::Value(result)
.annotate(members) .annotate(struct_type)
.into()) .into())
} }
Expression::And(box e1, box e2) => { Expression::And(box e1, box e2) => {
@ -2320,13 +2333,13 @@ mod tests {
.mock() .mock()
} }
fn struct0() -> StructTypeNode<'static> { fn struct0() -> StructDefinitionNode<'static> {
StructType { fields: vec![] }.mock() StructDefinition { fields: vec![] }.mock()
} }
fn struct1() -> StructTypeNode<'static> { fn struct1() -> StructDefinitionNode<'static> {
StructType { StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo".into(), id: "foo".into(),
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
@ -2554,7 +2567,7 @@ mod tests {
.mock(), .mock(),
SymbolDeclaration { SymbolDeclaration {
id: "foo", id: "foo",
symbol: Symbol::HereType(StructType { fields: vec![] }.mock()), symbol: Symbol::HereType(StructDefinition { fields: vec![] }.mock()),
} }
.mock(), .mock(),
], ],
@ -3855,7 +3868,7 @@ mod tests {
/// solver function to create a module at location "" with a single symbol `Foo { foo: field }` /// solver function to create a module at location "" with a single symbol `Foo { foo: field }`
fn create_module_with_foo( fn create_module_with_foo(
s: StructType<'static>, s: StructDefinition<'static>,
) -> (Checker<'static>, State<'static, Bn128Field>) { ) -> (Checker<'static>, State<'static, Bn128Field>) {
let module_id: PathBuf = "".into(); let module_id: PathBuf = "".into();
@ -3886,12 +3899,17 @@ mod tests {
// an empty struct should be allowed to be defined // an empty struct should be allowed to be defined
let module_id = "".into(); let module_id = "".into();
let types = HashMap::new(); let types = HashMap::new();
let declaration = StructType { fields: vec![] }.mock(); let declaration = StructDefinition { fields: vec![] }.mock();
let expected_type = Type::Struct(vec![]); let expected_type = Type::Struct(StructType::new("".into(), "Foo".into(), vec![]));
assert_eq!( assert_eq!(
Checker::new().check_struct_type_declaration(declaration, &module_id, &types), Checker::new().check_struct_type_declaration(
"Foo".into(),
declaration,
&module_id,
&types
),
Ok(expected_type) Ok(expected_type)
); );
} }
@ -3901,14 +3919,14 @@ mod tests {
// a valid struct should be allowed to be defined // a valid struct should be allowed to be defined
let module_id = "".into(); let module_id = "".into();
let types = HashMap::new(); let types = HashMap::new();
let declaration = StructType { let declaration = StructDefinition {
fields: vec![ fields: vec![
StructField { StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
.mock(), .mock(),
StructField { StructDefinitionField {
id: "bar", id: "bar",
ty: UnresolvedType::Boolean.mock(), ty: UnresolvedType::Boolean.mock(),
} }
@ -3917,13 +3935,22 @@ mod tests {
} }
.mock(); .mock();
let expected_type = Type::Struct(vec![ let expected_type = Type::Struct(StructType::new(
StructMember::new("foo".into(), Type::FieldElement), "".into(),
StructMember::new("bar".into(), Type::Boolean), "Foo".into(),
]); vec![
StructMember::new("foo".into(), Type::FieldElement),
StructMember::new("bar".into(), Type::Boolean),
],
));
assert_eq!( assert_eq!(
Checker::new().check_struct_type_declaration(declaration, &module_id, &types), Checker::new().check_struct_type_declaration(
"Foo".into(),
declaration,
&module_id,
&types
),
Ok(expected_type) Ok(expected_type)
); );
} }
@ -3934,14 +3961,14 @@ mod tests {
let module_id = "".into(); let module_id = "".into();
let types = HashMap::new(); let types = HashMap::new();
let declaration0 = StructType { let declaration0 = StructDefinition {
fields: vec![ fields: vec![
StructField { StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
.mock(), .mock(),
StructField { StructDefinitionField {
id: "bar", id: "bar",
ty: UnresolvedType::Boolean.mock(), ty: UnresolvedType::Boolean.mock(),
} }
@ -3950,14 +3977,14 @@ mod tests {
} }
.mock(); .mock();
let declaration1 = StructType { let declaration1 = StructDefinition {
fields: vec![ fields: vec![
StructField { StructDefinitionField {
id: "bar", id: "bar",
ty: UnresolvedType::Boolean.mock(), ty: UnresolvedType::Boolean.mock(),
} }
.mock(), .mock(),
StructField { StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
@ -3967,8 +3994,18 @@ mod tests {
.mock(); .mock();
assert_ne!( assert_ne!(
Checker::new().check_struct_type_declaration(declaration0, &module_id, &types), Checker::new().check_struct_type_declaration(
Checker::new().check_struct_type_declaration(declaration1, &module_id, &types) "Foo".into(),
declaration0,
&module_id,
&types
),
Checker::new().check_struct_type_declaration(
"Foo".into(),
declaration1,
&module_id,
&types
)
); );
} }
@ -3978,14 +4015,14 @@ mod tests {
let module_id = "".into(); let module_id = "".into();
let types = HashMap::new(); let types = HashMap::new();
let declaration = StructType { let declaration = StructDefinition {
fields: vec![ fields: vec![
StructField { StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
.mock(), .mock(),
StructField { StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::Boolean.mock(), ty: UnresolvedType::Boolean.mock(),
} }
@ -3996,7 +4033,12 @@ mod tests {
assert_eq!( assert_eq!(
Checker::new() Checker::new()
.check_struct_type_declaration(declaration, &module_id, &types) .check_struct_type_declaration(
"Foo".into(),
declaration,
&module_id,
&types
)
.unwrap_err()[0] .unwrap_err()[0]
.message, .message,
"Duplicate key foo in struct definition" "Duplicate key foo in struct definition"
@ -4018,8 +4060,8 @@ mod tests {
SymbolDeclaration { SymbolDeclaration {
id: "Foo", id: "Foo",
symbol: Symbol::HereType( symbol: Symbol::HereType(
StructType { StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
@ -4032,8 +4074,8 @@ mod tests {
SymbolDeclaration { SymbolDeclaration {
id: "Bar", id: "Bar",
symbol: Symbol::HereType( symbol: Symbol::HereType(
StructType { StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::User("Foo".into()).mock(), ty: UnresolvedType::User("Foo".into()).mock(),
} }
@ -4056,10 +4098,18 @@ mod tests {
.unwrap() .unwrap()
.get(&"Bar".to_string()) .get(&"Bar".to_string())
.unwrap(), .unwrap(),
&Type::Struct(vec![StructMember::new( &Type::Struct(StructType::new(
"foo".into(), module_id.clone(),
Type::Struct(vec![StructMember::new("foo".into(), Type::FieldElement)]) "Bar".into(),
)]) vec![StructMember::new(
"foo".into(),
Type::Struct(StructType::new(
module_id,
"Foo".into(),
vec![StructMember::new("foo".into(), Type::FieldElement)]
))
)]
))
); );
} }
@ -4076,8 +4126,8 @@ mod tests {
symbols: vec![SymbolDeclaration { symbols: vec![SymbolDeclaration {
id: "Bar", id: "Bar",
symbol: Symbol::HereType( symbol: Symbol::HereType(
StructType { StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::User("Foo".into()).mock(), ty: UnresolvedType::User("Foo".into()).mock(),
} }
@ -4107,8 +4157,8 @@ mod tests {
symbols: vec![SymbolDeclaration { symbols: vec![SymbolDeclaration {
id: "Foo", id: "Foo",
symbol: Symbol::HereType( symbol: Symbol::HereType(
StructType { StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::User("Foo".into()).mock(), ty: UnresolvedType::User("Foo".into()).mock(),
} }
@ -4140,8 +4190,8 @@ mod tests {
SymbolDeclaration { SymbolDeclaration {
id: "Foo", id: "Foo",
symbol: Symbol::HereType( symbol: Symbol::HereType(
StructType { StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "bar", id: "bar",
ty: UnresolvedType::User("Bar".into()).mock(), ty: UnresolvedType::User("Bar".into()).mock(),
} }
@ -4154,8 +4204,8 @@ mod tests {
SymbolDeclaration { SymbolDeclaration {
id: "Bar", id: "Bar",
symbol: Symbol::HereType( symbol: Symbol::HereType(
StructType { StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::User("Foo".into()).mock(), ty: UnresolvedType::User("Foo".into()).mock(),
} }
@ -4187,8 +4237,8 @@ mod tests {
// an undefined type cannot be checked // an undefined type cannot be checked
// Bar // Bar
let (checker, state) = create_module_with_foo(StructType { let (checker, state) = create_module_with_foo(StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
@ -4201,10 +4251,11 @@ mod tests {
&PathBuf::from(MODULE_ID).into(), &PathBuf::from(MODULE_ID).into(),
&state.types &state.types
), ),
Ok(Type::Struct(vec![StructMember::new( Ok(Type::Struct(StructType::new(
"foo".into(), "".into(),
Type::FieldElement "Foo".into(),
)])) vec![StructMember::new("foo".into(), Type::FieldElement)]
)))
); );
assert_eq!( assert_eq!(
@ -4226,8 +4277,8 @@ mod tests {
// an undefined type cannot be used as parameter // an undefined type cannot be used as parameter
let (checker, state) = create_module_with_foo(StructType { let (checker, state) = create_module_with_foo(StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
@ -4249,10 +4300,11 @@ mod tests {
Ok(Parameter { Ok(Parameter {
id: Variable::with_id_and_type( id: Variable::with_id_and_type(
"a", "a",
Type::Struct(vec![StructMember::new( Type::Struct(StructType::new(
"foo".to_string(), "".into(),
Type::FieldElement "Foo".into(),
)]) vec![StructMember::new("foo".into(), Type::FieldElement)]
))
), ),
private: true private: true
}) })
@ -4285,8 +4337,8 @@ mod tests {
// an undefined type cannot be used in a variable declaration // an undefined type cannot be used in a variable declaration
let (mut checker, state) = create_module_with_foo(StructType { let (mut checker, state) = create_module_with_foo(StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
@ -4305,10 +4357,11 @@ mod tests {
), ),
Ok(TypedStatement::Declaration(Variable::with_id_and_type( Ok(TypedStatement::Declaration(Variable::with_id_and_type(
"a", "a",
Type::Struct(vec![StructMember::new( Type::Struct(StructType::new(
"foo".to_string(), "".into(),
Type::FieldElement "Foo".into(),
)]) vec![StructMember::new("foo".into(), Type::FieldElement)]
))
))) )))
); );
@ -4345,8 +4398,8 @@ mod tests {
// struct Foo = { foo: field } // struct Foo = { foo: field }
// Foo { foo: 42 }.foo // Foo { foo: 42 }.foo
let (mut checker, state) = create_module_with_foo(StructType { let (mut checker, state) = create_module_with_foo(StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
@ -4375,7 +4428,11 @@ mod tests {
Bn128Field::from(42) Bn128Field::from(42)
) )
.into()]) .into()])
.annotate(vec![StructMember::new("foo".into(), Type::FieldElement)]), .annotate(StructType::new(
"".into(),
"Foo".into(),
vec![StructMember::new("foo".into(), Type::FieldElement)]
)),
"foo".into() "foo".into()
) )
.into()) .into())
@ -4389,8 +4446,8 @@ mod tests {
// struct Foo = { foo: field } // struct Foo = { foo: field }
// Foo { foo: 42 }.bar // Foo { foo: 42 }.bar
let (mut checker, state) = create_module_with_foo(StructType { let (mut checker, state) = create_module_with_foo(StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
@ -4417,7 +4474,7 @@ mod tests {
) )
.unwrap_err() .unwrap_err()
.message, .message,
"{foo: field} doesn\'t have member bar" "Foo {foo: field} doesn\'t have member bar"
); );
} }
} }
@ -4430,8 +4487,8 @@ mod tests {
fn wrong_name() { fn wrong_name() {
// a A value cannot be defined with B as id, even if A and B have the same members // a A value cannot be defined with B as id, even if A and B have the same members
let (mut checker, state) = create_module_with_foo(StructType { let (mut checker, state) = create_module_with_foo(StructDefinition {
fields: vec![StructField { fields: vec![StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
@ -4465,14 +4522,14 @@ mod tests {
// struct Foo = { foo: field, bar: bool } // struct Foo = { foo: field, bar: bool }
// Foo foo = Foo { foo: 42, bar: true } // Foo foo = Foo { foo: 42, bar: true }
let (mut checker, state) = create_module_with_foo(StructType { let (mut checker, state) = create_module_with_foo(StructDefinition {
fields: vec![ fields: vec![
StructField { StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
.mock(), .mock(),
StructField { StructDefinitionField {
id: "bar", id: "bar",
ty: UnresolvedType::Boolean.mock(), ty: UnresolvedType::Boolean.mock(),
} }
@ -4500,10 +4557,14 @@ mod tests {
FieldElementExpression::Number(Bn128Field::from(42)).into(), FieldElementExpression::Number(Bn128Field::from(42)).into(),
BooleanExpression::Value(true).into() BooleanExpression::Value(true).into()
]) ])
.annotate(vec![ .annotate(StructType::new(
StructMember::new("foo".into(), Type::FieldElement), "".into(),
StructMember::new("bar".into(), Type::Boolean) "Foo".into(),
]) vec![
StructMember::new("foo".into(), Type::FieldElement),
StructMember::new("bar".into(), Type::Boolean)
]
))
.into()) .into())
); );
} }
@ -4515,14 +4576,14 @@ mod tests {
// struct Foo = { foo: field, bar: bool } // struct Foo = { foo: field, bar: bool }
// Foo foo = Foo { bar: true, foo: 42 } // Foo foo = Foo { bar: true, foo: 42 }
let (mut checker, state) = create_module_with_foo(StructType { let (mut checker, state) = create_module_with_foo(StructDefinition {
fields: vec![ fields: vec![
StructField { StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
.mock(), .mock(),
StructField { StructDefinitionField {
id: "bar", id: "bar",
ty: UnresolvedType::Boolean.mock(), ty: UnresolvedType::Boolean.mock(),
} }
@ -4550,10 +4611,14 @@ mod tests {
FieldElementExpression::Number(Bn128Field::from(42)).into(), FieldElementExpression::Number(Bn128Field::from(42)).into(),
BooleanExpression::Value(true).into() BooleanExpression::Value(true).into()
]) ])
.annotate(vec![ .annotate(StructType::new(
StructMember::new("foo".into(), Type::FieldElement), "".into(),
StructMember::new("bar".into(), Type::Boolean) "Foo".into(),
]) vec![
StructMember::new("foo".into(), Type::FieldElement),
StructMember::new("bar".into(), Type::Boolean)
]
))
.into()) .into())
); );
} }
@ -4565,14 +4630,14 @@ mod tests {
// struct Foo = { foo: field, bar: bool } // struct Foo = { foo: field, bar: bool }
// Foo foo = Foo { foo: 42 } // Foo foo = Foo { foo: 42 }
let (mut checker, state) = create_module_with_foo(StructType { let (mut checker, state) = create_module_with_foo(StructDefinition {
fields: vec![ fields: vec![
StructField { StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
.mock(), .mock(),
StructField { StructDefinitionField {
id: "bar", id: "bar",
ty: UnresolvedType::Boolean.mock(), ty: UnresolvedType::Boolean.mock(),
} }
@ -4596,7 +4661,7 @@ mod tests {
) )
.unwrap_err() .unwrap_err()
.message, .message,
"Inline struct Foo {foo: 42} does not match Foo : {foo: field, bar: bool}" "Inline struct Foo {foo: 42} does not match Foo {foo: field, bar: bool}"
); );
} }
@ -4609,14 +4674,14 @@ mod tests {
// Foo { foo: 42, baz: bool } // error // Foo { foo: 42, baz: bool } // error
// Foo { foo: 42, baz: 42 } // error // Foo { foo: 42, baz: 42 } // error
let (mut checker, state) = create_module_with_foo(StructType { let (mut checker, state) = create_module_with_foo(StructDefinition {
fields: vec![ fields: vec![
StructField { StructDefinitionField {
id: "foo", id: "foo",
ty: UnresolvedType::FieldElement.mock(), ty: UnresolvedType::FieldElement.mock(),
} }
.mock(), .mock(),
StructField { StructDefinitionField {
id: "bar", id: "bar",
ty: UnresolvedType::Boolean.mock(), ty: UnresolvedType::Boolean.mock(),
} }
@ -4642,7 +4707,7 @@ mod tests {
&state.types &state.types
).unwrap_err() ).unwrap_err()
.message, .message,
"Member bar of struct Foo : {foo: field, bar: bool} not found in value Foo {baz: true, foo: 42}" "Member bar of struct Foo {foo: field, bar: bool} not found in value Foo {baz: true, foo: 42}"
); );
assert_eq!( assert_eq!(

View file

@ -1,5 +1,6 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use typed_absy; use typed_absy;
use typed_absy::types::StructType;
use zir; use zir;
use zokrates_field::Field; use zokrates_field::Field;
@ -201,7 +202,7 @@ impl<'ast, T: Field> Flattener<T> {
} }
fn fold_struct_expression_inner( fn fold_struct_expression_inner(
&mut self, &mut self,
ty: &Vec<(typed_absy::types::MemberId, typed_absy::Type)>, ty: &StructType,
e: typed_absy::StructExpressionInner<'ast, T>, e: typed_absy::StructExpressionInner<'ast, T>,
) -> Vec<zir::ZirExpression<'ast, T>> { ) -> Vec<zir::ZirExpression<'ast, T>> {
fold_struct_expression_inner(self, ty, e) fold_struct_expression_inner(self, ty, e)
@ -360,7 +361,7 @@ pub fn fold_array_expression_inner<'ast, T: Field>(
pub fn fold_struct_expression_inner<'ast, T: Field>( pub fn fold_struct_expression_inner<'ast, T: Field>(
f: &mut Flattener<T>, f: &mut Flattener<T>,
t: &Vec<(typed_absy::types::MemberId, typed_absy::Type)>, t: &StructType,
e: typed_absy::StructExpressionInner<'ast, T>, e: typed_absy::StructExpressionInner<'ast, T>,
) -> Vec<zir::ZirExpression<'ast, T>> { ) -> Vec<zir::ZirExpression<'ast, T>> {
match e { match e {
@ -427,9 +428,9 @@ pub fn fold_struct_expression_inner<'ast, T: Field>(
// we also need the size of this member // we also need the size of this member
let size = t let size = t
.iter() .iter()
.find(|(id, _)| id == id) .find(|member| member.id == id)
.unwrap() .unwrap()
.1 .ty
.get_primitive_count(); .get_primitive_count();
s[offset..offset + size].to_vec() s[offset..offset + size].to_vec()
@ -442,7 +443,7 @@ pub fn fold_struct_expression_inner<'ast, T: Field>(
zir::FieldElementExpression::Number(i) => { zir::FieldElementExpression::Number(i) => {
let size = t let size = t
.iter() .iter()
.map(|(_, t)| t.get_primitive_count()) .map(|m| m.ty.get_primitive_count())
.fold(0, |acc, current| acc + current); .fold(0, |acc, current| acc + current);
let start = i.to_dec_string().parse::<usize>().unwrap() * size; let start = i.to_dec_string().parse::<usize>().unwrap() * size;
let end = start + size; let end = start + size;
@ -777,10 +778,7 @@ pub fn fold_struct_expression<'ast, T: Field>(
f: &mut Flattener<T>, f: &mut Flattener<T>,
e: typed_absy::StructExpression<'ast, T>, e: typed_absy::StructExpression<'ast, T>,
) -> Vec<zir::ZirExpression<'ast, T>> { ) -> Vec<zir::ZirExpression<'ast, T>> {
f.fold_struct_expression_inner( f.fold_struct_expression_inner(&e.ty().clone(), e.into_inner())
&e.ty().clone().into_iter().map(|m| (m.id, *m.ty)).collect(),
e.into_inner(),
)
} }
pub fn fold_function_symbol<'ast, T: Field>( pub fn fold_function_symbol<'ast, T: Field>(

View file

@ -17,7 +17,7 @@
//! where any call in `main` must be to `_SHA_256_ROUND` or `_UNPACK` //! where any call in `main` must be to `_SHA_256_ROUND` or `_UNPACK`
use std::collections::HashMap; use std::collections::HashMap;
use typed_absy::types::{FunctionKey, StructMember, Type}; use typed_absy::types::{FunctionKey, Type};
use typed_absy::{folder::*, *}; use typed_absy::{folder::*, *};
use zokrates_field::Field; use zokrates_field::Field;
@ -483,7 +483,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> {
fn fold_struct_expression_inner( fn fold_struct_expression_inner(
&mut self, &mut self,
ty: &Vec<StructMember>, ty: &StructType,
e: StructExpressionInner<'ast, T>, e: StructExpressionInner<'ast, T>,
) -> StructExpressionInner<'ast, T> { ) -> StructExpressionInner<'ast, T> {
match e { match e {

View file

@ -14,7 +14,7 @@ use crate::typed_absy::folder::*;
use crate::typed_absy::*; use crate::typed_absy::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use typed_absy::types::{StructMember, Type}; use typed_absy::types::Type;
use zokrates_field::Field; use zokrates_field::Field;
pub struct Propagator<'ast, T: Field> { pub struct Propagator<'ast, T: Field> {
@ -816,7 +816,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
fn fold_struct_expression_inner( fn fold_struct_expression_inner(
&mut self, &mut self,
ty: &Vec<StructMember>, ty: &StructType,
e: StructExpressionInner<'ast, T>, e: StructExpressionInner<'ast, T>,
) -> StructExpressionInner<'ast, T> { ) -> StructExpressionInner<'ast, T> {
match e { match e {

View file

@ -1,4 +1,3 @@
use typed_absy::types::StructMember;
use typed_absy::{folder::*, *}; use typed_absy::{folder::*, *};
use zokrates_field::Field; use zokrates_field::Field;
@ -103,14 +102,14 @@ impl<'ast, T: Field> Folder<'ast, T> for VariableAccessRemover<'ast, T> {
fn fold_struct_expression_inner( fn fold_struct_expression_inner(
&mut self, &mut self,
members: &Vec<StructMember>, ty: &StructType,
e: StructExpressionInner<'ast, T>, e: StructExpressionInner<'ast, T>,
) -> StructExpressionInner<'ast, T> { ) -> StructExpressionInner<'ast, T> {
match e { match e {
StructExpressionInner::Select(box a, box i) => { StructExpressionInner::Select(box a, box i) => {
self.select::<StructExpression<'ast, T>>(a, i).into_inner() self.select::<StructExpression<'ast, T>>(a, i).into_inner()
} }
e => fold_struct_expression_inner(self, members, e), e => fold_struct_expression_inner(self, ty, e),
} }
} }

View file

@ -30,7 +30,7 @@ impl Abi {
mod tests { mod tests {
use super::*; use super::*;
use std::collections::HashMap; use std::collections::HashMap;
use typed_absy::types::{ArrayType, FunctionKey, StructMember}; use typed_absy::types::{ArrayType, FunctionKey, StructMember, StructType};
use typed_absy::{ use typed_absy::{
Parameter, Type, TypedFunction, TypedFunctionSymbol, TypedModule, TypedProgram, Variable, Parameter, Type, TypedFunction, TypedFunctionSymbol, TypedModule, TypedProgram, Variable,
}; };
@ -147,15 +147,23 @@ mod tests {
inputs: vec![AbiInput { inputs: vec![AbiInput {
name: String::from("foo"), name: String::from("foo"),
public: true, public: true,
ty: Type::Struct(vec![ ty: Type::Struct(StructType::new(
"".into(),
"Foo".into(),
vec![
StructMember::new(String::from("a"), Type::FieldElement),
StructMember::new(String::from("b"), Type::Boolean),
],
)),
}],
outputs: vec![Type::Struct(StructType::new(
"".into(),
"Foo".into(),
vec![
StructMember::new(String::from("a"), Type::FieldElement), StructMember::new(String::from("a"), Type::FieldElement),
StructMember::new(String::from("b"), Type::Boolean), StructMember::new(String::from("b"), Type::Boolean),
]), ],
}], ))],
outputs: vec![Type::Struct(vec![
StructMember::new(String::from("a"), Type::FieldElement),
StructMember::new(String::from("b"), Type::Boolean),
])],
}; };
let json = serde_json::to_string_pretty(&abi).unwrap(); let json = serde_json::to_string_pretty(&abi).unwrap();
@ -167,31 +175,37 @@ mod tests {
"name": "foo", "name": "foo",
"public": true, "public": true,
"type": "struct", "type": "struct",
"components": [ "components": {
{ "name": "Foo",
"name": "a", "members": [
"type": "field" {
}, "name": "a",
{ "type": "field"
"name": "b", },
"type": "bool" {
} "name": "b",
] "type": "bool"
}
]
}
} }
], ],
"outputs": [ "outputs": [
{ {
"type": "struct", "type": "struct",
"components": [ "components": {
{ "name": "Foo",
"name": "a", "members": [
"type": "field" {
}, "name": "a",
{ "type": "field"
"name": "b", },
"type": "bool" {
} "name": "b",
] "type": "bool"
}
]
}
} }
] ]
}"# }"#
@ -204,13 +218,21 @@ mod tests {
inputs: vec![AbiInput { inputs: vec![AbiInput {
name: String::from("foo"), name: String::from("foo"),
public: true, public: true,
ty: Type::Struct(vec![StructMember::new( ty: Type::Struct(StructType::new(
String::from("bar"), "".into(),
Type::Struct(vec![ "Foo".into(),
StructMember::new(String::from("a"), Type::FieldElement), vec![StructMember::new(
StructMember::new(String::from("b"), Type::FieldElement), String::from("bar"),
]), Type::Struct(StructType::new(
)]), "".into(),
"Bar".into(),
vec![
StructMember::new(String::from("a"), Type::FieldElement),
StructMember::new(String::from("b"), Type::FieldElement),
],
)),
)],
)),
}], }],
outputs: vec![], outputs: vec![],
}; };
@ -224,22 +246,28 @@ mod tests {
"name": "foo", "name": "foo",
"public": true, "public": true,
"type": "struct", "type": "struct",
"components": [ "components": {
{ "name": "Foo",
"name": "bar", "members": [
"type": "struct", {
"components": [ "name": "bar",
{ "type": "struct",
"name": "a", "components": {
"type": "field" "name": "Bar",
}, "members": [
{ {
"name": "b", "name": "a",
"type": "field" "type": "field"
},
{
"name": "b",
"type": "field"
}
]
} }
] }
} ]
] }
} }
], ],
"outputs": [] "outputs": []
@ -254,10 +282,14 @@ mod tests {
name: String::from("a"), name: String::from("a"),
public: false, public: false,
ty: Type::Array(ArrayType::new( ty: Type::Array(ArrayType::new(
Type::Struct(vec![ Type::Struct(StructType::new(
StructMember::new(String::from("b"), Type::FieldElement), "".into(),
StructMember::new(String::from("c"), Type::Boolean), "Foo".into(),
]), vec![
StructMember::new(String::from("b"), Type::FieldElement),
StructMember::new(String::from("c"), Type::Boolean),
],
)),
2, 2,
)), )),
}], }],
@ -276,16 +308,19 @@ mod tests {
"components": { "components": {
"size": 2, "size": 2,
"type": "struct", "type": "struct",
"components": [ "components": {
{ "name": "Foo",
"name": "b", "members": [
"type": "field" {
}, "name": "b",
{ "type": "field"
"name": "c", },
"type": "bool" {
} "name": "c",
] "type": "bool"
}
]
}
} }
} }
], ],

View file

@ -1,7 +1,6 @@
// Generic walk through a typed AST. Not mutating in place // Generic walk through a typed AST. Not mutating in place
use crate::typed_absy::*; use crate::typed_absy::*;
use typed_absy::types::StructMember;
use zokrates_field::Field; use zokrates_field::Field;
pub trait Folder<'ast, T: Field>: Sized { pub trait Folder<'ast, T: Field>: Sized {
@ -130,7 +129,7 @@ pub trait Folder<'ast, T: Field>: Sized {
} }
fn fold_struct_expression_inner( fn fold_struct_expression_inner(
&mut self, &mut self,
ty: &Vec<StructMember>, ty: &StructType,
e: StructExpressionInner<'ast, T>, e: StructExpressionInner<'ast, T>,
) -> StructExpressionInner<'ast, T> { ) -> StructExpressionInner<'ast, T> {
fold_struct_expression_inner(self, ty, e) fold_struct_expression_inner(self, ty, e)
@ -222,7 +221,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>>( pub fn fold_struct_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F, f: &mut F,
_: &Vec<StructMember>, _: &StructType,
e: StructExpressionInner<'ast, T>, e: StructExpressionInner<'ast, T>,
) -> StructExpressionInner<'ast, T> { ) -> StructExpressionInner<'ast, T> {
match e { match e {

View file

@ -16,7 +16,7 @@ mod variable;
pub use self::identifier::CoreIdentifier; pub use self::identifier::CoreIdentifier;
pub use self::parameter::Parameter; pub use self::parameter::Parameter;
pub use self::types::{Signature, Type}; pub use self::types::{Signature, StructType, Type};
pub use self::variable::Variable; pub use self::variable::Variable;
use std::path::PathBuf; use std::path::PathBuf;
pub use typed_absy::uint::{bitwidth, UExpression, UExpressionInner, UMetadata}; pub use typed_absy::uint::{bitwidth, UExpression, UExpressionInner, UMetadata};
@ -30,7 +30,6 @@ use zokrates_field::Field;
pub use self::folder::Folder; pub use self::folder::Folder;
use typed_absy::abi::{Abi, AbiInput}; use typed_absy::abi::{Abi, AbiInput};
use typed_absy::types::StructMember;
pub use self::identifier::Identifier; pub use self::identifier::Identifier;
@ -729,12 +728,12 @@ impl<'ast, T> ArrayExpression<'ast, T> {
#[derive(Clone, PartialEq, Hash, Eq)] #[derive(Clone, PartialEq, Hash, Eq)]
pub struct StructExpression<'ast, T> { pub struct StructExpression<'ast, T> {
ty: Vec<StructMember>, ty: StructType,
inner: StructExpressionInner<'ast, T>, inner: StructExpressionInner<'ast, T>,
} }
impl<'ast, T> StructExpression<'ast, T> { impl<'ast, T> StructExpression<'ast, T> {
pub fn ty(&self) -> &Vec<StructMember> { pub fn ty(&self) -> &StructType {
&self.ty &self.ty
} }
@ -765,7 +764,7 @@ pub enum StructExpressionInner<'ast, T> {
} }
impl<'ast, T> StructExpressionInner<'ast, T> { impl<'ast, T> StructExpressionInner<'ast, T> {
pub fn annotate(self, ty: Vec<StructMember>) -> StructExpression<'ast, T> { pub fn annotate(self, ty: StructType) -> StructExpression<'ast, T> {
StructExpression { ty, inner: self } StructExpression { ty, inner: self }
} }
} }

View file

@ -1,4 +1,5 @@
use std::fmt; use std::fmt;
use std::path::PathBuf;
pub type Identifier<'ast> = &'ast str; pub type Identifier<'ast> = &'ast str;
@ -19,6 +20,49 @@ pub struct ArrayType {
pub ty: Box<Type>, pub ty: Box<Type>,
} }
#[derive(Clone, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct StructType {
#[serde(skip)]
pub module: PathBuf,
pub name: String,
pub members: Vec<StructMember>,
}
impl PartialEq for StructType {
fn eq(&self, other: &Self) -> bool {
self.members.eq(&other.members)
}
}
impl Eq for StructType {}
impl StructType {
pub fn new(module: PathBuf, name: String, members: Vec<StructMember>) -> Self {
StructType {
module,
name,
members,
}
}
pub fn len(&self) -> usize {
self.members.len()
}
pub fn iter(&self) -> std::slice::Iter<StructMember> {
self.members.iter()
}
}
impl IntoIterator for StructType {
type Item = StructMember;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.members.into_iter()
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] #[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
#[serde(tag = "type", content = "components")] #[serde(tag = "type", content = "components")]
pub enum Type { pub enum Type {
@ -29,7 +73,7 @@ pub enum Type {
#[serde(rename = "array")] #[serde(rename = "array")]
Array(ArrayType), Array(ArrayType),
#[serde(rename = "struct")] #[serde(rename = "struct")]
Struct(Vec<StructMember>), Struct(StructType),
#[serde(rename = "u")] #[serde(rename = "u")]
Uint(usize), Uint(usize),
} }
@ -59,10 +103,12 @@ impl fmt::Display for Type {
Type::Boolean => write!(f, "bool"), Type::Boolean => write!(f, "bool"),
Type::Uint(ref bitwidth) => write!(f, "u{}", bitwidth), Type::Uint(ref bitwidth) => write!(f, "u{}", bitwidth),
Type::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size), Type::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size),
Type::Struct(ref members) => write!( Type::Struct(ref struct_type) => write!(
f, f,
"{{{}}}", "{} {{{}}}",
members struct_type.name,
struct_type
.members
.iter() .iter()
.map(|member| format!("{}: {}", member.id, member.ty)) .map(|member| format!("{}: {}", member.id, member.ty))
.collect::<Vec<_>>() .collect::<Vec<_>>()
@ -79,10 +125,12 @@ impl fmt::Debug for Type {
Type::Boolean => write!(f, "bool"), Type::Boolean => write!(f, "bool"),
Type::Uint(ref bitwidth) => write!(f, "u{}", bitwidth), Type::Uint(ref bitwidth) => write!(f, "u{}", bitwidth),
Type::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size), Type::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size),
Type::Struct(ref members) => write!( Type::Struct(ref struct_type) => write!(
f, f,
"{{{}}}", "{} {{{}}}",
members struct_type.name,
struct_type
.members
.iter() .iter()
.map(|member| format!("{}: {}", member.id, member.ty)) .map(|member| format!("{}: {}", member.id, member.ty))
.collect::<Vec<_>>() .collect::<Vec<_>>()
@ -97,12 +145,8 @@ impl Type {
Type::Array(ArrayType::new(ty, size)) Type::Array(ArrayType::new(ty, size))
} }
pub fn struc(ty: Vec<(MemberId, Type)>) -> Self { pub fn struc(struct_ty: StructType) -> Self {
Type::Struct( Type::Struct(struct_ty)
ty.into_iter()
.map(|(id, ty)| StructMember { id, ty: box ty })
.collect(),
)
} }
fn to_slug(&self) -> String { fn to_slug(&self) -> String {
@ -111,9 +155,9 @@ impl Type {
Type::Boolean => String::from("b"), Type::Boolean => String::from("b"),
Type::Uint(bitwidth) => format!("u{}", bitwidth), Type::Uint(bitwidth) => format!("u{}", bitwidth),
Type::Array(array_type) => format!("{}[{}]", array_type.ty.to_slug(), array_type.size), Type::Array(array_type) => format!("{}[{}]", array_type.ty.to_slug(), array_type.size),
Type::Struct(members) => format!( Type::Struct(struct_type) => format!(
"{{{}}}", "{{{}}}",
members struct_type
.iter() .iter()
.map(|member| format!("{}:{}", member.id, member.ty)) .map(|member| format!("{}:{}", member.id, member.ty))
.collect::<Vec<_>>() .collect::<Vec<_>>()
@ -128,8 +172,11 @@ impl Type {
Type::FieldElement => 1, Type::FieldElement => 1,
Type::Boolean => 1, Type::Boolean => 1,
Type::Uint(_) => 1, Type::Uint(_) => 1,
Type::Struct(members) => members.iter().map(|m| m.ty.get_primitive_count()).sum(),
Type::Array(array_type) => array_type.size * array_type.ty.get_primitive_count(), Type::Array(array_type) => array_type.size * array_type.ty.get_primitive_count(),
Type::Struct(struct_type) => struct_type
.iter()
.map(|member| member.ty.get_primitive_count())
.sum(),
} }
} }
} }

View file

@ -1,7 +1,7 @@
use crate::typed_absy::types::Type; use crate::typed_absy::types::Type;
use crate::typed_absy::Identifier; use crate::typed_absy::Identifier;
use std::fmt; use std::fmt;
use typed_absy::types::StructMember; use typed_absy::types::StructType;
#[derive(Clone, PartialEq, Hash, Eq)] #[derive(Clone, PartialEq, Hash, Eq)]
pub struct Variable<'ast> { pub struct Variable<'ast> {
@ -31,7 +31,7 @@ impl<'ast> Variable<'ast> {
Self::with_id_and_type(id, Type::array(ty, size)) Self::with_id_and_type(id, Type::array(ty, size))
} }
pub fn struc<I: Into<Identifier<'ast>>>(id: I, ty: Vec<StructMember>) -> Variable<'ast> { pub fn struc<I: Into<Identifier<'ast>>>(id: I, ty: StructType) -> Variable<'ast> {
Self::with_id_and_type(id, Type::Struct(ty)) Self::with_id_and_type(id, Type::Struct(ty))
} }