==================
Core syntax
==================

io :: import "@std/io"

hide private_value :: 1

hide private_counter i32 = 0

hide Private :: opaque

hide private_sum func(a, b i32) i32 {
	return a + b
}

Status :: enum {
	ok
	bad
}

Pair :: struct {
	left i32
	right i32
}

sum func(a, b i32) i32 ! Status {
	result :: a + b
	if result > 0 {
		return result
	} else {
		return .bad
	}
}

---

(source_file
  (import_declaration
    (identifier)
    (string
      (string_content)))
  (global_constant_declaration
    (identifier)
    (expression
      (integer)))
  (global_variable_declaration
    (identifier)
    (type
      (builtin_type))
    (expression
      (integer)))
  (type_declaration
    (identifier)
    (opaque_type))
  (function_declaration
    (identifier)
    (parameter_list
      (parameter
        (identifier)
        (identifier)
        (type
          (builtin_type))))
    (type
      (builtin_type))
    (block
      (statement
        (return_statement
          (expression
            (binary_expression
              (expression
                (identifier))
              (expression
                (identifier))))))))
  (type_declaration
    (identifier)
    (enum_type
      (enum_body
        (enum_member
          (identifier))
        (enum_member
          (identifier)))))
  (type_declaration
    (identifier)
    (struct_type
      (record_body
        (record_field
          (identifier)
          (type
            (builtin_type)))
        (record_field
          (identifier)
          (type
            (builtin_type))))))
  (function_declaration
    (identifier)
    (parameter_list
      (parameter
        (identifier)
        (identifier)
        (type
          (builtin_type))))
    (type
      (builtin_type))
    (type
      (named_type
        (qualified_identifier
          (identifier))))
    (block
      (statement
        (constant_declaration
          (identifier)
          (expression
            (binary_expression
              (expression
                (identifier))
              (expression
                (identifier))))))
      (statement
        (if_statement
          (expression
            (binary_expression
              (expression
                (identifier))
              (expression
                (integer))))
          (statement
            (block
              (statement
                (return_statement
                  (expression
                    (identifier))))))
          (statement
            (block
              (statement
                (return_statement
                  (expression
                    (enum_literal
                      (identifier))))))))))))

==================
Intrinsic calls
==================

main func() void {
	_ = sizeof ! (i32)
}

---

(source_file
  (function_declaration
    (identifier)
    (parameter_list)
    (type
      (builtin_type))
    (block
      (statement
        (assignment_statement
          (expression
            (sink))
          (expression
            (intrinsic_call_expression
              (identifier)
              (argument_list
                (expression
                  (builtin_type))))))))))

==================
Errdefer
==================

Failure :: enum { bad }

work func() i32 ! Failure {
  errdefer cleanup()
  errdefer |err| {
    _ = err
  }
  return 1
}

---

(source_file
  (type_declaration
    (identifier)
    (enum_type
      (enum_body
        (enum_member
          (identifier)))))
  (function_declaration
    (identifier)
    (parameter_list)
    (type
      (builtin_type))
    (type
      (named_type
        (qualified_identifier
          (identifier))))
    (block
      (statement
        (defer_statement
          (statement
            (expression_statement
              (expression
                (call_expression
                  (expression
                    (identifier))
                  (argument_list)))))))
      (statement
        (defer_statement
          (error_capture
            (identifier))
          (statement
            (block
              (statement
                (assignment_statement
                  (expression
                    (sink))
                  (expression
                    (identifier))))))))
      (statement
        (return_statement
          (expression
            (integer)))))))

==================
Bare return and value yield
==================

done func() void {
  return
}

inline func() void { return }

choose func() i32 {
  result :: { yield 1 }
  return result
}

---

(source_file
  (function_declaration
    (identifier)
    (parameter_list)
    (type
      (builtin_type))
    (block
      (statement
        (return_statement))))
  (function_declaration
    (identifier)
    (parameter_list)
    (type
      (builtin_type))
    (block
      (statement
        (return_statement))))
  (function_declaration
    (identifier)
    (parameter_list)
    (type
      (builtin_type))
    (block
      (statement
        (constant_declaration
          (identifier)
          (block
            (statement
              (yield_statement
                (expression
                  (integer)))))))
      (statement
        (return_statement
          (expression
            (identifier)))))))

==================
Tuples and expand for
==================

Pair :: struct { i32, []u8 }

main func() void {
	pair Pair = Pair {42, "bro"}
	singleton :: {1,}
	empty :: {}
	_ = pair.0
	expand for singleton |value| {
		_ = value
	}
}

---

(source_file
  (type_declaration
    (identifier)
    (struct_type
      (record_body
        (record_field
          (type
            (builtin_type)))
        (record_field
          (type
            (array_type
              (type
                (builtin_type))))))))
  (function_declaration
    (identifier)
    (parameter_list)
    (type
      (builtin_type))
    (block
      (statement
        (variable_declaration
          (identifier)
          (type
            (named_type
              (qualified_identifier
                (identifier))))
          (expression
            (struct_literal
              (qualified_identifier
                (identifier))
              (initializer_list
                (expression
                  (integer))
                (expression
                  (string
                    (string_content))))))))
      (statement
        (constant_declaration
          (identifier)
          (expression
            (tuple_literal
              (expression
                (integer))))))
      (statement
        (constant_declaration
          (identifier)
          (expression
            (tuple_literal))))
      (statement
        (assignment_statement
          (expression
            (sink))
          (expression
            (field_expression
              (expression
                (identifier))
              (integer)))))
      (statement
        (for_statement
          (expression
            (identifier))
          (identifier)
          (block
            (statement
              (assignment_statement
                (expression
                  (sink))
                (expression
                  (identifier))))))))))

==================
Expanded match arms
==================

Kind :: enum { one, two }
Value :: union(enum) { number i32, empty void }

test func(kind Kind, value Value) void {
	match kind {
		.one: {}
		expand |tag|: _ = tag
	}
	match value {
		expand |@payload, tag|: {
			_ = payload
			_ = tag
		}
	}
}

---

(source_file
  (type_declaration
    (identifier)
    (enum_type
      (enum_body
        (enum_member
          (identifier))
        (enum_member
          (identifier)))))
  (type_declaration
    (identifier)
    (union_type
      (record_body
        (record_field
          (identifier)
          (type
            (builtin_type)))
        (record_field
          (identifier)
          (type
            (builtin_type))))))
  (function_declaration
    (identifier)
    (parameter_list
      (parameter
        (identifier)
        (type
          (named_type
            (qualified_identifier
              (identifier)))))
      (parameter
        (identifier)
        (type
          (named_type
            (qualified_identifier
              (identifier))))))
    (type
      (builtin_type))
    (block
      (statement
        (match_statement
          (expression
            (identifier))
          (match_arm
            (expression
              (enum_literal
                (identifier)))
            (statement
              (expression_statement
                (expression
                  (tuple_literal)))))
          (match_arm
            (expand_match_capture
              (identifier))
            (statement
              (assignment_statement
                (expression
                  (sink))
                (expression
                  (identifier)))))))
      (statement
        (match_statement
          (expression
            (identifier))
          (match_arm
            (expand_match_capture
              (identifier)
              (identifier))
            (statement
              (block
                (statement
                  (assignment_statement
                    (expression
                      (sink))
                    (expression
                      (identifier))))
                (statement
                  (assignment_statement
                    (expression
                      (sink))
                    (expression
                      (identifier))))))))))))
