Use comma for struct field separators (disallow nesting)

This commit is contained in:
Ginger Bill
2017-09-21 23:18:28 +01:00
parent 95fb5fa46c
commit c43d66c286
20 changed files with 709 additions and 654 deletions
+149 -145
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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,
} }
+5 -5
View File
@@ -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 {
+6 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+7
View File
@@ -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) {