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), } } }