================================================================================
Top-level functions
================================================================================

func main() {}

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

(source_file
  (function_declaration
    (simple_identifier)
    (function_body)))

================================================================================
Generic functions
================================================================================

func test<T>(t: T) {}

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

(source_file
  (function_declaration
    (simple_identifier)
    (type_parameters
      (type_parameter
        (type_identifier)))
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)))
    (function_body)))

================================================================================
Static functions
================================================================================

static func help() {}
static func === (lhs: MyType, rhs: MyType) { }

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

(source_file
  (function_declaration
    (modifiers
      (property_modifier))
    (simple_identifier)
    (function_body))
  (function_declaration
    (modifiers
      (property_modifier))
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)))
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)))
    (function_body)))

================================================================================
Functions with parameters
================================================================================

func main(args: [String]) {}

func maybe_main(args: Maybe<String>) {}

func convert(@Arg args: [String: Int]) {}

func sum(a: Int, b: Int!) { return a + b }

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

(source_file
  (function_declaration
    (simple_identifier)
    (parameter
      (simple_identifier)
      (array_type
        (user_type
          (type_identifier))))
    (function_body))
  (function_declaration
    (simple_identifier)
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)
        (type_arguments
          (user_type
            (type_identifier)))))
    (function_body))
  (function_declaration
    (simple_identifier)
    (attribute
      (user_type
        (type_identifier)))
    (parameter
      (simple_identifier)
      (dictionary_type
        (user_type
          (type_identifier))
        (user_type
          (type_identifier))))
    (function_body))
  (function_declaration
    (simple_identifier)
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)))
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)))
    (function_body
      (statements
        (control_transfer_statement
          (additive_expression
            (simple_identifier)
            (simple_identifier)))))))

================================================================================
Functions with renamed parameters
================================================================================

func sum(_ a: Int, with b: Int) { return a + b }

sum(1, with: 2)

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

(source_file
  (function_declaration
    (simple_identifier)
    (parameter
      (simple_identifier)
      (simple_identifier)
      (user_type
        (type_identifier)))
    (parameter
      (simple_identifier)
      (simple_identifier)
      (user_type
        (type_identifier)))
    (function_body
      (statements
        (control_transfer_statement
          (additive_expression
            (simple_identifier)
            (simple_identifier))))))
  (call_expression
    (simple_identifier)
    (call_suffix
      (value_arguments
        (value_argument
          (integer_literal))
        (value_argument
          (simple_identifier)
          (integer_literal))))))

================================================================================
Functions with return types
================================================================================

func answerToTheUltimateQuestionOfLifeTheUniverseAndEverything() -> Int { return 42 }
func getConfig() -> [String: Int] {
    return [
        "TimeoutMillis": 1000,
        "RetryCount": 5,
        "RetryBackoffMillis": 5000
    ]
}

func returnGetsImplicitlyUnwrapped() -> String! {
    return nil
}

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

(source_file
  (function_declaration
    (simple_identifier)
    (user_type
      (type_identifier))
    (function_body
      (statements
        (control_transfer_statement
          (integer_literal)))))
  (function_declaration
    (simple_identifier)
    (dictionary_type
      (user_type
        (type_identifier))
      (user_type
        (type_identifier)))
    (function_body
      (statements
        (control_transfer_statement
          (dictionary_literal
            (line_string_literal
              (line_str_text))
            (integer_literal)
            (line_string_literal
              (line_str_text))
            (integer_literal)
            (line_string_literal
              (line_str_text))
            (integer_literal))))))
  (function_declaration
    (simple_identifier)
    (user_type
      (type_identifier))
    (function_body
      (statements
        (control_transfer_statement)))))

================================================================================
Variadic functions
================================================================================

func toUpperCaseAll(strings: String ...) -> [String] { }

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

(source_file
  (function_declaration
    (simple_identifier)
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)))
    (array_type
      (user_type
        (type_identifier)))
    (function_body)))

================================================================================
Operator overrides
================================================================================

public static func < (lhs: Wrapped<F>, rhs: Wrapped<F>) -> Bool {
    return false 
}

public func ??<V : Value>(optional: Expression<V?>, defaultValue: V) -> Expression<V> {
    return Expression(optional.inner() ?? defaultValue)
}

public prefix func ! (value: Wrapped<F>) -> Bool {
    return false
}

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

(source_file
  (function_declaration
    (modifiers
      (visibility_modifier)
      (property_modifier))
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)
        (type_arguments
          (user_type
            (type_identifier)))))
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)
        (type_arguments
          (user_type
            (type_identifier)))))
    (user_type
      (type_identifier))
    (function_body
      (statements
        (control_transfer_statement
          (boolean_literal)))))
  (function_declaration
    (modifiers
      (visibility_modifier))
    (custom_operator)
    (type_parameters
      (type_parameter
        (type_identifier)
        (user_type
          (type_identifier))))
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)
        (type_arguments
          (optional_type
            (user_type
              (type_identifier))))))
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)))
    (user_type
      (type_identifier)
      (type_arguments
        (user_type
          (type_identifier))))
    (function_body
      (statements
        (control_transfer_statement
          (call_expression
            (simple_identifier)
            (call_suffix
              (value_arguments
                (value_argument
                  (nil_coalescing_expression
                    (call_expression
                      (navigation_expression
                        (simple_identifier)
                        (navigation_suffix
                          (simple_identifier)))
                      (call_suffix
                        (value_arguments)))
                    (simple_identifier))))))))))
  (function_declaration
    (modifiers
      (visibility_modifier)
      (function_modifier))
    (bang)
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)
        (type_arguments
          (user_type
            (type_identifier)))))
    (user_type
      (type_identifier))
    (function_body
      (statements
        (control_transfer_statement
          (boolean_literal))))))

================================================================================
Custom operators
================================================================================

precedencegroup MyPrecedence {
    associativity: left
    assignment: true
    lowerThan: AdditionPrecedence
}

infix operator -=- : MyPrecedence

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

(source_file
  (precedence_group_declaration
    (simple_identifier)
    (precedence_group_attributes
      (precedence_group_attribute
        (simple_identifier)
        (simple_identifier))
      (precedence_group_attribute
        (simple_identifier)
        (boolean_literal))
      (precedence_group_attribute
        (simple_identifier)
        (simple_identifier))))
  (operator_declaration
    (custom_operator)
    (simple_identifier)))

================================================================================
Custom operator with another operator as a prefix
================================================================================

let messageCoerced = error ??? "nil"

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

(source_file
  (property_declaration
    (value_binding_pattern
      (non_binding_pattern
        (simple_identifier)))
    (infix_expression
      (simple_identifier)
      (custom_operator)
      (line_string_literal
        (line_str_text)))))

================================================================================
Functions that throw
================================================================================

func anythingYouCanDo() throws -> Int { return -1 }
func iCanDoBetter()
    throws
    -> Int { return -2 }

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

(source_file
  (function_declaration
    (simple_identifier)
    (throws)
    (user_type
      (type_identifier))
    (function_body
      (statements
        (control_transfer_statement
          (prefix_expression
            (integer_literal))))))
  (function_declaration
    (simple_identifier)
    (throws)
    (user_type
      (type_identifier))
    (function_body
      (statements
        (control_transfer_statement
          (prefix_expression
            (integer_literal)))))))

================================================================================
Async functions
================================================================================

func eventually() async -> Int { return -1 }
func maybe()
    async
    throws
    -> Int { return -2 }

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

(source_file
  (function_declaration
    (simple_identifier)
    (async)
    (user_type
      (type_identifier))
    (function_body
      (statements
        (control_transfer_statement
          (prefix_expression
            (integer_literal))))))
  (function_declaration
    (simple_identifier)
    (async)
    (throws)
    (user_type
      (type_identifier))
    (function_body
      (statements
        (control_transfer_statement
          (prefix_expression
            (integer_literal)))))))

================================================================================
Higher-order functions - pt 1
================================================================================

func test(i: Int = 0, block: (Int) throws -> Void) {}

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

(source_file
  (function_declaration
    (simple_identifier)
    (parameter
      (simple_identifier)
      (user_type
        (type_identifier)))
    (integer_literal)
    (parameter
      (simple_identifier)
      (function_type
        (tuple_type
          (tuple_type_item
            (user_type
              (type_identifier))))
        (throws)
        (user_type
          (type_identifier))))
    (function_body)))

================================================================================
Higher-order functions - pt 2
================================================================================

test { value in /* does nothing */ }

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

(source_file
  (call_expression
    (simple_identifier)
    (call_suffix
      (lambda_literal
        (lambda_function_type
          (lambda_function_type_parameters
            (lambda_parameter
              (simple_identifier))))
        (multiline_comment)))))

================================================================================
Higher-order functions - pt 3
================================================================================

test(2) { $0.doSomething() }

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

(source_file
  (call_expression
    (call_expression
      (simple_identifier)
      (call_suffix
        (value_arguments
          (value_argument
            (integer_literal)))))
    (call_suffix
      (lambda_literal
        (statements
          (call_expression
            (navigation_expression
              (simple_identifier)
              (navigation_suffix
                (simple_identifier)))
            (call_suffix
              (value_arguments))))))))

================================================================================
Higher-order functions - pt 4
================================================================================

test { (a) -> Void in }

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

(source_file
  (call_expression
    (simple_identifier)
    (call_suffix
      (lambda_literal
        (lambda_function_type
          (lambda_function_type_parameters
            (lambda_parameter
              (simple_identifier)))
          (user_type
            (type_identifier)))))))

================================================================================
Higher-order functions - pt 5
================================================================================

test { (a: inout Int) in }

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

(source_file
  (call_expression
    (simple_identifier)
    (call_suffix
      (lambda_literal
        (lambda_function_type
          (lambda_function_type_parameters
            (lambda_parameter
              (simple_identifier)
              (parameter_modifiers
                (parameter_modifier))
              (user_type
                (type_identifier)))))))))

================================================================================
Higher-order functions - pt 6
================================================================================

test { @Special [weak self, otherSelf] (a) in }

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

(source_file
  (call_expression
    (simple_identifier)
    (call_suffix
      (lambda_literal
        (capture_list
          (attribute
            (user_type
              (type_identifier)))
          (capture_list_item
            (ownership_modifier)
            (simple_identifier))
          (capture_list_item
            (simple_identifier)))
        (lambda_function_type
          (lambda_function_type_parameters
            (lambda_parameter
              (simple_identifier))))))))

================================================================================
Higher-order functions - pt 7
================================================================================

test(block: ===)

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

(source_file
  (call_expression
    (simple_identifier)
    (call_suffix
      (value_arguments
        (value_argument
          (simple_identifier))))))

================================================================================
Higher-order functions - pt 8
================================================================================

test { ($0, someVariable) }

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

(source_file
  (call_expression
    (simple_identifier)
    (call_suffix
      (lambda_literal
        (statements
          (tuple_expression
            (simple_identifier)
            (simple_identifier)))))))

================================================================================
Higher-order functions - pt 9
================================================================================

test { (self, a) -> Void in }

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

(source_file
  (call_expression
    (simple_identifier)
    (call_suffix
      (lambda_literal
        (lambda_function_type
          (lambda_function_type_parameters
            (lambda_parameter
              (self_expression))
            (lambda_parameter
              (simple_identifier)))
          (user_type
            (type_identifier)))))))

================================================================================
Higher-order functions - pt 10
================================================================================

test { (a: Any?) in foo(a) }

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

(source_file
  (call_expression
    (simple_identifier)
    (call_suffix
      (lambda_literal
        (lambda_function_type
          (lambda_function_type_parameters
            (lambda_parameter
              (simple_identifier)
              (optional_type
                (user_type
                  (type_identifier))))))
        (statements
          (call_expression
            (simple_identifier)
            (call_suffix
              (value_arguments
                (value_argument
                  (simple_identifier))))))))))

================================================================================
Higher-order functions - pt 11
================================================================================

types.flatMap { [abc, 1] }

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

(source_file
  (call_expression
    (navigation_expression
      (simple_identifier)
      (navigation_suffix
        (simple_identifier)))
    (call_suffix
      (lambda_literal
        (statements
          (array_literal
            (simple_identifier)
            (integer_literal)))))))

================================================================================
Function type with wildcard
================================================================================

private lazy var onCatClosure: (_ cat: Cat) throws -> Void = { _ in
}

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

(source_file
  (property_declaration
    (modifiers
      (visibility_modifier)
      (property_behavior_modifier))
    (value_binding_pattern
      (non_binding_pattern
        (simple_identifier)))
    (type_annotation
      (function_type
        (tuple_type
          (tuple_type_item
            (wildcard_pattern)
            (simple_identifier)
            (user_type
              (type_identifier))))
        (throws)
        (user_type
          (type_identifier))))
    (lambda_literal
      (lambda_function_type
        (lambda_function_type_parameters
          (lambda_parameter
            (simple_identifier)))))))

================================================================================
Multiple trailing lambdas
================================================================================

myInstance.registerCallbacks { } onCancelled: { }

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

(source_file
  (call_expression
    (navigation_expression
      (simple_identifier)
      (navigation_suffix
        (simple_identifier)))
    (call_suffix
      (lambda_literal)
      (simple_identifier)
      (lambda_literal))))

================================================================================
Return type fun
================================================================================

func opaqueType() -> some Equatable { return "" }
func multipleType() -> Foo & Bar { return Foo() }

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

(source_file
  (function_declaration
    (simple_identifier)
    (opaque_type
      (user_type
        (type_identifier)))
    (function_body
      (statements
        (control_transfer_statement
          (line_string_literal)))))
  (function_declaration
    (simple_identifier)
    (protocol_composition_type
      (user_type
        (type_identifier))
      (user_type
        (type_identifier)))
    (function_body
      (statements
        (control_transfer_statement
          (call_expression
            (simple_identifier)
            (call_suffix
              (value_arguments))))))))

================================================================================
Annotated function parameters in lambdas
================================================================================

types.flatMap { @Sendable _ in }

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

(source_file
  (call_expression
    (navigation_expression
      (simple_identifier)
      (navigation_suffix
        (simple_identifier)))
    (call_suffix
      (lambda_literal
        (lambda_function_type
          (lambda_function_type_parameters
            (lambda_parameter
              (attribute
                (user_type
                  (type_identifier)))
              (simple_identifier))))))))
