================================================================================
basic constant function
================================================================================

let functionName x = 4

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

(file
  (declaration_expression
    (function_or_value_defn
      (function_declaration_left
        (identifier)
        (argument_patterns
          (long_identifier
            (identifier))))
      body: (const
        (int)))))

================================================================================
basic constant function inline
================================================================================

let inline functionName x = 4

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

(file
  (declaration_expression
    (function_or_value_defn
      (function_declaration_left
        (identifier)
        (argument_patterns
          (long_identifier
            (identifier))))
      body: (const
        (int)))))

================================================================================
basic private constant function
================================================================================

let private functionName x = 4

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

(file
  (declaration_expression
    (function_or_value_defn
      (function_declaration_left
        (access_modifier)
        (identifier)
        (argument_patterns
          (long_identifier
            (identifier))))
      body: (const
        (int)))))

================================================================================
private rec function
================================================================================

let rec private functionName x = 4

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

(file
  (declaration_expression
    (function_or_value_defn
      (function_declaration_left
        (access_modifier)
        (identifier)
        (argument_patterns
          (long_identifier
            (identifier))))
      (const
        (int)))))

================================================================================
mutual rec function
================================================================================

let rec private f1 x = f2 x
and f2 y = y + 1

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

(file
  (declaration_expression
    (function_or_value_defn
      (function_declaration_left
        (access_modifier)
        (identifier)
        (argument_patterns
          (long_identifier
            (identifier))))
      (application_expression
        (long_identifier_or_op
          (identifier))
        (long_identifier_or_op
          (identifier)))
      (function_declaration_left
        (identifier)
        (argument_patterns
          (long_identifier
            (identifier))))
      (infix_expression
        (long_identifier_or_op
          (identifier))
        (infix_op)
        (const
          (int))))))

================================================================================
basic private constant function inline
================================================================================

let inline private functionName x = 4

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

(file
  (declaration_expression
    (function_or_value_defn
      (function_declaration_left
        (access_modifier)
        (identifier)
        (argument_patterns
          (long_identifier
            (identifier))))
      body: (const
        (int)))))

================================================================================
basic function with srt constraint (old-style, with ^)
================================================================================

let inline double<^a when ^a:(member Double: unit -> ^a)> (x: ^a) = x.Double()

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

(file
  (declaration_expression
    (function_or_value_defn
      (function_declaration_left
        (identifier)
        (type_arguments
          (type_argument_defn
            (type_argument
              (identifier)))
          (type_argument_constraints
            (constraint
              (type_argument
                (identifier))
              (trait_member_constraint
                (identifier)
                (function_type
                  (simple_type
                    (long_identifier
                      (identifier)))
                  (type_argument
                    (identifier)))))))
        (argument_patterns
          (typed_pattern
            (identifier_pattern
              (long_identifier_or_op
                (identifier)))
            (type_argument
              (identifier)))))
      (application_expression
        (long_identifier_or_op
          (long_identifier
            (identifier)
            (identifier)))
        (unit)))))

================================================================================
basic function with srt constraint (new-style, with ')
================================================================================

let inline double<'a when 'a:(member Double: unit -> 'a)> (x: 'a) = x.Double()

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

(file
  (declaration_expression
    (function_or_value_defn
      (function_declaration_left
        (identifier)
        (type_arguments
          (type_argument_defn
            (type_argument
              (identifier)))
          (type_argument_constraints
            (constraint
              (type_argument
                (identifier))
              (trait_member_constraint
                (identifier)
                (function_type
                  (simple_type
                    (long_identifier
                      (identifier)))
                  (type_argument
                    (identifier)))))))
        (argument_patterns
          (typed_pattern
            (identifier_pattern
              (long_identifier_or_op
                (identifier)))
            (type_argument
              (identifier)))))
      (application_expression
        (long_identifier_or_op
          (long_identifier
            (identifier)
            (identifier)))
        (unit)))))

================================================================================
function decl should be preferred over value decl
================================================================================

namespace Test

module Program =
  [<EntryPoint>]
  let main args =
    ()

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

(file
  (namespace
    (long_identifier
      (identifier))
    (module_defn
      (identifier)
      (declaration_expression
        (attributes
          (attribute
            (simple_type
              (long_identifier
                (identifier)))))
        (function_or_value_defn
          (function_declaration_left
            (identifier)
            (argument_patterns
              (long_identifier
                (identifier))))
          (const
            (unit)))))))

================================================================================
SRTP when constraint on return type (simple)
================================================================================

let inline f x : ^a when ^a : comparison = x

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

(file
  (declaration_expression
    (function_or_value_defn
      (function_declaration_left
        (identifier)
        (argument_patterns
          (long_identifier
            (identifier))))
      (type_argument
        (identifier))
      (type_argument_constraints
        (constraint
          (type_argument
            (identifier))))
      body: (long_identifier_or_op
        (long_identifier
          (identifier))))))

================================================================================
SRTP when constraint on return type (trait member)
================================================================================

let inline add (x: ^a) (y: ^a) : ^a when ^a : (static member (+) : ^a * ^a -> ^a) = x + y

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

(file
  (declaration_expression
    (function_or_value_defn
      (function_declaration_left
        (identifier)
        (argument_patterns
          (typed_pattern
            (identifier_pattern
              (long_identifier_or_op
                (identifier)))
            (type_argument
              (identifier)))
          (typed_pattern
            (identifier_pattern
              (long_identifier_or_op
                (identifier)))
            (type_argument
              (identifier)))))
      (type_argument
        (identifier))
      (type_argument_constraints
        (constraint
          (type_argument
            (identifier))
          (trait_member_constraint
            (op_identifier)
            (compound_type
              (type_argument
                (identifier))
              (function_type
                (type_argument
                  (identifier))
                (type_argument
                  (identifier)))))))
      body: (infix_expression
        (long_identifier_or_op
          (identifier))
        (infix_op)
        (long_identifier_or_op
          (long_identifier
            (identifier)))))))

================================================================================
typed value with quotient measure
================================================================================

let speed: float<m/s> = 1.0

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

(file
  (declaration_expression
    (function_or_value_defn
      (value_declaration_left
        (identifier_pattern
          (long_identifier_or_op
            (identifier))))
      (generic_type
        (long_identifier
          (identifier))
        (type_attributes
          (type_attribute
            (measure
              (measure_quotient
                (measure_atom
                  (simple_type
                    (long_identifier
                      (identifier))))
                (measure_atom
                  (simple_type
                    (long_identifier
                      (identifier)))))))))
      body: (const
        (float)))))

================================================================================
typed value with power measure
================================================================================

let area: float<cm^2> = 1.0

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

(file
  (declaration_expression
    (function_or_value_defn
      (value_declaration_left
        (identifier_pattern
          (long_identifier_or_op
            (identifier))))
      (generic_type
        (long_identifier
          (identifier))
        (type_attributes
          (type_attribute
            (measure
              (measure_power
                (measure_atom
                  (simple_type
                    (long_identifier
                      (identifier))))
                (int))))))
      body: (const
        (float)))))

================================================================================
typed value with parenthesized measure
================================================================================

let speed: float<(m/s)> = 1.0

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

(file
  (declaration_expression
    (function_or_value_defn
      (value_declaration_left
        (identifier_pattern
          (long_identifier_or_op
            (identifier))))
      (generic_type
        (long_identifier
          (identifier))
        (type_attributes
          (type_attribute
            (measure
              (measure
                (measure_quotient
                  (measure_atom
                    (simple_type
                      (long_identifier
                        (identifier))))
                  (measure_atom
                    (simple_type
                      (long_identifier
                        (identifier))))))))))
      body: (const
        (float)))))

================================================================================
typed value with dimensionless reciprocal measure
================================================================================

let freq: float<1/s> = 1.0

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

(file
  (declaration_expression
    (function_or_value_defn
      (value_declaration_left
        (identifier_pattern
          (long_identifier_or_op
            (identifier))))
      (generic_type
        (long_identifier
          (identifier))
        (type_attributes
          (type_attribute
            (measure
              (measure_quotient
                (measure_atom)
                (measure_atom
                  (simple_type
                    (long_identifier
                      (identifier)))))))))
      body: (const
        (float)))))

================================================================================
Semicolon in module let body
================================================================================

module OpenTelemetry =

  let private setOtlp (e: OtlpExporterOptions) =
    e.Endpoint <- new Uri("https://example.com");

[<RequiredQualifiedAccess>]
module Entry =

  type private Dummy = interface end

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

(file
  (module_defn
    (identifier)
    (declaration_expression
      (function_or_value_defn
        (function_declaration_left
          (access_modifier)
          (identifier)
          (argument_patterns
            (typed_pattern
              (identifier_pattern
                (long_identifier_or_op
                  (identifier)))
              (simple_type
                (long_identifier
                  (identifier))))))
        (mutate_expression
          (long_identifier_or_op
            (long_identifier
              (identifier)
              (identifier)))
          (prefixed_expression
            (application_expression
              (long_identifier_or_op
                (identifier))
              (const
                (string))))))))
  (module_defn
    (attributes
      (attribute
        (simple_type
          (long_identifier
            (identifier)))))
    (identifier)
    (type_definition
      (interface_type_defn
        (type_name
          (access_modifier)
          (identifier))))))
