=====================================
call without arguments
=====================================

fun do
  a
end

---

(source
  (call
    (identifier)
    (do_block
      (identifier))))

=====================================
call with arguments in parentheses
=====================================

fun(a, b) do
  c
end

---

(source
  (call
    (identifier)
    (arguments
      (identifier)
      (identifier))
    (do_block
      (identifier))))

=====================================
call with arguments without parentheses
=====================================

fun a, b do
  c
end

---

(source
  (call
    (identifier)
    (arguments
      (identifier)
      (identifier))
    (do_block
      (identifier))))

=====================================
remote call
=====================================

Mod.fun do
  a
end

---

(source
  (call
    (dot
      (alias)
      (identifier))
    (do_block
      (identifier))))

=====================================
sticks to the outermost call
=====================================

outer_fun inner_fun arg do
  a
end

---

(source
  (call
    (identifier)
    (arguments
      (call
        (identifier)
        (arguments
          (identifier))))
    (do_block
      (identifier))))

=====================================
newline before do
=====================================

fun x
do
  x
end

fun x
# comment
do
  x
end

fun()
do
  x
end

Mod.fun x
do
  x
end

---

(source
  (call
    (identifier)
    (arguments
      (identifier))
    (do_block
      (identifier)))
  (call
    (identifier)
    (arguments
      (identifier))
    (comment)
    (do_block
      (identifier)))
  (call
    (identifier)
    (arguments)
    (do_block
      (identifier)))
  (call
    (dot
      (alias)
      (identifier))
    (arguments
      (identifier))
    (do_block
      (identifier))))

=====================================
stab clause / no arguments
=====================================

fun do
 () -> x
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments)
        (body
          (identifier))))))

=====================================
stab clause / no arguments without parentheses
=====================================

fun do
  -> x
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (body
          (identifier))))))

=====================================
stab clause / one argument
=====================================

fun do
  x -> x
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (identifier))
        (body
          (identifier))))))

=====================================
stab clause / many arguments
=====================================

fun do
  x, y, 1 -> :ok
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (identifier)
          (identifier)
          (integer))
        (body
          (atom))))))

=====================================
stab clause / arguments in parentheses
=====================================

fun do
  (x, y) -> :ok
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (identifier)
          (identifier))
        (body
          (atom))))))

=====================================
stab clause / many clauses
=====================================

fun do
  1 -> :yes
  2 -> :no
  other -> :maybe
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (integer))
        (body
          (atom)))
      (stab_clause
        (arguments
          (integer))
        (body
          (atom)))
      (stab_clause
        (arguments
          (identifier))
        (body
          (atom))))))

=====================================
stab clause / multiline expression
=====================================

fun do
  x ->
    y
    x
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (identifier))
        (body
          (identifier)
          (identifier))))))

=====================================
stab clause / with guard / no arguments
=====================================

fun do
  () when node() == :nonode@nohost -> true
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (binary_operator
          (arguments)
          (binary_operator
            (call
              (identifier)
              (arguments))
            (atom)))
        (body
          (boolean))))))

=====================================
stab clause / with guard / one argument
=====================================

fun do
  x when x == [] -> x
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (binary_operator
          (arguments
            (identifier))
          (binary_operator
            (identifier)
            (list)))
        (body
          (identifier))))))

=====================================
stab clause / with guard / multiple arguments
=====================================

fun do
  x, y when x == [] -> x
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (binary_operator
          (arguments
            (identifier)
            (identifier))
          (binary_operator
            (identifier)
            (list)))
        (body
          (identifier))))))

=====================================
stab clause / with guard / arguments in parentheses
=====================================

fun do
  (x, y) when y == [] -> y
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (binary_operator
          (arguments
            (identifier)
            (identifier))
          (binary_operator
            (identifier)
            (list)))
        (body
          (identifier))))))

=====================================
stab clause / with guard / multiple guards
=====================================

fun do
  x when x > 10 when x < 5 -> x
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (binary_operator
          (arguments
            (identifier))
          (binary_operator
            (binary_operator
              (identifier)
              (integer))
            (binary_operator
              (identifier)
              (integer))))
        (body
          (identifier))))))

=====================================
stab clause / edge cases / no stab
=====================================

foo do
  a when a
end

foo do
  ([])
end

---

(source
  (call
    (identifier)
    (do_block
      (binary_operator
        (identifier)
        (identifier))))
  (call
    (identifier)
    (do_block
      (block
        (list)))))

=====================================
stab clause / edge cases / "when" in arguments
=====================================

foo do
  a when b, c when d == e -> 1
  (a, a when b) -> 1
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (binary_operator
          (arguments
            (binary_operator
              (identifier)
              (identifier))
            (identifier))
          (binary_operator
            (identifier)
            (identifier)))
        (body
          (integer)))
      (stab_clause
        (arguments
          (identifier)
          (binary_operator
            (identifier)
            (identifier)))
        (body
          (integer))))))

=====================================
stab clause / edge cases / block argument
=====================================

foo do
  (x; y) -> 1
  ((x; y)) -> 1
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (block
            (identifier)
            (identifier)))
        (body
          (integer)))
      (stab_clause
        (arguments
          (block
            (identifier)
            (identifier)))
        (body
          (integer))))))

=====================================
stab clause / edge cases / operator with lower precedence than "when"
=====================================

foo do
  x <- y when x -> y
end

foo do
  (x <- y) when x -> y
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (binary_operator
            (identifier)
            (binary_operator
              (identifier)
              (identifier))))
        (body
          (identifier)))))
  (call
    (identifier)
    (do_block
      (stab_clause
        (binary_operator
          (arguments
            (binary_operator
              (identifier)
              (identifier)))
          (identifier))
        (body
          (identifier))))))

=====================================
stab clause / edge cases / empty
=====================================

fun do->end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause))))


=====================================
stab clause / edge cases / trailing call in multiline clause
=====================================

fun do
  1 ->
    1
    x

  1 ->
    1
end

fun do
  1 ->
    1
    Mod.fun

  1 ->
    1
end

fun do
  1 ->
    1
    mod.fun

  1 ->
    1
end

fun do
  1 ->
    1

  x 1 ->
    1
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (integer))
        (body
          (integer)
          (identifier)))
      (stab_clause
        (arguments
          (integer))
        (body
          (integer)))))
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (integer))
        (body
          (integer)
          (call
            (dot
              (alias)
              (identifier)))))
      (stab_clause
        (arguments
          (integer))
        (body
          (integer)))))
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (integer))
        (body
          (integer)
          (call
            (dot
              (identifier)
              (identifier)))))
      (stab_clause
        (arguments
          (integer))
        (body
          (integer)))))
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (integer))
        (body
          (integer)))
      (stab_clause
        (arguments
          (call
            (identifier)
            (arguments
              (integer))))
        (body
          (integer))))))

=====================================
stab clause / edge cases / empty right-hand-side
=====================================

fun do
  x ->
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (identifier))
        (body)))))

=====================================
pattern matching
=====================================

fun do
  [h | tail] -> {h, tail}
end

---

(source
  (call
    (identifier)
    (do_block
      (stab_clause
        (arguments
          (list
            (binary_operator
              (identifier)
              (identifier))))
        (body
          (tuple
            (identifier)
            (identifier)))))))

=====================================
child blocks / after
=====================================

fun do
  x
after
  y
end

---

(source
  (call
    (identifier)
    (do_block
      (identifier)
      (after_block
        (identifier)))))

=====================================
child blocks / catch
=====================================

fun do
  x
catch
  y
end

---

(source
  (call
    (identifier)
    (do_block
      (identifier)
      (catch_block
        (identifier)))))

=====================================
child blocks / else
=====================================

fun do
  x
else
  y
end

---

(source
  (call
    (identifier)
    (do_block
      (identifier)
      (else_block
        (identifier)))))

=====================================
child blocks / rescue
=====================================

fun do
  x
rescue
  y
end

---

(source
  (call
    (identifier)
    (do_block
      (identifier)
      (rescue_block
        (identifier)))))

=====================================
child blocks / duplicated
=====================================

fun do
  x
after
  y
after
  z
end

---

(source
  (call
    (identifier)
    (do_block
      (identifier)
      (after_block
        (identifier))
      (after_block
        (identifier)))))

=====================================
child blocks / mixed
=====================================

fun do
  x
else
  y
after
  z
end

---

(source
  (call
    (identifier)
    (do_block
      (identifier)
      (else_block
        (identifier))
      (after_block
        (identifier)))))

=====================================
child blocks / stab clause
=====================================

fun do
  x
rescue
  y -> y
end

---

(source
  (call
    (identifier)
    (do_block
      (identifier)
      (rescue_block
        (stab_clause
          (arguments
            (identifier))
          (body
            (identifier)))))))

=====================================
child blocks / keyword pattern with child block start token
=====================================

fun do
  x
after
after
  after: 1 -> y
end

---

(source
  (call
    (identifier)
    (do_block
      (identifier)
      (after_block)
      (after_block
        (stab_clause
          (arguments
            (keywords
              (pair
                (keyword)
                (integer))))
          (body
            (identifier)))))))

=====================================
[field names]
=====================================

fun do
  x -> x
  x when x == [] -> x
end

---

(source
  (call
    target: (identifier)
    (do_block
      (stab_clause
        left: (arguments
          (identifier))
        right: (body
          (identifier)))
      (stab_clause
        left: (binary_operator
          left: (arguments
            (identifier))
          right: (binary_operator
            left: (identifier)
            right: (list)))
        right: (body
          (identifier))))))
