1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

Merge pull request #1222 from Zokrates/optional-return

Make return statement optional
This commit is contained in:
Thibaut Schaeffer 2022-08-30 14:29:21 +02:00 committed by GitHub
commit 909c3e0f24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 61 additions and 34 deletions

View file

@ -51,5 +51,5 @@ We enforce strict formatting of `.{js,json,ts}` files in CI. This check is not i
```
npm i -g prettier
prettier --write ./**/*.{js,ts,json}
prettier --write "./**/*.{js,ts,json}"
```

View file

@ -0,0 +1 @@
Make return statement optional if no returns are expected

View file

@ -752,6 +752,12 @@ pub enum TypedExpression<'ast, T> {
Int(IntExpression<'ast, T>),
}
impl<'ast, T> TypedExpression<'ast, T> {
pub fn empty_tuple() -> TypedExpression<'ast, T> {
TypedExpression::Tuple(TupleExpressionInner::Value(vec![]).annotate(TupleType::new(vec![])))
}
}
impl<'ast, T> From<BooleanExpression<'ast, T>> for TypedExpression<'ast, T> {
fn from(e: BooleanExpression<'ast, T>) -> TypedExpression<T> {
TypedExpression::Boolean(e)

View file

@ -895,6 +895,10 @@ impl<S> GType<S> {
pub fn uint<W: Into<UBitwidth>>(b: W) -> Self {
GType::Uint(b.into())
}
pub fn is_empty_tuple(&self) -> bool {
matches!(self, GType::Tuple(ty) if ty.elements.is_empty())
}
}
impl<'ast, T: fmt::Display + PartialEq + fmt::Debug> Type<'ast, T> {

View file

@ -1,13 +1,15 @@
## Functions
Functions are declared using the `def` keyword. A function's signature has to be explicitly provided.
Its arguments are type annotated, just like variables, and, if the function returns a value,
the return type must be specified after an arrow `->`.
A function has to be declared at the top level before it is called.
```zokrates
{{#include ../../../zokrates_cli/examples/book/function_declaration.zok}}
```
A function's signature has to be explicitly provided.
A function can be generic over any number of values of type `u32`.
```zokrates
@ -18,4 +20,10 @@ The generic parameters can be provided explicitly, especially when they cannot b
```zokrates
{{#include ../../../zokrates_cli/examples/book/explicit_generic_parameters.zok}}
```
If the return type of a function is the empty tuple `()`, the return type as well as the return statement can be omitted.
```zokrates
{{#include ../../../zokrates_cli/examples/book/no_return.zok}}
```

View file

@ -0,0 +1 @@
def main() {}

View file

@ -1,5 +1 @@
def foo() {}
def main() {
return;
}
def main() -> field {}

View file

@ -1204,10 +1204,16 @@ impl<'ast, T: Field> Checker<'ast, T> {
}
if !found_return {
errors.push(ErrorInner {
pos: Some(pos),
message: "Expected a return statement".to_string(),
});
match (&*s.output).is_empty_tuple() {
true => statements_checked
.push(TypedStatement::Return(TypedExpression::empty_tuple())),
false => {
errors.push(ErrorInner {
pos: Some(pos),
message: "Expected a return statement".to_string(),
});
}
}
}
signature = Some(s);
@ -1843,11 +1849,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
}
.map_err(|e| vec![e])
})
.unwrap_or_else(|| {
Ok(TupleExpressionInner::Value(vec![])
.annotate(TupleType::new(vec![]))
.into())
})?;
.unwrap_or_else(|| Ok(TypedExpression::empty_tuple()))?;
let res = match TypedExpression::align_to_type(e_checked.clone(), &return_type)
.map_err(|e| {
@ -4735,11 +4737,7 @@ mod tests {
10u32.into(),
for_statements_checked,
),
TypedStatement::Return(
TupleExpressionInner::Value(vec![])
.annotate(TupleType::new(vec![]))
.into(),
),
TypedStatement::Return(TypedExpression::empty_tuple()),
];
let foo = Function {

View file

@ -0,0 +1,4 @@
{
"entry_point": "./tests/tests/no_return.zok",
"tests": []
}

View file

@ -0,0 +1,9 @@
def foo() {
return;
}
def bar() {
return foo();
}
def main() {}

View file

@ -1,15 +1,15 @@
{
"entry_point": "./tests/tests/shadowing.zok",
"tests": [
{
"input": {
"values": []
},
"output": {
"Ok": {
"value": ["2", "84"]
}
}
"entry_point": "./tests/tests/shadowing.zok",
"tests": [
{
"input": {
"values": []
},
"output": {
"Ok": {
"value": ["2", "84"]
}
]
}
}
]
}