deprecate multi returns
This commit is contained in:
parent
bd69368f91
commit
b7e787dfd1
184 changed files with 1801 additions and 3051 deletions
|
@ -277,7 +277,7 @@ fn parse_value<T: Field>(
|
|||
.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 {}",
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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}}
|
||||
```
|
|
@ -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
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -59,11 +59,9 @@ In this example, the ABI specification is:
|
|||
"type":"field"
|
||||
}
|
||||
],
|
||||
"outputs":[
|
||||
{
|
||||
"type":"field"
|
||||
}
|
||||
]
|
||||
"output": {
|
||||
"type":"field"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -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"]);
|
||||
|
|
|
@ -11,5 +11,5 @@ def fill<R, C>(field v) -> matrix<R, C> {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -12,5 +12,5 @@ def buzz<N>() -> Buzz<N> {
|
|||
|
||||
def main(matrix_2x4 m) -> (Buzz<2>, matrix_2x4) {
|
||||
Buzz<2> b = buzz::<2>();
|
||||
return b, m;
|
||||
return (b, m);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
def main(field value) -> (field[3]) {
|
||||
def main(field value) -> field[3] {
|
||||
return [value, value, value];
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
def main() -> () {
|
||||
def main() {
|
||||
assert(1f + 1f == 2f);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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<N>(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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
def sum<N>(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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
def main() -> (field, field[3]) {
|
||||
return 1, [2, 3, 4];
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
def main(field a, field b) -> (bool) {
|
||||
def main(field a, field b) -> bool {
|
||||
return !(a == b);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
struct Bar<N> {
|
||||
field[N] c;
|
||||
bool d;
|
||||
field[N] c;
|
||||
bool d;
|
||||
}
|
||||
|
||||
struct Foo<P> {
|
||||
Bar<P> a;
|
||||
bool b;
|
||||
Bar<P> 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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,5 @@ def assert() {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
return
|
|
@ -1,6 +1,6 @@
|
|||
struct Foo {}
|
||||
struct Bar {}
|
||||
|
||||
def main() -> (Foo) {
|
||||
def main() -> Foo {
|
||||
return Bar {};
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<T: Field, I: Iterator<Item = ir::Statement<T>>>(
|
|||
}
|
||||
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<T: Field, I: Iterator<Item = ir::Statement<T>>>(
|
|||
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);
|
||||
|
|
|
@ -183,16 +183,13 @@ impl<'ast> From<pest::FunctionDefinition<'ast>> 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<absy::StatementN
|
|||
|
||||
fn statements_from_definition(definition: pest::DefinitionStatement) -> Vec<absy::StatementNode> {
|
||||
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<pest::ReturnStatement<'ast>> 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<absy::StatementNode> = 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<absy::StatementNode> = 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)");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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<ExpressionNode<'ast>>),
|
||||
Declaration(VariableNode<'ast>),
|
||||
Definition(AssigneeNode<'ast>, ExpressionNode<'ast>),
|
||||
Assertion(ExpressionNode<'ast>, Option<String>),
|
||||
|
@ -394,7 +394,6 @@ pub enum Statement<'ast> {
|
|||
ExpressionNode<'ast>,
|
||||
Vec<StatementNode<'ast>>,
|
||||
),
|
||||
MultipleDefinition(Vec<AssigneeNode<'ast>>, ExpressionNode<'ast>),
|
||||
}
|
||||
|
||||
pub type StatementNode<'ast> = Node<Statement<'ast>>;
|
||||
|
@ -402,7 +401,13 @@ pub type StatementNode<'ast> = Node<Statement<'ast>>;
|
|||
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<ExpressionNode<'ast>>,
|
||||
}
|
||||
|
||||
pub type ExpressionListNode<'ast> = Node<ExpressionList<'ast>>;
|
||||
|
||||
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, "")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> {}
|
||||
|
|
|
@ -85,15 +85,15 @@ mod signature {
|
|||
pub struct UnresolvedSignature<'ast> {
|
||||
pub generics: Vec<ConstantGenericNode<'ast>>,
|
||||
pub inputs: Vec<UnresolvedTypeNode<'ast>>,
|
||||
pub outputs: Vec<UnresolvedTypeNode<'ast>>,
|
||||
pub output: Option<UnresolvedTypeNode<'ast>>,
|
||||
}
|
||||
|
||||
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<UnresolvedTypeNode<'ast>>) -> Self {
|
||||
self.outputs = outputs;
|
||||
pub fn output(mut self, output: UnresolvedTypeNode<'ast>) -> Self {
|
||||
self.output = Some(output);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -469,7 +469,7 @@ struct Bar { field a; }
|
|||
}]
|
||||
))
|
||||
}],
|
||||
outputs: vec![]
|
||||
output: ConcreteType::Tuple(GTupleType::new(vec![]))
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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<Vec<TypedStatement<'ast, T>>, 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::<Result<Vec<_>, _>>()?;
|
||||
|
||||
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<TypedExpressionListInner<'ast, T>, Error> {
|
||||
match l {
|
||||
TypedExpressionListInner::EmbedCall(FlatEmbed::BitArrayLe, generics, arguments) => {
|
||||
let arguments = arguments
|
||||
.into_iter()
|
||||
.map(|a| self.fold_expression(a))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Bn128Field> = 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<Bn128Field> = 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<Bn128Field> = 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<Bn128Field> = 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<Bn128Field> = 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(),
|
||||
|
|
|
@ -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<T> {
|
|||
fold_tuple_expression(self, statements_buffer, e)
|
||||
}
|
||||
|
||||
fn fold_expression_list(
|
||||
&mut self,
|
||||
statements_buffer: &mut Vec<zir::ZirStatement<'ast, T>>,
|
||||
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<E: Flatten<'ast, T>>(
|
||||
&mut self,
|
||||
statements_buffer: &mut Vec<zir::ZirStatement<'ast, T>>,
|
||||
|
@ -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![],
|
||||
};
|
||||
|
|
|
@ -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<TypedAssignee<'ast, T>> = assignees
|
||||
.into_iter()
|
||||
.map(|a| self.fold_assignee(a))
|
||||
.collect::<Result<_, _>>()?;
|
||||
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::<Result<_, _>>()?,
|
||||
};
|
||||
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::<Result<_, _>>()?;
|
||||
let argument = arguments.last().cloned().unwrap();
|
||||
let argument = argument.into_canonical_constant();
|
||||
|
||||
fn process_u_from_bits<'ast, T: Field>(
|
||||
variables: Vec<TypedAssignee<'ast, T>>,
|
||||
mut arguments: Vec<TypedExpression<'ast, T>>,
|
||||
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<TypedAssignee<'ast, T>>,
|
||||
arguments: Vec<TypedExpression<'ast, T>>,
|
||||
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::<Vec<_>>()
|
||||
.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<TypedExpression<'ast, T>> = 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::<T>::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::<Vec<_>>()
|
||||
.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::<Result<_, _>>()?;
|
||||
|
||||
let arguments: Vec<_> = function_call
|
||||
.arguments
|
||||
.into_iter()
|
||||
.map(|a| self.fold_expression(a))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
// 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::<Vec<_>>()
|
||||
.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<TypedExpression<'ast, T>> = 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::<T>::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::<Vec<_>>()
|
||||
.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();
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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<u32>,
|
||||
Vec<TypedExpression<'ast, T>>,
|
||||
Types<'ast, T>,
|
||||
Type<'ast, T>,
|
||||
),
|
||||
NonConstant(
|
||||
DeclarationFunctionKey<'ast, T>,
|
||||
Vec<Option<UExpression<'ast, T>>>,
|
||||
Vec<TypedExpression<'ast, T>>,
|
||||
Types<'ast, T>,
|
||||
Type<'ast, T>,
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ fn get_canonical_function<'ast, T: Field>(
|
|||
}
|
||||
|
||||
type InlineResult<'ast, T> = Result<
|
||||
Output<(Vec<TypedStatement<'ast, T>>, Vec<TypedExpression<'ast, T>>), Vec<Versions<'ast>>>,
|
||||
Output<(Vec<TypedStatement<'ast, T>>, TypedExpression<'ast, T>), Vec<Versions<'ast>>>,
|
||||
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<Option<u32>> = 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::<T>(&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<ConcreteVariable<'ast>> = 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<TypedExpression<_>> = res
|
||||
.iter()
|
||||
.map(|v| TypedExpression::from(Variable::from(v.clone())))
|
||||
.collect();
|
||||
// let expressions: Vec<TypedExpression<_>> =
|
||||
// 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<TypedStatement<'ast, T>> = 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))))
|
||||
}
|
||||
|
|
|
@ -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<Vec<TypedStatement<'ast, T>>, 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::<Result<_, _>>()?;
|
||||
|
||||
let arguments = function_call
|
||||
.arguments
|
||||
.into_iter()
|
||||
.map(|a| self.fold_expression(a))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
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<T: Field>(f: &TypedFunction<T>) -> 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<Bn128Field> = 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<Bn128Field> = 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<Bn128Field> = 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<Bn128Field> = 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<Bn128Field> = 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<Bn128Field> = 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<Bn128Field> = 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<Bn128Field> = 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),
|
||||
)
|
||||
|
|
|
@ -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<Bn128Field> = TypedStatement::MultipleDefinition(
|
||||
vec![Variable::field_element("a").into()],
|
||||
TypedExpressionList::function_call(
|
||||
let s: TypedStatement<Bn128Field> = 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!(
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<UExpression<'ast, T>>),
|
||||
Member(MemberId),
|
||||
Element(u32),
|
||||
}
|
||||
|
@ -420,7 +420,7 @@ fn linear<T: Field>(a: TypedAssignee<T>) -> (Variable<T>, Vec<Access<T>>) {
|
|||
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();
|
||||
|
|
|
@ -14,7 +14,7 @@ pub type AbiOutput = ConcreteType;
|
|||
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Abi {
|
||||
pub inputs: Vec<AbiInput>,
|
||||
pub outputs: Vec<AbiOutput>,
|
||||
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
|
|
|
@ -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<E: Fold<'ast, T>>(
|
||||
|
@ -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<TypedStatement<'ast, T>> {
|
||||
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>,
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::<Vec<_>>()
|
||||
.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<u32>,
|
||||
pub arguments: Vec<TypedExpression<'ast, T>>,
|
||||
}
|
||||
|
||||
impl<'ast, T> EmbedCall<'ast, T> {
|
||||
pub fn new(
|
||||
embed: FlatEmbed,
|
||||
generics: Vec<u32>,
|
||||
arguments: Vec<TypedExpression<'ast, T>>,
|
||||
) -> 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::<Vec<_>>()
|
||||
.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<TypedExpression<'ast, T>>),
|
||||
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<TypedStatement<'ast, T>>,
|
||||
),
|
||||
MultipleDefinition(Vec<TypedAssignee<'ast, T>>, 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<Type<'ast, T>>;
|
||||
}
|
||||
|
||||
#[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<u32>, Vec<TypedExpression<'ast, T>>),
|
||||
}
|
||||
|
||||
impl<'ast, T> MultiTyped<'ast, T> for TypedExpressionList<'ast, T> {
|
||||
fn get_types(&self) -> &Vec<Type<'ast, T>> {
|
||||
&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<E> {
|
||||
pub left: Box<E>,
|
||||
|
@ -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<TypedExpression<'ast, T>> for TupleExpression<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
// `TypedExpressionList` can technically not be constructed from `TypedExpression`
|
||||
// However implementing `From<TypedExpression>` 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<TypedExpression<'ast, T>> for TypedExpressionList<'ast, T> {
|
||||
fn from(_: TypedExpression<'ast, T>) -> TypedExpressionList<'ast, T> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, T> From<TypedConstant<'ast, T>> 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::<Vec<_>>()
|
||||
.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<Variable<'ast, T>> for TypedExpression<'ast, T> {
|
||||
|
@ -1763,7 +1698,7 @@ impl<'ast, T: Field> From<Variable<'ast, T>> 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<Variable<'ast, T>> for TypedExpression<'ast, T> {
|
|||
|
||||
pub trait Expr<'ast, T>: fmt::Display + From<TypedExpression<'ast, T>> {
|
||||
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<TypedExpression>` 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<Option<UExpression<'ast, T>>>,
|
||||
arguments: Vec<TypedExpression<'ast, T>>,
|
||||
) -> Self::Inner {
|
||||
TypedExpressionListInner::FunctionCall(FunctionCallExpression::new(
|
||||
key, generics, arguments,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Block<'ast, T> {
|
||||
fn block(statements: Vec<TypedStatement<'ast, T>>, value: Self) -> Self;
|
||||
}
|
||||
|
@ -2471,7 +2365,7 @@ impl<'ast, T: Field> Block<'ast, T> for ArrayExpression<'ast, T> {
|
|||
fn block(statements: Vec<TypedStatement<'ast, T>>, 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::<Vec<_>>()
|
||||
.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::<Vec<_>>()
|
||||
.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!(),
|
||||
}
|
||||
|
|
|
@ -194,10 +194,6 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
fn fold_types(&mut self, tys: Types<'ast, T>) -> Result<Types<'ast, T>, 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<ArrayType<'ast, T>, 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<DeclarationArrayType<'ast, T>, 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<EmbedCall<'ast, T>, 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<TypedExpression<'ast, T>, 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<TypedExpressionListInner<'ast, T>, Self::Error> {
|
||||
fold_expression_list_inner(self, tys, es)
|
||||
}
|
||||
|
||||
fn fold_expression_list(
|
||||
&mut self,
|
||||
es: TypedExpressionList<'ast, T>,
|
||||
) -> Result<TypedExpressionList<'ast, T>, 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<Vec<TypedStatement<'ast, T>>, F::Error> {
|
||||
let res = match s {
|
||||
TypedStatement::Return(expressions) => TypedStatement::Return(
|
||||
expressions
|
||||
.into_iter()
|
||||
.map(|e| f.fold_expression(e))
|
||||
.collect::<Result<_, _>>()?,
|
||||
),
|
||||
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::<Result<_, _>>()?,
|
||||
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<EmbedCall<'ast, T>, F::Error> {
|
||||
Ok(EmbedCall {
|
||||
arguments: e
|
||||
.arguments
|
||||
.into_iter()
|
||||
.map(|s| f.fold_expression(s))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
..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::<Result<_, _>>()?,
|
||||
outputs: s
|
||||
.outputs
|
||||
.into_iter()
|
||||
.map(|o| f.fold_declaration_type(o))
|
||||
.collect::<Result<_, _>>()?,
|
||||
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<TypedExpression<'ast, T>, 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<TypedExpressionList<'ast, T>, 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<Types<'ast, T>, F::Error> {
|
||||
Ok(Types {
|
||||
inner: tys
|
||||
.inner
|
||||
.into_iter()
|
||||
.map(|t| f.fold_type(t))
|
||||
.collect::<Result<_, _>>()?,
|
||||
})
|
||||
}
|
||||
|
||||
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<TypedExpressionListInner<'ast, T>, 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::<Result<_, _>>()?,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fold_struct_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||
f: &mut F,
|
||||
e: StructExpression<'ast, T>,
|
||||
|
|
|
@ -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<Type<'ast, T>>,
|
||||
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<Type<'ast, T>>) -> 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<ConcreteStructMember> for StructMember<'ast, T> {
|
|||
|
||||
#[derive(Clone, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord, Debug)]
|
||||
pub struct GArrayType<S> {
|
||||
pub size: S,
|
||||
pub size: Box<S>,
|
||||
#[serde(flatten)]
|
||||
pub ty: Box<GType<S>>,
|
||||
}
|
||||
|
@ -348,7 +323,7 @@ pub type ArrayType<'ast, T> = GArrayType<UExpression<'ast, T>>;
|
|||
|
||||
impl<'ast, S, R: PartialEq<S>> PartialEq<GArrayType<S>> for GArrayType<R> {
|
||||
fn eq(&self, other: &GArrayType<S>) -> 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<T: TryInto<U>, U>(
|
|||
t: GArrayType<T>,
|
||||
) -> Result<GArrayType<U>, 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<S, U: Into<S>> From<(GType<S>, U)> for GArrayType<S> {
|
|||
fn from(tup: (GType<S>, U)) -> Self {
|
||||
GArrayType {
|
||||
ty: box tup.0,
|
||||
size: tup.1.into(),
|
||||
size: box tup.1.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -838,8 +813,8 @@ impl<S, U: Into<S>> From<(GType<S>, U)> for GArrayType<S> {
|
|||
impl<S> GArrayType<S> {
|
||||
pub fn new<U: Into<S>>(ty: GType<S>, 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<u32>>(
|
|||
(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<CanonicalConstantIdentifier<'ast>> for DeclarationConstant<'a
|
|||
pub fn specialize_declaration_type<
|
||||
'ast,
|
||||
T: Clone,
|
||||
S: Clone + PartialEq + From<u32> + fmt::Debug + From<CanonicalConstantIdentifier<'ast>>,
|
||||
S: Clone + PartialEq + From<u32> + From<CanonicalConstantIdentifier<'ast>>,
|
||||
>(
|
||||
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<S> {
|
||||
pub generics: Vec<Option<S>>,
|
||||
pub inputs: Vec<GType<S>>,
|
||||
pub outputs: Vec<GType<S>>,
|
||||
pub output: Box<GType<S>>,
|
||||
}
|
||||
|
||||
impl<S> Default for GSignature<S> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
generics: vec![],
|
||||
inputs: vec![],
|
||||
output: box GType::Tuple(GTupleType::new(vec![])),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: PartialEq> PartialEq for GSignature<S> {
|
||||
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<std::cmp::Ordering> {
|
||||
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<S: Hash> Hash for GSignature<S> {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.inputs.hash(state);
|
||||
self.outputs.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Default for GSignature<S> {
|
||||
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::<T, u32>(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<Option<u32>>,
|
||||
|
@ -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<Option<UExpression<'ast, T>>>,
|
||||
inputs: Vec<Type<'ast, T>>,
|
||||
) -> Result<Vec<Type<'ast, T>>, GenericIdentifier<'ast>> {
|
||||
) -> Result<Type<'ast, T>, 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::<Result<_, _>>()
|
||||
// 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::<Result<_, _>>()?,
|
||||
outputs: t
|
||||
.outputs
|
||||
.into_iter()
|
||||
.map(try_from_g_type)
|
||||
.collect::<Result<_, _>>()?,
|
||||
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<GType<S>>) -> Self {
|
||||
self.outputs = outputs;
|
||||
pub fn output(mut self, output: GType<S>) -> 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"));
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ impl From<typed_absy::types::ConcreteSignature> 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<zir::types::Type> {
|
|||
}
|
||||
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()
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
def main(bool[3] a) -> (bool[3]) {
|
||||
def main(bool[3] a) -> bool[3] {
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": [{"a": [true, true], "b": "3"}, "4"]
|
||||
"values": [[{"a": [true, true], "b": "3"}, "4"]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -3,13 +3,11 @@
|
|||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
]
|
||||
"values": []
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": [
|
||||
]
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,5 +41,5 @@ def main(field a, u32 b) -> (bool, bool) {
|
|||
field c = 42;
|
||||
u32 d = 42;
|
||||
|
||||
return le::<FIELD_SIZE_IN_BITS>(a, c), le(b, d);
|
||||
return (le::<FIELD_SIZE_IN_BITS>(a, c), le(b, d));
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": [["21888242871839275222246405745257275088548364400416034343698204186575808495615", "21888242871839275222246405745257275088548364400416034343698204186575808495616", "21888242871839275222246405745257275088548364400416034343698204186575808495616", "21888242871839275222246405745257275088548364400416034343698204186575808495616"], ["0xfe", "0xff", "0xff", "0xff"]]
|
||||
"values": [[["21888242871839275222246405745257275088548364400416034343698204186575808495615", "21888242871839275222246405745257275088548364400416034343698204186575808495616", "21888242871839275222246405745257275088548364400416034343698204186575808495616", "21888242871839275222246405745257275088548364400416034343698204186575808495616"], ["0xfe", "0xff", "0xff", "0xff"]]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
|
@ -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"]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,5 +24,5 @@ def main(field[4] values) -> (field, field, field) {
|
|||
}
|
||||
}
|
||||
|
||||
return res0, res1, res2;
|
||||
return (res0, res1, res2);
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -7,12 +7,7 @@
|
|||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
true,
|
||||
["1",
|
||||
"1"],
|
||||
"1"
|
||||
]
|
||||
"values": [true, ["1", "1"], "1"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": [["2"], ["1"], { "a": "2"}, {"a": "1"}, "2", "1"]
|
||||
"values": [[["2"], ["1"], { "a": "2"}, {"a": "1"}, "2", "1"]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -47,7 +47,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -19,7 +19,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -19,7 +19,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -19,7 +19,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -19,7 +19,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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];
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,6 @@ struct A {
|
|||
bool b;
|
||||
}
|
||||
|
||||
def main(A a) -> (A) {
|
||||
def main(A a) -> A {
|
||||
return a;
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": []
|
||||
"values": [[]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue