[erl-frontend] make guard sequence expression list list

Summary: Adapted the AST to reflect the official [documentation](https://erlang.org/doc/apps/erts/absform.html): a clause can have a *guard sequence*, which is a list of *guards*. Each *guard* is a list of *guard tests*. A *guard test* is a (restricted) expression. Therefore, in the AST we now have `guard_test = expression`, and a clause has `guard_test list list`. Furthermore, the JSON translator simply applies `to_expression` to the 2D list, instead of flattening one level with `andalso`. Using `andalso` to flatten was wrong because  it handles exceptions differently, see [note](https://learnyousomeerlang.com/syntax-in-functions#guards-guards).

Reviewed By: rgrig

Differential Revision: D28936558

fbshipit-source-id: 510930998
master
Akos Hajdu 4 years ago committed by Facebook GitHub Bot
parent 3eb6e0d344
commit 849c49280f

@ -113,11 +113,11 @@ and association = {kind: association_kind; key: expression; value: expression}
and pattern = expression
and guard = expression
and guard_test = expression
(** {2 S8.5 Clauses} *)
and 'pat clause = {line: line; patterns: 'pat list; guards: guard list; body: body}
and 'pat clause = {line: line; patterns: 'pat list; guards: guard_test list list; body: body}
and case_clause = pattern clause

@ -432,19 +432,9 @@ and to_catch_pattern json : Ast.catch_pattern option =
unknown "catch_pattern" json
and to_guards line json : Ast.expression list option =
let andalso e1 e2 = {Ast.line; simple_expression= BinaryOperator (e1, AndAlso, e2)} in
let to_dnf_term xs =
let* atom_guards = to_list ~f:to_expression (one_list xs) in
match atom_guards with
| [] ->
unknown "empty_guard?" json
| [e] ->
Some e
| e :: es ->
Some (List.fold ~init:e ~f:andalso es)
in
json |> one_list |> to_list ~f:to_dnf_term
and to_guards json : Ast.expression list list option =
let to_guard xs = to_list ~f:to_expression xs in
to_list ~f:to_guard json
and to_clause : 'pat. 'pat parser -> 'pat Ast.clause parser =
@ -453,7 +443,7 @@ and to_clause : 'pat. 'pat parser -> 'pat Ast.clause parser =
| `List [`String "clause"; anno; patterns; guards; body] ->
let* line = to_line anno in
let* patterns = to_list ~f:to_pat patterns in
let* guards = to_guards line guards in
let* guards = to_guards guards in
let body = one_list body in
let* body = to_body body in
Some {Ast.line; patterns; guards; body}

Loading…
Cancel
Save