From 7490ac2cfda3ef24195d98f47580f5d19df22ff2 Mon Sep 17 00:00:00 2001 From: Joseph Battelle Date: Wed, 16 Sep 2020 21:18:25 -0700 Subject: [PATCH 1/9] Fix issue #697 Add `is_type_typeid` check to `does_field_type_allow_using` --- src/check_type.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/check_type.cpp b/src/check_type.cpp index 24434dba0..54cfce614 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -110,6 +110,8 @@ bool does_field_type_allow_using(Type *t) { return true; } else if (is_type_array(t)) { return t->Array.count <= 4; + } else if (is_type_typeid(t)) { + return true; } return false; } From 49eaeccd846868bfa0088f88da190b3ac32799fb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 26 Sep 2020 20:02:24 +0100 Subject: [PATCH 2/9] Remove OS specific stuff from `package path` --- core/path/path.odin | 154 ++------------------------------------------ 1 file changed, 7 insertions(+), 147 deletions(-) diff --git a/core/path/path.odin b/core/path/path.odin index 9c8228d11..986d02d11 100644 --- a/core/path/path.odin +++ b/core/path/path.odin @@ -5,29 +5,14 @@ import "core:runtime" import "core:unicode/utf8" // is_separator checks whether the byte is a valid separator character -is_separator :: proc(c: byte) -> bool { - switch c { - case '/': return true; - case '\\': return ODIN_OS == "windows"; - } - return false; +is_separator :: inline proc(c: byte) -> bool { + return c == '/'; } // is_abs checks whether the path is absolute -is_abs :: proc(path: string) -> bool { - if len(path) > 0 && path[0] == '/' { - return true; - } - when ODIN_OS == "windows" { - if len(path) > 2 { - switch path[0] { - case 'A'..'Z', 'a'..'z': - return path[1] == ':' && is_separator(path[2]); - } - } - } - return false; +is_abs :: inline proc(path: string) -> bool { + return len(path) > 0 && path[0] == '/'; } @@ -51,7 +36,7 @@ base :: proc(path: string, new := false, allocator := context.allocator) -> (las for len(path) > 0 && is_separator(path[len(path)-1]) { path = path[:len(path)-1]; } - if i := strings.last_index_any(path, OS_SEPARATORS); i >= 0 { + if i := strings.last_index(path, "/"); i >= 0 { path = path[i+1:]; } @@ -79,13 +64,13 @@ dir :: proc(path: string, allocator := context.allocator) -> string { // If there is no slash in path, it returns an empty dir and file set to path // The returned values have the property that path = dir+file split :: proc(path: string) -> (dir, file: string) { - i := strings.last_index_any(path, OS_SEPARATORS); + i := strings.last_index(path, "/"); return path[:i+1], path[i+1:]; } // split_elements splits the path elements into slices of the original path string split_elements :: proc(path: string, allocator := context.allocator) -> []string { - return strings.split_multi(path, OS_SEPARATORS_ARRAY, true, allocator); + return strings.split(path, "/", allocator); } // clean returns the shortest path name equivalent to path through lexical analysis only @@ -206,131 +191,6 @@ name :: proc(path: string, new := false, allocator := context.allocator) -> (nam -rel :: proc{rel_between, rel_current}; - -// returns the relative path from one path to another -rel_between :: proc(from, to: string, allocator := context.allocator) -> string { - if from == "" || to == "" { - return ""; - } - - from, to := from, to; - from = full(from, context.temp_allocator); - to = full(to, context.temp_allocator); - - from_is_dir := is_dir(from); - to_is_dir := is_dir(to); - - index, slash := 0, 0; - - for { - if index >= len(from) { - if index >= len(to) || (from_is_dir && index < len(to) && (to[index] == '/' || to[index] == '\\')) { - slash = index; - } - - break; - } - else if index >= len(to) { - if index >= len(from) || (to_is_dir && index < len(from) && (from[index] == '/' || from[index] == '\\')) { - slash = index; - } - - break; - } - - lchar, skip := utf8.decode_rune_in_string(from[index:]); - rchar, _ := utf8.decode_rune_in_string(to[index:]); - - if (lchar == '/' || lchar == '\\') && (rchar == '/' || lchar == '\\') { - slash = index; - } - else if lchar != rchar { - break; - } - - index += skip; - } - - if slash < 1 { - // there is no common path, use the absolute `to` path - return strings.clone(to, allocator); - } - - from_slashes, to_slashes := 0, 0; - - if slash < len(from) { - from = from[slash+1:]; - - if from_is_dir { - from_slashes += 1; - } - } - else { - from = ""; - } - - if slash < len(to) { - to = to[slash+1:]; - - if to_is_dir { - to_slashes += 1; - } - } - else { - to = ""; - } - - for char in from { - if char == '/' || char == '\\' { - from_slashes += 1; - } - } - - for char in to { - if char == '/' || char == '\\' { - to_slashes += 1; - } - } - - if from_slashes == 0 { - buffer := make([]byte, 2 + len(to), allocator); - - buffer[0] = '.'; - buffer[1] = '/'; - copy(buffer[2:], to); - - return string(buffer); - } - else { - buffer := make([]byte, from_slashes*3 + len(to), allocator); - - for i in 0.. string { - return rel_between(current(context.allocator), to, allocator); -} - - - - - - - - /* Lazy_Buffer is a lazily made path buffer When it does allocate, it uses the context.allocator From 0bd38ba1f6281046692bc7344c10d287ea6ec3ef Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 26 Sep 2020 20:17:54 +0100 Subject: [PATCH 3/9] Add some comments to explain what the differences between packages path and path/filepath --- core/path/filepath/path.odin | 2 ++ core/path/path.odin | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/core/path/filepath/path.odin b/core/path/filepath/path.odin index f2dbedf1f..283eb3a9e 100644 --- a/core/path/filepath/path.odin +++ b/core/path/filepath/path.odin @@ -1,3 +1,5 @@ +// The path/filepath package uses either forward slashes or backslashes depending on the operating system +// To process paths usch as URLs that depend on forward slashes regardless of the OS, use the path package package filepath import "core:os" diff --git a/core/path/path.odin b/core/path/path.odin index 986d02d11..abdd213f9 100644 --- a/core/path/path.odin +++ b/core/path/path.odin @@ -1,3 +1,8 @@ +// The path package is only to be used for paths separated by forward slashes, +// e.g. paths in URLs +// +// This package does not deal with Windows/NT paths with volume letters or backslashes +// To manipulate operating system specific paths, use the path/filepath package package path import "core:strings" From b9f511954a70a9dd91cb1d21ff0d4aa1a4da8ebe Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 26 Sep 2020 23:12:04 +0100 Subject: [PATCH 4/9] Make runtime.slice_handle_error explicitly diverging --- core/runtime/error_checks.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/runtime/error_checks.odin b/core/runtime/error_checks.odin index 82d6b7159..d40ac45ca 100644 --- a/core/runtime/error_checks.odin +++ b/core/runtime/error_checks.odin @@ -35,7 +35,7 @@ bounds_check_error :: proc "contextless" (file: string, line, column: int, index handle_error(file, line, column, index, count); } -slice_handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { +slice_handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) -> ! { context = default_context(); fd := os_stderr(); print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); From b9076b0d5b5b2e84926eb85e81bc611597faf06c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 26 Sep 2020 23:16:18 +0100 Subject: [PATCH 5/9] Add `package unicode/utf8/utf8string` for efficient utf8 codepoint indexing to strings --- core/unicode/utf8/utf8string/string.odin | 155 +++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 core/unicode/utf8/utf8string/string.odin diff --git a/core/unicode/utf8/utf8string/string.odin b/core/unicode/utf8/utf8string/string.odin new file mode 100644 index 000000000..a34e754cf --- /dev/null +++ b/core/unicode/utf8/utf8string/string.odin @@ -0,0 +1,155 @@ +package utf8string + +import "core:unicode/utf8" +import "core:runtime" +import "builtin" + +String :: struct { + contents: string, + rune_count: int, + + // cached information + non_ascii: int, // index to non-ascii code points + width: int, // 0 if ascii + byte_pos: int, + rune_pos: int, +} + +@(private) +_len :: builtin.len; // helper procedure + +init :: proc(s: ^String, contents: string) -> ^String { + s.contents = contents; + s.byte_pos = 0; + s.rune_pos = 0; + + for i in 0..<_len(contents) { + if contents[i] >= utf8.RUNE_SELF { + s.rune_count = utf8.rune_count_in_string(contents); + _, s.width = utf8.decode_rune_in_string(contents); + s.non_ascii = i; + return s; + } + } + + s.rune_count = _len(contents); + s.width = 0; + s.non_ascii = _len(contents); + return s; +} + +to_string :: proc(s: ^String) -> string { + return s.contents; +} + +len :: proc(s: ^String) -> int { + return s.rune_count; +} + + +is_ascii :: proc(s: ^String) -> bool { + return s.width == 0; +} + +at :: proc(s: ^String, i: int, loc := #caller_location) -> (r: rune) { + runtime.bounds_check_error_loc(loc, i, s.rune_count); + + if i < s.non_ascii { + return rune(s.contents[i]); + } + + switch i { + case 0: + r, s.width = utf8.decode_rune_in_string(s.contents); + s.rune_pos = 0; + s.byte_pos = 0; + return; + + case s.rune_count-1: + r, s.width = utf8.decode_rune_in_string(s.contents); + s.rune_pos = i; + s.byte_pos = _len(s.contents) - s.width; + return; + + case s.rune_pos-1: + r, s.width = utf8.decode_rune_in_string(s.contents[0:s.byte_pos]); + s.rune_pos = i; + s.byte_pos -= s.width; + return; + + case s.rune_pos+1: + s.rune_pos = i; + s.byte_pos += s.width; + fallthrough; + case s.rune_pos: + r, s.width = utf8.decode_rune_in_string(s.contents[s.byte_pos:]); + return; + } + + // Linear scan + scan_forward := true; + if i < s.rune_pos { + if i < (s.rune_pos-s.non_ascii)/2 { + s.byte_pos, s.rune_pos = s.non_ascii, s.non_ascii; + } else { + scan_forward = false; + } + } else if i-s.rune_pos < (s.rune_count-s.rune_pos)/2 { + // scan_forward = true; + } else { + s.byte_pos, s.rune_pos = _len(s.contents), s.rune_count; + scan_forward = false; + } + + if scan_forward { + for { + r, s.width = utf8.decode_rune_in_string(s.contents[s.byte_pos:]); + if s.rune_pos == i { + return; + } + s.rune_pos += 1; + s.byte_pos += s.width; + + } + } else { + for { + r, s.width = utf8.decode_last_rune_in_string(s.contents[:s.byte_pos]); + s.rune_pos -= 1; + s.byte_pos -= s.width; + if s.rune_pos == i { + return; + } + } + } +} + +slice :: proc(s: ^String, i, j: int, loc := #caller_location) -> string { + runtime.slice_expr_error_lo_hi_loc(loc, i, j, s.rune_count); + + if j < s.non_ascii { + return s.contents[i:j]; + } + + if i == j { + return ""; + } + + lo, hi: int; + if i < s.non_ascii { + lo = i; + } else if i == s.rune_count { + lo = _len(s.contents); + } else { + at(s, i, loc); + lo = s.byte_pos; + } + + if j == s.rune_count { + hi = _len(s.contents); + } else { + at(s, j, loc); + hi = s.byte_pos; + } + + return s.contents[lo:hi]; +} From e26f63b448273aadf26d8390bfd6500ad75f5807 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 26 Sep 2020 23:51:42 +0100 Subject: [PATCH 6/9] Update `package reflect` --- core/fmt/fmt.odin | 2 +- core/reflect/reflect.odin | 185 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 181 insertions(+), 6 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 7252f31ed..a166f887c 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1811,7 +1811,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } - if info.maybe && len(info.variants) == 1 && reflect.is_pointer(info.variants[0]) { + if reflect.type_info_union_is_pure_maybe(info) { if v.data == nil { strings.write_string(fi.buf, "nil"); } else { diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index e4d8a23c8..446893c83 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -551,11 +551,22 @@ union_variant_type_info :: proc(a: any) -> ^runtime.Type_Info { return type_info_of(id); } +type_info_union_is_pure_maybe :: proc(info: runtime.Type_Info_Union) -> bool { + return info.maybe && len(info.variants) == 1 && is_pointer(info.variants[0]); +} + union_variant_typeid :: proc(a: any) -> typeid { if a == nil { return nil; } ti := runtime.type_info_base(type_info_of(a.id)); if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if type_info_union_is_pure_maybe(info) { + if a.data != nil { + return info.variants[0].id; + } + return nil; + } + tag_ptr := uintptr(a.data) + info.tag_offset; tag_any := any{rawptr(tag_ptr), info.tag_type.id}; @@ -573,15 +584,159 @@ union_variant_typeid :: proc(a: any) -> typeid { } if a.data != nil && tag != 0 { - return info.variants[tag-1].id; + i := tag if info.no_nil else tag-1; + return info.variants[i].id; } - } else { - panic("expected a union to reflect.union_variant_typeid"); - } - return nil; + return nil; + } + panic("expected a union to reflect.union_variant_typeid"); + } +get_union_variant_raw_tag :: proc(a: any) -> i64 { + if a == nil { return -1; } + + ti := runtime.type_info_base(type_info_of(a.id)); + if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if type_info_union_is_pure_maybe(info) { + return 1 if a.data != nil else 0; + } + + tag_ptr := uintptr(a.data) + info.tag_offset; + tag_any := any{rawptr(tag_ptr), info.tag_type.id}; + + tag: i64 = ---; + switch i in tag_any { + case u8: tag = i64(i); + case i8: tag = i64(i); + case u16: tag = i64(i); + case i16: tag = i64(i); + case u32: tag = i64(i); + case i32: tag = i64(i); + case u64: tag = i64(i); + case i64: tag = i64(i); + case: unimplemented(); + } + + return tag; + } + panic("expected a union to reflect.get_union_variant_raw_tag"); +} + + +set_union_variant_raw_tag :: proc(a: any, tag: i64) { + if a == nil { return; } + + ti := runtime.type_info_base(type_info_of(a.id)); + if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if type_info_union_is_pure_maybe(info) { + // Cannot do anything + return; + } + + tag_ptr := uintptr(a.data) + info.tag_offset; + tag_any := any{rawptr(tag_ptr), info.tag_type.id}; + + switch i in &tag_any { + case u8: i = u8(tag); + case i8: i = i8(tag); + case u16: i = u16(tag); + case i16: i = i16(tag); + case u32: i = u32(tag); + case i32: i = i32(tag); + case u64: i = u64(tag); + case i64: i = i64(tag); + case: unimplemented(); + } + + return; + } + panic("expected a union to reflect.set_union_variant_raw_tag"); +} + +set_union_variant_typeid :: proc(a: any, id: typeid) { + if a == nil { return; } + + ti := runtime.type_info_base(type_info_of(a.id)); + if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if type_info_union_is_pure_maybe(info) { + // Cannot do anything + return; + } + + if id == nil && !info.no_nil { + set_union_variant_raw_tag(a, 0); + return; + } + + for variant, i in info.variants { + if variant.id == id { + tag := i64(i); + if !info.no_nil { + tag += 1; + } + set_union_variant_raw_tag(a, tag); + return; + } + } + return; + } + panic("expected a union to reflect.set_union_variant_typeid"); +} + +set_union_variant_type_info :: proc(a: any, ti: ^Type_Info) { + if a == nil { return; } + + ti := runtime.type_info_base(type_info_of(a.id)); + if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if type_info_union_is_pure_maybe(info) { + // Cannot do anything + return; + } + + if ti == nil && !info.no_nil { + set_union_variant_raw_tag(a, 0); + return; + } + + for variant, i in info.variants { + if variant == ti { + tag := i64(i); + if !info.no_nil { + tag += 1; + } + set_union_variant_raw_tag(a, tag); + return; + } + } + return; + } + panic("expected a union to reflect.set_union_variant_type_info"); +} + + +as_bool :: proc(a: any) -> (value: bool, valid: bool) { + if a == nil { return; } + a := a; + ti := runtime.type_info_core(type_info_of(a.id)); + a.id = ti.id; + + #partial switch info in ti.variant { + case Type_Info_Boolean: + valid = true; + switch v in a { + case bool: value = bool(v); + case b8: value = bool(v); + case b16: value = bool(v); + case b32: value = bool(v); + case b64: value = bool(v); + case: valid = false; + } + } + + return; +} as_int :: proc(a: any) -> (value: int, valid: bool) { v: i64; @@ -915,3 +1070,23 @@ as_f64 :: proc(a: any) -> (value: f64, valid: bool) { return; } + + +as_string :: proc(a: any) -> (value: string, valid: bool) { + if a == nil { return; } + a := a; + ti := runtime.type_info_core(type_info_of(a.id)); + a.id = ti.id; + + #partial switch info in ti.variant { + case Type_Info_String: + valid = true; + switch v in a { + case string: value = string(v); + case cstring: value = string(v); + case: valid = false; + } + } + + return; +} From 626d0736f4ca333c365bf28711f798bf94b98098 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 27 Sep 2020 00:15:16 +0100 Subject: [PATCH 7/9] Add more to package reflect (as_string, as_pointer, as_raw_data, relative_pointer_to_absolute) --- core/fmt/fmt.odin | 50 +--------------- core/reflect/reflect.odin | 116 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 48 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index a166f887c..d82963fee 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1877,59 +1877,13 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { fmt_opaque(fi, v); case runtime.Type_Info_Relative_Pointer: - ptr_any := any{v.data, info.base_integer.id}; - ptr: rawptr; - switch i in &ptr_any { - case u8: ptr = handle_relative_pointer(&i); - case u16: ptr = handle_relative_pointer(&i); - case u32: ptr = handle_relative_pointer(&i); - case u64: ptr = handle_relative_pointer(&i); - case i8: ptr = handle_relative_pointer(&i); - case i16: ptr = handle_relative_pointer(&i); - case i32: ptr = handle_relative_pointer(&i); - case i64: ptr = handle_relative_pointer(&i); - case u16le: ptr = handle_relative_pointer(&i); - case u32le: ptr = handle_relative_pointer(&i); - case u64le: ptr = handle_relative_pointer(&i); - case i16le: ptr = handle_relative_pointer(&i); - case i32le: ptr = handle_relative_pointer(&i); - case i64le: ptr = handle_relative_pointer(&i); - case u16be: ptr = handle_relative_pointer(&i); - case u32be: ptr = handle_relative_pointer(&i); - case u64be: ptr = handle_relative_pointer(&i); - case i16be: ptr = handle_relative_pointer(&i); - case i32be: ptr = handle_relative_pointer(&i); - case i64be: ptr = handle_relative_pointer(&i); - } + ptr := reflect.relative_pointer_to_absolute_raw(v.data, info.base_integer.id); absolute_ptr := any{ptr, info.pointer.id}; fmt_value(fi, absolute_ptr, verb); case runtime.Type_Info_Relative_Slice: - ptr_any := any{v.data, info.base_integer.id}; - ptr: rawptr; - switch i in &ptr_any { - case u8: ptr = handle_relative_pointer(&i); - case u16: ptr = handle_relative_pointer(&i); - case u32: ptr = handle_relative_pointer(&i); - case u64: ptr = handle_relative_pointer(&i); - case i8: ptr = handle_relative_pointer(&i); - case i16: ptr = handle_relative_pointer(&i); - case i32: ptr = handle_relative_pointer(&i); - case i64: ptr = handle_relative_pointer(&i); - case u16le: ptr = handle_relative_pointer(&i); - case u32le: ptr = handle_relative_pointer(&i); - case u64le: ptr = handle_relative_pointer(&i); - case i16le: ptr = handle_relative_pointer(&i); - case i32le: ptr = handle_relative_pointer(&i); - case i64le: ptr = handle_relative_pointer(&i); - case u16be: ptr = handle_relative_pointer(&i); - case u32be: ptr = handle_relative_pointer(&i); - case u64be: ptr = handle_relative_pointer(&i); - case i16be: ptr = handle_relative_pointer(&i); - case i32be: ptr = handle_relative_pointer(&i); - case i64be: ptr = handle_relative_pointer(&i); - } + ptr := reflect.relative_pointer_to_absolute_raw(v.data, info.base_integer.id); if verb == 'p' { fmt_pointer(fi, ptr, 'p'); diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index 446893c83..f0f5c5000 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -2,6 +2,8 @@ package reflect import "core:runtime" import "core:mem" +import "intrinsics" +_ :: intrinsics; Type_Info :: runtime.Type_Info; @@ -1090,3 +1092,117 @@ as_string :: proc(a: any) -> (value: string, valid: bool) { return; } + +relative_pointer_to_absolute :: proc(a: any) -> rawptr { + if a == nil { return nil; } + a := a; + ti := runtime.type_info_core(type_info_of(a.id)); + a.id = ti.id; + + #partial switch info in ti.variant { + case Type_Info_Relative_Pointer: + return relative_pointer_to_absolute_raw(a.data, info.base_integer.id); + } + return nil; +} + + +relative_pointer_to_absolute_raw :: proc(data: rawptr, base_integer_id: typeid) -> rawptr { + _handle :: proc(ptr: ^$T) -> rawptr where intrinsics.type_is_integer(T) { + if ptr^ == 0 { + return nil; + } + when intrinsics.type_is_unsigned(T) { + return rawptr(uintptr(ptr) + uintptr(ptr^)); + } else { + return rawptr(uintptr(ptr) + uintptr(i64(ptr^))); + } + } + + ptr_any := any{data, base_integer_id}; + ptr: rawptr; + switch i in &ptr_any { + case u8: ptr = _handle(&i); + case u16: ptr = _handle(&i); + case u32: ptr = _handle(&i); + case u64: ptr = _handle(&i); + case i8: ptr = _handle(&i); + case i16: ptr = _handle(&i); + case i32: ptr = _handle(&i); + case i64: ptr = _handle(&i); + case u16le: ptr = _handle(&i); + case u32le: ptr = _handle(&i); + case u64le: ptr = _handle(&i); + case i16le: ptr = _handle(&i); + case i32le: ptr = _handle(&i); + case i64le: ptr = _handle(&i); + case u16be: ptr = _handle(&i); + case u32be: ptr = _handle(&i); + case u64be: ptr = _handle(&i); + case i16be: ptr = _handle(&i); + case i32be: ptr = _handle(&i); + case i64be: ptr = _handle(&i); + } + return ptr; + +} + + + +as_pointer :: proc(a: any) -> (value: rawptr, valid: bool) { + if a == nil { return; } + a := a; + ti := runtime.type_info_core(type_info_of(a.id)); + a.id = ti.id; + + #partial switch info in ti.variant { + case Type_Info_Pointer: + valid = true; + value = a.data; + + case Type_Info_String: + valid = true; + switch v in a { + case cstring: value = rawptr(v); + case: valid = false; + } + + case Type_Info_Relative_Pointer: + valid = true; + value = relative_pointer_to_absolute_raw(a.data, info.base_integer.id); + } + + return; +} + + +as_raw_data :: proc(a: any) -> (value: rawptr, valid: bool) { + if a == nil { return; } + a := a; + ti := runtime.type_info_core(type_info_of(a.id)); + a.id = ti.id; + + #partial switch info in ti.variant { + case Type_Info_String: + valid = true; + switch v in a { + case string: value = raw_data(v); + case cstring: value = rawptr(v); // just in case + case: valid = false; + } + + case Type_Info_Array: + valid = true; + value = a.data; + + case Type_Info_Slice: + valid = true; + value = (^mem.Raw_Slice)(a.data).data; + + case Type_Info_Dynamic_Array: + valid = true; + value = (^mem.Raw_Dynamic_Array)(a.data).data; + } + + return; +} From 96a0125599746d93a07f887350ffedb6a556e2f0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 27 Sep 2020 00:30:54 +0100 Subject: [PATCH 8/9] Fix typo in reflect.set_union_variant_type_info --- core/reflect/reflect.odin | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index f0f5c5000..947a10771 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -687,7 +687,7 @@ set_union_variant_typeid :: proc(a: any, id: typeid) { panic("expected a union to reflect.set_union_variant_typeid"); } -set_union_variant_type_info :: proc(a: any, ti: ^Type_Info) { +set_union_variant_type_info :: proc(a: any, tag_ti: ^Type_Info) { if a == nil { return; } ti := runtime.type_info_base(type_info_of(a.id)); @@ -697,13 +697,13 @@ set_union_variant_type_info :: proc(a: any, ti: ^Type_Info) { return; } - if ti == nil && !info.no_nil { + if tag_ti == nil && !info.no_nil { set_union_variant_raw_tag(a, 0); return; } for variant, i in info.variants { - if variant == ti { + if variant == tag_ti { tag := i64(i); if !info.no_nil { tag += 1; From 2ebb94fa729e50867ca882fd08acc64bab902ca3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 27 Sep 2020 00:31:29 +0100 Subject: [PATCH 9/9] Allow `os.read_dir` to use a different allocator --- core/os/dir_windows.odin | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/os/dir_windows.odin b/core/os/dir_windows.odin index 78c7d357b..6b8fa5dbe 100644 --- a/core/os/dir_windows.odin +++ b/core/os/dir_windows.odin @@ -4,7 +4,7 @@ import win32 "core:sys/windows" import "core:strings" import "core:time" -read_dir :: proc(fd: Handle, n: int) -> (fi: []File_Info, err: Errno) { +read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) { find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) { // Ignore "." and ".." if d.cFileName[0] == '.' && d.cFileName[1] == 0 { @@ -53,6 +53,8 @@ read_dir :: proc(fd: Handle, n: int) -> (fi: []File_Info, err: Errno) { return nil, ERROR_INVALID_HANDLE; } + context.allocator = allocator; + h := win32.HANDLE(fd); dir_fi, _ := stat_from_file_information("", h);