==================
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))))))))))))

==================
Anonymous keyed records
==================

inferred :: {
	x = 1,
	int = "bro",
}

empty :: {}
pair :: {1, 2}

---

(source_file
  (global_constant_declaration
    (identifier)
    (expression
      (anonymous_record_literal
        (keyed_field_initializer
          (identifier)
          (expression
            (integer)))
        (keyed_field_initializer
          (identifier)
          (expression
            (string
              (string_content)))))))
  (global_constant_declaration
    (identifier)
    (expression
      (tuple_literal)))
  (global_constant_declaration
    (identifier)
    (expression
      (tuple_literal
        (expression
          (integer))
        (expression
          (integer))))))

==================
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))))))))))

==================
Intrinsic type construction
==================

Generated :: alias struct_type!(.auto, {"value"}, {i32}, {null})

---

(source_file
  (type_declaration
    (identifier)
    (alias_type
      (type
        (intrinsic_type
          (identifier)
          (argument_list
            (expression
              (enum_literal
                (identifier)))
            (expression
              (tuple_literal
                (expression
                  (string
                    (string_content)))))
            (expression
              (tuple_literal
                (expression
                  (builtin_type))))
            (expression
              (tuple_literal
                (expression
                  (null))))))))))

==================
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))))))))))

==================
Native tests
==================

math :: import "../math"
test import "../math"

addition test {}

---

(source_file
  (import_declaration
    (identifier)
    (string
      (string_content)))
  (test_import_declaration
    (string
      (string_content)))
  (test_declaration
    (identifier)
    (block)))

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

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

visit 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))))))))))))

==================
Unsigned constraint
==================

value uint :: 255

---

(source_file
  (global_constant_declaration
    (identifier)
    (type
      (builtin_type))
    (expression
      (integer))))

==================
Bitwise operations
==================

ops func(value u8, count u8) u8 {
  value &= ~u8(1)
  value |= 2
  value xor= 3
  value <<= count
  value >>= count
  value <<|= count
  if (value | 1) |captured| { return captured }
  return (value & 15) xor (value << 1) | (value >> 1) | (value <<| 8)
}

---

(source_file
  (function_declaration
    (identifier)
    (parameter_list
      (parameter
        (identifier)
        (type
          (builtin_type)))
      (parameter
        (identifier)
        (type
          (builtin_type))))
    (type
      (builtin_type))
    (block
      (statement
        (assignment_statement
          (expression
            (identifier))
          (expression
            (unary_expression
              (expression
                (call_expression
                  (expression
                    (builtin_type))
                  (argument_list
                    (expression
                      (integer)))))))))
      (statement
        (assignment_statement
          (expression
            (identifier))
          (expression
            (integer))))
      (statement
        (assignment_statement
          (expression
            (identifier))
          (expression
            (integer))))
      (statement
        (assignment_statement
          (expression
            (identifier))
          (expression
            (identifier))))
      (statement
        (assignment_statement
          (expression
            (identifier))
          (expression
            (identifier))))
      (statement
        (assignment_statement
          (expression
            (identifier))
          (expression
            (identifier))))
      (statement
        (if_statement
          (expression
            (parenthesized_expression
              (expression
                (binary_expression
                  (expression
                    (identifier))
                  (expression
                    (integer))))))
          (capture_list
            (identifier))
          (statement
            (block
              (statement
                (return_statement
                  (expression
                    (identifier))))))))
      (statement
        (return_statement
          (expression
            (binary_expression
              (expression
                (binary_expression
                  (expression
                    (binary_expression
                      (expression
                        (parenthesized_expression
                          (expression
                            (binary_expression
                              (expression
                                (identifier))
                              (expression
                                (integer))))))
                      (expression
                        (parenthesized_expression
                          (expression
                            (binary_expression
                              (expression
                                (identifier))
                              (expression
                                (integer))))))))
                  (expression
                    (parenthesized_expression
                      (expression
                        (binary_expression
                          (expression
                            (identifier))
                          (expression
                            (integer))))))))
              (expression
                (parenthesized_expression
                  (expression
                    (binary_expression
                      (expression
                        (identifier))
                      (expression
                        (integer)))))))))))))

==================
Struct field defaults and grouped types
==================

Config :: struct {
	capacity usize = 8
}

work func() void ! (Config | errors.Full) {}

clear func($K, $V type) void {
	for 0..entries.len |i| {
		entries[i].hash = 0
	}
}

---

(source_file
  (type_declaration
    (identifier)
    (struct_type
      (record_body
        (record_field
          (identifier)
          (type
            (builtin_type))
          (expression
            (integer))))))
  (function_declaration
    (identifier)
    (parameter_list)
    (type
      (builtin_type))
    (type
      (parenthesized_type
        (type
          (named_type
            (qualified_identifier
              (identifier)))
          (named_type
            (qualified_identifier
              (identifier)
              (identifier))))))
    (block))
  (function_declaration
    (identifier)
    (parameter_list
      (parameter
        (identifier)
        (identifier)
        (type
          (builtin_type))))
    (type
      (builtin_type))
    (block
      (statement
        (for_statement
          (expression
            (binary_expression
              (expression
                (integer))
              (expression
                (field_expression
                  (expression
                    (identifier))
                  (identifier)))))
          (identifier)
          (block
            (statement
              (assignment_statement
                (expression
                  (field_expression
                    (expression
                      (index_expression
                        (expression
                          (identifier))
                        (expression
                          (identifier))))
                    (identifier)))
                (expression
                  (integer))))))))))

==================
Sink for captures and braceless while
==================

main func() void {
	for [1] |_, _| {}
	while (true) _ = 1
}

---

(source_file
  (function_declaration
    (identifier)
    (parameter_list)
    (type
      (builtin_type))
    (block
      (statement
        (for_statement
          (expression
            (array_literal
              (expression
                (integer))))
          (sink)
          (sink)
          (block)))
      (statement
        (while_statement
          (expression
            (parenthesized_expression
              (expression
                (boolean))))
          (statement
            (assignment_statement
              (expression
                (sink))
              (expression
                (integer)))))))))
