Odin Odinlang Memo

#### Allocator

##### トラッキングアロケーター
```go
package main

import "core:mem"

// トラッキングアロケーター: メモリーリークを検出する
// コンパイル時に '-debug' を加えると ODIN_DEBUG が 'true' になる

main :: proc() {

	when ODIN_DEBUG {
		track: mem.Tracking_Allocator
		mem.tracking_allocator_init(&track, context.allocator)
		context.allocator = mem.tracking_allocator(&track)

		defer {
			if len(track.allocation_map) > 0 {
				fmt.eprintf("=== %v allocations not freed: ===\n", len(track.allocation_map))
				for _, entry in track.allocation_map {
					fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
				}
			}
			if len(track.bad_free_array) > 0 {
				fmt.eprintf("=== %v incorrect frees: ===\n", len(track.bad_free_array))
				for entry in track.bad_free_array {
					fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
				}
			}
			mem.tracking_allocator_destroy(&track)
		}
	}

	a := make([dynamic]int)
	append(&a, 0)
	defer delete(a) // コメントアウトするとメモリーリークが発生する

}
```
##### テンプアロケーター
```go
package main

// テンプアロケーター: サイズが不足したらサイズが勝手に伸びるアリーナアロケーター
// a scratch allocator (a growing arena based allocator)

main :: proc() {

	context.allocator = context.temp_allocator
	defer free_all(context.temp_allocator)

}
```
##### ヒープを利用したアリーナアロケーター
```go
package main

import "core:mem"

// ヒープを利用したアリーナアロケーター: ヒープ上にメモリーを置く + サイズは固定(伸縮不可)

main :: proc() {

	block_heap_memory := make([]byte, 2 * mem.Megabyte)
	assert(block_heap_memory != nil)
	defer delete(block_heap_memory)

	arena_heap: mem.Arena

	mem.arena_init(&arena_heap, block_heap_memory[:])

	heap_allocator := mem.arena_allocator(&arena_heap)

	context.allocator = heap_allocator
	defer free_all(heap_allocator)


	a := make([dynamic]int)
	append(&a, 1)

	assert(block_heap_memory[0] == 1)
}
```
##### スタックを利用したアリーナアロケーター
```go
package main

import "core:mem"

// スタックを利用したアリーナアロケーター: メモリーをヒープ上に置くヒープベースのアロケーターのスタック版

main :: proc() {

	block_stack_buffer: [512]byte

	arena_stack: mem.Arena

	mem.arena_init(&arena_stack, block_stack_buffer[:])

	stack_allocator := mem.arena_allocator(&arena_stack)

	context.allocator = stack_allocator
	defer free_all(stack_allocator)

	a := make([dynamic]int)
	append(&a, 1)

	assert(block_stack_buffer[0] == 1)
}
```
- [詳細: Discord Link](https://discord.com/channels/568138951836172421/568871298428698645/1198756934375977081)

#### Explicit/Implicit parametric polymorphism (parapoly)

##### proc
```go
square :: proc($N: $T) -> (res: T) {
	res = N * N
	return
}

main :: proc() {
	{
		a := square(2)
		fmt.printf("%v %v\n", typeid_of(type_of(a)), a)
	}
	{
		a := square(2.3)
		fmt.printf("%v %v\n", typeid_of(type_of(a)), a)
	}
}

// int 4
// f64 5.289999999999999
```
##### struct
```go
S :: struct($Key, $Value: typeid) {
	key:   Key,
	value: Value,
}

main :: proc() {
	{
		a := S(string, int){"foobar", 1}

		// a := S(string, int) {
		// 	key   = "foobar",
		// 	value = 1,
		// }

		// a: S(string, int)
		// a.key = "foobar"
		// a.value = 1

		fmt.printf("%v\n", a)
	}
}

// S($Key=string, $Value=int){key = "foobar", value = 1}
```
##### union
```go
Error :: enum {
	Error1,
	Error2,
}

U :: union($T: typeid) {
	T,
	Error,
}

main :: proc() {

	{
		a: U(int)
		a = 1
		// or
		// a = .Error1

		fmt.printf("%v\n", a)
	}
}

// 1
```

#### Pointer

```go
package main

import "core:fmt"
import "core:mem"

pointer1 :: proc() {
	ptr: ^int
	if ptr == nil do fmt.println("nil")
	var := 0
	fmt.println("var =", var)
	ptr = &var
	ptr^ = 9999
	fmt.println("var =", var)
}

pointer2 :: proc() {
	var := 0
	ptr := &var
	ptrptr := &ptr
	ptrptr^^ = 9999
	fmt.println("var =", var)
}

pointer3 :: proc() {
	arr := [?]int{1, 2, 3, 4, 5}
	ptr := &arr[0]
	fmt.println("arr[0] =", ptr^)
	fmt.println("arr[1] =", mem.ptr_offset(ptr, 1)^)
	fmt.println("arr[4] =", mem.ptr_offset(ptr, 4)^)
	// fmt.println("arr[5] =", mem.ptr_offset(ptr, 5)^) // out of range
}

pointer4 :: proc() {
	arr := [?]i32{1, 2, 3, 4, 5}
	start := &arr[0]
	end := &arr[4]
	fmt.println(start^, end^)
	fmt.println(&start, &end)
	fmt.println(mem.ptr_sub(start, end))
	fmt.println(mem.ptr_sub(end, start))
}

main :: proc() {

	fmt.println(">> Pointer 1")
	pointer1()
	fmt.println(">> Pointer 2")
	pointer2()
	fmt.println(">> Pointer 3")
	pointer3()
	fmt.println(">> Pointer 4")
	pointer4()

}

// >> Pointer 1
// nil
// var = 0
// var = 9999
// >> Pointer 2
// var = 9999
// >> Pointer 3
// arr[0] = 1
// arr[1] = 2
// arr[4] = 5
// >> Pointer 4
// 1 5
// 0x4A0CEFF598 0x4A0CEFF590
// -4
// 4
```