Pattern guards for functions and switch statements (#339)

* Add case guards to parser

* Add pattern guards to infer types and fcode generation

* Add functions guards

* Add test for patterns guards

* Update docs

* Update CHANGELOG.md

* Remove stateful context from Env for guards

* Elaborate on guards

* Add failing test for stateful pattern guards

* Implement multiple guards

* Fix tests

* Disable aevm related tests

* Split the sentence before if and otherwise

* Fix type in docs

* Implement multiple exprs in the same guard

* Fix pretty printing

* Change tests to include multiple guards

* Add test for non-boolean guards

* Desugar clauses with guards

* Fix incomplete patterns bug

* Fix docs

* Compile to icode when no guards are used

* Revert "Disable aevm related tests"

This reverts commit e828099bd97dffe11438f2e48f3a92ce3641e85b.
This commit is contained in:
Gaith Hallak
2021-10-20 11:04:00 +03:00
committed by GitHub
parent 20cab3ae57
commit a982f25262
17 changed files with 245 additions and 74 deletions
+26 -3
View File
@@ -121,7 +121,7 @@ contract IntHolder =
type state = int
entrypoint init(x) = x
entrypoint get() = state
main contract IntHolderFactory =
stateful entrypoint new(x : int) : IntHolder =
let ih = Chain.create(x) : IntHolder
@@ -471,6 +471,8 @@ function
get_left(Both(x, _)) = Some(x)
```
*NOTE: Data types cannot currently be recursive.*
Sophia also supports the assignment of patterns to variables:
```sophia
function f(x) = switch(x)
@@ -482,7 +484,28 @@ function g(p : int * option(int)) : int =
b
```
*NOTE: Data types cannot currently be recursive.*
Guards are boolean expressions that can be used on patterns in both switch
statements and functions definitions. If a guard expression evaluates to
`true`, then the corresponding body will be used. Otherwise, the next pattern
will be checked:
```sophia
function get_left_if_positive(x : one_or_both(int, 'b)) : option(int) =
switch(x)
Left(x) | x > 0 => Some(x)
Both(x, _) | x > 0 => Some(x)
_ => None
```
```sophia
function
get_left_if_positive : one_or_both(int, 'b) => option(int)
get_left_if_positive(Left(x)) | x > 0 = Some(x)
get_left_if_positive(Both(x, _)) | x > 0 = Some(x)
get_left_if_positive(_) = None
```
Guards cannot be stateful even when used inside a stateful function.
## Lists
@@ -851,4 +874,4 @@ Some chain operations (`Oracle.<operation>` and `AENS.<operation>`) have an
optional delegation signature. This is typically used when a user/accounts
would like to allow a contract to act on it's behalf. The exact data to be
signed varies for the different operations, but in all cases you should prepend
the signature data with the `network_id` (`ae_mainnet` for the æternity mainnet, etc.).
the signature data with the `network_id` (`ae_mainnet` for the æternity mainnet, etc.).