From 90513aa745f370fefb98190a2f63bb491f09fa2c Mon Sep 17 00:00:00 2001 From: schaeff Date: Mon, 28 Sep 2020 15:20:51 +0200 Subject: [PATCH 1/4] update generated pedersen --- .../stdlib/hashes/pedersen/512bit.zok | 64 ++++++++++--------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/zokrates_stdlib/stdlib/hashes/pedersen/512bit.zok b/zokrates_stdlib/stdlib/hashes/pedersen/512bit.zok index ec5be80c..65d317af 100644 --- a/zokrates_stdlib/stdlib/hashes/pedersen/512bit.zok +++ b/zokrates_stdlib/stdlib/hashes/pedersen/512bit.zok @@ -1,3 +1,4 @@ + import "utils/multiplexer/lookup3bitSigned" as sel3s import "utils/multiplexer/lookup2bit" as sel2 import "ecc/babyjubjubParams" as context @@ -15,35 +16,38 @@ import "EMBED/u32_from_bits" as from_bits // #%% // entropy = np.random.bytes(64) // hasher = PedersenHasher("test") +// hasher.hash_bytes(entropy) // print(hasher.dsl_code) -// 512bit to 256bit Pedersen hash using compression of the field elements -def main(u32[16] input) -> u32[8]: - - bool[512] e = [ \ - ...to_bits(input[0]), - ...to_bits(input[1]), - ...to_bits(input[2]), - ...to_bits(input[3]), - ...to_bits(input[4]), - ...to_bits(input[5]), - ...to_bits(input[6]), - ...to_bits(input[7]), - ...to_bits(input[8]), - ...to_bits(input[9]), - ...to_bits(input[10]), - ...to_bits(input[11]), - ...to_bits(input[12]), - ...to_bits(input[13]), - ...to_bits(input[14]), - ...to_bits(input[15]) +def main(u32[16] inputs) -> u32[8]: + bool[513] e = [\ + ...to_bits(inputs[0]), + ...to_bits(inputs[1]), + ...to_bits(inputs[2]), + ...to_bits(inputs[3]), + ...to_bits(inputs[4]), + ...to_bits(inputs[5]), + ...to_bits(inputs[6]), + ...to_bits(inputs[7]), + ...to_bits(inputs[8]), + ...to_bits(inputs[9]), + ...to_bits(inputs[10]), + ...to_bits(inputs[11]), + ...to_bits(inputs[12]), + ...to_bits(inputs[13]), + ...to_bits(inputs[14]), + ...to_bits(inputs[15]), + false ] BabyJubJubParams context = context() field[2] a = context.INFINITY //Infinity + field cx = 0 + field cy = 0 + //Round 0 - field cx = sel3s([e[0], e[1], e[2]], [13418723823902222986275588345615650707197303761863176429873001977640541977977 , 8366451672790208592553809639953117385619257483837439526516290319251622927412, 1785026334726838136757054176272745265857971873904476677125553010508875025629, 15763987975760561753692294837740043971877392788040801334205375164715487005236]) - field cy = sel2([e[0], e[1]], [15255921313433251341520743036334816584226787412845488772781699434149539664639 , 10916775373885716961512013142444429405184550001421868906213743991404593770484, 18533662942827602783563125901366807026309605479742251601915445402562880550265, 12754584346112149619040942896930712185968371085994381911052593922432846916845]) + cx = sel3s([e[0], e[1], e[2]], [13418723823902222986275588345615650707197303761863176429873001977640541977977 , 8366451672790208592553809639953117385619257483837439526516290319251622927412, 1785026334726838136757054176272745265857971873904476677125553010508875025629, 15763987975760561753692294837740043971877392788040801334205375164715487005236]) + cy = sel2([e[0], e[1]], [15255921313433251341520743036334816584226787412845488772781699434149539664639 , 10916775373885716961512013142444429405184550001421868906213743991404593770484, 18533662942827602783563125901366807026309605479742251601915445402562880550265, 12754584346112149619040942896930712185968371085994381911052593922432846916845]) a = add(a, [cx, cy], context) //Round 1 cx = sel3s([e[3], e[4], e[5]], [10096735692467598736728394557736034054031417419721869067082824451240861468728 , 6979151010236415881632946866847657030447196774231162748523315765559549846746, 12137947022495312670974525048647679757468392619153927921382150023166867027471, 10624360821702266736197468438435445939719745367234393212061381062942588576905]) @@ -722,19 +726,19 @@ def main(u32[16] input) -> u32[8]: cy = sel2([e[507], e[508]], [18191174947339798787646910619446409943766046946921136035021645191602921923040 , 16559060177998758852323304784771936179434931576336411584121379336820727372618, 13858115732979799183025726471151602712224733686530960054365665740611187232029, 9933192519609817862698304326029579651414877338671776883175639003837130283966]) a = add(a, [cx, cy], context) //Round 170 - cx = sel3s([e[510], e[511], false], [3342564788366736273905106071612128667477972061160313630133110787799686301495 , 13766193863701503939885263345152684798552605679140222504700163745347162493183, 18523279471468319520962369406962457727155204375043681943707151819380964978377, 8094164074569624021939357073285075790695279643883973800173037824312344195506]) + cx = sel3s([e[510], e[511], e[512]], [3342564788366736273905106071612128667477972061160313630133110787799686301495 , 13766193863701503939885263345152684798552605679140222504700163745347162493183, 18523279471468319520962369406962457727155204375043681943707151819380964978377, 8094164074569624021939357073285075790695279643883973800173037824312344195506]) cy = sel2([e[510], e[511]], [2329094643034533408459502544740928833981119919633412709248656884170940780093 , 3216329736050668550647765981020076413548845117352735257893224753954595290363, 18710403072495673647060422294369054840513840567808020912157404388689648711093, 9785201456176703812798077455183487364035650707229293534561747881523562553649]) a = add(a, [cx, cy], context) bool[256] aC = edwardsCompress(a) return [\ - from_bits(aC[0..32]), - from_bits(aC[32..64]), - from_bits(aC[64..96]), - from_bits(aC[96..128]), - from_bits(aC[128..160]), - from_bits(aC[160..192]), - from_bits(aC[192..224]), + from_bits(aC[0..32]), + from_bits(aC[32..64]), + from_bits(aC[64..96]), + from_bits(aC[96..128]), + from_bits(aC[128..160]), + from_bits(aC[160..192]), + from_bits(aC[192..224]), from_bits(aC[224..256]) ] From 6c966e8f92e3dbbed226b4f8d6fa48b9af4997e9 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 1 Oct 2020 14:44:23 +0200 Subject: [PATCH 2/4] stop encoding call identifier with ssa version --- zokrates_core/src/static_analysis/inline.rs | 65 +++++++++++++-------- zokrates_core/src/typed_absy/identifier.rs | 4 +- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/zokrates_core/src/static_analysis/inline.rs b/zokrates_core/src/static_analysis/inline.rs index 3962711e..777ad4bc 100644 --- a/zokrates_core/src/static_analysis/inline.rs +++ b/zokrates_core/src/static_analysis/inline.rs @@ -351,11 +351,14 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { Err((key, expressions)) => { let tys = key.signature.outputs.clone(); let id = Identifier { - id: CoreIdentifier::Call(key.clone()), - version: *self - .call_count - .get(&(self.module_id().clone(), key.clone())) - .unwrap(), + id: CoreIdentifier::Call( + key.clone(), + *self + .call_count + .get(&(self.module_id().clone(), key.clone())) + .unwrap(), + ), + version: 0, stack: self.stack.clone(), }; self.statement_buffer @@ -388,11 +391,14 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { Err((key, expressions)) => { let tys = key.signature.outputs.clone(); let id = Identifier { - id: CoreIdentifier::Call(key.clone()), - version: *self - .call_count - .get(&(self.module_id().clone(), key.clone())) - .unwrap(), + id: CoreIdentifier::Call( + key.clone(), + *self + .call_count + .get(&(self.module_id().clone(), key.clone())) + .unwrap(), + ), + version: 0, stack: self.stack.clone(), }; self.statement_buffer @@ -440,11 +446,14 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { Err((embed_key, expressions)) => { let tys = key.signature.outputs.clone(); let id = Identifier { - id: CoreIdentifier::Call(key.clone()), - version: *self - .call_count - .get(&(self.module_id().clone(), embed_key.clone())) - .unwrap(), + id: CoreIdentifier::Call( + key.clone(), + *self + .call_count + .get(&(self.module_id().clone(), key.clone())) + .unwrap(), + ), + version: 0, stack: self.stack.clone(), }; self.statement_buffer @@ -493,11 +502,14 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { Err((key, expressions)) => { let tys = key.signature.outputs.clone(); let id = Identifier { - id: CoreIdentifier::Call(key.clone()), - version: *self - .call_count - .get(&(self.module_id().clone(), key.clone())) - .unwrap(), + id: CoreIdentifier::Call( + key.clone(), + *self + .call_count + .get(&(self.module_id().clone(), key.clone())) + .unwrap(), + ), + version: 0, stack: self.stack.clone(), }; self.statement_buffer @@ -531,11 +543,14 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { Err((embed_key, expressions)) => { let tys = key.signature.outputs.clone(); let id = Identifier { - id: CoreIdentifier::Call(key.clone()), - version: *self - .call_count - .get(&(self.module_id().clone(), embed_key.clone())) - .unwrap(), + id: CoreIdentifier::Call( + key.clone(), + *self + .call_count + .get(&(self.module_id().clone(), key.clone())) + .unwrap(), + ), + version: 0, stack: self.stack.clone(), }; self.statement_buffer diff --git a/zokrates_core/src/typed_absy/identifier.rs b/zokrates_core/src/typed_absy/identifier.rs index a22defd2..979536bb 100644 --- a/zokrates_core/src/typed_absy/identifier.rs +++ b/zokrates_core/src/typed_absy/identifier.rs @@ -6,7 +6,7 @@ use typed_absy::TypedModuleId; pub enum CoreIdentifier<'ast> { Source(&'ast str), Internal(&'static str, usize), - Call(FunctionKey<'ast>), + Call(FunctionKey<'ast>, usize), } impl<'ast> fmt::Display for CoreIdentifier<'ast> { @@ -14,7 +14,7 @@ impl<'ast> fmt::Display for CoreIdentifier<'ast> { match self { CoreIdentifier::Source(s) => write!(f, "{}", s), CoreIdentifier::Internal(s, i) => write!(f, "#INTERNAL#_{}_{}", s, i), - CoreIdentifier::Call(k) => write!(f, "{}", k.to_slug()), + CoreIdentifier::Call(k, i) => write!(f, "{}_{}", k.to_slug(), i), } } } From a9e42c40daae36e3fc467fc57ba230fc606f075e Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 1 Oct 2020 16:17:21 +0200 Subject: [PATCH 3/4] implement caching, move call count --- zokrates_core/src/static_analysis/inline.rs | 72 ++++++++++++++------- zokrates_core/src/static_analysis/mod.rs | 1 + 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/zokrates_core/src/static_analysis/inline.rs b/zokrates_core/src/static_analysis/inline.rs index 777ad4bc..f86d6186 100644 --- a/zokrates_core/src/static_analysis/inline.rs +++ b/zokrates_core/src/static_analysis/inline.rs @@ -234,15 +234,7 @@ impl<'ast, T: Field> Inliner<'ast, T> { Ok(res) } // if the function is a flat symbol, replace the call with a call to the local function we provide so it can be inlined in flattening - TypedFunctionSymbol::Flat(embed) => { - // increase the number of calls for this function by one - let _ = self - .call_count - .entry((self.module_id().clone(), embed.key::().clone())) - .and_modify(|i| *i += 1) - .or_insert(1); - Err((embed.key::(), expressions.clone())) - } + TypedFunctionSymbol::Flat(embed) => Err((embed.key::(), expressions.clone())), }; res.map(|exprs| { @@ -348,15 +340,16 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { TypedExpression::FieldElement(e) => e, _ => unreachable!(), }, - Err((key, expressions)) => { + Err((embed_key, expressions)) => { let tys = key.signature.outputs.clone(); let id = Identifier { id: CoreIdentifier::Call( key.clone(), *self .call_count - .get(&(self.module_id().clone(), key.clone())) - .unwrap(), + .entry((self.module_id().clone(), embed_key.clone())) + .and_modify(|i| *i += 1) + .or_insert(1), ), version: 0, stack: self.stack.clone(), @@ -364,8 +357,21 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { self.statement_buffer .push(TypedStatement::MultipleDefinition( vec![Variable::with_id_and_type(id.clone(), tys[0].clone())], - TypedExpressionList::FunctionCall(key, expressions, tys), + TypedExpressionList::FunctionCall( + key.clone(), + expressions.clone(), + tys, + ), )); + + self.call_cache_mut() + .entry(key.clone()) + .or_insert_with(|| HashMap::new()) + .insert( + expressions, + vec![FieldElementExpression::Identifier(id.clone()).into()], + ); + FieldElementExpression::Identifier(id) } } @@ -388,15 +394,16 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { TypedExpression::Boolean(e) => e, _ => unreachable!(), }, - Err((key, expressions)) => { + Err((embed_key, expressions)) => { let tys = key.signature.outputs.clone(); let id = Identifier { id: CoreIdentifier::Call( key.clone(), *self .call_count - .get(&(self.module_id().clone(), key.clone())) - .unwrap(), + .entry((self.module_id().clone(), embed_key.clone())) + .and_modify(|i| *i += 1) + .or_insert(1), ), version: 0, stack: self.stack.clone(), @@ -450,8 +457,9 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { key.clone(), *self .call_count - .get(&(self.module_id().clone(), key.clone())) - .unwrap(), + .entry((self.module_id().clone(), embed_key.clone())) + .and_modify(|i| *i += 1) + .or_insert(1), ), version: 0, stack: self.stack.clone(), @@ -499,15 +507,16 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { TypedExpression::Struct(e) => e.into_inner(), _ => unreachable!(), }, - Err((key, expressions)) => { + Err((embed_key, expressions)) => { let tys = key.signature.outputs.clone(); let id = Identifier { id: CoreIdentifier::Call( key.clone(), *self .call_count - .get(&(self.module_id().clone(), key.clone())) - .unwrap(), + .entry((self.module_id().clone(), embed_key.clone())) + .and_modify(|i| *i += 1) + .or_insert(1), ), version: 0, stack: self.stack.clone(), @@ -515,9 +524,21 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { self.statement_buffer .push(TypedStatement::MultipleDefinition( vec![Variable::with_id_and_type(id.clone(), tys[0].clone())], - TypedExpressionList::FunctionCall(key, expressions, tys), + TypedExpressionList::FunctionCall( + key.clone(), + expressions.clone(), + tys, + ), )); - StructExpressionInner::Identifier(id) + + let out = StructExpressionInner::Identifier(id); + + self.call_cache_mut() + .entry(key.clone()) + .or_insert_with(|| HashMap::new()) + .insert(expressions, vec![out.clone().annotate(ty.clone()).into()]); + + out } } } @@ -547,8 +568,9 @@ impl<'ast, T: Field> Folder<'ast, T> for Inliner<'ast, T> { key.clone(), *self .call_count - .get(&(self.module_id().clone(), key.clone())) - .unwrap(), + .entry((self.module_id().clone(), embed_key.clone())) + .and_modify(|i| *i += 1) + .or_insert(1), ), version: 0, stack: self.stack.clone(), diff --git a/zokrates_core/src/static_analysis/mod.rs b/zokrates_core/src/static_analysis/mod.rs index 41c67a99..c42c1b87 100644 --- a/zokrates_core/src/static_analysis/mod.rs +++ b/zokrates_core/src/static_analysis/mod.rs @@ -39,6 +39,7 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { pub fn analyse(self) -> ZirProgram<'ast, T> { // propagated unrolling let r = PropagatedUnroller::unroll(self).unwrap_or_else(|e| panic!(e)); + // return binding let r = ReturnBinder::bind(r); From 2b3183a6d3f83c844f681758acd1b3869ea71104 Mon Sep 17 00:00:00 2001 From: schaeff Date: Thu, 8 Oct 2020 10:43:14 +0200 Subject: [PATCH 4/4] fix tests of compile issues, change struct handling to make tests pass --- .../{error => compile_errors}/assert.zok | 0 .../{error => compile_errors}/empty-error.zok | 0 .../no_struct_equivalence.zok} | 0 .../out_of_for_scope.zok | 0 .../{error => compile_errors}/shadowing.zok | 0 .../compile_errors/too_many_return.zok | 2 + .../{error => compile_errors}/unassigned.zok | 0 .../wrongsyntax-error.zok | 0 .../examples/error/forbidden_power_base.zok | 2 - .../lt_overflow_p_minus_one.zok | 4 +- zokrates_cli/src/bin.rs | 15 +++--- zokrates_core/src/compile.rs | 24 +++++----- zokrates_core/src/semantics.rs | 9 ++-- zokrates_core/src/typed_absy/types.rs | 46 +++++++++++-------- 14 files changed, 57 insertions(+), 45 deletions(-) rename zokrates_cli/examples/{error => compile_errors}/assert.zok (100%) rename zokrates_cli/examples/{error => compile_errors}/empty-error.zok (100%) rename zokrates_cli/examples/{error/struct_if_else.zok => compile_errors/no_struct_equivalence.zok} (100%) rename zokrates_cli/examples/{error => compile_errors}/out_of_for_scope.zok (100%) rename zokrates_cli/examples/{error => compile_errors}/shadowing.zok (100%) create mode 100644 zokrates_cli/examples/compile_errors/too_many_return.zok rename zokrates_cli/examples/{error => compile_errors}/unassigned.zok (100%) rename zokrates_cli/examples/{error => compile_errors}/wrongsyntax-error.zok (100%) delete mode 100644 zokrates_cli/examples/error/forbidden_power_base.zok diff --git a/zokrates_cli/examples/error/assert.zok b/zokrates_cli/examples/compile_errors/assert.zok similarity index 100% rename from zokrates_cli/examples/error/assert.zok rename to zokrates_cli/examples/compile_errors/assert.zok diff --git a/zokrates_cli/examples/error/empty-error.zok b/zokrates_cli/examples/compile_errors/empty-error.zok similarity index 100% rename from zokrates_cli/examples/error/empty-error.zok rename to zokrates_cli/examples/compile_errors/empty-error.zok diff --git a/zokrates_cli/examples/error/struct_if_else.zok b/zokrates_cli/examples/compile_errors/no_struct_equivalence.zok similarity index 100% rename from zokrates_cli/examples/error/struct_if_else.zok rename to zokrates_cli/examples/compile_errors/no_struct_equivalence.zok diff --git a/zokrates_cli/examples/error/out_of_for_scope.zok b/zokrates_cli/examples/compile_errors/out_of_for_scope.zok similarity index 100% rename from zokrates_cli/examples/error/out_of_for_scope.zok rename to zokrates_cli/examples/compile_errors/out_of_for_scope.zok diff --git a/zokrates_cli/examples/error/shadowing.zok b/zokrates_cli/examples/compile_errors/shadowing.zok similarity index 100% rename from zokrates_cli/examples/error/shadowing.zok rename to zokrates_cli/examples/compile_errors/shadowing.zok diff --git a/zokrates_cli/examples/compile_errors/too_many_return.zok b/zokrates_cli/examples/compile_errors/too_many_return.zok new file mode 100644 index 00000000..8b1dec6f --- /dev/null +++ b/zokrates_cli/examples/compile_errors/too_many_return.zok @@ -0,0 +1,2 @@ +def main(): + return 1 \ No newline at end of file diff --git a/zokrates_cli/examples/error/unassigned.zok b/zokrates_cli/examples/compile_errors/unassigned.zok similarity index 100% rename from zokrates_cli/examples/error/unassigned.zok rename to zokrates_cli/examples/compile_errors/unassigned.zok diff --git a/zokrates_cli/examples/error/wrongsyntax-error.zok b/zokrates_cli/examples/compile_errors/wrongsyntax-error.zok similarity index 100% rename from zokrates_cli/examples/error/wrongsyntax-error.zok rename to zokrates_cli/examples/compile_errors/wrongsyntax-error.zok diff --git a/zokrates_cli/examples/error/forbidden_power_base.zok b/zokrates_cli/examples/error/forbidden_power_base.zok deleted file mode 100644 index 40c8b00c..00000000 --- a/zokrates_cli/examples/error/forbidden_power_base.zok +++ /dev/null @@ -1,2 +0,0 @@ -def main(field a) -> field: - return a*2**3 \ No newline at end of file diff --git a/zokrates_cli/examples/runtime_errors/lt_overflow_p_minus_one.zok b/zokrates_cli/examples/runtime_errors/lt_overflow_p_minus_one.zok index ec594e62..fd7aca40 100644 --- a/zokrates_cli/examples/runtime_errors/lt_overflow_p_minus_one.zok +++ b/zokrates_cli/examples/runtime_errors/lt_overflow_p_minus_one.zok @@ -2,6 +2,6 @@ // /!\ should be called with a = 0 def main(field a) -> bool: - field p = 21888242871839275222246405745257275088548364400416034343698204186575808495617 + a + field p = 21888242871839275222246405745257275088548364400416034343698204186575808495616 + a // we added a = 0 to prevent the condition to be evaluated at compile time - return 0 < p - 1 \ No newline at end of file + return 0 < p \ No newline at end of file diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs index 024a0bd1..9bafde62 100644 --- a/zokrates_cli/src/bin.rs +++ b/zokrates_cli/src/bin.rs @@ -994,7 +994,7 @@ mod tests { use super::*; #[test] - fn examples() { + fn compile_examples() { for p in glob("./examples/**/*").expect("Failed to read glob pattern") { let path = match p { Ok(x) => x, @@ -1007,9 +1007,7 @@ mod tests { assert!(path.extension().expect("extension expected") == "zok"); - if path.to_str().unwrap().contains("error") { - continue; - } + let should_error = path.to_str().unwrap().contains("compile_errors"); println!("Testing {:?}", path); @@ -1022,13 +1020,14 @@ mod tests { let stdlib = std::fs::canonicalize("../zokrates_stdlib/stdlib").unwrap(); let resolver = FileSystemResolver::with_stdlib_root(stdlib.to_str().unwrap()); - let _: CompilationArtifacts = - compile(source, path, Some(&resolver)).unwrap(); + let res = compile::(source, path, Some(&resolver)); + + assert_eq!(res.is_err(), should_error); } } #[test] - fn examples_with_input_success() { + fn execute_examples_ok() { //these examples should compile and run for p in glob("./examples/test*").expect("Failed to read glob pattern") { let path = match p { @@ -1059,7 +1058,7 @@ mod tests { #[test] #[should_panic] - fn examples_with_input_failure() { + fn execute_examples_err() { //these examples should compile but not run for p in glob("./examples/runtime_errors/*").expect("Failed to read glob pattern") { let path = match p { diff --git a/zokrates_core/src/compile.rs b/zokrates_core/src/compile.rs index 4e10d481..0653f406 100644 --- a/zokrates_core/src/compile.rs +++ b/zokrates_core/src/compile.rs @@ -292,7 +292,7 @@ mod test { #[test] fn use_struct_declaration_types() { - // when importing types and renaming them, we use the top-most renaming in the ABI + // when importing types and renaming them, we use the canonical struct names in the ABI // // main.zok // from foo import Foo as FooMain @@ -305,7 +305,7 @@ mod test { // struct Bar { field a } // Expected resolved type for FooMain: - // FooMain { BarFoo b } + // Foo { Bar b } let main = r#" from "foo" import Foo as FooMain @@ -370,21 +370,21 @@ struct Bar { field a } inputs: vec![AbiInput { name: "f".into(), public: true, - ty: Type::Struct(StructType { - module: "main".into(), - name: "FooMain".into(), - members: vec![StructMember { + ty: Type::Struct(StructType::new( + "foo".into(), + "Foo".into(), + vec![StructMember { id: "b".into(), - ty: box Type::Struct(StructType { - module: "foo".into(), - name: "BarFoo".into(), - members: vec![StructMember { + ty: box Type::Struct(StructType::new( + "bar".into(), + "Bar".into(), + vec![StructMember { id: "a".into(), ty: box Type::FieldElement }] - }) + )) }] - }) + )) }], outputs: vec![] } diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index c252d957..bc3490f4 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -16,7 +16,7 @@ use zokrates_field::Field; use crate::parser::Position; use crate::absy::types::{UnresolvedSignature, UnresolvedType, UserTypeId}; -use crate::typed_absy::types::{FunctionKey, Signature, Type}; +use crate::typed_absy::types::{FunctionKey, Signature, StructLocation, Type}; use std::hash::{Hash, Hasher}; use typed_absy::types::{ArrayType, StructMember}; @@ -124,6 +124,7 @@ impl fmt::Display for ErrorInner { } /// A function query in the current module. +#[derive(Debug)] struct FunctionQuery<'ast> { id: Identifier<'ast>, inputs: Vec, @@ -439,8 +440,10 @@ impl<'ast> Checker<'ast> { // 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(), + location: Some(StructLocation { + name: declaration.id.into(), + module: module_id.clone() + }), ..t }), _ => unreachable!() diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index d1eac1db..caffa86b 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -1,5 +1,5 @@ use std::fmt; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; pub type Identifier<'ast> = &'ast str; @@ -20,17 +20,25 @@ pub struct ArrayType { pub ty: Box, } -#[derive(Debug, Clone, Hash, Serialize, Deserialize, PartialOrd, Ord)] -pub struct StructType { +#[derive(Debug, Clone, Hash, Serialize, Deserialize, PartialOrd, Ord, Eq, PartialEq)] +pub struct StructLocation { #[serde(skip)] pub module: PathBuf, pub name: String, +} + +#[derive(Debug, Clone, Hash, Serialize, Deserialize, PartialOrd, Ord)] +pub struct StructType { + #[serde(flatten)] + pub canonical_location: StructLocation, + #[serde(skip)] + pub location: Option, pub members: Vec, } impl PartialEq for StructType { fn eq(&self, other: &Self) -> bool { - self.members.eq(&other.members) + self.canonical_location.eq(&other.canonical_location) && self.members.eq(&other.members) } } @@ -39,8 +47,8 @@ impl Eq for StructType {} impl StructType { pub fn new(module: PathBuf, name: String, members: Vec) -> Self { StructType { - module, - name, + canonical_location: StructLocation { module, name }, + location: None, members, } } @@ -52,6 +60,18 @@ impl StructType { pub fn iter(&self) -> std::slice::Iter { self.members.iter() } + + fn location(&self) -> &StructLocation { + &self.location.as_ref().unwrap_or(&self.canonical_location) + } + + pub fn name(&self) -> &str { + &self.location().name + } + + pub fn module(&self) -> &Path { + &self.location().module + } } impl IntoIterator for StructType { @@ -230,7 +250,7 @@ impl fmt::Display for Type { Type::Struct(ref struct_type) => write!( f, "{} {{{}}}", - struct_type.name, + struct_type.name(), struct_type .members .iter() @@ -249,17 +269,7 @@ impl fmt::Debug for Type { Type::Boolean => write!(f, "bool"), Type::Uint(ref bitwidth) => write!(f, "u{}", bitwidth), Type::Array(ref array_type) => write!(f, "{}[{}]", array_type.ty, array_type.size), - Type::Struct(ref struct_type) => write!( - f, - "{} {{{}}}", - struct_type.name, - struct_type - .members - .iter() - .map(|member| format!("{}: {}", member.id, member.ty)) - .collect::>() - .join(", ") - ), + Type::Struct(ref struct_type) => write!(f, "{:?}", struct_type), } } }