From bc25bc481672b3c16513b65a4b9905a2e2ae6064 Mon Sep 17 00:00:00 2001 From: dark64 Date: Mon, 29 Aug 2022 16:25:01 +0200 Subject: [PATCH] apply suggestions --- zokrates_ast/src/typed/mod.rs | 6 +++++ zokrates_ast/src/typed/types.rs | 4 +++ zokrates_book/src/language/functions.md | 12 ++++++--- .../examples/compile_errors/no_return.zok | 1 + zokrates_core/src/semantics.rs | 26 +++++-------------- 5 files changed, 26 insertions(+), 23 deletions(-) create mode 100644 zokrates_cli/examples/compile_errors/no_return.zok diff --git a/zokrates_ast/src/typed/mod.rs b/zokrates_ast/src/typed/mod.rs index 9c3f5e12..8ae1ce5b 100644 --- a/zokrates_ast/src/typed/mod.rs +++ b/zokrates_ast/src/typed/mod.rs @@ -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> for TypedExpression<'ast, T> { fn from(e: BooleanExpression<'ast, T>) -> TypedExpression { TypedExpression::Boolean(e) diff --git a/zokrates_ast/src/typed/types.rs b/zokrates_ast/src/typed/types.rs index 18cd658c..172bcc30 100644 --- a/zokrates_ast/src/typed/types.rs +++ b/zokrates_ast/src/typed/types.rs @@ -887,6 +887,10 @@ impl GType { pub fn uint>(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> { diff --git a/zokrates_book/src/language/functions.md b/zokrates_book/src/language/functions.md index 3a4872b8..b74c3b9c 100644 --- a/zokrates_book/src/language/functions.md +++ b/zokrates_book/src/language/functions.md @@ -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,8 @@ The generic parameters can be provided explicitly, especially when they cannot b ```zokrates {{#include ../../../zokrates_cli/examples/book/explicit_generic_parameters.zok}} -``` \ No newline at end of file +``` + +Functions that "don't" return a value, actually return an empty tuple `()`. +When a function returns an empty tuple `()`, the return type can be omitted from +the signature. In this case, a return statement can be omitted. \ No newline at end of file diff --git a/zokrates_cli/examples/compile_errors/no_return.zok b/zokrates_cli/examples/compile_errors/no_return.zok new file mode 100644 index 00000000..9480cf79 --- /dev/null +++ b/zokrates_cli/examples/compile_errors/no_return.zok @@ -0,0 +1 @@ +def main() -> field {} \ No newline at end of file diff --git a/zokrates_core/src/semantics.rs b/zokrates_core/src/semantics.rs index 38af1fdc..59488635 100644 --- a/zokrates_core/src/semantics.rs +++ b/zokrates_core/src/semantics.rs @@ -1186,16 +1186,10 @@ impl<'ast, T: Field> Checker<'ast, T> { } if !found_return { - match &s.output { - box DeclarationType::Tuple(tuple_type) - if tuple_type.elements.is_empty() => - { - statements_checked.push(TypedStatement::Return(TypedExpression::Tuple( - TupleExpressionInner::Value(vec![]) - .annotate(TupleType::new(vec![])), - ))) - } - _ => { + 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(), @@ -1877,11 +1871,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| { @@ -4700,11 +4690,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 {