diff --git a/zokrates_abi/src/lib.rs b/zokrates_abi/src/lib.rs index 80e3005e..8136d583 100644 --- a/zokrates_abi/src/lib.rs +++ b/zokrates_abi/src/lib.rs @@ -277,7 +277,7 @@ fn parse_value( .map_err(|_| Error::Type(format!("Could not parse `{}` to u64 type", s))), (ConcreteType::Boolean, serde_json::Value::Bool(b)) => Ok(Value::Boolean(b)), (ConcreteType::Array(array_type), serde_json::Value::Array(a)) => { - let size = array_type.size; + let size = *array_type.size; if a.len() != size as usize { Err(Error::Type(format!( "Expected array of size {}, found array of size {}", diff --git a/zokrates_book/src/language/control_flow.md b/zokrates_book/src/language/control_flow.md index 610d1c48..4ff255cf 100644 --- a/zokrates_book/src/language/control_flow.md +++ b/zokrates_book/src/language/control_flow.md @@ -12,7 +12,7 @@ Arguments are passed by value. {{#include ../../../zokrates_cli/examples/book/side_effects.zok}} ``` -Generic paramaters, if any, must be compile-time constants. They are inferred by the compiler if that is possible, but can also be provided explicitly. +Generic parameters, if any, must be compile-time constants. They are inferred by the compiler if that is possible, but can also be provided explicitly. ```zokrates {{#include ../../../zokrates_cli/examples/book/generic_call.zok}} diff --git a/zokrates_book/src/language/functions.md b/zokrates_book/src/language/functions.md index ea8952aa..3a4872b8 100644 --- a/zokrates_book/src/language/functions.md +++ b/zokrates_book/src/language/functions.md @@ -18,18 +18,4 @@ The generic parameters can be provided explicitly, especially when they cannot b ```zokrates {{#include ../../../zokrates_cli/examples/book/explicit_generic_parameters.zok}} -``` - -Functions can return multiple values by providing them as a comma-separated list. - -```zokrates -{{#include ../../../zokrates_cli/examples/book/multi_return.zok}} -``` - -### Variable declaration - -When defining a variable as the return value of a function, types are provided when the variable needs to be declared: - -```zokrates -{{#include ../../../zokrates_cli/examples/book/multi_def.zok}} ``` \ No newline at end of file diff --git a/zokrates_book/src/language/types.md b/zokrates_book/src/language/types.md index 3f1815d9..47cf1096 100644 --- a/zokrates_book/src/language/types.md +++ b/zokrates_book/src/language/types.md @@ -71,8 +71,8 @@ ZoKrates offers a special shorthand syntax to initialize an array with a constan The following code provides examples for declaration and initialization: ```zokrates - field[3] a = [1, 2, 3] // initialize a field array with field values - bool[13] b = [false; 13] // initialize a bool array with value false +field[3] a = [1, 2, 3] // initialize a field array with field values +bool[13] b = [false; 13] // initialize a bool array with value false ``` #### Multidimensional Arrays @@ -132,8 +132,8 @@ A struct definition starts with the `struct` keyword followed by a name. Afterwa ```zokrates struct Point { - field x - field y + field x + field y } ``` diff --git a/zokrates_book/src/toolbox/abi.md b/zokrates_book/src/toolbox/abi.md index b264426e..caaa0c3b 100644 --- a/zokrates_book/src/toolbox/abi.md +++ b/zokrates_book/src/toolbox/abi.md @@ -59,11 +59,9 @@ In this example, the ABI specification is: "type":"field" } ], - "outputs":[ - { - "type":"field" - } - ] + "output": { + "type":"field" + } } ``` diff --git a/zokrates_book/src/toolbox/zokrates_js.md b/zokrates_book/src/toolbox/zokrates_js.md index 8b96b0f8..fd2529a8 100644 --- a/zokrates_book/src/toolbox/zokrates_js.md +++ b/zokrates_book/src/toolbox/zokrates_js.md @@ -24,7 +24,7 @@ import { initialize } from 'zokrates-js/node'; // or require('zokrates-js/node') ## Example ```js initialize().then((zokratesProvider) => { - const source = "def main(private field a) -> field: return a * a"; + const source = "def main(private field a) -> field { return a * a; }"; // compilation const artifacts = zokratesProvider.compile(source); @@ -88,7 +88,7 @@ Returns: `CompilationArtifacts` Compilation: ```js -const artifacts = zokratesProvider.compile("def main() -> (): return"); +const artifacts = zokratesProvider.compile("def main() { return; }"); ``` Compilation with custom options: @@ -135,7 +135,7 @@ Returns: `ComputationResult` **Example:** ```js -const code = 'def main(private field a) -> (field): return a * a'; +const code = 'def main(private field a) -> field { return a * a; }'; const artifacts = zokratesProvider.compile(code); const { witness, output } = zokratesProvider.computeWitness(artifacts, ["2"]); diff --git a/zokrates_cli/examples/alias/basic_aliasing.zok b/zokrates_cli/examples/alias/basic_aliasing.zok index f00533b3..ffc3177f 100644 --- a/zokrates_cli/examples/alias/basic_aliasing.zok +++ b/zokrates_cli/examples/alias/basic_aliasing.zok @@ -11,5 +11,5 @@ def fill(field v) -> matrix { def main(uint32 a, uint32 b) -> (UInt32Array<2>, matrix<2, 4>) { UInt32Array<2> res = [a, b]; matrix<2, 4> m = fill(1); - return res, m; + return (res, m); } diff --git a/zokrates_cli/examples/alias/import_alias.zok b/zokrates_cli/examples/alias/import_alias.zok index 8ce717ff..21b0407e 100644 --- a/zokrates_cli/examples/alias/import_alias.zok +++ b/zokrates_cli/examples/alias/import_alias.zok @@ -12,5 +12,5 @@ def buzz() -> Buzz { def main(matrix_2x4 m) -> (Buzz<2>, matrix_2x4) { Buzz<2> b = buzz::<2>(); - return b, m; + return (b, m); } diff --git a/zokrates_cli/examples/arrays/array_loop_update.zok b/zokrates_cli/examples/arrays/array_loop_update.zok index 764050fa..911c956d 100644 --- a/zokrates_cli/examples/arrays/array_loop_update.zok +++ b/zokrates_cli/examples/arrays/array_loop_update.zok @@ -1,4 +1,4 @@ -def main() -> (u32[3]) { +def main() -> u32[3] { u32[3] a = [1, 2, 3]; u32[3] c = [4, 5, 6]; for u32 i in 0..3 { diff --git a/zokrates_cli/examples/arrays/boolean_array.zok b/zokrates_cli/examples/arrays/boolean_array.zok index 6a0870de..b42241ae 100644 --- a/zokrates_cli/examples/arrays/boolean_array.zok +++ b/zokrates_cli/examples/arrays/boolean_array.zok @@ -1,4 +1,4 @@ -def main(bool[3] a) -> (field[3]) { +def main(bool[3] a) -> field[3] { bool[3] c = [true, true || false, true]; a[1] = true || a[2]; a[2] = a[0]; diff --git a/zokrates_cli/examples/arrays/init_with_value.zok b/zokrates_cli/examples/arrays/init_with_value.zok index 0c5fcc6a..c7d6f5e4 100644 --- a/zokrates_cli/examples/arrays/init_with_value.zok +++ b/zokrates_cli/examples/arrays/init_with_value.zok @@ -1,3 +1,3 @@ -def main(field value) -> (field[3]) { +def main(field value) -> field[3] { return [value, value, value]; } diff --git a/zokrates_cli/examples/arrays/multidim_update.zok b/zokrates_cli/examples/arrays/multidim_update.zok index 8c86dd1a..b4fcf88f 100644 --- a/zokrates_cli/examples/arrays/multidim_update.zok +++ b/zokrates_cli/examples/arrays/multidim_update.zok @@ -1,4 +1,4 @@ -def main(field[10][10][10] a, u32 i, u32 j, u32 k) -> (field[3]) { +def main(field[10][10][10] a, u32 i, u32 j, u32 k) -> field[3] { a[i][j][k] = 42; field[3][3] b = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]; return b[0]; diff --git a/zokrates_cli/examples/arrays/slicefrom.zok b/zokrates_cli/examples/arrays/slicefrom.zok index 913eaca5..42656735 100644 --- a/zokrates_cli/examples/arrays/slicefrom.zok +++ b/zokrates_cli/examples/arrays/slicefrom.zok @@ -1,4 +1,4 @@ -def slice32from(u32 offset, field[2048] input) -> (field[32]) { +def slice32from(u32 offset, field[2048] input) -> field[32] { field[32] result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for u32 i in 0..32 { result[i] = input[offset + i]; @@ -6,7 +6,7 @@ def slice32from(u32 offset, field[2048] input) -> (field[32]) { return result; } -def main() -> (field[32]) { +def main() -> field[32] { field[2048] input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; return slice32from(67, input); } diff --git a/zokrates_cli/examples/arrays/update.zok b/zokrates_cli/examples/arrays/update.zok index 4f6e616b..d35fb525 100644 --- a/zokrates_cli/examples/arrays/update.zok +++ b/zokrates_cli/examples/arrays/update.zok @@ -7,6 +7,6 @@ def main() -> (field, field) { field[3] a = [0, 0, 0]; field res = foo(a); assert(a[1] == 0); - return res, a[1]; + return (res, a[1]); } diff --git a/zokrates_cli/examples/arrays/update_with_call.zok b/zokrates_cli/examples/arrays/update_with_call.zok index bf35342e..810bc857 100644 --- a/zokrates_cli/examples/arrays/update_with_call.zok +++ b/zokrates_cli/examples/arrays/update_with_call.zok @@ -7,5 +7,5 @@ def main(field a) -> (field, field) { field r = foo(a); result[1] = r; assert(result[1] == r); - return result[1], r; + return (result[1], r); } diff --git a/zokrates_cli/examples/assign_to_element.zok b/zokrates_cli/examples/assign_to_element.zok index 70adca98..56daff23 100644 --- a/zokrates_cli/examples/assign_to_element.zok +++ b/zokrates_cli/examples/assign_to_element.zok @@ -2,12 +2,8 @@ def foo() -> u32 { return 0; } -def bar() -> (u32, u32) { - return 0, 0; -} - -def main(u32[1] a, u32 b) { +def main(u32[1] a, (u32,) b) { a[0] = foo(); - a[0], b = bar(); + b.0 = foo(); return; } \ No newline at end of file diff --git a/zokrates_cli/examples/book/assert.zok b/zokrates_cli/examples/book/assert.zok index c7bd7830..167124bf 100644 --- a/zokrates_cli/examples/book/assert.zok +++ b/zokrates_cli/examples/book/assert.zok @@ -1,4 +1,4 @@ -def main() -> () { +def main() { assert(1f + 1f == 2f); - return; + return; } diff --git a/zokrates_cli/examples/book/bubblesort.zok b/zokrates_cli/examples/book/bubblesort.zok index a3892d4e..bfb35e4f 100644 --- a/zokrates_cli/examples/book/bubblesort.zok +++ b/zokrates_cli/examples/book/bubblesort.zok @@ -1,14 +1,16 @@ def swap(u32 a, u32 b, bool c) -> (u32, u32) { u32 a_prime = c ? b : a; b = c ? a : b; - return a_prime, b; + return (a_prime, b); } def bubblesort(u32[N] a) -> u32[N] { for u32 i in 0..(N-1) { for u32 j in 0..(N-1-i) { bool need_swap = a[j + 1] < a[j]; - a[j], a[j + 1] = swap(a[j], a[j + 1], need_swap); + (u32, u32) swapped = swap(a[j], a[j + 1], need_swap); + a[j] = swapped.0; + a[j + 1] = swapped.1; } } return a; diff --git a/zokrates_cli/examples/book/declaration.zok b/zokrates_cli/examples/book/declaration.zok index f4f8c7d7..225c4973 100644 --- a/zokrates_cli/examples/book/declaration.zok +++ b/zokrates_cli/examples/book/declaration.zok @@ -1,7 +1,7 @@ def main() { // declare and define `my_variable` - field my_variable = 2; - // redefine `my_variable` - my_variable = 3; - return; + field my_variable = 2; + // redefine `my_variable` + my_variable = 3; + return; } \ No newline at end of file diff --git a/zokrates_cli/examples/book/for.zok b/zokrates_cli/examples/book/for.zok index 994819f9..bea69a33 100644 --- a/zokrates_cli/examples/book/for.zok +++ b/zokrates_cli/examples/book/for.zok @@ -1,8 +1,8 @@ def main() -> u32 { u32 res = 0; for u32 i in 0..4 { - for u32 j in i..5 { - res = res + i; + for u32 j in i..5 { + res = res + i; } } return res; diff --git a/zokrates_cli/examples/book/for_scope.zok b/zokrates_cli/examples/book/for_scope.zok index 92e14bba..8bdfe443 100644 --- a/zokrates_cli/examples/book/for_scope.zok +++ b/zokrates_cli/examples/book/for_scope.zok @@ -1,8 +1,8 @@ def main() -> u32 { - u32 a = 0; - for u32 i in 0..5 { - a = a + i; - } - // return i <- not allowed - return a; + u32 a = 0; + for u32 i in 0..5 { + a = a + i; + } + // return i <- not allowed + return a; } diff --git a/zokrates_cli/examples/book/generics.zok b/zokrates_cli/examples/book/generics.zok index 54f27340..7021ac2e 100644 --- a/zokrates_cli/examples/book/generics.zok +++ b/zokrates_cli/examples/book/generics.zok @@ -1,9 +1,9 @@ def sum(field[N] a) -> field { - field res = 0; - for u32 i in 0..N { - res = res + a[i]; - } - return res; + field res = 0; + for u32 i in 0..N { + res = res + a[i]; + } + return res; } def main(field[3] a) -> field { diff --git a/zokrates_cli/examples/book/multi_def.zok b/zokrates_cli/examples/book/multi_def.zok deleted file mode 100644 index 0c931f30..00000000 --- a/zokrates_cli/examples/book/multi_def.zok +++ /dev/null @@ -1,11 +0,0 @@ -def foo() -> (field, field) { - return 21, 42; -} - -def main() { - // a is declared here - field a = 1; - // b is declared here - a, field b = foo(); - return; -} diff --git a/zokrates_cli/examples/book/multi_return.zok b/zokrates_cli/examples/book/multi_return.zok deleted file mode 100644 index 3095998d..00000000 --- a/zokrates_cli/examples/book/multi_return.zok +++ /dev/null @@ -1,3 +0,0 @@ -def main() -> (field, field[3]) { - return 1, [2, 3, 4]; -} diff --git a/zokrates_cli/examples/book/no_shadowing.zok b/zokrates_cli/examples/book/no_shadowing.zok index ee978a37..4147bfe6 100644 --- a/zokrates_cli/examples/book/no_shadowing.zok +++ b/zokrates_cli/examples/book/no_shadowing.zok @@ -1,8 +1,8 @@ def main() -> field { - field a = 2; - // field a = 3 <- not allowed - for u32 i in 0..5 { - // field a = 7 <- not allowed - } - return a; + field a = 2; + // field a = 3 <- not allowed + for u32 i in 0..5 { + // field a = 7 <- not allowed + } + return a; } diff --git a/zokrates_cli/examples/book/not_equal.zok b/zokrates_cli/examples/book/not_equal.zok index 382e6518..fba39802 100644 --- a/zokrates_cli/examples/book/not_equal.zok +++ b/zokrates_cli/examples/book/not_equal.zok @@ -1,3 +1,3 @@ -def main(field a, field b) -> (bool) { +def main(field a, field b) -> bool { return !(a == b); } \ No newline at end of file diff --git a/zokrates_cli/examples/book/numeric_inference.zok b/zokrates_cli/examples/book/numeric_inference.zok index dc034475..f8106431 100644 --- a/zokrates_cli/examples/book/numeric_inference.zok +++ b/zokrates_cli/examples/book/numeric_inference.zok @@ -1,10 +1,10 @@ def main() { - // `255` is infered to `255f`, and the addition happens between field elements - assert(255 + 1f == 256); + // `255` is infered to `255f`, and the addition happens between field elements + assert(255 + 1f == 256); - // `255` is infered to `255u8`, and the addition happens between u8 - // This causes an overflow - assert(255 + 1u8 == 0); + // `255` is infered to `255u8`, and the addition happens between u8 + // This causes an overflow + assert(255 + 1u8 == 0); - return; + return; } diff --git a/zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok b/zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok index e56a6cc5..917fa2c9 100644 --- a/zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok +++ b/zokrates_cli/examples/book/rng_tutorial/reveal_bit.zok @@ -15,5 +15,5 @@ def main(private u32[16] preimage, u32 bitNum) -> (u32[8], bool) { preimageBits[i*32 + bit] = val[bit]; } } - return sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum]; + return (sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum]); } \ No newline at end of file diff --git a/zokrates_cli/examples/book/struct_assign.zok b/zokrates_cli/examples/book/struct_assign.zok index 633af8e1..2d8fa938 100644 --- a/zokrates_cli/examples/book/struct_assign.zok +++ b/zokrates_cli/examples/book/struct_assign.zok @@ -1,9 +1,9 @@ struct Point { - field x; - field y; + field x; + field y; } -def main(field a) -> (Point) { +def main(field a) -> Point { Point p = Point { x: 1, y: 0 }; p.x = a; p.y = p.x; diff --git a/zokrates_cli/examples/book/struct_init.zok b/zokrates_cli/examples/book/struct_init.zok index 4da779da..b145ee2d 100644 --- a/zokrates_cli/examples/book/struct_init.zok +++ b/zokrates_cli/examples/book/struct_init.zok @@ -1,10 +1,10 @@ struct Point { - field x; - field y; + field x; + field y; } -def main() -> (Point) { - Point p = Point { x: 1, y: 0 }; - return p; +def main() -> Point { + Point p = Point { x: 1, y: 0 }; + return p; } diff --git a/zokrates_cli/examples/book/structs.zok b/zokrates_cli/examples/book/structs.zok index 86f6f891..0b395465 100644 --- a/zokrates_cli/examples/book/structs.zok +++ b/zokrates_cli/examples/book/structs.zok @@ -1,16 +1,16 @@ struct Bar { - field[N] c; - bool d; + field[N] c; + bool d; } struct Foo

{ - Bar

a; - bool b; + Bar

a; + bool b; } -def main() -> (Foo<2>) { - Foo<2>[2] f = [Foo { a: Bar { c: [0, 0], d: false }, b: true}, Foo { a: Bar {c: [0, 0], d: false}, b: true }]; - f[0].a.c = [42, 43]; - return f[0]; +def main() -> Foo<2> { + Foo<2>[2] f = [Foo { a: Bar { c: [0, 0], d: false }, b: true}, Foo { a: Bar {c: [0, 0], d: false}, b: true }]; + f[0].a.c = [42, 43]; + return f[0]; } diff --git a/zokrates_cli/examples/book/tuples.zok b/zokrates_cli/examples/book/tuples.zok index 560de181..a1a3521f 100644 --- a/zokrates_cli/examples/book/tuples.zok +++ b/zokrates_cli/examples/book/tuples.zok @@ -1,6 +1,6 @@ def main() -> bool { - (field[2], bool) v = ([1, 2], true); - v.0 = [42, 43]; - return v.1; + (field[2], bool) v = ([1, 2], true); + v.0 = [42, 43]; + return v.1; } diff --git a/zokrates_cli/examples/book/type_annotations.zok b/zokrates_cli/examples/book/type_annotations.zok index 3903c389..dc703184 100644 --- a/zokrates_cli/examples/book/type_annotations.zok +++ b/zokrates_cli/examples/book/type_annotations.zok @@ -1,12 +1,12 @@ def foo() -> (field, field[3]) { - return 1, [2, 3, 4]; + return (1, [2, 3, 4]); } def foo() -> (field, field) { - return 1, 2; + return (1, 2); } def main() { - field a, field[3] b = foo(); + (field, field[3]) a = foo(); return; } diff --git a/zokrates_cli/examples/compile_errors/keyword_as_identifier.zok b/zokrates_cli/examples/compile_errors/keyword_as_identifier.zok index 517d2444..3a460665 100644 --- a/zokrates_cli/examples/compile_errors/keyword_as_identifier.zok +++ b/zokrates_cli/examples/compile_errors/keyword_as_identifier.zok @@ -2,6 +2,5 @@ def assert() { return; } - def main(): return \ No newline at end of file diff --git a/zokrates_cli/examples/compile_errors/no_struct_equivalence.zok b/zokrates_cli/examples/compile_errors/no_struct_equivalence.zok index bf2c05fc..34229980 100644 --- a/zokrates_cli/examples/compile_errors/no_struct_equivalence.zok +++ b/zokrates_cli/examples/compile_errors/no_struct_equivalence.zok @@ -1,6 +1,6 @@ struct Foo {} struct Bar {} -def main() -> (Foo) { +def main() -> Foo { return Bar {}; } \ No newline at end of file diff --git a/zokrates_cli/examples/merkleTree/sha256PathProof3.zok b/zokrates_cli/examples/merkleTree/sha256PathProof3.zok index 44bd1aa4..a8ad61e7 100644 --- a/zokrates_cli/examples/merkleTree/sha256PathProof3.zok +++ b/zokrates_cli/examples/merkleTree/sha256PathProof3.zok @@ -4,7 +4,7 @@ import "hashes/utils/256bitsDirectionHelper" as multiplex; const u32 DEPTH = 3; def select(bool condition, u32[8] left, u32[8] right) -> (u32[8], u32[8]) { - return condition ? right : left, condition ? left : right; + return (condition ? right : left, condition ? left : right); } // Merke-Tree inclusion proof for tree depth 4 using sha256 @@ -16,8 +16,8 @@ def main(u32[8] root, private u32[8] leaf, private bool[DEPTH] directionSelector // Loop up the tree for u32 i in 0..DEPTH { - u32[8] left, u32[8] right = select(directionSelector[i], digest, path[i]); - digest = hash(left, right); + (u32[8], u32[8]) s = select(directionSelector[i], digest, path[i]); + digest = hash(s.0, s.1); } return digest == root; diff --git a/zokrates_cli/examples/multi_return.zok b/zokrates_cli/examples/multi_return.zok deleted file mode 100644 index ea2067e4..00000000 --- a/zokrates_cli/examples/multi_return.zok +++ /dev/null @@ -1,9 +0,0 @@ -def foo(field a) -> (field, field, field, field) { - field b = 12 * a; - return a, 2 * a, 5 * b, a * b; -} - -def main(field i) { - field x, field y, field z, field t = foo(i); - return; -} diff --git a/zokrates_cli/examples/multi_return_sum.zok b/zokrates_cli/examples/multi_return_sum.zok deleted file mode 100644 index da539c55..00000000 --- a/zokrates_cli/examples/multi_return_sum.zok +++ /dev/null @@ -1,8 +0,0 @@ -def foo() -> (field, field) { - return 1, 2; -} - -def main() -> (field, field) { - field a, field b = foo(); - return a + b, b - a; -} diff --git a/zokrates_cli/examples/propagate_call.zok b/zokrates_cli/examples/propagate_call.zok index 41f89f0d..6464559a 100644 --- a/zokrates_cli/examples/propagate_call.zok +++ b/zokrates_cli/examples/propagate_call.zok @@ -1,9 +1,9 @@ def foo(field a, field b) -> (field, field) { assert(a == b); - return a, b; + return (a, b); } def main() -> field { - field a, field b = foo(1, 1); - return a + b; + (field, field) v = foo(1, 1); + return v.0 + v.1; } diff --git a/zokrates_cli/examples/tuples/add.zok b/zokrates_cli/examples/tuples/add.zok index 168959f4..bd45a65d 100644 --- a/zokrates_cli/examples/tuples/add.zok +++ b/zokrates_cli/examples/tuples/add.zok @@ -1,4 +1,4 @@ -def main((field, field) p, (field, field) q) -> ((field, field)) { +def main((field, field) p, (field, field) q) -> (field, field) { field a = 42; field d = 21; diff --git a/zokrates_cli/examples/tuples/set_member.zok b/zokrates_cli/examples/tuples/set_member.zok index 83a37909..e004aa30 100644 --- a/zokrates_cli/examples/tuples/set_member.zok +++ b/zokrates_cli/examples/tuples/set_member.zok @@ -8,7 +8,7 @@ struct Foo { bool b; } -def main() -> (((field[2], bool), bool)) { +def main() -> ((field[2], bool), bool) { ((field[2], bool), bool)[2] f = [ (([0, 0], false), true), (([0, 0], false), true) diff --git a/zokrates_cli/src/ops/compute_witness.rs b/zokrates_cli/src/ops/compute_witness.rs index 944451df..cb224bb0 100644 --- a/zokrates_cli/src/ops/compute_witness.rs +++ b/zokrates_cli/src/ops/compute_witness.rs @@ -8,7 +8,7 @@ use zokrates_abi::Encode; use zokrates_core::ir; use zokrates_core::ir::ProgEnum; use zokrates_core::typed_absy::abi::Abi; -use zokrates_core::typed_absy::types::{ConcreteSignature, ConcreteType}; +use zokrates_core::typed_absy::types::{ConcreteSignature, ConcreteType, GTupleType}; use zokrates_field::Field; pub fn subcommand() -> App<'static, 'static> { @@ -103,7 +103,9 @@ fn cli_compute>>( } false => ConcreteSignature::new() .inputs(vec![ConcreteType::FieldElement; ir_prog.arguments.len()]) - .outputs(vec![ConcreteType::FieldElement; ir_prog.return_count]), + .output(ConcreteType::Tuple(GTupleType::new( + vec![ConcreteType::FieldElement; ir_prog.return_count], + ))), }; use zokrates_abi::Inputs; @@ -165,7 +167,7 @@ fn cli_compute>>( use zokrates_abi::Decode; let results_json_value: serde_json::Value = - zokrates_abi::Values::decode(witness.return_values(), signature.outputs).into_serde_json(); + zokrates_abi::Value::decode(witness.return_values(), *signature.output).into_serde_json(); if verbose { println!("\nWitness: \n{}\n", results_json_value); diff --git a/zokrates_core/src/absy/from_ast.rs b/zokrates_core/src/absy/from_ast.rs index c78ed8cf..937896fe 100644 --- a/zokrates_core/src/absy/from_ast.rs +++ b/zokrates_core/src/absy/from_ast.rs @@ -183,16 +183,13 @@ impl<'ast> From> for absy::SymbolDeclarationNode< .into_iter() .map(|p| absy::UnresolvedTypeNode::from(p.ty)) .collect(), - ) - .outputs( - function - .returns - .clone() - .into_iter() - .map(absy::UnresolvedTypeNode::from) - .collect(), ); + let signature = match function.return_type { + Some(ret_ty) => signature.output(absy::UnresolvedTypeNode::from(ret_ty)), + None => signature, + }; + let id = function.id.span.as_str(); let function = absy::Function { @@ -261,92 +258,28 @@ fn statements_from_statement(statement: pest::Statement) -> Vec Vec { use crate::absy::NodeValue; - let lhs = definition.lhs; + let e: absy::ExpressionNode = absy::ExpressionNode::from(definition.expression); - match lhs.len() { - 1 => { - // Definition or assignment - let a = lhs[0].clone(); - - let e: absy::ExpressionNode = absy::ExpressionNode::from(definition.expression); - - match a { - pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => { - let declaration = absy::Statement::Declaration( - absy::Variable::new( - i.identifier.span.as_str(), - absy::UnresolvedTypeNode::from(i.ty), - ) - .span(i.identifier.span.clone()), - ) - .span(definition.span.clone()); - - let s = match e.value { - absy::Expression::FunctionCall(..) => absy::Statement::MultipleDefinition( - vec![absy::AssigneeNode::from(i.identifier.clone())], - e, - ), - _ => absy::Statement::Definition( - absy::AssigneeNode::from(i.identifier.clone()), - e, - ), - }; - - vec![declaration, s.span(definition.span)] - } - pest::TypedIdentifierOrAssignee::Assignee(a) => { - let s = match e.value { - absy::Expression::FunctionCall(..) => absy::Statement::MultipleDefinition( - vec![absy::AssigneeNode::from(a)], - e, - ), - _ => absy::Statement::Definition(absy::AssigneeNode::from(a), e), - }; - - vec![s.span(definition.span)] - } - } - } - _ => { - // Multidefinition - let declarations = lhs.clone().into_iter().filter_map(|i| match i { - pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => { - let ty = i.ty; - let id = i.identifier; - - Some( - absy::Statement::Declaration( - absy::Variable::new( - id.span.as_str(), - absy::UnresolvedTypeNode::from(ty), - ) - .span(id.span), - ) - .span(i.span), - ) - } - _ => None, - }); - - let lhs = lhs - .into_iter() - .map(|i| match i { - pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => { - absy::Assignee::Identifier(i.identifier.span.as_str()) - .span(i.identifier.span) - } - pest::TypedIdentifierOrAssignee::Assignee(a) => absy::AssigneeNode::from(a), - }) - .collect(); - - let multi_def = absy::Statement::MultipleDefinition( - lhs, - absy::ExpressionNode::from(definition.expression), + match lhs { + pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => { + let declaration = absy::Statement::Declaration( + absy::Variable::new( + i.identifier.span.as_str(), + absy::UnresolvedTypeNode::from(i.ty), + ) + .span(i.identifier.span.clone()), ) - .span(definition.span); + .span(definition.span.clone()); - declarations.chain(std::iter::once(multi_def)).collect() + let definition = + absy::Statement::Definition(absy::AssigneeNode::from(i.identifier.clone()), e) + .span(definition.span); + + vec![declaration, definition] + } + pest::TypedIdentifierOrAssignee::Assignee(a) => { + vec![absy::Statement::Definition(absy::AssigneeNode::from(a), e).span(definition.span)] } } } @@ -355,17 +288,8 @@ impl<'ast> From> for absy::StatementNode<'ast> { fn from(statement: pest::ReturnStatement<'ast>) -> absy::StatementNode<'ast> { use crate::absy::NodeValue; - absy::Statement::Return( - absy::ExpressionList { - expressions: statement - .expressions - .into_iter() - .map(absy::ExpressionNode::from) - .collect(), - } - .span(statement.span.clone()), - ) - .span(statement.span) + absy::Statement::Return(statement.expression.map(absy::ExpressionNode::from)) + .span(statement.span) } } @@ -914,18 +838,13 @@ mod tests { symbol: absy::Symbol::Here(absy::SymbolDefinition::Function( absy::Function { arguments: vec![], - statements: vec![absy::Statement::Return( - absy::ExpressionList { - expressions: vec![ - absy::Expression::IntConstant(42usize.into()).into() - ], - } - .into(), - ) + statements: vec![absy::Statement::Return(Some( + absy::Expression::IntConstant(42usize.into()).into(), + )) .into()], signature: UnresolvedSignature::new() .inputs(vec![]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), + .output(UnresolvedType::FieldElement.mock()), } .into(), )), @@ -945,16 +864,13 @@ mod tests { symbol: absy::Symbol::Here(absy::SymbolDefinition::Function( absy::Function { arguments: vec![], - statements: vec![absy::Statement::Return( - absy::ExpressionList { - expressions: vec![absy::Expression::BooleanConstant(true).into()], - } - .into(), - ) + statements: vec![absy::Statement::Return(Some( + absy::Expression::BooleanConstant(true).into(), + )) .into()], signature: UnresolvedSignature::new() .inputs(vec![]) - .outputs(vec![UnresolvedType::Boolean.mock()]), + .output(UnresolvedType::Boolean.mock()), } .into(), )), @@ -992,21 +908,16 @@ mod tests { ) .into(), ], - statements: vec![absy::Statement::Return( - absy::ExpressionList { - expressions: vec![ - absy::Expression::IntConstant(42usize.into()).into() - ], - } - .into(), - ) + statements: vec![absy::Statement::Return(Some( + absy::Expression::IntConstant(42usize.into()).into(), + )) .into()], signature: UnresolvedSignature::new() .inputs(vec![ UnresolvedType::FieldElement.mock(), UnresolvedType::Boolean.mock(), ]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), + .output(UnresolvedType::FieldElement.mock()), } .into(), )), @@ -1031,13 +942,7 @@ mod tests { absy::Variable::new("a", ty.clone().mock()).into(), ) .into()], - statements: vec![absy::Statement::Return( - absy::ExpressionList { - expressions: vec![], - } - .into(), - ) - .into()], + statements: vec![absy::Statement::Return(None).into()], signature: UnresolvedSignature::new().inputs(vec![ty.mock()]), } .into(), @@ -1101,13 +1006,9 @@ mod tests { symbol: absy::Symbol::Here(absy::SymbolDefinition::Function( absy::Function { arguments: vec![], - statements: vec![absy::Statement::Return( - absy::ExpressionList { - expressions: vec![expression.into()], - } - .into(), - ) - .into()], + statements: vec![ + absy::Statement::Return(Some(expression.into())).into() + ], signature: UnresolvedSignature::new(), } .into(), @@ -1239,20 +1140,19 @@ mod tests { let span = Span::new("", 0, 0).unwrap(); - // For different definitions, we generate declarations - // Case 1: `id = expr` where `expr` is not a function call - // This is a simple assignment, doesn't implicitely declare a variable - // A `Definition` is generated and no `Declaration`s + // Case 1: `id = expr` + // This is a simple assignment to an already existing variable + // A definition is generated let definition = pest::DefinitionStatement { - lhs: vec![pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { + lhs: pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { id: pest::IdentifierExpression { value: String::from("a"), span: span.clone(), }, accesses: vec![], span: span.clone(), - })], + }), expression: pest::Expression::Literal(pest::LiteralExpression::DecimalLiteral( pest::DecimalLiteralExpression { value: pest::DecimalNumber { @@ -1275,71 +1175,20 @@ mod tests { } }; - // Case 2: `id = expr` where `expr` is a function call - // A MultiDef is generated + // Case 2: `type id = expr` + // A declaration and a definition is generated let definition = pest::DefinitionStatement { - lhs: vec![pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { - id: pest::IdentifierExpression { + lhs: pest::TypedIdentifierOrAssignee::TypedIdentifier(pest::TypedIdentifier { + ty: pest::Type::Basic(pest::BasicType::Field(pest::FieldType { + span: span.clone(), + })), + identifier: pest::IdentifierExpression { value: String::from("a"), span: span.clone(), }, - accesses: vec![], - span: span.clone(), - })], - expression: pest::Expression::Postfix(pest::PostfixExpression { - base: box pest::Expression::Identifier(pest::IdentifierExpression { - value: String::from("foo"), - span: span.clone(), - }), - accesses: vec![pest::Access::Call(pest::CallAccess { - explicit_generics: None, - arguments: pest::Arguments { - expressions: vec![], - span: span.clone(), - }, - span: span.clone(), - })], span: span.clone(), }), - span: span.clone(), - }; - - let statements: Vec = statements_from_definition(definition); - - assert_eq!(statements.len(), 1); - match &statements[0].value { - absy::Statement::MultipleDefinition(..) => {} - s => { - panic!("should be a Definition, found {}", s); - } - }; - // Case 3: `ids = expr` where `expr` is a function call - // This implicitely declares all variables which are type annotated - - // `field a, b = foo()` - - let definition = pest::DefinitionStatement { - lhs: vec![ - pest::TypedIdentifierOrAssignee::TypedIdentifier(pest::TypedIdentifier { - ty: pest::Type::Basic(pest::BasicType::Field(pest::FieldType { - span: span.clone(), - })), - identifier: pest::IdentifierExpression { - value: String::from("a"), - span: span.clone(), - }, - span: span.clone(), - }), - pest::TypedIdentifierOrAssignee::Assignee(pest::Assignee { - id: pest::IdentifierExpression { - value: String::from("b"), - span: span.clone(), - }, - accesses: vec![], - span: span.clone(), - }), - ], expression: pest::Expression::Postfix(pest::PostfixExpression { base: box pest::Expression::Identifier(pest::IdentifierExpression { value: String::from("foo"), @@ -1361,10 +1210,10 @@ mod tests { let statements: Vec = statements_from_definition(definition); assert_eq!(statements.len(), 2); - match &statements[1].value { - absy::Statement::MultipleDefinition(..) => {} - s => { - panic!("should be a Definition, found {}", s); + match (&statements[0].value, &statements[1].value) { + (absy::Statement::Declaration(..), absy::Statement::Definition(..)) => {} + _ => { + panic!("should be a (Declaration, Definition)"); } }; } diff --git a/zokrates_core/src/absy/mod.rs b/zokrates_core/src/absy/mod.rs index 7862b1ef..a06048a9 100644 --- a/zokrates_core/src/absy/mod.rs +++ b/zokrates_core/src/absy/mod.rs @@ -384,7 +384,7 @@ impl<'ast> fmt::Display for Assignee<'ast> { #[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, PartialEq)] pub enum Statement<'ast> { - Return(ExpressionListNode<'ast>), + Return(Option>), Declaration(VariableNode<'ast>), Definition(AssigneeNode<'ast>, ExpressionNode<'ast>), Assertion(ExpressionNode<'ast>, Option), @@ -394,7 +394,6 @@ pub enum Statement<'ast> { ExpressionNode<'ast>, Vec>, ), - MultipleDefinition(Vec>, ExpressionNode<'ast>), } pub type StatementNode<'ast> = Node>; @@ -402,7 +401,13 @@ pub type StatementNode<'ast> = Node>; impl<'ast> fmt::Display for Statement<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Statement::Return(ref expr) => write!(f, "return {};", expr), + Statement::Return(ref expr) => { + write!(f, "return")?; + match expr { + Some(e) => write!(f, " {};", e), + None => write!(f, ";"), + } + } Statement::Declaration(ref var) => write!(f, "{};", var), Statement::Definition(ref lhs, ref rhs) => write!(f, "{} = {};", lhs, rhs), Statement::Assertion(ref e, ref message) => { @@ -419,15 +424,6 @@ impl<'ast> fmt::Display for Statement<'ast> { } write!(f, "\t}}") } - Statement::MultipleDefinition(ref ids, ref rhs) => { - for (i, id) in ids.iter().enumerate() { - write!(f, "{}", id)?; - if i < ids.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, " = {};", rhs) - } } } } @@ -664,23 +660,3 @@ impl<'ast> fmt::Display for Expression<'ast> { } } } - -/// A list of expressions, used in return statements -#[derive(Debug, Clone, PartialEq, Default)] -pub struct ExpressionList<'ast> { - pub expressions: Vec>, -} - -pub type ExpressionListNode<'ast> = Node>; - -impl<'ast> fmt::Display for ExpressionList<'ast> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for (i, param) in self.expressions.iter().enumerate() { - write!(f, "{}", param)?; - if i < self.expressions.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, "") - } -} diff --git a/zokrates_core/src/absy/node.rs b/zokrates_core/src/absy/node.rs index 0332ad57..3010f041 100644 --- a/zokrates_core/src/absy/node.rs +++ b/zokrates_core/src/absy/node.rs @@ -85,7 +85,6 @@ use crate::absy::types::UnresolvedType; use crate::absy::*; impl<'ast> NodeValue for Expression<'ast> {} -impl<'ast> NodeValue for ExpressionList<'ast> {} impl<'ast> NodeValue for Assignee<'ast> {} impl<'ast> NodeValue for Statement<'ast> {} impl<'ast> NodeValue for SymbolDeclaration<'ast> {} diff --git a/zokrates_core/src/absy/types.rs b/zokrates_core/src/absy/types.rs index 924e72cf..1bb1f765 100644 --- a/zokrates_core/src/absy/types.rs +++ b/zokrates_core/src/absy/types.rs @@ -85,15 +85,15 @@ mod signature { pub struct UnresolvedSignature<'ast> { pub generics: Vec>, pub inputs: Vec>, - pub outputs: Vec>, + pub output: Option>, } impl<'ast> fmt::Debug for UnresolvedSignature<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "Signature(inputs: {:?}, outputs: {:?})", - self.inputs, self.outputs + "Signature(inputs: {:?}, output: {:?})", + self.inputs, self.output ) } } @@ -107,14 +107,10 @@ mod signature { write!(f, ", ")?; } } - write!(f, ") -> (")?; - for (i, t) in self.outputs.iter().enumerate() { - write!(f, "{}", t)?; - if i < self.outputs.len() - 1 { - write!(f, ", ")?; - } + match &self.output { + Some(ty) => write!(f, ") -> {}", ty), + None => write!(f, ")"), } - write!(f, ")") } } @@ -133,8 +129,8 @@ mod signature { self } - pub fn outputs(mut self, outputs: Vec>) -> Self { - self.outputs = outputs; + pub fn output(mut self, output: UnresolvedTypeNode<'ast>) -> Self { + self.output = Some(output); self } } diff --git a/zokrates_core/src/compile.rs b/zokrates_core/src/compile.rs index 6e5cee22..3b8466ff 100644 --- a/zokrates_core/src/compile.rs +++ b/zokrates_core/src/compile.rs @@ -469,7 +469,7 @@ struct Bar { field a; } }] )) }], - outputs: vec![] + output: ConcreteType::Tuple(GTupleType::new(vec![])) } ); } diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index 54906148..3f38778a 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -65,66 +65,76 @@ impl FlatEmbed { ) .into(), ]) - .outputs(vec![UnresolvedType::Boolean.into()]), + .output(UnresolvedType::Boolean.into()), FlatEmbed::Unpack => UnresolvedSignature::new() .generics(vec!["N".into()]) .inputs(vec![UnresolvedType::FieldElement.into()]) - .outputs(vec![UnresolvedType::array( - UnresolvedType::Boolean.into(), - Expression::Identifier("N").into(), - ) - .into()]), + .output( + UnresolvedType::array( + UnresolvedType::Boolean.into(), + Expression::Identifier("N").into(), + ) + .into(), + ), FlatEmbed::U8ToBits => UnresolvedSignature::new() .inputs(vec![UnresolvedType::Uint(8).into()]) - .outputs(vec![UnresolvedType::array( - UnresolvedType::Boolean.into(), - Expression::U32Constant(8).into(), - ) - .into()]), + .output( + UnresolvedType::array( + UnresolvedType::Boolean.into(), + Expression::U32Constant(8).into(), + ) + .into(), + ), FlatEmbed::U16ToBits => UnresolvedSignature::new() .inputs(vec![UnresolvedType::Uint(16).into()]) - .outputs(vec![UnresolvedType::array( - UnresolvedType::Boolean.into(), - Expression::U32Constant(16).into(), - ) - .into()]), + .output( + UnresolvedType::array( + UnresolvedType::Boolean.into(), + Expression::U32Constant(16).into(), + ) + .into(), + ), FlatEmbed::U32ToBits => UnresolvedSignature::new() .inputs(vec![UnresolvedType::Uint(32).into()]) - .outputs(vec![UnresolvedType::array( - UnresolvedType::Boolean.into(), - Expression::U32Constant(32).into(), - ) - .into()]), + .output( + UnresolvedType::array( + UnresolvedType::Boolean.into(), + Expression::U32Constant(32).into(), + ) + .into(), + ), FlatEmbed::U64ToBits => UnresolvedSignature::new() .inputs(vec![UnresolvedType::Uint(64).into()]) - .outputs(vec![UnresolvedType::array( - UnresolvedType::Boolean.into(), - Expression::U32Constant(64).into(), - ) - .into()]), + .output( + UnresolvedType::array( + UnresolvedType::Boolean.into(), + Expression::U32Constant(64).into(), + ) + .into(), + ), FlatEmbed::U8FromBits => UnresolvedSignature::new() - .outputs(vec![UnresolvedType::Uint(8).into()]) + .output(UnresolvedType::Uint(8).into()) .inputs(vec![UnresolvedType::array( UnresolvedType::Boolean.into(), Expression::U32Constant(8).into(), ) .into()]), FlatEmbed::U16FromBits => UnresolvedSignature::new() - .outputs(vec![UnresolvedType::Uint(16).into()]) + .output(UnresolvedType::Uint(16).into()) .inputs(vec![UnresolvedType::array( UnresolvedType::Boolean.into(), Expression::U32Constant(16).into(), ) .into()]), FlatEmbed::U32FromBits => UnresolvedSignature::new() - .outputs(vec![UnresolvedType::Uint(32).into()]) + .output(UnresolvedType::Uint(32).into()) .inputs(vec![UnresolvedType::array( UnresolvedType::Boolean.into(), Expression::U32Constant(32).into(), ) .into()]), FlatEmbed::U64FromBits => UnresolvedSignature::new() - .outputs(vec![UnresolvedType::Uint(64).into()]) + .output(UnresolvedType::Uint(64).into()) .inputs(vec![UnresolvedType::array( UnresolvedType::Boolean.into(), Expression::U32Constant(64).into(), @@ -144,11 +154,13 @@ impl FlatEmbed { ) .into(), ]) - .outputs(vec![UnresolvedType::array( - UnresolvedType::Boolean.into(), - Expression::U32Constant(256).into(), - ) - .into()]), + .output( + UnresolvedType::array( + UnresolvedType::Boolean.into(), + Expression::U32Constant(256).into(), + ) + .into(), + ), #[cfg(feature = "ark")] FlatEmbed::SnarkVerifyBls12377 => UnresolvedSignature::new() .generics(vec!["N".into(), "V".into()]) @@ -169,7 +181,7 @@ impl FlatEmbed { ) .into(), // 18 + (2 * n) // vk ]) - .outputs(vec![UnresolvedType::Boolean.into()]), + .output(UnresolvedType::Boolean.into()), } } @@ -189,60 +201,48 @@ impl FlatEmbed { GenericIdentifier::with_name("N").with_index(0), )), ]) - .outputs(vec![DeclarationType::Boolean]), + .output(DeclarationType::Boolean), FlatEmbed::Unpack => DeclarationSignature::new() .generics(vec![Some(DeclarationConstant::Generic( GenericIdentifier::with_name("N").with_index(0), ))]) .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::array(( + .output(DeclarationType::array(( DeclarationType::Boolean, GenericIdentifier::with_name("N").with_index(0), - ))]), + ))), FlatEmbed::U8ToBits => DeclarationSignature::new() .inputs(vec![DeclarationType::uint(8)]) - .outputs(vec![DeclarationType::array(( - DeclarationType::Boolean, - 8u32, - ))]), + .output(DeclarationType::array((DeclarationType::Boolean, 8u32))), FlatEmbed::U16ToBits => DeclarationSignature::new() .inputs(vec![DeclarationType::uint(16)]) - .outputs(vec![DeclarationType::array(( - DeclarationType::Boolean, - 16u32, - ))]), + .output(DeclarationType::array((DeclarationType::Boolean, 16u32))), FlatEmbed::U32ToBits => DeclarationSignature::new() .inputs(vec![DeclarationType::uint(32)]) - .outputs(vec![DeclarationType::array(( - DeclarationType::Boolean, - 32u32, - ))]), + .output(DeclarationType::array((DeclarationType::Boolean, 32u32))), FlatEmbed::U64ToBits => DeclarationSignature::new() .inputs(vec![DeclarationType::uint(64)]) - .outputs(vec![DeclarationType::array(( - DeclarationType::Boolean, - 64u32, - ))]), + .output(DeclarationType::array((DeclarationType::Boolean, 64u32))), FlatEmbed::U8FromBits => DeclarationSignature::new() - .outputs(vec![DeclarationType::uint(8)]) + .output(DeclarationType::uint(8)) .inputs(vec![DeclarationType::array(( DeclarationType::Boolean, 8u32, ))]), FlatEmbed::U16FromBits => DeclarationSignature::new() - .outputs(vec![DeclarationType::uint(16)]) + .output(DeclarationType::uint(16)) .inputs(vec![DeclarationType::array(( DeclarationType::Boolean, 16u32, ))]), FlatEmbed::U32FromBits => DeclarationSignature::new() - .outputs(vec![DeclarationType::uint(32)]) + .output(DeclarationType::uint(32)) .inputs(vec![DeclarationType::array(( DeclarationType::Boolean, 32u32, ))]), FlatEmbed::U64FromBits => DeclarationSignature::new() - .outputs(vec![DeclarationType::uint(64)]) + .output(DeclarationType::uint(64)) .inputs(vec![DeclarationType::array(( DeclarationType::Boolean, 64u32, @@ -253,10 +253,7 @@ impl FlatEmbed { DeclarationType::array((DeclarationType::Boolean, 512u32)), DeclarationType::array((DeclarationType::Boolean, 256u32)), ]) - .outputs(vec![DeclarationType::array(( - DeclarationType::Boolean, - 256u32, - ))]), + .output(DeclarationType::array((DeclarationType::Boolean, 256u32))), #[cfg(feature = "ark")] FlatEmbed::SnarkVerifyBls12377 => DeclarationSignature::new() .generics(vec![ @@ -278,7 +275,7 @@ impl FlatEmbed { GenericIdentifier::with_name("V").with_index(1), )), // 18 + (2 * n) // vk ]) - .outputs(vec![DeclarationType::Boolean]), + .output(DeclarationType::Boolean), } } diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 8ba4a69b..a8df6689 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -6,7 +6,7 @@ use crate::absy::Identifier; use crate::absy::*; -use crate::typed_absy::types::{GGenericsAssignment, GenericsAssignment}; +use crate::typed_absy::types::{GGenericsAssignment, GTupleType, GenericsAssignment}; use crate::typed_absy::*; use crate::typed_absy::{DeclarationParameter, DeclarationVariable, Variable}; use num_bigint::BigUint; @@ -182,8 +182,8 @@ struct FunctionQuery<'ast, T> { id: Identifier<'ast>, generics_count: Option, inputs: Vec>, - /// Output types are optional as we try to infer them - outputs: Vec>>, + /// Output type is optional as we try to infer it + output: Option>, } impl<'ast, T: fmt::Display> fmt::Display for FunctionQuery<'ast, T> { @@ -208,30 +208,14 @@ impl<'ast, T: fmt::Display> fmt::Display for FunctionQuery<'ast, T> { } write!(f, ")")?; - match self.outputs.len() { - 0 => write!(f, ""), - 1 => write!( - f, - " -> {}", - match &self.outputs[0] { - Some(t) => format!("{}", t), - None => "_".into(), - } - ), - _ => { - write!(f, " -> (")?; - for (i, t) in self.outputs.iter().enumerate() { - match t { - Some(t) => write!(f, "{}", t)?, - None => write!(f, "_")?, - } - if i < self.outputs.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, ")") - } - } + write!( + f, + " -> {}", + self.output + .as_ref() + .map(|o| o.to_string()) + .unwrap_or_else(|| "_".to_string()) + ) } } @@ -241,13 +225,13 @@ impl<'ast, T: Field> FunctionQuery<'ast, T> { id: Identifier<'ast>, generics: &Option>>>, inputs: &[Type<'ast, T>], - outputs: &[Option>], + output: Option>, ) -> Self { FunctionQuery { id, generics_count: generics.as_ref().map(|g| g.len()), inputs: inputs.to_owned(), - outputs: outputs.to_owned(), + output, } } @@ -261,17 +245,10 @@ impl<'ast, T: Field> FunctionQuery<'ast, T> { .iter() .zip(func.signature.inputs.iter()) .all(|(input_ty, sig_ty)| input_ty.can_be_specialized_to(sig_ty)) - && self.outputs.len() == func.signature.outputs.len() - && self - .outputs - .iter() - .zip(func.signature.outputs.iter()) - .all(|(output_ty, sig_ty)| { - output_ty - .as_ref() - .map(|output_ty| output_ty.can_be_specialized_to(sig_ty)) - .unwrap_or(true) - }) + && self.output + .as_ref() + .map(|o| o.can_be_specialized_to(&func.signature.output)) + .unwrap_or(true) } fn match_funcs( @@ -342,7 +319,7 @@ type Scope<'ast, T> = HashMap, Type<'ast, T>>; /// Checker checks the semantics of a program, keeping track of functions and variables in scope #[derive(Default)] pub struct Checker<'ast, T> { - return_types: Option>>, + return_type: Option>, scope: Scope<'ast, T>, functions: HashSet>, level: usize, @@ -1087,7 +1064,7 @@ impl<'ast, T: Field> Checker<'ast, T> { module_id: &ModuleId, state: &State<'ast, T>, ) -> Result, Vec> { - assert!(self.return_types.is_none()); + assert!(self.return_type.is_none()); self.enter_scope(); @@ -1176,29 +1153,6 @@ impl<'ast, T: Field> Checker<'ast, T> { match self.check_statement(stat, module_id, &state.types) { Ok(statement) => { - if let TypedStatement::Return(e) = &statement { - match e.iter().map(|e| e.get_type()).collect::>() - == s.outputs - { - true => {} - false => errors.push(ErrorInner { - pos, - message: format!( - "Expected ({}) in return statement, found ({})", - s.outputs - .iter() - .map(|t| t.to_string()) - .collect::>() - .join(", "), - e.iter() - .map(|e| e.get_type()) - .map(|t| t.to_string()) - .collect::>() - .join(", ") - ), - }), - } - }; statements_checked.push(statement); } Err(e) => { @@ -1227,7 +1181,7 @@ impl<'ast, T: Field> Checker<'ast, T> { return Err(errors); } - self.return_types = None; + self.return_type = None; Ok(TypedFunction { arguments: arguments_checked, @@ -1244,7 +1198,6 @@ impl<'ast, T: Field> Checker<'ast, T> { ) -> Result, Vec> { let mut errors = vec![]; let mut inputs = vec![]; - let mut outputs = vec![]; let mut generics = vec![]; let mut generics_map = BTreeMap::new(); @@ -1297,34 +1250,35 @@ impl<'ast, T: Field> Checker<'ast, T> { } } - for t in signature.outputs { - match self.check_declaration_type( - t, - module_id, - state, - &generics_map, - &mut HashSet::default(), - ) { - Ok(t) => { - outputs.push(t); - } - Err(e) => { - errors.push(e); + match signature + .output + .map(|o| { + self.check_declaration_type( + o, + module_id, + state, + &generics_map, + &mut HashSet::default(), + ) + }) + .unwrap_or_else(|| Ok(DeclarationType::Tuple(GTupleType::new(vec![])))) + { + Ok(output) => { + if !errors.is_empty() { + return Err(errors); } + + self.return_type = Some(output.clone()); + Ok(DeclarationSignature::new() + .generics(generics) + .inputs(inputs) + .output(output)) + } + Err(e) => { + errors.push(e); + Err(errors) } } - - if !errors.is_empty() { - return Err(errors); - } - - self.return_types = Some(outputs.clone()); - - Ok(DeclarationSignature { - generics, - inputs, - outputs, - }) } fn check_type( @@ -1752,74 +1706,50 @@ impl<'ast, T: Field> Checker<'ast, T> { let pos = stat.pos(); match stat.value { - Statement::Return(e) => { - let mut expression_list_checked = vec![]; + Statement::Return(None) => Ok(TypedStatement::Return( + TupleExpressionInner::Value(vec![]) + .annotate(TupleType::new(vec![])) + .into(), + )), + Statement::Return(Some(e)) => { let mut errors = vec![]; - // we clone the return types because there might be other return statements - let return_types = self.return_types.clone().unwrap(); + // we clone the return type because there might be other return statements + let return_type = self.return_type.clone().unwrap(); - for e in e.value.expressions.into_iter() { - let e_checked = self - .check_expression(e, module_id, types) - .map_err(|e| vec![e])?; - expression_list_checked.push(e_checked); - } + let e_checked = self + .check_expression(e, module_id, types) + .map_err(|e| vec![e])?; - let res = match expression_list_checked.len() == return_types.len() { - true => match expression_list_checked - .clone() - .into_iter() - .zip(return_types.iter()) - .map(|(e, t)| TypedExpression::align_to_type(e, t)) - .collect::, _>>() - .map_err(|e| { - vec![ErrorInner { - pos: Some(pos), - message: format!( - "Expected return value to be of type {}, found {}", - e.1, e.0 - ), - }] - }) { - Ok(e) => { - match e.iter().map(|e| e.get_type()).collect::>() == return_types - { - true => {} - false => errors.push(ErrorInner { - pos: Some(pos), - message: format!( - "Expected ({}) in return statement, found ({})", - return_types - .iter() - .map(|t| t.to_string()) - .collect::>() - .join(", "), - e.iter() - .map(|e| e.get_type()) - .map(|t| t.to_string()) - .collect::>() - .join(", ") - ), - }), - }; - TypedStatement::Return(e) - } - Err(err) => { - errors.extend(err); - TypedStatement::Return(expression_list_checked) - } - }, - false => { - errors.push(ErrorInner { + let res = match TypedExpression::align_to_type(e_checked.clone(), &return_type) + .map_err(|e| { + vec![ErrorInner { pos: Some(pos), message: format!( - "Expected {} expressions in return statement, found {}", - return_types.len(), - expression_list_checked.len() + "Expected return value to be of type `{}`, found `{}` of type `{}`", + e.1, + e.0, + e.0.get_type() ), - }); - TypedStatement::Return(expression_list_checked) + }] + }) { + Ok(e) => { + match e.get_type() == return_type { + true => {} + false => errors.push(ErrorInner { + pos: Some(pos), + message: format!( + "Expected `{}` in return statement, found `{}`", + return_type, + e.get_type() + ), + }), + } + TypedStatement::Return(e) + } + Err(err) => { + errors.extend(err); + TypedStatement::Return(e_checked) } }; @@ -1841,59 +1771,193 @@ impl<'ast, T: Field> Checker<'ast, T> { .map_err(|e| vec![e]) } Statement::Definition(assignee, expr) => { - // we create multidef when rhs is a function call to benefit from inference - // check rhs is not a function call here - if let Expression::FunctionCall(..) = expr.value { - panic!("Parser should not generate Definition where the right hand side is a FunctionCall") + match expr.value { + Expression::FunctionCall(fun_id_expression, generics, arguments) => { + let fun_id = match fun_id_expression.value { + Expression::Identifier(id) => Ok(id), + e => Err(vec![ErrorInner { + pos: Some(pos), + message: format!( + "Expected function in function call to be an identifier, found {}", + e + ), + }]) + }?; + + // check the generic arguments, if any + let generics_checked: Option>>> = generics + .map(|generics| { + generics + .into_iter() + .map(|g| { + g.map(|g| { + let pos = g.pos(); + self.check_expression(g, module_id, types).and_then( + |g| { + UExpression::try_from_typed(g, &UBitwidth::B32) + .map_err(|e| ErrorInner { + pos: Some(pos), + message: format!( + "Expected {} to be of type u32, found {}", + e, + e.get_type(), + ), + }) + }, + ) + }) + .transpose() + }) + .collect::>() + }) + .transpose() + .map_err(|e| vec![e])?; + + let assignee = self + .check_assignee(assignee, module_id, types) + .map_err(|e| vec![e])?; + + // find argument types + let mut arguments_checked = vec![]; + for arg in arguments { + let arg_checked = self + .check_expression(arg, module_id, types) + .map_err(|e| vec![e])?; + arguments_checked.push(arg_checked); + } + + let arguments_types: Vec<_> = + arguments_checked.iter().map(|a| a.get_type()).collect(); + + let query = FunctionQuery::new( + fun_id, + &generics_checked, + &arguments_types, + Some(assignee.get_type()), + ); + + let functions = self.find_functions(&query); + + match functions.len() { + // the function has to be defined + 1 => { + + let mut functions = functions; + let f = functions.pop().unwrap(); + + let signature = f.signature; + + let arguments_checked = arguments_checked.into_iter().zip(signature.inputs.iter()).map(|(a, t)| TypedExpression::align_to_type(a, t)).collect::, _>>().map_err(|e| ErrorInner { + pos: Some(pos), + message: format!("Expected function call argument to be of type `{}`, found `{}` of type `{}`", e.1, e.0, e.0.get_type()) + }).map_err(|e| vec![e])?; + + let generics_checked = generics_checked.unwrap_or_else(|| vec![None; signature.generics.len()]); + + let output_type = assignee.get_type(); + + let function_key = DeclarationFunctionKey { + module: module_id.to_path_buf(), + id: f.id, + signature: signature.clone(), + }; + + let call = match output_type { + Type::Int => unreachable!(), + Type::FieldElement => FieldElementExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).into(), + Type::Boolean => BooleanExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).into(), + Type::Uint(bitwidth) => UExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).annotate(bitwidth).into(), + Type::Struct(struct_ty) => StructExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).annotate(struct_ty).into(), + Type::Array(array_ty) => ArrayExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).annotate(*array_ty.ty, *array_ty.size).into(), + Type::Tuple(tuple_ty) => TupleExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).annotate(tuple_ty).into(), + }; + + Ok(TypedStatement::Definition(assignee, call)) + }, + 0 => Err(ErrorInner { + pos: Some(pos), + message: format!("Function definition for function {} with signature {} not found.", fun_id, query) + }), + n => Err(ErrorInner { + pos: Some(pos), + message: format!("Ambiguous call to function {}, {} candidates were found. Please be more explicit.", fun_id, n) + }) + }.map_err(|e| vec![e]) + } + _ => { + // check the expression to be assigned + let checked_expr = self + .check_expression(expr, module_id, types) + .map_err(|e| vec![e])?; + + // check that the assignee is declared and is well formed + let var = self + .check_assignee(assignee, module_id, types) + .map_err(|e| vec![e])?; + + let var_type = var.get_type(); + + // make sure the assignee has the same type as the rhs + match var_type { + Type::FieldElement => FieldElementExpression::try_from_typed(checked_expr) + .map(TypedExpression::from), + Type::Boolean => { + BooleanExpression::try_from_typed(checked_expr).map(TypedExpression::from) + } + Type::Uint(bitwidth) => UExpression::try_from_typed(checked_expr, &bitwidth) + .map(TypedExpression::from), + Type::Array(ref array_ty) => { + ArrayExpression::try_from_typed(checked_expr, array_ty) + .map(TypedExpression::from) + } + Type::Struct(ref struct_ty) => { + StructExpression::try_from_typed(checked_expr, struct_ty) + .map(TypedExpression::from) + } + Type::Tuple(ref tuple_ty) => { + TupleExpression::try_from_typed(checked_expr, tuple_ty) + .map(TypedExpression::from) + } + Type::Int => Err(checked_expr), // Integers cannot be assigned + } + .map_err(|e| ErrorInner { + pos: Some(pos), + message: format!( + "Expression `{}` of type `{}` cannot be assigned to `{}` of type `{}`", + e, + e.get_type(), + var.clone(), + var_type + ), + }) + .map(|rhs| TypedStatement::Definition(var, rhs)) + .map_err(|e| vec![e]) + } } - - // check the expression to be assigned - let checked_expr = self - .check_expression(expr, module_id, types) - .map_err(|e| vec![e])?; - - // check that the assignee is declared and is well formed - let var = self - .check_assignee(assignee, module_id, types) - .map_err(|e| vec![e])?; - - let var_type = var.get_type(); - - // make sure the assignee has the same type as the rhs - match var_type { - Type::FieldElement => FieldElementExpression::try_from_typed(checked_expr) - .map(TypedExpression::from), - Type::Boolean => { - BooleanExpression::try_from_typed(checked_expr).map(TypedExpression::from) - } - Type::Uint(bitwidth) => UExpression::try_from_typed(checked_expr, &bitwidth) - .map(TypedExpression::from), - Type::Array(ref array_ty) => { - ArrayExpression::try_from_typed(checked_expr, array_ty) - .map(TypedExpression::from) - } - Type::Struct(ref struct_ty) => { - StructExpression::try_from_typed(checked_expr, struct_ty) - .map(TypedExpression::from) - } - Type::Tuple(ref tuple_ty) => { - TupleExpression::try_from_typed(checked_expr, tuple_ty) - .map(TypedExpression::from) - } - Type::Int => Err(checked_expr), // Integers cannot be assigned - } - .map_err(|e| ErrorInner { - pos: Some(pos), - message: format!( - "Expression `{}` of type `{}` cannot be assigned to `{}` of type `{}`", - e, - e.get_type(), - var.clone(), - var_type - ), - }) - .map(|rhs| TypedStatement::Definition(var, rhs)) - .map_err(|e| vec![e]) } Statement::Assertion(e, message) => { let e = self @@ -1929,101 +1993,6 @@ impl<'ast, T: Field> Checker<'ast, T> { res } - Statement::MultipleDefinition(assignees, rhs) => { - match rhs.value { - // Right side has to be a function call - Expression::FunctionCall(fun_id_expression, generics, arguments) => { - - let fun_id = match fun_id_expression.value { - Expression::Identifier(id) => Ok(id), - e => Err(vec![ErrorInner { - pos: Some(pos), - message: format!( - "Expected function in function call to be an identifier, found {}", - e - ), - }]) - }?; - - // check the generic arguments, if any - let generics_checked: Option>>> = generics - .map(|generics| - generics.into_iter().map(|g| - g.map(|g| { - let pos = g.pos(); - self.check_expression(g, module_id, types).and_then(|g| { - UExpression::try_from_typed(g, &UBitwidth::B32).map_err( - |e| ErrorInner { - pos: Some(pos), - message: format!( - "Expected {} to be of type u32, found {}", - e, - e.get_type(), - ), - }, - ) - }) - }) - .transpose() - ) - .collect::>() - ).transpose().map_err(|e| vec![e])?; - - // check lhs assignees are defined - let (assignees, errors): (Vec<_>, Vec<_>) = assignees.into_iter().map(|a| self.check_assignee(a, module_id, types)).partition(|r| r.is_ok()); - - if !errors.is_empty() { - return Err(errors.into_iter().map(|e| e.unwrap_err()).collect()); - } - - let assignees: Vec<_> = assignees.into_iter().map(|a| a.unwrap()).collect(); - - let assignee_types: Vec<_> = assignees.iter().map(|a| Some(a.get_type().clone())).collect(); - - // find argument types - let mut arguments_checked = vec![]; - for arg in arguments { - let arg_checked = self.check_expression(arg, module_id, types).map_err(|e| vec![e])?; - arguments_checked.push(arg_checked); - } - - let arguments_types: Vec<_> = - arguments_checked.iter().map(|a| a.get_type()).collect(); - - let query = FunctionQuery::new(fun_id, &generics_checked, &arguments_types, &assignee_types); - - let functions = self.find_functions(&query); - - match functions.len() { - // the function has to be defined - 1 => { - - let mut functions = functions; - let f = functions.pop().unwrap(); - - let arguments_checked = arguments_checked.into_iter().zip(f.signature.inputs.iter()).map(|(a, t)| TypedExpression::align_to_type(a, t)).collect::, _>>().map_err(|e| vec![ErrorInner { - pos: Some(pos), - message: format!("Expected function call argument to be of type {}, found {} of type {}", e.1, e.0, e.0.get_type()) - }])?; - - let call = TypedExpressionList::function_call(f.clone(), generics_checked.unwrap_or_else(|| vec![None; f.signature.generics.len()]), arguments_checked).annotate(Types { inner: assignees.iter().map(|a| a.get_type()).collect()}); - - Ok(TypedStatement::MultipleDefinition(assignees, call)) - }, - 0 => Err(ErrorInner { pos: Some(pos), - message: format!("Function definition for function {} with signature {} not found.", fun_id, query) }), - n => Err(ErrorInner { - pos: Some(pos), - message: format!("Ambiguous call to function {}, {} candidates were found. Please be more explicit.", fun_id, n) - }) - } - } - _ => Err(ErrorInner { - pos: Some(pos), - message: format!("{} should be a function call", rhs), - }), - }.map_err(|e| vec![e]) - } } } @@ -2211,7 +2180,7 @@ impl<'ast, T: Field> Checker<'ast, T> { } Type::Array(array_type) => { Ok(ArrayExpressionInner::Identifier(id.id.into()) - .annotate(*array_type.ty, array_type.size) + .annotate(*array_type.ty, *array_type.size) .into()) } Type::Struct(members) => { @@ -2576,15 +2545,11 @@ impl<'ast, T: Field> Checker<'ast, T> { arguments_checked.push(arg_checked); } - let mut arguments_types = vec![]; - for arg in arguments_checked.iter() { - arguments_types.push(arg.get_type()); - } + let arguments_types: Vec<_> = + arguments_checked.iter().map(|a| a.get_type()).collect(); - // outside of multidef, function calls must have a single return value // we use type inference to determine the type of the return, so we don't specify it - let query = - FunctionQuery::new(fun_id, &generics_checked, &arguments_types, &[None]); + let query = FunctionQuery::new(fun_id, &generics_checked, &arguments_types, None); let functions = self.find_functions(&query); @@ -2599,12 +2564,12 @@ impl<'ast, T: Field> Checker<'ast, T> { let arguments_checked = arguments_checked.into_iter().zip(signature.inputs.iter()).map(|(a, t)| TypedExpression::align_to_type(a, t)).collect::, _>>().map_err(|e| ErrorInner { pos: Some(pos), - message: format!("Expected function call argument to be of type {}, found {}", e.1, e.0) + message: format!("Expected function call argument to be of type `{}`, found `{}` of type `{}`", e.1, e.0, e.0.get_type()) })?; let generics_checked = generics_checked.unwrap_or_else(|| vec![None; signature.generics.len()]); - let mut output_types = signature.get_output_types( + let output_type = signature.get_output_type( generics_checked.clone(), arguments_checked.iter().map(|a| a.get_type()).collect() ).map_err(|e| ErrorInner { @@ -2621,54 +2586,42 @@ impl<'ast, T: Field> Checker<'ast, T> { signature: signature.clone(), }; - // the return count has to be 1 - match output_types.len() { - 1 => match output_types.pop().unwrap() { - Type::Int => unreachable!(), - Type::FieldElement => Ok(FieldElementExpression::function_call( - function_key, - generics_checked, - arguments_checked, - ).into()), - Type::Boolean => Ok(BooleanExpression::function_call( - function_key, - generics_checked, - arguments_checked, - ).into()), - Type::Uint(bitwidth) => Ok(UExpression::function_call( - function_key, - generics_checked, - arguments_checked, - ).annotate(bitwidth).into()), - Type::Struct(struct_ty) => Ok(StructExpression::function_call( - function_key, - generics_checked, - arguments_checked, - ).annotate(struct_ty).into()), - Type::Array(array_ty) => Ok(ArrayExpression::function_call( - function_key, - generics_checked, - arguments_checked, - ).annotate(*array_ty.ty, array_ty.size).into()), - Type::Tuple(tuple_ty) => Ok(TupleExpression::function_call( - function_key, - generics_checked, - arguments_checked, - ).annotate(tuple_ty).into()), - }, - n => Err(ErrorInner { - pos: Some(pos), - - message: format!( - "{} returns {} values but is called outside of a definition", - f.id, n - ), - }), + match output_type { + Type::Int => unreachable!(), + Type::FieldElement => Ok(FieldElementExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).into()), + Type::Boolean => Ok(BooleanExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).into()), + Type::Uint(bitwidth) => Ok(UExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).annotate(bitwidth).into()), + Type::Struct(struct_ty) => Ok(StructExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).annotate(struct_ty).into()), + Type::Array(array_ty) => Ok(ArrayExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).annotate(*array_ty.ty, *array_ty.size).into()), + Type::Tuple(tuple_ty) => Ok(TupleExpression::function_call( + function_key, + generics_checked, + arguments_checked, + ).annotate(tuple_ty).into()), } } 0 => Err(ErrorInner { pos: Some(pos), - message: format!( "Function definition for function {} with signature {} not found.", fun_id, query @@ -3621,6 +3574,7 @@ impl<'ast, T: Field> Checker<'ast, T> { mod tests { use super::*; use crate::absy; + use crate::absy::Expression; use crate::typed_absy; use lazy_static::lazy_static; use zokrates_field::Bn128Field; @@ -3713,15 +3667,9 @@ mod tests { } } - /// Helper function to create ((): return) + /// Helper function to create: def function0() { return; } fn function0() -> FunctionNode<'static> { - let statements = vec![Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock()]; + let statements = vec![Statement::Return(None).mock()]; let arguments = vec![]; @@ -3735,15 +3683,9 @@ mod tests { .mock() } - /// Helper function to create ((private field a): return) + /// Helper function to create def function1(private field a) { return; } fn function1() -> FunctionNode<'static> { - let statements = vec![Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock()]; + let statements = vec![Statement::Return(None).mock()]; let arguments = vec![absy::Parameter { id: absy::Variable::new("a", UnresolvedType::FieldElement.mock()).mock(), @@ -4353,7 +4295,7 @@ mod tests { scope, functions, level, - return_types: None, + return_type: None, } } @@ -4397,15 +4339,17 @@ mod tests { Expression::Identifier("L").mock(), ) .mock()]) - .outputs(vec![UnresolvedType::Array( - box UnresolvedType::Array( - box UnresolvedType::FieldElement.mock(), - Expression::Identifier("L").mock(), + .output( + UnresolvedType::Array( + box UnresolvedType::Array( + box UnresolvedType::FieldElement.mock(), + Expression::Identifier("L").mock(), + ) + .mock(), + Expression::Identifier("K").mock(), ) .mock(), - Expression::Identifier("K").mock(), - ) - .mock()]); + ); assert_eq!( Checker::::default().check_signature(signature, &*MODULE_ID, &state), Ok(DeclarationSignature::new() @@ -4416,13 +4360,13 @@ mod tests { )), GenericIdentifier::with_name("L").with_index(1) ))]) - .outputs(vec![DeclarationType::array(( + .output(DeclarationType::array(( DeclarationType::array(( DeclarationType::FieldElement, GenericIdentifier::with_name("L").with_index(1) )), GenericIdentifier::with_name("K").with_index(0) - ))])) + )))) ); } } @@ -4507,13 +4451,7 @@ mod tests { Expression::IntConstant(1usize.into()).mock(), ) .mock(), - Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock(), + Statement::Return(None).mock(), ]; let foo = Function { arguments: foo_args, @@ -4523,20 +4461,15 @@ mod tests { .mock(); let bar_args = vec![]; - let bar_statements = vec![Statement::Return( - ExpressionList { - expressions: vec![Expression::Identifier("a").mock()], - } - .mock(), - ) - .mock()]; + let bar_statements = + vec![Statement::Return(Some(Expression::Identifier("a").mock())).mock()]; let bar = Function { arguments: bar_args, statements: bar_statements, signature: UnresolvedSignature::new() .inputs(vec![]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), + .output(UnresolvedType::FieldElement.mock()), } .mock(); @@ -4595,13 +4528,7 @@ mod tests { Expression::IntConstant(1usize.into()).mock(), ) .mock(), - Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock(), + Statement::Return(None).mock(), ]; let foo = Function { @@ -4622,13 +4549,7 @@ mod tests { Expression::IntConstant(2usize.into()).mock(), ) .mock(), - Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock(), + Statement::Return(None).mock(), ]; let bar = Function { arguments: bar_args, @@ -4638,20 +4559,15 @@ mod tests { .mock(); let main_args = vec![]; - let main_statements = vec![Statement::Return( - ExpressionList { - expressions: vec![Expression::IntConstant(1usize.into()).mock()], - } - .mock(), - ) - .mock()]; + let main_statements = + vec![Statement::Return(Some(Expression::IntConstant(1usize.into()).mock())).mock()]; let main = Function { arguments: main_args, statements: main_statements, signature: UnresolvedSignature::new() .inputs(vec![]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), + .output(UnresolvedType::FieldElement.mock()), } .mock(); @@ -4696,20 +4612,14 @@ mod tests { vec![], ) .mock(), - Statement::Return( - ExpressionList { - expressions: vec![Expression::Identifier("i").mock()], - } - .mock(), - ) - .mock(), + Statement::Return(Some(Expression::Identifier("i").mock())).mock(), ]; let foo = Function { arguments: vec![], statements: foo_statements, signature: UnresolvedSignature::new() .inputs(vec![]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), + .output(UnresolvedType::FieldElement.mock()), } .mock(); @@ -4756,13 +4666,7 @@ mod tests { for_statements, ) .mock(), - Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock(), + Statement::Return(None).mock(), ]; let for_statements_checked = vec![ @@ -4782,7 +4686,11 @@ mod tests { 10u32.into(), for_statements_checked, ), - TypedStatement::Return(vec![]), + TypedStatement::Return( + TupleExpressionInner::Value(vec![]) + .annotate(TupleType::new(vec![])) + .into(), + ), ]; let foo = Function { @@ -4810,8 +4718,8 @@ mod tests { #[test] fn arity_mismatch() { - // def foo() { - // return 1, 2; + // def foo() -> bool { + // return true; // } // def bar() { // field a = foo(); @@ -4823,28 +4731,21 @@ mod tests { absy::Variable::new("a", UnresolvedType::FieldElement.mock()).mock(), ) .mock(), - Statement::MultipleDefinition( - vec![Assignee::Identifier("a").mock()], + Statement::Definition( + Assignee::Identifier("a").mock(), Expression::FunctionCall(box Expression::Identifier("foo").mock(), None, vec![]) .mock(), ) .mock(), - Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock(), + Statement::Return(None).mock(), ]; let foo = DeclarationFunctionKey { module: (*MODULE_ID).clone(), id: "foo", - signature: DeclarationSignature::new().inputs(vec![]).outputs(vec![ - DeclarationType::FieldElement, - DeclarationType::FieldElement, - ]), + signature: DeclarationSignature::new() + .inputs(vec![]) + .output(DeclarationType::Boolean), }; let functions = vec![foo].into_iter().collect(); @@ -4872,73 +4773,7 @@ mod tests { } #[test] - fn multi_return_outside_multidef() { - // def foo() -> (field, field) { - // return 1, 2; - // } - // def bar() { - // assert(2 == foo()); - // return; - // } - // should fail - let bar_statements: Vec = vec![ - Statement::Assertion( - Expression::Eq( - box Expression::IntConstant(2usize.into()).mock(), - box Expression::FunctionCall( - box Expression::Identifier("foo").mock(), - None, - vec![], - ) - .mock(), - ) - .mock(), - None, - ) - .mock(), - Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock(), - ]; - - let foo = DeclarationFunctionKey { - module: (*MODULE_ID).clone(), - id: "foo", - signature: DeclarationSignature::new().inputs(vec![]).outputs(vec![ - DeclarationType::FieldElement, - DeclarationType::FieldElement, - ]), - }; - - let functions = vec![foo].into_iter().collect(); - - let bar = Function { - arguments: vec![], - statements: bar_statements, - signature: UnresolvedSignature::new(), - } - .mock(); - - let modules = Modules::new(); - let state = State::new(modules); - - let mut checker: Checker = new_with_args(HashMap::new(), 0, functions); - assert_eq!( - checker.check_function(bar, &*MODULE_ID, &state), - Err(vec![ErrorInner { - pos: Some((Position::mock(), Position::mock())), - message: "Function definition for function foo with signature () -> _ not found." - .into() - }]) - ); - } - - #[test] - fn function_undefined_in_multidef() { + fn function_undefined_in_definition() { // def bar() { // field a = foo(); // return; @@ -4949,19 +4784,13 @@ mod tests { absy::Variable::new("a", UnresolvedType::FieldElement.mock()).mock(), ) .mock(), - Statement::MultipleDefinition( - vec![Assignee::Identifier("a").mock()], + Statement::Definition( + Assignee::Identifier("a").mock(), Expression::FunctionCall(box Expression::Identifier("foo").mock(), None, vec![]) .mock(), ) .mock(), - Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock(), + Statement::Return(None).mock(), ]; let bar = Function { @@ -4988,72 +4817,36 @@ mod tests { } #[test] - fn undefined_variable_in_multireturn_call() { - // def foo(field x) { - // return 1, 2; - // } - // def main() -> field { - // a, b = foo(x); + fn undeclared_variable() { + // def foo() -> field { // return 1; // } + // def main() { + // a = foo(); + // return; + // } // should fail - let foo_statements: Vec = vec![Statement::Return( - ExpressionList { - expressions: vec![ - Expression::IntConstant(1usize.into()).mock(), - Expression::IntConstant(2usize.into()).mock(), - ], - } - .mock(), - ) - .mock()]; + let foo_statements: Vec = + vec![Statement::Return(Some(Expression::IntConstant(1usize.into()).mock())).mock()]; let foo = Function { - arguments: vec![crate::absy::Parameter { - id: absy::Variable::new("x", UnresolvedType::FieldElement.mock()).mock(), - private: false, - } - .mock()], + arguments: vec![], statements: foo_statements, signature: UnresolvedSignature::new() - .inputs(vec![UnresolvedType::FieldElement.mock()]) - .outputs(vec![ - UnresolvedType::FieldElement.mock(), - UnresolvedType::FieldElement.mock(), - ]), + .inputs(vec![]) + .output(UnresolvedType::FieldElement.mock()), } .mock(); let main_statements: Vec = vec![ - Statement::Declaration( - absy::Variable::new("a", UnresolvedType::FieldElement.mock()).mock(), - ) - .mock(), - Statement::Declaration( - absy::Variable::new("b", UnresolvedType::FieldElement.mock()).mock(), - ) - .mock(), - Statement::MultipleDefinition( - vec![ - Assignee::Identifier("a").mock(), - Assignee::Identifier("b").mock(), - ], - Expression::FunctionCall( - box Expression::Identifier("foo").mock(), - None, - vec![Expression::Identifier("x").mock()], - ) - .mock(), - ) - .mock(), - Statement::Return( - ExpressionList { - expressions: vec![Expression::IntConstant(1usize.into()).mock()], - } - .mock(), + Statement::Definition( + Assignee::Identifier("a").mock(), + Expression::FunctionCall(box Expression::Identifier("foo").mock(), None, vec![]) + .mock(), ) .mock(), + Statement::Return(None).mock(), ]; let main = Function { @@ -5061,7 +4854,7 @@ mod tests { statements: main_statements, signature: UnresolvedSignature::new() .inputs(vec![]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), + .output(UnresolvedType::Tuple(vec![]).mock()), } .mock(); @@ -5089,111 +4882,13 @@ mod tests { Err(vec![Error { inner: ErrorInner { pos: Some((Position::mock(), Position::mock())), - message: "Identifier \"x\" is undefined".into() + message: "Variable `a` is undeclared".into() }, module_id: (*MODULE_ID).clone() }]) ); } - #[test] - fn undeclared_variables() { - // def foo() -> (field, field) { - // return 1, 2; - // } - // def main() { - // a, b = foo(); - // return; - // } - // should fail - - let foo_statements: Vec = vec![Statement::Return( - ExpressionList { - expressions: vec![ - Expression::IntConstant(1usize.into()).mock(), - Expression::IntConstant(2usize.into()).mock(), - ], - } - .mock(), - ) - .mock()]; - - let foo = Function { - arguments: vec![], - statements: foo_statements, - signature: UnresolvedSignature::new().inputs(vec![]).outputs(vec![ - UnresolvedType::FieldElement.mock(), - UnresolvedType::FieldElement.mock(), - ]), - } - .mock(); - - let main_statements: Vec = vec![ - Statement::MultipleDefinition( - vec![ - Assignee::Identifier("a").mock(), - Assignee::Identifier("b").mock(), - ], - Expression::FunctionCall(box Expression::Identifier("foo").mock(), None, vec![]) - .mock(), - ) - .mock(), - Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock(), - ]; - - let main = Function { - arguments: vec![], - statements: main_statements, - signature: UnresolvedSignature::new().inputs(vec![]).outputs(vec![]), - } - .mock(); - - let module = Module { - symbols: vec![ - SymbolDeclaration { - id: "foo", - symbol: Symbol::Here(SymbolDefinition::Function(foo)), - } - .mock(), - SymbolDeclaration { - id: "main", - symbol: Symbol::Here(SymbolDefinition::Function(main)), - } - .mock(), - ], - }; - - let mut state = - State::::new(vec![((*MODULE_ID).clone(), module)].into_iter().collect()); - - let mut checker: Checker = new_with_args(HashMap::new(), 0, HashSet::new()); - assert_eq!( - checker.check_module(&*MODULE_ID, &mut state), - Err(vec![ - Error { - inner: ErrorInner { - pos: Some((Position::mock(), Position::mock())), - message: "Variable `a` is undeclared".into() - }, - module_id: (*MODULE_ID).clone() - }, - Error { - inner: ErrorInner { - pos: Some((Position::mock(), Position::mock())), - message: "Variable `b` is undeclared".into() - }, - module_id: (*MODULE_ID).clone() - } - ]) - ); - } - #[test] fn assign_to_select() { // def foo() -> field { @@ -5206,20 +4901,15 @@ mod tests { // } // should succeed - let foo_statements: Vec = vec![Statement::Return( - ExpressionList { - expressions: vec![Expression::IntConstant(1usize.into()).mock()], - } - .mock(), - ) - .mock()]; + let foo_statements: Vec = + vec![Statement::Return(Some(Expression::IntConstant(1usize.into()).mock())).mock()]; let foo = Function { arguments: vec![], statements: foo_statements, signature: UnresolvedSignature::new() .inputs(vec![]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), + .output(UnresolvedType::FieldElement.mock()), } .mock(); @@ -5244,31 +4934,27 @@ mod tests { .mock(), ) .mock(), - Statement::MultipleDefinition( - vec![Assignee::Select( + Statement::Definition( + Assignee::Select( box Assignee::Identifier("a").mock(), box RangeOrExpression::Expression( absy::Expression::IntConstant(0usize.into()).mock(), ), ) - .mock()], + .mock(), Expression::FunctionCall(box Expression::Identifier("foo").mock(), None, vec![]) .mock(), ) .mock(), - Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock(), + Statement::Return(None).mock(), ]; let main = Function { arguments: vec![], statements: main_statements, - signature: UnresolvedSignature::new().inputs(vec![]).outputs(vec![]), + signature: UnresolvedSignature::new() + .inputs(vec![]) + .output(UnresolvedType::Tuple(vec![]).mock()), } .mock(); @@ -5317,13 +5003,7 @@ mod tests { None, ) .mock(), - Statement::Return( - ExpressionList { - expressions: vec![], - } - .mock(), - ) - .mock(), + Statement::Return(None).mock(), ]; let bar = Function { @@ -5351,27 +5031,18 @@ mod tests { #[test] fn return_undefined() { // def bar() { - // return a, b; + // return a; // } // should fail - let bar_statements: Vec = vec![Statement::Return( - ExpressionList { - expressions: vec![ - Expression::Identifier("a").mock(), - Expression::Identifier("b").mock(), - ], - } - .mock(), - ) - .mock()]; + let bar_statements: Vec = + vec![Statement::Return(Some(Expression::Identifier("a").mock())).mock()]; let bar = Function { arguments: vec![], statements: bar_statements, - signature: UnresolvedSignature::new().inputs(vec![]).outputs(vec![ - UnresolvedType::FieldElement.mock(), - UnresolvedType::FieldElement.mock(), - ]), + signature: UnresolvedSignature::new() + .inputs(vec![]) + .output(UnresolvedType::FieldElement.mock()), } .mock(); @@ -5388,114 +5059,6 @@ mod tests { ); } - #[test] - fn multi_def() { - // def foo() -> (field, field) { - // return 1, 2; - // } - // def bar() { - // field a, field b = foo(); - // return a + b; - // } - // - // should pass - let bar_statements: Vec = vec![ - Statement::Declaration( - absy::Variable::new("a", UnresolvedType::FieldElement.mock()).mock(), - ) - .mock(), - Statement::Declaration( - absy::Variable::new("b", UnresolvedType::FieldElement.mock()).mock(), - ) - .mock(), - Statement::MultipleDefinition( - vec![ - Assignee::Identifier("a").mock(), - Assignee::Identifier("b").mock(), - ], - Expression::FunctionCall(box Expression::Identifier("foo").mock(), None, vec![]) - .mock(), - ) - .mock(), - Statement::Return( - ExpressionList { - expressions: vec![Expression::Add( - box Expression::Identifier("a").mock(), - box Expression::Identifier("b").mock(), - ) - .mock()], - } - .mock(), - ) - .mock(), - ]; - - let bar_statements_checked: Vec> = vec![ - TypedStatement::Declaration(typed_absy::Variable::field_element("a")), - TypedStatement::Declaration(typed_absy::Variable::field_element("b")), - TypedStatement::MultipleDefinition( - vec![ - typed_absy::Variable::field_element("a").into(), - typed_absy::Variable::field_element("b").into(), - ], - TypedExpressionList::function_call( - DeclarationFunctionKey::with_location((*MODULE_ID).clone(), "foo").signature( - DeclarationSignature::new().outputs(vec![ - DeclarationType::FieldElement, - DeclarationType::FieldElement, - ]), - ), - vec![], - vec![], - ) - .annotate(Types::new(vec![Type::FieldElement, Type::FieldElement])), - ), - TypedStatement::Return(vec![FieldElementExpression::Add( - box FieldElementExpression::Identifier("a".into()), - box FieldElementExpression::Identifier("b".into()), - ) - .into()]), - ]; - - let foo = DeclarationFunctionKey { - module: (*MODULE_ID).clone(), - id: "foo", - signature: DeclarationSignature::new().inputs(vec![]).outputs(vec![ - DeclarationType::FieldElement, - DeclarationType::FieldElement, - ]), - }; - - let mut functions = HashSet::new(); - functions.insert(foo); - - let bar = Function { - arguments: vec![], - statements: bar_statements, - signature: UnresolvedSignature::new() - .inputs(vec![]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), - } - .mock(); - - let bar_checked = TypedFunction { - arguments: vec![], - statements: bar_statements_checked, - signature: DeclarationSignature::new() - .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), - }; - - let modules = Modules::new(); - let state = State::new(modules); - - let mut checker: Checker = new_with_args(HashMap::new(), 0, functions); - assert_eq!( - checker.check_function(bar, &*MODULE_ID, &state), - Ok(bar_checked) - ); - } - #[test] fn duplicate_argument_name() { // def main(field a, bool a) { @@ -5543,13 +5106,8 @@ mod tests { // } // // should fail - let main1_statements: Vec = vec![Statement::Return( - ExpressionList { - expressions: vec![Expression::IntConstant(1usize.into()).mock()], - } - .mock(), - ) - .mock()]; + let main1_statements: Vec = + vec![Statement::Return(Some(Expression::IntConstant(1usize.into()).mock())).mock()]; let main1_arguments = vec![crate::absy::Parameter { id: absy::Variable::new("a", UnresolvedType::FieldElement.mock()).mock(), @@ -5557,13 +5115,8 @@ mod tests { } .mock()]; - let main2_statements: Vec = vec![Statement::Return( - ExpressionList { - expressions: vec![Expression::IntConstant(1usize.into()).mock()], - } - .mock(), - ) - .mock()]; + let main2_statements: Vec = + vec![Statement::Return(Some(Expression::IntConstant(1usize.into()).mock())).mock()]; let main2_arguments = vec![]; @@ -5572,7 +5125,7 @@ mod tests { statements: main1_statements, signature: UnresolvedSignature::new() .inputs(vec![UnresolvedType::FieldElement.mock()]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), + .output(UnresolvedType::FieldElement.mock()), } .mock(); @@ -5581,7 +5134,7 @@ mod tests { statements: main2_statements, signature: UnresolvedSignature::new() .inputs(vec![]) - .outputs(vec![UnresolvedType::FieldElement.mock()]), + .output(UnresolvedType::FieldElement.mock()), } .mock(); @@ -6437,16 +5990,11 @@ mod tests { .mock(), ) .mock()]; - foo_field.value.statements = vec![Statement::Return( - ExpressionList { - expressions: vec![Expression::IntConstant(0usize.into()).mock()], - } - .mock(), - ) - .mock()]; + foo_field.value.statements = + vec![Statement::Return(Some(Expression::IntConstant(0usize.into()).mock())).mock()]; foo_field.value.signature = UnresolvedSignature::new() .inputs(vec![UnresolvedType::FieldElement.mock()]) - .outputs(vec![UnresolvedType::FieldElement.mock()]); + .output(UnresolvedType::FieldElement.mock()); let mut foo_u32 = function0(); @@ -6458,33 +6006,25 @@ mod tests { .mock(), ) .mock()]; - foo_u32.value.statements = vec![Statement::Return( - ExpressionList { - expressions: vec![Expression::IntConstant(0usize.into()).mock()], - } - .mock(), - ) - .mock()]; + foo_u32.value.statements = + vec![Statement::Return(Some(Expression::IntConstant(0usize.into()).mock())).mock()]; foo_u32.value.signature = UnresolvedSignature::new() .inputs(vec![UnresolvedType::Uint(32).mock()]) - .outputs(vec![UnresolvedType::FieldElement.mock()]); + .output(UnresolvedType::FieldElement.mock()); let mut main = function0(); - main.value.statements = vec![Statement::Return( - ExpressionList { - expressions: vec![Expression::FunctionCall( - box Expression::Identifier("foo").mock(), - None, - vec![Expression::IntConstant(0usize.into()).mock()], - ) - .mock()], - } + main.value.statements = vec![Statement::Return(Some( + Expression::FunctionCall( + box Expression::Identifier("foo").mock(), + None, + vec![Expression::IntConstant(0usize.into()).mock()], + ) .mock(), - ) + )) .mock()]; main.value.signature = - UnresolvedSignature::new().outputs(vec![UnresolvedType::FieldElement.mock()]); + UnresolvedSignature::new().output(UnresolvedType::FieldElement.mock()); let m = Module::with_symbols(vec![ absy::SymbolDeclaration { diff --git a/zokrates_core/src/static_analysis/constant_argument_checker.rs b/zokrates_core/src/static_analysis/constant_argument_checker.rs index 42bb3b66..20e36ed0 100644 --- a/zokrates_core/src/static_analysis/constant_argument_checker.rs +++ b/zokrates_core/src/static_analysis/constant_argument_checker.rs @@ -1,9 +1,8 @@ use crate::embed::FlatEmbed; -use crate::typed_absy::TypedProgram; use crate::typed_absy::{ result_folder::ResultFolder, - result_folder::{fold_expression_list_inner, fold_uint_expression_inner}, - Constant, TypedExpressionListInner, Types, UBitwidth, UExpressionInner, + result_folder::{fold_statement, fold_uint_expression_inner}, + Constant, EmbedCall, TypedProgram, TypedStatement, UBitwidth, UExpressionInner, }; use std::fmt; use zokrates_field::Field; @@ -28,6 +27,46 @@ impl fmt::Display for Error { impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantArgumentChecker { type Error = Error; + fn fold_statement( + &mut self, + s: TypedStatement<'ast, T>, + ) -> Result>, Self::Error> { + match s { + TypedStatement::EmbedCallDefinition(assignee, embed_call) => match embed_call { + EmbedCall { + embed: FlatEmbed::BitArrayLe, + .. + } => { + let arguments = embed_call + .arguments + .into_iter() + .map(|a| self.fold_expression(a)) + .collect::, _>>()?; + + if arguments[1].is_constant() { + Ok(vec![TypedStatement::EmbedCallDefinition( + assignee, + EmbedCall { + embed: FlatEmbed::BitArrayLe, + generics: embed_call.generics, + arguments, + }, + )]) + } else { + Err(Error(format!( + "Cannot compare to a variable value, found `{}`", + arguments[1] + ))) + } + } + embed_call => Ok(vec![TypedStatement::EmbedCallDefinition( + assignee, embed_call, + )]), + }, + s => fold_statement(self, s), + } + } + fn fold_uint_expression_inner( &mut self, bitwidth: UBitwidth, @@ -63,33 +102,4 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantArgumentChecker { e => fold_uint_expression_inner(self, bitwidth, e), } } - - fn fold_expression_list_inner( - &mut self, - tys: &Types<'ast, T>, - l: TypedExpressionListInner<'ast, T>, - ) -> Result, Error> { - match l { - TypedExpressionListInner::EmbedCall(FlatEmbed::BitArrayLe, generics, arguments) => { - let arguments = arguments - .into_iter() - .map(|a| self.fold_expression(a)) - .collect::, _>>()?; - - if arguments[1].is_constant() { - Ok(TypedExpressionListInner::EmbedCall( - FlatEmbed::BitArrayLe, - generics, - arguments, - )) - } else { - Err(Error(format!( - "Cannot compare to a variable value, found `{}`", - arguments[1] - ))) - } - } - l => fold_expression_list_inner(self, tys, l), - } - } } diff --git a/zokrates_core/src/static_analysis/constant_resolver.rs b/zokrates_core/src/static_analysis/constant_resolver.rs index 807267a8..fad43753 100644 --- a/zokrates_core/src/static_analysis/constant_resolver.rs +++ b/zokrates_core/src/static_analysis/constant_resolver.rs @@ -109,7 +109,7 @@ impl<'ast, T: Field> Folder<'ast, T> for ConstantResolver<'ast, T> { #[cfg(test)] mod tests { use super::*; - use crate::typed_absy::types::DeclarationSignature; + use crate::typed_absy::types::{DeclarationSignature, GTupleType}; use crate::typed_absy::{ DeclarationArrayType, DeclarationFunctionKey, DeclarationType, FieldElementExpression, GType, Identifier, TypedConstant, TypedExpression, TypedFunction, TypedFunctionSymbol, @@ -130,12 +130,12 @@ mod tests { let const_id = "a"; let main: TypedFunction = TypedFunction { arguments: vec![], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( FieldElementExpression::Identifier(Identifier::from(const_id)).into(), - ])], + )], signature: DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let program = TypedProgram { @@ -158,7 +158,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(main), ) @@ -190,13 +190,12 @@ mod tests { let const_id = CanonicalConstantIdentifier::new("a", "main".into()); let main: TypedFunction = TypedFunction { arguments: vec![], - statements: vec![TypedStatement::Return(vec![BooleanExpression::Identifier( - Identifier::from(const_id.clone()), - ) - .into()])], + statements: vec![TypedStatement::Return( + BooleanExpression::Identifier(Identifier::from(const_id.clone())).into(), + )], signature: DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::Boolean]), + .output(DeclarationType::Boolean), }; let program = TypedProgram { @@ -217,7 +216,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::Boolean]), + .output(DeclarationType::Boolean), ), TypedFunctionSymbol::Here(main), ) @@ -249,14 +248,14 @@ mod tests { let const_id = CanonicalConstantIdentifier::new("a", "main".into()); let main: TypedFunction = TypedFunction { arguments: vec![], - statements: vec![TypedStatement::Return(vec![UExpressionInner::Identifier( - Identifier::from(const_id.clone()), - ) - .annotate(UBitwidth::B32) - .into()])], + statements: vec![TypedStatement::Return( + UExpressionInner::Identifier(Identifier::from(const_id.clone())) + .annotate(UBitwidth::B32) + .into(), + )], signature: DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::Uint(UBitwidth::B32)]), + .output(DeclarationType::Uint(UBitwidth::B32)), }; let program = TypedProgram { @@ -279,7 +278,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::Uint(UBitwidth::B32)]), + .output(DeclarationType::Uint(UBitwidth::B32)), ), TypedFunctionSymbol::Here(main), ) @@ -311,24 +310,26 @@ mod tests { let const_id = CanonicalConstantIdentifier::new("a", "main".into()); let main: TypedFunction = TypedFunction { arguments: vec![], - statements: vec![TypedStatement::Return(vec![FieldElementExpression::Add( - FieldElementExpression::select( - ArrayExpressionInner::Identifier(Identifier::from(const_id.clone())) - .annotate(GType::FieldElement, 2u32), - UExpressionInner::Value(0u128).annotate(UBitwidth::B32), + statements: vec![TypedStatement::Return( + FieldElementExpression::Add( + FieldElementExpression::select( + ArrayExpressionInner::Identifier(Identifier::from(const_id.clone())) + .annotate(GType::FieldElement, 2u32), + UExpressionInner::Value(0u128).annotate(UBitwidth::B32), + ) + .into(), + FieldElementExpression::select( + ArrayExpressionInner::Identifier(Identifier::from(const_id.clone())) + .annotate(GType::FieldElement, 2u32), + UExpressionInner::Value(1u128).annotate(UBitwidth::B32), + ) + .into(), ) .into(), - FieldElementExpression::select( - ArrayExpressionInner::Identifier(Identifier::from(const_id.clone())) - .annotate(GType::FieldElement, 2u32), - UExpressionInner::Value(1u128).annotate(UBitwidth::B32), - ) - .into(), - ) - .into()])], + )], signature: DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let program = TypedProgram { @@ -363,7 +364,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(main), ) @@ -396,12 +397,12 @@ mod tests { let main: TypedFunction = TypedFunction { arguments: vec![], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( FieldElementExpression::Identifier(Identifier::from(const_b_id.clone())).into(), - ])], + )], signature: DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let program = TypedProgram { @@ -437,7 +438,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(main), ) @@ -522,12 +523,17 @@ mod tests { ) .into(), TypedFunctionSymbolDeclaration::new( - DeclarationFunctionKey::with_location("foo", "main") - .signature(DeclarationSignature::new().inputs(vec![]).outputs(vec![])), + DeclarationFunctionKey::with_location("foo", "main").signature( + DeclarationSignature::new() + .inputs(vec![]) + .output(DeclarationType::Tuple(GTupleType::new(vec![]))), + ), TypedFunctionSymbol::Here(TypedFunction { arguments: vec![], statements: vec![], - signature: DeclarationSignature::new().inputs(vec![]).outputs(vec![]), + signature: DeclarationSignature::new() + .inputs(vec![]) + .output(DeclarationType::Tuple(GTupleType::new(vec![]))), }), ) .into(), @@ -546,19 +552,19 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(TypedFunction { arguments: vec![], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( FieldElementExpression::Identifier(Identifier::from( main_const_id.clone(), )) .into(), - ])], + )], signature: DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }), ) .into(), @@ -592,19 +598,19 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(TypedFunction { arguments: vec![], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( FieldElementExpression::Identifier(Identifier::from( main_const_id.clone(), )) .into(), - ])], + )], signature: DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }), ) .into(), @@ -702,12 +708,17 @@ mod tests { ) .into(), TypedFunctionSymbolDeclaration::new( - DeclarationFunctionKey::with_location("foo", "main") - .signature(DeclarationSignature::new().inputs(vec![]).outputs(vec![])), + DeclarationFunctionKey::with_location("foo", "main").signature( + DeclarationSignature::new() + .inputs(vec![]) + .output(DeclarationType::Tuple(GTupleType::new(vec![]))), + ), TypedFunctionSymbol::Here(TypedFunction { arguments: vec![], statements: vec![], - signature: DeclarationSignature::new().inputs(vec![]).outputs(vec![]), + signature: DeclarationSignature::new() + .inputs(vec![]) + .output(DeclarationType::Tuple(GTupleType::new(vec![]))), }), ) .into(), @@ -748,19 +759,19 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(TypedFunction { arguments: vec![], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( FieldElementExpression::Identifier(Identifier::from( main_foo_const_id.clone(), )) .into(), - ])], + )], signature: DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }), ) .into(), @@ -823,19 +834,19 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(TypedFunction { arguments: vec![], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( FieldElementExpression::Identifier(Identifier::from( main_foo_const_id.clone(), )) .into(), - ])], + )], signature: DeclarationSignature::new() .inputs(vec![]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }), ) .into(), diff --git a/zokrates_core/src/static_analysis/flatten_complex_types.rs b/zokrates_core/src/static_analysis/flatten_complex_types.rs index f3427762..09ae390b 100644 --- a/zokrates_core/src/static_analysis/flatten_complex_types.rs +++ b/zokrates_core/src/static_analysis/flatten_complex_types.rs @@ -29,7 +29,7 @@ fn flatten_identifier_rec<'ast>( id: zir::Identifier::Source(id), _type: zir::Type::uint(bitwidth.to_usize()), }], - typed_absy::types::ConcreteType::Array(array_type) => (0..array_type.size) + typed_absy::types::ConcreteType::Array(array_type) => (0..*array_type.size) .flat_map(|i| { flatten_identifier_rec( zir::SourceIdentifier::Select(box id.clone(), i), @@ -310,26 +310,6 @@ impl<'ast, T: Field> Flattener { fold_tuple_expression(self, statements_buffer, e) } - fn fold_expression_list( - &mut self, - statements_buffer: &mut Vec>, - es: typed_absy::TypedExpressionList<'ast, T>, - ) -> zir::ZirExpressionList<'ast, T> { - match es.into_inner() { - typed_absy::TypedExpressionListInner::EmbedCall(embed, generics, arguments) => { - zir::ZirExpressionList::EmbedCall( - embed, - generics, - arguments - .into_iter() - .flat_map(|a| self.fold_expression(statements_buffer, a)) - .collect(), - ) - } - _ => unreachable!("should have been inlined"), - } - } - fn fold_conditional_expression>( &mut self, statements_buffer: &mut Vec>, @@ -436,11 +416,8 @@ fn fold_statement<'ast, T: Field>( s: typed_absy::TypedStatement<'ast, T>, ) { let res = match s { - typed_absy::TypedStatement::Return(expressions) => vec![zir::ZirStatement::Return( - expressions - .into_iter() - .flat_map(|e| f.fold_expression(statements_buffer, e)) - .collect(), + typed_absy::TypedStatement::Return(expression) => vec![zir::ZirStatement::Return( + f.fold_expression(statements_buffer, expression), )], typed_absy::TypedStatement::Definition(a, e) => { let a = f.fold_assignee(a); @@ -464,16 +441,21 @@ fn fold_statement<'ast, T: Field>( }; vec![zir::ZirStatement::Assertion(e, error)] } - typed_absy::TypedStatement::For(..) => unreachable!(), - typed_absy::TypedStatement::MultipleDefinition(variables, elist) => { + typed_absy::TypedStatement::EmbedCallDefinition(assignee, embed_call) => { vec![zir::ZirStatement::MultipleDefinition( - variables - .into_iter() - .flat_map(|v| f.fold_assignee(v)) - .collect(), - f.fold_expression_list(statements_buffer, elist), + f.fold_assignee(assignee), + zir::ZirExpressionList::EmbedCall( + embed_call.embed, + embed_call.generics, + embed_call + .arguments + .into_iter() + .flat_map(|a| f.fold_expression(statements_buffer, a)) + .collect(), + ), )] } + typed_absy::TypedStatement::For(..) => unreachable!(), typed_absy::TypedStatement::PushCallLog(..) => vec![], typed_absy::TypedStatement::PopCallLog => vec![], }; diff --git a/zokrates_core/src/static_analysis/propagation.rs b/zokrates_core/src/static_analysis/propagation.rs index 0d7af511..418b4b08 100644 --- a/zokrates_core/src/static_analysis/propagation.rs +++ b/zokrates_core/src/static_analysis/propagation.rs @@ -285,354 +285,240 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> { Ok(vec![TypedStatement::For(v, from, to, statements)]) } - TypedStatement::MultipleDefinition(assignees, expression_list) => { - let assignees: Vec> = assignees - .into_iter() - .map(|a| self.fold_assignee(a)) - .collect::>()?; - let expression_list = self.fold_expression_list(expression_list)?; + TypedStatement::EmbedCallDefinition(assignee, embed_call) => { + let assignee = self.fold_assignee(assignee)?; + let embed_call = self.fold_embed_call(embed_call)?; - let types = Types { - inner: expression_list - .types - .clone() - .inner - .into_iter() - .map(|t| self.fold_type(t)) - .collect::>()?, - }; + fn process_u_from_bits<'ast, T: Field>( + arguments: &[TypedExpression<'ast, T>], + bitwidth: UBitwidth, + ) -> TypedExpression<'ast, T> { + assert_eq!(arguments.len(), 1); - let statements = match expression_list.into_inner() { - TypedExpressionListInner::EmbedCall(embed, generics, arguments) => { - let arguments: Vec<_> = arguments - .into_iter() - .map(|a| self.fold_expression(a)) - .collect::>()?; + let argument = arguments.last().cloned().unwrap(); + let argument = argument.into_canonical_constant(); - fn process_u_from_bits<'ast, T: Field>( - variables: Vec>, - mut arguments: Vec>, - bitwidth: UBitwidth, - ) -> TypedExpression<'ast, T> { - assert_eq!(variables.len(), 1); - assert_eq!(arguments.len(), 1); - - let argument = arguments.pop().unwrap(); - - let argument = argument.into_canonical_constant(); - - match ArrayExpression::try_from(argument) - .unwrap() - .into_inner() - { - ArrayExpressionInner::Value(v) => - UExpressionInner::Value( - v.into_iter() - .map(|v| match v { - TypedExpressionOrSpread::Expression( - TypedExpression::Boolean( - BooleanExpression::Value(v), - ), - ) => v, - _ => unreachable!("Should be a constant boolean expression. Spreads are not expected here, as in their presence the argument isn't constant"), - }) - .enumerate() - .fold(0, |acc, (i, v)| { - if v { - acc + 2u128.pow( - (bitwidth.to_usize() - i - 1) - .try_into() - .unwrap(), - ) - } else { - acc - } - }), - ) - .annotate(bitwidth) - .into(), - _ => unreachable!("should be an array value"), - } - } - - fn process_u_to_bits<'ast, T: Field>( - variables: Vec>, - arguments: Vec>, - bitwidth: UBitwidth, - ) -> TypedExpression<'ast, T> { - assert_eq!(variables.len(), 1); - assert_eq!(arguments.len(), 1); - - match UExpression::try_from(arguments[0].clone()) - .unwrap() - .into_inner() - { - UExpressionInner::Value(v) => { - let mut num = v; - let mut res = vec![]; - - for i in (0..bitwidth as u32).rev() { - if 2u128.pow(i) <= num { - num -= 2u128.pow(i); - res.push(true); + match ArrayExpression::try_from(argument) + .unwrap() + .into_inner() + { + ArrayExpressionInner::Value(v) => + UExpressionInner::Value( + v.into_iter() + .map(|v| match v { + TypedExpressionOrSpread::Expression( + TypedExpression::Boolean( + BooleanExpression::Value(v), + ), + ) => v, + _ => unreachable!("Should be a constant boolean expression. Spreads are not expected here, as in their presence the argument isn't constant"), + }) + .enumerate() + .fold(0, |acc, (i, v)| { + if v { + acc + 2u128.pow( + (bitwidth.to_usize() - i - 1) + .try_into() + .unwrap(), + ) } else { - res.push(false); + acc } - } - assert_eq!(num, 0); - - ArrayExpressionInner::Value( - res.into_iter() - .map(|v| BooleanExpression::Value(v).into()) - .collect::>() - .into(), - ) - .annotate(Type::Boolean, bitwidth.to_usize() as u32) - .into() - } - _ => unreachable!("should be a uint value"), - } - } - - match arguments.iter().all(|a| a.is_constant()) { - true => { - let r: Option> = match embed { - FlatEmbed::BitArrayLe => Ok(None), // todo - FlatEmbed::U64FromBits => Ok(Some(process_u_from_bits( - assignees.clone(), - arguments.clone(), - UBitwidth::B64, - ))), - FlatEmbed::U32FromBits => Ok(Some(process_u_from_bits( - assignees.clone(), - arguments.clone(), - UBitwidth::B32, - ))), - FlatEmbed::U16FromBits => Ok(Some(process_u_from_bits( - assignees.clone(), - arguments.clone(), - UBitwidth::B16, - ))), - FlatEmbed::U8FromBits => Ok(Some(process_u_from_bits( - assignees.clone(), - arguments.clone(), - UBitwidth::B8, - ))), - FlatEmbed::U64ToBits => Ok(Some(process_u_to_bits( - assignees.clone(), - arguments.clone(), - UBitwidth::B64, - ))), - FlatEmbed::U32ToBits => Ok(Some(process_u_to_bits( - assignees.clone(), - arguments.clone(), - UBitwidth::B32, - ))), - FlatEmbed::U16ToBits => Ok(Some(process_u_to_bits( - assignees.clone(), - arguments.clone(), - UBitwidth::B16, - ))), - FlatEmbed::U8ToBits => Ok(Some(process_u_to_bits( - assignees.clone(), - arguments.clone(), - UBitwidth::B8, - ))), - FlatEmbed::Unpack => { - assert_eq!(assignees.len(), 1); - assert_eq!(arguments.len(), 1); - assert_eq!(generics.len(), 1); - - let bit_width = generics[0]; - - match FieldElementExpression::::try_from( - arguments[0].clone(), - ) - .unwrap() - { - FieldElementExpression::Number(num) => { - let mut acc = num.clone(); - let mut res = vec![]; - - for i in (0..bit_width as usize).rev() { - if T::from(2).pow(i) <= acc { - acc = acc - T::from(2).pow(i); - res.push(true); - } else { - res.push(false); - } - } - - if acc != T::zero() { - Err(Error::ValueTooLarge(format!( - "Cannot unpack `{}` to `{}`: value is too large", - num, assignees.first().unwrap().get_type() - ))) - } else { - Ok(Some( - ArrayExpressionInner::Value( - res.into_iter() - .map(|v| { - BooleanExpression::Value(v) - .into() - }) - .collect::>() - .into(), - ) - .annotate(Type::Boolean, bit_width) - .into(), - )) - } - } - _ => unreachable!("should be a field value"), - } - } - #[cfg(feature = "bellman")] - FlatEmbed::Sha256Round => Ok(None), - #[cfg(feature = "ark")] - FlatEmbed::SnarkVerifyBls12377 => Ok(None), - }?; - - Ok(match r { - // if the function call returns a constant - Some(expr) => { - let mut assignees = assignees; - - match assignees.pop().unwrap() { - TypedAssignee::Identifier(var) => { - self.constants.insert(var.id, expr); - vec![] - } - assignee => { - match self.try_get_constant_mut(&assignee) { - Ok((_, c)) => { - *c = expr; - vec![] - } - Err(v) => match self.constants.remove(&v.id) { - Some(c) => vec![ - TypedStatement::Definition( - v.clone().into(), - c, - ), - TypedStatement::Definition( - assignee, expr, - ), - ], - None => { - vec![TypedStatement::Definition( - assignee, expr, - )] - } - }, - } - } - } - } - None => { - // if the function call does not return a constant, invalidate the cache - // this happpens because we only propagate certain calls here - let mut assignees = assignees; - - let assignee = assignees.pop().unwrap(); - - let v = self - .try_get_constant_mut(&assignee) - .map(|(v, _)| v) - .unwrap_or_else(|v| v); - - match self.constants.remove(&v.id) { - Some(c) => vec![ - TypedStatement::Definition(v.clone().into(), c), - TypedStatement::MultipleDefinition( - vec![assignee], - TypedExpressionListInner::EmbedCall( - embed, generics, arguments, - ) - .annotate(types), - ), - ], - None => vec![TypedStatement::MultipleDefinition( - vec![assignee], - TypedExpressionListInner::EmbedCall( - embed, generics, arguments, - ) - .annotate(types), - )], - } - } - }) - } - false => { - // if the function arguments are not constant, invalidate the cache - // for the return assignees - - let def = TypedStatement::MultipleDefinition( - assignees.clone(), - TypedExpressionListInner::EmbedCall(embed, generics, arguments) - .annotate(types), - ); - - let invalidations = assignees.iter().flat_map(|assignee| { - let v = self - .try_get_constant_mut(assignee) - .map(|(v, _)| v) - .unwrap_or_else(|v| v); - match self.constants.remove(&v.id) { - Some(c) => { - vec![TypedStatement::Definition(v.clone().into(), c)] - } - None => vec![], - } - }); - - Ok(invalidations.chain(std::iter::once(def)).collect()) - } - } - } - TypedExpressionListInner::FunctionCall(function_call) => { - let generics = function_call - .generics - .into_iter() - .map(|g| g.map(|g| self.fold_uint_expression(g)).transpose()) - .collect::>()?; - - let arguments: Vec<_> = function_call - .arguments - .into_iter() - .map(|a| self.fold_expression(a)) - .collect::>()?; - - // invalidate the cache for the return assignees as this call mutates them - - let def = TypedStatement::MultipleDefinition( - assignees.clone(), - TypedExpressionList::function_call( - function_call.function_key, - generics, - arguments, + }), ) - .annotate(types), - ); - - let invalidations = assignees.iter().flat_map(|assignee| { - let v = self - .try_get_constant_mut(assignee) - .map(|(v, _)| v) - .unwrap_or_else(|v| v); - match self.constants.remove(&v.id) { - Some(c) => { - vec![TypedStatement::Definition(v.clone().into(), c)] - } - None => vec![], - } - }); - - Ok(invalidations.chain(std::iter::once(def)).collect()) + .annotate(bitwidth) + .into(), + _ => unreachable!("should be an array value"), } - }?; + } - Ok(statements) + fn process_u_to_bits<'ast, T: Field>( + arguments: &[TypedExpression<'ast, T>], + bitwidth: UBitwidth, + ) -> TypedExpression<'ast, T> { + assert_eq!(arguments.len(), 1); + + match UExpression::try_from(arguments[0].clone()) + .unwrap() + .into_inner() + { + UExpressionInner::Value(v) => { + let mut num = v; + let mut res = vec![]; + + for i in (0..bitwidth as u32).rev() { + if 2u128.pow(i) <= num { + num -= 2u128.pow(i); + res.push(true); + } else { + res.push(false); + } + } + assert_eq!(num, 0); + + ArrayExpressionInner::Value( + res.into_iter() + .map(|v| BooleanExpression::Value(v).into()) + .collect::>() + .into(), + ) + .annotate(Type::Boolean, bitwidth.to_usize() as u32) + .into() + } + _ => unreachable!("should be a uint value"), + } + } + + match embed_call.arguments.iter().all(|a| a.is_constant()) { + true => { + let r: Option> = match embed_call.embed { + FlatEmbed::BitArrayLe => Ok(None), // todo + FlatEmbed::U64FromBits => Ok(Some(process_u_from_bits( + &embed_call.arguments, + UBitwidth::B64, + ))), + FlatEmbed::U32FromBits => Ok(Some(process_u_from_bits( + &embed_call.arguments, + UBitwidth::B32, + ))), + FlatEmbed::U16FromBits => Ok(Some(process_u_from_bits( + &embed_call.arguments, + UBitwidth::B16, + ))), + FlatEmbed::U8FromBits => Ok(Some(process_u_from_bits( + &embed_call.arguments, + UBitwidth::B8, + ))), + FlatEmbed::U64ToBits => Ok(Some(process_u_to_bits( + &embed_call.arguments, + UBitwidth::B64, + ))), + FlatEmbed::U32ToBits => Ok(Some(process_u_to_bits( + &embed_call.arguments, + UBitwidth::B32, + ))), + FlatEmbed::U16ToBits => Ok(Some(process_u_to_bits( + &embed_call.arguments, + UBitwidth::B16, + ))), + FlatEmbed::U8ToBits => Ok(Some(process_u_to_bits( + &embed_call.arguments, + UBitwidth::B8, + ))), + FlatEmbed::Unpack => { + assert_eq!(embed_call.arguments.len(), 1); + assert_eq!(embed_call.generics.len(), 1); + + let bit_width = embed_call.generics[0]; + + match FieldElementExpression::::try_from( + embed_call.arguments[0].clone(), + ) + .unwrap() + { + FieldElementExpression::Number(num) => { + let mut acc = num.clone(); + let mut res = vec![]; + + for i in (0..bit_width as usize).rev() { + if T::from(2).pow(i) <= acc { + acc = acc - T::from(2).pow(i); + res.push(true); + } else { + res.push(false); + } + } + + if acc != T::zero() { + Err(Error::ValueTooLarge(format!( + "Cannot unpack `{}` to `{}`: value is too large", + num, + assignee.get_type() + ))) + } else { + Ok(Some( + ArrayExpressionInner::Value( + res.into_iter() + .map(|v| BooleanExpression::Value(v).into()) + .collect::>() + .into(), + ) + .annotate(Type::Boolean, bit_width) + .into(), + )) + } + } + _ => unreachable!("should be a field value"), + } + } + #[cfg(feature = "bellman")] + FlatEmbed::Sha256Round => Ok(None), + #[cfg(feature = "ark")] + FlatEmbed::SnarkVerifyBls12377 => Ok(None), + }?; + + Ok(match r { + // if the function call returns a constant + Some(expr) => match assignee { + TypedAssignee::Identifier(var) => { + self.constants.insert(var.id, expr); + vec![] + } + assignee => match self.try_get_constant_mut(&assignee) { + Ok((_, c)) => { + *c = expr; + vec![] + } + Err(v) => match self.constants.remove(&v.id) { + Some(c) => vec![ + TypedStatement::Definition(v.clone().into(), c), + TypedStatement::Definition(assignee, expr), + ], + None => { + vec![TypedStatement::Definition(assignee, expr)] + } + }, + }, + }, + None => { + // if the function call does not return a constant, invalidate the cache + // this happens because we only propagate certain calls here + + let v = self + .try_get_constant_mut(&assignee) + .map(|(v, _)| v) + .unwrap_or_else(|v| v); + + match self.constants.remove(&v.id) { + Some(c) => vec![ + TypedStatement::Definition(v.clone().into(), c), + TypedStatement::EmbedCallDefinition(assignee, embed_call), + ], + None => vec![TypedStatement::EmbedCallDefinition( + assignee, embed_call, + )], + } + } + }) + } + false => { + // if the function arguments are not constant, invalidate the cache + // for the return assignees + let def = TypedStatement::EmbedCallDefinition(assignee.clone(), embed_call); + + let v = self + .try_get_constant_mut(&assignee) + .map(|(v, _)| v) + .unwrap_or_else(|v| v); + + Ok(match self.constants.remove(&v.id) { + Some(c) => { + vec![TypedStatement::Definition(v.clone().into(), c), def] + } + None => vec![def], + }) + } + } } TypedStatement::Assertion(e, ty) => { let e_str = e.to_string(); diff --git a/zokrates_core/src/static_analysis/reducer/constants_reader.rs b/zokrates_core/src/static_analysis/reducer/constants_reader.rs index 8fb1d4a1..4b6f391d 100644 --- a/zokrates_core/src/static_analysis/reducer/constants_reader.rs +++ b/zokrates_core/src/static_analysis/reducer/constants_reader.rs @@ -4,8 +4,8 @@ use crate::static_analysis::reducer::ConstantDefinitions; use crate::typed_absy::{ folder::*, ArrayExpression, ArrayExpressionInner, ArrayType, BooleanExpression, CoreIdentifier, DeclarationConstant, Expr, FieldElementExpression, Identifier, StructExpression, - StructExpressionInner, StructType, TypedProgram, TypedSymbolDeclaration, UBitwidth, - UExpression, UExpressionInner, + StructExpressionInner, StructType, TupleExpression, TupleExpressionInner, TupleType, + TypedProgram, TypedSymbolDeclaration, UBitwidth, UExpression, UExpressionInner, }; use zokrates_field::Field; @@ -33,6 +33,26 @@ impl<'a, 'ast, T: Field> ConstantsReader<'a, 'ast, T> { } impl<'a, 'ast, T: Field> Folder<'ast, T> for ConstantsReader<'a, 'ast, T> { + fn fold_declaration_constant( + &mut self, + c: DeclarationConstant<'ast, T>, + ) -> DeclarationConstant<'ast, T> { + match c { + DeclarationConstant::Constant(c) => { + let c = self.fold_canonical_constant_identifier(c); + + match self.constants.get(&c).cloned() { + Some(e) => match UExpression::try_from(e).unwrap().into_inner() { + UExpressionInner::Value(v) => DeclarationConstant::Concrete(v as u32), + _ => unreachable!(), + }, + None => DeclarationConstant::Constant(c), + } + } + c => fold_declaration_constant(self, c), + } + } + fn fold_field_expression( &mut self, e: FieldElementExpression<'ast, T>, @@ -124,6 +144,29 @@ impl<'a, 'ast, T: Field> Folder<'ast, T> for ConstantsReader<'a, 'ast, T> { } } + fn fold_tuple_expression_inner( + &mut self, + ty: &TupleType<'ast, T>, + e: TupleExpressionInner<'ast, T>, + ) -> TupleExpressionInner<'ast, T> { + match e { + TupleExpressionInner::Identifier(Identifier { + id: CoreIdentifier::Constant(c), + version, + }) => { + assert_eq!(version, 0); + match self.constants.get(&c).cloned() { + Some(v) => TupleExpression::try_from(v).unwrap().into_inner(), + None => TupleExpressionInner::Identifier(Identifier { + id: CoreIdentifier::Constant(c), + version, + }), + } + } + e => fold_tuple_expression_inner(self, ty, e), + } + } + fn fold_struct_expression_inner( &mut self, ty: &StructType<'ast, T>, @@ -146,24 +189,4 @@ impl<'a, 'ast, T: Field> Folder<'ast, T> for ConstantsReader<'a, 'ast, T> { e => fold_struct_expression_inner(self, ty, e), } } - - fn fold_declaration_constant( - &mut self, - c: DeclarationConstant<'ast, T>, - ) -> DeclarationConstant<'ast, T> { - match c { - DeclarationConstant::Constant(c) => { - let c = self.fold_canonical_constant_identifier(c); - - match self.constants.get(&c).cloned() { - Some(e) => match UExpression::try_from(e).unwrap().into_inner() { - UExpressionInner::Value(v) => DeclarationConstant::Concrete(v as u32), - _ => unreachable!(), - }, - None => DeclarationConstant::Constant(c), - } - } - c => fold_declaration_constant(self, c), - } - } } diff --git a/zokrates_core/src/static_analysis/reducer/constants_writer.rs b/zokrates_core/src/static_analysis/reducer/constants_writer.rs index f84c24b0..fae57d32 100644 --- a/zokrates_core/src/static_analysis/reducer/constants_writer.rs +++ b/zokrates_core/src/static_analysis/reducer/constants_writer.rs @@ -4,9 +4,9 @@ use crate::static_analysis::reducer::{ constants_reader::ConstantsReader, reduce_function, ConstantDefinitions, Error, }; use crate::typed_absy::{ - result_folder::*, types::ConcreteGenericsAssignment, OwnedTypedModuleId, TypedConstant, - TypedConstantSymbol, TypedConstantSymbolDeclaration, TypedModuleId, TypedProgram, - TypedSymbolDeclaration, UExpression, + result_folder::*, types::ConcreteGenericsAssignment, Constant, OwnedTypedModuleId, Typed, + TypedConstant, TypedConstantSymbol, TypedConstantSymbolDeclaration, TypedModuleId, + TypedProgram, TypedSymbolDeclaration, UExpression, }; use std::collections::{BTreeMap, HashSet}; use zokrates_field::Field; @@ -114,8 +114,8 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantsWriter<'ast, T> { // wrap this expression in a function let wrapper = TypedFunction { arguments: vec![], - statements: vec![TypedStatement::Return(vec![c.expression])], - signature: DeclarationSignature::new().outputs(vec![c.ty.clone()]), + statements: vec![TypedStatement::Return(c.expression)], + signature: DeclarationSignature::new().output(c.ty.clone()), }; let mut inlined_wrapper = reduce_function( @@ -124,27 +124,21 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantsWriter<'ast, T> { &self.program, )?; - if let TypedStatement::Return(mut expressions) = + if let TypedStatement::Return(expression) = inlined_wrapper.statements.pop().unwrap() { - assert_eq!(expressions.len(), 1); - let constant_expression = expressions.pop().unwrap(); - - use crate::typed_absy::Constant; - if !constant_expression.is_constant() { + if !expression.is_constant() { return Err(Error::ConstantReduction(id.id.to_string(), id.module)); }; - use crate::typed_absy::Typed; if crate::typed_absy::types::try_from_g_type::<_, UExpression<'ast, T>>( c.ty.clone(), ) .unwrap() - == constant_expression.get_type() + == expression.get_type() { // add to the constant map - self.constants - .insert(id.clone(), constant_expression.clone()); + self.constants.insert(id.clone(), expression.clone()); // after we reduced a constant, propagate it through the whole program self.update_program(); @@ -152,12 +146,12 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ConstantsWriter<'ast, T> { Ok(TypedConstantSymbolDeclaration { id, symbol: TypedConstantSymbol::Here(TypedConstant { - expression: constant_expression, + expression, ty: c.ty, }), }) } else { - Err(Error::Type(format!("Expression of type `{}` cannot be assigned to constant `{}` of type `{}`", constant_expression.get_type(), id, c.ty))) + Err(Error::Type(format!("Expression of type `{}` cannot be assigned to constant `{}` of type `{}`", expression.get_type(), id, c.ty))) } } else { Err(Error::ConstantReduction(id.id.to_string(), id.module)) diff --git a/zokrates_core/src/static_analysis/reducer/inline.rs b/zokrates_core/src/static_analysis/reducer/inline.rs index 9e84d288..ff8b49b7 100644 --- a/zokrates_core/src/static_analysis/reducer/inline.rs +++ b/zokrates_core/src/static_analysis/reducer/inline.rs @@ -30,15 +30,15 @@ use crate::embed::FlatEmbed; use crate::static_analysis::reducer::Output; use crate::static_analysis::reducer::ShallowTransformer; use crate::static_analysis::reducer::Versions; -use crate::typed_absy::types::{ConcreteGenericsAssignment, IntoTypes}; -use crate::typed_absy::CoreIdentifier; +use crate::typed_absy::types::{ConcreteGenericsAssignment, IntoType}; use crate::typed_absy::Identifier; use crate::typed_absy::TypedAssignee; use crate::typed_absy::{ ConcreteFunctionKey, ConcreteSignature, ConcreteVariable, DeclarationFunctionKey, Expr, Signature, TypedExpression, TypedFunctionSymbol, TypedFunctionSymbolDeclaration, TypedProgram, - TypedStatement, Types, UExpression, UExpressionInner, Variable, + TypedStatement, UExpression, UExpressionInner, Variable, }; +use crate::typed_absy::{CoreIdentifier, Type}; use zokrates_field::Field; pub enum InlineError<'ast, T> { @@ -47,13 +47,13 @@ pub enum InlineError<'ast, T> { FlatEmbed, Vec, Vec>, - Types<'ast, T>, + Type<'ast, T>, ), NonConstant( DeclarationFunctionKey<'ast, T>, Vec>>, Vec>, - Types<'ast, T>, + Type<'ast, T>, ), } @@ -76,7 +76,7 @@ fn get_canonical_function<'ast, T: Field>( } type InlineResult<'ast, T> = Result< - Output<(Vec>, Vec>), Vec>>, + Output<(Vec>, TypedExpression<'ast, T>), Vec>>, InlineError<'ast, T>, >; @@ -91,8 +91,7 @@ pub fn inline_call<'a, 'ast, T: Field, E: Expr<'ast, T>>( use std::convert::TryFrom; use crate::typed_absy::Typed; - - let output_types = output.clone().into_types(); + let output_type = output.clone().into_type(); // we try to get concrete values for explicit generics let generics_values: Vec> = generics @@ -111,7 +110,7 @@ pub fn inline_call<'a, 'ast, T: Field, E: Expr<'ast, T>>( k.clone(), generics.clone(), arguments.clone(), - output_types.clone(), + output_type.clone(), ) })?; @@ -120,7 +119,7 @@ pub fn inline_call<'a, 'ast, T: Field, E: Expr<'ast, T>>( let inferred_signature = Signature::new() .generics(generics.clone()) .inputs(arguments.iter().map(|a| a.get_type()).collect()) - .outputs(output_types.clone().inner); + .output(output_type.clone()); // we try to get concrete values for the whole signature. if this fails we should propagate again let inferred_signature = match ConcreteSignature::try_from(inferred_signature) { @@ -130,7 +129,7 @@ pub fn inline_call<'a, 'ast, T: Field, E: Expr<'ast, T>>( k, generics, arguments, - output_types, + output_type, )); } }; @@ -158,7 +157,7 @@ pub fn inline_call<'a, 'ast, T: Field, E: Expr<'ast, T>>( e, e.generics::(&assignment), arguments.clone(), - output_types, + output_type, )), _ => unreachable!(), }?; @@ -188,51 +187,39 @@ pub fn inline_call<'a, 'ast, T: Field, E: Expr<'ast, T>>( assert_eq!(returns.len(), 1); - let returns = match returns.pop().unwrap() { + let return_expression = match returns.pop().unwrap() { TypedStatement::Return(e) => e, _ => unreachable!(), }; - let res: Vec> = inferred_signature - .outputs - .iter() - .enumerate() - .map(|(i, t)| { - ConcreteVariable::with_id_and_type( - Identifier::from(CoreIdentifier::Call(i)).version( - *versions - .entry(CoreIdentifier::Call(i).clone()) - .and_modify(|e| *e += 1) // if it was already declared, we increment - .or_insert(0), - ), - t.clone(), - ) - }) - .collect(); + let v: ConcreteVariable<'ast> = ConcreteVariable::with_id_and_type( + Identifier::from(CoreIdentifier::Call(0)).version( + *versions + .entry(CoreIdentifier::Call(0).clone()) + .and_modify(|e| *e += 1) // if it was already declared, we increment + .or_insert(0), + ), + *inferred_signature.output.clone(), + ); - let expressions: Vec> = res - .iter() - .map(|v| TypedExpression::from(Variable::from(v.clone()))) - .collect(); + // let expressions: Vec> = + // vec![TypedExpression::from(Variable::from(v.clone()))]; - assert_eq!(res.len(), returns.len()); + let expression = TypedExpression::from(Variable::from(v.clone())); - let output_bindings: Vec> = res - .into_iter() - .zip(returns) - .map(|(v, a)| TypedStatement::Definition(TypedAssignee::Identifier(v.into()), a)) - .collect(); + let output_binding = + TypedStatement::Definition(TypedAssignee::Identifier(v.into()), return_expression); let pop_log = TypedStatement::PopCallLog; let statements: Vec<_> = std::iter::once(call_log) .chain(input_bindings) .chain(statements) - .chain(output_bindings) + .chain(std::iter::once(output_binding)) .chain(std::iter::once(pop_log)) .collect(); Ok(incomplete_data - .map(|d| Output::Incomplete((statements.clone(), expressions.clone()), d)) - .unwrap_or_else(|| Output::Complete((statements, expressions)))) + .map(|d| Output::Incomplete((statements.clone(), expression.clone()), d)) + .unwrap_or_else(|| Output::Complete((statements, expression)))) } diff --git a/zokrates_core/src/static_analysis/reducer/mod.rs b/zokrates_core/src/static_analysis/reducer/mod.rs index 982ea3e3..49fb8939 100644 --- a/zokrates_core/src/static_analysis/reducer/mod.rs +++ b/zokrates_core/src/static_analysis/reducer/mod.rs @@ -20,16 +20,15 @@ use self::inline::{inline_call, InlineError}; use crate::typed_absy::result_folder::*; use crate::typed_absy::types::ConcreteGenericsAssignment; use crate::typed_absy::types::GGenericsAssignment; -use crate::typed_absy::CanonicalConstantIdentifier; use crate::typed_absy::Folder; +use crate::typed_absy::{CanonicalConstantIdentifier, EmbedCall, Variable}; use std::collections::HashMap; use crate::typed_absy::{ ArrayExpressionInner, ArrayType, BlockExpression, CoreIdentifier, Expr, FunctionCall, FunctionCallExpression, FunctionCallOrExpression, Id, Identifier, OwnedTypedModuleId, - TypedExpression, TypedExpressionList, TypedExpressionListInner, TypedFunction, - TypedFunctionSymbol, TypedFunctionSymbolDeclaration, TypedModule, TypedProgram, TypedStatement, - UExpression, UExpressionInner, Variable, + TypedExpression, TypedFunction, TypedFunctionSymbol, TypedFunctionSymbolDeclaration, + TypedModule, TypedProgram, TypedStatement, UExpression, UExpressionInner, }; use zokrates_field::Field; @@ -240,19 +239,19 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Reducer<'ast, 'a, T> { ); match res { - Ok(Output::Complete((statements, mut expressions))) => { + Ok(Output::Complete((statements, expression))) => { self.complete &= true; self.statement_buffer.extend(statements); Ok(FunctionCallOrExpression::Expression( - E::from(expressions.pop().unwrap()).into_inner(), + E::from(expression).into_inner(), )) } - Ok(Output::Incomplete((statements, expressions), delta_for_loop_versions)) => { + Ok(Output::Incomplete((statements, expression), delta_for_loop_versions)) => { self.complete = false; self.statement_buffer.extend(statements); self.for_loop_versions_after.extend(delta_for_loop_versions); Ok(FunctionCallOrExpression::Expression( - E::from(expressions[0].clone()).into_inner(), + E::from(expression.clone()).into_inner(), )) } Err(InlineError::Generic(decl, conc)) => Err(Error::Incompatible(format!( @@ -266,7 +265,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Reducer<'ast, 'a, T> { key, generics, arguments, ))) } - Err(InlineError::Flat(embed, generics, arguments, output_types)) => { + Err(InlineError::Flat(embed, generics, arguments, output_type)) => { let identifier = Identifier::from(CoreIdentifier::Call(0)).version( *self .versions @@ -274,18 +273,14 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Reducer<'ast, 'a, T> { .and_modify(|e| *e += 1) // if it was already declared, we increment .or_insert(0), ); - let var = Variable::with_id_and_type( - identifier.clone(), - output_types.clone().inner.pop().unwrap(), - ); + let var = Variable::with_id_and_type(identifier.clone(), output_type); - let v = vec![var.clone().into()]; + let v = var.clone().into(); self.statement_buffer - .push(TypedStatement::MultipleDefinition( + .push(TypedStatement::EmbedCallDefinition( v, - TypedExpressionListInner::EmbedCall(embed, generics, arguments) - .annotate(output_types), + EmbedCall::new(embed, generics, arguments), )); Ok(FunctionCallOrExpression::Expression(E::identifier( identifier, @@ -329,84 +324,6 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Reducer<'ast, 'a, T> { s: TypedStatement<'ast, T>, ) -> Result>, Self::Error> { let res = match s { - TypedStatement::MultipleDefinition( - v, - TypedExpressionList { - inner: TypedExpressionListInner::FunctionCall(function_call), - types, - }, - ) => { - let generics = function_call - .generics - .into_iter() - .map(|g| g.map(|g| self.fold_uint_expression(g)).transpose()) - .collect::>()?; - - let arguments = function_call - .arguments - .into_iter() - .map(|a| self.fold_expression(a)) - .collect::>()?; - - match inline_call::<_, TypedExpressionList<'ast, T>>( - function_call.function_key, - generics, - arguments, - &types, - self.program, - self.versions, - ) { - Ok(Output::Complete((statements, expressions))) => { - assert_eq!(v.len(), expressions.len()); - - self.complete &= true; - - Ok(statements - .into_iter() - .chain( - v.into_iter() - .zip(expressions) - .map(|(v, e)| TypedStatement::Definition(v, e)), - ) - .collect()) - } - Ok(Output::Incomplete((statements, expressions), delta_for_loop_versions)) => { - assert_eq!(v.len(), expressions.len()); - - self.complete = false; - self.for_loop_versions_after.extend(delta_for_loop_versions); - - Ok(statements - .into_iter() - .chain( - v.into_iter() - .zip(expressions) - .map(|(v, e)| TypedStatement::Definition(v, e)), - ) - .collect()) - } - Err(InlineError::Generic(decl, conc)) => Err(Error::Incompatible(format!( - "Call site `{}` incompatible with declaration `{}`", - conc, decl - ))), - Err(InlineError::NonConstant(key, generics, arguments, output_types)) => { - self.complete = false; - - Ok(vec![TypedStatement::MultipleDefinition( - v, - TypedExpressionList::function_call(key, generics, arguments) - .annotate(output_types), - )]) - } - Err(InlineError::Flat(embed, generics, arguments, output_types)) => { - Ok(vec![TypedStatement::MultipleDefinition( - v, - TypedExpressionListInner::EmbedCall(embed, generics, arguments) - .annotate(output_types), - )]) - } - } - } TypedStatement::For(v, from, to, statements) => { let versions_before = self.for_loop_versions.pop().unwrap(); @@ -640,13 +557,13 @@ fn compute_hash(f: &TypedFunction) -> u64 { #[cfg(test)] mod tests { use super::*; - use crate::typed_absy::types::DeclarationConstant; use crate::typed_absy::types::DeclarationSignature; + use crate::typed_absy::types::{DeclarationConstant, GTupleType}; use crate::typed_absy::{ ArrayExpression, ArrayExpressionInner, DeclarationFunctionKey, DeclarationType, DeclarationVariable, FieldElementExpression, GenericIdentifier, Identifier, - OwnedTypedModuleId, Select, Type, TypedExpression, TypedExpressionList, - TypedExpressionOrSpread, Types, UBitwidth, UExpressionInner, Variable, + OwnedTypedModuleId, Select, TupleExpressionInner, TupleType, Type, TypedExpression, + TypedExpressionOrSpread, UBitwidth, UExpressionInner, Variable, }; use zokrates_field::Bn128Field; @@ -683,12 +600,12 @@ mod tests { let foo: TypedFunction = TypedFunction { arguments: vec![DeclarationVariable::field_element("a").into()], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( FieldElementExpression::Identifier("a".into()).into(), - ])], + )], signature: DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let main: TypedFunction = TypedFunction { @@ -708,18 +625,18 @@ mod tests { Variable::field_element("a").into(), FieldElementExpression::Identifier("a".into()).into(), ), - TypedStatement::MultipleDefinition( - vec![Variable::field_element("a").into()], - TypedExpressionList::function_call( + TypedStatement::Definition( + Variable::field_element("a").into(), + FieldElementExpression::function_call( DeclarationFunctionKey::with_location("main", "foo").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), vec![], vec![FieldElementExpression::Identifier("a".into()).into()], ) - .annotate(Types::new(vec![Type::FieldElement])), + .into(), ), TypedStatement::Definition( Variable::uint("n", UBitwidth::B32).into(), @@ -727,11 +644,11 @@ mod tests { .annotate(UBitwidth::B32) .into(), ), - TypedStatement::Return(vec![FieldElementExpression::Identifier("a".into()).into()]), + TypedStatement::Return(FieldElementExpression::Identifier("a".into()).into()), ], signature: DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let p = TypedProgram { @@ -744,7 +661,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "foo").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(foo), ) @@ -753,7 +670,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(main), ) @@ -778,7 +695,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "foo").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), GGenericsAssignment::default(), ), @@ -799,14 +716,13 @@ mod tests { ) .into(), ), - TypedStatement::Return(vec![FieldElementExpression::Identifier( - Identifier::from("a").version(2), - ) - .into()]), + TypedStatement::Return( + FieldElementExpression::Identifier(Identifier::from("a").version(2)).into(), + ), ], signature: DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let expected: TypedProgram = TypedProgram { @@ -818,7 +734,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(expected_main), ) @@ -865,10 +781,10 @@ mod tests { DeclarationType::FieldElement, DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)), ))]) - .outputs(vec![DeclarationType::array(( + .output(DeclarationType::array(( DeclarationType::FieldElement, DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)), - ))]); + ))); let foo: TypedFunction = TypedFunction { arguments: vec![DeclarationVariable::array( @@ -877,11 +793,11 @@ mod tests { GenericIdentifier::with_name("K").with_index(0), ) .into()], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( ArrayExpressionInner::Identifier("a".into()) .annotate(Type::FieldElement, 1u32) .into(), - ])], + )], signature: foo_signature.clone(), }; @@ -906,9 +822,9 @@ mod tests { .annotate(Type::FieldElement, 1u32) .into(), ), - TypedStatement::MultipleDefinition( - vec![Variable::array("b", Type::FieldElement, 1u32).into()], - TypedExpressionList::function_call( + TypedStatement::Definition( + Variable::array("b", Type::FieldElement, 1u32).into(), + ArrayExpression::function_call( DeclarationFunctionKey::with_location("main", "foo") .signature(foo_signature.clone()), vec![None], @@ -916,7 +832,8 @@ mod tests { .annotate(Type::FieldElement, 1u32) .into()], ) - .annotate(Types::new(vec![Type::array((Type::FieldElement, 1u32))])), + .annotate(Type::FieldElement, 1u32) + .into(), ), TypedStatement::Definition( Variable::uint("n", UBitwidth::B32).into(), @@ -924,17 +841,19 @@ mod tests { .annotate(UBitwidth::B32) .into(), ), - TypedStatement::Return(vec![(FieldElementExpression::Identifier("a".into()) - + FieldElementExpression::select( - ArrayExpressionInner::Identifier("b".into()) - .annotate(Type::FieldElement, 1u32), - 0u32, - )) - .into()]), + TypedStatement::Return( + (FieldElementExpression::Identifier("a".into()) + + FieldElementExpression::select( + ArrayExpressionInner::Identifier("b".into()) + .annotate(Type::FieldElement, 1u32), + 0u32, + )) + .into(), + ), ], signature: DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let p = TypedProgram { @@ -953,7 +872,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(main), ) @@ -1015,17 +934,19 @@ mod tests { .annotate(Type::FieldElement, 1u32) .into(), ), - TypedStatement::Return(vec![(FieldElementExpression::Identifier("a".into()) - + FieldElementExpression::select( - ArrayExpressionInner::Identifier(Identifier::from("b").version(1)) - .annotate(Type::FieldElement, 1u32), - 0u32, - )) - .into()]), + TypedStatement::Return( + (FieldElementExpression::Identifier("a".into()) + + FieldElementExpression::select( + ArrayExpressionInner::Identifier(Identifier::from("b").version(1)) + .annotate(Type::FieldElement, 1u32), + 0u32, + )) + .into(), + ), ], signature: DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let expected = TypedProgram { @@ -1037,7 +958,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(expected_main), ) @@ -1084,10 +1005,10 @@ mod tests { DeclarationType::FieldElement, DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)), ))]) - .outputs(vec![DeclarationType::array(( + .output(DeclarationType::array(( DeclarationType::FieldElement, DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)), - ))]); + ))); let foo: TypedFunction = TypedFunction { arguments: vec![DeclarationVariable::array( @@ -1096,11 +1017,11 @@ mod tests { GenericIdentifier::with_name("K").with_index(0), ) .into()], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( ArrayExpressionInner::Identifier("a".into()) .annotate(Type::FieldElement, 1u32) .into(), - ])], + )], signature: foo_signature.clone(), }; @@ -1134,9 +1055,9 @@ mod tests { .annotate(Type::FieldElement, 1u32) .into(), ), - TypedStatement::MultipleDefinition( - vec![Variable::array("b", Type::FieldElement, 1u32).into()], - TypedExpressionList::function_call( + TypedStatement::Definition( + Variable::array("b", Type::FieldElement, 1u32).into(), + ArrayExpression::function_call( DeclarationFunctionKey::with_location("main", "foo") .signature(foo_signature.clone()), vec![None], @@ -1144,7 +1065,8 @@ mod tests { .annotate(Type::FieldElement, 1u32) .into()], ) - .annotate(Types::new(vec![Type::array((Type::FieldElement, 1u32))])), + .annotate(Type::FieldElement, 1u32) + .into(), ), TypedStatement::Definition( Variable::uint("n", UBitwidth::B32).into(), @@ -1152,17 +1074,19 @@ mod tests { .annotate(UBitwidth::B32) .into(), ), - TypedStatement::Return(vec![(FieldElementExpression::Identifier("a".into()) - + FieldElementExpression::select( - ArrayExpressionInner::Identifier("b".into()) - .annotate(Type::FieldElement, 1u32), - 0u32, - )) - .into()]), + TypedStatement::Return( + (FieldElementExpression::Identifier("a".into()) + + FieldElementExpression::select( + ArrayExpressionInner::Identifier("b".into()) + .annotate(Type::FieldElement, 1u32), + 0u32, + )) + .into(), + ), ], signature: DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let p = TypedProgram { @@ -1181,7 +1105,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(main), ) @@ -1243,17 +1167,19 @@ mod tests { .annotate(Type::FieldElement, 1u32) .into(), ), - TypedStatement::Return(vec![(FieldElementExpression::Identifier("a".into()) - + FieldElementExpression::select( - ArrayExpressionInner::Identifier(Identifier::from("b").version(1)) - .annotate(Type::FieldElement, 1u32), - 0u32, - )) - .into()]), + TypedStatement::Return( + (FieldElementExpression::Identifier("a".into()) + + FieldElementExpression::select( + ArrayExpressionInner::Identifier(Identifier::from("b").version(1)) + .annotate(Type::FieldElement, 1u32), + 0u32, + )) + .into(), + ), ], signature: DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let expected = TypedProgram { @@ -1265,7 +1191,7 @@ mod tests { DeclarationFunctionKey::with_location("main", "main").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), TypedFunctionSymbol::Here(expected_main), ) @@ -1312,10 +1238,10 @@ mod tests { DeclarationType::FieldElement, DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)), ))]) - .outputs(vec![DeclarationType::array(( + .output(DeclarationType::array(( DeclarationType::FieldElement, DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)), - ))]) + ))) .generics(vec![Some( GenericIdentifier::with_name("K").with_index(0).into(), )]); @@ -1372,12 +1298,14 @@ mod tests { ) .into(), ), - TypedStatement::Return(vec![ArrayExpressionInner::Identifier("ret".into()) - .annotate( - Type::FieldElement, - UExpressionInner::Identifier("K".into()).annotate(UBitwidth::B32), - ) - .into()]), + TypedStatement::Return( + ArrayExpressionInner::Identifier("ret".into()) + .annotate( + Type::FieldElement, + UExpressionInner::Identifier("K".into()).annotate(UBitwidth::B32), + ) + .into(), + ), ], signature: foo_signature.clone(), }; @@ -1391,23 +1319,23 @@ mod tests { DeclarationConstant::Generic(GenericIdentifier::with_name("K").with_index(0)), ) .into()], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( ArrayExpressionInner::Identifier("a".into()) .annotate( Type::FieldElement, UExpressionInner::Identifier("K".into()).annotate(UBitwidth::B32), ) .into(), - ])], + )], signature: bar_signature.clone(), }; let main: TypedFunction = TypedFunction { arguments: vec![], statements: vec![ - TypedStatement::MultipleDefinition( - vec![Variable::array("b", Type::FieldElement, 1u32).into()], - TypedExpressionList::function_call( + TypedStatement::Definition( + Variable::array("b", Type::FieldElement, 1u32).into(), + ArrayExpression::function_call( DeclarationFunctionKey::with_location("main", "foo") .signature(foo_signature.clone()), vec![None], @@ -1417,9 +1345,14 @@ mod tests { .annotate(Type::FieldElement, 1u32) .into()], ) - .annotate(Types::new(vec![Type::array((Type::FieldElement, 1u32))])), + .annotate(Type::FieldElement, 1u32) + .into(), + ), + TypedStatement::Return( + TupleExpressionInner::Value(vec![]) + .annotate(TupleType::new(vec![])) + .into(), ), - TypedStatement::Return(vec![]), ], signature: DeclarationSignature::new(), }; @@ -1479,7 +1412,11 @@ mod tests { ), TypedStatement::PopCallLog, TypedStatement::PopCallLog, - TypedStatement::Return(vec![]), + TypedStatement::Return( + TupleExpressionInner::Value(vec![]) + .annotate(TupleType::new(vec![])) + .into(), + ), ], signature: DeclarationSignature::new(), }; @@ -1525,10 +1462,10 @@ mod tests { DeclarationType::FieldElement, GenericIdentifier::with_name("K").with_index(0), ))]) - .outputs(vec![DeclarationType::array(( + .output(DeclarationType::array(( DeclarationType::FieldElement, GenericIdentifier::with_name("K").with_index(0), - ))]); + ))); let foo: TypedFunction = TypedFunction { arguments: vec![DeclarationVariable::array( @@ -1537,20 +1474,20 @@ mod tests { GenericIdentifier::with_name("K").with_index(0), ) .into()], - statements: vec![TypedStatement::Return(vec![ + statements: vec![TypedStatement::Return( ArrayExpressionInner::Identifier("a".into()) .annotate(Type::FieldElement, 1u32) .into(), - ])], + )], signature: foo_signature.clone(), }; let main: TypedFunction = TypedFunction { arguments: vec![], statements: vec![ - TypedStatement::MultipleDefinition( - vec![Variable::array("b", Type::FieldElement, 1u32).into()], - TypedExpressionList::function_call( + TypedStatement::Definition( + Variable::array("b", Type::FieldElement, 1u32).into(), + ArrayExpression::function_call( DeclarationFunctionKey::with_location("main", "foo") .signature(foo_signature.clone()), vec![None], @@ -1558,11 +1495,18 @@ mod tests { .annotate(Type::FieldElement, 0u32) .into()], ) - .annotate(Types::new(vec![Type::array((Type::FieldElement, 1u32))])), + .annotate(Type::FieldElement, 1u32) + .into(), + ), + TypedStatement::Return( + TupleExpressionInner::Value(vec![]) + .annotate(TupleType::new(vec![])) + .into(), ), - TypedStatement::Return(vec![]), ], - signature: DeclarationSignature::new().inputs(vec![]).outputs(vec![]), + signature: DeclarationSignature::new() + .inputs(vec![]) + .output(DeclarationType::Tuple(GTupleType::new(vec![]))), }; let p = TypedProgram { @@ -1579,7 +1523,9 @@ mod tests { .into(), TypedFunctionSymbolDeclaration::new( DeclarationFunctionKey::with_location("main", "main").signature( - DeclarationSignature::new().inputs(vec![]).outputs(vec![]), + DeclarationSignature::new() + .inputs(vec![]) + .output(DeclarationType::Tuple(GTupleType::new(vec![]))), ), TypedFunctionSymbol::Here(main), ) diff --git a/zokrates_core/src/static_analysis/reducer/shallow_ssa.rs b/zokrates_core/src/static_analysis/reducer/shallow_ssa.rs index b4ddbc9b..a41b2ec5 100644 --- a/zokrates_core/src/static_analysis/reducer/shallow_ssa.rs +++ b/zokrates_core/src/static_analysis/reducer/shallow_ssa.rs @@ -141,20 +141,16 @@ impl<'ast, 'a, T: Field> Folder<'ast, T> for ShallowTransformer<'ast, 'a> { vec![TypedStatement::Definition(a, e)] } - TypedStatement::MultipleDefinition(assignees, exprs) => { - let exprs = self.fold_expression_list(exprs); - let assignees = assignees - .into_iter() - .map(|a| match a { - TypedAssignee::Identifier(v) => { - let v = self.issue_next_ssa_variable(v); - TypedAssignee::Identifier(self.fold_variable(v)) - } - a => fold_assignee(self, a), - }) - .collect(); - - vec![TypedStatement::MultipleDefinition(assignees, exprs)] + TypedStatement::EmbedCallDefinition(assignee, embed_call) => { + let assignee = match assignee { + TypedAssignee::Identifier(v) => { + let v = self.issue_next_ssa_variable(v); + TypedAssignee::Identifier(self.fold_variable(v)) + } + a => fold_assignee(self, a), + }; + let embed_call = self.fold_embed_call(embed_call); + vec![TypedStatement::EmbedCallDefinition(assignee, embed_call)] } TypedStatement::For(v, from, to, stats) => { let from = self.fold_uint_expression(from); @@ -338,8 +334,6 @@ mod tests { #[test] fn incremental_multiple_definition() { - use crate::typed_absy::types::Type; - // field a // a = 2 // a = foo(a) @@ -370,28 +364,28 @@ mod tests { )] ); - let s: TypedStatement = TypedStatement::MultipleDefinition( - vec![Variable::field_element("a").into()], - TypedExpressionList::function_call( + let s: TypedStatement = TypedStatement::Definition( + Variable::field_element("a").into(), + FieldElementExpression::function_call( DeclarationFunctionKey::with_location("main", "foo").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), ), vec![], vec![FieldElementExpression::Identifier("a".into()).into()], ) - .annotate(Types::new(vec![Type::FieldElement])), + .into(), ); assert_eq!( u.fold_statement(s), - vec![TypedStatement::MultipleDefinition( - vec![Variable::field_element(Identifier::from("a").version(1)).into()], - TypedExpressionList::function_call( + vec![TypedStatement::Definition( + Variable::field_element(Identifier::from("a").version(1)).into(), + FieldElementExpression::function_call( DeclarationFunctionKey::with_location("main", "foo").signature( DeclarationSignature::new() .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]) + .output(DeclarationType::FieldElement) ), vec![], vec![ @@ -399,7 +393,7 @@ mod tests { .into() ] ) - .annotate(Types::new(vec![Type::FieldElement])) + .into() )] ); } @@ -659,16 +653,14 @@ mod tests { Variable::field_element("a").into(), FieldElementExpression::Identifier("a".into()).into(), ), - TypedStatement::Return(vec![ - FieldElementExpression::Identifier("a".into()).into() - ]), + TypedStatement::Return(FieldElementExpression::Identifier("a".into()).into()), ], signature: DeclarationSignature::new() .generics(vec![Some( GenericIdentifier::with_name("K").with_index(0).into(), )]) .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let mut versions = Versions::default(); @@ -738,17 +730,16 @@ mod tests { Variable::field_element(Identifier::from("a").version(5)).into(), FieldElementExpression::Identifier(Identifier::from("a").version(4)).into(), ), - TypedStatement::Return(vec![FieldElementExpression::Identifier( - Identifier::from("a").version(5), - ) - .into()]), + TypedStatement::Return( + FieldElementExpression::Identifier(Identifier::from("a").version(5)).into(), + ), ], signature: DeclarationSignature::new() .generics(vec![Some( GenericIdentifier::with_name("K").with_index(0).into(), )]) .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; assert_eq!( @@ -819,16 +810,16 @@ mod tests { Variable::field_element("a").into(), FieldElementExpression::Identifier("a".into()).into(), ), - TypedStatement::MultipleDefinition( - vec![Variable::field_element("a").into()], - TypedExpressionList::function_call( + TypedStatement::Definition( + Variable::field_element("a").into(), + FieldElementExpression::function_call( DeclarationFunctionKey::with_location("main", "foo"), vec![Some( UExpressionInner::Identifier("n".into()).annotate(UBitwidth::B32), )], vec![FieldElementExpression::Identifier("a".into()).into()], ) - .annotate(Types::new(vec![Type::FieldElement])), + .into(), ), TypedStatement::Definition( Variable::uint("n", UBitwidth::B32).into(), @@ -849,16 +840,14 @@ mod tests { )) .into(), ), - TypedStatement::Return(vec![ - FieldElementExpression::Identifier("a".into()).into() - ]), + TypedStatement::Return(FieldElementExpression::Identifier("a".into()).into()), ], signature: DeclarationSignature::new() .generics(vec![Some( GenericIdentifier::with_name("K").with_index(0).into(), )]) .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; let mut versions = Versions::default(); @@ -894,9 +883,9 @@ mod tests { Variable::field_element(Identifier::from("a").version(1)).into(), FieldElementExpression::Identifier("a".into()).into(), ), - TypedStatement::MultipleDefinition( - vec![Variable::field_element(Identifier::from("a").version(2)).into()], - TypedExpressionList::function_call( + TypedStatement::Definition( + Variable::field_element(Identifier::from("a").version(2)).into(), + FieldElementExpression::function_call( DeclarationFunctionKey::with_location("main", "foo"), vec![Some( UExpressionInner::Identifier(Identifier::from("n").version(1)) @@ -907,7 +896,7 @@ mod tests { ) .into()], ) - .annotate(Types::new(vec![Type::FieldElement])), + .into(), ), TypedStatement::Definition( Variable::uint(Identifier::from("n").version(2), UBitwidth::B32).into(), @@ -931,17 +920,16 @@ mod tests { )) .into(), ), - TypedStatement::Return(vec![FieldElementExpression::Identifier( - Identifier::from("a").version(3), - ) - .into()]), + TypedStatement::Return( + FieldElementExpression::Identifier(Identifier::from("a").version(3)).into(), + ), ], signature: DeclarationSignature::new() .generics(vec![Some( GenericIdentifier::with_name("K").with_index(0).into(), )]) .inputs(vec![DeclarationType::FieldElement]) - .outputs(vec![DeclarationType::FieldElement]), + .output(DeclarationType::FieldElement), }; assert_eq!( diff --git a/zokrates_core/src/static_analysis/struct_concretizer.rs b/zokrates_core/src/static_analysis/struct_concretizer.rs index 71502cc1..9b090a49 100644 --- a/zokrates_core/src/static_analysis/struct_concretizer.rs +++ b/zokrates_core/src/static_analysis/struct_concretizer.rs @@ -83,7 +83,7 @@ impl<'ast, T: Field> Folder<'ast, T> for StructConcretizer<'ast, T> { let size = ty.size.map_concrete(&self.generics).unwrap(); DeclarationArrayType { - size: DeclarationConstant::Concrete(size), + size: box DeclarationConstant::Concrete(size), ty: box self.fold_declaration_type(*ty.ty), } } diff --git a/zokrates_core/src/static_analysis/variable_write_remover.rs b/zokrates_core/src/static_analysis/variable_write_remover.rs index 2780475f..e8336d28 100644 --- a/zokrates_core/src/static_analysis/variable_write_remover.rs +++ b/zokrates_core/src/static_analysis/variable_write_remover.rs @@ -45,7 +45,7 @@ impl<'ast> VariableWriteRemover { let tail = indices; match head { - Access::Select(head) => { + Access::Select(box head) => { statements.insert(TypedStatement::Assertion( BooleanExpression::UintLt(box head.clone(), box size.into()), RuntimeError::SelectRangeCheck, @@ -409,7 +409,7 @@ impl<'ast> VariableWriteRemover { #[derive(Clone, Debug)] enum Access<'ast, T: Field> { - Select(UExpression<'ast, T>), + Select(Box>), Member(MemberId), Element(u32), } @@ -420,7 +420,7 @@ fn linear(a: TypedAssignee) -> (Variable, Vec>) { TypedAssignee::Identifier(v) => (v, vec![]), TypedAssignee::Select(box array, box index) => { let (v, mut indices) = linear(array); - indices.push(Access::Select(index)); + indices.push(Access::Select(box index)); (v, indices) } TypedAssignee::Member(box s, m) => { @@ -473,7 +473,7 @@ impl<'ast, T: Field> Folder<'ast, T> for VariableWriteRemover { .into(), Type::Array(array_type) => { ArrayExpressionInner::Identifier(variable.id.clone()) - .annotate(*array_type.ty, array_type.size) + .annotate(*array_type.ty, *array_type.size) .into() } Type::Struct(members) => { @@ -493,7 +493,9 @@ impl<'ast, T: Field> Folder<'ast, T> for VariableWriteRemover { let indices = indices .into_iter() .map(|a| match a { - Access::Select(i) => Access::Select(self.fold_uint_expression(i)), + Access::Select(box i) => { + Access::Select(box self.fold_uint_expression(i)) + } a => a, }) .collect(); diff --git a/zokrates_core/src/typed_absy/abi.rs b/zokrates_core/src/typed_absy/abi.rs index 4bcd11b6..95e4602e 100644 --- a/zokrates_core/src/typed_absy/abi.rs +++ b/zokrates_core/src/typed_absy/abi.rs @@ -14,7 +14,7 @@ pub type AbiOutput = ConcreteType; #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] pub struct Abi { pub inputs: Vec, - pub outputs: Vec, + pub output: AbiOutput, } impl Abi { @@ -22,7 +22,7 @@ impl Abi { ConcreteSignature { generics: vec![], inputs: self.inputs.iter().map(|i| i.ty.clone()).collect(), - outputs: self.outputs.clone(), + output: box self.output.clone(), } } } @@ -31,7 +31,8 @@ impl Abi { mod tests { use super::*; use crate::typed_absy::types::{ - ConcreteArrayType, ConcreteFunctionKey, ConcreteStructMember, ConcreteStructType, UBitwidth, + ConcreteArrayType, ConcreteFunctionKey, ConcreteStructMember, ConcreteStructType, + GTupleType, UBitwidth, }; use crate::typed_absy::{ parameter::DeclarationParameter, variable::DeclarationVariable, ConcreteTupleType, @@ -59,7 +60,7 @@ mod tests { statements: vec![], signature: ConcreteSignature::new() .inputs(vec![ConcreteType::FieldElement, ConcreteType::Boolean]) - .outputs(vec![ConcreteType::FieldElement]) + .output(ConcreteType::FieldElement) .into(), }), ) @@ -87,7 +88,7 @@ mod tests { ty: ConcreteType::Boolean, }, ], - outputs: vec![ConcreteType::FieldElement], + output: ConcreteType::FieldElement, }; assert_eq!(expected_abi, abi); @@ -97,11 +98,14 @@ mod tests { fn serialize_empty() { let abi: Abi = Abi { inputs: vec![], - outputs: vec![], + output: ConcreteType::Tuple(GTupleType::new(vec![])), }; let json = serde_json::to_string(&abi).unwrap(); - assert_eq!(&json, r#"{"inputs":[],"outputs":[]}"#); + assert_eq!( + &json, + r#"{"inputs":[],"output":{"type":"tuple","components":{"elements":[]}}}"# + ); let de_abi: Abi = serde_json::from_str(json.as_ref()).unwrap(); assert_eq!(de_abi, abi); } @@ -113,7 +117,7 @@ mod tests { let abi: Abi = Abi { inputs: vec![], - outputs: vec![ConcreteType::Int], + output: ConcreteType::Int, }; let _ = serde_json::to_string_pretty(&abi).unwrap(); @@ -134,7 +138,7 @@ mod tests { ty: ConcreteType::FieldElement, }, ], - outputs: vec![ConcreteType::FieldElement], + output: ConcreteType::FieldElement, }; let json = serde_json::to_string_pretty(&abi).unwrap(); @@ -153,11 +157,9 @@ mod tests { "type": "field" } ], - "outputs": [ - { - "type": "field" - } - ] + "output": { + "type": "field" + } }"# ); @@ -185,7 +187,7 @@ mod tests { ty: ConcreteType::Uint(UBitwidth::B32), }, ], - outputs: vec![], + output: ConcreteType::Tuple(GTupleType::new(vec![])), }; let json = serde_json::to_string_pretty(&abi).unwrap(); @@ -209,7 +211,12 @@ mod tests { "type": "u32" } ], - "outputs": [] + "output": { + "type": "tuple", + "components": { + "elements": [] + } + } }"# ); @@ -236,7 +243,7 @@ mod tests { )], )), }], - outputs: vec![ConcreteType::Struct(ConcreteStructType::new( + output: ConcreteType::Struct(ConcreteStructType::new( "".into(), "Foo".into(), vec![], @@ -244,7 +251,7 @@ mod tests { ConcreteStructMember::new(String::from("a"), ConcreteType::FieldElement), ConcreteStructMember::new(String::from("b"), ConcreteType::Boolean), ], - ))], + )), }; let json = serde_json::to_string_pretty(&abi).unwrap(); @@ -274,25 +281,23 @@ mod tests { } } ], - "outputs": [ - { - "type": "struct", - "components": { - "name": "Foo", - "generics": [], - "members": [ - { - "name": "a", - "type": "field" - }, - { - "name": "b", - "type": "bool" - } - ] - } + "output": { + "type": "struct", + "components": { + "name": "Foo", + "generics": [], + "members": [ + { + "name": "a", + "type": "field" + }, + { + "name": "b", + "type": "bool" + } + ] } - ] + } }"# ); @@ -330,7 +335,7 @@ mod tests { )], )), }], - outputs: vec![], + output: ConcreteType::Tuple(GTupleType::new(vec![])), }; let json = serde_json::to_string_pretty(&abi).unwrap(); @@ -368,7 +373,12 @@ mod tests { } } ], - "outputs": [] + "output": { + "type": "tuple", + "components": { + "elements": [] + } + } }"# ); @@ -398,7 +408,7 @@ mod tests { 2u32, )), }], - outputs: vec![ConcreteType::Boolean], + output: ConcreteType::Boolean, }; let json = serde_json::to_string_pretty(&abi).unwrap(); @@ -430,11 +440,9 @@ mod tests { } } ], - "outputs": [ - { - "type": "bool" - } - ] + "output": { + "type": "bool" + } }"# ); @@ -453,7 +461,7 @@ mod tests { 2u32, )), }], - outputs: vec![ConcreteType::FieldElement], + output: ConcreteType::FieldElement, }; let json = serde_json::to_string_pretty(&abi).unwrap(); @@ -475,11 +483,9 @@ mod tests { } } ], - "outputs": [ - { - "type": "field" - } - ] + "output": { + "type": "field" + } }"# ); @@ -498,9 +504,7 @@ mod tests { ConcreteType::Boolean, ])), }], - outputs: vec![ConcreteType::Tuple(ConcreteTupleType::new(vec![ - ConcreteType::FieldElement, - ]))], + output: ConcreteType::Tuple(ConcreteTupleType::new(vec![ConcreteType::FieldElement])), }; let json = serde_json::to_string_pretty(&abi).unwrap(); @@ -524,18 +528,16 @@ mod tests { } } ], - "outputs": [ - { - "type": "tuple", - "components": { - "elements": [ - { - "type": "field" - } - ] - } + "output": { + "type": "tuple", + "components": { + "elements": [ + { + "type": "field" + } + ] } - ] + } }"# ); diff --git a/zokrates_core/src/typed_absy/folder.rs b/zokrates_core/src/typed_absy/folder.rs index 2c4e861c..9f46dfcc 100644 --- a/zokrates_core/src/typed_absy/folder.rs +++ b/zokrates_core/src/typed_absy/folder.rs @@ -166,14 +166,10 @@ pub trait Folder<'ast, T: Field>: Sized { } } - fn fold_types(&mut self, tys: Types<'ast, T>) -> Types<'ast, T> { - fold_types(self, tys) - } - fn fold_array_type(&mut self, t: ArrayType<'ast, T>) -> ArrayType<'ast, T> { ArrayType { ty: box self.fold_type(*t.ty), - size: self.fold_uint_expression(t.size), + size: box self.fold_uint_expression(*t.size), } } @@ -208,6 +204,7 @@ pub trait Folder<'ast, T: Field>: Sized { match t { Array(array_type) => Array(self.fold_declaration_array_type(array_type)), Struct(struct_type) => Struct(self.fold_declaration_struct_type(struct_type)), + Tuple(tuple_type) => Tuple(self.fold_declaration_tuple_type(tuple_type)), t => t, } } @@ -218,7 +215,7 @@ pub trait Folder<'ast, T: Field>: Sized { ) -> DeclarationArrayType<'ast, T> { DeclarationArrayType { ty: box self.fold_declaration_type(*t.ty), - size: self.fold_declaration_constant(t.size), + size: box self.fold_declaration_constant(*t.size), } } @@ -265,6 +262,10 @@ pub trait Folder<'ast, T: Field>: Sized { fold_statement(self, s) } + fn fold_embed_call(&mut self, e: EmbedCall<'ast, T>) -> EmbedCall<'ast, T> { + fold_embed_call(self, e) + } + fn fold_expression_or_spread( &mut self, e: TypedExpressionOrSpread<'ast, T>, @@ -300,15 +301,7 @@ pub trait Folder<'ast, T: Field>: Sized { } fn fold_expression(&mut self, e: TypedExpression<'ast, T>) -> TypedExpression<'ast, T> { - match e { - TypedExpression::FieldElement(e) => self.fold_field_expression(e).into(), - TypedExpression::Boolean(e) => self.fold_boolean_expression(e).into(), - TypedExpression::Uint(e) => self.fold_uint_expression(e).into(), - TypedExpression::Array(e) => self.fold_array_expression(e).into(), - TypedExpression::Tuple(e) => self.fold_tuple_expression(e).into(), - TypedExpression::Struct(e) => self.fold_struct_expression(e).into(), - TypedExpression::Int(e) => self.fold_int_expression(e).into(), - } + fold_expression(self, e) } fn fold_block_expression>( @@ -394,21 +387,6 @@ pub trait Folder<'ast, T: Field>: Sized { fold_tuple_expression(self, e) } - fn fold_expression_list( - &mut self, - es: TypedExpressionList<'ast, T>, - ) -> TypedExpressionList<'ast, T> { - fold_expression_list(self, es) - } - - fn fold_expression_list_inner( - &mut self, - tys: Types<'ast, T>, - es: TypedExpressionListInner<'ast, T>, - ) -> TypedExpressionListInner<'ast, T> { - fold_expression_list_inner(self, tys, es) - } - fn fold_int_expression(&mut self, e: IntExpression<'ast, T>) -> IntExpression<'ast, T> { fold_int_expression(self, e) } @@ -419,12 +397,14 @@ pub trait Folder<'ast, T: Field>: Sized { ) -> FieldElementExpression<'ast, T> { fold_field_expression(self, e) } + fn fold_boolean_expression( &mut self, e: BooleanExpression<'ast, T>, ) -> BooleanExpression<'ast, T> { fold_boolean_expression(self, e) } + fn fold_uint_expression(&mut self, e: UExpression<'ast, T>) -> UExpression<'ast, T> { fold_uint_expression(self, e) } @@ -514,12 +494,7 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>( s: TypedStatement<'ast, T>, ) -> Vec> { let res = match s { - TypedStatement::Return(expressions) => TypedStatement::Return( - expressions - .into_iter() - .map(|e| f.fold_expression(e)) - .collect(), - ), + TypedStatement::Return(e) => TypedStatement::Return(f.fold_expression(e)), TypedStatement::Definition(a, e) => { TypedStatement::Definition(f.fold_assignee(a), f.fold_expression(e)) } @@ -536,15 +511,46 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>( .flat_map(|s| f.fold_statement(s)) .collect(), ), - TypedStatement::MultipleDefinition(assignees, elist) => TypedStatement::MultipleDefinition( - assignees.into_iter().map(|a| f.fold_assignee(a)).collect(), - f.fold_expression_list(elist), - ), + TypedStatement::EmbedCallDefinition(assignee, embed_call) => { + TypedStatement::EmbedCallDefinition( + f.fold_assignee(assignee), + f.fold_embed_call(embed_call), + ) + } s => s, }; vec![res] } +pub fn fold_embed_call<'ast, T: Field, F: Folder<'ast, T>>( + f: &mut F, + e: EmbedCall<'ast, T>, +) -> EmbedCall<'ast, T> { + EmbedCall { + arguments: e + .arguments + .into_iter() + .map(|s| f.fold_expression(s)) + .collect(), + ..e + } +} + +pub fn fold_expression<'ast, T: Field, F: Folder<'ast, T>>( + f: &mut F, + e: TypedExpression<'ast, T>, +) -> TypedExpression<'ast, T> { + match e { + TypedExpression::FieldElement(e) => f.fold_field_expression(e).into(), + TypedExpression::Boolean(e) => f.fold_boolean_expression(e).into(), + TypedExpression::Uint(e) => f.fold_uint_expression(e).into(), + TypedExpression::Array(e) => f.fold_array_expression(e).into(), + TypedExpression::Tuple(e) => f.fold_tuple_expression(e).into(), + TypedExpression::Struct(e) => f.fold_struct_expression(e).into(), + TypedExpression::Int(e) => f.fold_int_expression(e).into(), + } +} + pub fn fold_array_expression_inner<'ast, T: Field, F: Folder<'ast, T>>( f: &mut F, ty: &ArrayType<'ast, T>, @@ -1132,11 +1138,7 @@ fn fold_signature<'ast, T: Field, F: Folder<'ast, T>>( .into_iter() .map(|o| f.fold_declaration_type(o)) .collect(), - outputs: s - .outputs - .into_iter() - .map(|o| f.fold_declaration_type(o)) - .collect(), + output: box f.fold_declaration_type(*s.output), } } @@ -1165,54 +1167,6 @@ pub fn fold_array_expression<'ast, T: Field, F: Folder<'ast, T>>( } } -pub fn fold_expression_list<'ast, T: Field, F: Folder<'ast, T>>( - f: &mut F, - es: TypedExpressionList<'ast, T>, -) -> TypedExpressionList<'ast, T> { - let types = f.fold_types(es.types); - - TypedExpressionList { - inner: f.fold_expression_list_inner(types.clone(), es.inner), - types, - } -} - -pub fn fold_types<'ast, T: Field, F: Folder<'ast, T>>( - f: &mut F, - tys: Types<'ast, T>, -) -> Types<'ast, T> { - Types { - inner: tys.inner.into_iter().map(|t| f.fold_type(t)).collect(), - } -} - -pub fn fold_expression_list_inner<'ast, T: Field, F: Folder<'ast, T>>( - f: &mut F, - tys: Types<'ast, T>, - es: TypedExpressionListInner<'ast, T>, -) -> TypedExpressionListInner<'ast, T> { - match es { - TypedExpressionListInner::FunctionCall(function_call) => { - match f.fold_function_call_expression(&tys, function_call) { - FunctionCallOrExpression::FunctionCall(function_call) => { - TypedExpressionListInner::FunctionCall(function_call) - } - FunctionCallOrExpression::Expression(u) => u, - } - } - TypedExpressionListInner::EmbedCall(embed, generics, arguments) => { - TypedExpressionListInner::EmbedCall( - embed, - generics, - arguments - .into_iter() - .map(|a| f.fold_expression(a)) - .collect(), - ) - } - } -} - pub fn fold_struct_expression<'ast, T: Field, F: Folder<'ast, T>>( f: &mut F, e: StructExpression<'ast, T>, diff --git a/zokrates_core/src/typed_absy/integer.rs b/zokrates_core/src/typed_absy/integer.rs index 2d979cb6..2f088c2b 100644 --- a/zokrates_core/src/typed_absy/integer.rs +++ b/zokrates_core/src/typed_absy/integer.rs @@ -86,7 +86,7 @@ impl<'ast, T: Clone> IntegerInference for ArrayType<'ast, T> { Ok(DeclarationArrayType::new( self.ty .get_common_pattern(*other.ty) - .map_err(|(t, u)| (ArrayType::new(t, s0), ArrayType::new(u, s1)))?, + .map_err(|(t, u)| (ArrayType::new(t, *s0), ArrayType::new(u, *s1)))?, DeclarationConstant::Generic(GenericIdentifier::with_name("DUMMY")), // sizes are not checked at this stage, therefore we insert a dummy generic variable which will be equal to all possible sizes )) } @@ -657,28 +657,28 @@ impl<'ast, T: Field> ArrayExpression<'ast, T> { let inner_ty = res.0[0].get_type().0; - Ok(ArrayExpressionInner::Value(res).annotate(inner_ty, array_ty.size)) + Ok(ArrayExpressionInner::Value(res).annotate(inner_ty, *array_ty.size)) } ArrayExpressionInner::Repeat(box e, box count) => { match &*target_array_ty.ty { GType::Int => Ok(ArrayExpressionInner::Repeat(box e, box count) - .annotate(Type::Int, array_ty.size)), + .annotate(Type::Int, *array_ty.size)), // try to align the repeated element to the target type t => TypedExpression::align_to_type(e, t) .map(|e| { let ty = e.get_type().clone(); ArrayExpressionInner::Repeat(box e, box count) - .annotate(ty, array_ty.size) + .annotate(ty, *array_ty.size) }) .map_err(|(e, _)| e), } } a => { if *target_array_ty.ty == *array_ty.ty { - Ok(a.annotate(*array_ty.ty, array_ty.size)) + Ok(a.annotate(*array_ty.ty, *array_ty.size)) } else { - Err(a.annotate(*array_ty.ty, array_ty.size).into()) + Err(a.annotate(*array_ty.ty, *array_ty.size).into()) } } } diff --git a/zokrates_core/src/typed_absy/mod.rs b/zokrates_core/src/typed_absy/mod.rs index 0349adc0..747b23a4 100644 --- a/zokrates_core/src/typed_absy/mod.rs +++ b/zokrates_core/src/typed_absy/mod.rs @@ -22,11 +22,11 @@ pub use self::types::{ CanonicalConstantIdentifier, ConcreteFunctionKey, ConcreteSignature, ConcreteTupleType, ConcreteType, ConstantIdentifier, DeclarationArrayType, DeclarationConstant, DeclarationFunctionKey, DeclarationSignature, DeclarationStructType, DeclarationType, - GArrayType, GStructType, GType, GenericIdentifier, IntoTypes, Signature, StructType, TupleType, - Type, Types, UBitwidth, + GArrayType, GStructType, GType, GenericIdentifier, Signature, StructType, TupleType, Type, + UBitwidth, }; use crate::parser::Position; -use crate::typed_absy::types::ConcreteGenericsAssignment; +use crate::typed_absy::types::{ConcreteGenericsAssignment, IntoType}; pub use self::variable::{ConcreteVariable, DeclarationVariable, GVariable, Variable}; use std::marker::PhantomData; @@ -123,21 +123,14 @@ impl<'ast, T: Field> TypedProgram<'ast, T> { .unwrap() }) .collect(), - outputs: main - .signature - .outputs - .iter() - .map(|ty| { - types::ConcreteType::try_from( - crate::typed_absy::types::try_from_g_type::< - DeclarationConstant<'ast, T>, - UExpression<'ast, T>, - >(ty.clone()) - .unwrap(), - ) - .unwrap() - }) - .collect(), + output: types::ConcreteType::try_from( + crate::typed_absy::types::try_from_g_type::< + DeclarationConstant<'ast, T>, + UExpression<'ast, T>, + >(*main.signature.output.clone()) + .unwrap(), + ) + .unwrap(), } } } @@ -362,23 +355,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedFunction<'ast, T> { .join(", "), )?; - write!( - f, - "{} {{", - match self.signature.outputs.len() { - 0 => "".into(), - 1 => format!(" -> {}", self.signature.outputs[0]), - _ => format!( - " -> ({})", - self.signature - .outputs - .iter() - .map(|x| format!("{}", x)) - .collect::>() - .join(", ") - ), - } - )?; + write!(f, " -> {} {{", self.signature.output)?; writeln!(f)?; @@ -628,11 +605,58 @@ impl fmt::Display for RuntimeError { } } +#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)] +pub struct EmbedCall<'ast, T> { + pub embed: FlatEmbed, + pub generics: Vec, + pub arguments: Vec>, +} + +impl<'ast, T> EmbedCall<'ast, T> { + pub fn new( + embed: FlatEmbed, + generics: Vec, + arguments: Vec>, + ) -> Self { + Self { + embed, + generics, + arguments, + } + } +} + +impl<'ast, T: fmt::Display> fmt::Display for EmbedCall<'ast, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.embed.id())?; + if !self.generics.is_empty() { + write!( + f, + "::<{}>", + self.generics + .iter() + .map(|g| g.to_string()) + .collect::>() + .join(", ") + )?; + } + write!(f, "(")?; + let len = self.arguments.len(); + for (i, arg) in self.arguments.iter().enumerate() { + write!(f, "{}", arg)?; + if i < len - 1 { + write!(f, ", ")?; + } + } + write!(f, ")") + } +} + /// A statement in a `TypedFunction` #[allow(clippy::large_enum_variant)] #[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)] pub enum TypedStatement<'ast, T> { - Return(Vec>), + Return(TypedExpression<'ast, T>), Definition(TypedAssignee<'ast, T>, TypedExpression<'ast, T>), Declaration(Variable<'ast, T>), Assertion(BooleanExpression<'ast, T>, RuntimeError), @@ -642,7 +666,7 @@ pub enum TypedStatement<'ast, T> { UExpression<'ast, T>, Vec>, ), - MultipleDefinition(Vec>, TypedExpressionList<'ast, T>), + EmbedCallDefinition(TypedAssignee<'ast, T>, EmbedCall<'ast, T>), // Aux PushCallLog( DeclarationFunctionKey<'ast, T>, @@ -671,15 +695,8 @@ impl<'ast, T: fmt::Display> TypedStatement<'ast, T> { impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - TypedStatement::Return(ref exprs) => { - write!(f, "return ")?; - for (i, expr) in exprs.iter().enumerate() { - write!(f, "{}", expr)?; - if i < exprs.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, ";") + TypedStatement::Return(ref e) => { + write!(f, "return {};", e) } TypedStatement::Declaration(ref var) => write!(f, "{};", var), TypedStatement::Definition(ref lhs, ref rhs) => write!(f, "{} = {};", lhs, rhs), @@ -700,14 +717,8 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> { } write!(f, "\t}}") } - TypedStatement::MultipleDefinition(ref ids, ref rhs) => { - for (i, id) in ids.iter().enumerate() { - write!(f, "{}", id)?; - if i < ids.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, " = {};", rhs) + TypedStatement::EmbedCallDefinition(ref lhs, ref rhs) => { + write!(f, "{} = {};", lhs, rhs) } TypedStatement::PushCallLog(ref key, ref generics) => write!( f, @@ -878,41 +889,6 @@ impl<'ast, T: Clone> Typed<'ast, T> for BooleanExpression<'ast, T> { } } -pub trait MultiTyped<'ast, T> { - fn get_types(&self) -> &Vec>; -} - -#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)] - -pub struct TypedExpressionList<'ast, T> { - pub inner: TypedExpressionListInner<'ast, T>, - pub types: Types<'ast, T>, -} - -impl<'ast, T: fmt::Display> fmt::Display for TypedExpressionList<'ast, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.inner) - } -} - -#[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)] -pub enum TypedExpressionListInner<'ast, T> { - FunctionCall(FunctionCallExpression<'ast, T, TypedExpressionList<'ast, T>>), - EmbedCall(FlatEmbed, Vec, Vec>), -} - -impl<'ast, T> MultiTyped<'ast, T> for TypedExpressionList<'ast, T> { - fn get_types(&self) -> &Vec> { - &self.types.inner - } -} - -impl<'ast, T> TypedExpressionListInner<'ast, T> { - pub fn annotate(self, types: Types<'ast, T>) -> TypedExpressionList<'ast, T> { - TypedExpressionList { inner: self, types } - } -} - #[derive(Clone, PartialEq, Debug, Hash, Eq, PartialOrd, Ord)] pub struct EqExpression { pub left: Box, @@ -1278,7 +1254,7 @@ impl<'ast, T: Field> ArrayValue<'ast, T> { .map(|i| { Some(U::select( a.clone() - .annotate(*array_ty.ty.clone(), array_ty.size.clone()), + .annotate(*array_ty.ty.clone(), *array_ty.size.clone()), i as u32, )) }) @@ -1354,7 +1330,7 @@ impl<'ast, T: Clone> ArrayExpression<'ast, T> { } pub fn size(&self) -> UExpression<'ast, T> { - self.ty.size.clone() + *self.ty.size.clone() } } @@ -1541,15 +1517,6 @@ impl<'ast, T> From> for TupleExpression<'ast, T> { } } -// `TypedExpressionList` can technically not be constructed from `TypedExpression` -// However implementing `From` is required for `TypedExpressionList` to be `Expr`, which makes generic treatment of function calls possible -// This could maybe be avoided by splitting the `Expr` trait into many, but I did not find a way -impl<'ast, T> From> for TypedExpressionList<'ast, T> { - fn from(_: TypedExpression<'ast, T>) -> TypedExpressionList<'ast, T> { - unreachable!() - } -} - impl<'ast, T> From> for FieldElementExpression<'ast, T> { fn from(tc: TypedConstant<'ast, T>) -> FieldElementExpression<'ast, T> { tc.expression.into() @@ -1723,38 +1690,6 @@ impl<'ast, T: fmt::Display> fmt::Display for ArrayExpressionInner<'ast, T> { } } -impl<'ast, T: fmt::Display> fmt::Display for TypedExpressionListInner<'ast, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - TypedExpressionListInner::FunctionCall(ref function_call) => { - write!(f, "{}", function_call) - } - TypedExpressionListInner::EmbedCall(ref embed, ref generics, ref p) => { - write!(f, "{}", embed.id())?; - if !generics.is_empty() { - write!( - f, - "::<{}>", - generics - .iter() - .map(|g| g.to_string()) - .collect::>() - .join(", ") - )?; - } - write!(f, "(")?; - for (i, param) in p.iter().enumerate() { - write!(f, "{}", param)?; - if i < p.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, ")") - } - } - } -} - // Variable to TypedExpression conversion impl<'ast, T: Field> From> for TypedExpression<'ast, T> { @@ -1763,7 +1698,7 @@ impl<'ast, T: Field> From> for TypedExpression<'ast, T> { Type::FieldElement => FieldElementExpression::Identifier(v.id).into(), Type::Boolean => BooleanExpression::Identifier(v.id).into(), Type::Array(ty) => ArrayExpressionInner::Identifier(v.id) - .annotate(*ty.ty, ty.size) + .annotate(*ty.ty, *ty.size) .into(), Type::Struct(ty) => StructExpressionInner::Identifier(v.id).annotate(ty).into(), Type::Tuple(ty) => TupleExpressionInner::Identifier(v.id).annotate(ty).into(), @@ -1777,7 +1712,7 @@ impl<'ast, T: Field> From> for TypedExpression<'ast, T> { pub trait Expr<'ast, T>: fmt::Display + From> { type Inner; - type Ty: Clone + IntoTypes<'ast, T>; + type Ty: Clone + IntoType<'ast, T>; fn ty(&self) -> &Self::Ty; @@ -1935,27 +1870,6 @@ impl<'ast, T: Field> Expr<'ast, T> for IntExpression<'ast, T> { } } -impl<'ast, T: Field> Expr<'ast, T> for TypedExpressionList<'ast, T> { - type Inner = TypedExpressionListInner<'ast, T>; - type Ty = Types<'ast, T>; - - fn ty(&self) -> &Self::Ty { - &self.types - } - - fn into_inner(self) -> Self::Inner { - self.inner - } - - fn as_inner(&self) -> &Self::Inner { - &self.inner - } - - fn as_inner_mut(&mut self) -> &mut Self::Inner { - &mut self.inner - } -} - // Enums types to enable returning e.g a member expression OR another type of expression of this type pub enum FunctionCallOrExpression<'ast, T, E: Expr<'ast, T>> { @@ -2157,7 +2071,8 @@ impl<'ast, T: Clone> Select<'ast, T> for ArrayExpression<'ast, T> { _ => unreachable!(), }; - ArrayExpressionInner::Select(SelectExpression::new(array, index.into())).annotate(*ty, size) + ArrayExpressionInner::Select(SelectExpression::new(array, index.into())) + .annotate(*ty, *size) } } @@ -2223,7 +2138,7 @@ impl<'ast, T: Clone> Member<'ast, T> for ArrayExpression<'ast, T> { }) => (*array_ty.ty.clone(), array_ty.size.clone()), _ => unreachable!(), }; - ArrayExpressionInner::Member(MemberExpression::new(s, id)).annotate(ty, size) + ArrayExpressionInner::Member(MemberExpression::new(s, id)).annotate(ty, *size) } } @@ -2289,7 +2204,7 @@ impl<'ast, T: Clone> Element<'ast, T> for ArrayExpression<'ast, T> { Type::Array(array_ty) => (*array_ty.ty.clone(), array_ty.size.clone()), _ => unreachable!(), }; - ArrayExpressionInner::Element(ElementExpression::new(s, id)).annotate(ty, size) + ArrayExpressionInner::Element(ElementExpression::new(s, id)).annotate(ty, *size) } } @@ -2355,15 +2270,6 @@ impl<'ast, T: Field> Id<'ast, T> for TupleExpression<'ast, T> { } } -// `TypedExpressionList` does not have an Identifier variant -// However implementing `From` is required for `TypedExpressionList` to be `Expr`, which makes generic treatment of function calls possible -// This could maybe be avoided by splitting the `Expr` trait into many, but I did not find a way -impl<'ast, T: Field> Id<'ast, T> for TypedExpressionList<'ast, T> { - fn identifier(_: Identifier<'ast>) -> Self::Inner { - unreachable!() - } -} - pub trait FunctionCall<'ast, T>: Expr<'ast, T> { fn function_call( key: DeclarationFunctionKey<'ast, T>, @@ -2432,18 +2338,6 @@ impl<'ast, T: Field> FunctionCall<'ast, T> for StructExpression<'ast, T> { } } -impl<'ast, T: Field> FunctionCall<'ast, T> for TypedExpressionList<'ast, T> { - fn function_call( - key: DeclarationFunctionKey<'ast, T>, - generics: Vec>>, - arguments: Vec>, - ) -> Self::Inner { - TypedExpressionListInner::FunctionCall(FunctionCallExpression::new( - key, generics, arguments, - )) - } -} - pub trait Block<'ast, T> { fn block(statements: Vec>, value: Self) -> Self; } @@ -2471,7 +2365,7 @@ impl<'ast, T: Field> Block<'ast, T> for ArrayExpression<'ast, T> { fn block(statements: Vec>, value: Self) -> Self { let array_ty = value.ty().clone(); ArrayExpressionInner::Block(BlockExpression::new(statements, value)) - .annotate(*array_ty.ty, array_ty.size) + .annotate(*array_ty.ty, *array_ty.size) } } @@ -2592,7 +2486,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> { .collect::>() .into(), ) - .annotate(*array_ty.ty, array_ty.size), + .annotate(*array_ty.ty, *array_ty.size), ArrayExpressionInner::Slice(box a, box from, box to) => { let from = match from.into_inner() { UExpressionInner::Value(from) => from as usize, @@ -2618,7 +2512,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> { .collect::>() .into(), ) - .annotate(*array_ty.ty, array_ty.size) + .annotate(*array_ty.ty, *array_ty.size) } ArrayExpressionInner::Repeat(box e, box count) => { let count = match count.into_inner() { @@ -2631,7 +2525,7 @@ impl<'ast, T: Field> Constant for ArrayExpression<'ast, T> { ArrayExpressionInner::Value( vec![TypedExpressionOrSpread::Expression(e); count].into(), ) - .annotate(*array_ty.ty, array_ty.size) + .annotate(*array_ty.ty, *array_ty.size) } _ => unreachable!(), } diff --git a/zokrates_core/src/typed_absy/result_folder.rs b/zokrates_core/src/typed_absy/result_folder.rs index 999de227..c359509c 100644 --- a/zokrates_core/src/typed_absy/result_folder.rs +++ b/zokrates_core/src/typed_absy/result_folder.rs @@ -194,10 +194,6 @@ pub trait ResultFolder<'ast, T: Field>: Sized { } } - fn fold_types(&mut self, tys: Types<'ast, T>) -> Result, Self::Error> { - fold_types(self, tys) - } - fn fold_conditional_expression< E: Expr<'ast, T> + PartialEq + Conditional<'ast, T> + ResultFold<'ast, T>, >( @@ -273,7 +269,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized { ) -> Result, Self::Error> { Ok(ArrayType { ty: box self.fold_type(*t.ty)?, - size: self.fold_uint_expression(t.size)?, + size: box self.fold_uint_expression(*t.size)?, }) } @@ -322,6 +318,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized { match t { Array(array_type) => Ok(Array(self.fold_declaration_array_type(array_type)?)), Struct(struct_type) => Ok(Struct(self.fold_declaration_struct_type(struct_type)?)), + Tuple(tuple_type) => Ok(Tuple(self.fold_declaration_tuple_type(tuple_type)?)), t => Ok(t), } } @@ -332,7 +329,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized { ) -> Result, Self::Error> { Ok(DeclarationArrayType { ty: box self.fold_declaration_type(*t.ty)?, - size: self.fold_declaration_constant(t.size)?, + size: box self.fold_declaration_constant(*t.size)?, }) } @@ -386,6 +383,13 @@ pub trait ResultFolder<'ast, T: Field>: Sized { fold_statement(self, s) } + fn fold_embed_call( + &mut self, + e: EmbedCall<'ast, T>, + ) -> Result, Self::Error> { + fold_embed_call(self, e) + } + fn fold_expression_or_spread( &mut self, e: TypedExpressionOrSpread<'ast, T>, @@ -413,15 +417,7 @@ pub trait ResultFolder<'ast, T: Field>: Sized { &mut self, e: TypedExpression<'ast, T>, ) -> Result, Self::Error> { - match e { - TypedExpression::FieldElement(e) => Ok(self.fold_field_expression(e)?.into()), - TypedExpression::Boolean(e) => Ok(self.fold_boolean_expression(e)?.into()), - TypedExpression::Uint(e) => Ok(self.fold_uint_expression(e)?.into()), - TypedExpression::Array(e) => Ok(self.fold_array_expression(e)?.into()), - TypedExpression::Struct(e) => Ok(self.fold_struct_expression(e)?.into()), - TypedExpression::Tuple(e) => Ok(self.fold_tuple_expression(e)?.into()), - TypedExpression::Int(e) => Ok(self.fold_int_expression(e)?.into()), - } + fold_expression(self, e) } fn fold_array_expression( @@ -445,21 +441,6 @@ pub trait ResultFolder<'ast, T: Field>: Sized { fold_tuple_expression(self, e) } - fn fold_expression_list_inner( - &mut self, - tys: &Types<'ast, T>, - es: TypedExpressionListInner<'ast, T>, - ) -> Result, Self::Error> { - fold_expression_list_inner(self, tys, es) - } - - fn fold_expression_list( - &mut self, - es: TypedExpressionList<'ast, T>, - ) -> Result, Self::Error> { - fold_expression_list(self, es) - } - fn fold_int_expression( &mut self, e: IntExpression<'ast, T>, @@ -523,12 +504,7 @@ pub fn fold_statement<'ast, T: Field, F: ResultFolder<'ast, T>>( s: TypedStatement<'ast, T>, ) -> Result>, F::Error> { let res = match s { - TypedStatement::Return(expressions) => TypedStatement::Return( - expressions - .into_iter() - .map(|e| f.fold_expression(e)) - .collect::>()?, - ), + TypedStatement::Return(e) => TypedStatement::Return(f.fold_expression(e)?), TypedStatement::Definition(a, e) => { TypedStatement::Definition(f.fold_assignee(a)?, f.fold_expression(e)?) } @@ -548,18 +524,31 @@ pub fn fold_statement<'ast, T: Field, F: ResultFolder<'ast, T>>( .flatten() .collect(), ), - TypedStatement::MultipleDefinition(variables, elist) => TypedStatement::MultipleDefinition( - variables - .into_iter() - .map(|v| f.fold_assignee(v)) - .collect::>()?, - f.fold_expression_list(elist)?, - ), + TypedStatement::EmbedCallDefinition(assignee, embed_call) => { + TypedStatement::EmbedCallDefinition( + f.fold_assignee(assignee)?, + f.fold_embed_call(embed_call)?, + ) + } s => s, }; Ok(vec![res]) } +pub fn fold_embed_call<'ast, T: Field, F: ResultFolder<'ast, T>>( + f: &mut F, + e: EmbedCall<'ast, T>, +) -> Result, F::Error> { + Ok(EmbedCall { + arguments: e + .arguments + .into_iter() + .map(|s| f.fold_expression(s)) + .collect::, _>>()?, + ..e + }) +} + pub fn fold_array_expression_inner<'ast, T: Field, F: ResultFolder<'ast, T>>( f: &mut F, ty: &ArrayType<'ast, T>, @@ -1200,11 +1189,7 @@ pub fn fold_signature<'ast, T: Field, F: ResultFolder<'ast, T>>( .into_iter() .map(|o| f.fold_declaration_type(o)) .collect::>()?, - outputs: s - .outputs - .into_iter() - .map(|o| f.fold_declaration_type(o)) - .collect::>()?, + output: box f.fold_declaration_type(*s.output)?, }) } @@ -1223,6 +1208,21 @@ pub fn fold_declaration_constant<'ast, T: Field, F: ResultFolder<'ast, T>>( } } +pub fn fold_expression<'ast, T: Field, F: ResultFolder<'ast, T>>( + f: &mut F, + e: TypedExpression<'ast, T>, +) -> Result, F::Error> { + match e { + TypedExpression::FieldElement(e) => Ok(f.fold_field_expression(e)?.into()), + TypedExpression::Boolean(e) => Ok(f.fold_boolean_expression(e)?.into()), + TypedExpression::Uint(e) => Ok(f.fold_uint_expression(e)?.into()), + TypedExpression::Array(e) => Ok(f.fold_array_expression(e)?.into()), + TypedExpression::Struct(e) => Ok(f.fold_struct_expression(e)?.into()), + TypedExpression::Tuple(e) => Ok(f.fold_tuple_expression(e)?.into()), + TypedExpression::Int(e) => Ok(f.fold_int_expression(e)?.into()), + } +} + pub fn fold_array_expression<'ast, T: Field, F: ResultFolder<'ast, T>>( f: &mut F, e: ArrayExpression<'ast, T>, @@ -1235,58 +1235,6 @@ pub fn fold_array_expression<'ast, T: Field, F: ResultFolder<'ast, T>>( }) } -pub fn fold_expression_list<'ast, T: Field, F: ResultFolder<'ast, T>>( - f: &mut F, - es: TypedExpressionList<'ast, T>, -) -> Result, F::Error> { - let types = f.fold_types(es.types)?; - - Ok(TypedExpressionList { - inner: f.fold_expression_list_inner(&types, es.inner)?, - types, - }) -} - -pub fn fold_types<'ast, T: Field, F: ResultFolder<'ast, T>>( - f: &mut F, - tys: Types<'ast, T>, -) -> Result, F::Error> { - Ok(Types { - inner: tys - .inner - .into_iter() - .map(|t| f.fold_type(t)) - .collect::>()?, - }) -} - -pub fn fold_expression_list_inner<'ast, T: Field, F: ResultFolder<'ast, T>>( - f: &mut F, - tys: &Types<'ast, T>, - es: TypedExpressionListInner<'ast, T>, -) -> Result, F::Error> { - match es { - TypedExpressionListInner::FunctionCall(function_call) => { - match f.fold_function_call_expression(tys, function_call)? { - FunctionCallOrExpression::FunctionCall(function_call) => { - Ok(TypedExpressionListInner::FunctionCall(function_call)) - } - FunctionCallOrExpression::Expression(list) => Ok(list), - } - } - TypedExpressionListInner::EmbedCall(embed, generics, arguments) => { - Ok(TypedExpressionListInner::EmbedCall( - embed, - generics, - arguments - .into_iter() - .map(|a| f.fold_expression(a)) - .collect::>()?, - )) - } - } -} - pub fn fold_struct_expression<'ast, T: Field, F: ResultFolder<'ast, T>>( f: &mut F, e: StructExpression<'ast, T>, diff --git a/zokrates_core/src/typed_absy/types.rs b/zokrates_core/src/typed_absy/types.rs index f817c65f..4bad5960 100644 --- a/zokrates_core/src/typed_absy/types.rs +++ b/zokrates_core/src/typed_absy/types.rs @@ -8,62 +8,37 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::path::{Path, PathBuf}; -pub trait IntoTypes<'ast, T> { - fn into_types(self) -> Types<'ast, T>; +pub trait IntoType<'ast, T> { + fn into_type(self) -> Type<'ast, T>; } -impl<'ast, T> IntoTypes<'ast, T> for Type<'ast, T> { - fn into_types(self) -> Types<'ast, T> { - Types { inner: vec![self] } - } -} - -impl<'ast, T> IntoTypes<'ast, T> for StructType<'ast, T> { - fn into_types(self) -> Types<'ast, T> { - Types { - inner: vec![Type::Struct(self)], - } - } -} - -impl<'ast, T> IntoTypes<'ast, T> for ArrayType<'ast, T> { - fn into_types(self) -> Types<'ast, T> { - Types { - inner: vec![Type::Array(self)], - } - } -} - -impl<'ast, T> IntoTypes<'ast, T> for TupleType<'ast, T> { - fn into_types(self) -> Types<'ast, T> { - Types { - inner: vec![Type::Tuple(self)], - } - } -} - -impl<'ast, T> IntoTypes<'ast, T> for UBitwidth { - fn into_types(self) -> Types<'ast, T> { - Types { - inner: vec![Type::Uint(self)], - } - } -} - -impl<'ast, T> IntoTypes<'ast, T> for Types<'ast, T> { - fn into_types(self) -> Types<'ast, T> { +impl<'ast, T> IntoType<'ast, T> for Type<'ast, T> { + fn into_type(self) -> Type<'ast, T> { self } } -#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)] -pub struct Types<'ast, T> { - pub inner: Vec>, +impl<'ast, T> IntoType<'ast, T> for StructType<'ast, T> { + fn into_type(self) -> Type<'ast, T> { + Type::Struct(self) + } } -impl<'ast, T> Types<'ast, T> { - pub fn new(types: Vec>) -> Self { - Self { inner: types } +impl<'ast, T> IntoType<'ast, T> for ArrayType<'ast, T> { + fn into_type(self) -> Type<'ast, T> { + Type::Array(self) + } +} + +impl<'ast, T> IntoType<'ast, T> for TupleType<'ast, T> { + fn into_type(self) -> Type<'ast, T> { + Type::Tuple(self) + } +} + +impl<'ast, T> IntoType<'ast, T> for UBitwidth { + fn into_type(self) -> Type<'ast, T> { + Type::Uint(self) } } @@ -337,7 +312,7 @@ impl<'ast, T> From for StructMember<'ast, T> { #[derive(Clone, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord, Debug)] pub struct GArrayType { - pub size: S, + pub size: Box, #[serde(flatten)] pub ty: Box>, } @@ -348,7 +323,7 @@ pub type ArrayType<'ast, T> = GArrayType>; impl<'ast, S, R: PartialEq> PartialEq> for GArrayType { fn eq(&self, other: &GArrayType) -> bool { - *self.ty == *other.ty && self.size == other.size + *self.ty == *other.ty && *self.size == *other.size } } @@ -382,7 +357,7 @@ fn try_from_g_array_type, U>( t: GArrayType, ) -> Result, SpecializationError> { Ok(GArrayType { - size: t.size.try_into().map_err(|_| SpecializationError)?, + size: box (*t.size).try_into().map_err(|_| SpecializationError)?, ty: box try_from_g_type(*t.ty)?, }) } @@ -830,7 +805,7 @@ impl> From<(GType, U)> for GArrayType { fn from(tup: (GType, U)) -> Self { GArrayType { ty: box tup.0, - size: tup.1.into(), + size: box tup.1.into(), } } } @@ -838,8 +813,8 @@ impl> From<(GType, U)> for GArrayType { impl GArrayType { pub fn new>(ty: GType, size: U) -> Self { GArrayType { - ty: Box::new(ty), - size: size.into(), + ty: box ty, + size: box size.into(), } } } @@ -922,7 +897,7 @@ impl<'ast, T: fmt::Display + PartialEq + fmt::Debug> Type<'ast, T> { (Array(l), Array(r)) => match l.ty.can_be_specialized_to(&r.ty) { true => { // check the size if types match - match (&l.size.as_inner(), &r.size) { + match (&l.size.as_inner(), &*r.size) { // compare the sizes for concrete ones (UExpressionInner::Value(v), DeclarationConstant::Concrete(c)) => { (*v as u32) == *c @@ -953,7 +928,7 @@ impl ConcreteType { GType::Boolean => 1, GType::Uint(_) => 1, GType::Array(array_type) => { - array_type.size as usize * array_type.ty.get_primitive_count() + *array_type.size as usize * array_type.ty.get_primitive_count() } GType::Tuple(tuple_type) => tuple_type .elements @@ -1123,7 +1098,7 @@ pub fn check_type<'ast, T, S: Clone + PartialEq + PartialEq>( (DeclarationType::Array(t0), GType::Array(t1)) => { // both the inner type and the size must match check_type(&t0.ty, &t1.ty, constants) - && check_generic(&t0.size, Some(&t1.size), constants) + && check_generic(&*t0.size, Some(&*t1.size), constants) } (DeclarationType::FieldElement, GType::FieldElement) | (DeclarationType::Boolean, GType::Boolean) => true, @@ -1164,7 +1139,7 @@ impl<'ast, T> From> for DeclarationConstant<'a pub fn specialize_declaration_type< 'ast, T: Clone, - S: Clone + PartialEq + From + fmt::Debug + From>, + S: Clone + PartialEq + From + From>, >( decl_ty: DeclarationType<'ast, T>, generics: &GGenericsAssignment<'ast, S>, @@ -1172,10 +1147,10 @@ pub fn specialize_declaration_type< Ok(match decl_ty { DeclarationType::Int => unreachable!(), DeclarationType::Array(t0) => { - let ty = box specialize_declaration_type(*t0.ty, generics)?; + let ty = specialize_declaration_type(*t0.ty, generics)?; let size = t0.size.map(generics)?; - GType::Array(GArrayType { size, ty }) + GType::Array(GArrayType::new(ty, size)) } DeclarationType::Tuple(t0) => { let elements = t0 @@ -1244,12 +1219,22 @@ pub mod signature { pub struct GSignature { pub generics: Vec>, pub inputs: Vec>, - pub outputs: Vec>, + pub output: Box>, + } + + impl Default for GSignature { + fn default() -> Self { + Self { + generics: vec![], + inputs: vec![], + output: box GType::Tuple(GTupleType::new(vec![])), + } + } } impl PartialEq for GSignature { fn eq(&self, other: &Self) -> bool { - self.inputs == other.inputs && self.outputs == other.outputs + self.inputs == other.inputs && self.output == other.output } } @@ -1257,7 +1242,7 @@ pub mod signature { fn partial_cmp(&self, other: &Self) -> Option { self.inputs .partial_cmp(&other.inputs) - .map(|c| self.outputs.partial_cmp(&other.outputs).map(|d| c.then(d))) + .map(|c| self.output.partial_cmp(&other.output).map(|d| c.then(d))) .unwrap() } } @@ -1271,17 +1256,7 @@ pub mod signature { impl Hash for GSignature { fn hash(&self, state: &mut H) { self.inputs.hash(state); - self.outputs.hash(state); - } - } - - impl Default for GSignature { - fn default() -> Self { - GSignature { - generics: vec![], - inputs: vec![], - outputs: vec![], - } + self.output.hash(state); } } @@ -1297,13 +1272,13 @@ pub mod signature { other .inputs .iter() - .chain(other.outputs.iter()) - .zip(self.inputs.iter().chain(self.outputs.iter())) + .chain(std::iter::once(&*other.output)) + .zip(self.inputs.iter().chain(std::iter::once(&*self.output))) .all(|(decl_ty, ty)| check_type::(decl_ty, ty, &mut constants)) } } - impl<'ast, T: Clone + PartialEq + fmt::Debug> DeclarationSignature<'ast, T> { + impl<'ast, T: Clone + PartialEq> DeclarationSignature<'ast, T> { pub fn specialize( &self, values: Vec>, @@ -1312,9 +1287,8 @@ pub mod signature { // we keep track of the value of constants in a map, as a given constant can only have one value let mut constants = ConcreteGenericsAssignment::default(); - assert_eq!(self.inputs.len(), signature.inputs.len()); - assert_eq!(self.outputs.len(), signature.outputs.len()); assert_eq!(self.generics.len(), values.len()); + assert_eq!(self.inputs.len(), signature.inputs.len()); let decl_generics = self.generics.iter().map(|g| match g.clone().unwrap() { DeclarationConstant::Generic(g) => g, @@ -1330,8 +1304,13 @@ pub mod signature { let condition = self .inputs .iter() - .chain(self.outputs.iter()) - .zip(signature.inputs.iter().chain(signature.outputs.iter())) + .chain(std::iter::once(&*self.output)) + .zip( + signature + .inputs + .iter() + .chain(std::iter::once(&*signature.output)), + ) .all(|(decl_ty, ty)| check_type(decl_ty, ty, &mut constants)); if constants.0.len() != self.generics.len() { @@ -1344,11 +1323,11 @@ pub mod signature { } } - pub fn get_output_types( + pub fn get_output_type( &self, generics: Vec>>, inputs: Vec>, - ) -> Result>, GenericIdentifier<'ast>> { + ) -> Result, GenericIdentifier<'ast>> { // we keep track of the value of constants in a map, as a given constant can only have one value let mut constants = GenericsAssignment::default(); @@ -1375,12 +1354,8 @@ pub mod signature { .zip(inputs.iter()) .all(|(decl_ty, ty)| check_type(decl_ty, ty, &mut constants)); - // get the outputs from the map - self.outputs - .clone() - .into_iter() - .map(|t| specialize_declaration_type(t, &constants)) - .collect::>() + // get the specialized output + specialize_declaration_type(*self.output.clone(), &constants) } } @@ -1401,11 +1376,7 @@ pub mod signature { .into_iter() .map(try_from_g_type) .collect::>()?, - outputs: t - .outputs - .into_iter() - .map(try_from_g_type) - .collect::>()?, + output: box try_from_g_type(*t.output)?, }) } @@ -1453,21 +1424,7 @@ pub mod signature { write!(f, ", ")?; } } - write!(f, ")")?; - match self.outputs.len() { - 0 => write!(f, ""), - 1 => write!(f, " -> {}", self.outputs[0]), - _ => { - write!(f, " -> (")?; - for (i, t) in self.outputs.iter().enumerate() { - write!(f, "{}", t)?; - if i < self.outputs.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, ")") - } - } + write!(f, ") -> {}", self.output) } } @@ -1486,8 +1443,8 @@ pub mod signature { self } - pub fn outputs(mut self, outputs: Vec>) -> Self { - self.outputs = outputs; + pub fn output(mut self, output: GType) -> Self { + self.output = Box::new(output); self } } @@ -1501,7 +1458,7 @@ pub mod signature { fn signature() { let s = ConcreteSignature::new() .inputs(vec![ConcreteType::FieldElement, ConcreteType::Boolean]) - .outputs(vec![ConcreteType::Boolean]); + .output(ConcreteType::Boolean); assert_eq!(s.to_string(), String::from("(field, bool) -> bool")); } diff --git a/zokrates_core/src/zir/from_typed.rs b/zokrates_core/src/zir/from_typed.rs index 3b5b9384..24f1b6ea 100644 --- a/zokrates_core/src/zir/from_typed.rs +++ b/zokrates_core/src/zir/from_typed.rs @@ -5,7 +5,7 @@ impl From for zir::types::Signature { fn from(s: typed_absy::types::ConcreteSignature) -> zir::types::Signature { zir::types::Signature { inputs: s.inputs.into_iter().flat_map(from_type).collect(), - outputs: s.outputs.into_iter().flat_map(from_type).collect(), + outputs: from_type(*s.output), } } } @@ -20,7 +20,7 @@ fn from_type(t: typed_absy::types::ConcreteType) -> Vec { } typed_absy::types::ConcreteType::Array(array_type) => { let inner = from_type(*array_type.ty); - (0..array_type.size).flat_map(|_| inner.clone()).collect() + (0..*array_type.size).flat_map(|_| inner.clone()).collect() } typed_absy::types::ConcreteType::Struct(members) => members .into_iter() diff --git a/zokrates_core_test/tests/tests/arrays/fun_spread.zok b/zokrates_core_test/tests/tests/arrays/fun_spread.zok index ac44579e..7a2ccd90 100644 --- a/zokrates_core_test/tests/tests/arrays/fun_spread.zok +++ b/zokrates_core_test/tests/tests/arrays/fun_spread.zok @@ -1,6 +1,6 @@ import "utils/pack/bool/nonStrictUnpack256.zok" as unpack256; -def main(field[2] inputs) -> (bool[512]) { +def main(field[2] inputs) -> bool[512] { bool[512] preimage512 = [...unpack256(inputs[0]), ...unpack256(inputs[1])]; return preimage512; } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/arrays/identity.zok b/zokrates_core_test/tests/tests/arrays/identity.zok index fb48f34a..125d0732 100644 --- a/zokrates_core_test/tests/tests/arrays/identity.zok +++ b/zokrates_core_test/tests/tests/arrays/identity.zok @@ -1,3 +1,3 @@ -def main(bool[3] a) -> (bool[3]) { +def main(bool[3] a) -> bool[3] { return a; } diff --git a/zokrates_core_test/tests/tests/assert_array_equality.json b/zokrates_core_test/tests/tests/assert_array_equality.json index 108ea801..edb9d1f7 100644 --- a/zokrates_core_test/tests/tests/assert_array_equality.json +++ b/zokrates_core_test/tests/tests/assert_array_equality.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }, diff --git a/zokrates_core_test/tests/tests/complex_call.json b/zokrates_core_test/tests/tests/complex_call.json index 467b0ef9..688a0bba 100644 --- a/zokrates_core_test/tests/tests/complex_call.json +++ b/zokrates_core_test/tests/tests/complex_call.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [{"a": [true, true], "b": "3"}, "4"] + "values": [[{"a": [true, true], "b": "3"}, "4"]] } } } diff --git a/zokrates_core_test/tests/tests/complex_call.zok b/zokrates_core_test/tests/tests/complex_call.zok index 7461b0d8..ae45a6e8 100644 --- a/zokrates_core_test/tests/tests/complex_call.zok +++ b/zokrates_core_test/tests/tests/complex_call.zok @@ -4,10 +4,10 @@ struct Foo { } def f(bool a, field b, Foo c, field[2] d) -> (Foo, field) { - return Foo { a: [a, a], b: d[0] }, c.a[0] ? b + c.b : d[1]; + return (Foo { a: [a, a], b: d[0] }, c.a[0] ? b + c.b : d[1]); } def main(bool a, field b, Foo c, field[2] d) -> (Foo, field) { - Foo e, field f = f(a, b, c, d); - return e, f; + (Foo, field) r = f(a, b, c, d); + return r; } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/generics/cache.json b/zokrates_core_test/tests/tests/generics/cache.json index 749eefef..20652ea5 100644 --- a/zokrates_core_test/tests/tests/generics/cache.json +++ b/zokrates_core_test/tests/tests/generics/cache.json @@ -3,13 +3,11 @@ "tests": [ { "input": { - "values": [ - ] + "values": [] }, "output": { "Ok": { - "values": [ - ] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/memoize/memoize.json b/zokrates_core_test/tests/tests/memoize/memoize.json index 3cc57aaf..7cab2891 100644 --- a/zokrates_core_test/tests/tests/memoize/memoize.json +++ b/zokrates_core_test/tests/tests/memoize/memoize.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/memoize/no_array_memoization.json b/zokrates_core_test/tests/tests/memoize/no_array_memoization.json index d8f7a9d3..6a3c45a5 100644 --- a/zokrates_core_test/tests/tests/memoize/no_array_memoization.json +++ b/zokrates_core_test/tests/tests/memoize/no_array_memoization.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/native_le.json b/zokrates_core_test/tests/tests/native_le.json index b504c5fe..e73e0124 100644 --- a/zokrates_core_test/tests/tests/native_le.json +++ b/zokrates_core_test/tests/tests/native_le.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [true, true] + "values": [[true, true]] } } }, @@ -18,7 +18,7 @@ }, "output": { "Ok": { - "values": [true, true] + "values": [[true, true]] } } }, @@ -28,7 +28,7 @@ }, "output": { "Ok": { - "values": [true, true] + "values": [[true, true]] } } }, @@ -38,7 +38,7 @@ }, "output": { "Ok": { - "values": [true, true] + "values": [[true, true]] } } }, @@ -48,7 +48,7 @@ }, "output": { "Ok": { - "values": [true, true] + "values": [[true, true]] } } }, @@ -58,7 +58,7 @@ }, "output": { "Ok": { - "values": [false, false] + "values": [[false, false]] } } }, @@ -68,7 +68,7 @@ }, "output": { "Ok": { - "values": [false, false] + "values": [[false, false]] } } }, @@ -78,7 +78,7 @@ }, "output": { "Ok": { - "values": [false, false] + "values": [[false, false]] } } } diff --git a/zokrates_core_test/tests/tests/native_le.zok b/zokrates_core_test/tests/tests/native_le.zok index 536e0579..5f5a90c2 100644 --- a/zokrates_core_test/tests/tests/native_le.zok +++ b/zokrates_core_test/tests/tests/native_le.zok @@ -41,5 +41,5 @@ def main(field a, u32 b) -> (bool, bool) { field c = 42; u32 d = 42; - return le::(a, c), le(b, d); + return (le::(a, c), le(b, d)); } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/neg_pos.json b/zokrates_core_test/tests/tests/neg_pos.json index 07b74515..a3dd812b 100644 --- a/zokrates_core_test/tests/tests/neg_pos.json +++ b/zokrates_core_test/tests/tests/neg_pos.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [["21888242871839275222246405745257275088548364400416034343698204186575808495615", "21888242871839275222246405745257275088548364400416034343698204186575808495616", "21888242871839275222246405745257275088548364400416034343698204186575808495616", "21888242871839275222246405745257275088548364400416034343698204186575808495616"], ["0xfe", "0xff", "0xff", "0xff"]] + "values": [[["21888242871839275222246405745257275088548364400416034343698204186575808495615", "21888242871839275222246405745257275088548364400416034343698204186575808495616", "21888242871839275222246405745257275088548364400416034343698204186575808495616", "21888242871839275222246405745257275088548364400416034343698204186575808495616"], ["0xfe", "0xff", "0xff", "0xff"]]] } } } diff --git a/zokrates_core_test/tests/tests/neg_pos.zok b/zokrates_core_test/tests/tests/neg_pos.zok index b399006d..decc6c27 100644 --- a/zokrates_core_test/tests/tests/neg_pos.zok +++ b/zokrates_core_test/tests/tests/neg_pos.zok @@ -12,5 +12,5 @@ def main(field x, field y, u8 z, u8 t) -> (field[4], u8[4]) { assert(-0x00 == 0x00); assert(-0f == 0); - return [a, b, c, d], [e, f, g, h]; + return ([a, b, c, d], [e, f, g, h]); } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/nested_loop.json b/zokrates_core_test/tests/tests/nested_loop.json index a771a908..cd7a8035 100644 --- a/zokrates_core_test/tests/tests/nested_loop.json +++ b/zokrates_core_test/tests/tests/nested_loop.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": ["4838400", "10", "25"] + "values": [["4838400", "10", "25"]] } } }, @@ -17,7 +17,7 @@ }, "output": { "Ok": { - "values": ["0", "10", "25"] + "values": [["0", "10", "25"]] } } } diff --git a/zokrates_core_test/tests/tests/nested_loop.zok b/zokrates_core_test/tests/tests/nested_loop.zok index 18837208..24f40fff 100644 --- a/zokrates_core_test/tests/tests/nested_loop.zok +++ b/zokrates_core_test/tests/tests/nested_loop.zok @@ -24,5 +24,5 @@ def main(field[4] values) -> (field, field, field) { } } - return res0, res1, res2; + return (res0, res1, res2); } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/panics/loop_bound.json b/zokrates_core_test/tests/tests/panics/loop_bound.json index abed4b29..91dced87 100644 --- a/zokrates_core_test/tests/tests/panics/loop_bound.json +++ b/zokrates_core_test/tests/tests/panics/loop_bound.json @@ -28,7 +28,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/panics/panic_isolation.json b/zokrates_core_test/tests/tests/panics/panic_isolation.json index 58b9fbd9..70c0bff9 100644 --- a/zokrates_core_test/tests/tests/panics/panic_isolation.json +++ b/zokrates_core_test/tests/tests/panics/panic_isolation.json @@ -7,12 +7,7 @@ "tests": [ { "input": { - "values": [ - true, - ["42", - "42"], - "0" - ] + "values": [true, ["42", "42"], "0"] }, "output": { "Err": { @@ -28,41 +23,21 @@ }, { "input": { - "values": [ - true, - ["1", - "1"], - "1" - ] + "values": [true, ["1", "1"], "1"] }, "output": { "Ok": { - "values": [ - true, - ["1", - "1"], - "1" - ] + "values": [[true, ["1", "1"], "1"]] } } }, { "input": { - "values": [ - false, - ["2", - "2"], - "0" - ] + "values": [false, ["2", "2"], "0"] }, "output": { "Ok": { - "values": [ - false, - ["2", - "2"], - "0" - ] + "values": [[false, ["2", "2"], "0"]] } } } diff --git a/zokrates_core_test/tests/tests/panics/panic_isolation.zok b/zokrates_core_test/tests/tests/panics/panic_isolation.zok index 7faf8f26..276bcc58 100644 --- a/zokrates_core_test/tests/tests/panics/panic_isolation.zok +++ b/zokrates_core_test/tests/tests/panics/panic_isolation.zok @@ -32,7 +32,7 @@ def main(bool condition, field[2] a, field x) -> (bool, field[2], field) { // first branch asserts that `condition` is true, second branch asserts that `condition` is false. This should never throw. // first branch asserts that all elements in `a` are 1, 2 in the second branch. This should throw only if `a` is neither ones or zeroes // first branch asserts that `x` is zero and returns it, second branch asserts that `x` isn't 0 and returns its inverse (which internally generates a failing assert if x is 0). This should never throw - return condition ? yes(condition) : no(condition), \ + return (condition ? yes(condition) : no(condition), \ condition ? ones(a) : twos(a), \ - x == 0 ? zero(x) : inverse(x); + x == 0 ? zero(x) : inverse(x)); } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/panics/panic_no_isolation.json b/zokrates_core_test/tests/tests/panics/panic_no_isolation.json index a5c0732c..22a40897 100644 --- a/zokrates_core_test/tests/tests/panics/panic_no_isolation.json +++ b/zokrates_core_test/tests/tests/panics/panic_no_isolation.json @@ -7,12 +7,7 @@ "tests": [ { "input": { - "values": [ - true, - ["1", - "1"], - "1" - ] + "values": [true, ["1", "1"], "1"] }, "output": { "Err": { diff --git a/zokrates_core_test/tests/tests/pass_by_value.json b/zokrates_core_test/tests/tests/pass_by_value.json index e46bca88..2ee8eaa8 100644 --- a/zokrates_core_test/tests/tests/pass_by_value.json +++ b/zokrates_core_test/tests/tests/pass_by_value.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [["2"], ["1"], { "a": "2"}, {"a": "1"}, "2", "1"] + "values": [[["2"], ["1"], { "a": "2"}, {"a": "1"}, "2", "1"]] } } } diff --git a/zokrates_core_test/tests/tests/pass_by_value.zok b/zokrates_core_test/tests/tests/pass_by_value.zok index 8022fd03..2c3fad88 100644 --- a/zokrates_core_test/tests/tests/pass_by_value.zok +++ b/zokrates_core_test/tests/tests/pass_by_value.zok @@ -18,5 +18,5 @@ def mutate(field[1] f) -> field[1] { } def main(field[1] f, Foo g, field h) -> (field[1], field[1], Foo, Foo, field, field) { - return mutate(f), f, mutate(g), g, mutate(h), h; + return (mutate(f), f, mutate(g), g, mutate(h), h); } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/precedence.json b/zokrates_core_test/tests/tests/precedence.json index 9c2f0b0d..09e8a275 100644 --- a/zokrates_core_test/tests/tests/precedence.json +++ b/zokrates_core_test/tests/tests/precedence.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/range_check/assert_ge.json b/zokrates_core_test/tests/tests/range_check/assert_ge.json index 0569b4b3..110c0c94 100644 --- a/zokrates_core_test/tests/tests/range_check/assert_ge.json +++ b/zokrates_core_test/tests/tests/range_check/assert_ge.json @@ -37,7 +37,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }, @@ -47,7 +47,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/range_check/assert_gt.json b/zokrates_core_test/tests/tests/range_check/assert_gt.json index 631eca10..d760d302 100644 --- a/zokrates_core_test/tests/tests/range_check/assert_gt.json +++ b/zokrates_core_test/tests/tests/range_check/assert_gt.json @@ -51,7 +51,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/range_check/assert_gt_big_constant.json b/zokrates_core_test/tests/tests/range_check/assert_gt_big_constant.json index bcb6c603..521b84dc 100644 --- a/zokrates_core_test/tests/tests/range_check/assert_gt_big_constant.json +++ b/zokrates_core_test/tests/tests/range_check/assert_gt_big_constant.json @@ -37,7 +37,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/range_check/assert_le.json b/zokrates_core_test/tests/tests/range_check/assert_le.json index 76ebbdeb..dd202537 100644 --- a/zokrates_core_test/tests/tests/range_check/assert_le.json +++ b/zokrates_core_test/tests/tests/range_check/assert_le.json @@ -9,7 +9,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }, @@ -19,7 +19,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }, diff --git a/zokrates_core_test/tests/tests/range_check/assert_lt.json b/zokrates_core_test/tests/tests/range_check/assert_lt.json index 9bbf8aa7..86947b96 100644 --- a/zokrates_core_test/tests/tests/range_check/assert_lt.json +++ b/zokrates_core_test/tests/tests/range_check/assert_lt.json @@ -9,7 +9,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }, @@ -19,7 +19,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }, diff --git a/zokrates_core_test/tests/tests/range_check/assert_lt_big_constant.json b/zokrates_core_test/tests/tests/range_check/assert_lt_big_constant.json index 1a62c5a8..7b8c492b 100644 --- a/zokrates_core_test/tests/tests/range_check/assert_lt_big_constant.json +++ b/zokrates_core_test/tests/tests/range_check/assert_lt_big_constant.json @@ -9,7 +9,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }, @@ -19,7 +19,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }, diff --git a/zokrates_core_test/tests/tests/range_check/assert_lt_u8.json b/zokrates_core_test/tests/tests/range_check/assert_lt_u8.json index 341696c3..70ac881f 100644 --- a/zokrates_core_test/tests/tests/range_check/assert_lt_u8.json +++ b/zokrates_core_test/tests/tests/range_check/assert_lt_u8.json @@ -9,7 +9,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }, @@ -19,7 +19,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }, diff --git a/zokrates_core_test/tests/tests/spread_slice.zok b/zokrates_core_test/tests/tests/spread_slice.zok index e58ecc82..8d144461 100644 --- a/zokrates_core_test/tests/tests/spread_slice.zok +++ b/zokrates_core_test/tests/tests/spread_slice.zok @@ -1,3 +1,3 @@ -def main(field[3] a, field[3] b, field c) -> (field[9]) { +def main(field[3] a, field[3] b, field c) -> field[9] { return [...a[..2], ...b[1..], ...a[..], ...b[1..2], c]; } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/structs/constant.json b/zokrates_core_test/tests/tests/structs/constant.json index 2026e62d..8f835aa4 100644 --- a/zokrates_core_test/tests/tests/structs/constant.json +++ b/zokrates_core_test/tests/tests/structs/constant.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/structs/identity.zok b/zokrates_core_test/tests/tests/structs/identity.zok index 68a83acd..4ffc43ff 100644 --- a/zokrates_core_test/tests/tests/structs/identity.zok +++ b/zokrates_core_test/tests/tests/structs/identity.zok @@ -3,6 +3,6 @@ struct A { bool b; } -def main(A a) -> (A) { +def main(A a) -> A { return a; } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/structs/member_order.json b/zokrates_core_test/tests/tests/structs/member_order.json index e6aed584..67e1628a 100644 --- a/zokrates_core_test/tests/tests/structs/member_order.json +++ b/zokrates_core_test/tests/tests/structs/member_order.json @@ -12,7 +12,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/tuples/conditional.zok b/zokrates_core_test/tests/tests/tuples/conditional.zok index 5ada9311..2883d321 100644 --- a/zokrates_core_test/tests/tests/tuples/conditional.zok +++ b/zokrates_core_test/tests/tests/tuples/conditional.zok @@ -1,4 +1,4 @@ -def main(bool flag) -> ((field, field)) { +def main(bool flag) -> (field, field) { (field, field) a = flag ? (1f, 2f) : (2f, 1f); return a; } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/tuples/constant.json b/zokrates_core_test/tests/tests/tuples/constant.json index 25b4d618..7981c60e 100644 --- a/zokrates_core_test/tests/tests/tuples/constant.json +++ b/zokrates_core_test/tests/tests/tuples/constant.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/tuples/element_order.json b/zokrates_core_test/tests/tests/tuples/element_order.json index f9a97789..427bd300 100644 --- a/zokrates_core_test/tests/tests/tuples/element_order.json +++ b/zokrates_core_test/tests/tests/tuples/element_order.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/tuples/empty.zok b/zokrates_core_test/tests/tests/tuples/empty.zok index 8426e4d4..2b41e095 100644 --- a/zokrates_core_test/tests/tests/tuples/empty.zok +++ b/zokrates_core_test/tests/tests/tuples/empty.zok @@ -1,4 +1,4 @@ -def main(() a) -> (()) { +def main(() a) -> () { () b = (); assert(a == b); return a; diff --git a/zokrates_core_test/tests/tests/tuples/identity.zok b/zokrates_core_test/tests/tests/tuples/identity.zok index a78b07fa..1e4a119d 100644 --- a/zokrates_core_test/tests/tests/tuples/identity.zok +++ b/zokrates_core_test/tests/tests/tuples/identity.zok @@ -1,3 +1,3 @@ -def main((field, bool,) a) -> ((field, bool,)) { +def main((field, bool) a) -> (field, bool) { return a; } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/uint/from_to_bits.json b/zokrates_core_test/tests/tests/uint/from_to_bits.json index f1a60a2b..18dd9510 100644 --- a/zokrates_core_test/tests/tests/uint/from_to_bits.json +++ b/zokrates_core_test/tests/tests/uint/from_to_bits.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": ["0x0000000000000000", "0x00000000", "0x0000", "0x00"] + "values": [["0x0000000000000000", "0x00000000", "0x0000", "0x00"]] } } }, @@ -17,7 +17,7 @@ }, "output": { "Ok": { - "values": ["0xffffffffffffffff", "0xffffffff", "0xffff", "0xff"] + "values": [["0xffffffffffffffff", "0xffffffff", "0xffff", "0xff"]] } } }, @@ -27,7 +27,7 @@ }, "output": { "Ok": { - "values": ["0x1234567812345678", "0x12345678", "0x1234", "0x12"] + "values": [["0x1234567812345678", "0x12345678", "0x1234", "0x12"]] } } } diff --git a/zokrates_core_test/tests/tests/uint/from_to_bits.zok b/zokrates_core_test/tests/tests/uint/from_to_bits.zok index 4689d71d..79764ff2 100644 --- a/zokrates_core_test/tests/tests/uint/from_to_bits.zok +++ b/zokrates_core_test/tests/tests/uint/from_to_bits.zok @@ -12,5 +12,5 @@ def main(u64 d, u32 e, u16 f, u8 g) -> (u64, u32, u16, u8) { bool[32] e_bits = to_bits_32(e); bool[16] f_bits = to_bits_16(f); bool[8] g_bits = to_bits_8(g); - return from_bits_64(d_bits), from_bits_32(e_bits), from_bits_16(f_bits), from_bits_8(g_bits); + return (from_bits_64(d_bits), from_bits_32(e_bits), from_bits_16(f_bits), from_bits_8(g_bits)); } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/uint/operations.json b/zokrates_core_test/tests/tests/uint/operations.json index 1b8aaca9..fd017672 100644 --- a/zokrates_core_test/tests/tests/uint/operations.json +++ b/zokrates_core_test/tests/tests/uint/operations.json @@ -6,7 +6,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/uint/propagation/rotate.json b/zokrates_core_test/tests/tests/uint/propagation/rotate.json index b8c273c2..114bbfbe 100644 --- a/zokrates_core_test/tests/tests/uint/propagation/rotate.json +++ b/zokrates_core_test/tests/tests/uint/propagation/rotate.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_core_test/tests/tests/uint/u16/sub.json b/zokrates_core_test/tests/tests/uint/u16/sub.json index f13a0b38..703c0c92 100644 --- a/zokrates_core_test/tests/tests/uint/u16/sub.json +++ b/zokrates_core_test/tests/tests/uint/u16/sub.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": ["0xfffe", "0xfffe", "0x0002"] + "values": [["0xfffe", "0xfffe", "0x0002"]] } } }, @@ -18,7 +18,7 @@ }, "output": { "Ok": { - "values": ["0xffff", "0xffff", "0x0001"] + "values": [["0xffff", "0xffff", "0x0001"]] } } } diff --git a/zokrates_core_test/tests/tests/uint/u16/sub.zok b/zokrates_core_test/tests/tests/uint/u16/sub.zok index b3108091..759b22c8 100644 --- a/zokrates_core_test/tests/tests/uint/u16/sub.zok +++ b/zokrates_core_test/tests/tests/uint/u16/sub.zok @@ -1,3 +1,3 @@ def main(u16 a, u16 b) -> (u16, u16, u16) { - return a - b, a - 1, 1 - a; + return (a - b, a - 1, 1 - a); } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/uint/u32/sub.json b/zokrates_core_test/tests/tests/uint/u32/sub.json index 3187b91c..ac77b0c4 100644 --- a/zokrates_core_test/tests/tests/uint/u32/sub.json +++ b/zokrates_core_test/tests/tests/uint/u32/sub.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": ["0xfffffffe", "0xfffffffe", "0x00000002"] + "values": [["0xfffffffe", "0xfffffffe", "0x00000002"]] } } }, @@ -18,7 +18,7 @@ }, "output": { "Ok": { - "values": ["0xffffffff", "0xffffffff", "0x00000001"] + "values": [["0xffffffff", "0xffffffff", "0x00000001"]] } } } diff --git a/zokrates_core_test/tests/tests/uint/u32/sub.zok b/zokrates_core_test/tests/tests/uint/u32/sub.zok index 3d9b3b2d..2f7b873b 100644 --- a/zokrates_core_test/tests/tests/uint/u32/sub.zok +++ b/zokrates_core_test/tests/tests/uint/u32/sub.zok @@ -1,3 +1,3 @@ def main(u32 a, u32 b) -> (u32, u32, u32) { - return a - b, a - 1, 1 - a; + return (a - b, a - 1, 1 - a); } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/uint/u64/sub.json b/zokrates_core_test/tests/tests/uint/u64/sub.json index db2b037d..bbcbb362 100644 --- a/zokrates_core_test/tests/tests/uint/u64/sub.json +++ b/zokrates_core_test/tests/tests/uint/u64/sub.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": ["0xfffffffffffffffe", "0xfffffffffffffffe", "0x0000000000000002"] + "values": [["0xfffffffffffffffe", "0xfffffffffffffffe", "0x0000000000000002"]] } } }, @@ -18,7 +18,7 @@ }, "output": { "Ok": { - "values": ["0xffffffffffffffff", "0xffffffffffffffff", "0x0000000000000001"] + "values": [["0xffffffffffffffff", "0xffffffffffffffff", "0x0000000000000001"]] } } } diff --git a/zokrates_core_test/tests/tests/uint/u64/sub.zok b/zokrates_core_test/tests/tests/uint/u64/sub.zok index 5ff65bd5..55e5ca5e 100644 --- a/zokrates_core_test/tests/tests/uint/u64/sub.zok +++ b/zokrates_core_test/tests/tests/uint/u64/sub.zok @@ -1,3 +1,3 @@ def main(u64 a, u64 b) -> (u64, u64, u64) { - return a - b, a - 1, 1 - a; + return (a - b, a - 1, 1 - a); } \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/uint/u8/sub.json b/zokrates_core_test/tests/tests/uint/u8/sub.json index 1126982a..2ca50909 100644 --- a/zokrates_core_test/tests/tests/uint/u8/sub.json +++ b/zokrates_core_test/tests/tests/uint/u8/sub.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": ["0xfe", "0xfe", "0x02"] + "values": [["0xfe", "0xfe", "0x02"]] } } }, @@ -18,7 +18,7 @@ }, "output": { "Ok": { - "values": ["0xff", "0xff", "0x01"] + "values": [["0xff", "0xff", "0x01"]] } } } diff --git a/zokrates_core_test/tests/tests/uint/u8/sub.zok b/zokrates_core_test/tests/tests/uint/u8/sub.zok index 02a70621..d5a8a510 100644 --- a/zokrates_core_test/tests/tests/uint/u8/sub.zok +++ b/zokrates_core_test/tests/tests/uint/u8/sub.zok @@ -1,3 +1,3 @@ def main(u8 a, u8 b) -> (u8, u8, u8) { - return a - b, a - 1, 1 - a; + return (a - b, a - 1, 1 - a); } \ No newline at end of file diff --git a/zokrates_parser/src/zokrates.pest b/zokrates_parser/src/zokrates.pest index f2a64151..b8b2a51f 100644 --- a/zokrates_parser/src/zokrates.pest +++ b/zokrates_parser/src/zokrates.pest @@ -13,10 +13,9 @@ from_import_directive = { "from" ~ quoted_string ~ "import" ~ import_symbol_list main_import_directive = { "import" ~ quoted_string ~ ("as" ~ identifier)? } import_symbol = { identifier ~ ("as" ~ identifier)? } import_symbol_list = _{ import_symbol ~ ("," ~ import_symbol)* } -function_definition = {"def" ~ identifier ~ constant_generics_declaration? ~ "(" ~ parameter_list ~ ")" ~ return_types ~ block_statement } +function_definition = {"def" ~ identifier ~ constant_generics_declaration? ~ "(" ~ parameter_list ~ ")" ~ ("->" ~ ty)? ~ block_statement } const_definition = {"const" ~ typed_identifier ~ "=" ~ expression } type_definition = {"type" ~ identifier ~ constant_generics_declaration? ~ "=" ~ ty } -return_types = _{ ( "->" ~ ( "(" ~ ty_list ~ ")" | ty ))? } constant_generics_declaration = _{ "<" ~ constant_generics_list ~ ">" } constant_generics_list = _{ identifier ~ ("," ~ identifier)* } @@ -34,7 +33,6 @@ ty_basic = { ty_field | ty_bool | ty_u8 | ty_u16 | ty_u32 | ty_u64 } ty_basic_or_struct_or_tuple = { ty_basic | ty_struct | ty_tuple } ty_array = { ty_basic_or_struct_or_tuple ~ ("[" ~ expression ~ "]")+ } ty = { ty_array | ty_basic | ty_struct | ty_tuple } -ty_list = _{(ty ~ ("," ~ ty)*)?} // tuples ty_tuple = { "(" ~ (ty_tuple_multiple_inner | ty_tuple_single_inner | ty_tuple_empty_inner ) ~ ")" } ty_tuple_empty_inner = _{ "" } @@ -61,12 +59,11 @@ statement = { (iteration_statement // does not require semicolon block_statement = _{ "{" ~ NEWLINE* ~ statement* ~ NEWLINE* ~ "}" } iteration_statement = { "for" ~ typed_identifier ~ "in" ~ expression ~ ".." ~ expression ~ block_statement } -return_statement = { "return" ~ expression_list } -definition_statement = { typed_identifier_or_assignee_list ~ "=" ~ expression } // declare and assign, so only identifiers are allowed, unlike `assignment_statement` +return_statement = { "return" ~ expression? } +definition_statement = { typed_identifier_or_assignee ~ "=" ~ expression } assertion_statement = {"assert" ~ "(" ~ expression ~ ("," ~ quoted_string)? ~ ")"} -typed_identifier_or_assignee_list = _{ typed_identifier_or_assignee ~ ("," ~ typed_identifier_or_assignee)* } -typed_identifier_or_assignee = { typed_identifier | assignee } // we don't use { ty? ~ identifier } as with a single token, it gets parsed as `ty` but we want `identifier` +typed_identifier_or_assignee = { typed_identifier | assignee } // Expressions expression_list = _{(expression ~ ("," ~ expression)*)?} diff --git a/zokrates_pest_ast/src/lib.rs b/zokrates_pest_ast/src/lib.rs index ece94cb1..4aa5d7c2 100644 --- a/zokrates_pest_ast/src/lib.rs +++ b/zokrates_pest_ast/src/lib.rs @@ -175,7 +175,7 @@ mod ast { pub id: IdentifierExpression<'ast>, pub generics: Vec>, pub parameters: Vec>, - pub returns: Vec>, + pub return_type: Option>, pub statements: Vec>, #[pest_ast(outer())] pub span: Span<'ast>, @@ -368,7 +368,7 @@ mod ast { #[derive(Debug, FromPest, PartialEq, Clone)] #[pest_ast(rule(Rule::definition_statement))] pub struct DefinitionStatement<'ast> { - pub lhs: Vec>, + pub lhs: TypedIdentifierOrAssignee<'ast>, pub expression: Expression<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, @@ -406,7 +406,7 @@ mod ast { #[derive(Debug, FromPest, PartialEq, Clone)] #[pest_ast(rule(Rule::return_statement))] pub struct ReturnStatement<'ast> { - pub expressions: Vec>, + pub expression: Option>, #[pest_ast(outer())] pub span: Span<'ast>, } @@ -1119,7 +1119,7 @@ mod tests { let source = r#" import "foo"; - def main() -> (field) { + def main() -> field { return 1 + 1; } "#; @@ -1143,38 +1143,38 @@ mod tests { span: Span::new(source, 36, 40).unwrap() }, parameters: vec![], - returns: vec![Type::Basic(BasicType::Field(FieldType { - span: Span::new(source, 47, 52).unwrap() - }))], + return_type: Some(Type::Basic(BasicType::Field(FieldType { + span: Span::new(source, 46, 51).unwrap() + }))), statements: vec![Statement::Return(ReturnStatement { - expressions: vec![Expression::add( + expression: Some(Expression::add( Expression::Literal(LiteralExpression::DecimalLiteral( DecimalLiteralExpression { value: DecimalNumber { - span: Span::new(source, 75, 76).unwrap() + span: Span::new(source, 73, 74).unwrap() }, suffix: None, - span: Span::new(source, 75, 76).unwrap() + span: Span::new(source, 73, 74).unwrap() } )), Expression::Literal(LiteralExpression::DecimalLiteral( DecimalLiteralExpression { value: DecimalNumber { - span: Span::new(source, 79, 80).unwrap() + span: Span::new(source, 77, 78).unwrap() }, suffix: None, - span: Span::new(source, 79, 80).unwrap() + span: Span::new(source, 77, 78).unwrap() } )), - Span::new(source, 75, 80).unwrap() - )], - span: Span::new(source, 68, 80).unwrap(), + Span::new(source, 73, 78).unwrap() + )), + span: Span::new(source, 66, 78).unwrap(), })], - span: Span::new(source, 32, 91).unwrap(), + span: Span::new(source, 32, 89).unwrap(), }) ], eoi: EOI {}, - span: Span::new(source, 0, 92).unwrap() + span: Span::new(source, 0, 90).unwrap() }) ); } @@ -1184,7 +1184,7 @@ mod tests { let source = r#" import "foo"; - def main() -> (field) { + def main() -> field { return 1 + 2 * 3 ** 4; } "#; @@ -1208,18 +1208,18 @@ mod tests { span: Span::new(source, 36, 40).unwrap() }, parameters: vec![], - returns: vec![Type::Basic(BasicType::Field(FieldType { - span: Span::new(source, 47, 52).unwrap() - }))], + return_type: Some(Type::Basic(BasicType::Field(FieldType { + span: Span::new(source, 46, 51).unwrap() + }))), statements: vec![Statement::Return(ReturnStatement { - expressions: vec![Expression::add( + expression: Some(Expression::add( Expression::Literal(LiteralExpression::DecimalLiteral( DecimalLiteralExpression { suffix: None, value: DecimalNumber { - span: Span::new(source, 75, 76).unwrap() + span: Span::new(source, 73, 74).unwrap() }, - span: Span::new(source, 75, 76).unwrap() + span: Span::new(source, 73, 74).unwrap() } )), Expression::mul( @@ -1227,9 +1227,9 @@ mod tests { DecimalLiteralExpression { suffix: None, value: DecimalNumber { - span: Span::new(source, 79, 80).unwrap() + span: Span::new(source, 77, 78).unwrap() }, - span: Span::new(source, 79, 80).unwrap() + span: Span::new(source, 77, 78).unwrap() } )), Expression::pow( @@ -1237,33 +1237,33 @@ mod tests { DecimalLiteralExpression { suffix: None, value: DecimalNumber { - span: Span::new(source, 83, 84).unwrap() + span: Span::new(source, 81, 82).unwrap() }, - span: Span::new(source, 83, 84).unwrap() + span: Span::new(source, 81, 82).unwrap() } )), Expression::Literal(LiteralExpression::DecimalLiteral( DecimalLiteralExpression { suffix: None, value: DecimalNumber { - span: Span::new(source, 88, 89).unwrap() + span: Span::new(source, 86, 87).unwrap() }, - span: Span::new(source, 88, 89).unwrap() + span: Span::new(source, 86, 87).unwrap() } )), - Span::new(source, 83, 89).unwrap() + Span::new(source, 81, 87).unwrap() ), - Span::new(source, 79, 89).unwrap() + Span::new(source, 77, 87).unwrap() ), - Span::new(source, 75, 89).unwrap() - )], - span: Span::new(source, 68, 89).unwrap(), + Span::new(source, 73, 87).unwrap() + )), + span: Span::new(source, 66, 87).unwrap(), })], - span: Span::new(source, 32, 100).unwrap(), + span: Span::new(source, 32, 98).unwrap(), }) ], eoi: EOI {}, - span: Span::new(source, 0, 101).unwrap() + span: Span::new(source, 0, 99).unwrap() }) ); } @@ -1273,7 +1273,7 @@ mod tests { let source = r#" import "foo"; - def main() -> (field) { + def main() -> field { return 1 ? 2 : 3; } "#; @@ -1297,54 +1297,54 @@ mod tests { span: Span::new(source, 36, 40).unwrap() }, parameters: vec![], - returns: vec![Type::Basic(BasicType::Field(FieldType { - span: Span::new(source, 47, 52).unwrap() - }))], + return_type: Some(Type::Basic(BasicType::Field(FieldType { + span: Span::new(source, 46, 51).unwrap() + }))), statements: vec![Statement::Return(ReturnStatement { - expressions: vec![Expression::ternary( + expression: Some(Expression::ternary( Box::new(Expression::Literal(LiteralExpression::DecimalLiteral( DecimalLiteralExpression { suffix: None, value: DecimalNumber { - span: Span::new(source, 75, 76).unwrap() + span: Span::new(source, 73, 74).unwrap() }, - span: Span::new(source, 75, 76).unwrap() + span: Span::new(source, 73, 74).unwrap() } ))), Box::new(Expression::Literal(LiteralExpression::DecimalLiteral( DecimalLiteralExpression { suffix: None, value: DecimalNumber { - span: Span::new(source, 79, 80).unwrap() + span: Span::new(source, 77, 78).unwrap() }, - span: Span::new(source, 79, 80).unwrap() + span: Span::new(source, 77, 78).unwrap() } ))), Box::new(Expression::Literal(LiteralExpression::DecimalLiteral( DecimalLiteralExpression { suffix: None, value: DecimalNumber { - span: Span::new(source, 83, 84).unwrap() + span: Span::new(source, 81, 82).unwrap() }, - span: Span::new(source, 83, 84).unwrap() + span: Span::new(source, 81, 82).unwrap() } ))), - Span::new(source, 75, 84).unwrap() - )], - span: Span::new(source, 68, 84).unwrap(), + Span::new(source, 73, 82).unwrap() + )), + span: Span::new(source, 66, 82).unwrap(), })], - span: Span::new(source, 32, 95).unwrap(), + span: Span::new(source, 32, 93).unwrap(), }) ], eoi: EOI {}, - span: Span::new(source, 0, 96).unwrap() + span: Span::new(source, 0, 94).unwrap() }) ); } #[test] fn parentheses() { - let source = r#"def main() -> (field) { return (1); } + let source = r#"def main() -> field { return 1; } "#; assert_eq!( generate_ast(source), @@ -1357,120 +1357,25 @@ mod tests { span: Span::new(source, 4, 8).unwrap() }, parameters: vec![], - returns: vec![Type::Basic(BasicType::Field(FieldType { - span: Span::new(source, 15, 20).unwrap() - }))], + return_type: Some(Type::Basic(BasicType::Field(FieldType { + span: Span::new(source, 14, 19).unwrap() + }))), statements: vec![Statement::Return(ReturnStatement { - expressions: vec![Expression::Literal(LiteralExpression::DecimalLiteral( + expression: Some(Expression::Literal(LiteralExpression::DecimalLiteral( DecimalLiteralExpression { suffix: None, value: DecimalNumber { - span: Span::new(source, 32, 33).unwrap() + span: Span::new(source, 29, 30).unwrap() }, - span: Span::new(source, 32, 33).unwrap() + span: Span::new(source, 29, 30).unwrap() } - ))], - span: Span::new(source, 24, 34).unwrap(), + ))), + span: Span::new(source, 22, 30).unwrap(), })], - span: Span::new(source, 0, 37).unwrap(), + span: Span::new(source, 0, 33).unwrap(), })], eoi: EOI {}, - span: Span::new(source, 0, 38).unwrap() - }) - ); - } - - #[test] - fn multidef() { - let source = r#"def main() -> (field) { field a, b = foo(1, 2 + 3); } -"#; - assert_eq!( - generate_ast(source), - Ok(File { - pragma: None, - declarations: vec![SymbolDeclaration::Function(FunctionDefinition { - generics: vec![], - id: IdentifierExpression { - value: String::from("main"), - span: Span::new(source, 4, 8).unwrap() - }, - parameters: vec![], - returns: vec![Type::Basic(BasicType::Field(FieldType { - span: Span::new(source, 15, 20).unwrap() - }))], - statements: vec![Statement::Definition(DefinitionStatement { - lhs: vec![ - TypedIdentifierOrAssignee::TypedIdentifier(TypedIdentifier { - ty: Type::Basic(BasicType::Field(FieldType { - span: Span::new(source, 24, 29).unwrap() - })), - identifier: IdentifierExpression { - value: String::from("a"), - span: Span::new(source, 30, 31).unwrap(), - }, - span: Span::new(source, 24, 31).unwrap() - }), - TypedIdentifierOrAssignee::Assignee(Assignee { - id: IdentifierExpression { - value: String::from("b"), - span: Span::new(source, 33, 34).unwrap(), - }, - accesses: vec![], - span: Span::new(source, 33, 35).unwrap() - }), - ], - expression: Expression::Postfix(PostfixExpression { - base: Box::new(Expression::Identifier(IdentifierExpression { - value: String::from("foo"), - span: Span::new(source, 37, 40).unwrap() - })), - accesses: vec![Access::Call(CallAccess { - explicit_generics: None, - arguments: Arguments { - expressions: vec![ - Expression::Literal(LiteralExpression::DecimalLiteral( - DecimalLiteralExpression { - suffix: None, - value: DecimalNumber { - span: Span::new(source, 41, 42).unwrap() - }, - span: Span::new(source, 41, 42).unwrap() - } - )), - Expression::add( - Expression::Literal(LiteralExpression::DecimalLiteral( - DecimalLiteralExpression { - suffix: None, - value: DecimalNumber { - span: Span::new(source, 44, 45).unwrap() - }, - span: Span::new(source, 44, 45).unwrap() - } - )), - Expression::Literal(LiteralExpression::DecimalLiteral( - DecimalLiteralExpression { - suffix: None, - value: DecimalNumber { - span: Span::new(source, 48, 49).unwrap() - }, - span: Span::new(source, 48, 49).unwrap() - } - )), - Span::new(source, 44, 49).unwrap() - ), - ], - span: Span::new(source, 41, 49).unwrap() - }, - span: Span::new(source, 40, 50).unwrap() - })], - span: Span::new(source, 37, 50).unwrap(), - }), - span: Span::new(source, 24, 50).unwrap() - })], - span: Span::new(source, 0, 53).unwrap(), - })], - eoi: EOI {}, - span: Span::new(source, 0, 54).unwrap() + span: Span::new(source, 0, 34).unwrap() }) ); } @@ -1485,18 +1390,17 @@ mod tests { Bar bar; } - def main

(private field[Q] a) -> (bool[234 + 6]) { + def main

(private field[Q] a) -> bool[234 + 6] { field a = 1; a[32 + x][55] = foo::(y); for field i in 0..3 { - assert(a == 1 + 2 + 3+ 4+ 5+ 6+ 6+ 7+ 8 + 4+ 5+ 3+ 4+ 2+ 3); + assert(a == 1 + 2 + 3 + 4 + 5 + 6 + 6 + 7 + 8 + 4 + 5 + 3 + 4 + 2 + 3); } assert(a.member == 1); return a; } "#; let res = generate_ast(source); - println!("{:#?}", generate_ast(source)); assert!(res.is_ok()); } @@ -1506,8 +1410,8 @@ mod tests { field a; } - def foo() -> ((field, field)) { - return 1, (1, 2); + def foo() -> (field, field) { + return (1, 2); } def main((field, field) a, (field,) b) -> (Foo,)[2] { @@ -1516,7 +1420,6 @@ mod tests { } "#; let res = generate_ast(source); - println!("{:#?}", generate_ast(source)); assert!(res.is_ok()); } } diff --git a/zokrates_stdlib/stdlib/field.zok b/zokrates_stdlib/stdlib/field.zok index d593f3a4..6a33cce5 100644 --- a/zokrates_stdlib/stdlib/field.zok +++ b/zokrates_stdlib/stdlib/field.zok @@ -1,8 +1,4 @@ from "EMBED" import FIELD_SIZE_IN_BITS; const field FIELD_MIN = 0; -const field FIELD_MAX = -1; - -def main() -> (field, field, u32) { - return FIELD_MIN, FIELD_MAX, FIELD_SIZE_IN_BITS; -} \ No newline at end of file +const field FIELD_MAX = -1; \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/blake2/blake2s.zok b/zokrates_stdlib/stdlib/hashes/blake2/blake2s.zok index 90cf0a12..f0b301a8 100644 --- a/zokrates_stdlib/stdlib/hashes/blake2/blake2s.zok +++ b/zokrates_stdlib/stdlib/hashes/blake2/blake2s.zok @@ -1,5 +1,5 @@ import "hashes/blake2/blake2s_p" as blake2s_p; -def main(u32[K][16] input) -> (u32[8]) { +def main(u32[K][16] input) -> u32[8] { return blake2s_p(input, [0; 2]); } \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok b/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok index 33bab9fc..50541663 100644 --- a/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok +++ b/zokrates_stdlib/stdlib/hashes/blake2/blake2s_p.zok @@ -37,7 +37,7 @@ def swap_u32(u32 val) -> u32 { } -def mixing_g(u32[16] v, u32 a, u32 b, u32 c, u32 d, u32 x, u32 y) -> (u32[16]) { +def mixing_g(u32[16] v, u32 a, u32 b, u32 c, u32 d, u32 x, u32 y) -> u32[16] { v[a] = (v[a] + v[b] + x); v[d] = rotr32::<16>(v[d] ^ v[a]); v[c] = (v[c] + v[d]); @@ -49,7 +49,7 @@ def mixing_g(u32[16] v, u32 a, u32 b, u32 c, u32 d, u32 x, u32 y) -> (u32[16]) { return v; } -def blake2s_compression(u32[8] h, u32[16] m, u32[2] t, bool last) -> (u32[8]) { +def blake2s_compression(u32[8] h, u32[16] m, u32[2] t, bool last) -> u32[8] { u32[16] v = [...h, ...IV]; v[12] = v[12] ^ t[0]; @@ -75,7 +75,7 @@ def blake2s_compression(u32[8] h, u32[16] m, u32[2] t, bool last) -> (u32[8]) { return h; } -def main(u32[K][16] input, u32[2] p) -> (u32[8]) { +def main(u32[K][16] input, u32[2] p) -> u32[8] { u32[8] h = [ IV[0] ^ 0x01010000 ^ 0x00000020, IV[1], diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bit.zok index a76b717a..c4b13b7e 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bit.zok @@ -4,7 +4,7 @@ import "./shaRoundNoBoolCheck" as sha256; // A function that takes 4 bool[256] arrays as inputs // and applies 2 rounds of sha256 compression. // It returns an array of 256 bool. -def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> (bool[256]) { +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> bool[256] { bool[256] IV = IVconstants(); bool[256] digest1 = sha256(a, b, IV); diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok index e3671b7a..a4bd52e0 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok @@ -2,7 +2,7 @@ import "./1536bit" as sha256; // Take two bool[256] arrays as input // and returns their sha256 full round output as an array of 256 bool. -def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> (bool[256]) { +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> bool[256] { // Hash is computed on the full 1024bit block size // padding does not fit in the first two blocks diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1536bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1536bit.zok index ce604444..511b2a53 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/1536bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1536bit.zok @@ -4,7 +4,7 @@ import "./shaRoundNoBoolCheck" as sha256; // A function that takes 6 bool[256] arrays as inputs // and applies 3 rounds of sha256 compression. // It returns an array of 256 bool. -def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d, bool[256] e, bool[256] f) -> (bool[256]) { +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d, bool[256] e, bool[256] f) -> bool[256] { bool[256] IV = IVconstants(); bool[256] digest1 = sha256(a, b, IV); diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok index a594d0e0..5dd8bd51 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok @@ -2,7 +2,7 @@ import "./512bit" as sha256; // A function that takes 1 bool[256] array as input // and returns the sha256 full round output as an array of 256 bool. -def main(bool[256] a) -> (bool[256]) { +def main(bool[256] a) -> bool[256] { // Hash is computed on 256 bits of input // padding fits in the remaining 256 bits of the first block diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok index 601d549f..3d6d9ce4 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok @@ -4,7 +4,7 @@ import "./shaRoundNoBoolCheck" as sha256; // A function that takes 2 bool[256] arrays as inputs // and returns their sha256 compression function as an array of 256 bool. // No padding is being applied -def main(bool[256] a, bool[256] b) -> (bool[256]) { +def main(bool[256] a, bool[256] b) -> bool[256] { bool[256] IV = IVconstants(); bool[256] digest = sha256(a, b, IV); return digest; diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPacked.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPacked.zok index be3cb307..6d596d26 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPacked.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPacked.zok @@ -5,7 +5,7 @@ import "./512bitPadded" as sha256; // A function that takes an array of 4 field elements as inputs, unpacks each of them to 128 // bits (big endian), concatenates them and applies sha256. // It then returns an array of two field elements, each representing 128 bits of the result. -def main(field[4] preimage) -> (field[2]) { +def main(field[4] preimage) -> field[2] { bool[128] a = unpack128(preimage[0]); bool[128] b = unpack128(preimage[1]); diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok index 9e7c6f0d..6b19a026 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok @@ -2,7 +2,7 @@ import "./1024bit" as sha256; // A function that takes 2 bool[256] arrays as inputs // and returns their sha256 full round output as an array of 256 bool. -def main(bool[256] a, bool[256] b) -> (bool[256]) { +def main(bool[256] a, bool[256] b) -> bool[256] { // Hash is computed on the full 512bit block size // padding does not fit in the primary block diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/IVconstants.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/IVconstants.zok index 3b770fee..99e65060 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/IVconstants.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/IVconstants.zok @@ -1,6 +1,6 @@ // SHA-256 is specified in FIPS 180-3 and initial values are listed in section 5.3.3 // https://csrc.nist.gov/csrc/media/publications/fips/180/3/archive/2008-10-31/documents/fips180-3_final.pdf -def main() -> (bool[256]) { +def main() -> bool[256] { bool[32] h0 = [false, true, true, false, true, false, true, false, false, false, false, false, true, false, false, true, true, true, true, false, false, true, true, false, false, true, true, false, false, true, true, true]; bool[32] h1 = [true, false, true, true, true, false, true, true, false, true, true, false, false, true, true, true, true, false, true, false, true, true, true, false, true, false, false, false, false, true, false, true]; bool[32] h2 = [false, false, true, true, true, true, false, false, false, true, true, false, true, true, true, false, true, true, true, true, false, false, true, true, false, true, true, true, false, false, true, false]; diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok index 32ce78b2..b3f2e7aa 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok @@ -5,6 +5,6 @@ from "EMBED" import sha256round; // a and b is NOT checked to be 0 or 1 // the return value is checked to be 0 or 1 // IV vector is checked to be of type bool -def main(bool[256] a, bool[256] b, bool[256] IV) -> (bool[256]) { +def main(bool[256] a, bool[256] b, bool[256] IV) -> bool[256] { return sha256round([...a, ...b], IV); } \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha3/256bit.zok b/zokrates_stdlib/stdlib/hashes/sha3/256bit.zok index ad8d213c..d6ea34ac 100644 --- a/zokrates_stdlib/stdlib/hashes/sha3/256bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha3/256bit.zok @@ -4,6 +4,6 @@ def sha3_256(u8[N] input) -> u64[4] { return keccak_u8::<_, 256>(input, 0x0000000000000006)[..4]; } -def main(u64[N] input) -> (u64[4]) { +def main(u64[N] input) -> u64[4] { return keccak::<_, 256>(input, 0x0000000000000006)[..4]; } \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha3/384bit.zok b/zokrates_stdlib/stdlib/hashes/sha3/384bit.zok index 3e529fca..fd3a274f 100644 --- a/zokrates_stdlib/stdlib/hashes/sha3/384bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha3/384bit.zok @@ -4,6 +4,6 @@ def sha3_384(u8[N] input) -> u64[6] { return keccak_u8::<_, 384>(input, 0x0000000000000006)[..6]; } -def main(u64[N] input) -> (u64[6]) { +def main(u64[N] input) -> u64[6] { return keccak::<_, 384>(input, 0x0000000000000006)[..6]; } \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha3/512bit.zok b/zokrates_stdlib/stdlib/hashes/sha3/512bit.zok index c662be73..5652d8bd 100644 --- a/zokrates_stdlib/stdlib/hashes/sha3/512bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha3/512bit.zok @@ -4,6 +4,6 @@ def sha3_512(u8[N] input) -> u64[8] { return keccak_u8::<_, 512>(input, 0x0000000000000006)[..8]; } -def main(u64[N] input) -> (u64[8]) { +def main(u64[N] input) -> u64[8] { return keccak::<_, 512>(input, 0x0000000000000006)[..8]; } \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok b/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok deleted file mode 100644 index 19b7644e..00000000 --- a/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok +++ /dev/null @@ -1,3 +0,0 @@ -def main(bool[1024] input) -> (bool[256], bool[256], bool[256], bool[256]) { - return input[0..256], input[256..512], input[512..768], input[768..1024]; -} \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsAdd.json b/zokrates_stdlib/tests/tests/ecc/edwardsAdd.json index 2ff3bf0a..f48237fa 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsAdd.json +++ b/zokrates_stdlib/tests/tests/ecc/edwardsAdd.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsCompress.json b/zokrates_stdlib/tests/tests/ecc/edwardsCompress.json index 53f4fbf6..e71b1417 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsCompress.json +++ b/zokrates_stdlib/tests/tests/ecc/edwardsCompress.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.json b/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.json index ec61ed51..b739bfec 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.json +++ b/zokrates_stdlib/tests/tests/ecc/edwardsOnCurve.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.json b/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.json index 07768ffc..20d08fad 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.json +++ b/zokrates_stdlib/tests/tests/ecc/edwardsOrderCheck.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.json b/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.json index f2743f66..8937c02f 100644 --- a/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.json +++ b/zokrates_stdlib/tests/tests/ecc/edwardsScalarMult.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.json b/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.json index 779793e5..a47c3793 100644 --- a/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.json +++ b/zokrates_stdlib/tests/tests/ecc/proofOfOwnership.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/field.zok b/zokrates_stdlib/tests/tests/field.zok index 0e17d0d0..e30fb1f5 100644 --- a/zokrates_stdlib/tests/tests/field.zok +++ b/zokrates_stdlib/tests/tests/field.zok @@ -1,5 +1,5 @@ from "field" import FIELD_MIN, FIELD_MAX, FIELD_SIZE_IN_BITS; def main() -> (field, field, u32) { - return FIELD_MIN, FIELD_MAX, FIELD_SIZE_IN_BITS; + return (FIELD_MIN, FIELD_MAX, FIELD_SIZE_IN_BITS); } \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.json b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.json index eb0fe602..7fcd8d5a 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.json +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1024bit.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.json b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.json index e637ac91..fa9ec10f 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.json +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_1536bit.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.json b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.json index 756f2038..de8af1bd 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.json +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_512bit.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.json b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.json index 2b7ea18b..3fd05377 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.json +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_8192bit.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.json b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.json index 2412b8f3..e0d8a790 100644 --- a/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.json +++ b/zokrates_stdlib/tests/tests/hashes/blake2/blake2s_p.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/keccak/256bit.json b/zokrates_stdlib/tests/tests/hashes/keccak/256bit.json index fc1db71e..45e34ecc 100644 --- a/zokrates_stdlib/tests/tests/hashes/keccak/256bit.json +++ b/zokrates_stdlib/tests/tests/hashes/keccak/256bit.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/keccak/384bit.json b/zokrates_stdlib/tests/tests/hashes/keccak/384bit.json index b90c14f3..89a247e6 100644 --- a/zokrates_stdlib/tests/tests/hashes/keccak/384bit.json +++ b/zokrates_stdlib/tests/tests/hashes/keccak/384bit.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/keccak/512bit.json b/zokrates_stdlib/tests/tests/hashes/keccak/512bit.json index 6ee6daa5..13b0f6b2 100644 --- a/zokrates_stdlib/tests/tests/hashes/keccak/512bit.json +++ b/zokrates_stdlib/tests/tests/hashes/keccak/512bit.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/keccak/keccak.json b/zokrates_stdlib/tests/tests/hashes/keccak/keccak.json index 63325772..5b8c913e 100644 --- a/zokrates_stdlib/tests/tests/hashes/keccak/keccak.json +++ b/zokrates_stdlib/tests/tests/hashes/keccak/keccak.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/mimc7/mimc7.json b/zokrates_stdlib/tests/tests/hashes/mimc7/mimc7.json index fe7581b2..d1dd1478 100644 --- a/zokrates_stdlib/tests/tests/hashes/mimc7/mimc7.json +++ b/zokrates_stdlib/tests/tests/hashes/mimc7/mimc7.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcSponge.json b/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcSponge.json index 98b62d1d..8134aa93 100644 --- a/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcSponge.json +++ b/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcSponge.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/pedersen/512bit.json b/zokrates_stdlib/tests/tests/hashes/pedersen/512bit.json index 79c4aeb1..2018cef2 100644 --- a/zokrates_stdlib/tests/tests/hashes/pedersen/512bit.json +++ b/zokrates_stdlib/tests/tests/hashes/pedersen/512bit.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/pedersen/512bitBool.json b/zokrates_stdlib/tests/tests/hashes/pedersen/512bitBool.json index bfa287ae..336ef9c3 100644 --- a/zokrates_stdlib/tests/tests/hashes/pedersen/512bitBool.json +++ b/zokrates_stdlib/tests/tests/hashes/pedersen/512bitBool.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }] diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/1024bitPadded.json b/zokrates_stdlib/tests/tests/hashes/sha256/1024bitPadded.json index 503a8945..c8bfc0cb 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/1024bitPadded.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/1024bitPadded.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/256bitPadded.json b/zokrates_stdlib/tests/tests/hashes/sha256/256bitPadded.json index 37db7b23..65523460 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/256bitPadded.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/256bitPadded.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }] diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/512bit.json b/zokrates_stdlib/tests/tests/hashes/sha256/512bit.json index 64bd9658..bde824a9 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/512bit.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/512bit.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/512bitPacked2.json b/zokrates_stdlib/tests/tests/hashes/sha256/512bitPacked2.json index c4d22fc2..decc69ee 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/512bitPacked2.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/512bitPacked2.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/512bitPadded.json b/zokrates_stdlib/tests/tests/hashes/sha256/512bitPadded.json index 8345033f..53f01461 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/512bitPadded.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/512bitPadded.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/1024bitPadded.json b/zokrates_stdlib/tests/tests/hashes/sha256/embed/1024bitPadded.json index b8d1e376..ceda6bfe 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/embed/1024bitPadded.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/1024bitPadded.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/256bitPadded.json b/zokrates_stdlib/tests/tests/hashes/sha256/embed/256bitPadded.json index 87520567..9a9720e2 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/embed/256bitPadded.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/256bitPadded.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }] diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bit.json b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bit.json index f12b66cb..32df8047 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bit.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bit.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPacked.json b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPacked.json index d446289c..9e22dad7 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPacked.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPacked.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPadded.json b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPadded.json index 2f8780ae..0d30c40b 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPadded.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPadded.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/sha256Padded.json b/zokrates_stdlib/tests/tests/hashes/sha256/sha256Padded.json index 84f8796d..0f41c5fd 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha256/sha256Padded.json +++ b/zokrates_stdlib/tests/tests/hashes/sha256/sha256Padded.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } }] diff --git a/zokrates_stdlib/tests/tests/hashes/sha3/256bit.json b/zokrates_stdlib/tests/tests/hashes/sha3/256bit.json index 86108146..f7fc1d35 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha3/256bit.json +++ b/zokrates_stdlib/tests/tests/hashes/sha3/256bit.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/sha3/384bit.json b/zokrates_stdlib/tests/tests/hashes/sha3/384bit.json index 2d03a2a5..dec76d77 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha3/384bit.json +++ b/zokrates_stdlib/tests/tests/hashes/sha3/384bit.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/sha3/512bit.json b/zokrates_stdlib/tests/tests/hashes/sha3/512bit.json index a5dba0ca..5ac72eb3 100644 --- a/zokrates_stdlib/tests/tests/hashes/sha3/512bit.json +++ b/zokrates_stdlib/tests/tests/hashes/sha3/512bit.json @@ -7,7 +7,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/hashes/utils/256bitsDirectionHelper.json b/zokrates_stdlib/tests/tests/hashes/utils/256bitsDirectionHelper.json index a9475c28..3bf60fb9 100644 --- a/zokrates_stdlib/tests/tests/hashes/utils/256bitsDirectionHelper.json +++ b/zokrates_stdlib/tests/tests/hashes/utils/256bitsDirectionHelper.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/signatures/verifyEddsa.json b/zokrates_stdlib/tests/tests/signatures/verifyEddsa.json index f6b36bc0..8f3244e0 100644 --- a/zokrates_stdlib/tests/tests/signatures/verifyEddsa.json +++ b/zokrates_stdlib/tests/tests/signatures/verifyEddsa.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/utils/casts/field_to_uint.zok b/zokrates_stdlib/tests/tests/utils/casts/field_to_uint.zok index d5ec1519..af6c02fb 100644 --- a/zokrates_stdlib/tests/tests/utils/casts/field_to_uint.zok +++ b/zokrates_stdlib/tests/tests/utils/casts/field_to_uint.zok @@ -16,5 +16,5 @@ def main(field[5] a, field[5] b, field[5] c, field[5] d) -> (u64[5], u32[5], u16 h[i] = field_to_u8(d[i]); } - return e, f, g, h; + return (e, f, g, h); } \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/utils/casts/to_bits.zok b/zokrates_stdlib/tests/tests/utils/casts/to_bits.zok index a4896be9..a4ddcc7a 100644 --- a/zokrates_stdlib/tests/tests/utils/casts/to_bits.zok +++ b/zokrates_stdlib/tests/tests/utils/casts/to_bits.zok @@ -16,5 +16,5 @@ def main(u64[4] a, u32[4] b, u16[4] c, u8[4] d) -> (bool[4][64], bool[4][32], bo h[i] = u8_to_bits(d[i]); } - return e, f, g, h; + return (e, f, g, h); } \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/utils/casts/to_field.zok b/zokrates_stdlib/tests/tests/utils/casts/to_field.zok index 93b9957d..f9bd6826 100644 --- a/zokrates_stdlib/tests/tests/utils/casts/to_field.zok +++ b/zokrates_stdlib/tests/tests/utils/casts/to_field.zok @@ -16,5 +16,5 @@ def main(u64[4] a, u32[4] b, u16[4] c, u8[4] d) -> (field[4], field[4], field[4] h[i] = u8_to_field(d[i]); } - return e, f, g, h; + return (e, f, g, h); } \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup1bit.json b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup1bit.json index 3e2cbc25..cd3a99a3 100644 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup1bit.json +++ b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup1bit.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup2bit.json b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup2bit.json index 2d2f4fab..6d9c2edd 100644 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup2bit.json +++ b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup2bit.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup3bitSigned.json b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup3bitSigned.json index 5c77d558..4f7d46fe 100644 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/lookup3bitSigned.json +++ b/zokrates_stdlib/tests/tests/utils/multiplexer/lookup3bitSigned.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/utils/pack/bool/nonStrictUnpack256.json b/zokrates_stdlib/tests/tests/utils/pack/bool/nonStrictUnpack256.json index fe64e6d0..c75abd31 100644 --- a/zokrates_stdlib/tests/tests/utils/pack/bool/nonStrictUnpack256.json +++ b/zokrates_stdlib/tests/tests/utils/pack/bool/nonStrictUnpack256.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/utils/pack/bool/pack128.json b/zokrates_stdlib/tests/tests/utils/pack/bool/pack128.json index 5fcaea64..db7657e4 100644 --- a/zokrates_stdlib/tests/tests/utils/pack/bool/pack128.json +++ b/zokrates_stdlib/tests/tests/utils/pack/bool/pack128.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/utils/pack/bool/unpack128.json b/zokrates_stdlib/tests/tests/utils/pack/bool/unpack128.json index daf93ea7..f7ac8593 100644 --- a/zokrates_stdlib/tests/tests/utils/pack/bool/unpack128.json +++ b/zokrates_stdlib/tests/tests/utils/pack/bool/unpack128.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.json b/zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.json index 5739811a..358a0c6d 100644 --- a/zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.json +++ b/zokrates_stdlib/tests/tests/utils/pack/bool/unpack256.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/utils/pack/u32/nonStrictUnpack256.json b/zokrates_stdlib/tests/tests/utils/pack/u32/nonStrictUnpack256.json index 92dcbbf3..0b97f02d 100644 --- a/zokrates_stdlib/tests/tests/utils/pack/u32/nonStrictUnpack256.json +++ b/zokrates_stdlib/tests/tests/utils/pack/u32/nonStrictUnpack256.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/utils/pack/u32/pack128.json b/zokrates_stdlib/tests/tests/utils/pack/u32/pack128.json index c2d11d52..b37bcfb3 100644 --- a/zokrates_stdlib/tests/tests/utils/pack/u32/pack128.json +++ b/zokrates_stdlib/tests/tests/utils/pack/u32/pack128.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_stdlib/tests/tests/utils/pack/u32/unpack128.json b/zokrates_stdlib/tests/tests/utils/pack/u32/unpack128.json index 2d93be8e..be5a271c 100644 --- a/zokrates_stdlib/tests/tests/utils/pack/u32/unpack128.json +++ b/zokrates_stdlib/tests/tests/utils/pack/u32/unpack128.json @@ -8,7 +8,7 @@ }, "output": { "Ok": { - "values": [] + "values": [[]] } } } diff --git a/zokrates_test/src/lib.rs b/zokrates_test/src/lib.rs index 7ddbaf09..c9321cde 100644 --- a/zokrates_test/src/lib.rs +++ b/zokrates_test/src/lib.rs @@ -165,21 +165,17 @@ fn compile_and_run(t: Tests) { }; let output = interpreter.execute(bin.clone(), &input); + let signature = abi.signature(); use zokrates_abi::Decode; let output: Result = output.map(|witness| Output { values: zokrates_abi::Values::decode( witness.return_values(), if with_abi { - abi.signature().outputs + vec![*signature.output] } else { - abi.signature() - .outputs - .iter() - .flat_map(|t| { - (0..t.get_primitive_count()) - .map(|_| zokrates_core::typed_absy::ConcreteType::FieldElement) - }) + (0..signature.output.get_primitive_count()) + .map(|_| zokrates_core::typed_absy::ConcreteType::FieldElement) .collect() }, )