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

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

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

(source_file
  (let_declaration
    (let_binding
      (value_identifier)
      (number)))
  (let_declaration
    (let_binding
      (value_identifier)
      (value_identifier)))
  (let_declaration
    (let_binding
      (value_identifier)
      (polyvar
        (polyvar_identifier))))
  (let_declaration
    (let_binding
      (value_identifier)
      (number)))
  (let_declaration
    (let_binding
      (value_identifier)
      (value_identifier)))
  (let_declaration
    (let_binding
      (value_identifier)
      (number)))
  (let_declaration
    (let_binding
      (value_identifier)
      (number)))
  (let_declaration
    (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_declaration
    (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_declaration
    (let_binding
      (tuple_pattern
        (tuple_item_pattern
          (value_identifier)
          (type_annotation
            (type_identifier)))
        (tuple_item_pattern
          (value_identifier)))
      (value_identifier)))
  (let_declaration
    (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
let {?Bar.bar} = foo
let {?bar} = foo

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

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

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

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

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

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

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

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

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

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

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

let x = {
  3
  4
}

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

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

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

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

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

(source_file
  (let_declaration
    (let_binding
      (value_identifier)
      (type_annotation
        (type_identifier))
      (number)))
  (let_declaration
    (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_declaration
    (let_binding
      (value_identifier)
      (function
        (value_identifier)
        (call_expression
          (value_identifier)
          (arguments
            (binary_expression
              (value_identifier)
              (number))))))))

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

let () = noop

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

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

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

let a = 5 and b = 4

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

(source_file
  (let_declaration
    (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_declaration
    (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))))))

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

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

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

(source_file
  (let_declaration
    (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_declaration
    (let_binding
      (record_pattern
        (value_identifier)
        (value_identifier))
      (module_pack
        (module_identifier))))
  (let_declaration
    (let_binding
      (record_pattern
        (value_identifier)
        (value_identifier))
      (module_pack
        (module_identifier_path
          (module_identifier)
          (module_identifier))))))

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

let foo = module(Bar)

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

(source_file
  (let_declaration
    (let_binding
      (value_identifier)
      (module_pack
        (module_identifier)))))

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

let module(Bar) = foo

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

(source_file
  (let_declaration
    (let_binding
      (module_pack
        (module_identifier))
      (value_identifier))))

================================================================================
Lazy Values
================================================================================

let lazy x = lazy(1)

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

(source_file
  (let_declaration
    (let_binding
      (lazy_pattern
        (value_identifier))
      (lazy_expression
        (parenthesized_expression
          (number))))))
