diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-09-13 12:11:52 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-09-13 14:04:05 +0100 |
| commit | 817ae643c5a469bf2f237525086288a2632fa500 (patch) | |
| tree | 7d6e012b11bd76aeb62898f7311bd7bbeeaea256 /code | |
| parent | 59fb74d2a2706898cca60e35874ecd2477202e71 (diff) | |
Remove len(), cap() and replace with selectors; fix defer in match
Diffstat (limited to 'code')
| -rw-r--r-- | code/demo.odin | 8 | ||||
| -rw-r--r-- | code/file.odin | 4 | ||||
| -rw-r--r-- | code/print.odin | 226 | ||||
| -rw-r--r-- | code/runtime.odin | 169 |
4 files changed, 276 insertions, 131 deletions
diff --git a/code/demo.odin b/code/demo.odin index 64af72d26..b15888012 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,6 +1,10 @@ #load "basic.odin" main :: proc() { - println("% % % %", "Hellope", true, 6.28, [4]int{1, 2, 3, 4}) - println("%0 %1 %0", "Hellope", 34) + println("% % % %", "Hellope", true, 6.28, {4}int{1, 2, 3, 4}) + x: struct #ordered { + x, y: int + z: f32 + } + println("%", x) } diff --git a/code/file.odin b/code/file.odin index dc97e909e..a424e6d73 100644 --- a/code/file.odin +++ b/code/file.odin @@ -31,7 +31,7 @@ file_close :: proc(f: ^File) { file_write :: proc(f: ^File, buf: []byte) -> bool { bytes_written: i32 - return WriteFile(f.handle, ^buf[0], len(buf) as i32, ^bytes_written, null) != 0 + return WriteFile(f.handle, ^buf[0], buf.count as i32, ^bytes_written, null) != 0 } File_Standard :: type enum { @@ -95,7 +95,7 @@ read_entire_file :: proc(name: string) -> (string, bool) { ReadFile(f.handle as HANDLE, ^data[total_read], to_read, ^single_read_length, null) if single_read_length <= 0 { - delete(data) + free(^data[0]) return "", false } diff --git a/code/print.odin b/code/print.odin index 2a32f3c9e..01a972ebb 100644 --- a/code/print.odin +++ b/code/print.odin @@ -3,22 +3,12 @@ #load "file.odin" print_byte_buffer :: proc(buf: ^[]byte, b: []byte) { - // NOTE(bill): This is quite a hack - // TODO(bill): Should I allow the raw editing of a slice by exposing its - // internal members? - Raw_Bytes :: struct #ordered { - data: ^byte - len: int - cap: int - } - - slice := buf as ^Raw_Bytes - if slice.len < slice.cap { - n := min(slice.cap-slice.len, len(b)) + if buf.count < buf.capacity { + n := min(buf.capacity-buf.count, b.count) if n > 0 { - offset := ptr_offset(slice.data, slice.len) + offset := ptr_offset(buf.data, buf.count) memory_copy(offset, ^b[0], n) - slice.len += n + buf.count += n } } } @@ -29,7 +19,7 @@ print_string_to_buffer :: proc(buf: ^[]byte, s: string) { byte_reverse :: proc(b: []byte) { - n := len(b) + n := b.count for i := 0; i < n/2; i++ { b[i], b[n-1-i] = b[n-1-i], b[i] } @@ -184,6 +174,128 @@ print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) { } } +print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) { + if ti == null { return } + + using Type_Info + match type info : ti { + case Named: + print_string_to_buffer(buf, info.name) + case Integer: + match { + case ti == type_info(int): + print_string_to_buffer(buf, "int") + case ti == type_info(uint): + print_string_to_buffer(buf, "uint") + default: + if info.signed { + print_string_to_buffer(buf, "i") + } else { + print_string_to_buffer(buf, "u") + } + print_int_to_buffer(buf, 8*info.size) + } + + case Float: + match info.size { + case 4: print_string_to_buffer(buf, "f32") + case 8: print_string_to_buffer(buf, "f64") + } + case String: print_string_to_buffer(buf, "string") + case Boolean: print_string_to_buffer(buf, "bool") + case Pointer: + print_string_to_buffer(buf, "^") + print_type_to_buffer(buf, info.elem) + case Procedure: + print_string_to_buffer(buf, "proc") + if info.params == null { + print_string_to_buffer(buf, "()") + } else { + count := (info.params as ^Tuple).fields.count + if count == 1 { print_string_to_buffer(buf, "(") } + print_type_to_buffer(buf, info.params) + if count == 1 { print_string_to_buffer(buf, ")") } + } + if info.results != null { + print_string_to_buffer(buf, " -> ") + print_type_to_buffer(buf, info.results) + } + case Tuple: + count := info.fields.count + if count != 1 { print_string_to_buffer(buf, "(") } + for i := 0; i < count; i++ { + if i > 0 { print_string_to_buffer(buf, ", ") } + + f := info.fields[i] + + if f.name.count > 0 { + print_string_to_buffer(buf, f.name) + print_string_to_buffer(buf, ": ") + } + print_type_to_buffer(buf, f.type_info) + } + if count != 1 { print_string_to_buffer(buf, ")") } + + case Array: + print_string_to_buffer(buf, "[") + print_int_to_buffer(buf, info.count) + print_string_to_buffer(buf, "]") + print_type_to_buffer(buf, info.elem) + case Slice: + print_string_to_buffer(buf, "[") + print_string_to_buffer(buf, "]") + print_type_to_buffer(buf, info.elem) + case Vector: + print_string_to_buffer(buf, "{") + print_int_to_buffer(buf, info.count) + print_string_to_buffer(buf, "}") + print_type_to_buffer(buf, info.elem) + + case Struct: + print_string_to_buffer(buf, "struct ") + if info.packed { print_string_to_buffer(buf, "#packed ") } + if info.ordered { print_string_to_buffer(buf, "#ordered ") } + print_string_to_buffer(buf, "{") + for i := 0; i < info.fields.count; i++ { + if i > 0 { + print_string_to_buffer(buf, ", ") + } + print_any_to_buffer(buf, info.fields[i].name) + print_string_to_buffer(buf, ": ") + print_type_to_buffer(buf, info.fields[i].type_info) + } + print_string_to_buffer(buf, "}") + + case Union: + print_string_to_buffer(buf, "union {") + for i := 0; i < info.fields.count; i++ { + if i > 0 { + print_string_to_buffer(buf, ", ") + } + print_any_to_buffer(buf, info.fields[i].name) + print_string_to_buffer(buf, ": ") + print_type_to_buffer(buf, info.fields[i].type_info) + } + print_string_to_buffer(buf, "}") + + case Raw_Union: + print_string_to_buffer(buf, "raw_union {") + for i := 0; i < info.fields.count; i++ { + if i > 0 { + print_string_to_buffer(buf, ", ") + } + print_any_to_buffer(buf, info.fields[i].name) + print_string_to_buffer(buf, ": ") + print_type_to_buffer(buf, info.fields[i].type_info) + } + print_string_to_buffer(buf, "}") + + case Enum: + print_string_to_buffer(buf, "enum ") + print_type_to_buffer(buf, info.base) + print_string_to_buffer(buf, "{}") + } +} print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { @@ -197,7 +309,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { case Struct: print_string_to_buffer(buf, info.name) print_string_to_buffer(buf, "{") - for i := 0; i < len(b.fields); i++ { + for i := 0; i < b.fields.count; i++ { f := b.fields[i]; if i > 0 { print_string_to_buffer(buf, ", ") @@ -282,7 +394,9 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { case Array: print_string_to_buffer(buf, "[") - for i := 0; i < info.len; i++ { + defer print_string_to_buffer(buf, "]") + + for i := 0; i < info.count; i++ { if i > 0 { print_string_to_buffer(buf, ", ") } @@ -292,55 +406,66 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { elem.type_info = info.elem print_any_to_buffer(buf, elem) } - print_string_to_buffer(buf, "]") case Slice: - slice := arg.data as ^struct { data: rawptr; len, cap: int } + slice := arg.data as ^[]byte print_string_to_buffer(buf, "[") - for i := 0; i < slice.len; i++ { + defer print_string_to_buffer(buf, "]") + + for i := 0; i < slice.count; i++ { if i > 0 { print_string_to_buffer(buf, ", ") } elem: any - elem.data = (slice.data as int + i*info.elem_size) as rawptr + elem.data = ptr_offset(slice.data, i*info.elem_size) elem.type_info = info.elem print_any_to_buffer(buf, elem) } - print_string_to_buffer(buf, "]") case Vector: print_string_to_buffer(buf, "<") - for i := 0; i < info.len; i++ { + defer print_string_to_buffer(buf, ">") + + for i := 0; i < info.count; i++ { if i > 0 { print_string_to_buffer(buf, ", ") } elem: any - elem.data = (arg.data as int + i*info.elem_size) as rawptr + elem.data = ptr_offset(arg.data as ^byte, i*info.elem_size) elem.type_info = info.elem print_any_to_buffer(buf, elem) } - print_string_to_buffer(buf, ">") case Struct: - print_string_to_buffer(buf, "(struct ") - for i := 0; i < len(info.fields); i++ { + print_string_to_buffer(buf, "struct") + print_string_to_buffer(buf, "{") + defer print_string_to_buffer(buf, "}") + + for i := 0; i < info.fields.count; i++ { if i > 0 { print_string_to_buffer(buf, ", ") } print_any_to_buffer(buf, info.fields[i].name) + print_string_to_buffer(buf, " = ") + a: any + a.data = ptr_offset(arg.data as ^byte, info.fields[i].offset) + a.type_info = info.fields[i].type_info + print_any_to_buffer(buf, a) } - print_string_to_buffer(buf, ")") - case Union: print_string_to_buffer(buf, "(union)") - case Raw_Union: print_string_to_buffer(buf, "(raw_union)") + + case Union: + print_string_to_buffer(buf, "(union)") + case Raw_Union: + print_string_to_buffer(buf, "(raw_union)") case Procedure: - print_string_to_buffer(buf, "(procedure 0x") + print_type_to_buffer(buf, arg.type_info) + print_string_to_buffer(buf, " @ 0x") print_pointer_to_buffer(buf, (arg.data as ^rawptr)^) - print_string_to_buffer(buf, ")") + default: - print_string_to_buffer(buf, "") } } @@ -373,7 +498,7 @@ print_to_buffer :: proc(buf: ^[]byte, fmt: string, args: ..any) { parse_int :: proc(s: string, offset: int) -> (int, int) { result := 0 - for ; offset < len(s); offset++ { + for ; offset < s.count; offset++ { c := s[offset] as rune if !is_digit(c) { break @@ -389,8 +514,9 @@ print_to_buffer :: proc(buf: ^[]byte, fmt: string, args: ..any) { prev := 0 implicit_index := 0 - for i := 0; i < len(fmt); i++ { + for i := 0; i < fmt.count; i++ { r := fmt[i] as rune + index := implicit_index if r != #rune "%" { continue @@ -398,26 +524,22 @@ print_to_buffer :: proc(buf: ^[]byte, fmt: string, args: ..any) { print_string_to_buffer(buf, fmt[prev:i]) i++ // Skip % - if i >= len(fmt) { - return - } - - next := fmt[i] as rune - if next == #rune "%" { - print_string_to_buffer(buf, "%") - i++ - prev = i - continue - } - - index := implicit_index - set_prev := true + if i < fmt.count { + next := fmt[i] as rune + + if next == #rune "%" { + print_string_to_buffer(buf, "%") + i++ + prev = i + continue + } - if is_digit(next) { - index, i = parse_int(fmt, i) + if is_digit(next) { + index, i = parse_int(fmt, i) + } } - if 0 <= index && index < len(args) { + if 0 <= index && index < args.count { print_any_to_buffer(buf, args[index]) implicit_index = index+1 } else { diff --git a/code/runtime.odin b/code/runtime.odin index 5f42c39c5..21a00c8b9 100644 --- a/code/runtime.odin +++ b/code/runtime.odin @@ -11,6 +11,8 @@ Type_Info :: union { } Record :: struct #ordered { fields: []Member + packed: bool + ordered: bool } @@ -38,7 +40,7 @@ Type_Info :: union { Array: struct #ordered { elem: ^Type_Info elem_size: int - len: int + count: int } Slice: struct #ordered { elem: ^Type_Info @@ -47,7 +49,7 @@ Type_Info :: union { Vector: struct #ordered { elem: ^Type_Info elem_size: int - len: int + count: int } Tuple: Record Struct: Record @@ -81,7 +83,7 @@ heap_alloc :: proc(len: int) -> rawptr { return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len) } -heap_dealloc :: proc(ptr: rawptr) { +heap_free :: proc(ptr: rawptr) { _ = HeapFree(GetProcessHeap(), 0, ptr) } @@ -108,18 +110,18 @@ memory_copy :: proc(dst, src: rawptr, len: int) #inline { } __string_eq :: proc(a, b: string) -> bool { - if len(a) != len(b) { + if a.count != b.count { return false } if ^a[0] == ^b[0] { return true } - return memory_compare(^a[0], ^b[0], len(a)) == 0 + return memory_compare(^a[0], ^b[0], a.count) == 0 } __string_cmp :: proc(a, b : string) -> int { // Translation of http://mgronhol.github.io/fast-strcmp/ - n := min(len(a), len(b)) + n := min(a.count, b.count) fast := n/size_of(int) + 1 offset := (fast-1)*size_of(int) @@ -159,20 +161,64 @@ __string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > +__assert :: proc(msg: string) { + file_write(file_get_standard(File_Standard.ERROR), msg as []byte) + __debug_trap() +} -Allocation_Mode :: enum { - ALLOC, - DEALLOC, - DEALLOC_ALL, - RESIZE, +__bounds_check_error :: proc(file: string, line, column: int, + index, count: int) { + if 0 <= index && index < count { + return + } + // TODO(bill): Probably reduce the need for `print` in the runtime if possible + println_err("%(%:%) Index % is out of bounds range [0, %)", + file, line, column, index, count) + __debug_trap() +} + +__slice_expr_error :: proc(file: string, line, column: int, + low, high, max: int) { + if 0 <= low && low <= high && high <= max { + return + } + println_err("%(%:%) Invalid slice indices: [%:%:%]", + file, line, column, low, high, max) + __debug_trap() } +__substring_expr_error :: proc(file: string, line, column: int, + low, high: int) { + if 0 <= low && low <= high { + return + } + println_err("%(%:%) Invalid substring indices: [%:%:%]", + file, line, column, low, high) + __debug_trap() +} + + + + + + + + + -Allocator_Proc :: type proc(allocator_data: rawptr, mode: Allocation_Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, flags: u64) -> rawptr Allocator :: struct { - procedure: Allocator_Proc; + Mode :: enum { + ALLOC, + FREE, + FREE_ALL, + RESIZE, + } + Proc :: type proc(allocator_data: rawptr, mode: Mode, + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64) -> rawptr + + + procedure: Proc; data: rawptr } @@ -180,24 +226,26 @@ Allocator :: struct { Context :: struct { thread_ptr: rawptr + allocator: Allocator + user_data: rawptr user_index: int - - allocator: Allocator } -#thread_local context: Context +#thread_local __context: Context + DEFAULT_ALIGNMENT :: 2*size_of(int) -__check_context :: proc() { - if context.allocator.procedure == null { - context.allocator = __default_allocator() +__check_context :: proc(c: ^Context) { + assert(c != null) + if c.allocator.procedure == null { + c.allocator = __default_allocator() } - if context.thread_ptr == null { + if c.thread_ptr == null { // TODO(bill): - // context.thread_ptr = current_thread_pointer() + // c.thread_ptr = current_thread_pointer() } } @@ -205,28 +253,28 @@ __check_context :: proc() { 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) + __check_context(^__context) + a := __context.allocator + return a.procedure(a.data, Allocator.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) +free :: proc(ptr: rawptr) #inline { + __check_context(^__context) + a := __context.allocator + _ = a.procedure(a.data, Allocator.Mode.FREE, 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) +free_all :: proc() #inline { + __check_context(^__context) + a := __context.allocator + _ = a.procedure(a.data, Allocator.Mode.FREE_ALL, 0, 0, null, 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) + __check_context(^__context) + a := __context.allocator + return a.procedure(a.data, Allocator.Mode.RESIZE, new_size, alignment, ptr, old_size, 0) } @@ -237,7 +285,7 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: } if new_size == 0 { - dealloc(old_memory) + free(old_memory) return null } @@ -251,24 +299,24 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: } memory_copy(new_memory, old_memory, min(old_size, new_size)); - dealloc(old_memory) + free(old_memory) return new_memory } -__default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocation_Mode, +__default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode, size, alignment: int, old_memory: rawptr, old_size: int, flags: u64) -> rawptr { - using Allocation_Mode + using Allocator.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 FREE: + heap_free(old_memory) return null - case DEALLOC_ALL: + case FREE_ALL: // NOTE(bill): Does nothing } @@ -277,40 +325,11 @@ __default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocation_Mode, __default_allocator :: proc() -> Allocator { return Allocator{ - __default_allocator_proc, - null, + procedure = __default_allocator_proc, + data = null, } } -__assert :: proc(msg: string) { - file_write(file_get_standard(File_Standard.ERROR), msg as []byte) - __debug_trap() -} - -__bounds_check_error :: proc(file: string, line, column: int, - index, count: int) { - println_err("%(%:%) Index % is out of bounds range [0, %)", - file, line, column, index, count) - __debug_trap() -} - -__slice_expr_error :: proc(file: string, line, column: int, - low, high, max: int) { - print_err("%(%:%) Invalid slice indices: [%:%:%]\n", - file, line, column, low, high, max) - __debug_trap() -} -__substring_expr_error :: proc(file: string, line, column: int, - low, high: int) { - print_err("%(%:%) Invalid substring indices: [%:%:%]\n", - file, line, column, low, high) - __debug_trap() -} - - - - - |