diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-09-23 19:45:45 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-09-23 19:45:45 +0100 |
| commit | fa7d7938e1faeed446d22cdc65bb072620b8d35a (patch) | |
| tree | 496f4a6a12ec5cd676499ad61a9a85898471edc4 /code/old_demos | |
| parent | a31bab5aae10757f5029b00e39beb0e3815b92b1 (diff) | |
Fix push_* with better defer system
Diffstat (limited to 'code/old_demos')
| -rw-r--r-- | code/old_demos/demo001.odin | 334 | ||||
| -rw-r--r-- | code/old_demos/old_runtime.odin | 412 |
2 files changed, 746 insertions, 0 deletions
diff --git a/code/old_demos/demo001.odin b/code/old_demos/demo001.odin new file mode 100644 index 000000000..7418ad137 --- /dev/null +++ b/code/old_demos/demo001.odin @@ -0,0 +1,334 @@ +#import "fmt.odin" +#import "os.odin" +#import "mem.odin" +// #import "http_test.odin" as ht +// #import "game.odin" as game +// #import "punity.odin" as pn + +main :: proc() { + // struct_padding() + // bounds_checking() + // type_introspection() + // any_type() + // crazy_introspection() + // namespaces_and_files() + // miscellany() + // ht.run() + // game.run() + // { + // init :: proc(c: ^pn.Core) {} + // step :: proc(c: ^pn.Core) {} + + // pn.run(init, step) + // } +} + +struct_padding :: proc() { + { + A :: struct { + a: u8 + b: u32 + c: u16 + } + + B :: struct { + a: [7]u8 + b: [3]u16 + c: u8 + d: u16 + } + + fmt.println("size_of(A):", size_of(A)) + fmt.println("size_of(B):", size_of(B)) + + // n.b. http://cbloomrants.blogspot.co.uk/2012/07/07-23-12-structs-are-not-what-you-want.html + } + { + A :: struct #ordered { + a: u8 + b: u32 + c: u16 + } + + B :: struct #ordered { + a: [7]u8 + b: [3]u16 + c: u8 + d: u16 + } + + fmt.println("size_of(A):", size_of(A)) + fmt.println("size_of(B):", size_of(B)) + + // C-style structure layout + } + { + A :: struct #packed { + a: u8 + b: u32 + c: u16 + } + + B :: struct #packed { + a: [7]u8 + b: [3]u16 + c: u8 + d: u16 + } + + fmt.println("size_of(A):", size_of(A)) + fmt.println("size_of(B):", size_of(B)) + + // Useful for explicit layout + } + + // Member sorting by priority + // Alignment desc. + // Size desc. + // source order asc. + + /* + A :: struct { + a: u8 + b: u32 + c: u16 + } + + B :: struct { + a: [7]u8 + b: [3]u16 + c: u8 + d: u16 + } + + Equivalent too + + A :: struct #ordered { + b: u32 + c: u16 + a: u8 + } + + B :: struct #ordered { + b: [3]u16 + d: u16 + a: [7]u8 + c: u8 + } + */ +} + +bounds_checking :: proc() { + x: [4]int + // x[-1] = 0; // Compile Time + // x[4] = 0; // Compile Time + + { + a, b := -1, 4; + // x[a] = 0; // Runtime Time + // x[b] = 0; // Runtime Time + } + + // Works for arrays, strings, slices, and related procedures & operations + + { + base: [10]int + s := base[2:6] + a, b := -1, 6 + + #no_bounds_check { + s[a] = 0; + // #bounds_check s[b] = 0; + } + + #no_bounds_check + if s[a] == 0 { + // Do whatever + } + + // Bounds checking can be toggled explicit + // on a per statement basis. + // _any statement_ + } +} + +type_introspection :: proc() { + { + info: ^Type_Info + x: int + + info = type_info(int) // by type + info = type_info_of_val(x) // by value + // See: runtime.odin + + match type i : info { + case Type_Info.Integer: + fmt.println("integer!") + case Type_Info.Float: + fmt.println("float!") + default: + fmt.println("potato!") + } + + // Unsafe cast + integer_info := info as ^Type_Info.Integer + } + + { + Vector2 :: struct { x, y: f32 } + Vector3 :: struct { x, y, z: f32 } + + v1: Vector2 + v2: Vector3 + v3: Vector3 + + t1 := type_info_of_val(v1) + t2 := type_info_of_val(v2) + t3 := type_info_of_val(v3) + + fmt.println() + fmt.print("Type of v1 is:\n\t", t1) + + fmt.println() + fmt.print("Type of v2 is:\n\t", t2) + + fmt.println("\n") + fmt.println("t1 == t2:", t1 == t2) + fmt.println("t2 == t3:", t2 == t3) + } +} + +any_type :: proc() { + a: any + + x: int = 123 + y: f64 = 6.28 + z: string = "Yo-Yo Ma" + // All types can be implicit cast to `any` + a = x + a = y + a = z + a = a // This the "identity" type, it doesn't get converted + + a = 123 // Literals are copied onto the stack first + + // any has two members + // data - rawptr to the data + // type_info - pointer to the type info + + fmt.println(x, y, z) + // See: fmt.odin + // For variadic any procedures in action +} + +crazy_introspection :: proc() { + { + Fruit :: enum { + APPLE, + BANANA, + GRAPE, + MELON, + PEACH, + TOMATO, + } + + s: string + s = enum_to_string(Fruit.PEACH) + fmt.println(s) + + f := Fruit.GRAPE + s = enum_to_string(f) + fmt.println(s) + + fmt.println(f) + // See: runtime.odin + } + + + { + // NOTE(bill): This is not safe code and I would not recommend this at all + // I'd recommend you use `match type` to get the subtype rather than + // casting pointers + + Fruit :: enum { + APPLE, + BANANA, + GRAPE, + MELON, + PEACH, + TOMATO, + } + + fruit_ti := type_info(Fruit) + name := (fruit_ti as ^Type_Info.Named).name // Unsafe casts + info := type_info_base(fruit_ti) as ^Type_Info.Enum // Unsafe casts + + fmt.printf("% :: enum % {\n", name, info.base); + for i := 0; i < info.values.count; i++ { + fmt.printf("\t%\t= %,\n", info.names[i], info.values[i]) + } + fmt.printf("}\n") + + // NOTE(bill): look at that type-safe printf! + } + + { + Vector3 :: struct {x, y, z: f32} + + a := Vector3{x = 1, y = 4, z = 9} + fmt.println(a) + b := Vector3{x = 9, y = 3, z = 1} + fmt.println(b) + + // NOTE(bill): See fmt.odin + } + + // n.b. This pretty much "solves" serialization (to strings) +} + +// #import "test.odin" + +namespaces_and_files :: proc() { + + // test.thing() + // test.format.println() + // test.println() + /* + // Non-exporting import + #import "file.odin" + #import "file.odin" as file + #import "file.odin" as . + #import "file.odin" as _ + + // Exporting import + #load "file.odin" + */ + + // Talk about scope rules and diagram +} + +miscellany :: proc() { + /* + win32 `__imp__` prefix + #dll_import + #dll_export + + Change exported name/symbol for linking + #link_name + + Custom calling conventions + #stdcall + #fastcall + + Runtime stuff + #shared_global_scope + */ + + // assert(false) + // compile_assert(false) + // panic("Panic message goes here") +} + + + + diff --git a/code/old_demos/old_runtime.odin b/code/old_demos/old_runtime.odin new file mode 100644 index 000000000..af788f11d --- /dev/null +++ b/code/old_demos/old_runtime.odin @@ -0,0 +1,412 @@ +#load "win32.odin" + +assume :: proc(cond: bool) #foreign "llvm.assume" + +__debug_trap :: proc() #foreign "llvm.debugtrap" +__trap :: proc() #foreign "llvm.trap" +read_cycle_counter :: proc() -> u64 #foreign "llvm.readcyclecounter" + +bit_reverse16 :: proc(b: u16) -> u16 #foreign "llvm.bitreverse.i16" +bit_reverse32 :: proc(b: u32) -> u32 #foreign "llvm.bitreverse.i32" +bit_reverse64 :: proc(b: u64) -> u64 #foreign "llvm.bitreverse.i64" + +byte_swap16 :: proc(b: u16) -> u16 #foreign "llvm.bswap.i16" +byte_swap32 :: proc(b: u32) -> u32 #foreign "llvm.bswap.i32" +byte_swap64 :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64" + +fmuladd_f32 :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32" +fmuladd_f64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64" + +// TODO(bill): make custom heap procedures +heap_alloc :: proc(len: int) -> rawptr #foreign "malloc" +heap_dealloc :: proc(ptr: rawptr) #foreign "free" + +memory_zero :: proc(data: rawptr, len: int) { + d := slice_ptr(data as ^byte, len) + for i := 0; i < len; i++ { + d[i] = 0 + } +} + +memory_compare :: proc(dst, src: rawptr, len: int) -> int { + s1, s2: ^byte = dst, src + for i := 0; i < len; i++ { + a := ptr_offset(s1, i)^ + b := ptr_offset(s2, i)^ + if a != b { + return (a - b) as int + } + } + return 0 +} + +memory_copy :: proc(dst, src: rawptr, n: int) #inline { + if dst == src { + return + } + + v128b :: type {4}u32 + compile_assert(align_of(v128b) == 16) + + d, s: ^byte = dst, src + + for ; s as uint % 16 != 0 && n != 0; n-- { + d^ = s^ + d, s = ptr_offset(d, 1), ptr_offset(s, 1) + } + + if d as uint % 16 == 0 { + for ; n >= 16; d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 { + (d as ^v128b)^ = (s as ^v128b)^ + } + + if n&8 != 0 { + (d as ^u64)^ = (s as ^u64)^ + d, s = ptr_offset(d, 8), ptr_offset(s, 8) + } + if n&4 != 0 { + (d as ^u32)^ = (s as ^u32)^; + d, s = ptr_offset(d, 4), ptr_offset(s, 4) + } + if n&2 != 0 { + (d as ^u16)^ = (s as ^u16)^ + d, s = ptr_offset(d, 2), ptr_offset(s, 2) + } + if n&1 != 0 { + d^ = s^ + d, s = ptr_offset(d, 1), ptr_offset(s, 1) + } + return; + } + + // IMPORTANT NOTE(bill): Little endian only + LS :: proc(a, b: u32) -> u32 #inline { return a << b } + RS :: proc(a, b: u32) -> u32 #inline { return a >> b } + /* NOTE(bill): Big endian version + LS :: proc(a, b: u32) -> u32 #inline { return a >> b; } + RS :: proc(a, b: u32) -> u32 #inline { return a << b; } + */ + + w, x: u32 + + if d as uint % 4 == 1 { + w = (s as ^u32)^ + d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1) + d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1) + d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1) + n -= 3 + + for n > 16 { + d32 := d as ^u32 + s32 := ptr_offset(s, 1) as ^u32 + x = s32^; d32^ = LS(w, 24) | RS(x, 8) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + w = s32^; d32^ = LS(x, 24) | RS(w, 8) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + x = s32^; d32^ = LS(w, 24) | RS(x, 8) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + w = s32^; d32^ = LS(x, 24) | RS(w, 8) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + + d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 + } + + } else if d as uint % 4 == 2 { + w = (s as ^u32)^ + d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1) + d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1) + n -= 2 + + for n > 17 { + d32 := d as ^u32 + s32 := ptr_offset(s, 2) as ^u32 + x = s32^; d32^ = LS(w, 16) | RS(x, 16) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + w = s32^; d32^ = LS(x, 16) | RS(w, 16) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + x = s32^; d32^ = LS(w, 16) | RS(x, 16) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + w = s32^; d32^ = LS(x, 16) | RS(w, 16) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + + d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 + } + + } else if d as uint % 4 == 3 { + w = (s as ^u32)^ + d^ = s^ + n -= 1 + + for n > 18 { + d32 := d as ^u32 + s32 := ptr_offset(s, 3) as ^u32 + x = s32^; d32^ = LS(w, 8) | RS(x, 24) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + w = s32^; d32^ = LS(x, 8) | RS(w, 24) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + x = s32^; d32^ = LS(w, 8) | RS(x, 24) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + w = s32^; d32^ = LS(x, 8) | RS(w, 24) + d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) + + d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 + } + } + + if n&16 != 0 { + (d as ^v128b)^ = (s as ^v128b)^ + d, s = ptr_offset(d, 16), ptr_offset(s, 16) + } + if n&8 != 0 { + (d as ^u64)^ = (s as ^u64)^ + d, s = ptr_offset(d, 8), ptr_offset(s, 8) + } + if n&4 != 0 { + (d as ^u32)^ = (s as ^u32)^; + d, s = ptr_offset(d, 4), ptr_offset(s, 4) + } + if n&2 != 0 { + (d as ^u16)^ = (s as ^u16)^ + d, s = ptr_offset(d, 2), ptr_offset(s, 2) + } + if n&1 != 0 { + d^ = s^ + } +} + +memory_move :: proc(dst, src: rawptr, n: int) #inline { + d, s: ^byte = dst, src + if d == s { + return + } + if d >= ptr_offset(s, n) || ptr_offset(d, n) <= s { + memory_copy(d, s, n) + return + } + + // TODO(bill): Vectorize the shit out of this + if d < s { + if s as int % size_of(int) == d as int % size_of(int) { + for d as int % size_of(int) != 0 { + if n == 0 { + return + } + n-- + d^ = s^ + d, s = ptr_offset(d, 1), ptr_offset(s, 1) + } + di, si := d as ^int, s as ^int + for n >= size_of(int) { + di^ = si^ + di, si = ptr_offset(di, 1), ptr_offset(si, 1) + n -= size_of(int) + } + } + for ; n > 0; n-- { + d^ = s^ + d, s = ptr_offset(d, 1), ptr_offset(s, 1) + } + } else { + if s as int % size_of(int) == d as int % size_of(int) { + for ptr_offset(d, n) as int % size_of(int) != 0 { + if n == 0 { + return + } + n-- + d^ = s^ + d, s = ptr_offset(d, 1), ptr_offset(s, 1) + } + for n >= size_of(int) { + n -= size_of(int) + di := ptr_offset(d, n) as ^int + si := ptr_offset(s, n) as ^int + di^ = si^ + } + for ; n > 0; n-- { + d^ = s^ + d, s = ptr_offset(d, 1), ptr_offset(s, 1) + } + } + for n > 0 { + n-- + dn := ptr_offset(d, n) + sn := ptr_offset(s, n) + dn^ = sn^ + } + } +} + +__string_eq :: proc(a, b: string) -> bool { + if len(a) != len(b) { + return false + } + if ^a[0] == ^b[0] { + return true + } + return memory_compare(^a[0], ^b[0], len(a)) == 0 +} + +__string_cmp :: proc(a, b : string) -> int { + min_len := len(a) + if len(b) < min_len { + min_len = len(b) + } + for i := 0; i < min_len; i++ { + x := a[i] + y := b[i] + if x < y { + return -1 + } else if x > y { + return +1 + } + } + + if len(a) < len(b) { + return -1 + } else if len(a) > len(b) { + return +1 + } + return 0 +} + +__string_ne :: proc(a, b : string) -> bool #inline { return !__string_eq(a, b) } +__string_lt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) < 0 } +__string_gt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > 0 } +__string_le :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) <= 0 } +__string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >= 0 } + + + + +Allocation_Mode :: type enum { + ALLOC, + DEALLOC, + DEALLOC_ALL, + RESIZE, +} + + + +Allocator_Proc :: type proc(allocator_data: rawptr, mode: Allocation_Mode, + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64) -> rawptr + +Allocator :: type struct { + procedure: Allocator_Proc; + data: rawptr +} + + +Context :: type struct { + thread_ptr: rawptr + + user_data: rawptr + user_index: int + + allocator: Allocator +} + +#thread_local context: Context + +DEFAULT_ALIGNMENT :: 2*size_of(int) + + +__check_context :: proc() { + if context.allocator.procedure == null { + context.allocator = __default_allocator() + } + if context.thread_ptr == null { + // TODO(bill): + // context.thread_ptr = current_thread_pointer() + } +} + + +alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT) } + +alloc_align :: proc(size, alignment: int) -> rawptr #inline { + __check_context() + a := context.allocator + return a.procedure(a.data, Allocation_Mode.ALLOC, size, alignment, null, 0, 0) +} + +dealloc :: proc(ptr: rawptr) #inline { + __check_context() + a := context.allocator + _ = a.procedure(a.data, Allocation_Mode.DEALLOC, 0, 0, ptr, 0, 0) +} +dealloc_all :: proc(ptr: rawptr) #inline { + __check_context() + a := context.allocator + _ = a.procedure(a.data, Allocation_Mode.DEALLOC_ALL, 0, 0, ptr, 0, 0) +} + + +resize :: proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT) } +resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr #inline { + __check_context() + a := context.allocator + return a.procedure(a.data, Allocation_Mode.RESIZE, new_size, alignment, ptr, old_size, 0) +} + + + +default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr { + if old_memory == null { + return alloc_align(new_size, alignment) + } + + if new_size == 0 { + dealloc(old_memory) + return null + } + + if new_size == old_size { + return old_memory + } + + new_memory := alloc_align(new_size, alignment) + if new_memory == null { + return null + } + + memory_copy(new_memory, old_memory, min(old_size, new_size)); + dealloc(old_memory) + return new_memory +} + + +__default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocation_Mode, + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64) -> rawptr { + using Allocation_Mode + match mode { + case ALLOC: + return heap_alloc(size) + case RESIZE: + return default_resize_align(old_memory, old_size, size, alignment) + case DEALLOC: + heap_dealloc(old_memory) + case DEALLOC_ALL: + // NOTE(bill): Does nothing + } + + return null +} + +__default_allocator :: proc() -> Allocator { + return Allocator{ + __default_allocator_proc, + null, + } +} + + + + +__assert :: proc(msg: string) { + file_write(file_get_standard(File_Standard.ERROR), msg as []byte) + // TODO(bill): Which is better? + // __trap() + __debug_trap() +} |