============================================
Plain
============================================

let a = 5
let b = a
let c = #foo
let list = 1
let a = list
export d = 5

---

(source_file
  (let_binding (value_identifier) (number))
  (let_binding (value_identifier) (value_identifier))
  (let_binding (value_identifier) (polyvar (polyvar_identifier)))
  (let_binding (value_identifier) (number))
  (let_binding (value_identifier) (value_identifier))
  (let_binding (value_identifier) (number)))

============================================
Tuple destructuring
============================================

let (a, b, (c, d)) = foo
let (state: int, setState) = foo
let (a, b, ()) = foo

---

(source_file
  (let_binding
    (tuple_pattern
      (tuple_item_pattern (value_identifier))
      (tuple_item_pattern (value_identifier))
      (tuple_item_pattern
        (tuple_pattern
          (tuple_item_pattern (value_identifier))
          (tuple_item_pattern (value_identifier)))))
    (value_identifier))
  (let_binding
    (tuple_pattern
       (tuple_item_pattern (value_identifier) (type_annotation (type_identifier)))
       (tuple_item_pattern (value_identifier)))
    (value_identifier))
  (let_binding
    (tuple_pattern
      (tuple_item_pattern (value_identifier))
      (tuple_item_pattern (value_identifier))
      (tuple_item_pattern (unit)))
    (value_identifier)))

============================================
Record destructuring
============================================

let {bar, baz} = foo
let {bar, baz: qux} = foo
let {Bar.Bar.bar: bar} = foo

---

(source_file
  (let_binding
    (record_pattern (value_identifier) (value_identifier)) (value_identifier))
  (let_binding
    (record_pattern
      (value_identifier)
      (value_identifier)
      (value_identifier))
    (value_identifier))
  (let_binding
    (record_pattern
      (value_identifier_path
        (module_identifier)
        (module_identifier)
        (value_identifier))
      (value_identifier))
    (value_identifier)))

============================================
Array destructuring
============================================

let [bar, baz] = foo
let [bar, baz, _] = foo

---

(source_file
  (let_binding
    (array_pattern
      (value_identifier)
      (value_identifier))
    (value_identifier))

  (let_binding
    (array_pattern
      (value_identifier)
      (value_identifier)
      (value_identifier))
    (value_identifier)))

============================================
List destructuring
============================================

let list{head, ...tail} = foo

---

(source_file
  (let_binding
    (list_pattern
      (value_identifier)
      (spread_pattern (value_identifier)))
    (value_identifier)))


============================================
Block
============================================

let x = {
  3
  4
}

---

(source_file
  (let_binding
    (value_identifier)
    (block
      (expression_statement (number))
      (expression_statement (number)))))

============================================
Annotated
============================================

let a: int = 5
let b: 'a => unit = ignore

---

(source_file
  (let_binding
    (value_identifier)
    (type_annotation (type_identifier))
    (number))
  (let_binding
    (value_identifier)
    (type_annotation
      (function_type
        (function_type_parameters (type_identifier))
        (unit_type)))
    (value_identifier)))

============================================
Recursive
============================================

let rec foo = n => foo(n-1)

---

(source_file
  (let_binding
    (value_identifier)
      (function
        (value_identifier)
        (call_expression
          (value_identifier)
          (arguments
            (binary_expression
              (value_identifier)
              (number)))))))

============================================
Unit
============================================

let () = noop

---

(source_file (let_binding (unit) (value_identifier)))

============================================
And (Primitives)
============================================

let a = 5 and b = 4

---

(source_file
  (let_binding
    (value_identifier)
    (number)
    (let_binding
      (value_identifier)
      (number))))

============================================
And (Functions)
============================================

let rec a = x => x + b(x) and b = y => y - 1

---

(source_file
  (let_binding
    (value_identifier)
    (function
      (value_identifier)
      (binary_expression
        (value_identifier)
        (call_expression
          (value_identifier)
          (arguments
            (value_identifier)))))
    (let_binding
      (value_identifier)
      (function
        (value_identifier)
        (binary_expression
          (value_identifier)
          (number))))))

============================================
And (decorated)
============================================

@one
let rec a = b
@two @three
and b = c

@four and c = 42

---

(source_file
  (decorated
    (decorator (decorator_identifier))
    (let_binding
      (value_identifier)
      (value_identifier)
      (let_binding
        (decorator (decorator_identifier))
        (decorator (decorator_identifier))
        (value_identifier)
        (value_identifier))
      (let_binding
        (decorator (decorator_identifier))
        (value_identifier)
        (number)))))

===========================================
Labled function with uncurried
===========================================

let test = (. ~attr) => ()

---

(source_file
  (let_binding
    (value_identifier)
    (function
      (formal_parameters
        (parameter
          (uncurry)
          (labeled_parameter
            (value_identifier))))
      (unit))))

===========================================
Destructuring module
===========================================


let {foo, bar} = module(User)
let {baz, _} = module(User.Inner)

---

(source_file
  (let_binding
    (record_pattern
      (value_identifier)
      (value_identifier))
    (module_pack_expression (module_identifier)))

  (let_binding
    (record_pattern
      (value_identifier)
      (value_identifier))
    (module_pack_expression
      (module_identifier_path
        (module_identifier)
        (module_identifier)))))

===========================================
Packing module
===========================================

let foo = module(Bar)

---

(source_file
  (let_binding
    (value_identifier)
    (module_pack_expression (module_identifier))))

===========================================
Unpacking module
===========================================

let module(Bar) = foo

---

(source_file
  (let_binding
    (module_unpack_pattern (module_identifier))
    (value_identifier)))
