mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
Use comma for struct field separators (disallow nesting)
This commit is contained in:
+149
-145
@@ -35,102 +35,103 @@ Calling_Convention :: enum {
|
|||||||
}
|
}
|
||||||
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
||||||
// The compiler relies upon this _exact_ order
|
// The compiler relies upon this _exact_ order
|
||||||
Type_Info :: struct #ordered {
|
|
||||||
// Core Types
|
Type_Info_Enum_Value :: union {
|
||||||
Enum_Value :: union {
|
rune,
|
||||||
rune,
|
i8, i16, i32, i64, i128, int,
|
||||||
i8, i16, i32, i64, i128, int,
|
u8, u16, u32, u64, u128, uint,
|
||||||
u8, u16, u32, u64, u128, uint,
|
f32, f64,
|
||||||
f32, f64,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// Variant Types
|
// Variant Types
|
||||||
Named :: struct #ordered {name: string; base: ^Type_Info};
|
Type_Info_Named :: struct #ordered {name: string, base: ^Type_Info};
|
||||||
Integer :: struct #ordered {signed: bool};
|
Type_Info_Integer :: struct #ordered {signed: bool};
|
||||||
Rune :: struct{};
|
Type_Info_Rune :: struct{};
|
||||||
Float :: struct{};
|
Type_Info_Float :: struct{};
|
||||||
Complex :: struct{};
|
Type_Info_Complex :: struct{};
|
||||||
String :: struct{};
|
Type_Info_String :: struct{};
|
||||||
Boolean :: struct{};
|
Type_Info_Boolean :: struct{};
|
||||||
Any :: struct{};
|
Type_Info_Any :: struct{};
|
||||||
Pointer :: struct #ordered {
|
Type_Info_Pointer :: struct #ordered {
|
||||||
elem: ^Type_Info; // nil -> rawptr
|
elem: ^Type_Info // nil -> rawptr
|
||||||
};
|
};
|
||||||
Procedure :: struct #ordered {
|
Type_Info_Procedure :: struct #ordered {
|
||||||
params: ^Type_Info; // Type_Info.Tuple
|
params: ^Type_Info, // Type_Info_Tuple
|
||||||
results: ^Type_Info; // Type_Info.Tuple
|
results: ^Type_Info, // Type_Info_Tuple
|
||||||
variadic: bool;
|
variadic: bool,
|
||||||
convention: Calling_Convention;
|
convention: Calling_Convention,
|
||||||
};
|
};
|
||||||
Array :: struct #ordered {
|
Type_Info_Array :: struct #ordered {
|
||||||
elem: ^Type_Info;
|
elem: ^Type_Info,
|
||||||
elem_size: int;
|
elem_size: int,
|
||||||
count: int;
|
count: int,
|
||||||
};
|
};
|
||||||
Dynamic_Array :: struct #ordered {elem: ^Type_Info; elem_size: int};
|
Type_Info_Dynamic_Array :: struct #ordered {elem: ^Type_Info, elem_size: int};
|
||||||
Slice :: struct #ordered {elem: ^Type_Info; elem_size: int};
|
Type_Info_Slice :: struct #ordered {elem: ^Type_Info, elem_size: int};
|
||||||
Vector :: struct #ordered {elem: ^Type_Info; elem_size, count: int};
|
Type_Info_Vector :: struct #ordered {elem: ^Type_Info, elem_size, count: int};
|
||||||
Tuple :: struct #ordered { // Only really used for procedures
|
Type_Info_Tuple :: struct #ordered { // Only really used for procedures
|
||||||
types: []^Type_Info;
|
types: []^Type_Info,
|
||||||
names: []string;
|
names: []string,
|
||||||
};
|
};
|
||||||
Struct :: struct #ordered {
|
Type_Info_Struct :: struct #ordered {
|
||||||
types: []^Type_Info;
|
types: []^Type_Info,
|
||||||
names: []string;
|
names: []string,
|
||||||
offsets: []int; // offsets may not be used in tuples
|
offsets: []int, // offsets may not be used in tuples
|
||||||
usings: []bool; // usings may not be used in tuples
|
usings: []bool, // usings may not be used in tuples
|
||||||
is_packed: bool;
|
is_packed: bool,
|
||||||
is_ordered: bool;
|
is_ordered: bool,
|
||||||
is_raw_union: bool;
|
is_raw_union: bool,
|
||||||
custom_align: bool;
|
custom_align: bool,
|
||||||
};
|
};
|
||||||
Union :: struct #ordered {
|
Type_Info_Union :: struct #ordered {
|
||||||
variants: []^Type_Info;
|
variants: []^Type_Info,
|
||||||
tag_offset: int;
|
tag_offset: int,
|
||||||
};
|
};
|
||||||
Enum :: struct #ordered {
|
Type_Info_Enum :: struct #ordered {
|
||||||
base: ^Type_Info;
|
base: ^Type_Info,
|
||||||
names: []string;
|
names: []string,
|
||||||
values: []Enum_Value;
|
values: []Type_Info_Enum_Value,
|
||||||
};
|
};
|
||||||
Map :: struct #ordered {
|
Type_Info_Map :: struct #ordered {
|
||||||
key: ^Type_Info;
|
key: ^Type_Info,
|
||||||
value: ^Type_Info;
|
value: ^Type_Info,
|
||||||
generated_struct: ^Type_Info;
|
generated_struct: ^Type_Info,
|
||||||
};
|
};
|
||||||
Bit_Field :: struct #ordered {
|
Type_Info_Bit_Field :: struct #ordered {
|
||||||
names: []string;
|
names: []string,
|
||||||
bits: []i32;
|
bits: []i32,
|
||||||
offsets: []i32;
|
offsets: []i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Type_Info :: struct #ordered {
|
||||||
// Fields
|
// Fields
|
||||||
size: int;
|
size: int,
|
||||||
align: int;
|
align: int,
|
||||||
|
|
||||||
variant: union {
|
variant: union {
|
||||||
Named,
|
Type_Info_Named,
|
||||||
Integer,
|
Type_Info_Integer,
|
||||||
Rune,
|
Type_Info_Rune,
|
||||||
Float,
|
Type_Info_Float,
|
||||||
Complex,
|
Type_Info_Complex,
|
||||||
String,
|
Type_Info_String,
|
||||||
Boolean,
|
Type_Info_Boolean,
|
||||||
Any,
|
Type_Info_Any,
|
||||||
Pointer,
|
Type_Info_Pointer,
|
||||||
Procedure,
|
Type_Info_Procedure,
|
||||||
Array,
|
Type_Info_Array,
|
||||||
Dynamic_Array,
|
Type_Info_Dynamic_Array,
|
||||||
Slice,
|
Type_Info_Slice,
|
||||||
Vector,
|
Type_Info_Vector,
|
||||||
Tuple,
|
Type_Info_Tuple,
|
||||||
Struct,
|
Type_Info_Struct,
|
||||||
Union,
|
Type_Info_Union,
|
||||||
Enum,
|
Type_Info_Enum,
|
||||||
Map,
|
Type_Info_Map,
|
||||||
Bit_Field,
|
Type_Info_Bit_Field,
|
||||||
};
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(bill): only the ones that are needed (not all types)
|
// 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)
|
// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
|
||||||
|
|
||||||
Allocator :: struct #ordered {
|
Allocator_Mode :: enum u8 {
|
||||||
Mode :: enum u8 {
|
Alloc,
|
||||||
Alloc,
|
Free,
|
||||||
Free,
|
FreeAll,
|
||||||
FreeAll,
|
Resize,
|
||||||
Resize,
|
}
|
||||||
}
|
|
||||||
Proc :: #type proc(allocator_data: rawptr, mode: Mode,
|
|
||||||
size, alignment: int,
|
|
||||||
old_memory: rawptr, old_size: int, flags: u64 = 0) -> rawptr;
|
|
||||||
|
|
||||||
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 {
|
Context :: struct #ordered {
|
||||||
allocator: Allocator;
|
allocator: Allocator,
|
||||||
thread_id: int;
|
thread_id: int,
|
||||||
|
|
||||||
user_data: any;
|
user_data: any,
|
||||||
user_index: int;
|
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);
|
DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
|
||||||
|
|
||||||
Source_Code_Location :: struct #ordered {
|
Source_Code_Location :: struct #ordered {
|
||||||
file_path: string;
|
file_path: string,
|
||||||
line, column: i64;
|
line, column: i64,
|
||||||
procedure: string;
|
procedure: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
__INITIAL_MAP_CAP :: 16;
|
__INITIAL_MAP_CAP :: 16;
|
||||||
|
|
||||||
__Map_Key :: struct #ordered {
|
__Map_Key :: struct #ordered {
|
||||||
hash: u128;
|
hash: u128,
|
||||||
str: string;
|
str: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
__Map_Find_Result :: struct #ordered {
|
__Map_Find_Result :: struct #ordered {
|
||||||
hash_index: int;
|
hash_index: int,
|
||||||
entry_prev: int;
|
entry_prev: int,
|
||||||
entry_index: int;
|
entry_index: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
__Map_Entry_Header :: struct #ordered {
|
__Map_Entry_Header :: struct #ordered {
|
||||||
key: __Map_Key;
|
key: __Map_Key,
|
||||||
next: int;
|
next: int,
|
||||||
/*
|
/*
|
||||||
value: Value_Type;
|
value: Value_Type,
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
__Map_Header :: struct #ordered {
|
__Map_Header :: struct #ordered {
|
||||||
m: ^raw.Map;
|
m: ^raw.Map,
|
||||||
is_key_string: bool;
|
is_key_string: bool,
|
||||||
entry_size: int;
|
entry_size: int,
|
||||||
entry_align: int;
|
entry_align: int,
|
||||||
value_offset: int;
|
value_offset: int,
|
||||||
value_size: int;
|
value_size: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -214,7 +218,7 @@ type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
|||||||
|
|
||||||
base := info;
|
base := info;
|
||||||
match i in base.variant {
|
match i in base.variant {
|
||||||
case Type_Info.Named: base = i.base;
|
case Type_Info_Named: base = i.base;
|
||||||
}
|
}
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
@@ -225,8 +229,8 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info {
|
|||||||
|
|
||||||
base := info;
|
base := info;
|
||||||
match i in base.variant {
|
match i in base.variant {
|
||||||
case Type_Info.Named: base = i.base;
|
case Type_Info_Named: base = i.base;
|
||||||
case Type_Info.Enum: base = i.base;
|
case Type_Info_Enum: base = i.base;
|
||||||
}
|
}
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
@@ -281,26 +285,26 @@ __check_context :: proc() {
|
|||||||
|
|
||||||
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
|
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
|
||||||
a := context.allocator;
|
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 {
|
free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline {
|
||||||
if ptr == nil do return;
|
if ptr == nil do return;
|
||||||
if a.procedure == 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_ptr :: proc(ptr: rawptr) #inline do free_ptr_with_allocator(context.allocator, ptr);
|
||||||
|
|
||||||
free_all :: proc() #inline {
|
free_all :: proc() #inline {
|
||||||
a := context.allocator;
|
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 {
|
resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
|
||||||
a := context.allocator;
|
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);
|
new_size := capacity * size_of(E);
|
||||||
allocator := a.allocator;
|
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;
|
if new_data == nil do return false;
|
||||||
|
|
||||||
a.data = new_data;
|
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 {
|
__get_map_header :: proc(m: ^$T/map[$K]$V) -> __Map_Header #cc_contextless {
|
||||||
header := __Map_Header{m = cast(^raw.Map)m};
|
header := __Map_Header{m = cast(^raw.Map)m};
|
||||||
Entry :: struct {
|
Entry :: struct {
|
||||||
key: __Map_Key;
|
key: __Map_Key,
|
||||||
next: int;
|
next: int,
|
||||||
value: V;
|
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.is_key_string = is_string;
|
||||||
header.entry_size = size_of(Entry);
|
header.entry_size = size_of(Entry);
|
||||||
header.entry_align = align_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;
|
map_key: __Map_Key;
|
||||||
ti := type_info_base_without_enum(type_info_of(K));
|
ti := type_info_base_without_enum(type_info_of(K));
|
||||||
match _ in ti.variant {
|
match _ in ti.variant {
|
||||||
case Type_Info.Integer:
|
case Type_Info_Integer:
|
||||||
match 8*size_of(key) {
|
match 8*size_of(key) {
|
||||||
case 8: map_key.hash = u128(( ^u8)(&key)^);
|
case 8: map_key.hash = u128(( ^u8)(&key)^);
|
||||||
case 16: map_key.hash = u128(( ^u16)(&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 128: map_key.hash = u128((^u128)(&key)^);
|
||||||
case: panic("Unhandled integer size");
|
case: panic("Unhandled integer size");
|
||||||
}
|
}
|
||||||
case Type_Info.Rune:
|
case Type_Info_Rune:
|
||||||
map_key.hash = u128((cast(^rune)&key)^);
|
map_key.hash = u128((cast(^rune)&key)^);
|
||||||
case Type_Info.Pointer:
|
case Type_Info_Pointer:
|
||||||
map_key.hash = u128(uint((^rawptr)(&key)^));
|
map_key.hash = u128(uint((^rawptr)(&key)^));
|
||||||
case Type_Info.Float:
|
case Type_Info_Float:
|
||||||
match 8*size_of(key) {
|
match 8*size_of(key) {
|
||||||
case 32: map_key.hash = u128((^u32)(&key)^);
|
case 32: map_key.hash = u128((^u32)(&key)^);
|
||||||
case 64: map_key.hash = u128((^u64)(&key)^);
|
case 64: map_key.hash = u128((^u64)(&key)^);
|
||||||
case: panic("Unhandled float size");
|
case: panic("Unhandled float size");
|
||||||
}
|
}
|
||||||
case Type_Info.String:
|
case Type_Info_String:
|
||||||
str := (^string)(&key)^;
|
str := (^string)(&key)^;
|
||||||
map_key.hash = __default_hash_string(str);
|
map_key.hash = __default_hash_string(str);
|
||||||
map_key.str = 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,
|
default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||||
size, alignment: int,
|
size, alignment: int,
|
||||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
||||||
using Allocator.Mode;
|
using Allocator_Mode;
|
||||||
|
|
||||||
match mode {
|
match mode {
|
||||||
case Alloc:
|
case Alloc:
|
||||||
@@ -788,7 +792,7 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap:
|
|||||||
new_size := cap * elem_size;
|
new_size := cap * elem_size;
|
||||||
allocator := array.allocator;
|
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;
|
if new_data == nil do return false;
|
||||||
|
|
||||||
array.data = new_data;
|
array.data = new_data;
|
||||||
|
|||||||
+10
-9
@@ -5,16 +5,17 @@ __multi3 :: proc(a, b: u128) -> u128 #cc_c #link_name "__multi3" {
|
|||||||
lower_mask :: u128(~u64(0) >> bits_in_dword_2);
|
lower_mask :: u128(~u64(0) >> bits_in_dword_2);
|
||||||
|
|
||||||
|
|
||||||
TWords :: struct #raw_union {
|
when ODIN_ENDIAN == "big" {
|
||||||
all: u128;
|
TWords :: struct #raw_union {
|
||||||
using _: struct {
|
all: u128,
|
||||||
when ODIN_ENDIAN == "big" {
|
using _: struct {lo, hi: u64},
|
||||||
lo, hi: u64;
|
|
||||||
} else {
|
|
||||||
hi, lo: u64;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
} else {
|
||||||
|
TWords :: struct #raw_union {
|
||||||
|
all: u128,
|
||||||
|
using _: struct {hi, lo: u64},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
r: TWords;
|
r: TWords;
|
||||||
t: u64;
|
t: u64;
|
||||||
|
|||||||
+4
-4
@@ -3,10 +3,10 @@
|
|||||||
// NOTE: This is only for floating point printing and nothing else
|
// NOTE: This is only for floating point printing and nothing else
|
||||||
|
|
||||||
Decimal :: struct {
|
Decimal :: struct {
|
||||||
digits: [384]u8; // big-endian digits
|
digits: [384]u8, // big-endian digits
|
||||||
count: int;
|
count: int,
|
||||||
decimal_point: int;
|
decimal_point: int,
|
||||||
neg, trunc: bool;
|
neg, trunc: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
decimal_to_string :: proc(buf: []u8, a: ^Decimal) -> string {
|
decimal_to_string :: proc(buf: []u8, a: ^Decimal) -> string {
|
||||||
|
|||||||
+59
-63
@@ -14,23 +14,23 @@ String_Buffer :: union {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Fmt_Info :: struct {
|
Fmt_Info :: struct {
|
||||||
minus: bool;
|
minus: bool,
|
||||||
plus: bool;
|
plus: bool,
|
||||||
space: bool;
|
space: bool,
|
||||||
zero: bool;
|
zero: bool,
|
||||||
hash: bool;
|
hash: bool,
|
||||||
width_set: bool;
|
width_set: bool,
|
||||||
prec_set: bool;
|
prec_set: bool,
|
||||||
|
|
||||||
width: int;
|
width: int,
|
||||||
prec: int;
|
prec: int,
|
||||||
indent: int;
|
indent: int,
|
||||||
|
|
||||||
reordered: bool;
|
reordered: bool,
|
||||||
good_arg_index: bool;
|
good_arg_index: bool,
|
||||||
|
|
||||||
buf: ^String_Buffer;
|
buf: ^String_Buffer,
|
||||||
arg: any; // Temporary
|
arg: any, // Temporary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -179,11 +179,10 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using Type_Info;
|
|
||||||
match info in ti.variant {
|
match info in ti.variant {
|
||||||
case Named:
|
case Type_Info_Named:
|
||||||
write_string(buf, info.name);
|
write_string(buf, info.name);
|
||||||
case Integer:
|
case Type_Info_Integer:
|
||||||
match {
|
match {
|
||||||
case ti == type_info_of(int): write_string(buf, "int");
|
case ti == type_info_of(int): write_string(buf, "int");
|
||||||
case ti == type_info_of(uint): write_string(buf, "uint");
|
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');
|
else do write_byte(buf, 'u');
|
||||||
write_int(buf, i64(8*ti.size), 10);
|
write_int(buf, i64(8*ti.size), 10);
|
||||||
}
|
}
|
||||||
case Rune:
|
case Type_Info_Rune:
|
||||||
write_string(buf, "rune");
|
write_string(buf, "rune");
|
||||||
case Float:
|
case Type_Info_Float:
|
||||||
match ti.size {
|
match ti.size {
|
||||||
case 2: write_string(buf, "f16");
|
case 2: write_string(buf, "f16");
|
||||||
case 4: write_string(buf, "f32");
|
case 4: write_string(buf, "f32");
|
||||||
case 8: write_string(buf, "f64");
|
case 8: write_string(buf, "f64");
|
||||||
}
|
}
|
||||||
case Complex:
|
case Type_Info_Complex:
|
||||||
match ti.size {
|
match ti.size {
|
||||||
case 4: write_string(buf, "complex32");
|
case 4: write_string(buf, "complex32");
|
||||||
case 8: write_string(buf, "complex64");
|
case 8: write_string(buf, "complex64");
|
||||||
case 16: write_string(buf, "complex128");
|
case 16: write_string(buf, "complex128");
|
||||||
}
|
}
|
||||||
case String: write_string(buf, "string");
|
case Type_Info_String: write_string(buf, "string");
|
||||||
case Boolean: write_string(buf, "bool");
|
case Type_Info_Boolean: write_string(buf, "bool");
|
||||||
case Any:
|
case Type_Info_Any:
|
||||||
write_string(buf, "any");
|
write_string(buf, "any");
|
||||||
|
|
||||||
case Pointer:
|
case Type_Info_Pointer:
|
||||||
if info.elem == nil {
|
if info.elem == nil {
|
||||||
write_string(buf, "rawptr");
|
write_string(buf, "rawptr");
|
||||||
} else {
|
} else {
|
||||||
write_string(buf, "^");
|
write_string(buf, "^");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
}
|
}
|
||||||
case Procedure:
|
case Type_Info_Procedure:
|
||||||
write_string(buf, "proc");
|
write_string(buf, "proc");
|
||||||
if info.params == nil {
|
if info.params == nil {
|
||||||
write_string(buf, "()");
|
write_string(buf, "()");
|
||||||
} else {
|
} else {
|
||||||
t := info.params.variant.(Tuple);
|
t := info.params.variant.(Type_Info_Tuple);
|
||||||
write_string(buf, "(");
|
write_string(buf, "(");
|
||||||
for t, i in t.types {
|
for t, i in t.types {
|
||||||
if i > 0 do write_string(buf, ", ");
|
if i > 0 do write_string(buf, ", ");
|
||||||
@@ -235,7 +234,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
write_string(buf, " -> ");
|
write_string(buf, " -> ");
|
||||||
write_type(buf, info.results);
|
write_type(buf, info.results);
|
||||||
}
|
}
|
||||||
case Tuple:
|
case Type_Info_Tuple:
|
||||||
count := len(info.names);
|
count := len(info.names);
|
||||||
if count != 1 do write_string(buf, "(");
|
if count != 1 do write_string(buf, "(");
|
||||||
for name, i in info.names {
|
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, ")");
|
if count != 1 do write_string(buf, ")");
|
||||||
|
|
||||||
case Array:
|
case Type_Info_Array:
|
||||||
write_string(buf, "[");
|
write_string(buf, "[");
|
||||||
fi := Fmt_Info{buf = buf};
|
fi := Fmt_Info{buf = buf};
|
||||||
write_int(buf, i64(info.count), 10);
|
write_int(buf, i64(info.count), 10);
|
||||||
write_string(buf, "]");
|
write_string(buf, "]");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
case Dynamic_Array:
|
case Type_Info_Dynamic_Array:
|
||||||
write_string(buf, "[dynamic]");
|
write_string(buf, "[dynamic]");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
case Slice:
|
case Type_Info_Slice:
|
||||||
write_string(buf, "[]");
|
write_string(buf, "[]");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
case Vector:
|
case Type_Info_Vector:
|
||||||
write_string(buf, "[vector ");
|
write_string(buf, "[vector ");
|
||||||
write_int(buf, i64(info.count), 10);
|
write_int(buf, i64(info.count), 10);
|
||||||
write_string(buf, "]");
|
write_string(buf, "]");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
|
|
||||||
case Map:
|
case Type_Info_Map:
|
||||||
write_string(buf, "map[");
|
write_string(buf, "map[");
|
||||||
write_type(buf, info.key);
|
write_type(buf, info.key);
|
||||||
write_byte(buf, ']');
|
write_byte(buf, ']');
|
||||||
write_type(buf, info.value);
|
write_type(buf, info.value);
|
||||||
|
|
||||||
case Struct:
|
case Type_Info_Struct:
|
||||||
write_string(buf, "struct ");
|
write_string(buf, "struct ");
|
||||||
if info.is_packed do write_string(buf, "#packed ");
|
if info.is_packed do write_string(buf, "#packed ");
|
||||||
if info.is_ordered do write_string(buf, "#ordered ");
|
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, '}');
|
write_byte(buf, '}');
|
||||||
|
|
||||||
case Union:
|
case Type_Info_Union:
|
||||||
write_string(buf, "union {");
|
write_string(buf, "union {");
|
||||||
for variant, i in info.variants {
|
for variant, i in info.variants {
|
||||||
if i > 0 do write_string(buf, ", ");
|
if i > 0 do write_string(buf, ", ");
|
||||||
@@ -302,7 +301,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
}
|
}
|
||||||
write_string(buf, "}");
|
write_string(buf, "}");
|
||||||
|
|
||||||
case Enum:
|
case Type_Info_Enum:
|
||||||
write_string(buf, "enum ");
|
write_string(buf, "enum ");
|
||||||
write_type(buf, info.base);
|
write_type(buf, info.base);
|
||||||
write_string(buf, " {");
|
write_string(buf, " {");
|
||||||
@@ -312,7 +311,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
}
|
}
|
||||||
write_string(buf, "}");
|
write_string(buf, "}");
|
||||||
|
|
||||||
case Bit_Field:
|
case Type_Info_Bit_Field:
|
||||||
write_string(buf, "bit_field ");
|
write_string(buf, "bit_field ");
|
||||||
if ti.align != 1 {
|
if ti.align != 1 {
|
||||||
write_string(buf, "#align ");
|
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) {
|
enum_value_to_string :: proc(v: any) -> (string, bool) {
|
||||||
v.type_info = type_info_base(v.type_info);
|
v.type_info = type_info_base(v.type_info);
|
||||||
|
|
||||||
using Type_Info;
|
|
||||||
match e in v.type_info.variant {
|
match e in v.type_info.variant {
|
||||||
case: return "", false;
|
case: return "", false;
|
||||||
case Enum:
|
case Type_Info_Enum:
|
||||||
get_str :: proc(i: $T, e: Enum) -> (string, bool) {
|
get_str :: proc(i: $T, e: Type_Info_Enum) -> (string, bool) {
|
||||||
if types.is_string(e.base) {
|
if types.is_string(e.base) {
|
||||||
for val, idx in e.values {
|
for val, idx in e.values {
|
||||||
if v, ok := val.(T); ok && v == i {
|
if v, ok := val.(T); ok && v == i {
|
||||||
@@ -718,10 +716,9 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using Type_Info;
|
|
||||||
match e in v.type_info.variant {
|
match e in v.type_info.variant {
|
||||||
case: fmt_bad_verb(fi, verb);
|
case: fmt_bad_verb(fi, verb);
|
||||||
case Enum:
|
case Type_Info_Enum:
|
||||||
match verb {
|
match verb {
|
||||||
case: fmt_bad_verb(fi, verb);
|
case: fmt_bad_verb(fi, verb);
|
||||||
case 'd', 'f':
|
case 'd', 'f':
|
||||||
@@ -741,11 +738,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using Type_Info;
|
|
||||||
match info in v.type_info.variant {
|
match info in v.type_info.variant {
|
||||||
case Named:
|
case Type_Info_Named:
|
||||||
match b in info.base.variant {
|
match b in info.base.variant {
|
||||||
case Struct:
|
case Type_Info_Struct:
|
||||||
if verb != 'v' {
|
if verb != 'v' {
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
return;
|
return;
|
||||||
@@ -792,21 +788,21 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
fmt_value(fi, any{v.data, info.base}, verb);
|
fmt_value(fi, any{v.data, info.base}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Boolean: fmt_arg(fi, v, verb);
|
case Type_Info_Boolean: fmt_arg(fi, v, verb);
|
||||||
case Integer: fmt_arg(fi, v, verb);
|
case Type_Info_Integer: fmt_arg(fi, v, verb);
|
||||||
case Rune: fmt_arg(fi, v, verb);
|
case Type_Info_Rune: fmt_arg(fi, v, verb);
|
||||||
case Float: fmt_arg(fi, v, verb);
|
case Type_Info_Float: fmt_arg(fi, v, verb);
|
||||||
case Complex: fmt_arg(fi, v, verb);
|
case Type_Info_Complex: fmt_arg(fi, v, verb);
|
||||||
case String: 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) {
|
if v.type_info == type_info_of(^Type_Info) {
|
||||||
write_type(fi.buf, (cast(^^Type_Info)v.data)^);
|
write_type(fi.buf, (cast(^^Type_Info)v.data)^);
|
||||||
} else {
|
} else {
|
||||||
fmt_pointer(fi, (cast(^rawptr)v.data)^, verb);
|
fmt_pointer(fi, (cast(^rawptr)v.data)^, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Array:
|
case Type_Info_Array:
|
||||||
write_byte(fi.buf, '[');
|
write_byte(fi.buf, '[');
|
||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
for i in 0..info.count {
|
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);
|
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Dynamic_Array:
|
case Type_Info_Dynamic_Array:
|
||||||
write_byte(fi.buf, '[');
|
write_byte(fi.buf, '[');
|
||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
array := cast(^raw.Dynamic_Array)v.data;
|
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);
|
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Slice:
|
case Type_Info_Slice:
|
||||||
write_byte(fi.buf, '[');
|
write_byte(fi.buf, '[');
|
||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
slice := cast(^[]u8)v.data;
|
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);
|
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Vector:
|
case Type_Info_Vector:
|
||||||
write_byte(fi.buf, '<');
|
write_byte(fi.buf, '<');
|
||||||
defer 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);
|
fmt_value(fi, any{rawptr(data), info.elem}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Map:
|
case Type_Info_Map:
|
||||||
if verb != 'v' {
|
if verb != 'v' {
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
return;
|
return;
|
||||||
@@ -859,9 +855,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
|
|
||||||
entries := &((cast(^raw.Map)v.data).entries);
|
entries := &((cast(^raw.Map)v.data).entries);
|
||||||
gs := type_info_base(info.generated_struct).variant.(Struct);
|
gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct);
|
||||||
ed := type_info_base(gs.types[1]).variant.(Dynamic_Array);
|
ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array);
|
||||||
entry_type := ed.elem.variant.(Struct);
|
entry_type := ed.elem.variant.(Type_Info_Struct);
|
||||||
entry_size := ed.elem_size;
|
entry_size := ed.elem_size;
|
||||||
|
|
||||||
for i in 0..entries.len {
|
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 {
|
if info.is_raw_union {
|
||||||
write_string(fi.buf, "(raw_union)");
|
write_string(fi.buf, "(raw_union)");
|
||||||
return;
|
return;
|
||||||
@@ -922,7 +918,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
if hash do write_string(fi.buf, ",\n");
|
if hash do write_string(fi.buf, ",\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
case Union:
|
case Type_Info_Union:
|
||||||
data := cast(^u8)v.data;
|
data := cast(^u8)v.data;
|
||||||
tipp := cast(^^Type_Info)(data + info.tag_offset);
|
tipp := cast(^^Type_Info)(data + info.tag_offset);
|
||||||
if data == nil || tipp == nil {
|
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);
|
fmt_arg(fi, any{data, ti}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Enum:
|
case Type_Info_Enum:
|
||||||
fmt_enum(fi, v, verb);
|
fmt_enum(fi, v, verb);
|
||||||
|
|
||||||
case Procedure:
|
case Type_Info_Procedure:
|
||||||
write_type(fi.buf, v.type_info);
|
write_type(fi.buf, v.type_info);
|
||||||
write_string(fi.buf, " @ ");
|
write_string(fi.buf, " @ ");
|
||||||
fmt_pointer(fi, (cast(^rawptr)v.data)^, 'p');
|
fmt_pointer(fi, (cast(^rawptr)v.data)^, 'p');
|
||||||
|
|||||||
+43
-47
@@ -64,9 +64,7 @@ align_forward :: proc(ptr: rawptr, align: int) -> rawptr {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
AllocationHeader :: struct {
|
AllocationHeader :: struct {size: int};
|
||||||
size: int;
|
|
||||||
}
|
|
||||||
|
|
||||||
allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) {
|
allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) {
|
||||||
header.size = size;
|
header.size = size;
|
||||||
@@ -91,14 +89,14 @@ allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
|
|||||||
// Custom allocators
|
// Custom allocators
|
||||||
|
|
||||||
Arena :: struct {
|
Arena :: struct {
|
||||||
backing: Allocator;
|
backing: Allocator,
|
||||||
memory: []u8;
|
memory: []u8,
|
||||||
temp_count: int;
|
temp_count: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
ArenaTempMemory :: struct {
|
ArenaTempMemory :: struct {
|
||||||
arena: ^Arena;
|
arena: ^Arena,
|
||||||
original_count: int;
|
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,
|
size, alignment: int,
|
||||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
||||||
using Allocator.Mode;
|
using Allocator_Mode;
|
||||||
arena := cast(^Arena)allocator_data;
|
arena := cast(^Arena)allocator_data;
|
||||||
|
|
||||||
match mode {
|
match mode {
|
||||||
@@ -202,46 +200,45 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
|||||||
|
|
||||||
WORD_SIZE :: size_of(int);
|
WORD_SIZE :: size_of(int);
|
||||||
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
||||||
using Type_Info;
|
|
||||||
match info in type_info.variant {
|
match info in type_info.variant {
|
||||||
case Named:
|
case Type_Info_Named:
|
||||||
return align_of_type_info(info.base);
|
return align_of_type_info(info.base);
|
||||||
case Integer:
|
case Type_Info_Integer:
|
||||||
return type_info.align;
|
return type_info.align;
|
||||||
case Rune:
|
case Type_Info_Rune:
|
||||||
return type_info.align;
|
return type_info.align;
|
||||||
case Float:
|
case Type_Info_Float:
|
||||||
return type_info.align;
|
return type_info.align;
|
||||||
case String:
|
case Type_Info_String:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Boolean:
|
case Type_Info_Boolean:
|
||||||
return 1;
|
return 1;
|
||||||
case Any:
|
case Type_Info_Any:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Pointer:
|
case Type_Info_Pointer:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Procedure:
|
case Type_Info_Procedure:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Array:
|
case Type_Info_Array:
|
||||||
return align_of_type_info(info.elem);
|
return align_of_type_info(info.elem);
|
||||||
case Dynamic_Array:
|
case Type_Info_Dynamic_Array:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Slice:
|
case Type_Info_Slice:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Vector:
|
case Type_Info_Vector:
|
||||||
size := size_of_type_info(info.elem);
|
size := size_of_type_info(info.elem);
|
||||||
count := int(max(prev_pow2(i64(info.count)), 1));
|
count := int(max(prev_pow2(i64(info.count)), 1));
|
||||||
total := size * count;
|
total := size * count;
|
||||||
return clamp(total, 1, MAX_ALIGN);
|
return clamp(total, 1, MAX_ALIGN);
|
||||||
case Tuple:
|
case Type_Info_Tuple:
|
||||||
return type_info.align;
|
return type_info.align;
|
||||||
case Struct:
|
case Type_Info_Struct:
|
||||||
return type_info.align;
|
return type_info.align;
|
||||||
case Union:
|
case Type_Info_Union:
|
||||||
return type_info.align;
|
return type_info.align;
|
||||||
case Enum:
|
case Type_Info_Enum:
|
||||||
return align_of_type_info(info.base);
|
return align_of_type_info(info.base);
|
||||||
case Map:
|
case Type_Info_Map:
|
||||||
return align_of_type_info(info.generated_struct);
|
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 {
|
size_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
||||||
WORD_SIZE :: size_of(int);
|
WORD_SIZE :: size_of(int);
|
||||||
using Type_Info;
|
|
||||||
match info in type_info.variant {
|
match info in type_info.variant {
|
||||||
case Named:
|
case Type_Info_Named:
|
||||||
return size_of_type_info(info.base);
|
return size_of_type_info(info.base);
|
||||||
case Integer:
|
case Type_Info_Integer:
|
||||||
return type_info.size;
|
return type_info.size;
|
||||||
case Rune:
|
case Type_Info_Rune:
|
||||||
return type_info.size;
|
return type_info.size;
|
||||||
case Float:
|
case Type_Info_Float:
|
||||||
return type_info.size;
|
return type_info.size;
|
||||||
case String:
|
case Type_Info_String:
|
||||||
return 2*WORD_SIZE;
|
return 2*WORD_SIZE;
|
||||||
case Boolean:
|
case Type_Info_Boolean:
|
||||||
return 1;
|
return 1;
|
||||||
case Any:
|
case Type_Info_Any:
|
||||||
return 2*WORD_SIZE;
|
return 2*WORD_SIZE;
|
||||||
case Pointer:
|
case Type_Info_Pointer:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Procedure:
|
case Type_Info_Procedure:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Array:
|
case Type_Info_Array:
|
||||||
count := info.count;
|
count := info.count;
|
||||||
if count == 0 do return 0;
|
if count == 0 do return 0;
|
||||||
size := size_of_type_info(info.elem);
|
size := size_of_type_info(info.elem);
|
||||||
align := align_of_type_info(info.elem);
|
align := align_of_type_info(info.elem);
|
||||||
alignment := align_formula(size, align);
|
alignment := align_formula(size, align);
|
||||||
return alignment*(count-1) + size;
|
return alignment*(count-1) + size;
|
||||||
case Dynamic_Array:
|
case Type_Info_Dynamic_Array:
|
||||||
return size_of(rawptr) + 2*size_of(int) + size_of(Allocator);
|
return size_of(rawptr) + 2*size_of(int) + size_of(Allocator);
|
||||||
case Slice:
|
case Type_Info_Slice:
|
||||||
return 2*WORD_SIZE;
|
return 2*WORD_SIZE;
|
||||||
case Vector:
|
case Type_Info_Vector:
|
||||||
count := info.count;
|
count := info.count;
|
||||||
if count == 0 do return 0;
|
if count == 0 do return 0;
|
||||||
size := size_of_type_info(info.elem);
|
size := size_of_type_info(info.elem);
|
||||||
align := align_of_type_info(info.elem);
|
align := align_of_type_info(info.elem);
|
||||||
alignment := align_formula(size, align);
|
alignment := align_formula(size, align);
|
||||||
return alignment*(count-1) + size;
|
return alignment*(count-1) + size;
|
||||||
case Struct:
|
case Type_Info_Struct:
|
||||||
return type_info.size;
|
return type_info.size;
|
||||||
case Union:
|
case Type_Info_Union:
|
||||||
return type_info.size;
|
return type_info.size;
|
||||||
case Enum:
|
case Type_Info_Enum:
|
||||||
return size_of_type_info(info.base);
|
return size_of_type_info(info.base);
|
||||||
case Map:
|
case Type_Info_Map:
|
||||||
return size_of_type_info(info.generated_struct);
|
return size_of_type_info(info.generated_struct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-20
@@ -40,9 +40,9 @@ RTLD_GLOBAL :: 0x100;
|
|||||||
args := _alloc_command_line_arguments();
|
args := _alloc_command_line_arguments();
|
||||||
|
|
||||||
_File_Time :: struct #ordered {
|
_File_Time :: struct #ordered {
|
||||||
seconds: i64;
|
seconds: i64,
|
||||||
nanoseconds: i32;
|
nanoseconds: i32,
|
||||||
reserved: i32;
|
reserved: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translated from
|
// Translated from
|
||||||
@@ -50,27 +50,27 @@ _File_Time :: struct #ordered {
|
|||||||
// Validity is not guaranteed.
|
// Validity is not guaranteed.
|
||||||
|
|
||||||
Stat :: struct #ordered {
|
Stat :: struct #ordered {
|
||||||
device_id: u64; // ID of device containing file
|
device_id: u64, // ID of device containing file
|
||||||
serial: u64; // File serial number
|
serial: u64, // File serial number
|
||||||
nlink: u32; // Number of hard links
|
nlink: u32, // Number of hard links
|
||||||
mode: u32; // Mode of the file
|
mode: u32, // Mode of the file
|
||||||
uid: u32; // User ID of the file's owner
|
uid: u32, // User ID of the file's owner
|
||||||
gid: u32; // Group ID of the file's group
|
gid: u32, // Group ID of the file's group
|
||||||
_padding: i32; // 32 bits of padding
|
_padding: i32, // 32 bits of padding
|
||||||
rdev: u64; // Device ID, if device
|
rdev: u64, // Device ID, if device
|
||||||
size: i64; // Size of the file, in bytes
|
size: i64, // Size of the file, in bytes
|
||||||
block_size: i64; // Optimal bllocksize for I/O
|
block_size: i64, // Optimal bllocksize for I/O
|
||||||
blocks: i64; // Number of 512-byte blocks allocated
|
blocks: i64, // Number of 512-byte blocks allocated
|
||||||
|
|
||||||
last_access: _File_Time; // Time of last access
|
last_access: _File_Time, // Time of last access
|
||||||
modified: _File_Time; // Time of last modification
|
modified: _File_Time, // Time of last modification
|
||||||
status_change: _File_Time; // Time of last status change
|
status_change: _File_Time, // Time of last status change
|
||||||
|
|
||||||
_reserve1,
|
_reserve1,
|
||||||
_reserve2,
|
_reserve2,
|
||||||
_reserve3: i64;
|
_reserve3: i64,
|
||||||
serial_numbe: u64; // File serial number...? Maybe.
|
serial_numbe: u64, // File serial number...? Maybe.
|
||||||
_reserve4: i64;
|
_reserve4: i64,
|
||||||
};
|
};
|
||||||
|
|
||||||
// File type
|
// File type
|
||||||
|
|||||||
+20
-20
@@ -45,32 +45,32 @@ RTLD_FIRST :: 0x100;
|
|||||||
args: [dynamic]string;
|
args: [dynamic]string;
|
||||||
|
|
||||||
_File_Time :: struct #ordered {
|
_File_Time :: struct #ordered {
|
||||||
seconds: i64;
|
seconds: i64,
|
||||||
nanoseconds: i64;
|
nanoseconds: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
Stat :: struct #ordered {
|
Stat :: struct #ordered {
|
||||||
device_id: i32; // ID of device containing file
|
device_id: i32, // ID of device containing file
|
||||||
mode: u16; // Mode of the file
|
mode: u16, // Mode of the file
|
||||||
nlink: u16; // Number of hard links
|
nlink: u16, // Number of hard links
|
||||||
serial: u64; // File serial number
|
serial: u64, // File serial number
|
||||||
uid: u32; // User ID of the file's owner
|
uid: u32, // User ID of the file's owner
|
||||||
gid: u32; // Group ID of the file's group
|
gid: u32, // Group ID of the file's group
|
||||||
rdev: i32; // Device ID, if device
|
rdev: i32, // Device ID, if device
|
||||||
|
|
||||||
last_access: File_Time; // Time of last access
|
last_access: File_Time, // Time of last access
|
||||||
modified: File_Time; // Time of last modification
|
modified: File_Time, // Time of last modification
|
||||||
status_change: File_Time; // Time of last status change
|
status_change: File_Time, // Time of last status change
|
||||||
created: File_Time; // Time of creation
|
created: File_Time, // Time of creation
|
||||||
|
|
||||||
size: i64; // Size of the file, in bytes
|
size: i64, // Size of the file, in bytes
|
||||||
blocks: i64; // Number of blocks allocated for the file
|
blocks: i64, // Number of blocks allocated for the file
|
||||||
block_size: i32; // Optimal blocksize for I/O
|
block_size: i32, // Optimal blocksize for I/O
|
||||||
flags: u32; // User-defined flags for the file
|
flags: u32, // User-defined flags for the file
|
||||||
gen_num: u32; // File generation number ...?
|
gen_num: u32, // File generation number ...?
|
||||||
_spare: i32; // RESERVED
|
_spare: i32, // RESERVED
|
||||||
_reserve1,
|
_reserve1,
|
||||||
_reserve2: i64; // RESERVED
|
_reserve2: i64, // RESERVED
|
||||||
};
|
};
|
||||||
|
|
||||||
// File type
|
// File type
|
||||||
|
|||||||
+18
-18
@@ -1,28 +1,28 @@
|
|||||||
Any :: struct #ordered {
|
Any :: struct #ordered {
|
||||||
data: rawptr;
|
data: rawptr,
|
||||||
type_info: ^Type_Info;
|
type_info: ^Type_Info,
|
||||||
};
|
}
|
||||||
|
|
||||||
String :: struct #ordered {
|
String :: struct #ordered {
|
||||||
data: ^u8;
|
data: ^u8,
|
||||||
len: int;
|
len: int,
|
||||||
};
|
}
|
||||||
|
|
||||||
Slice :: struct #ordered {
|
Slice :: struct #ordered {
|
||||||
data: rawptr;
|
data: rawptr,
|
||||||
len: int;
|
len: int,
|
||||||
cap: int;
|
cap: int,
|
||||||
};
|
}
|
||||||
|
|
||||||
Dynamic_Array :: struct #ordered {
|
Dynamic_Array :: struct #ordered {
|
||||||
data: rawptr;
|
data: rawptr,
|
||||||
len: int;
|
len: int,
|
||||||
cap: int;
|
cap: int,
|
||||||
allocator: Allocator;
|
allocator: Allocator,
|
||||||
};
|
}
|
||||||
|
|
||||||
Map :: struct #ordered {
|
Map :: struct #ordered {
|
||||||
hashes: [dynamic]int;
|
hashes: [dynamic]int,
|
||||||
entries: Dynamic_Array;
|
entries: Dynamic_Array,
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -202,16 +202,16 @@ append_float :: proc(buf: []u8, f: f64, fmt: u8, prec, bit_size: int) -> string
|
|||||||
|
|
||||||
|
|
||||||
DecimalSlice :: struct {
|
DecimalSlice :: struct {
|
||||||
digits: []u8;
|
digits: []u8,
|
||||||
count: int;
|
count: int,
|
||||||
decimal_point: int;
|
decimal_point: int,
|
||||||
neg: bool;
|
neg: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatInfo :: struct {
|
FloatInfo :: struct {
|
||||||
mantbits: uint;
|
mantbits: uint,
|
||||||
expbits: uint;
|
expbits: uint,
|
||||||
bias: int;
|
bias: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import "core:atomics.odin";
|
|||||||
import "core:os.odin";
|
import "core:os.odin";
|
||||||
|
|
||||||
Semaphore :: struct {
|
Semaphore :: struct {
|
||||||
// _handle: win32.Handle;
|
// _handle: win32.Handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
Mutex :: struct {
|
Mutex :: struct {
|
||||||
_semaphore: Semaphore;
|
_semaphore: Semaphore,
|
||||||
_counter: i32;
|
_counter: i32,
|
||||||
_owner: i32;
|
_owner: i32,
|
||||||
_recursion: i32;
|
_recursion: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
current_thread_id :: proc() -> i32 {
|
current_thread_id :: proc() -> i32 {
|
||||||
|
|||||||
@@ -2,20 +2,20 @@ when ODIN_OS == "windows" do import win32 "core:sys/windows.odin";
|
|||||||
import "core:atomics.odin";
|
import "core:atomics.odin";
|
||||||
|
|
||||||
Semaphore :: struct {
|
Semaphore :: struct {
|
||||||
_handle: win32.Handle;
|
_handle: win32.Handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mutex :: struct {
|
Mutex :: struct {
|
||||||
_semaphore: Semaphore;
|
_semaphore: Semaphore,
|
||||||
_counter: i32;
|
_counter: i32,
|
||||||
_owner: i32;
|
_owner: i32,
|
||||||
_recursion: i32;
|
_recursion: i32,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Mutex :: struct {
|
Mutex :: struct {
|
||||||
_critical_section: win32.Critical_Section;
|
_critical_section: win32.Critical_Section,
|
||||||
}
|
}
|
||||||
|
|
||||||
current_thread_id :: proc() -> i32 {
|
current_thread_id :: proc() -> i32 {
|
||||||
|
|||||||
+29
-29
@@ -14,40 +14,40 @@ Hglrc :: Handle;
|
|||||||
Color_Ref :: u32;
|
Color_Ref :: u32;
|
||||||
|
|
||||||
Layer_Plane_Descriptor :: struct {
|
Layer_Plane_Descriptor :: struct {
|
||||||
size: u16;
|
size: u16,
|
||||||
version: u16;
|
version: u16,
|
||||||
flags: u32;
|
flags: u32,
|
||||||
pixel_type: u8;
|
pixel_type: u8,
|
||||||
color_bits: u8;
|
color_bits: u8,
|
||||||
red_bits: u8;
|
red_bits: u8,
|
||||||
red_shift: u8;
|
red_shift: u8,
|
||||||
green_bits: u8;
|
green_bits: u8,
|
||||||
green_shift: u8;
|
green_shift: u8,
|
||||||
blue_bits: u8;
|
blue_bits: u8,
|
||||||
blue_shift: u8;
|
blue_shift: u8,
|
||||||
alpha_bits: u8;
|
alpha_bits: u8,
|
||||||
alpha_shift: u8;
|
alpha_shift: u8,
|
||||||
accum_bits: u8;
|
accum_bits: u8,
|
||||||
accum_red_bits: u8;
|
accum_red_bits: u8,
|
||||||
accum_green_bits: u8;
|
accum_green_bits: u8,
|
||||||
accum_blue_bits: u8;
|
accum_blue_bits: u8,
|
||||||
accum_alpha_bits: u8;
|
accum_alpha_bits: u8,
|
||||||
depth_bits: u8;
|
depth_bits: u8,
|
||||||
stencil_bits: u8;
|
stencil_bits: u8,
|
||||||
aux_buffers: u8;
|
aux_buffers: u8,
|
||||||
layer_type: u8;
|
layer_type: u8,
|
||||||
reserved: u8;
|
reserved: u8,
|
||||||
transparent: Color_Ref;
|
transparent: Color_Ref,
|
||||||
}
|
}
|
||||||
|
|
||||||
Point_Float :: struct {x, y: f32};
|
Point_Float :: struct {x, y: f32};
|
||||||
|
|
||||||
Glyph_Metrics_Float :: struct {
|
Glyph_Metrics_Float :: struct {
|
||||||
black_box_x: f32;
|
black_box_x: f32,
|
||||||
black_box_y: f32;
|
black_box_y: f32,
|
||||||
glyph_origin: Point_Float;
|
glyph_origin: Point_Float,
|
||||||
cell_inc_x: f32;
|
cell_inc_x: f32,
|
||||||
cell_inc_y: f32;
|
cell_inc_y: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Create_Context_Attribs_ARB_Type :: #type proc(hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc;
|
Create_Context_Attribs_ARB_Type :: #type proc(hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc;
|
||||||
|
|||||||
+82
-82
@@ -27,86 +27,86 @@ FALSE: Bool : 0;
|
|||||||
TRUE: Bool : 1;
|
TRUE: Bool : 1;
|
||||||
|
|
||||||
Point :: struct #ordered {
|
Point :: struct #ordered {
|
||||||
x, y: i32;
|
x, y: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Wnd_Class_Ex_A :: struct #ordered {
|
Wnd_Class_Ex_A :: struct #ordered {
|
||||||
size, style: u32;
|
size, style: u32,
|
||||||
wnd_proc: Wnd_Proc;
|
wnd_proc: Wnd_Proc,
|
||||||
cls_extra, wnd_extra: i32;
|
cls_extra, wnd_extra: i32,
|
||||||
instance: Hinstance;
|
instance: Hinstance,
|
||||||
icon: Hicon;
|
icon: Hicon,
|
||||||
cursor: Hcursor;
|
cursor: Hcursor,
|
||||||
background: Hbrush;
|
background: Hbrush,
|
||||||
menu_name, class_name: ^u8;
|
menu_name, class_name: ^u8,
|
||||||
sm: Hicon;
|
sm: Hicon,
|
||||||
}
|
}
|
||||||
|
|
||||||
Msg :: struct #ordered {
|
Msg :: struct #ordered {
|
||||||
hwnd: Hwnd;
|
hwnd: Hwnd,
|
||||||
message: u32;
|
message: u32,
|
||||||
wparam: Wparam;
|
wparam: Wparam,
|
||||||
lparam: Lparam;
|
lparam: Lparam,
|
||||||
time: u32;
|
time: u32,
|
||||||
pt: Point;
|
pt: Point,
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect :: struct #ordered {
|
Rect :: struct #ordered {
|
||||||
left: i32;
|
left: i32,
|
||||||
top: i32;
|
top: i32,
|
||||||
right: i32;
|
right: i32,
|
||||||
bottom: i32;
|
bottom: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Filetime :: struct #ordered {
|
Filetime :: struct #ordered {
|
||||||
lo, hi: u32;
|
lo, hi: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Systemtime :: struct #ordered {
|
Systemtime :: struct #ordered {
|
||||||
year, month: u16;
|
year, month: u16,
|
||||||
day_of_week, day: u16;
|
day_of_week, day: u16,
|
||||||
hour, minute, second, millisecond: u16;
|
hour, minute, second, millisecond: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
By_Handle_File_Information :: struct #ordered {
|
By_Handle_File_Information :: struct #ordered {
|
||||||
file_attributes: u32;
|
file_attributes: u32,
|
||||||
creation_time,
|
creation_time,
|
||||||
last_access_time,
|
last_access_time,
|
||||||
last_write_time: Filetime;
|
last_write_time: Filetime,
|
||||||
volume_serial_number,
|
volume_serial_number,
|
||||||
file_size_high,
|
file_size_high,
|
||||||
file_size_low,
|
file_size_low,
|
||||||
number_of_links,
|
number_of_links,
|
||||||
file_index_high,
|
file_index_high,
|
||||||
file_index_low: u32;
|
file_index_low: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
File_Attribute_Data :: struct #ordered {
|
File_Attribute_Data :: struct #ordered {
|
||||||
file_attributes: u32;
|
file_attributes: u32,
|
||||||
creation_time,
|
creation_time,
|
||||||
last_access_time,
|
last_access_time,
|
||||||
last_write_time: Filetime;
|
last_write_time: Filetime,
|
||||||
file_size_high,
|
file_size_high,
|
||||||
file_size_low: u32;
|
file_size_low: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Find_Data :: struct #ordered{
|
Find_Data :: struct #ordered{
|
||||||
file_attributes: u32;
|
file_attributes: u32,
|
||||||
creation_time: Filetime;
|
creation_time: Filetime,
|
||||||
last_access_time: Filetime;
|
last_access_time: Filetime,
|
||||||
last_write_time: Filetime;
|
last_write_time: Filetime,
|
||||||
file_size_high: u32;
|
file_size_high: u32,
|
||||||
file_size_low: u32;
|
file_size_low: u32,
|
||||||
reserved0: u32;
|
reserved0: u32,
|
||||||
reserved1: u32;
|
reserved1: u32,
|
||||||
file_name: [MAX_PATH]u8;
|
file_name: [MAX_PATH]u8,
|
||||||
alternate_file_name: [14]u8;
|
alternate_file_name: [14]u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
Security_Attributes :: struct #ordered {
|
Security_Attributes :: struct #ordered {
|
||||||
length: u32;
|
length: u32,
|
||||||
security_descriptor: rawptr;
|
security_descriptor: rawptr,
|
||||||
inherit_handle: Bool;
|
inherit_handle: Bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ Security_Attributes :: struct #ordered {
|
|||||||
Pixel_Format_Descriptor :: struct #ordered {
|
Pixel_Format_Descriptor :: struct #ordered {
|
||||||
size,
|
size,
|
||||||
version,
|
version,
|
||||||
flags: u32;
|
flags: u32,
|
||||||
|
|
||||||
pixel_type,
|
pixel_type,
|
||||||
color_bits,
|
color_bits,
|
||||||
@@ -135,33 +135,33 @@ Pixel_Format_Descriptor :: struct #ordered {
|
|||||||
stencil_bits,
|
stencil_bits,
|
||||||
aux_buffers,
|
aux_buffers,
|
||||||
layer_type,
|
layer_type,
|
||||||
reserved: u8;
|
reserved: u8,
|
||||||
|
|
||||||
layer_mask,
|
layer_mask,
|
||||||
visible_mask,
|
visible_mask,
|
||||||
damage_mask: u32;
|
damage_mask: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Critical_Section :: struct #ordered {
|
Critical_Section :: struct #ordered {
|
||||||
debug_info: ^Critical_Section_Debug;
|
debug_info: ^Critical_Section_Debug,
|
||||||
|
|
||||||
lock_count: i32;
|
lock_count: i32,
|
||||||
recursion_count: i32;
|
recursion_count: i32,
|
||||||
owning_thread: Handle;
|
owning_thread: Handle,
|
||||||
lock_semaphore: Handle;
|
lock_semaphore: Handle,
|
||||||
spin_count: ^u32;
|
spin_count: ^u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Critical_Section_Debug :: struct #ordered {
|
Critical_Section_Debug :: struct #ordered {
|
||||||
typ: u16;
|
typ: u16,
|
||||||
creator_back_trace_index: u16;
|
creator_back_trace_index: u16,
|
||||||
critical_section: ^Critical_Section;
|
critical_section: ^Critical_Section,
|
||||||
process_locks_list: ^List_Entry;
|
process_locks_list: ^List_Entry,
|
||||||
entry_count: u32;
|
entry_count: u32,
|
||||||
contention_count: u32;
|
contention_count: u32,
|
||||||
flags: u32;
|
flags: u32,
|
||||||
creator_back_trace_index_high: u16;
|
creator_back_trace_index_high: u16,
|
||||||
spare_word: u16;
|
spare_word: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
List_Entry :: struct #ordered {flink, blink: ^List_Entry};
|
List_Entry :: struct #ordered {flink, blink: ^List_Entry};
|
||||||
@@ -546,35 +546,35 @@ FILE_TYPE_PIPE :: 0x0003;
|
|||||||
|
|
||||||
|
|
||||||
Monitor_Info :: struct #ordered {
|
Monitor_Info :: struct #ordered {
|
||||||
size: u32;
|
size: u32,
|
||||||
monitor: Rect;
|
monitor: Rect,
|
||||||
work: Rect;
|
work: Rect,
|
||||||
flags: u32;
|
flags: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Window_Placement :: struct #ordered {
|
Window_Placement :: struct #ordered {
|
||||||
length: u32;
|
length: u32,
|
||||||
flags: u32;
|
flags: u32,
|
||||||
show_cmd: u32;
|
show_cmd: u32,
|
||||||
min_pos: Point;
|
min_pos: Point,
|
||||||
max_pos: Point;
|
max_pos: Point,
|
||||||
normal_pos: Rect;
|
normal_pos: Rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap_Info_Header :: struct #ordered {
|
Bitmap_Info_Header :: struct #ordered {
|
||||||
size: u32;
|
size: u32,
|
||||||
width, height: i32;
|
width, height: i32,
|
||||||
planes, bit_count: i16;
|
planes, bit_count: i16,
|
||||||
compression: u32;
|
compression: u32,
|
||||||
size_image: u32;
|
size_image: u32,
|
||||||
x_pels_per_meter: i32;
|
x_pels_per_meter: i32,
|
||||||
y_pels_per_meter: i32;
|
y_pels_per_meter: i32,
|
||||||
clr_used: u32;
|
clr_used: u32,
|
||||||
clr_important: u32;
|
clr_important: u32,
|
||||||
}
|
}
|
||||||
Bitmap_Info :: struct #ordered {
|
Bitmap_Info :: struct #ordered {
|
||||||
using header: Bitmap_Info_Header;
|
using header: Bitmap_Info_Header,
|
||||||
colors: [1]Rgb_Quad;
|
colors: [1]Rgb_Quad,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+14
-13
@@ -4,24 +4,25 @@ when ODIN_OS == "windows" {
|
|||||||
import win32 "core:sys/windows.odin";
|
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 {
|
Thread :: struct {
|
||||||
using specific: Os_Specific;
|
using specific: Thread_Os_Specific,
|
||||||
procedure: Proc;
|
procedure: Thread_Proc,
|
||||||
data: any;
|
data: any,
|
||||||
user_index: int;
|
user_index: int,
|
||||||
|
|
||||||
init_context: Context;
|
init_context: Context,
|
||||||
use_init_context: bool;
|
use_init_context: bool,
|
||||||
|
|
||||||
Proc :: #type proc(^Thread) -> int;
|
|
||||||
Os_Specific :: struct {
|
|
||||||
win32_thread: win32.Handle;
|
|
||||||
win32_thread_id: u32;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
create :: proc(procedure: Thread.Proc) -> ^Thread {
|
create :: proc(procedure: Thread_Proc) -> ^Thread {
|
||||||
win32_thread_id: u32;
|
win32_thread_id: u32;
|
||||||
|
|
||||||
__windows_thread_entry_proc :: proc(data: rawptr) -> i32 #cc_c {
|
__windows_thread_entry_proc :: proc(data: rawptr) -> i32 #cc_c {
|
||||||
|
|||||||
+21
-21
@@ -1,103 +1,103 @@
|
|||||||
is_signed :: proc(info: ^Type_Info) -> bool {
|
is_signed :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
match i in type_info_base(info).variant {
|
match i in type_info_base(info).variant {
|
||||||
case Type_Info.Integer: return i.signed;
|
case Type_Info_Integer: return i.signed;
|
||||||
case Type_Info.Float: return true;
|
case Type_Info_Float: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
is_integer :: proc(info: ^Type_Info) -> bool {
|
is_integer :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_rune :: proc(info: ^Type_Info) -> bool {
|
is_rune :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_float :: proc(info: ^Type_Info) -> bool {
|
is_float :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_complex :: proc(info: ^Type_Info) -> bool {
|
is_complex :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_any :: proc(info: ^Type_Info) -> bool {
|
is_any :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_string :: proc(info: ^Type_Info) -> bool {
|
is_string :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_boolean :: proc(info: ^Type_Info) -> bool {
|
is_boolean :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_pointer :: proc(info: ^Type_Info) -> bool {
|
is_pointer :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_procedure :: proc(info: ^Type_Info) -> bool {
|
is_procedure :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_array :: proc(info: ^Type_Info) -> bool {
|
is_array :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_dynamic_array :: proc(info: ^Type_Info) -> bool {
|
is_dynamic_array :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_dynamic_map :: proc(info: ^Type_Info) -> bool {
|
is_dynamic_map :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_slice :: proc(info: ^Type_Info) -> bool {
|
is_slice :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_vector :: proc(info: ^Type_Info) -> bool {
|
is_vector :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_tuple :: proc(info: ^Type_Info) -> bool {
|
is_tuple :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_struct :: proc(info: ^Type_Info) -> bool {
|
is_struct :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok && !s.is_raw_union;
|
||||||
}
|
}
|
||||||
is_raw_union :: proc(info: ^Type_Info) -> bool {
|
is_raw_union :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok && s.is_raw_union;
|
||||||
}
|
}
|
||||||
is_union :: proc(info: ^Type_Info) -> bool {
|
is_union :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
is_enum :: proc(info: ^Type_Info) -> bool {
|
is_enum :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-71
@@ -58,8 +58,8 @@ general_stuff :: proc() {
|
|||||||
|
|
||||||
{ // `expand_to_tuple` built-in procedure
|
{ // `expand_to_tuple` built-in procedure
|
||||||
Foo :: struct {
|
Foo :: struct {
|
||||||
x: int;
|
x: int,
|
||||||
b: bool;
|
b: bool,
|
||||||
}
|
}
|
||||||
f := Foo{137, true};
|
f := Foo{137, true};
|
||||||
x, b := expand_to_tuple(f);
|
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() {
|
default_struct_values :: proc() {
|
||||||
{
|
{
|
||||||
Vector3 :: struct {
|
Vector3 :: struct {
|
||||||
x: f32;
|
x: f32,
|
||||||
y: f32;
|
y: f32,
|
||||||
z: f32;
|
z: f32,
|
||||||
}
|
}
|
||||||
v: Vector3;
|
v: Vector3;
|
||||||
fmt.println(v);
|
fmt.println(v);
|
||||||
@@ -109,9 +90,9 @@ default_struct_values :: proc() {
|
|||||||
{
|
{
|
||||||
// Default values must be constants
|
// Default values must be constants
|
||||||
Vector3 :: struct {
|
Vector3 :: struct {
|
||||||
x: f32 = 1;
|
x: f32 = 1,
|
||||||
y: f32 = 4;
|
y: f32 = 4,
|
||||||
z: f32 = 9;
|
z: f32 = 9,
|
||||||
}
|
}
|
||||||
v: Vector3;
|
v: Vector3;
|
||||||
fmt.println(v);
|
fmt.println(v);
|
||||||
@@ -129,9 +110,9 @@ default_struct_values :: proc() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
Vector3 :: struct {
|
Vector3 :: struct {
|
||||||
x := 1.0;
|
x := 1.0,
|
||||||
y := 4.0;
|
y := 4.0,
|
||||||
z := 9.0;
|
z := 9.0,
|
||||||
}
|
}
|
||||||
stack_default: Vector3;
|
stack_default: Vector3;
|
||||||
stack_literal := Vector3{};
|
stack_literal := Vector3{};
|
||||||
@@ -197,13 +178,8 @@ union_type :: proc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 :: struct {
|
Vector3 :: struct {x, y, z: f32};
|
||||||
x, y, z: f32;
|
Quaternion :: struct {x, y, z: f32, w: f32 = 1};
|
||||||
};
|
|
||||||
Quaternion :: struct {
|
|
||||||
x, y, z: f32;
|
|
||||||
w: f32 = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// More realistic examples
|
// More realistic examples
|
||||||
{
|
{
|
||||||
@@ -214,23 +190,23 @@ union_type :: proc() {
|
|||||||
// an example of this for a basic game Entity.
|
// an example of this for a basic game Entity.
|
||||||
|
|
||||||
Entity :: struct {
|
Entity :: struct {
|
||||||
id: u64;
|
id: u64,
|
||||||
name: string;
|
name: string,
|
||||||
position: Vector3;
|
position: Vector3,
|
||||||
orientation: Quaternion;
|
orientation: Quaternion,
|
||||||
|
|
||||||
derived: any;
|
derived: any,
|
||||||
}
|
}
|
||||||
|
|
||||||
Frog :: struct {
|
Frog :: struct {
|
||||||
using entity: Entity;
|
using entity: Entity,
|
||||||
jump_height: f32;
|
jump_height: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Monster :: struct {
|
Monster :: struct {
|
||||||
using entity: Entity;
|
using entity: Entity,
|
||||||
is_robot: bool;
|
is_robot: bool,
|
||||||
is_zombie: bool;
|
is_zombie: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// See `parametric_polymorphism` procedure for details
|
// See `parametric_polymorphism` procedure for details
|
||||||
@@ -258,23 +234,23 @@ union_type :: proc() {
|
|||||||
// basic game Entity but using an union.
|
// basic game Entity but using an union.
|
||||||
|
|
||||||
Entity :: struct {
|
Entity :: struct {
|
||||||
id: u64;
|
id: u64,
|
||||||
name: string;
|
name: string,
|
||||||
position: Vector3;
|
position: Vector3,
|
||||||
orientation: Quaternion;
|
orientation: Quaternion,
|
||||||
|
|
||||||
derived: union {Frog, Monster};
|
derived: union {Frog, Monster},
|
||||||
}
|
}
|
||||||
|
|
||||||
Frog :: struct {
|
Frog :: struct {
|
||||||
using entity: ^Entity;
|
using entity: ^Entity,
|
||||||
jump_height: f32;
|
jump_height: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Monster :: struct {
|
Monster :: struct {
|
||||||
using entity: ^Entity;
|
using entity: ^Entity,
|
||||||
is_robot: bool;
|
is_robot: bool,
|
||||||
is_zombie: bool;
|
is_zombie: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// See `parametric_polymorphism` procedure for details
|
// See `parametric_polymorphism` procedure for details
|
||||||
@@ -386,18 +362,17 @@ parametric_polymorphism :: proc() {
|
|||||||
|
|
||||||
|
|
||||||
{ // Polymorphic Types and Type Specialization
|
{ // 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) {
|
Table :: struct(Key, Value: type) {
|
||||||
Slot :: struct {
|
count: int,
|
||||||
occupied: bool;
|
allocator: Allocator,
|
||||||
hash: u32;
|
slots: []Table_Slot(Key, Value),
|
||||||
key: Key;
|
|
||||||
value: Value;
|
|
||||||
}
|
|
||||||
SIZE_MIN :: 32;
|
|
||||||
|
|
||||||
count: int;
|
|
||||||
allocator: Allocator;
|
|
||||||
slots: []Slot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only allow types that are specializations of a (polymorphic) slice
|
// 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;
|
if table.allocator.procedure != nil do c.allocator = table.allocator;
|
||||||
|
|
||||||
push_context c {
|
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 {
|
push_context c {
|
||||||
old_slots := table.slots;
|
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);
|
allocate(table, cap);
|
||||||
|
|
||||||
for s in old_slots do if s.occupied {
|
for s in old_slots do if s.occupied {
|
||||||
@@ -588,7 +563,6 @@ threading_example :: proc() {
|
|||||||
main :: proc() {
|
main :: proc() {
|
||||||
when false {
|
when false {
|
||||||
fmt.println("\n# general_stuff"); general_stuff();
|
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# default_struct_values"); default_struct_values();
|
||||||
fmt.println("\n# union_type"); union_type();
|
fmt.println("\n# union_type"); union_type();
|
||||||
fmt.println("\n# parametric_polymorphism"); parametric_polymorphism();
|
fmt.println("\n# parametric_polymorphism"); parametric_polymorphism();
|
||||||
|
|||||||
+143
-46
@@ -986,8 +986,8 @@ void check_struct_field_decl(Checker *c, AstNode *decl, Array<Entity *> *fields,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns filled field_count
|
// Returns filled field_count
|
||||||
Array<Entity *> check_fields(Checker *c, AstNode *node, Array<AstNode *> decls,
|
Array<Entity *> check_struct_fields(Checker *c, AstNode *node, Array<AstNode *> params,
|
||||||
isize init_field_capacity, String context) {
|
isize init_field_capacity, String context) {
|
||||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
defer (gb_temp_arena_memory_end(tmp));
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
@@ -998,30 +998,152 @@ Array<Entity *> check_fields(Checker *c, AstNode *node, Array<AstNode *> decls,
|
|||||||
map_init(&entity_map, c->tmp_allocator, 2*init_field_capacity);
|
map_init(&entity_map, c->tmp_allocator, 2*init_field_capacity);
|
||||||
|
|
||||||
|
|
||||||
if (node != nullptr) {
|
GB_ASSERT(node->kind == AstNode_StructType);
|
||||||
GB_ASSERT(node->kind != AstNode_UnionType);
|
|
||||||
}
|
|
||||||
|
|
||||||
check_collect_entities(c, decls);
|
isize variable_count = 0;
|
||||||
for_array(i, c->context.scope->elements.entries) {
|
for_array(i, params) {
|
||||||
Entity *e = c->context.scope->elements.entries[i].value;
|
AstNode *field = params[i];
|
||||||
DeclInfo *d = nullptr;
|
if (ast_node_expect(field, AstNode_Field)) {
|
||||||
switch (e->kind) {
|
ast_node(f, Field, field);
|
||||||
default: continue;
|
variable_count += gb_max(f->names.count, 1);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for_array(decl_index, decls) {
|
i32 field_src_index = 0;
|
||||||
check_struct_field_decl(c, decls[decl_index], &fields, &entity_map, node, context, context == "struct");
|
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;
|
return fields;
|
||||||
}
|
}
|
||||||
@@ -1278,7 +1400,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
|
|||||||
Array<Entity *> fields = {};
|
Array<Entity *> fields = {};
|
||||||
|
|
||||||
if (!is_polymorphic) {
|
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;
|
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) {
|
void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) {
|
||||||
ast_node(et, EnumType, node);
|
ast_node(et, EnumType, node);
|
||||||
GB_ASSERT(is_type_enum(enum_type));
|
GB_ASSERT(is_type_enum(enum_type));
|
||||||
|
|||||||
+2
-19
@@ -472,24 +472,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
|
|||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
case Entity_TypeName: {
|
case Entity_TypeName: {
|
||||||
Type *t = base_type(e->type);
|
Type *t = base_type(e->type);
|
||||||
if (t->kind == Type_Struct) {
|
if (t->kind == Type_Enum) {
|
||||||
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) {
|
|
||||||
for (isize i = 0; i < t->Enum.field_count; i++) {
|
for (isize i = 0; i < t->Enum.field_count; i++) {
|
||||||
Entity *f = t->Enum.fields[i];
|
Entity *f = t->Enum.fields[i];
|
||||||
Entity *found = scope_insert_entity(c->context.scope, f);
|
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;
|
f->using_parent = e;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
} break;
|
||||||
|
|
||||||
|
|||||||
+25
-29
@@ -1595,17 +1595,17 @@ Entity *find_core_entity(Checker *c, String name) {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity *find_sub_core_entity(TypeStruct *parent, String name) {
|
Type *find_core_type(Checker *c, String name) {
|
||||||
GB_ASSERT(parent->scope->parent->is_global);
|
Entity *e = current_scope_lookup_entity(c->global_scope, name);
|
||||||
Entity *e = current_scope_lookup_entity(parent->scope, name);
|
|
||||||
if (e == nullptr) {
|
if (e == nullptr) {
|
||||||
compiler_error("Could not find type declaration for `%.*s`\n"
|
compiler_error("Could not find type declaration for `%.*s`\n"
|
||||||
"Is `_preload.odin` missing from the `core` directory relative to odin.exe?", LIT(name));
|
"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!
|
// 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 check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type);
|
||||||
|
|
||||||
void init_preload(Checker *c) {
|
void init_preload(Checker *c) {
|
||||||
@@ -1617,7 +1617,7 @@ void init_preload(Checker *c) {
|
|||||||
GB_ASSERT(is_type_struct(type_info_entity->type));
|
GB_ASSERT(is_type_struct(type_info_entity->type));
|
||||||
TypeStruct *tis = &base_type(type_info_entity->type)->Struct;
|
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 = type_info_enum_value->type;
|
||||||
t_type_info_enum_value_ptr = make_type_pointer(c->allocator, t_type_info_enum_value);
|
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];
|
Entity *type_info_variant = tis->fields_in_src_order[2];
|
||||||
Type *tiv_type = type_info_variant->type;
|
Type *tiv_type = type_info_variant->type;
|
||||||
GB_ASSERT(is_type_union(tiv_type));
|
GB_ASSERT(is_type_union(tiv_type));
|
||||||
TypeUnion *tiv = &tiv_type->Union;
|
|
||||||
|
|
||||||
if (tiv->variants.count != 20) {
|
t_type_info_named = find_core_type(c, str_lit("Type_Info_Named"));
|
||||||
compiler_error("Invalid `Type_Info` layout");
|
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_named = tiv->variants[ 0];
|
t_type_info_float = find_core_type(c, str_lit("Type_Info_Float"));
|
||||||
t_type_info_integer = tiv->variants[ 1];
|
t_type_info_complex = find_core_type(c, str_lit("Type_Info_Complex"));
|
||||||
t_type_info_rune = tiv->variants[ 2];
|
t_type_info_string = find_core_type(c, str_lit("Type_Info_String"));
|
||||||
t_type_info_float = tiv->variants[ 3];
|
t_type_info_boolean = find_core_type(c, str_lit("Type_Info_Boolean"));
|
||||||
t_type_info_complex = tiv->variants[ 4];
|
t_type_info_any = find_core_type(c, str_lit("Type_Info_Any"));
|
||||||
t_type_info_string = tiv->variants[ 5];
|
t_type_info_pointer = find_core_type(c, str_lit("Type_Info_Pointer"));
|
||||||
t_type_info_boolean = tiv->variants[ 6];
|
t_type_info_procedure = find_core_type(c, str_lit("Type_Info_Procedure"));
|
||||||
t_type_info_any = tiv->variants[ 7];
|
t_type_info_array = find_core_type(c, str_lit("Type_Info_Array"));
|
||||||
t_type_info_pointer = tiv->variants[ 8];
|
t_type_info_dynamic_array = find_core_type(c, str_lit("Type_Info_Dynamic_Array"));
|
||||||
t_type_info_procedure = tiv->variants[ 9];
|
t_type_info_slice = find_core_type(c, str_lit("Type_Info_Slice"));
|
||||||
t_type_info_array = tiv->variants[10];
|
t_type_info_vector = find_core_type(c, str_lit("Type_Info_Vector"));
|
||||||
t_type_info_dynamic_array = tiv->variants[11];
|
t_type_info_tuple = find_core_type(c, str_lit("Type_Info_Tuple"));
|
||||||
t_type_info_slice = tiv->variants[12];
|
t_type_info_struct = find_core_type(c, str_lit("Type_Info_Struct"));
|
||||||
t_type_info_vector = tiv->variants[13];
|
t_type_info_union = find_core_type(c, str_lit("Type_Info_Union"));
|
||||||
t_type_info_tuple = tiv->variants[14];
|
t_type_info_enum = find_core_type(c, str_lit("Type_Info_Enum"));
|
||||||
t_type_info_struct = tiv->variants[15];
|
t_type_info_map = find_core_type(c, str_lit("Type_Info_Map"));
|
||||||
t_type_info_union = tiv->variants[16];
|
t_type_info_bit_field = find_core_type(c, str_lit("Type_Info_Bit_Field"));
|
||||||
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_ptr = make_type_pointer(c->allocator, t_type_info_named);
|
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);
|
t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer);
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ enum FieldFlag {
|
|||||||
FieldFlag_c_vararg = 1<<3,
|
FieldFlag_c_vararg = 1<<3,
|
||||||
|
|
||||||
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg,
|
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg,
|
||||||
|
FieldFlag_Struct = FieldFlag_using,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum StmtAllowFlag {
|
enum StmtAllowFlag {
|
||||||
@@ -3478,6 +3479,11 @@ AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) {
|
|||||||
|
|
||||||
isize total_name_count = 0;
|
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 &&
|
while (f->curr_token.kind != Token_CloseBrace &&
|
||||||
f->curr_token.kind != Token_EOF) {
|
f->curr_token.kind != Token_EOF) {
|
||||||
AstNode *decl = parse_stmt(f);
|
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;
|
if (name_count_) *name_count_ = total_name_count;
|
||||||
return ast_field_list(f, start_token, decls);
|
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) {
|
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters, bool allow_type_token) {
|
||||||
|
|||||||
Reference in New Issue
Block a user