========================
Module Definition
========================

module my_module {
  // module body ...
}

---

(source_file
  (module_definition
    (qualified_identifier (identifier))
    (comment)))

========================
Constant declarations
========================
      
const N: int
const Proc: Set[str]

---

(source_file
  (constant_declaration
    (qualified_identifier (identifier))
    (type
      (qualified_identifier (identifier))))
  (constant_declaration
    (qualified_identifier (identifier))
    (type
      (polymorphic_type
        (qualified_identifier (identifier))
        (type
          (qualified_identifier (identifier)))))))

========================
Assumptions
========================
      
assume AtLeast4 = N >= 4

---

(source_file
  (assumption
    (qualified_identifier (identifier))
    (expr
      (binary_expr
        (expr
          (qualified_identifier (identifier)))
        (expr
          (int_literal))))))

========================
Variable Definitions
========================
      
var name: str
var timer: int
var isArmed: bool

---
  
(source_file
  (variable_definition
    (qualified_identifier (identifier))
    (type
      (qualified_identifier (identifier))))
  (variable_definition
    (qualified_identifier (identifier))
    (type
      (qualified_identifier (identifier))))
  (variable_definition
    (qualified_identifier (identifier))
    (type
      (qualified_identifier (identifier)))))


========================
Static Constant Value
========================
    
pure val Nodes: Set[int] = 1.to(10)

---

(source_file
  (operator_definition
    (qualified_identifier
      (identifier))
    (type
      (polymorphic_type
        (qualified_identifier
          (identifier))
        (type
          (qualified_identifier
            (identifier)))))
    (expr
      (binary_expr
        (expr
          (int_literal))
        (ufcs_right_hand_side
          (operator_application
            (qualified_identifier
              (identifier))
            (expr
              (int_literal))))))))

==========================================
Definition with Optional Ending Semicolon
==========================================
    
pure val eleven = 11;

---

(source_file
  (operator_definition
    (qualified_identifier (identifier))
    (expr
      (int_literal)))) 

========================
Zero-Argument Operator
========================
    
pure def fst(): int = 1

---

(source_file
  (operator_definition
    (qualified_identifier (identifier))
    (typed_argument_list)
    (type
      (qualified_identifier (identifier)))
    (expr
      (int_literal))))

========================
Two-Argument Operator
========================
    
pure def fst(x: int, y: int): int = 
  x

---

(source_file
  (operator_definition
    (qualified_identifier (identifier))
    (typed_argument_list
      (identifier)
      (type
        (qualified_identifier (identifier)))
      (identifier)
      (type
        (qualified_identifier (identifier))))
    (type
      (qualified_identifier (identifier)))
    (expr
      (qualified_identifier (identifier)))))

========================
Higher-Order Operator
========================

pure def F(G: a => b, x: a): b = G(x)

---

(source_file
  (operator_definition
    (qualified_identifier (identifier))
    (typed_argument_list
      (identifier)
      (type
        (operator_type
          (type
            (qualified_identifier (identifier)))
          (type
            (qualified_identifier (identifier)))))
      (identifier)
      (type
        (qualified_identifier (identifier))))
    (type
      (qualified_identifier (identifier)))
    (expr
      (operator_application
        (qualified_identifier (identifier))
        (expr
          (qualified_identifier (identifier)))))))
 
========================
Stateful Variable
========================

var timer: int

---

(source_file
  (variable_definition
    (qualified_identifier (identifier))
    (type
      (qualified_identifier (identifier)))))

========================
State Dependent Value
========================

val isTimerPositive =
    timer >= 0

---

(source_file
  (operator_definition
    (qualified_identifier (identifier))
    (expr
      (binary_expr
        (expr
          (qualified_identifier (identifier)))
        (expr
          (int_literal))))))

========================
State Dependent Operator
========================

def hasExpired(timestamp: int) =
    timer >= timestamp
 
---

(source_file
  (operator_definition
    (qualified_identifier (identifier))
    (typed_argument_list
      (identifier)
      (type
        (qualified_identifier (identifier))))
    (expr
      (binary_expr
        (expr
          (qualified_identifier (identifier)))
        (expr
          (qualified_identifier (identifier)))))))

========================
Action without Argument
========================

action init =
  timer' = 0
 
---

(source_file
  (operator_definition
    (qualified_identifier (identifier))
    (expr
      (binary_expr
        (expr
          (qualified_identifier (identifier)))
        (expr
          (int_literal))))))

========================
Action with Argument
========================

action advance(unit: int) =
  timer' = timer + unit
 
---

(source_file
  (operator_definition
    (qualified_identifier (identifier))
    (typed_argument_list
      (identifier)
      (type
        (qualified_identifier (identifier))))
    (expr
      (binary_expr
        (expr
          (qualified_identifier (identifier)))
        (expr
          (binary_expr
            (expr
              (qualified_identifier (identifier)))
            (expr
              (qualified_identifier (identifier)))))))))

========================
Temporal Formula
========================

temporal neverNegative =
    always(timer >= 0)
 
---

(source_file
  (operator_definition
    (qualified_identifier (identifier))
    (expr
      (operator_application
        (qualified_identifier (identifier))
        (expr
          (binary_expr
            (expr
              (qualified_identifier (identifier)))
            (expr
              (int_literal))))))))

========================
Type Alias
========================

type INT_SET = Set[int]
 
---

(source_file
  (type_alias
    (qualified_identifier (identifier))
    (type
      (polymorphic_type
        (qualified_identifier (identifier))
        (type
          (qualified_identifier (identifier)))))))

========================
Sum Type
========================

type _ = S(str) | I(int) | Nil

type _ = 
  | S(str) // <-- optional leading pipe
  | I(int) 
  | Nil
 
---

(source_file
  (type_alias
    (qualified_identifier
      (identifier))
    (sum_type
      (variant_constructor
        (qualified_identifier
          (identifier))
        (type
          (qualified_identifier
            (identifier))))
      (variant_constructor
        (qualified_identifier
          (identifier))
        (type
          (qualified_identifier
            (identifier))))
      (variant_constructor
        (qualified_identifier
          (identifier)))))
  (type_alias
    (qualified_identifier
      (identifier))
    (sum_type
      (variant_constructor
        (qualified_identifier
          (identifier))
        (type
          (qualified_identifier
            (identifier))))
      (comment)
      (variant_constructor
        (qualified_identifier
          (identifier))
        (type
          (qualified_identifier
            (identifier))))
      (variant_constructor
        (qualified_identifier
          (identifier))))))

========================
Operator Type
========================

type _ = int => int
type _ = () => int
type _ = (int) => int
type _ = (int, bool) => int
 
---

(source_file
  (type_alias
    (qualified_identifier (identifier))
    (type
      (operator_type
        (type
          (qualified_identifier (identifier)))
        (type
          (qualified_identifier (identifier))))))
  (type_alias
    (qualified_identifier (identifier))
    (type
      (operator_type
        (type
          (qualified_identifier (identifier))))))
  (type_alias
    (qualified_identifier (identifier))
    (type
      (operator_type
        (type
          (qualified_identifier (identifier)))
        (type
          (qualified_identifier (identifier))))))
  (type_alias
    (qualified_identifier (identifier))
    (type
      (operator_type
        (type
          (qualified_identifier (identifier)))
        (type
          (qualified_identifier (identifier)))
        (type
          (qualified_identifier (identifier)))))))

========================
Function Type
========================

type _ = bool -> int -> int
 
---

(source_file
  (type_alias
    (qualified_identifier (identifier))
    (type
      (function_type
        (type
          (qualified_identifier (identifier)))
        (type
          (function_type
            (type
              (qualified_identifier (identifier)))
            (type
              (qualified_identifier (identifier)))))))))

  
========================
Record Type
========================

type _ = {
  address: str,
  coins: Coins,
}

type _ = {}
 
---

(source_file
  (type_alias
    (qualified_identifier
      (identifier))
    (type
      (record_type
        (qualified_identifier
          (identifier))
        (type
          (qualified_identifier
            (identifier)))
        (qualified_identifier
          (identifier))
        (type
          (qualified_identifier
            (identifier))))))
  (type_alias
    (qualified_identifier
      (identifier))
    (type
      (record_type))))

========================
Tuple Type
========================

type _ = () 
type _ = (int) 
type _ = (int, str) 

---

(source_file
  (type_alias
    (qualified_identifier
      (identifier))
    (type
      (tuple_type)))
  (type_alias
    (qualified_identifier
      (identifier))
    (type
      (tuple_type
        (type
          (qualified_identifier
            (identifier))))))
  (type_alias
    (qualified_identifier
      (identifier))
    (type
      (tuple_type
        (type
          (qualified_identifier
            (identifier)))
        (type
          (qualified_identifier
            (identifier)))))))

========================
Qualified Identifier
========================

def Foo::bar = Foo::Bar::baz

---

(source_file
  (operator_definition
    (qualified_identifier
      (identifier)
      (identifier))
    (expr
      (qualified_identifier
        (identifier)
        (identifier)
        (identifier)))))

========================
Imports
========================

module _ {
  import Foo.bar.baz
  import Math.*
  import bank.* from "./bank"
  import Foo as MyFoo
  import A::Impl.*
  import BinSearch(
    INPUT_SEQ=[ 1, 2, 3, 4, 5, 6, 8, 9, 10, 33 ],
    INPUT_KEY=7,
    INT_WIDTH=16
  ).*
}

---

(source_file
  (module_definition
    (qualified_identifier
      (identifier))
    (import
      (import_segment
        (qualified_identifier
          (identifier)))
      (import_segment
        (qualified_identifier
          (identifier)))
      (import_segment
        (qualified_identifier
          (identifier))))
    (import
      (import_segment
        (qualified_identifier
          (identifier)))
      (import_segment))
    (import
      (import_segment
        (qualified_identifier
          (identifier)))
      (import_segment)
      (string
        (string_fragment)))
    (import
      (import_segment
        (qualified_identifier
          (identifier)))
      (qualified_identifier
        (identifier)))
    (import
      (import_segment
        (qualified_identifier
          (identifier)
          (identifier)))
      (import_segment))
    (import
      (import_segment
        (qualified_identifier
          (identifier))
        (import_segment_arguments
          (qualified_identifier
            (identifier))
          (expr
            (list_literal
              (expr
                (int_literal))
              (expr
                (int_literal))
              (expr
                (int_literal))
              (expr
                (int_literal))
              (expr
                (int_literal))
              (expr
                (int_literal))
              (expr
                (int_literal))
              (expr
                (int_literal))
              (expr
                (int_literal))
              (expr
                (int_literal))))
          (qualified_identifier
            (identifier))
          (expr
            (int_literal))
          (qualified_identifier
            (identifier))
          (expr
            (int_literal))))
      (import_segment))))

========================
Exports
========================

module _ {
  export Math.*
  export Foo
  export Foo as MyFoo
}

---

(source_file
  (module_definition
    (qualified_identifier
      (identifier))
    (export
      (qualified_identifier
        (identifier)))
    (export
      (qualified_identifier
        (identifier)))
    (export
      (qualified_identifier
        (identifier))
      (qualified_identifier
        (identifier)))))

