================================================================================
record index
================================================================================

f() -> #record.field.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (record_index_expr
          (record_name
            (atom))
          (record_field_name
            (atom)))))))

================================================================================
record field
================================================================================

f(X) -> X#record.field.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args
        (var))
      (clause_body
        (record_field_expr
          (var)
          (record_name
            (atom))
          (record_field_name
            (atom)))))))

================================================================================
record expr
================================================================================

f() -> #record{a = 1}.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (record_expr
          (record_name
            (atom))
          (record_field
            (atom)
            (field_expr
              (integer))))))))

================================================================================
record update
================================================================================

f(X) -> X#record{a = 1}.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args
        (var))
      (clause_body
        (record_update_expr
          (var)
          (record_name
            (atom))
          (record_field
            (atom)
            (field_expr
              (integer))))))))

================================================================================
try
================================================================================

f(X) ->
  try 1 of
    X -> ok;
    Y when Z -> ok
  catch
    Pattern -> ok;
    error:Pattern -> ok;
    throw:Pattern:Stack -> ok;
    exit:Complex + Pattern:Stack -> ok
  after
    ok
  end,
  try _
  catch
  end.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args
        (var))
      (clause_body
        (try_expr
          (integer)
          (cr_clause
            (var)
            (clause_body
              (atom)))
          (cr_clause
            (var)
            (guard
              (guard_clause
                (var)))
            (clause_body
              (atom)))
          (catch_clause
            (var)
            (clause_body
              (atom)))
          (catch_clause
            (try_class
              (atom))
            (var)
            (clause_body
              (atom)))
          (catch_clause
            (try_class
              (atom))
            (var)
            (try_stack
              (var))
            (clause_body
              (atom)))
          (catch_clause
            (try_class
              (atom))
            (binary_op_expr
              (var)
              (var))
            (try_stack
              (var))
            (clause_body
              (atom)))
          (try_after
            (atom)))
        (try_expr
          (var))))))

================================================================================
funs
================================================================================

f() -> [
  fun foo/1,
  fun mod:foo/1,
  fun () -> ok end
].

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (list
          (internal_fun
            (atom)
            (arity
              (integer)))
          (external_fun
            (module
              (atom))
            (atom)
            (arity
              (integer)))
          (anonymous_fun
            (fun_clause
              (expr_args)
              (clause_body
                (atom)))))))))

================================================================================
list
================================================================================

f() ->
  [],
  [A],
  [A, B],
  [A | B],
  [A + B | B + C],
  [A, B | C].

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (list)
        (list
          (var))
        (list
          (var)
          (var))
        (list
          (pipe
            (var)
            (var)))
        (list
          (pipe
            (binary_op_expr
              (var)
              (var))
            (binary_op_expr
              (var)
              (var))))
        (list
          (var)
          (pipe
            (var)
            (var)))))))

================================================================================
binary
================================================================================

f(<<_>>) ->
  <<>>,
  <<1>>,
  <<1/integer>>,
  <<1:32/integer>>,
  <<+1:32/integer>>,
  <<1:32/integer-unit:8>>.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args
        (binary
          (bin_element
            (var))))
      (clause_body
        (binary)
        (binary
          (bin_element
            (integer)))
        (binary
          (bin_element
            (integer)
            (bit_type_list
              (atom))))
        (binary
          (bin_element
            (integer)
            (bit_size_expr
              (integer))
            (bit_type_list
              (atom))))
        (binary
          (bin_element
            (unary_op_expr
              (integer))
            (bit_size_expr
              (integer))
            (bit_type_list
              (atom))))
        (binary
          (bin_element
            (integer)
            (bit_size_expr
              (integer))
            (bit_type_list
              (atom)
              (bit_type_unit
                (integer)))))))))

================================================================================
catch
================================================================================

f() ->
  catch 1 + 2.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (catch_expr
          (binary_op_expr
            (integer)
            (integer)))))))

================================================================================
receive
================================================================================

f() ->
  receive
  end,
  receive
    ok -> ok;
    error -> error
  end,
  receive
    after 1000 -> ok
  end,
  receive
    ok -> ok
    after Timeout -> timeout
  end.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (receive_expr)
        (receive_expr
          (cr_clause
            (atom)
            (clause_body
              (atom)))
          (cr_clause
            (atom)
            (clause_body
              (atom))))
        (receive_expr
          (receive_after
            (integer)
            (clause_body
              (atom))))
        (receive_expr
          (cr_clause
            (atom)
            (clause_body
              (atom)))
          (receive_after
            (var)
            (clause_body
              (atom))))))))

================================================================================
case
================================================================================

f() ->
  case _ of
  end,
  case Foo of
    A when A; B, C -> ok;
    _ -> error
  end.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (case_expr
          (var))
        (case_expr
          (var)
          (cr_clause
            (var)
            (guard
              (guard_clause
                (var))
              (guard_clause
                (var)
                (var)))
            (clause_body
              (atom)))
          (cr_clause
            (var)
            (clause_body
              (atom))))))))

================================================================================
function call
================================================================================

f() ->
  foo(),
  (foo)(),
  mod:foo(),
  (mod:foo)(),
  (Mod):(Foo)().

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (call
          (atom)
          (expr_args))
        (call
          (paren_expr
            (atom))
          (expr_args))
        (call
          (remote
            (remote_module
              (atom))
            (atom))
          (expr_args))
        (call
          (paren_expr
            (remote
              (remote_module
                (atom))
              (atom)))
          (expr_args))
        (call
          (remote
            (remote_module
              (paren_expr
                (var)))
            (paren_expr
              (var)))
          (expr_args))))))

================================================================================
variable assignment
================================================================================

f() ->
  A = 3 + B.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (match_expr
          (var)
          (binary_op_expr
            (integer)
            (var)))))))

================================================================================
fun
================================================================================

 foo() -> fun(X) -> X end.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (anonymous_fun
          (fun_clause
            (expr_args
              (var))
            (clause_body
              (var))))))))

================================================================================
named fun
================================================================================

 foo() -> fun Named(X) -> X end.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (anonymous_fun
          (fun_clause
            (var)
            (expr_args
              (var))
            (clause_body
              (var))))))))

================================================================================
maybe
================================================================================
f() ->
  maybe
    {ok, A} ?= a(),
    true = A >= 0,
    {ok, B} ?= b(),
    A + B
  end.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (maybe_expr
          (cond_match_expr
            (tuple
              (atom)
              (var))
            (call
              (atom)
              (expr_args)))
          (match_expr
            (atom)
            (binary_op_expr
              (var)
              (integer)))
          (cond_match_expr
            (tuple
              (atom)
              (var))
            (call
              (atom)
              (expr_args)))
          (binary_op_expr
            (var)
            (var)))))))

================================================================================
maybe else
================================================================================
f() ->
  maybe
    {ok, A} ?= a(),
    true = A >= 0,
    A
  else
    Err when Err /= warn -> error;
    false -> error
  end.

--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (maybe_expr
          (cond_match_expr
            (tuple
              (atom)
              (var))
            (call
              (atom)
              (expr_args)))
          (match_expr
            (atom)
            (binary_op_expr
              (var)
              (integer)))
          (var)
          (cr_clause
            (var)
            (guard
              (guard_clause
                (binary_op_expr
                  (var)
                  (atom))))
            (clause_body
              (atom)))
          (cr_clause
            (atom)
            (clause_body
              (atom))))))))

================================================================================
simple map comprehension
================================================================================
f() ->
  #{K => V || K := V <- #{1 => 2, 3 => 4}}.
--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (map_comprehension
          (map_field
            (var)
            (var))
          (lc_exprs
            (map_generator
              (map_field
                (var)
                (var))
              (map_expr
                (map_field
                  (integer)
                  (integer))
                (map_field
                  (integer)
                  (integer))))))))))

================================================================================
simple map comprehension with filter
================================================================================
f() ->
  #{K => V || K := V <- #{1 => 2, 3 => 4}, K>1}.
--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (map_comprehension
          (map_field
            (var)
            (var))
          (lc_exprs
            (map_generator
              (map_field
                (var)
                (var))
              (map_expr
                (map_field
                  (integer)
                  (integer))
                (map_field
                  (integer)
                  (integer))))
            (binary_op_expr
              (var)
              (integer))))))))

================================================================================
map comprehension with list generator
================================================================================
f() ->
  #{K => K + 1 || K <- [1, 2, 3], K>1}.
--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (map_comprehension
          (map_field
            (var)
            (binary_op_expr
              (var)
              (integer)))
          (lc_exprs
            (generator
              (var)
              (list
                (integer)
                (integer)
                (integer)))
            (binary_op_expr
              (var)
              (integer))))))))

================================================================================
map comprehension with binary generator
================================================================================
f() ->
  #{K => V || <<K, V>> <= <<1, 2, 3, 4>>, K>1}.
--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (map_comprehension
          (map_field
            (var)
            (var))
          (lc_exprs
            (b_generator
              (binary
                (bin_element
                  (var))
                (bin_element
                  (var)))
              (binary
                (bin_element
                  (integer))
                (bin_element
                  (integer))
                (bin_element
                  (integer))
                (bin_element
                  (integer))))
            (binary_op_expr
              (var)
              (integer))))))))

================================================================================
list comprehension with map generator
================================================================================
f() ->
  [{K, V} || K := V <- #{1 => 2, 3 => 4}, K>1].
--------------------------------------------------------------------------------

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (list_comprehension
          (tuple
            (var)
            (var))
          (lc_exprs
            (map_generator
              (map_field
                (var)
                (var))
              (map_expr
                (map_field
                  (integer)
                  (integer))
                (map_field
                  (integer)
                  (integer))))
            (binary_op_expr
              (var)
              (integer))))))))
