From 2c07fee81282e7a9431e07ee83b41fa4c94a82ea Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 14 May 2020 20:17:50 +0200 Subject: [PATCH 1/8] remove if else --- zokrates_cli/examples/error/struct_if_else.zok | 0 zokrates_core/src/semantics.rs | 8 ++------ zokrates_core_test/tests/tests/structs/if_else.zok | 0 3 files changed, 2 insertions(+), 6 deletions(-) create mode 100644 zokrates_cli/examples/error/struct_if_else.zok create mode 100644 zokrates_core_test/tests/tests/structs/if_else.zok diff --git a/zokrates_cli/examples/error/struct_if_else.zok b/zokrates_cli/examples/error/struct_if_else.zok new file mode 100644 index 00000000..e69de29b diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index dad2d637..94870da7 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -1297,12 +1297,8 @@ impl<'ast> Checker<'ast> { Ok(ArrayExpressionInner::IfElse(box condition, box consequence, box alternative).annotate(inner_type, size).into()) }, (TypedExpression::Struct(consequence), TypedExpression::Struct(alternative)) => { - if consequence.get_type() == alternative.get_type() { - let ty = consequence.ty().clone(); - Ok(StructExpressionInner::IfElse(box condition, box consequence, box alternative).annotate(ty).into()) - } else { - unimplemented!("handle consequence alternative inner type mismatch") - } + let ty = consequence.ty().clone(); + Ok(StructExpressionInner::IfElse(box condition, box consequence, box alternative).annotate(ty).into()) }, _ => unreachable!("types should match here as we checked them explicitly") } diff --git a/zokrates_core_test/tests/tests/structs/if_else.zok b/zokrates_core_test/tests/tests/structs/if_else.zok new file mode 100644 index 00000000..e69de29b From 648f71e8c14b42978e208959dc937d58b03c7c4c Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 14 May 2020 23:03:15 +0200 Subject: [PATCH 2/8] add name to typed types --- zokrates_abi/src/lib.rs | 38 +-- .../examples/error/struct_if_else.zok | 5 + zokrates_core/src/absy/from_ast.rs | 10 +- zokrates_core/src/absy/mod.rs | 16 +- zokrates_core/src/absy/node.rs | 4 +- zokrates_core/src/semantics.rs | 258 +++++++++++------- .../src/static_analysis/constrain_inputs.rs | 2 +- zokrates_core/src/static_analysis/inline.rs | 4 +- .../src/static_analysis/propagation.rs | 4 +- zokrates_core/src/typed_absy/abi.rs | 161 ++++++----- zokrates_core/src/typed_absy/folder.rs | 5 +- zokrates_core/src/typed_absy/mod.rs | 9 +- zokrates_core/src/typed_absy/types.rs | 60 +++- zokrates_core/src/typed_absy/variable.rs | 4 +- 14 files changed, 364 insertions(+), 216 deletions(-) diff --git a/zokrates_abi/src/lib.rs b/zokrates_abi/src/lib.rs index 3286233d..90170c6d 100644 --- a/zokrates_abi/src/lib.rs +++ b/zokrates_abi/src/lib.rs @@ -365,7 +365,7 @@ mod tests { mod strict { use super::*; - use zokrates_core::typed_absy::types::StructMember; + use zokrates_core::typed_absy::types::{StructMember, StructType}; #[test] fn fields() { @@ -410,10 +410,11 @@ mod tests { assert_eq!( parse_strict::( s, - vec![Type::Struct(vec![StructMember::new( - "a".into(), - Type::FieldElement - )])] + vec![Type::Struct(StructType::new( + "".into(), + "".into(), + vec![StructMember::new("a".into(), Type::FieldElement)] + ))] ) .unwrap(), CheckedValues(vec![CheckedValue::Struct( @@ -427,10 +428,11 @@ mod tests { assert_eq!( parse_strict::( s, - vec![Type::Struct(vec![StructMember::new( - "a".into(), - Type::FieldElement - )])] + vec![Type::Struct(StructType::new( + "".into(), + "".into(), + vec![StructMember::new("a".into(), Type::FieldElement)] + ))] ) .unwrap_err(), Error::Type("Member with id `a` not found".into()) @@ -440,10 +442,11 @@ mod tests { assert_eq!( parse_strict::( s, - vec![Type::Struct(vec![StructMember::new( - "a".into(), - Type::FieldElement - )])] + vec![Type::Struct(StructType::new( + "".into(), + "".into(), + vec![StructMember::new("a".into(), Type::FieldElement)] + ))] ) .unwrap_err(), Error::Type("Expected 1 member(s), found 0".into()) @@ -453,10 +456,11 @@ mod tests { assert_eq!( parse_strict::( s, - vec![Type::Struct(vec![StructMember::new( - "a".into(), - Type::FieldElement - )])] + vec![Type::Struct(StructType::new( + "".into(), + "".into(), + vec![StructMember::new("a".into(), Type::FieldElement)] + ))] ) .unwrap_err(), Error::Type("Value `false` doesn't match expected type `field`".into()) diff --git a/zokrates_cli/examples/error/struct_if_else.zok b/zokrates_cli/examples/error/struct_if_else.zok index e69de29b..73f81980 100644 --- a/zokrates_cli/examples/error/struct_if_else.zok +++ b/zokrates_cli/examples/error/struct_if_else.zok @@ -0,0 +1,5 @@ +struct Foo {} +struct Bar {} + +def main() -> (Foo): + return Bar {} \ No newline at end of file diff --git a/zokrates_core/src/absy/from_ast.rs b/zokrates_core/src/absy/from_ast.rs index 7542e134..4fd1abfa 100644 --- a/zokrates_core/src/absy/from_ast.rs +++ b/zokrates_core/src/absy/from_ast.rs @@ -47,11 +47,11 @@ impl<'ast, T: Field> From> for absy::SymbolDeclarat let id = definition.id.span.as_str(); - let ty = absy::StructType { + let ty = absy::StructDefinition { fields: definition .fields .into_iter() - .map(|f| absy::StructFieldNode::from(f)) + .map(|f| absy::StructDefinitionFieldNode::from(f)) .collect(), } .span(span.clone()); @@ -64,8 +64,8 @@ impl<'ast, T: Field> From> for absy::SymbolDeclarat } } -impl<'ast> From> for absy::StructFieldNode<'ast> { - fn from(field: pest::StructField<'ast>) -> absy::StructFieldNode { +impl<'ast> From> for absy::StructDefinitionFieldNode<'ast> { + fn from(field: pest::StructField<'ast>) -> absy::StructDefinitionFieldNode { use absy::NodeValue; let span = field.span; @@ -74,7 +74,7 @@ impl<'ast> From> for absy::StructFieldNode<'ast> { let ty = absy::UnresolvedTypeNode::from(field.ty); - absy::StructField { id, ty }.span(span) + absy::StructDefinitionField { id, ty }.span(span) } } diff --git a/zokrates_core/src/absy/mod.rs b/zokrates_core/src/absy/mod.rs index f05a6437..08a7c3f0 100644 --- a/zokrates_core/src/absy/mod.rs +++ b/zokrates_core/src/absy/mod.rs @@ -51,7 +51,7 @@ pub struct SymbolDeclaration<'ast, T> { #[derive(PartialEq, Clone)] pub enum Symbol<'ast, T> { - HereType(StructTypeNode<'ast>), + HereType(StructDefinitionNode<'ast>), HereFunction(FunctionNode<'ast, T>), There(SymbolImportNode<'ast>), Flat(FlatEmbed), @@ -112,11 +112,11 @@ pub type UnresolvedTypeNode = Node; /// A struct type definition #[derive(Debug, Clone, PartialEq)] -pub struct StructType<'ast> { - pub fields: Vec>, +pub struct StructDefinition<'ast> { + pub fields: Vec>, } -impl<'ast> fmt::Display for StructType<'ast> { +impl<'ast> fmt::Display for StructDefinition<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, @@ -130,22 +130,22 @@ impl<'ast> fmt::Display for StructType<'ast> { } } -pub type StructTypeNode<'ast> = Node>; +pub type StructDefinitionNode<'ast> = Node>; /// A struct type definition #[derive(Debug, Clone, PartialEq)] -pub struct StructField<'ast> { +pub struct StructDefinitionField<'ast> { pub id: Identifier<'ast>, 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 { write!(f, "{}: {},", self.id, self.ty) } } -type StructFieldNode<'ast> = Node>; +type StructDefinitionFieldNode<'ast> = Node>; /// An import #[derive(Debug, Clone, PartialEq)] diff --git a/zokrates_core/src/absy/node.rs b/zokrates_core/src/absy/node.rs index 21837f39..1cbc059d 100644 --- a/zokrates_core/src/absy/node.rs +++ b/zokrates_core/src/absy/node.rs @@ -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: Field> NodeValue for SymbolDeclaration<'ast, T> {} impl NodeValue for UnresolvedType {} -impl<'ast> NodeValue for StructType<'ast> {} -impl<'ast> NodeValue for StructField<'ast> {} +impl<'ast> NodeValue for StructDefinition<'ast> {} +impl<'ast> NodeValue for StructDefinitionField<'ast> {} impl<'ast, T: fmt::Display + fmt::Debug + PartialEq> NodeValue for Function<'ast, T> {} impl<'ast, T: Field> NodeValue for Module<'ast, T> {} impl<'ast> NodeValue for SymbolImport<'ast> {} diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 94870da7..f34ade74 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -268,7 +268,8 @@ impl<'ast> Checker<'ast> { fn check_struct_type_declaration( &mut self, - s: StructTypeNode<'ast>, + id: String, + s: StructDefinitionNode<'ast>, module_id: &ModuleId, types: &TypeMap, ) -> Result> { @@ -302,12 +303,14 @@ impl<'ast> Checker<'ast> { return Err(errors); } - Ok(Type::Struct( + Ok(Type::Struct(StructType::new( + module_id.into(), + id, fields .iter() .map(|f| StructMember::new(f.0.clone(), f.1.clone())) .collect(), - )) + ))) } fn check_symbol_declaration( @@ -325,7 +328,12 @@ impl<'ast> Checker<'ast> { match declaration.symbol { 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) => { match symbol_unifier.insert_type(declaration.id) { false => errors.push( @@ -1820,21 +1828,21 @@ impl<'ast> Checker<'ast> { module_id, &types, )?; - let members = match ty { - Type::Struct(members) => members, + let struct_type = match ty { + Type::Struct(struct_type) => struct_type, _ => unreachable!(), }; // 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 { pos: Some(pos), message: format!( "Inline struct {} does not match {} : {}", Expression::InlineStruct(id.clone(), inline_members), id, - Type::Struct(members) + Type::Struct(struct_type) ), }); } @@ -1849,7 +1857,7 @@ impl<'ast> Checker<'ast> { .collect::>(); let mut result: Vec> = vec![]; - for member in &members { + for member in struct_type.iter() { match inline_members_map.remove(member.id.as_str()) { Some(value) => { let expression_checked = @@ -1878,7 +1886,7 @@ impl<'ast> Checker<'ast> { "Member {} of struct {} : {} not found in value {}", member.id, id.clone(), - Type::Struct(members.clone()), + Type::Struct(struct_type.clone()), Expression::InlineStruct(id.clone(), inline_members), ), }) @@ -1887,7 +1895,7 @@ impl<'ast> Checker<'ast> { } Ok(StructExpressionInner::Value(result) - .annotate(members) + .annotate(struct_type) .into()) } Expression::And(box e1, box e2) => { @@ -2084,13 +2092,13 @@ mod tests { .mock() } - fn struct0() -> StructTypeNode<'static> { - StructType { fields: vec![] }.mock() + fn struct0() -> StructDefinitionNode<'static> { + StructDefinition { fields: vec![] }.mock() } - fn struct1() -> StructTypeNode<'static> { - StructType { - fields: vec![StructField { + fn struct1() -> StructDefinitionNode<'static> { + StructDefinition { + fields: vec![StructDefinitionField { id: "foo".into(), ty: UnresolvedType::FieldElement.mock(), } @@ -2318,7 +2326,7 @@ mod tests { .mock(), SymbolDeclaration { id: "foo", - symbol: Symbol::HereType(StructType { fields: vec![] }.mock()), + symbol: Symbol::HereType(StructDefinition { fields: vec![] }.mock()), } .mock(), ], @@ -3619,7 +3627,7 @@ mod tests { /// solver function to create a module at location "" with a single symbol `Foo { foo: field }` fn create_module_with_foo( - s: StructType<'static>, + s: StructDefinition<'static>, ) -> (Checker<'static>, State<'static, Bn128Field>) { let module_id: PathBuf = "".into(); @@ -3650,12 +3658,17 @@ mod tests { // an empty struct should be allowed to be defined let module_id = "".into(); 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!( - 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) ); } @@ -3665,14 +3678,14 @@ mod tests { // a valid struct should be allowed to be defined let module_id = "".into(); let types = HashMap::new(); - let declaration = StructType { + let declaration = StructDefinition { fields: vec![ - StructField { + StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } .mock(), - StructField { + StructDefinitionField { id: "bar", ty: UnresolvedType::Boolean.mock(), } @@ -3681,13 +3694,22 @@ mod tests { } .mock(); - let expected_type = Type::Struct(vec![ - StructMember::new("foo".into(), Type::FieldElement), - StructMember::new("bar".into(), Type::Boolean), - ]); + let expected_type = Type::Struct(StructType::new( + "".into(), + "Foo".into(), + vec![ + StructMember::new("foo".into(), Type::FieldElement), + StructMember::new("bar".into(), Type::Boolean), + ], + )); 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) ); } @@ -3698,14 +3720,14 @@ mod tests { let module_id = "".into(); let types = HashMap::new(); - let declaration0 = StructType { + let declaration0 = StructDefinition { fields: vec![ - StructField { + StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } .mock(), - StructField { + StructDefinitionField { id: "bar", ty: UnresolvedType::Boolean.mock(), } @@ -3714,14 +3736,14 @@ mod tests { } .mock(); - let declaration1 = StructType { + let declaration1 = StructDefinition { fields: vec![ - StructField { + StructDefinitionField { id: "bar", ty: UnresolvedType::Boolean.mock(), } .mock(), - StructField { + StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } @@ -3731,8 +3753,18 @@ mod tests { .mock(); assert_ne!( - Checker::new().check_struct_type_declaration(declaration0, &module_id, &types), - Checker::new().check_struct_type_declaration(declaration1, &module_id, &types) + Checker::new().check_struct_type_declaration( + "Foo".into(), + declaration0, + &module_id, + &types + ), + Checker::new().check_struct_type_declaration( + "Foo".into(), + declaration1, + &module_id, + &types + ) ); } @@ -3742,14 +3774,14 @@ mod tests { let module_id = "".into(); let types = HashMap::new(); - let declaration = StructType { + let declaration = StructDefinition { fields: vec![ - StructField { + StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } .mock(), - StructField { + StructDefinitionField { id: "foo", ty: UnresolvedType::Boolean.mock(), } @@ -3760,7 +3792,12 @@ mod tests { assert_eq!( Checker::new() - .check_struct_type_declaration(declaration, &module_id, &types) + .check_struct_type_declaration( + "Foo".into(), + declaration, + &module_id, + &types + ) .unwrap_err()[0] .message, "Duplicate key foo in struct definition" @@ -3782,8 +3819,8 @@ mod tests { SymbolDeclaration { id: "Foo", symbol: Symbol::HereType( - StructType { - fields: vec![StructField { + StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } @@ -3796,8 +3833,8 @@ mod tests { SymbolDeclaration { id: "Bar", symbol: Symbol::HereType( - StructType { - fields: vec![StructField { + StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::User("Foo".into()).mock(), } @@ -3820,10 +3857,18 @@ mod tests { .unwrap() .get(&"Bar".to_string()) .unwrap(), - &Type::Struct(vec![StructMember::new( - "foo".into(), - Type::Struct(vec![StructMember::new("foo".into(), Type::FieldElement)]) - )]) + &Type::Struct(StructType::new( + module_id.clone(), + "Bar".into(), + vec![StructMember::new( + "foo".into(), + Type::Struct(StructType::new( + module_id, + "Foo".into(), + vec![StructMember::new("foo".into(), Type::FieldElement)] + )) + )] + )) ); } @@ -3840,8 +3885,8 @@ mod tests { symbols: vec![SymbolDeclaration { id: "Bar", symbol: Symbol::HereType( - StructType { - fields: vec![StructField { + StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::User("Foo".into()).mock(), } @@ -3871,8 +3916,8 @@ mod tests { symbols: vec![SymbolDeclaration { id: "Foo", symbol: Symbol::HereType( - StructType { - fields: vec![StructField { + StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::User("Foo".into()).mock(), } @@ -3904,8 +3949,8 @@ mod tests { SymbolDeclaration { id: "Foo", symbol: Symbol::HereType( - StructType { - fields: vec![StructField { + StructDefinition { + fields: vec![StructDefinitionField { id: "bar", ty: UnresolvedType::User("Bar".into()).mock(), } @@ -3918,8 +3963,8 @@ mod tests { SymbolDeclaration { id: "Bar", symbol: Symbol::HereType( - StructType { - fields: vec![StructField { + StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::User("Foo".into()).mock(), } @@ -3951,8 +3996,8 @@ mod tests { // an undefined type cannot be checked // Bar - let (checker, state) = create_module_with_foo(StructType { - fields: vec![StructField { + let (checker, state) = create_module_with_foo(StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } @@ -3965,10 +4010,11 @@ mod tests { &PathBuf::from(MODULE_ID).into(), &state.types ), - Ok(Type::Struct(vec![StructMember::new( - "foo".into(), - Type::FieldElement - )])) + Ok(Type::Struct(StructType::new( + "".into(), + "Foo".into(), + vec![StructMember::new("foo".into(), Type::FieldElement)] + ))) ); assert_eq!( @@ -3990,8 +4036,8 @@ mod tests { // an undefined type cannot be used as parameter - let (checker, state) = create_module_with_foo(StructType { - fields: vec![StructField { + let (checker, state) = create_module_with_foo(StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } @@ -4013,7 +4059,11 @@ mod tests { Ok(Parameter { id: Variable::with_id_and_type( "a".into(), - Type::Struct(vec![StructMember::new("foo".into(), Type::FieldElement)]) + Type::Struct(StructType::new( + "".into(), + "Foo".into(), + vec![StructMember::new("foo".into(), Type::FieldElement)] + )) ), private: true }) @@ -4046,8 +4096,8 @@ mod tests { // an undefined type cannot be used in a variable declaration - let (mut checker, state) = create_module_with_foo(StructType { - fields: vec![StructField { + let (mut checker, state) = create_module_with_foo(StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } @@ -4066,7 +4116,11 @@ mod tests { ), Ok(TypedStatement::Declaration(Variable::with_id_and_type( "a".into(), - Type::Struct(vec![StructMember::new("foo".into(), Type::FieldElement)]) + Type::Struct(StructType::new( + "".into(), + "Foo".into(), + vec![StructMember::new("foo".into(), Type::FieldElement)] + )) ))) ); @@ -4103,8 +4157,8 @@ mod tests { // struct Foo = { foo: field } // Foo { foo: 42 }.foo - let (mut checker, state) = create_module_with_foo(StructType { - fields: vec![StructField { + let (mut checker, state) = create_module_with_foo(StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } @@ -4133,7 +4187,11 @@ mod tests { Bn128Field::from(42) ) .into()]) - .annotate(vec![StructMember::new("foo".into(), Type::FieldElement)]), + .annotate(StructType::new( + "".into(), + "Foo".into(), + vec![StructMember::new("foo".into(), Type::FieldElement)] + )), "foo".into() ) .into()) @@ -4147,8 +4205,8 @@ mod tests { // struct Foo = { foo: field } // Foo { foo: 42 }.bar - let (mut checker, state) = create_module_with_foo(StructType { - fields: vec![StructField { + let (mut checker, state) = create_module_with_foo(StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } @@ -4188,8 +4246,8 @@ mod tests { fn wrong_name() { // 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 { - fields: vec![StructField { + let (mut checker, state) = create_module_with_foo(StructDefinition { + fields: vec![StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } @@ -4223,14 +4281,14 @@ mod tests { // struct Foo = { foo: field, bar: bool } // 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![ - StructField { + StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } .mock(), - StructField { + StructDefinitionField { id: "bar", ty: UnresolvedType::Boolean.mock(), } @@ -4258,10 +4316,14 @@ mod tests { FieldElementExpression::Number(Bn128Field::from(42)).into(), BooleanExpression::Value(true).into() ]) - .annotate(vec![ - StructMember::new("foo".into(), Type::FieldElement), - StructMember::new("bar".into(), Type::Boolean) - ]) + .annotate(StructType::new( + "".into(), + "Foo".into(), + vec![ + StructMember::new("foo".into(), Type::FieldElement), + StructMember::new("bar".into(), Type::Boolean) + ] + )) .into()) ); } @@ -4273,14 +4335,14 @@ mod tests { // struct Foo = { foo: field, bar: bool } // 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![ - StructField { + StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } .mock(), - StructField { + StructDefinitionField { id: "bar", ty: UnresolvedType::Boolean.mock(), } @@ -4308,10 +4370,14 @@ mod tests { FieldElementExpression::Number(Bn128Field::from(42)).into(), BooleanExpression::Value(true).into() ]) - .annotate(vec![ - StructMember::new("foo".into(), Type::FieldElement), - StructMember::new("bar".into(), Type::Boolean) - ]) + .annotate(StructType::new( + "".into(), + "Foo".into(), + vec![ + StructMember::new("foo".into(), Type::FieldElement), + StructMember::new("bar".into(), Type::Boolean) + ] + )) .into()) ); } @@ -4323,14 +4389,14 @@ mod tests { // struct Foo = { foo: field, bar: bool } // 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![ - StructField { + StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } .mock(), - StructField { + StructDefinitionField { id: "bar", ty: UnresolvedType::Boolean.mock(), } @@ -4367,14 +4433,14 @@ mod tests { // Foo { foo: 42, baz: bool } // 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![ - StructField { + StructDefinitionField { id: "foo", ty: UnresolvedType::FieldElement.mock(), } .mock(), - StructField { + StructDefinitionField { id: "bar", ty: UnresolvedType::Boolean.mock(), } diff --git a/zokrates_core/src/static_analysis/constrain_inputs.rs b/zokrates_core/src/static_analysis/constrain_inputs.rs index a0729f09..4253d2e6 100644 --- a/zokrates_core/src/static_analysis/constrain_inputs.rs +++ b/zokrates_core/src/static_analysis/constrain_inputs.rs @@ -83,7 +83,7 @@ impl<'ast, T: Field> InputConstrainer<'ast, T> { } } TypedExpression::Struct(s) => { - for member in s.ty() { + for member in s.ty().iter() { let e = match *member.ty { Type::FieldElement => { FieldElementExpression::member(s.clone(), member.id.clone()).into() diff --git a/zokrates_core/src/static_analysis/inline.rs b/zokrates_core/src/static_analysis/inline.rs index a85e8105..268f5a57 100644 --- a/zokrates_core/src/static_analysis/inline.rs +++ b/zokrates_core/src/static_analysis/inline.rs @@ -17,7 +17,7 @@ //! where any call in `main` must be to `_SHA_256_ROUND` or `_UNPACK` use std::collections::HashMap; -use typed_absy::types::{FunctionKey, StructMember, Type}; +use typed_absy::types::{FunctionKey, Type}; use typed_absy::{folder::*, *}; use zokrates_field::Field; @@ -371,7 +371,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { fn fold_struct_expression_inner( &mut self, - ty: &Vec, + ty: &StructType, e: StructExpressionInner<'ast, T>, ) -> StructExpressionInner<'ast, T> { match e { diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 0d87a654..b3935c2d 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -14,7 +14,7 @@ use crate::typed_absy::folder::*; use crate::typed_absy::*; use std::collections::HashMap; use std::convert::TryFrom; -use typed_absy::types::{StructMember, Type}; +use typed_absy::types::Type; use zokrates_field::Field; pub struct Propagator<'ast, T: Field> { @@ -405,7 +405,7 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> { fn fold_struct_expression_inner( &mut self, - ty: &Vec, + ty: &StructType, e: StructExpressionInner<'ast, T>, ) -> StructExpressionInner<'ast, T> { match e { diff --git a/zokrates_core/src/typed_absy/abi.rs b/zokrates_core/src/typed_absy/abi.rs index f80f0f01..262b4f63 100644 --- a/zokrates_core/src/typed_absy/abi.rs +++ b/zokrates_core/src/typed_absy/abi.rs @@ -147,15 +147,23 @@ mod tests { inputs: vec![AbiInput { name: String::from("foo"), 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("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(); @@ -167,31 +175,37 @@ mod tests { "name": "foo", "public": true, "type": "struct", - "components": [ - { - "name": "a", - "type": "field" - }, - { - "name": "b", - "type": "bool" - } - ] + "components": { + "name": "Foo", + "members": [ + { + "name": "a", + "type": "field" + }, + { + "name": "b", + "type": "bool" + } + ] + } } ], "outputs": [ { "type": "struct", - "components": [ - { - "name": "a", - "type": "field" - }, - { - "name": "b", - "type": "bool" - } - ] + "components": { + "name": "Foo", + "members": [ + { + "name": "a", + "type": "field" + }, + { + "name": "b", + "type": "bool" + } + ] + } } ] }"# @@ -204,13 +218,21 @@ mod tests { inputs: vec![AbiInput { name: String::from("foo"), public: true, - ty: Type::Struct(vec![StructMember::new( - String::from("bar"), - Type::Struct(vec![ - StructMember::new(String::from("a"), Type::FieldElement), - StructMember::new(String::from("b"), Type::FieldElement), - ]), - )]), + ty: Type::Struct(StructType::new( + "".into(), + "Foo".into(), + vec![StructMember::new( + 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![], }; @@ -224,22 +246,28 @@ mod tests { "name": "foo", "public": true, "type": "struct", - "components": [ - { - "name": "bar", - "type": "struct", - "components": [ - { - "name": "a", - "type": "field" - }, - { - "name": "b", - "type": "field" + "components": { + "name": "Foo", + "members": [ + { + "name": "bar", + "type": "struct", + "components": { + "name": "Bar", + "members": [ + { + "name": "a", + "type": "field" + }, + { + "name": "b", + "type": "field" + } + ] } - ] - } - ] + } + ] + } } ], "outputs": [] @@ -254,10 +282,14 @@ mod tests { name: String::from("a"), public: false, ty: Type::Array(ArrayType::new( - Type::Struct(vec![ - StructMember::new(String::from("b"), Type::FieldElement), - StructMember::new(String::from("c"), Type::Boolean), - ]), + Type::Struct(StructType::new( + "".into(), + "Foo".into(), + vec![ + StructMember::new(String::from("b"), Type::FieldElement), + StructMember::new(String::from("c"), Type::Boolean), + ], + )), 2, )), }], @@ -276,16 +308,19 @@ mod tests { "components": { "size": 2, "type": "struct", - "components": [ - { - "name": "b", - "type": "field" - }, - { - "name": "c", - "type": "bool" - } - ] + "components": { + "name": "Foo", + "members": [ + { + "name": "b", + "type": "field" + }, + { + "name": "c", + "type": "bool" + } + ] + } } } ], diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_core/src/typed_absy/folder.rs index edcad635..892c63bd 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_core/src/typed_absy/folder.rs @@ -1,7 +1,6 @@ // Generic walk through a typed AST. Not mutating in place use crate::typed_absy::*; -use typed_absy::types::StructMember; use zokrates_field::Field; pub trait Folder<'ast, T: Field>: Sized { @@ -117,7 +116,7 @@ pub trait Folder<'ast, T: Field>: Sized { } fn fold_struct_expression_inner( &mut self, - ty: &Vec, + ty: &StructType, e: StructExpressionInner<'ast, T>, ) -> StructExpressionInner<'ast, T> { fold_struct_expression_inner(self, ty, e) @@ -209,7 +208,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, - _: &Vec, + _: &StructType, e: StructExpressionInner<'ast, T>, ) -> StructExpressionInner<'ast, T> { match e { diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index aa1c8c46..9a4ee861 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -13,7 +13,7 @@ pub mod types; mod variable; pub use crate::typed_absy::parameter::Parameter; -pub use crate::typed_absy::types::{Signature, Type}; +pub use crate::typed_absy::types::{Signature, StructType, Type}; pub use crate::typed_absy::variable::Variable; use std::path::PathBuf; @@ -27,7 +27,6 @@ use zokrates_field::Field; pub use self::folder::Folder; use typed_absy::abi::{Abi, AbiInput}; pub use typed_absy::identifier::Identifier; -use typed_absy::types::StructMember; /// An identifier for a `TypedModule`. Typically a path or uri. pub type TypedModuleId = PathBuf; @@ -708,12 +707,12 @@ impl<'ast, T> ArrayExpression<'ast, T> { #[derive(Clone, PartialEq, Hash, Eq)] pub struct StructExpression<'ast, T> { - ty: Vec, + ty: StructType, inner: StructExpressionInner<'ast, T>, } impl<'ast, T> StructExpression<'ast, T> { - pub fn ty(&self) -> &Vec { + pub fn ty(&self) -> &StructType { &self.ty } @@ -744,7 +743,7 @@ pub enum StructExpressionInner<'ast, T> { } impl<'ast, T> StructExpressionInner<'ast, T> { - pub fn annotate(self, ty: Vec) -> StructExpression<'ast, T> { + pub fn annotate(self, ty: StructType) -> StructExpression<'ast, T> { StructExpression { ty, inner: self } } } diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index 9dc1583e..330bab0d 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::path::PathBuf; pub type Identifier<'ast> = &'ast str; @@ -19,6 +20,41 @@ pub struct ArrayType { pub ty: Box, } +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +pub struct StructType { + #[serde(skip)] + pub module: PathBuf, + pub name: String, + pub members: Vec, +} + +impl StructType { + pub fn new(module: PathBuf, name: String, members: Vec) -> Self { + StructType { + module, + name, + members, + } + } + + pub fn len(&self) -> usize { + self.members.len() + } + + pub fn iter(&self) -> std::slice::Iter { + self.members.iter() + } +} + +impl IntoIterator for StructType { + type Item = StructMember; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.members.into_iter() + } +} + #[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] #[serde(tag = "type", content = "components")] pub enum Type { @@ -29,7 +65,7 @@ pub enum Type { #[serde(rename = "array")] Array(ArrayType), #[serde(rename = "struct")] - Struct(Vec), + Struct(StructType), } impl ArrayType { @@ -56,10 +92,12 @@ impl fmt::Display for Type { Type::FieldElement => write!(f, "field"), Type::Boolean => write!(f, "bool"), 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, - "{{{}}}", - members + "{} {{{}}}", + struct_type.name, + struct_type + .members .iter() .map(|member| format!("{}: {}", member.id, member.ty)) .collect::>() @@ -75,10 +113,12 @@ impl fmt::Debug for Type { Type::FieldElement => write!(f, "field"), Type::Boolean => write!(f, "bool"), 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, - "{{{}}}", - members + "{} {{{}}}", + struct_type.name, + struct_type + .members .iter() .map(|member| format!("{}: {}", member.id, member.ty)) .collect::>() @@ -98,9 +138,9 @@ impl Type { Type::FieldElement => String::from("f"), Type::Boolean => String::from("b"), 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() .map(|member| format!("{}:{}", member.id, member.ty)) .collect::>() @@ -115,7 +155,7 @@ impl Type { Type::FieldElement => 1, Type::Boolean => 1, Type::Array(array_type) => array_type.size * array_type.ty.get_primitive_count(), - Type::Struct(members) => members + Type::Struct(struct_type) => struct_type .iter() .map(|member| member.ty.get_primitive_count()) .sum(), diff --git a/zokrates_core/src/typed_absy/variable.rs b/zokrates_core/src/typed_absy/variable.rs index eb11caf6..68fa49ad 100644 --- a/zokrates_core/src/typed_absy/variable.rs +++ b/zokrates_core/src/typed_absy/variable.rs @@ -1,7 +1,7 @@ use crate::typed_absy::types::Type; use crate::typed_absy::Identifier; use std::fmt; -use typed_absy::types::StructMember; +use typed_absy::types::StructType; #[derive(Clone, PartialEq, Hash, Eq)] pub struct Variable<'ast> { @@ -27,7 +27,7 @@ impl<'ast> Variable<'ast> { Self::with_id_and_type(id, Type::array(ty, size)) } - pub fn struc(id: Identifier<'ast>, ty: Vec) -> Variable<'ast> { + pub fn struc(id: Identifier<'ast>, ty: StructType) -> Variable<'ast> { Self::with_id_and_type(id, Type::Struct(ty)) } From ca8acfd11ef398cef9f24ab143803917f20fa79d Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 14 May 2020 23:22:57 +0200 Subject: [PATCH 3/8] fix tests --- zokrates_core/src/semantics.rs | 12 +++++------- zokrates_core/src/typed_absy/abi.rs | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index f34ade74..7cb09990 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -1839,9 +1839,8 @@ impl<'ast> Checker<'ast> { return Err(ErrorInner { pos: Some(pos), message: format!( - "Inline struct {} does not match {} : {}", + "Inline struct {} does not match {}", Expression::InlineStruct(id.clone(), inline_members), - id, Type::Struct(struct_type) ), }); @@ -1883,9 +1882,8 @@ impl<'ast> Checker<'ast> { return Err(ErrorInner { pos: Some(pos), message: format!( - "Member {} of struct {} : {} not found in value {}", + "Member {} of struct {} not found in value {}", member.id, - id.clone(), Type::Struct(struct_type.clone()), Expression::InlineStruct(id.clone(), inline_members), ), @@ -4233,7 +4231,7 @@ mod tests { ) .unwrap_err() .message, - "{foo: field} doesn\'t have member bar" + "Foo {foo: field} doesn\'t have member bar" ); } } @@ -4420,7 +4418,7 @@ mod tests { ) .unwrap_err() .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}" ); } @@ -4466,7 +4464,7 @@ mod tests { &state.types ).unwrap_err() .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!( diff --git a/zokrates_core/src/typed_absy/abi.rs b/zokrates_core/src/typed_absy/abi.rs index 262b4f63..3ad35cc6 100644 --- a/zokrates_core/src/typed_absy/abi.rs +++ b/zokrates_core/src/typed_absy/abi.rs @@ -30,7 +30,7 @@ impl Abi { mod tests { use super::*; use std::collections::HashMap; - use typed_absy::types::{ArrayType, FunctionKey, StructMember}; + use typed_absy::types::{ArrayType, FunctionKey, StructMember, StructType}; use typed_absy::{ Parameter, Type, TypedFunction, TypedFunctionSymbol, TypedModule, TypedProgram, Variable, }; From 8e332cc9da5fcea516438c98af12050865ef77e7 Mon Sep 17 00:00:00 2001 From: schaeff Date: Fri, 15 May 2020 12:56:17 +0200 Subject: [PATCH 4/8] fix wrong name in imported structs, make name in imported struct the alias, not the source --- zokrates_core/src/semantics.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 7cb09990..b860d73d 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -326,7 +326,7 @@ impl<'ast> Checker<'ast> { let pos = declaration.pos(); let declaration = declaration.value; - match declaration.symbol { + match declaration.symbol.clone() { Symbol::HereType(t) => { match self.check_struct_type_declaration( declaration.id.to_string(), @@ -394,6 +394,8 @@ impl<'ast> Checker<'ast> { let pos = import.pos(); let import = import.value; + println!("{:?}", declaration); + match Checker::new().check_module(&import.module_id, state) { Ok(()) => { // find candidates in the checked module @@ -420,6 +422,21 @@ impl<'ast> Checker<'ast> { match (function_candidates.len(), type_candidate) { (0, Some(t)) => { + + println!("before {:?}", 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!() + }; + + println!("after {:?}", t); + // we imported a type, so the symbol it gets bound to should not already exist match symbol_unifier.insert_type(declaration.id) { false => { @@ -439,7 +456,7 @@ impl<'ast> Checker<'ast> { .types .entry(module_id.clone()) .or_default() - .insert(import.symbol_id.to_string(), t.clone()); + .insert(declaration.id.to_string(), t.clone()); } (0, None) => { errors.push(ErrorInner { From c488d90b110939869f2763c47b55b6d1b2b80c7e Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 18 May 2020 16:05:04 +0200 Subject: [PATCH 5/8] make resolved types equivalent, default from-import alias to symbol --- zokrates_core/src/absy/from_ast.rs | 7 ++++++- zokrates_core/src/semantics.rs | 6 ------ zokrates_core/src/typed_absy/types.rs | 10 +++++++++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/zokrates_core/src/absy/from_ast.rs b/zokrates_core/src/absy/from_ast.rs index 4fd1abfa..ca7dba19 100644 --- a/zokrates_core/src/absy/from_ast.rs +++ b/zokrates_core/src/absy/from_ast.rs @@ -33,7 +33,12 @@ impl<'ast> From> for absy::ImportNode<'ast> { Some(import.symbol.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), } } diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index b860d73d..c0d5e489 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -394,8 +394,6 @@ impl<'ast> Checker<'ast> { let pos = import.pos(); let import = import.value; - println!("{:?}", declaration); - match Checker::new().check_module(&import.module_id, state) { Ok(()) => { // find candidates in the checked module @@ -423,8 +421,6 @@ impl<'ast> Checker<'ast> { match (function_candidates.len(), type_candidate) { (0, Some(t)) => { - println!("before {:?}", t); - // rename the type to the declared symbol let t = match t { Type::Struct(t) => Type::Struct(StructType { @@ -435,8 +431,6 @@ impl<'ast> Checker<'ast> { _ => unreachable!() }; - println!("after {:?}", t); - // we imported a type, so the symbol it gets bound to should not already exist match symbol_unifier.insert_type(declaration.id) { false => { diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index 330bab0d..ea22a590 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -20,7 +20,7 @@ pub struct ArrayType { pub ty: Box, } -#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Clone, Hash, Serialize, Deserialize, PartialOrd, Ord)] pub struct StructType { #[serde(skip)] pub module: PathBuf, @@ -28,6 +28,14 @@ pub struct StructType { pub members: Vec, } +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) -> Self { StructType { From 2abb0ead20e30dc5fe31753f85d35f6b9e1d26b0 Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 18 May 2020 17:04:48 +0200 Subject: [PATCH 6/8] disable format --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 27511643..ecf45c41 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,9 +42,9 @@ jobs: - restore_cache: keys: - v4-cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }} - - run: - name: Check format - command: rustup component add rustfmt; cargo fmt --all -- --check + # - run: + # name: Check format + # command: rustup component add rustfmt; cargo fmt --all -- --check - run: name: Install libsnark prerequisites command: ./scripts/install_libsnark_prerequisites.sh From b65c49da54fc3a50d4b2535e55e940030b1ef590 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 19 May 2020 15:31:38 +0200 Subject: [PATCH 7/8] add test for struct abi --- zokrates_core/src/compile.rs | 107 +++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/zokrates_core/src/compile.rs b/zokrates_core/src/compile.rs index 0ab8209c..5c3601b4 100644 --- a/zokrates_core/src/compile.rs +++ b/zokrates_core/src/compile.rs @@ -263,4 +263,111 @@ mod test { ); 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 Resolver 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::( + 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![] + } + ); + } + } } From 1dc34e2b7f43f12bdccf1956cfa5bb37517488f5 Mon Sep 17 00:00:00 2001 From: schaeff Date: Tue, 19 May 2020 19:27:21 +0200 Subject: [PATCH 8/8] update docs --- zokrates_book/src/reference/abi.md | 123 ++++++++++++++--------------- zokrates_cli/examples/book/abi.zok | 11 +++ 2 files changed, 71 insertions(+), 63 deletions(-) create mode 100644 zokrates_cli/examples/book/abi.zok diff --git a/zokrates_book/src/reference/abi.md b/zokrates_book/src/reference/abi.md index bfd03c05..0e0c9b07 100644 --- a/zokrates_book/src/reference/abi.md +++ b/zokrates_book/src/reference/abi.md @@ -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: ``` -struct Bar { - field a -} - -struct Foo { - field a - Bar b -} - -def main(private Foo foo, bool[2] bar, field num) -> (field): - return 42 +{{#include ../../../zokrates_cli/examples/book/abi.zok}} ``` ## ABI specification @@ -26,48 +16,54 @@ In this example, the ABI specification is: ```json { - "inputs": [ - { - "name": "foo", - "public": false, - "type": "struct", - "components": [ - { - "name": "a", - "type": "field" - }, - { - "name": "b", - "type": "struct", - "components": [ + "inputs":[ + { + "name":"foo", + "public":true, + "type":"struct", + "components":{ + "name":"Foo", + "members":[ + { + "name":"a", + "type":"field" + }, + { + "name":"b", + "type":"struct", + "components":{ + "name":"Bar", + "members":[ { - "name": "a", - "type": "field" + "name":"a", + "type":"field" } - ] - } + ] + } + } ] - }, - { - "name": "bar", - "public": "true", - "type": "array", - "components": { - "size": 2, - "type": "bool" - } - }, - { - "name": "num", - "public": "true", - "type": "field" - } - ], - "outputs": [ - { - "type": "field" - } - ] + } + }, + { + "name":"bar", + "public":true, + "type":"array", + "components":{ + "size":2, + "type":"bool" + } + }, + { + "name":"num", + "public":true, + "type":"field" + } + ], + "outputs":[ + { + "type":"field" + } + ] } ``` @@ -78,19 +74,20 @@ When executing a program, arguments can be passed as a JSON object of the follow ```json [ - { - "a": "42", - "b": - { - "a": "42" - } - }, - [ - true, - false - ], - "42" + { + "a":"42", + "b":{ + "a":"42" + } + }, + [ + true, + false + ], + "42" ] ``` -Note that field elements are passed as JSON strings in order to support arbitrary large numbers. \ No newline at end of file +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 \ No newline at end of file diff --git a/zokrates_cli/examples/book/abi.zok b/zokrates_cli/examples/book/abi.zok new file mode 100644 index 00000000..84969792 --- /dev/null +++ b/zokrates_cli/examples/book/abi.zok @@ -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 \ No newline at end of file