============================================
Declaration statements
============================================

package main

func main() {
  var x = y
  const x = 5
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration (identifier) (parameter_list) (block
    (var_declaration
      (var_spec (identifier) (expression_list (identifier))))
    (const_declaration
      (const_spec (identifier) (expression_list (int_literal)))))))

============================================
Expression statements
============================================

package main

func main() {
  foo(5)
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration (identifier) (parameter_list) (block
    (call_expression (identifier) (argument_list (int_literal))))))

============================================
Send statements
============================================

package main

func main() {
  foo <- 5
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration (identifier) (parameter_list) (block
    (send_statement (identifier) (int_literal)))))

============================================
Increment/Decrement statements
============================================

package main

func main() {
  i++
  j--
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration (identifier) (parameter_list) (block
    (inc_statement (identifier))
    (dec_statement (identifier)))))

============================================
Assignment statements
============================================

package main

func main() {
  a = 1
  b, c += 2, 3
  d *= 3
  e += 1
  f /= 2
  g <<= 1
  h >>= 1
  i %= 1
  j &= 2
  k &^= 3
  l -= 1
  m |= 2
  n ^= 2
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration (identifier) (parameter_list) (block
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier) (identifier))
      (expression_list (int_literal) (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal)))
    (assignment_statement
      (expression_list (identifier))
      (expression_list (int_literal))))))

============================================
Short var declarations
============================================

package main

func main() {
  a, b := 1, 2
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration (identifier) (parameter_list) (block
    (short_var_declaration
      (expression_list (identifier) (identifier))
      (expression_list (int_literal) (int_literal))))))

============================================
If statements
============================================

package main

func main() {
  if a {
    b()
  }

  if a := b(); c {
    d()
  }

  if a {
    b()
  } else {
    c()
  }

  if b {
    c()
  } else if d {
    e()
  } else {
    f()
  }
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration
    name: (identifier)
    parameters: (parameter_list)
    body: (block
      (if_statement
        condition: (identifier)
        consequence: (block (call_expression
          function: (identifier)
          arguments: (argument_list))))

      (if_statement
        initializer: (short_var_declaration
          left: (expression_list (identifier))
          right: (expression_list (call_expression
            function: (identifier)
            arguments: (argument_list))))
        condition: (identifier)
        consequence: (block
          (call_expression
            function: (identifier)
            arguments: (argument_list))))

      (if_statement
        condition: (identifier)
        consequence: (block (call_expression
          function: (identifier)
          arguments: (argument_list)))
        alternative: (block (call_expression
          function: (identifier)
          arguments: (argument_list))))

      (if_statement
        condition: (identifier)
        consequence: (block (call_expression
          function: (identifier)
          arguments: (argument_list)))
        alternative: (if_statement
          condition: (identifier)
          consequence: (block (call_expression
            function: (identifier)
            arguments: (argument_list)))
          alternative: (block (call_expression
            function: (identifier)
            arguments: (argument_list))))))))

============================================
For statements
============================================

package main

func main() {
  for {
    a()
    goto loop
  }

  loop: for i := 0; i < 5; i++ {
    a()
    break loop
  }

loop2:
  for ; i < 10; i++ {
    a()
    continue loop2
  }

  for ;; {
    a()
    continue
  }

  for x := range y {
    a(x)
    break
  }
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration (identifier) (parameter_list) (block
    (for_statement
      (block
        (call_expression (identifier) (argument_list))
        (goto_statement (label_name))))
    (labeled_statement (label_name)
      (for_statement
        (for_clause
          (short_var_declaration
            (expression_list (identifier))
            (expression_list (int_literal)))
          (binary_expression (identifier) (int_literal))
          (inc_statement (identifier)))
        (block
          (call_expression (identifier) (argument_list))
          (break_statement (label_name)))))
    (labeled_statement (label_name)
      (for_statement
        (for_clause
          (binary_expression (identifier) (int_literal))
          (inc_statement (identifier)))
        (block
          (call_expression (identifier) (argument_list))
          (continue_statement (label_name)))))
    (for_statement
      (for_clause)
      (block
        (call_expression (identifier) (argument_list))
        (continue_statement)))
    (for_statement
      (range_clause (expression_list (identifier)) (identifier))
      (block
        (call_expression (identifier) (argument_list (identifier)))
        (break_statement))))))

============================================
Switch statements
============================================

func main() {
  switch e {
    case 1, 2:
      a()
      fallthrough
    case 3:
      d()
    default:
      c()
      break
  }

  switch {
    case true:
      return
  }

  switch f := y(); f {
  }
}

---

(source_file
  (function_declaration
    name: (identifier)
    parameters: (parameter_list)
    body: (block
      (expression_switch_statement
        value: (identifier)
        (expression_case
          value: (expression_list (int_literal) (int_literal))
          (call_expression
            function: (identifier)
            arguments: (argument_list))
          (fallthrough_statement))
        (expression_case
          value: (expression_list (int_literal))
          (call_expression
            function: (identifier)
            arguments: (argument_list)))
        (default_case
          (call_expression
            function: (identifier)
            arguments: (argument_list))
          (break_statement)))
      (expression_switch_statement
        (expression_case
          value: (expression_list (true))
          (return_statement)))
      (expression_switch_statement
        initializer: (short_var_declaration
          left: (expression_list (identifier))
          right: (expression_list (call_expression
            function: (identifier)
            arguments: (argument_list))))
        value: (identifier)))))

============================================
Type switch statements
============================================

func main() {
  switch e.(type) {
    case []Person:
      a()
    case *Dog:
      break
  }
  switch i := x.(type) {
    case nil:
    	printString("x is nil")
    case int:
    	printInt(i)
    case float64:
    	printFloat64(i)
    case func(int) float64:
    	printFunction(i)
    case bool, string:
    	printString("type is bool or string")
    default:
    	printString("don't know the type")
  }
}

---

(source_file
  (function_declaration
    name: (identifier)
    parameters: (parameter_list)
    body: (block
      (type_switch_statement
        value: (identifier)
        (type_case
          type: (slice_type
            element: (type_identifier))
          (call_expression
            function: (identifier)
            arguments: (argument_list)))
        (type_case
          type: (pointer_type (type_identifier))
          (break_statement)))
      (type_switch_statement
        alias: (expression_list (identifier))
        value: (identifier)
        (type_case
          type: (type_identifier)
          (call_expression
            function: (identifier)
            arguments: (argument_list (interpreted_string_literal))))
        (type_case
          type: (type_identifier)
          (call_expression
            function: (identifier)
            arguments: (argument_list (identifier))))
        (type_case
          type: (type_identifier)
          (call_expression
            function: (identifier)
            arguments: (argument_list (identifier))))
        (type_case
          type: (function_type
            parameters: (parameter_list (parameter_declaration
              type: (type_identifier)))
            result: (type_identifier))
          (call_expression
            function: (identifier)
            arguments: (argument_list (identifier))))
        (type_case
          type: (type_identifier)
          type: (type_identifier)
          (call_expression
            function: (identifier)
            arguments: (argument_list (interpreted_string_literal))))
        (default_case
          (call_expression
            function: (identifier)
            arguments: (argument_list (interpreted_string_literal))))))))

============================================
Select statements
============================================

package main

func main() {
  select {
    case x := <-c:
      println(x)
    case y <- c:
      println(5)
    case <-time.After(1):
      println(6)
    default:
      return
  }
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration
    name: (identifier)
    parameters: (parameter_list)
    body: (block
      (select_statement
        (communication_case
          communication: (receive_statement
            left: (expression_list (identifier))
            right: (unary_expression operand: (identifier)))
          (call_expression
            function: (identifier)
            arguments: (argument_list (identifier))))
        (communication_case
          communication: (send_statement
            channel: (identifier)
            value: (identifier))
          (call_expression
            function: (identifier)
            arguments: (argument_list (int_literal))))
        (communication_case
          communication: (receive_statement
            right: (unary_expression operand: (call_expression
              function: (selector_expression
                operand: (identifier)
                field: (field_identifier))
              arguments: (argument_list (int_literal)))))
          (call_expression
            function: (identifier)
            arguments: (argument_list (int_literal))))
        (default_case
          (return_statement))))))

============================================
Go and defer statements
============================================

package main

func main() {
  defer x.y()
  go x.y()
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration (identifier) (parameter_list) (block
    (defer_statement (call_expression (selector_expression (identifier) (field_identifier)) (argument_list)))
    (go_statement (call_expression (selector_expression (identifier) (field_identifier)) (argument_list))))))

============================================
Nested statement blocks
============================================

func main() {
  {
    println("hi")
  }
  {
    println("bye")
  }
}

---

(source_file
  (function_declaration (identifier) (parameter_list) (block
    (block (call_expression (identifier) (argument_list (interpreted_string_literal))))
    (block (call_expression (identifier) (argument_list (interpreted_string_literal)))))))

============================================
Labels at the ends of statement blocks
============================================

func main() {
  {
  end_of_block:
  }
}

---

(source_file
  (function_declaration
    name: (identifier)
    parameters: (parameter_list)
    body: (block (block
      (labeled_statement
        label: (label_name))))))

============================================
Empty statements
============================================

package main

func main() {
	;
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration (identifier) (parameter_list) (block
    (empty_statement))))

=============================================
Nested control statements
=============================================

package main

func main() {
  for i, v := range vectors {
    func() {
      if v == v {
        fmt.Println("something: %v", vectors[i])
      }
    }()
  }
}

---

(source_file
  (package_clause (package_identifier))
  (function_declaration (identifier) (parameter_list) (block
    (for_statement
      (range_clause (expression_list (identifier) (identifier)) (identifier))
      (block
        (call_expression
          (func_literal
            (parameter_list)
            (block
              (if_statement
                (binary_expression (identifier) (identifier))
                (block
                  (call_expression
                    (selector_expression (identifier) (field_identifier))
                    (argument_list
                      (interpreted_string_literal)
                      (index_expression (identifier) (identifier))))))))
          (argument_list)))))))

============================================
Top-level statements
============================================

foo(5)
x := T { a: b }

---

(source_file
  (call_expression (identifier) (argument_list (int_literal)))
  (short_var_declaration
    (expression_list (identifier))
    (expression_list
      (composite_literal
        (type_identifier)
        (literal_value (keyed_element (field_identifier) (identifier)))))))
