diff --git a/core/_preload.odin b/core/_preload.odin index 8d0a9c639..014a3c219 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -35,102 +35,103 @@ Calling_Convention :: enum { } // IMPORTANT NOTE(bill): Do not change the order of any of this data // The compiler relies upon this _exact_ order -Type_Info :: struct #ordered { -// Core Types - Enum_Value :: union { - rune, - i8, i16, i32, i64, i128, int, - u8, u16, u32, u64, u128, uint, - f32, f64, - }; + +Type_Info_Enum_Value :: union { + rune, + i8, i16, i32, i64, i128, int, + u8, u16, u32, u64, u128, uint, + f32, f64, +}; + // Variant Types - Named :: struct #ordered {name: string; base: ^Type_Info}; - Integer :: struct #ordered {signed: bool}; - Rune :: struct{}; - Float :: struct{}; - Complex :: struct{}; - String :: struct{}; - Boolean :: struct{}; - Any :: struct{}; - Pointer :: struct #ordered { - elem: ^Type_Info; // nil -> rawptr - }; - Procedure :: struct #ordered { - params: ^Type_Info; // Type_Info.Tuple - results: ^Type_Info; // Type_Info.Tuple - variadic: bool; - convention: Calling_Convention; - }; - Array :: struct #ordered { - elem: ^Type_Info; - elem_size: int; - count: int; - }; - Dynamic_Array :: struct #ordered {elem: ^Type_Info; elem_size: int}; - Slice :: struct #ordered {elem: ^Type_Info; elem_size: int}; - Vector :: struct #ordered {elem: ^Type_Info; elem_size, count: int}; - Tuple :: struct #ordered { // Only really used for procedures - types: []^Type_Info; - names: []string; - }; - Struct :: struct #ordered { - types: []^Type_Info; - names: []string; - offsets: []int; // offsets may not be used in tuples - usings: []bool; // usings may not be used in tuples - is_packed: bool; - is_ordered: bool; - is_raw_union: bool; - custom_align: bool; - }; - Union :: struct #ordered { - variants: []^Type_Info; - tag_offset: int; - }; - Enum :: struct #ordered { - base: ^Type_Info; - names: []string; - values: []Enum_Value; - }; - Map :: struct #ordered { - key: ^Type_Info; - value: ^Type_Info; - generated_struct: ^Type_Info; - }; - Bit_Field :: struct #ordered { - names: []string; - bits: []i32; - offsets: []i32; - }; +Type_Info_Named :: struct #ordered {name: string, base: ^Type_Info}; +Type_Info_Integer :: struct #ordered {signed: bool}; +Type_Info_Rune :: struct{}; +Type_Info_Float :: struct{}; +Type_Info_Complex :: struct{}; +Type_Info_String :: struct{}; +Type_Info_Boolean :: struct{}; +Type_Info_Any :: struct{}; +Type_Info_Pointer :: struct #ordered { + elem: ^Type_Info // nil -> rawptr +}; +Type_Info_Procedure :: struct #ordered { + params: ^Type_Info, // Type_Info_Tuple + results: ^Type_Info, // Type_Info_Tuple + variadic: bool, + convention: Calling_Convention, +}; +Type_Info_Array :: struct #ordered { + elem: ^Type_Info, + elem_size: int, + count: int, +}; +Type_Info_Dynamic_Array :: struct #ordered {elem: ^Type_Info, elem_size: int}; +Type_Info_Slice :: struct #ordered {elem: ^Type_Info, elem_size: int}; +Type_Info_Vector :: struct #ordered {elem: ^Type_Info, elem_size, count: int}; +Type_Info_Tuple :: struct #ordered { // Only really used for procedures + types: []^Type_Info, + names: []string, +}; +Type_Info_Struct :: struct #ordered { + types: []^Type_Info, + names: []string, + offsets: []int, // offsets may not be used in tuples + usings: []bool, // usings may not be used in tuples + is_packed: bool, + is_ordered: bool, + is_raw_union: bool, + custom_align: bool, +}; +Type_Info_Union :: struct #ordered { + variants: []^Type_Info, + tag_offset: int, +}; +Type_Info_Enum :: struct #ordered { + base: ^Type_Info, + names: []string, + values: []Type_Info_Enum_Value, +}; +Type_Info_Map :: struct #ordered { + key: ^Type_Info, + value: ^Type_Info, + generated_struct: ^Type_Info, +}; +Type_Info_Bit_Field :: struct #ordered { + names: []string, + bits: []i32, + offsets: []i32, +}; +Type_Info :: struct #ordered { // Fields - size: int; - align: int; + size: int, + align: int, variant: union { - Named, - Integer, - Rune, - Float, - Complex, - String, - Boolean, - Any, - Pointer, - Procedure, - Array, - Dynamic_Array, - Slice, - Vector, - Tuple, - Struct, - Union, - Enum, - Map, - Bit_Field, - }; + Type_Info_Named, + Type_Info_Integer, + Type_Info_Rune, + Type_Info_Float, + Type_Info_Complex, + Type_Info_String, + Type_Info_Boolean, + Type_Info_Any, + Type_Info_Pointer, + Type_Info_Procedure, + Type_Info_Array, + Type_Info_Dynamic_Array, + Type_Info_Slice, + Type_Info_Vector, + Type_Info_Tuple, + Type_Info_Struct, + Type_Info_Union, + Type_Info_Enum, + Type_Info_Map, + Type_Info_Bit_Field, + }, } // NOTE(bill): only the ones that are needed (not all types) @@ -142,69 +143,72 @@ __argc__: i32; // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it) -Allocator :: struct #ordered { - Mode :: enum u8 { - Alloc, - Free, - FreeAll, - Resize, - } - Proc :: #type proc(allocator_data: rawptr, mode: Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, flags: u64 = 0) -> rawptr; +Allocator_Mode :: enum u8 { + Alloc, + Free, + FreeAll, + Resize, +} - procedure: Proc; - data: rawptr; + +Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode, + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64 = 0) -> rawptr; + + +Allocator :: struct #ordered { + procedure: Allocator_Proc, + data: rawptr, } Context :: struct #ordered { - allocator: Allocator; - thread_id: int; + allocator: Allocator, + thread_id: int, - user_data: any; - user_index: int; + user_data: any, + user_index: int, - derived: any; // May be used for derived data types + derived: any, // May be used for derived data types } DEFAULT_ALIGNMENT :: align_of([vector 4]f32); Source_Code_Location :: struct #ordered { - file_path: string; - line, column: i64; - procedure: string; + file_path: string, + line, column: i64, + procedure: string, } __INITIAL_MAP_CAP :: 16; __Map_Key :: struct #ordered { - hash: u128; - str: string; + hash: u128, + str: string, } __Map_Find_Result :: struct #ordered { - hash_index: int; - entry_prev: int; - entry_index: int; + hash_index: int, + entry_prev: int, + entry_index: int, } __Map_Entry_Header :: struct #ordered { - key: __Map_Key; - next: int; + key: __Map_Key, + next: int, /* - value: Value_Type; + value: Value_Type, */ } __Map_Header :: struct #ordered { - m: ^raw.Map; - is_key_string: bool; - entry_size: int; - entry_align: int; - value_offset: int; - value_size: int; + m: ^raw.Map, + is_key_string: bool, + entry_size: int, + entry_align: int, + value_offset: int, + value_size: int, } @@ -214,7 +218,7 @@ type_info_base :: proc(info: ^Type_Info) -> ^Type_Info { base := info; match i in base.variant { - case Type_Info.Named: base = i.base; + case Type_Info_Named: base = i.base; } return base; } @@ -225,8 +229,8 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info { base := info; match i in base.variant { - case Type_Info.Named: base = i.base; - case Type_Info.Enum: base = i.base; + case Type_Info_Named: base = i.base; + case Type_Info_Enum: base = i.base; } return base; } @@ -281,26 +285,26 @@ __check_context :: proc() { alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline { a := context.allocator; - return a.procedure(a.data, Allocator.Mode.Alloc, size, alignment, nil, 0, 0); + return a.procedure(a.data, Allocator_Mode.Alloc, size, alignment, nil, 0, 0); } free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline { if ptr == nil do return; if a.procedure == nil do return; - a.procedure(a.data, Allocator.Mode.Free, 0, 0, ptr, 0, 0); + a.procedure(a.data, Allocator_Mode.Free, 0, 0, ptr, 0, 0); } free_ptr :: proc(ptr: rawptr) #inline do free_ptr_with_allocator(context.allocator, ptr); free_all :: proc() #inline { a := context.allocator; - a.procedure(a.data, Allocator.Mode.FreeAll, 0, 0, nil, 0, 0); + a.procedure(a.data, Allocator_Mode.FreeAll, 0, 0, nil, 0, 0); } resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline { a := context.allocator; - return a.procedure(a.data, Allocator.Mode.Resize, new_size, alignment, ptr, old_size, 0); + return a.procedure(a.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, 0); } @@ -411,7 +415,7 @@ reserve :: proc(array: ^$T/[dynamic]$E, capacity: int) -> bool { new_size := capacity * size_of(E); allocator := a.allocator; - new_data := allocator.procedure(allocator.data, Allocator.Mode.Resize, new_size, align_of(E), a.data, old_size, 0); + new_data := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, align_of(E), a.data, old_size, 0); if new_data == nil do return false; a.data = new_data; @@ -423,12 +427,12 @@ reserve :: proc(array: ^$T/[dynamic]$E, capacity: int) -> bool { __get_map_header :: proc(m: ^$T/map[$K]$V) -> __Map_Header #cc_contextless { header := __Map_Header{m = cast(^raw.Map)m}; Entry :: struct { - key: __Map_Key; - next: int; - value: V; + key: __Map_Key, + next: int, + value: V, } - _, is_string := type_info_base(type_info_of(K)).variant.(Type_Info.String); + _, is_string := type_info_base(type_info_of(K)).variant.(Type_Info_String); header.is_key_string = is_string; header.entry_size = size_of(Entry); header.entry_align = align_of(Entry); @@ -441,7 +445,7 @@ __get_map_key :: proc(key: $K) -> __Map_Key #cc_contextless { map_key: __Map_Key; ti := type_info_base_without_enum(type_info_of(K)); match _ in ti.variant { - case Type_Info.Integer: + case Type_Info_Integer: match 8*size_of(key) { case 8: map_key.hash = u128(( ^u8)(&key)^); case 16: map_key.hash = u128(( ^u16)(&key)^); @@ -450,17 +454,17 @@ __get_map_key :: proc(key: $K) -> __Map_Key #cc_contextless { case 128: map_key.hash = u128((^u128)(&key)^); case: panic("Unhandled integer size"); } - case Type_Info.Rune: + case Type_Info_Rune: map_key.hash = u128((cast(^rune)&key)^); - case Type_Info.Pointer: + case Type_Info_Pointer: map_key.hash = u128(uint((^rawptr)(&key)^)); - case Type_Info.Float: + case Type_Info_Float: match 8*size_of(key) { case 32: map_key.hash = u128((^u32)(&key)^); case 64: map_key.hash = u128((^u64)(&key)^); case: panic("Unhandled float size"); } - case Type_Info.String: + case Type_Info_String: str := (^string)(&key)^; map_key.hash = __default_hash_string(str); map_key.str = str; @@ -566,10 +570,10 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: } -default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, flags: u64) -> rawptr { - using Allocator.Mode; +default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64) -> rawptr { + using Allocator_Mode; match mode { case Alloc: @@ -788,7 +792,7 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: new_size := cap * elem_size; allocator := array.allocator; - new_data := allocator.procedure(allocator.data, Allocator.Mode.Resize, new_size, elem_align, array.data, old_size, 0); + new_data := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, elem_align, array.data, old_size, 0); if new_data == nil do return false; array.data = new_data; diff --git a/core/_soft_numbers.odin b/core/_soft_numbers.odin index 0dc7b216e..023c6a6de 100644 --- a/core/_soft_numbers.odin +++ b/core/_soft_numbers.odin @@ -5,16 +5,17 @@ __multi3 :: proc(a, b: u128) -> u128 #cc_c #link_name "__multi3" { lower_mask :: u128(~u64(0) >> bits_in_dword_2); - TWords :: struct #raw_union { - all: u128; - using _: struct { - when ODIN_ENDIAN == "big" { - lo, hi: u64; - } else { - hi, lo: u64; - } + when ODIN_ENDIAN == "big" { + TWords :: struct #raw_union { + all: u128, + using _: struct {lo, hi: u64}, }; - }; + } else { + TWords :: struct #raw_union { + all: u128, + using _: struct {hi, lo: u64}, + }; + } r: TWords; t: u64; diff --git a/core/decimal.odin b/core/decimal.odin index 398cc91fa..0a00ae5aa 100644 --- a/core/decimal.odin +++ b/core/decimal.odin @@ -3,10 +3,10 @@ // NOTE: This is only for floating point printing and nothing else Decimal :: struct { - digits: [384]u8; // big-endian digits - count: int; - decimal_point: int; - neg, trunc: bool; + digits: [384]u8, // big-endian digits + count: int, + decimal_point: int, + neg, trunc: bool, } decimal_to_string :: proc(buf: []u8, a: ^Decimal) -> string { diff --git a/core/fmt.odin b/core/fmt.odin index 6cb142aea..fc6249afd 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -14,23 +14,23 @@ String_Buffer :: union { } Fmt_Info :: struct { - minus: bool; - plus: bool; - space: bool; - zero: bool; - hash: bool; - width_set: bool; - prec_set: bool; + minus: bool, + plus: bool, + space: bool, + zero: bool, + hash: bool, + width_set: bool, + prec_set: bool, - width: int; - prec: int; - indent: int; + width: int, + prec: int, + indent: int, - reordered: bool; - good_arg_index: bool; + reordered: bool, + good_arg_index: bool, - buf: ^String_Buffer; - arg: any; // Temporary + buf: ^String_Buffer, + arg: any, // Temporary } @@ -179,11 +179,10 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { return; } - using Type_Info; match info in ti.variant { - case Named: + case Type_Info_Named: write_string(buf, info.name); - case Integer: + case Type_Info_Integer: match { case ti == type_info_of(int): write_string(buf, "int"); case ti == type_info_of(uint): write_string(buf, "uint"); @@ -192,38 +191,38 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { else do write_byte(buf, 'u'); write_int(buf, i64(8*ti.size), 10); } - case Rune: + case Type_Info_Rune: write_string(buf, "rune"); - case Float: + case Type_Info_Float: match ti.size { case 2: write_string(buf, "f16"); case 4: write_string(buf, "f32"); case 8: write_string(buf, "f64"); } - case Complex: + case Type_Info_Complex: match ti.size { case 4: write_string(buf, "complex32"); case 8: write_string(buf, "complex64"); case 16: write_string(buf, "complex128"); } - case String: write_string(buf, "string"); - case Boolean: write_string(buf, "bool"); - case Any: + case Type_Info_String: write_string(buf, "string"); + case Type_Info_Boolean: write_string(buf, "bool"); + case Type_Info_Any: write_string(buf, "any"); - case Pointer: + case Type_Info_Pointer: if info.elem == nil { write_string(buf, "rawptr"); } else { write_string(buf, "^"); write_type(buf, info.elem); } - case Procedure: + case Type_Info_Procedure: write_string(buf, "proc"); if info.params == nil { write_string(buf, "()"); } else { - t := info.params.variant.(Tuple); + t := info.params.variant.(Type_Info_Tuple); write_string(buf, "("); for t, i in t.types { if i > 0 do write_string(buf, ", "); @@ -235,7 +234,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { write_string(buf, " -> "); write_type(buf, info.results); } - case Tuple: + case Type_Info_Tuple: count := len(info.names); if count != 1 do write_string(buf, "("); for name, i in info.names { @@ -251,31 +250,31 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { } if count != 1 do write_string(buf, ")"); - case Array: + case Type_Info_Array: write_string(buf, "["); fi := Fmt_Info{buf = buf}; write_int(buf, i64(info.count), 10); write_string(buf, "]"); write_type(buf, info.elem); - case Dynamic_Array: + case Type_Info_Dynamic_Array: write_string(buf, "[dynamic]"); write_type(buf, info.elem); - case Slice: + case Type_Info_Slice: write_string(buf, "[]"); write_type(buf, info.elem); - case Vector: + case Type_Info_Vector: write_string(buf, "[vector "); write_int(buf, i64(info.count), 10); write_string(buf, "]"); write_type(buf, info.elem); - case Map: + case Type_Info_Map: write_string(buf, "map["); write_type(buf, info.key); write_byte(buf, ']'); write_type(buf, info.value); - case Struct: + case Type_Info_Struct: write_string(buf, "struct "); if info.is_packed do write_string(buf, "#packed "); if info.is_ordered do write_string(buf, "#ordered "); @@ -294,7 +293,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { } write_byte(buf, '}'); - case Union: + case Type_Info_Union: write_string(buf, "union {"); for variant, i in info.variants { if i > 0 do write_string(buf, ", "); @@ -302,7 +301,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { } write_string(buf, "}"); - case Enum: + case Type_Info_Enum: write_string(buf, "enum "); write_type(buf, info.base); write_string(buf, " {"); @@ -312,7 +311,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { } write_string(buf, "}"); - case Bit_Field: + case Type_Info_Bit_Field: write_string(buf, "bit_field "); if ti.align != 1 { write_string(buf, "#align "); @@ -651,11 +650,10 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) { enum_value_to_string :: proc(v: any) -> (string, bool) { v.type_info = type_info_base(v.type_info); - using Type_Info; match e in v.type_info.variant { case: return "", false; - case Enum: - get_str :: proc(i: $T, e: Enum) -> (string, bool) { + case Type_Info_Enum: + get_str :: proc(i: $T, e: Type_Info_Enum) -> (string, bool) { if types.is_string(e.base) { for val, idx in e.values { if v, ok := val.(T); ok && v == i { @@ -718,10 +716,9 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) { return; } - using Type_Info; match e in v.type_info.variant { case: fmt_bad_verb(fi, verb); - case Enum: + case Type_Info_Enum: match verb { case: fmt_bad_verb(fi, verb); case 'd', 'f': @@ -741,11 +738,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { return; } - using Type_Info; match info in v.type_info.variant { - case Named: + case Type_Info_Named: match b in info.base.variant { - case Struct: + case Type_Info_Struct: if verb != 'v' { fmt_bad_verb(fi, verb); return; @@ -792,21 +788,21 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_value(fi, any{v.data, info.base}, verb); } - case Boolean: fmt_arg(fi, v, verb); - case Integer: fmt_arg(fi, v, verb); - case Rune: fmt_arg(fi, v, verb); - case Float: fmt_arg(fi, v, verb); - case Complex: fmt_arg(fi, v, verb); - case String: fmt_arg(fi, v, verb); + case Type_Info_Boolean: fmt_arg(fi, v, verb); + case Type_Info_Integer: fmt_arg(fi, v, verb); + case Type_Info_Rune: fmt_arg(fi, v, verb); + case Type_Info_Float: fmt_arg(fi, v, verb); + case Type_Info_Complex: fmt_arg(fi, v, verb); + case Type_Info_String: fmt_arg(fi, v, verb); - case Pointer: + case Type_Info_Pointer: if v.type_info == type_info_of(^Type_Info) { write_type(fi.buf, (cast(^^Type_Info)v.data)^); } else { fmt_pointer(fi, (cast(^rawptr)v.data)^, verb); } - case Array: + case Type_Info_Array: write_byte(fi.buf, '['); defer write_byte(fi.buf, ']'); for i in 0..info.count { @@ -816,7 +812,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_arg(fi, any{rawptr(data), info.elem}, verb); } - case Dynamic_Array: + case Type_Info_Dynamic_Array: write_byte(fi.buf, '['); defer write_byte(fi.buf, ']'); array := cast(^raw.Dynamic_Array)v.data; @@ -827,7 +823,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_arg(fi, any{rawptr(data), info.elem}, verb); } - case Slice: + case Type_Info_Slice: write_byte(fi.buf, '['); defer write_byte(fi.buf, ']'); slice := cast(^[]u8)v.data; @@ -838,7 +834,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_arg(fi, any{rawptr(data), info.elem}, verb); } - case Vector: + case Type_Info_Vector: write_byte(fi.buf, '<'); defer write_byte(fi.buf, '>'); @@ -849,7 +845,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_value(fi, any{rawptr(data), info.elem}, verb); } - case Map: + case Type_Info_Map: if verb != 'v' { fmt_bad_verb(fi, verb); return; @@ -859,9 +855,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { defer write_byte(fi.buf, ']'); entries := &((cast(^raw.Map)v.data).entries); - gs := type_info_base(info.generated_struct).variant.(Struct); - ed := type_info_base(gs.types[1]).variant.(Dynamic_Array); - entry_type := ed.elem.variant.(Struct); + gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct); + ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array); + entry_type := ed.elem.variant.(Type_Info_Struct); entry_size := ed.elem_size; for i in 0..entries.len { @@ -885,7 +881,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { - case Struct: + case Type_Info_Struct: if info.is_raw_union { write_string(fi.buf, "(raw_union)"); return; @@ -922,7 +918,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { if hash do write_string(fi.buf, ",\n"); } - case Union: + case Type_Info_Union: data := cast(^u8)v.data; tipp := cast(^^Type_Info)(data + info.tag_offset); if data == nil || tipp == nil { @@ -932,10 +928,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_arg(fi, any{data, ti}, verb); } - case Enum: + case Type_Info_Enum: fmt_enum(fi, v, verb); - case Procedure: + case Type_Info_Procedure: write_type(fi.buf, v.type_info); write_string(fi.buf, " @ "); fmt_pointer(fi, (cast(^rawptr)v.data)^, 'p'); diff --git a/core/mem.odin b/core/mem.odin index a050e2ccb..b2e05131c 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -64,9 +64,7 @@ align_forward :: proc(ptr: rawptr, align: int) -> rawptr { -AllocationHeader :: struct { - size: int; -} +AllocationHeader :: struct {size: int}; allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) { header.size = size; @@ -91,14 +89,14 @@ allocation_header :: proc(data: rawptr) -> ^AllocationHeader { // Custom allocators Arena :: struct { - backing: Allocator; - memory: []u8; - temp_count: int; + backing: Allocator, + memory: []u8, + temp_count: int, } ArenaTempMemory :: struct { - arena: ^Arena; - original_count: int; + arena: ^Arena, + original_count: int, } @@ -133,10 +131,10 @@ arena_allocator :: proc(arena: ^Arena) -> Allocator { }; } -arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode, +arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, flags: u64) -> rawptr { - using Allocator.Mode; + using Allocator_Mode; arena := cast(^Arena)allocator_data; match mode { @@ -202,46 +200,45 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int { WORD_SIZE :: size_of(int); MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants? - using Type_Info; match info in type_info.variant { - case Named: + case Type_Info_Named: return align_of_type_info(info.base); - case Integer: + case Type_Info_Integer: return type_info.align; - case Rune: + case Type_Info_Rune: return type_info.align; - case Float: + case Type_Info_Float: return type_info.align; - case String: + case Type_Info_String: return WORD_SIZE; - case Boolean: + case Type_Info_Boolean: return 1; - case Any: + case Type_Info_Any: return WORD_SIZE; - case Pointer: + case Type_Info_Pointer: return WORD_SIZE; - case Procedure: + case Type_Info_Procedure: return WORD_SIZE; - case Array: + case Type_Info_Array: return align_of_type_info(info.elem); - case Dynamic_Array: + case Type_Info_Dynamic_Array: return WORD_SIZE; - case Slice: + case Type_Info_Slice: return WORD_SIZE; - case Vector: + case Type_Info_Vector: size := size_of_type_info(info.elem); count := int(max(prev_pow2(i64(info.count)), 1)); total := size * count; return clamp(total, 1, MAX_ALIGN); - case Tuple: + case Type_Info_Tuple: return type_info.align; - case Struct: + case Type_Info_Struct: return type_info.align; - case Union: + case Type_Info_Union: return type_info.align; - case Enum: + case Type_Info_Enum: return align_of_type_info(info.base); - case Map: + case Type_Info_Map: return align_of_type_info(info.generated_struct); } @@ -255,51 +252,50 @@ align_formula :: proc(size, align: int) -> int { size_of_type_info :: proc(type_info: ^Type_Info) -> int { WORD_SIZE :: size_of(int); - using Type_Info; match info in type_info.variant { - case Named: + case Type_Info_Named: return size_of_type_info(info.base); - case Integer: + case Type_Info_Integer: return type_info.size; - case Rune: + case Type_Info_Rune: return type_info.size; - case Float: + case Type_Info_Float: return type_info.size; - case String: + case Type_Info_String: return 2*WORD_SIZE; - case Boolean: + case Type_Info_Boolean: return 1; - case Any: + case Type_Info_Any: return 2*WORD_SIZE; - case Pointer: + case Type_Info_Pointer: return WORD_SIZE; - case Procedure: + case Type_Info_Procedure: return WORD_SIZE; - case Array: + case Type_Info_Array: count := info.count; if count == 0 do return 0; size := size_of_type_info(info.elem); align := align_of_type_info(info.elem); alignment := align_formula(size, align); return alignment*(count-1) + size; - case Dynamic_Array: + case Type_Info_Dynamic_Array: return size_of(rawptr) + 2*size_of(int) + size_of(Allocator); - case Slice: + case Type_Info_Slice: return 2*WORD_SIZE; - case Vector: + case Type_Info_Vector: count := info.count; if count == 0 do return 0; size := size_of_type_info(info.elem); align := align_of_type_info(info.elem); alignment := align_formula(size, align); return alignment*(count-1) + size; - case Struct: + case Type_Info_Struct: return type_info.size; - case Union: + case Type_Info_Union: return type_info.size; - case Enum: + case Type_Info_Enum: return size_of_type_info(info.base); - case Map: + case Type_Info_Map: return size_of_type_info(info.generated_struct); } diff --git a/core/os_linux.odin b/core/os_linux.odin index bd1b32990..afbd41f7c 100644 --- a/core/os_linux.odin +++ b/core/os_linux.odin @@ -40,9 +40,9 @@ RTLD_GLOBAL :: 0x100; args := _alloc_command_line_arguments(); _File_Time :: struct #ordered { - seconds: i64; - nanoseconds: i32; - reserved: i32; + seconds: i64, + nanoseconds: i32, + reserved: i32, } // Translated from @@ -50,27 +50,27 @@ _File_Time :: struct #ordered { // Validity is not guaranteed. Stat :: struct #ordered { - device_id: u64; // ID of device containing file - serial: u64; // File serial number - nlink: u32; // Number of hard links - mode: u32; // Mode of the file - uid: u32; // User ID of the file's owner - gid: u32; // Group ID of the file's group - _padding: i32; // 32 bits of padding - rdev: u64; // Device ID, if device - size: i64; // Size of the file, in bytes - block_size: i64; // Optimal bllocksize for I/O - blocks: i64; // Number of 512-byte blocks allocated + device_id: u64, // ID of device containing file + serial: u64, // File serial number + nlink: u32, // Number of hard links + mode: u32, // Mode of the file + uid: u32, // User ID of the file's owner + gid: u32, // Group ID of the file's group + _padding: i32, // 32 bits of padding + rdev: u64, // Device ID, if device + size: i64, // Size of the file, in bytes + block_size: i64, // Optimal bllocksize for I/O + blocks: i64, // Number of 512-byte blocks allocated - last_access: _File_Time; // Time of last access - modified: _File_Time; // Time of last modification - status_change: _File_Time; // Time of last status change + last_access: _File_Time, // Time of last access + modified: _File_Time, // Time of last modification + status_change: _File_Time, // Time of last status change _reserve1, _reserve2, - _reserve3: i64; - serial_numbe: u64; // File serial number...? Maybe. - _reserve4: i64; + _reserve3: i64, + serial_numbe: u64, // File serial number...? Maybe. + _reserve4: i64, }; // File type diff --git a/core/os_x.odin b/core/os_x.odin index 796edd08a..ad267e22a 100644 --- a/core/os_x.odin +++ b/core/os_x.odin @@ -45,32 +45,32 @@ RTLD_FIRST :: 0x100; args: [dynamic]string; _File_Time :: struct #ordered { - seconds: i64; - nanoseconds: i64; + seconds: i64, + nanoseconds: i64, } Stat :: struct #ordered { - device_id: i32; // ID of device containing file - mode: u16; // Mode of the file - nlink: u16; // Number of hard links - serial: u64; // File serial number - uid: u32; // User ID of the file's owner - gid: u32; // Group ID of the file's group - rdev: i32; // Device ID, if device + device_id: i32, // ID of device containing file + mode: u16, // Mode of the file + nlink: u16, // Number of hard links + serial: u64, // File serial number + uid: u32, // User ID of the file's owner + gid: u32, // Group ID of the file's group + rdev: i32, // Device ID, if device - last_access: File_Time; // Time of last access - modified: File_Time; // Time of last modification - status_change: File_Time; // Time of last status change - created: File_Time; // Time of creation + last_access: File_Time, // Time of last access + modified: File_Time, // Time of last modification + status_change: File_Time, // Time of last status change + created: File_Time, // Time of creation - size: i64; // Size of the file, in bytes - blocks: i64; // Number of blocks allocated for the file - block_size: i32; // Optimal blocksize for I/O - flags: u32; // User-defined flags for the file - gen_num: u32; // File generation number ...? - _spare: i32; // RESERVED + size: i64, // Size of the file, in bytes + blocks: i64, // Number of blocks allocated for the file + block_size: i32, // Optimal blocksize for I/O + flags: u32, // User-defined flags for the file + gen_num: u32, // File generation number ...? + _spare: i32, // RESERVED _reserve1, - _reserve2: i64; // RESERVED + _reserve2: i64, // RESERVED }; // File type diff --git a/core/raw.odin b/core/raw.odin index 76d284b94..ac6310915 100644 --- a/core/raw.odin +++ b/core/raw.odin @@ -1,28 +1,28 @@ Any :: struct #ordered { - data: rawptr; - type_info: ^Type_Info; -}; + data: rawptr, + type_info: ^Type_Info, +} String :: struct #ordered { - data: ^u8; - len: int; -}; + data: ^u8, + len: int, +} Slice :: struct #ordered { - data: rawptr; - len: int; - cap: int; -}; + data: rawptr, + len: int, + cap: int, +} Dynamic_Array :: struct #ordered { - data: rawptr; - len: int; - cap: int; - allocator: Allocator; -}; + data: rawptr, + len: int, + cap: int, + allocator: Allocator, +} Map :: struct #ordered { - hashes: [dynamic]int; - entries: Dynamic_Array; -}; + hashes: [dynamic]int, + entries: Dynamic_Array, +} diff --git a/core/strconv.odin b/core/strconv.odin index 0bb158768..b75e1fe2b 100644 --- a/core/strconv.odin +++ b/core/strconv.odin @@ -202,16 +202,16 @@ append_float :: proc(buf: []u8, f: f64, fmt: u8, prec, bit_size: int) -> string DecimalSlice :: struct { - digits: []u8; - count: int; - decimal_point: int; - neg: bool; + digits: []u8, + count: int, + decimal_point: int, + neg: bool, } FloatInfo :: struct { - mantbits: uint; - expbits: uint; - bias: int; + mantbits: uint, + expbits: uint, + bias: int, } diff --git a/core/sync_linux.odin b/core/sync_linux.odin index fcc8f7200..0df140efe 100644 --- a/core/sync_linux.odin +++ b/core/sync_linux.odin @@ -2,14 +2,14 @@ import "core:atomics.odin"; import "core:os.odin"; Semaphore :: struct { - // _handle: win32.Handle; + // _handle: win32.Handle, } Mutex :: struct { - _semaphore: Semaphore; - _counter: i32; - _owner: i32; - _recursion: i32; + _semaphore: Semaphore, + _counter: i32, + _owner: i32, + _recursion: i32, } current_thread_id :: proc() -> i32 { diff --git a/core/sync_windows.odin b/core/sync_windows.odin index af4177daa..a6a88e246 100644 --- a/core/sync_windows.odin +++ b/core/sync_windows.odin @@ -2,20 +2,20 @@ when ODIN_OS == "windows" do import win32 "core:sys/windows.odin"; import "core:atomics.odin"; Semaphore :: struct { - _handle: win32.Handle; + _handle: win32.Handle, } /* Mutex :: struct { - _semaphore: Semaphore; - _counter: i32; - _owner: i32; - _recursion: i32; + _semaphore: Semaphore, + _counter: i32, + _owner: i32, + _recursion: i32, } */ Mutex :: struct { - _critical_section: win32.Critical_Section; + _critical_section: win32.Critical_Section, } current_thread_id :: proc() -> i32 { diff --git a/core/sys/wgl.odin b/core/sys/wgl.odin index a859aeb92..2191018d5 100644 --- a/core/sys/wgl.odin +++ b/core/sys/wgl.odin @@ -14,40 +14,40 @@ Hglrc :: Handle; Color_Ref :: u32; Layer_Plane_Descriptor :: struct { - size: u16; - version: u16; - flags: u32; - pixel_type: u8; - color_bits: u8; - red_bits: u8; - red_shift: u8; - green_bits: u8; - green_shift: u8; - blue_bits: u8; - blue_shift: u8; - alpha_bits: u8; - alpha_shift: u8; - accum_bits: u8; - accum_red_bits: u8; - accum_green_bits: u8; - accum_blue_bits: u8; - accum_alpha_bits: u8; - depth_bits: u8; - stencil_bits: u8; - aux_buffers: u8; - layer_type: u8; - reserved: u8; - transparent: Color_Ref; + size: u16, + version: u16, + flags: u32, + pixel_type: u8, + color_bits: u8, + red_bits: u8, + red_shift: u8, + green_bits: u8, + green_shift: u8, + blue_bits: u8, + blue_shift: u8, + alpha_bits: u8, + alpha_shift: u8, + accum_bits: u8, + accum_red_bits: u8, + accum_green_bits: u8, + accum_blue_bits: u8, + accum_alpha_bits: u8, + depth_bits: u8, + stencil_bits: u8, + aux_buffers: u8, + layer_type: u8, + reserved: u8, + transparent: Color_Ref, } Point_Float :: struct {x, y: f32}; Glyph_Metrics_Float :: struct { - black_box_x: f32; - black_box_y: f32; - glyph_origin: Point_Float; - cell_inc_x: f32; - cell_inc_y: f32; + black_box_x: f32, + black_box_y: f32, + glyph_origin: Point_Float, + cell_inc_x: f32, + cell_inc_y: f32, } Create_Context_Attribs_ARB_Type :: #type proc(hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc; diff --git a/core/sys/windows.odin b/core/sys/windows.odin index 7d478d5f1..cfab08229 100644 --- a/core/sys/windows.odin +++ b/core/sys/windows.odin @@ -27,86 +27,86 @@ FALSE: Bool : 0; TRUE: Bool : 1; Point :: struct #ordered { - x, y: i32; + x, y: i32, } Wnd_Class_Ex_A :: struct #ordered { - size, style: u32; - wnd_proc: Wnd_Proc; - cls_extra, wnd_extra: i32; - instance: Hinstance; - icon: Hicon; - cursor: Hcursor; - background: Hbrush; - menu_name, class_name: ^u8; - sm: Hicon; + size, style: u32, + wnd_proc: Wnd_Proc, + cls_extra, wnd_extra: i32, + instance: Hinstance, + icon: Hicon, + cursor: Hcursor, + background: Hbrush, + menu_name, class_name: ^u8, + sm: Hicon, } Msg :: struct #ordered { - hwnd: Hwnd; - message: u32; - wparam: Wparam; - lparam: Lparam; - time: u32; - pt: Point; + hwnd: Hwnd, + message: u32, + wparam: Wparam, + lparam: Lparam, + time: u32, + pt: Point, } Rect :: struct #ordered { - left: i32; - top: i32; - right: i32; - bottom: i32; + left: i32, + top: i32, + right: i32, + bottom: i32, } Filetime :: struct #ordered { - lo, hi: u32; + lo, hi: u32, } Systemtime :: struct #ordered { - year, month: u16; - day_of_week, day: u16; - hour, minute, second, millisecond: u16; + year, month: u16, + day_of_week, day: u16, + hour, minute, second, millisecond: u16, } By_Handle_File_Information :: struct #ordered { - file_attributes: u32; + file_attributes: u32, creation_time, last_access_time, - last_write_time: Filetime; + last_write_time: Filetime, volume_serial_number, file_size_high, file_size_low, number_of_links, file_index_high, - file_index_low: u32; + file_index_low: u32, } File_Attribute_Data :: struct #ordered { - file_attributes: u32; + file_attributes: u32, creation_time, last_access_time, - last_write_time: Filetime; + last_write_time: Filetime, file_size_high, - file_size_low: u32; + file_size_low: u32, } Find_Data :: struct #ordered{ - file_attributes: u32; - creation_time: Filetime; - last_access_time: Filetime; - last_write_time: Filetime; - file_size_high: u32; - file_size_low: u32; - reserved0: u32; - reserved1: u32; - file_name: [MAX_PATH]u8; - alternate_file_name: [14]u8; + file_attributes: u32, + creation_time: Filetime, + last_access_time: Filetime, + last_write_time: Filetime, + file_size_high: u32, + file_size_low: u32, + reserved0: u32, + reserved1: u32, + file_name: [MAX_PATH]u8, + alternate_file_name: [14]u8, } Security_Attributes :: struct #ordered { - length: u32; - security_descriptor: rawptr; - inherit_handle: Bool; + length: u32, + security_descriptor: rawptr, + inherit_handle: Bool, } @@ -114,7 +114,7 @@ Security_Attributes :: struct #ordered { Pixel_Format_Descriptor :: struct #ordered { size, version, - flags: u32; + flags: u32, pixel_type, color_bits, @@ -135,33 +135,33 @@ Pixel_Format_Descriptor :: struct #ordered { stencil_bits, aux_buffers, layer_type, - reserved: u8; + reserved: u8, layer_mask, visible_mask, - damage_mask: u32; + damage_mask: u32, } Critical_Section :: struct #ordered { - debug_info: ^Critical_Section_Debug; + debug_info: ^Critical_Section_Debug, - lock_count: i32; - recursion_count: i32; - owning_thread: Handle; - lock_semaphore: Handle; - spin_count: ^u32; + lock_count: i32, + recursion_count: i32, + owning_thread: Handle, + lock_semaphore: Handle, + spin_count: ^u32, } Critical_Section_Debug :: struct #ordered { - typ: u16; - creator_back_trace_index: u16; - critical_section: ^Critical_Section; - process_locks_list: ^List_Entry; - entry_count: u32; - contention_count: u32; - flags: u32; - creator_back_trace_index_high: u16; - spare_word: u16; + typ: u16, + creator_back_trace_index: u16, + critical_section: ^Critical_Section, + process_locks_list: ^List_Entry, + entry_count: u32, + contention_count: u32, + flags: u32, + creator_back_trace_index_high: u16, + spare_word: u16, } List_Entry :: struct #ordered {flink, blink: ^List_Entry}; @@ -546,35 +546,35 @@ FILE_TYPE_PIPE :: 0x0003; Monitor_Info :: struct #ordered { - size: u32; - monitor: Rect; - work: Rect; - flags: u32; + size: u32, + monitor: Rect, + work: Rect, + flags: u32, } Window_Placement :: struct #ordered { - length: u32; - flags: u32; - show_cmd: u32; - min_pos: Point; - max_pos: Point; - normal_pos: Rect; + length: u32, + flags: u32, + show_cmd: u32, + min_pos: Point, + max_pos: Point, + normal_pos: Rect, } Bitmap_Info_Header :: struct #ordered { - size: u32; - width, height: i32; - planes, bit_count: i16; - compression: u32; - size_image: u32; - x_pels_per_meter: i32; - y_pels_per_meter: i32; - clr_used: u32; - clr_important: u32; + size: u32, + width, height: i32, + planes, bit_count: i16, + compression: u32, + size_image: u32, + x_pels_per_meter: i32, + y_pels_per_meter: i32, + clr_used: u32, + clr_important: u32, } Bitmap_Info :: struct #ordered { - using header: Bitmap_Info_Header; - colors: [1]Rgb_Quad; + using header: Bitmap_Info_Header, + colors: [1]Rgb_Quad, } diff --git a/core/thread.odin b/core/thread.odin index e44879122..51d4b2da4 100644 --- a/core/thread.odin +++ b/core/thread.odin @@ -4,24 +4,25 @@ when ODIN_OS == "windows" { import win32 "core:sys/windows.odin"; } +Thread_Proc :: #type proc(^Thread) -> int; + +Thread_Os_Specific :: struct { + win32_thread: win32.Handle, + win32_thread_id: u32, +} + Thread :: struct { - using specific: Os_Specific; - procedure: Proc; - data: any; - user_index: int; + using specific: Thread_Os_Specific, + procedure: Thread_Proc, + data: any, + user_index: int, - init_context: Context; - use_init_context: bool; - - Proc :: #type proc(^Thread) -> int; - Os_Specific :: struct { - win32_thread: win32.Handle; - win32_thread_id: u32; - } + init_context: Context, + use_init_context: bool, } -create :: proc(procedure: Thread.Proc) -> ^Thread { +create :: proc(procedure: Thread_Proc) -> ^Thread { win32_thread_id: u32; __windows_thread_entry_proc :: proc(data: rawptr) -> i32 #cc_c { diff --git a/core/types.odin b/core/types.odin index 2315440d1..796b0c13b 100644 --- a/core/types.odin +++ b/core/types.odin @@ -1,103 +1,103 @@ is_signed :: proc(info: ^Type_Info) -> bool { if info == nil do return false; match i in type_info_base(info).variant { - case Type_Info.Integer: return i.signed; - case Type_Info.Float: return true; + case Type_Info_Integer: return i.signed; + case Type_Info_Float: return true; } return false; } is_integer :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Integer); + _, ok := type_info_base(info).variant.(Type_Info_Integer); return ok; } is_rune :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Rune); + _, ok := type_info_base(info).variant.(Type_Info_Rune); return ok; } is_float :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Float); + _, ok := type_info_base(info).variant.(Type_Info_Float); return ok; } is_complex :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Complex); + _, ok := type_info_base(info).variant.(Type_Info_Complex); return ok; } is_any :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Any); + _, ok := type_info_base(info).variant.(Type_Info_Any); return ok; } is_string :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.String); + _, ok := type_info_base(info).variant.(Type_Info_String); return ok; } is_boolean :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Boolean); + _, ok := type_info_base(info).variant.(Type_Info_Boolean); return ok; } is_pointer :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Pointer); + _, ok := type_info_base(info).variant.(Type_Info_Pointer); return ok; } is_procedure :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Procedure); + _, ok := type_info_base(info).variant.(Type_Info_Procedure); return ok; } is_array :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Array); + _, ok := type_info_base(info).variant.(Type_Info_Array); return ok; } is_dynamic_array :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Dynamic_Array); + _, ok := type_info_base(info).variant.(Type_Info_Dynamic_Array); return ok; } is_dynamic_map :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Map); + _, ok := type_info_base(info).variant.(Type_Info_Map); return ok; } is_slice :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Slice); + _, ok := type_info_base(info).variant.(Type_Info_Slice); return ok; } is_vector :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Vector); + _, ok := type_info_base(info).variant.(Type_Info_Vector); return ok; } is_tuple :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Tuple); + _, ok := type_info_base(info).variant.(Type_Info_Tuple); return ok; } is_struct :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - s, ok := type_info_base(info).variant.(Type_Info.Struct); + s, ok := type_info_base(info).variant.(Type_Info_Struct); return ok && !s.is_raw_union; } is_raw_union :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - s, ok := type_info_base(info).variant.(Type_Info.Struct); + s, ok := type_info_base(info).variant.(Type_Info_Struct); return ok && s.is_raw_union; } is_union :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Union); + _, ok := type_info_base(info).variant.(Type_Info_Union); return ok; } is_enum :: proc(info: ^Type_Info) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(Type_Info.Enum); + _, ok := type_info_base(info).variant.(Type_Info_Enum); return ok; } diff --git a/examples/demo.odin b/examples/demo.odin index 3733fd8f1..a744d7234 100644 --- a/examples/demo.odin +++ b/examples/demo.odin @@ -58,8 +58,8 @@ general_stuff :: proc() { { // `expand_to_tuple` built-in procedure Foo :: struct { - x: int; - b: bool; + x: int, + b: bool, } f := Foo{137, true}; x, b := expand_to_tuple(f); @@ -77,31 +77,12 @@ general_stuff :: proc() { } } -nested_struct_declarations :: proc() { - { - FooInteger :: int; - Foo :: struct { - i: FooInteger; - }; - f := Foo{FooInteger(137)}; - } - { - Foo :: struct { - Integer :: int; - - i: Integer; - } - f := Foo{Foo.Integer(137)}; - - } -} - default_struct_values :: proc() { { Vector3 :: struct { - x: f32; - y: f32; - z: f32; + x: f32, + y: f32, + z: f32, } v: Vector3; fmt.println(v); @@ -109,9 +90,9 @@ default_struct_values :: proc() { { // Default values must be constants Vector3 :: struct { - x: f32 = 1; - y: f32 = 4; - z: f32 = 9; + x: f32 = 1, + y: f32 = 4, + z: f32 = 9, } v: Vector3; fmt.println(v); @@ -129,9 +110,9 @@ default_struct_values :: proc() { { Vector3 :: struct { - x := 1.0; - y := 4.0; - z := 9.0; + x := 1.0, + y := 4.0, + z := 9.0, } stack_default: Vector3; stack_literal := Vector3{}; @@ -197,13 +178,8 @@ union_type :: proc() { } } - Vector3 :: struct { - x, y, z: f32; - }; - Quaternion :: struct { - x, y, z: f32; - w: f32 = 1; - }; + Vector3 :: struct {x, y, z: f32}; + Quaternion :: struct {x, y, z: f32, w: f32 = 1}; // More realistic examples { @@ -214,23 +190,23 @@ union_type :: proc() { // an example of this for a basic game Entity. Entity :: struct { - id: u64; - name: string; - position: Vector3; - orientation: Quaternion; + id: u64, + name: string, + position: Vector3, + orientation: Quaternion, - derived: any; + derived: any, } Frog :: struct { - using entity: Entity; - jump_height: f32; + using entity: Entity, + jump_height: f32, } Monster :: struct { - using entity: Entity; - is_robot: bool; - is_zombie: bool; + using entity: Entity, + is_robot: bool, + is_zombie: bool, } // See `parametric_polymorphism` procedure for details @@ -258,23 +234,23 @@ union_type :: proc() { // basic game Entity but using an union. Entity :: struct { - id: u64; - name: string; - position: Vector3; - orientation: Quaternion; + id: u64, + name: string, + position: Vector3, + orientation: Quaternion, - derived: union {Frog, Monster}; + derived: union {Frog, Monster}, } Frog :: struct { - using entity: ^Entity; - jump_height: f32; + using entity: ^Entity, + jump_height: f32, } Monster :: struct { - using entity: ^Entity; - is_robot: bool; - is_zombie: bool; + using entity: ^Entity, + is_robot: bool, + is_zombie: bool, } // See `parametric_polymorphism` procedure for details @@ -386,18 +362,17 @@ parametric_polymorphism :: proc() { { // Polymorphic Types and Type Specialization + Table_Slot :: struct(Key, Value: type) { + occupied: bool, + hash: u32, + key: Key, + value: Value, + } + TABLE_SIZE_MIN :: 32; Table :: struct(Key, Value: type) { - Slot :: struct { - occupied: bool; - hash: u32; - key: Key; - value: Value; - } - SIZE_MIN :: 32; - - count: int; - allocator: Allocator; - slots: []Slot; + count: int, + allocator: Allocator, + slots: []Table_Slot(Key, Value), } // Only allow types that are specializations of a (polymorphic) slice @@ -412,7 +387,7 @@ parametric_polymorphism :: proc() { if table.allocator.procedure != nil do c.allocator = table.allocator; push_context c { - table.slots = make_slice([]T.Slot, max(capacity, T.SIZE_MIN)); + table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN)); } } @@ -423,7 +398,7 @@ parametric_polymorphism :: proc() { push_context c { old_slots := table.slots; - cap := max(2*cap(table.slots), T.SIZE_MIN); + cap := max(2*cap(table.slots), TABLE_SIZE_MIN); allocate(table, cap); for s in old_slots do if s.occupied { @@ -588,7 +563,6 @@ threading_example :: proc() { main :: proc() { when false { fmt.println("\n# general_stuff"); general_stuff(); - fmt.println("\n# nested_struct_declarations"); nested_struct_declarations(); fmt.println("\n# default_struct_values"); default_struct_values(); fmt.println("\n# union_type"); union_type(); fmt.println("\n# parametric_polymorphism"); parametric_polymorphism(); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d33cee97b..8c38d7441 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -986,8 +986,8 @@ void check_struct_field_decl(Checker *c, AstNode *decl, Array *fields, } // Returns filled field_count -Array check_fields(Checker *c, AstNode *node, Array decls, - isize init_field_capacity, String context) { +Array check_struct_fields(Checker *c, AstNode *node, Array params, + isize init_field_capacity, String context) { gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); defer (gb_temp_arena_memory_end(tmp)); @@ -998,30 +998,152 @@ Array check_fields(Checker *c, AstNode *node, Array decls, map_init(&entity_map, c->tmp_allocator, 2*init_field_capacity); - if (node != nullptr) { - GB_ASSERT(node->kind != AstNode_UnionType); - } + GB_ASSERT(node->kind == AstNode_StructType); - check_collect_entities(c, decls); - for_array(i, c->context.scope->elements.entries) { - Entity *e = c->context.scope->elements.entries[i].value; - DeclInfo *d = nullptr; - switch (e->kind) { - default: continue; - case Entity_Constant: - case Entity_TypeName: - d = decl_info_of_entity(&c->info, e); - if (d != nullptr) { - check_entity_decl(c, e, d, nullptr); - } - break; + isize variable_count = 0; + for_array(i, params) { + AstNode *field = params[i]; + if (ast_node_expect(field, AstNode_Field)) { + ast_node(f, Field, field); + variable_count += gb_max(f->names.count, 1); } } - for_array(decl_index, decls) { - check_struct_field_decl(c, decls[decl_index], &fields, &entity_map, node, context, context == "struct"); + i32 field_src_index = 0; + for_array(i, params) { + AstNode *param = params[i]; + if (param->kind != AstNode_Field) { + continue; + } + ast_node(p, Field, param); + AstNode *type_expr = p->type; + Type *type = nullptr; + AstNode *default_value = unparen_expr(p->default_value); + ExactValue value = {}; + bool default_is_nil = false; + bool detemine_type_from_operand = false; + + + if (type_expr == nullptr) { + Operand o = {}; + check_expr_or_type(c, &o, default_value); + if (is_operand_nil(o)) { + default_is_nil = true; + } else if (o.mode != Addressing_Constant) { + error(default_value, "Default parameter must be a constant"); + } else { + value = o.value; + } + + type = default_type(o.type); + } else { + type = check_type(c, type_expr); + + if (default_value != nullptr) { + Operand o = {}; + check_expr_with_type_hint(c, &o, default_value, type); + + if (is_operand_nil(o)) { + default_is_nil = true; + } else if (o.mode != Addressing_Constant) { + error(default_value, "Default parameter must be a constant"); + } else { + value = o.value; + } + + check_is_assignable_to(c, &o, type); + } + + if (is_type_polymorphic(type)) { + type = nullptr; + } + } + if (type == nullptr) { + error(params[i], "Invalid parameter type"); + type = t_invalid; + } + if (is_type_untyped(type)) { + if (is_type_untyped_undef(type)) { + error(params[i], "Cannot determine parameter type from ---"); + } else { + error(params[i], "Cannot determine parameter type from a nil"); + } + type = t_invalid; + } + if (is_type_empty_union(type)) { + gbString str = type_to_string(type); + error(params[i], "Invalid use of an empty union `%s`", str); + gb_string_free(str); + type = t_invalid; + } + + bool is_using = (p->flags&FieldFlag_using) != 0; + + for_array(j, p->names) { + AstNode *name = p->names[j]; + if (!ast_node_expect(name, AstNode_Ident)) { + continue; + } + + Token name_token = name->Ident.token; + + Entity *field = nullptr; + field = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, field_src_index); + field->Variable.default_value = value; + field->Variable.default_is_nil = default_is_nil; + + add_entity(c, c->context.scope, name, field); + array_add(&fields, field); + + field_src_index += 1; + } + + Entity *using_index_expr = nullptr; + + if (is_using && p->names.count > 0) { + Type *first_type = fields[fields.count-1]->type; + Type *t = base_type(type_deref(first_type)); + + if (!is_type_struct(t) && !is_type_raw_union(t) && !is_type_bit_field(t) && + p->names.count >= 1 && + p->names[0]->kind == AstNode_Ident) { + Token name_token = p->names[0]->Ident.token; + if (is_type_indexable(t)) { + bool ok = true; + for_array(emi, entity_map.entries) { + Entity *e = entity_map.entries[emi].value; + if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { + if (is_type_indexable(e->type)) { + if (e->identifier != p->names[0]) { + ok = false; + using_index_expr = e; + break; + } + } + } + } + if (ok) { + using_index_expr = fields[fields.count-1]; + } else { + fields[fields.count-1]->flags &= ~EntityFlag_Using; + error(name_token, "Previous `using` for an index expression `%.*s`", LIT(name_token.string)); + } + } else { + gbString type_str = type_to_string(first_type); + error(name_token, "`using` cannot be applied to the field `%.*s` of type `%s`", LIT(name_token.string), type_str); + gb_string_free(type_str); + continue; + } + } + + populate_using_entity_map(c, node, type, &entity_map); + } } + // for_array(decl_index, params) { + // check_struct_field_decl(c, params[decl_index], &fields, &entity_map, node, context, context == "struct"); + // } + return fields; } @@ -1278,7 +1400,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array fields = {}; if (!is_polymorphic) { - fields = check_fields(c, node, st->fields, min_field_count, context); + fields = check_struct_fields(c, node, st->fields, min_field_count, context); } struct_type->Struct.scope = c->context.scope; @@ -1392,31 +1514,6 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) { } } -// void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) { -// GB_ASSERT(node->kind == AstNode_RawUnionType); -// GB_ASSERT(is_type_raw_union(union_type)); -// ast_node(ut, RawUnionType, node); - -// isize min_field_count = 0; -// for_array(i, ut->fields) { -// AstNode *field = ut->fields[i]; -// switch (field->kind) { -// case_ast_node(f, ValueDecl, field); -// min_field_count += f->names.count; -// case_end; -// } -// } - -// union_type->Struct.names = make_names_field_for_struct(c, c->context.scope); - -// auto fields = check_fields(c, node, ut->fields, min_field_count, str_lit("raw_union")); - -// union_type->Struct.scope = c->context.scope; -// union_type->Struct.fields = fields.data; -// union_type->Struct.field_count = fields.count; -// } - - void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) { ast_node(et, EnumType, node); GB_ASSERT(is_type_enum(enum_type)); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index d6c8f654d..9235d6055 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -472,24 +472,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo switch (e->kind) { case Entity_TypeName: { Type *t = base_type(e->type); - if (t->kind == Type_Struct) { - Scope *s = t->Struct.scope; - if (s != nullptr) { - for_array(i, s->elements.entries) { - Entity *f = s->elements.entries[i].value; - if (f->kind != Entity_Variable) { - Entity *found = scope_insert_entity(c->context.scope, f); - if (found != nullptr) { - gbString expr_str = expr_to_string(expr); - error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string)); - gb_string_free(expr_str); - return false; - } - f->using_parent = e; - } - } - } - } else if (t->kind == Type_Enum) { + if (t->kind == Type_Enum) { for (isize i = 0; i < t->Enum.field_count; i++) { Entity *f = t->Enum.fields[i]; Entity *found = scope_insert_entity(c->context.scope, f); @@ -502,7 +485,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo f->using_parent = e; } } else { - error(us->token, "`using` can be only applied to struct type entities"); + error(us->token, "`using` can be only applied to enum type entities"); } } break; diff --git a/src/checker.cpp b/src/checker.cpp index 7758d7803..dd53a7902 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1595,17 +1595,17 @@ Entity *find_core_entity(Checker *c, String name) { return e; } -Entity *find_sub_core_entity(TypeStruct *parent, String name) { - GB_ASSERT(parent->scope->parent->is_global); - Entity *e = current_scope_lookup_entity(parent->scope, name); +Type *find_core_type(Checker *c, String name) { + Entity *e = current_scope_lookup_entity(c->global_scope, name); if (e == nullptr) { compiler_error("Could not find type declaration for `%.*s`\n" "Is `_preload.odin` missing from the `core` directory relative to odin.exe?", LIT(name)); // NOTE(bill): This will exit the program as it's cannot continue without it! } - return e; + return e->type; } + void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type); void init_preload(Checker *c) { @@ -1617,7 +1617,7 @@ void init_preload(Checker *c) { GB_ASSERT(is_type_struct(type_info_entity->type)); TypeStruct *tis = &base_type(type_info_entity->type)->Struct; - Entity *type_info_enum_value = find_sub_core_entity(tis, str_lit("Enum_Value")); + Entity *type_info_enum_value = find_core_entity(c, str_lit("Type_Info_Enum_Value")); t_type_info_enum_value = type_info_enum_value->type; t_type_info_enum_value_ptr = make_type_pointer(c->allocator, t_type_info_enum_value); @@ -1627,31 +1627,27 @@ void init_preload(Checker *c) { Entity *type_info_variant = tis->fields_in_src_order[2]; Type *tiv_type = type_info_variant->type; GB_ASSERT(is_type_union(tiv_type)); - TypeUnion *tiv = &tiv_type->Union; - if (tiv->variants.count != 20) { - compiler_error("Invalid `Type_Info` layout"); - } - t_type_info_named = tiv->variants[ 0]; - t_type_info_integer = tiv->variants[ 1]; - t_type_info_rune = tiv->variants[ 2]; - t_type_info_float = tiv->variants[ 3]; - t_type_info_complex = tiv->variants[ 4]; - t_type_info_string = tiv->variants[ 5]; - t_type_info_boolean = tiv->variants[ 6]; - t_type_info_any = tiv->variants[ 7]; - t_type_info_pointer = tiv->variants[ 8]; - t_type_info_procedure = tiv->variants[ 9]; - t_type_info_array = tiv->variants[10]; - t_type_info_dynamic_array = tiv->variants[11]; - t_type_info_slice = tiv->variants[12]; - t_type_info_vector = tiv->variants[13]; - t_type_info_tuple = tiv->variants[14]; - t_type_info_struct = tiv->variants[15]; - t_type_info_union = tiv->variants[16]; - t_type_info_enum = tiv->variants[17]; - t_type_info_map = tiv->variants[18]; - t_type_info_bit_field = tiv->variants[19]; + t_type_info_named = find_core_type(c, str_lit("Type_Info_Named")); + t_type_info_integer = find_core_type(c, str_lit("Type_Info_Integer")); + t_type_info_rune = find_core_type(c, str_lit("Type_Info_Rune")); + t_type_info_float = find_core_type(c, str_lit("Type_Info_Float")); + t_type_info_complex = find_core_type(c, str_lit("Type_Info_Complex")); + t_type_info_string = find_core_type(c, str_lit("Type_Info_String")); + t_type_info_boolean = find_core_type(c, str_lit("Type_Info_Boolean")); + t_type_info_any = find_core_type(c, str_lit("Type_Info_Any")); + t_type_info_pointer = find_core_type(c, str_lit("Type_Info_Pointer")); + t_type_info_procedure = find_core_type(c, str_lit("Type_Info_Procedure")); + t_type_info_array = find_core_type(c, str_lit("Type_Info_Array")); + t_type_info_dynamic_array = find_core_type(c, str_lit("Type_Info_Dynamic_Array")); + t_type_info_slice = find_core_type(c, str_lit("Type_Info_Slice")); + t_type_info_vector = find_core_type(c, str_lit("Type_Info_Vector")); + t_type_info_tuple = find_core_type(c, str_lit("Type_Info_Tuple")); + t_type_info_struct = find_core_type(c, str_lit("Type_Info_Struct")); + t_type_info_union = find_core_type(c, str_lit("Type_Info_Union")); + t_type_info_enum = find_core_type(c, str_lit("Type_Info_Enum")); + t_type_info_map = find_core_type(c, str_lit("Type_Info_Map")); + t_type_info_bit_field = find_core_type(c, str_lit("Type_Info_Bit_Field")); t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named); t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer); diff --git a/src/parser.cpp b/src/parser.cpp index 730f16d06..37412c157 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -130,6 +130,7 @@ enum FieldFlag { FieldFlag_c_vararg = 1<<3, FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg, + FieldFlag_Struct = FieldFlag_using, }; enum StmtAllowFlag { @@ -3478,6 +3479,11 @@ AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) { isize total_name_count = 0; + AstNode *params = parse_field_list(f, &total_name_count, FieldFlag_Struct, Token_CloseBrace, true, false); + if (name_count_) *name_count_ = total_name_count; + return params; + +#if 0 while (f->curr_token.kind != Token_CloseBrace && f->curr_token.kind != Token_EOF) { AstNode *decl = parse_stmt(f); @@ -3508,6 +3514,7 @@ AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) { if (name_count_) *name_count_ = total_name_count; return ast_field_list(f, start_token, decls); +#endif } AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters, bool allow_type_token) {