mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 22:58:46 +00:00
Change record field syntax
This commit is contained in:
+55
-55
@@ -13,67 +13,67 @@
|
|||||||
// 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 Type_Info_Member struct #ordered {
|
type Type_Info_Member struct #ordered {
|
||||||
name: string; // can be empty if tuple
|
name string; // can be empty if tuple
|
||||||
type_info: ^Type_Info;
|
type_info ^Type_Info;
|
||||||
offset: int; // offsets are not used in tuples
|
offset int; // offsets are not used in tuples
|
||||||
};
|
}
|
||||||
type Type_Info_Record struct #ordered {
|
type Type_Info_Record struct #ordered {
|
||||||
fields: []Type_Info_Member;
|
fields []Type_Info_Member;
|
||||||
size: int; // in bytes
|
size int; // in bytes
|
||||||
align: int; // in bytes
|
align int; // in bytes
|
||||||
packed: bool;
|
packed bool;
|
||||||
ordered: bool;
|
ordered bool;
|
||||||
};
|
}
|
||||||
|
|
||||||
type Type_Info union {
|
type Type_Info union {
|
||||||
Named: struct #ordered {
|
Named struct #ordered {
|
||||||
name: string;
|
name string;
|
||||||
base: ^Type_Info; // This will _not_ be a Type_Info.Named
|
base ^Type_Info; // This will _not_ be a Type_Info.Named
|
||||||
};
|
};
|
||||||
Integer: struct #ordered {
|
Integer struct #ordered {
|
||||||
size: int; // in bytes
|
size int; // in bytes
|
||||||
signed: bool;
|
signed bool;
|
||||||
};
|
};
|
||||||
Float: struct #ordered {
|
Float struct #ordered {
|
||||||
size: int; // in bytes
|
size int; // in bytes
|
||||||
};
|
};
|
||||||
Any: struct #ordered {};
|
Any struct #ordered {};
|
||||||
String: struct #ordered {};
|
String struct #ordered {};
|
||||||
Boolean: struct #ordered {};
|
Boolean struct #ordered {};
|
||||||
Pointer: struct #ordered {
|
Pointer struct #ordered {
|
||||||
elem: ^Type_Info; // nil -> rawptr
|
elem ^Type_Info; // nil -> rawptr
|
||||||
};
|
};
|
||||||
Maybe: struct #ordered {
|
Maybe struct #ordered {
|
||||||
elem: ^Type_Info;
|
elem ^Type_Info;
|
||||||
};
|
};
|
||||||
Procedure: struct #ordered {
|
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;
|
||||||
};
|
};
|
||||||
Array: struct #ordered {
|
Array struct #ordered {
|
||||||
elem: ^Type_Info;
|
elem ^Type_Info;
|
||||||
elem_size: int;
|
elem_size int;
|
||||||
count: int;
|
count int;
|
||||||
};
|
};
|
||||||
Slice: struct #ordered {
|
Slice struct #ordered {
|
||||||
elem: ^Type_Info;
|
elem ^Type_Info;
|
||||||
elem_size: int;
|
elem_size int;
|
||||||
};
|
};
|
||||||
Vector: struct #ordered {
|
Vector struct #ordered {
|
||||||
elem: ^Type_Info;
|
elem ^Type_Info;
|
||||||
elem_size: int;
|
elem_size int;
|
||||||
count: int;
|
count int;
|
||||||
align: int;
|
align int;
|
||||||
};
|
};
|
||||||
Tuple: Type_Info_Record;
|
Tuple Type_Info_Record;
|
||||||
Struct: Type_Info_Record;
|
Struct Type_Info_Record;
|
||||||
Union: Type_Info_Record;
|
Union Type_Info_Record;
|
||||||
Raw_Union: Type_Info_Record;
|
Raw_Union Type_Info_Record;
|
||||||
Enum: struct #ordered {
|
Enum struct #ordered {
|
||||||
base: ^Type_Info;
|
base ^Type_Info;
|
||||||
values: []i64;
|
values []i64;
|
||||||
names: []string;
|
names []string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -126,18 +126,18 @@ type Allocator_Proc proc(allocator_data rawptr, mode Allocator_Mode,
|
|||||||
|
|
||||||
|
|
||||||
type Allocator struct #ordered {
|
type Allocator struct #ordered {
|
||||||
procedure: Allocator_Proc;
|
procedure Allocator_Proc;
|
||||||
data: rawptr;
|
data rawptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type Context struct #ordered {
|
type Context struct #ordered {
|
||||||
thread_id: int;
|
thread_id int;
|
||||||
|
|
||||||
allocator: Allocator;
|
allocator Allocator;
|
||||||
|
|
||||||
user_data: rawptr;
|
user_data rawptr;
|
||||||
user_index: int;
|
user_index int;
|
||||||
}
|
}
|
||||||
|
|
||||||
#thread_local var __context Context;
|
#thread_local var __context Context;
|
||||||
|
|||||||
+6
-6
@@ -90,7 +90,7 @@ proc align_forward(ptr rawptr, align int) -> rawptr {
|
|||||||
|
|
||||||
|
|
||||||
type Allocation_Header struct {
|
type Allocation_Header struct {
|
||||||
size: int;
|
size int;
|
||||||
}
|
}
|
||||||
proc allocation_header_fill(header ^Allocation_Header, data rawptr, size int) {
|
proc allocation_header_fill(header ^Allocation_Header, data rawptr, size int) {
|
||||||
header.size = size;
|
header.size = size;
|
||||||
@@ -115,14 +115,14 @@ proc allocation_header(data rawptr) -> ^Allocation_Header {
|
|||||||
// Custom allocators
|
// Custom allocators
|
||||||
|
|
||||||
type Arena struct {
|
type Arena struct {
|
||||||
backing: Allocator;
|
backing Allocator;
|
||||||
memory: []byte;
|
memory []byte;
|
||||||
temp_count: int;
|
temp_count int;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Arena_Temp_Memory struct {
|
type Arena_Temp_Memory struct {
|
||||||
arena: ^Arena;
|
arena ^Arena;
|
||||||
original_count: int;
|
original_count int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
type File_Time u64;
|
type File_Time u64;
|
||||||
|
|
||||||
type File_Handle raw_union {
|
type File_Handle raw_union {
|
||||||
p: rawptr;
|
p rawptr;
|
||||||
i: int;
|
i int;
|
||||||
}
|
}
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
handle: File_Handle;
|
handle File_Handle;
|
||||||
last_write_time: File_Time;
|
last_write_time File_Time;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc open(name string) -> (File, bool) {
|
proc open(name string) -> (File, bool) {
|
||||||
|
|||||||
+5
-5
@@ -2,14 +2,14 @@
|
|||||||
#import "atomic.odin";
|
#import "atomic.odin";
|
||||||
|
|
||||||
type Semaphore struct {
|
type Semaphore struct {
|
||||||
handle: win32.HANDLE;
|
handle win32.HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutex struct {
|
type Mutex struct {
|
||||||
semaphore: Semaphore;
|
semaphore Semaphore;
|
||||||
counter: i32;
|
counter i32;
|
||||||
owner: i32;
|
owner i32;
|
||||||
recursion: i32;
|
recursion i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+45
-45
@@ -51,62 +51,62 @@ const SM_CYSCREEN = 1;
|
|||||||
const SW_SHOW = 5;
|
const SW_SHOW = 5;
|
||||||
|
|
||||||
type POINT struct #ordered {
|
type POINT struct #ordered {
|
||||||
x, y: i32;
|
x, y i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type WNDCLASSEXA struct #ordered {
|
type WNDCLASSEXA struct #ordered {
|
||||||
size, style: u32;
|
size, style u32;
|
||||||
wnd_proc: WNDPROC;
|
wnd_proc WNDPROC;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
type MSG struct #ordered {
|
type 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
type RECT struct #ordered {
|
type RECT struct #ordered {
|
||||||
left: i32;
|
left i32;
|
||||||
top: i32;
|
top i32;
|
||||||
right: i32;
|
right i32;
|
||||||
bottom: i32;
|
bottom i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
type FILETIME struct #ordered {
|
type FILETIME struct #ordered {
|
||||||
low_date_time, high_date_time: u32;
|
low_date_time, high_date_time u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
type BY_HANDLE_FILE_INFORMATION struct #ordered {
|
type 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
type WIN32_FILE_ATTRIBUTE_DATA struct #ordered {
|
type WIN32_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
type GET_FILEEX_INFO_LEVELS i32;
|
type GET_FILEEX_INFO_LEVELS i32;
|
||||||
@@ -209,9 +209,9 @@ const HEAP_ZERO_MEMORY = 0x00000008;
|
|||||||
// Synchronization
|
// Synchronization
|
||||||
|
|
||||||
type SECURITY_ATTRIBUTES struct #ordered {
|
type SECURITY_ATTRIBUTES struct #ordered {
|
||||||
length: u32;
|
length u32;
|
||||||
security_descriptor: rawptr;
|
security_descriptor rawptr;
|
||||||
inherit_handle: BOOL;
|
inherit_handle BOOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const INFINITE = 0xffffffff;
|
const INFINITE = 0xffffffff;
|
||||||
@@ -242,24 +242,24 @@ proc ReadBarrier () #foreign
|
|||||||
// GDI
|
// GDI
|
||||||
|
|
||||||
type BITMAPINFOHEADER struct #ordered {
|
type BITMAPINFOHEADER 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;
|
||||||
}
|
}
|
||||||
type BITMAPINFO struct #ordered {
|
type BITMAPINFO struct #ordered {
|
||||||
using header: BITMAPINFOHEADER;
|
using header BITMAPINFOHEADER;
|
||||||
colors: [1]RGBQUAD;
|
colors [1]RGBQUAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type RGBQUAD struct #ordered {
|
type RGBQUAD struct #ordered {
|
||||||
blue, green, red, reserved: byte;
|
blue, green, red, reserved byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BI_RGB = 0;
|
const BI_RGB = 0;
|
||||||
@@ -315,7 +315,7 @@ type wglCreateContextAttribsARBType proc(hdc HDC, hshareContext rawptr, attribLi
|
|||||||
type PIXELFORMATDESCRIPTOR struct #ordered {
|
type PIXELFORMATDESCRIPTOR struct #ordered {
|
||||||
size,
|
size,
|
||||||
version,
|
version,
|
||||||
flags: u32;
|
flags u32;
|
||||||
|
|
||||||
pixel_type,
|
pixel_type,
|
||||||
color_bits,
|
color_bits,
|
||||||
@@ -336,11 +336,11 @@ type PIXELFORMATDESCRIPTOR struct #ordered {
|
|||||||
stencil_bits,
|
stencil_bits,
|
||||||
aux_buffers,
|
aux_buffers,
|
||||||
layer_type,
|
layer_type,
|
||||||
reserved: byte;
|
reserved byte;
|
||||||
|
|
||||||
layer_mask,
|
layer_mask,
|
||||||
visible_mask,
|
visible_mask,
|
||||||
damage_mask: u32;
|
damage_mask u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc GetDC (h HANDLE) -> HDC #foreign
|
proc GetDC (h HANDLE) -> HDC #foreign
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ const SURROGATE_MAX = 0xdfff;
|
|||||||
|
|
||||||
|
|
||||||
type Accept_Range struct {
|
type Accept_Range struct {
|
||||||
lo, hi: u8;
|
lo, hi u8;
|
||||||
};
|
};
|
||||||
|
|
||||||
accept_ranges := [5]Accept_Range{
|
accept_ranges := [5]Accept_Range{
|
||||||
|
|||||||
+34
-78
@@ -464,37 +464,29 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, MapEntity *en
|
|||||||
|
|
||||||
void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||||
Entity **fields, isize field_count,
|
Entity **fields, isize field_count,
|
||||||
Entity **other_fields, isize other_field_count,
|
|
||||||
String context) {
|
String context) {
|
||||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
|
|
||||||
MapEntity entity_map = {0};
|
MapEntity entity_map = {0};
|
||||||
map_entity_init_with_reserve(&entity_map, c->tmp_allocator, 2*(field_count+other_field_count));
|
map_entity_init_with_reserve(&entity_map, c->tmp_allocator, 2*field_count);
|
||||||
|
|
||||||
isize other_field_index = 0;
|
isize other_field_index = 0;
|
||||||
Entity *using_index_expr = NULL;
|
Entity *using_index_expr = NULL;
|
||||||
|
|
||||||
DelayedOtherFields dof = {0};
|
|
||||||
dof.other_fields = other_fields;
|
|
||||||
dof.other_field_count = other_field_count;
|
|
||||||
dof.entity_map = &entity_map;
|
|
||||||
|
|
||||||
check_scope_decls(c, decls, 1.2*other_field_count, &dof);
|
|
||||||
|
|
||||||
if (node->kind == AstNode_UnionType) {
|
if (node->kind == AstNode_UnionType) {
|
||||||
isize field_index = 0;
|
isize field_index = 0;
|
||||||
fields[field_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL);
|
fields[field_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL);
|
||||||
for_array(decl_index, decls) {
|
for_array(decl_index, decls) {
|
||||||
AstNode *decl = decls.e[decl_index];
|
AstNode *decl = decls.e[decl_index];
|
||||||
if (decl->kind != AstNode_VarDecl) {
|
if (decl->kind != AstNode_Parameter) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_node(vd, VarDecl, decl);
|
ast_node(p, Parameter, decl);
|
||||||
Type *base_type = check_type_extra(c, vd->type, NULL);
|
Type *base_type = check_type_extra(c, p->type, NULL);
|
||||||
|
|
||||||
for_array(name_index, vd->names) {
|
for_array(name_index, p->names) {
|
||||||
AstNode *name = vd->names.e[name_index];
|
AstNode *name = p->names.e[name_index];
|
||||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
if (!ast_node_expect(name, AstNode_Ident)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -526,28 +518,28 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
isize field_index = 0;
|
isize field_index = 0;
|
||||||
for_array(decl_index, decls) {
|
for_array(decl_index, decls) {
|
||||||
AstNode *decl = decls.e[decl_index];
|
AstNode *decl = decls.e[decl_index];
|
||||||
if (decl->kind != AstNode_VarDecl) {
|
if (decl->kind != AstNode_Parameter) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ast_node(vd, VarDecl, decl);
|
ast_node(param, Parameter, decl);
|
||||||
|
|
||||||
Type *type = check_type_extra(c, vd->type, NULL);
|
Type *type = check_type_extra(c, param->type, NULL);
|
||||||
|
|
||||||
if (vd->is_using) {
|
if (param->is_using) {
|
||||||
if (vd->names.count > 1) {
|
if (param->names.count > 1) {
|
||||||
error_node(vd->names.e[0], "Cannot apply `using` to more than one of the same type");
|
error_node(param->names.e[0], "Cannot apply `using` to more than one of the same type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for_array(name_index, vd->names) {
|
for_array(name_index, param->names) {
|
||||||
AstNode *name = vd->names.e[name_index];
|
AstNode *name = param->names.e[name_index];
|
||||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
if (!ast_node_expect(name, AstNode_Ident)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token name_token = name->Ident;
|
Token name_token = name->Ident;
|
||||||
|
|
||||||
Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, vd->is_using, cast(i32)field_index);
|
Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, param->is_using, cast(i32)field_index);
|
||||||
e->identifier = name;
|
e->identifier = name;
|
||||||
if (str_eq(name_token.string, str_lit("_"))) {
|
if (str_eq(name_token.string, str_lit("_"))) {
|
||||||
fields[field_index++] = e;
|
fields[field_index++] = e;
|
||||||
@@ -566,19 +558,19 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (vd->is_using) {
|
if (param->is_using) {
|
||||||
Type *t = base_type(type_deref(type));
|
Type *t = base_type(type_deref(type));
|
||||||
if (!is_type_struct(t) && !is_type_raw_union(t) &&
|
if (!is_type_struct(t) && !is_type_raw_union(t) &&
|
||||||
vd->names.count >= 1 &&
|
param->names.count >= 1 &&
|
||||||
vd->names.e[0]->kind == AstNode_Ident) {
|
param->names.e[0]->kind == AstNode_Ident) {
|
||||||
Token name_token = vd->names.e[0]->Ident;
|
Token name_token = param->names.e[0]->Ident;
|
||||||
if (is_type_indexable(t)) {
|
if (is_type_indexable(t)) {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
for_array(emi, entity_map.entries) {
|
for_array(emi, entity_map.entries) {
|
||||||
Entity *e = entity_map.entries.e[emi].value;
|
Entity *e = entity_map.entries.e[emi].value;
|
||||||
if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) {
|
if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) {
|
||||||
if (is_type_indexable(e->type)) {
|
if (is_type_indexable(e->type)) {
|
||||||
if (e->identifier != vd->names.e[0]) {
|
if (e->identifier != param->names.e[0]) {
|
||||||
ok = false;
|
ok = false;
|
||||||
using_index_expr = e;
|
using_index_expr = e;
|
||||||
break;
|
break;
|
||||||
@@ -643,36 +635,24 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
|
|||||||
ast_node(st, StructType, node);
|
ast_node(st, StructType, node);
|
||||||
|
|
||||||
isize field_count = 0;
|
isize field_count = 0;
|
||||||
isize other_field_count = 0;
|
|
||||||
for_array(field_index, st->fields) {
|
for_array(field_index, st->fields) {
|
||||||
AstNode *field = st->fields.e[field_index];
|
AstNode *field = st->fields.e[field_index];
|
||||||
switch (field->kind) {
|
switch (field->kind) {
|
||||||
case_ast_node(vd, VarDecl, field);
|
case_ast_node(p, Parameter, field);
|
||||||
field_count += vd->names.count;
|
field_count += p->names.count;
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(cd, ConstDecl, field);
|
|
||||||
other_field_count += cd->names.count;
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(td, TypeDecl, field);
|
|
||||||
other_field_count += 1;
|
|
||||||
case_end;
|
case_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
||||||
Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
|
|
||||||
|
|
||||||
check_fields(c, node, st->fields, fields, field_count, other_fields, other_field_count, str_lit("struct"));
|
check_fields(c, node, st->fields, fields, field_count, str_lit("struct"));
|
||||||
|
|
||||||
struct_type->Record.struct_is_packed = st->is_packed;
|
struct_type->Record.struct_is_packed = st->is_packed;
|
||||||
struct_type->Record.struct_is_ordered = st->is_ordered;
|
struct_type->Record.struct_is_ordered = st->is_ordered;
|
||||||
struct_type->Record.fields = fields;
|
struct_type->Record.fields = fields;
|
||||||
struct_type->Record.fields_in_src_order = fields;
|
struct_type->Record.fields_in_src_order = fields;
|
||||||
struct_type->Record.field_count = field_count;
|
struct_type->Record.field_count = field_count;
|
||||||
struct_type->Record.other_fields = other_fields;
|
|
||||||
struct_type->Record.other_field_count = other_field_count;
|
|
||||||
|
|
||||||
if (!st->is_packed && !st->is_ordered) {
|
if (!st->is_packed && !st->is_ordered) {
|
||||||
// NOTE(bill): Reorder fields for reduced size/performance
|
// NOTE(bill): Reorder fields for reduced size/performance
|
||||||
@@ -704,33 +684,21 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
|
|||||||
ast_node(ut, UnionType, node);
|
ast_node(ut, UnionType, node);
|
||||||
|
|
||||||
isize field_count = 1;
|
isize field_count = 1;
|
||||||
isize other_field_count = 0;
|
|
||||||
for_array(field_index, ut->fields) {
|
for_array(field_index, ut->fields) {
|
||||||
AstNode *field = ut->fields.e[field_index];
|
AstNode *field = ut->fields.e[field_index];
|
||||||
switch (field->kind) {
|
switch (field->kind) {
|
||||||
case_ast_node(vd, VarDecl, field);
|
case_ast_node(p, Parameter, field);
|
||||||
field_count += vd->names.count;
|
field_count += p->names.count;
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(cd, ConstDecl, field);
|
|
||||||
other_field_count += cd->names.count;
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(td, TypeDecl, field);
|
|
||||||
other_field_count += 1;
|
|
||||||
case_end;
|
case_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
||||||
Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
|
|
||||||
|
|
||||||
check_fields(c, node, ut->fields, fields, field_count, other_fields, other_field_count, str_lit("union"));
|
check_fields(c, node, ut->fields, fields, field_count, str_lit("union"));
|
||||||
|
|
||||||
union_type->Record.fields = fields;
|
union_type->Record.fields = fields;
|
||||||
union_type->Record.field_count = field_count;
|
union_type->Record.field_count = field_count;
|
||||||
union_type->Record.other_fields = other_fields;
|
|
||||||
union_type->Record.other_field_count = other_field_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||||
@@ -739,33 +707,21 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
|||||||
ast_node(ut, RawUnionType, node);
|
ast_node(ut, RawUnionType, node);
|
||||||
|
|
||||||
isize field_count = 0;
|
isize field_count = 0;
|
||||||
isize other_field_count = 0;
|
|
||||||
for_array(field_index, ut->fields) {
|
for_array(field_index, ut->fields) {
|
||||||
AstNode *field = ut->fields.e[field_index];
|
AstNode *field = ut->fields.e[field_index];
|
||||||
switch (field->kind) {
|
switch (field->kind) {
|
||||||
case_ast_node(vd, VarDecl, field);
|
case_ast_node(p, Parameter, field);
|
||||||
field_count += vd->names.count;
|
field_count += p->names.count;
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(cd, ConstDecl, field);
|
|
||||||
other_field_count += cd->names.count;
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(td, TypeDecl, field);
|
|
||||||
other_field_count += 1;
|
|
||||||
case_end;
|
case_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
||||||
Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
|
|
||||||
|
|
||||||
check_fields(c, node, ut->fields, fields, field_count, other_fields, other_field_count, str_lit("raw union"));
|
check_fields(c, node, ut->fields, fields, field_count, str_lit("raw_union"));
|
||||||
|
|
||||||
union_type->Record.fields = fields;
|
union_type->Record.fields = fields;
|
||||||
union_type->Record.field_count = field_count;
|
union_type->Record.field_count = field_count;
|
||||||
union_type->Record.other_fields = other_fields;
|
|
||||||
union_type->Record.other_field_count = other_field_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_COMPARE_PROC(cmp_enum_order) {
|
GB_COMPARE_PROC(cmp_enum_order) {
|
||||||
@@ -895,11 +851,11 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
|
|||||||
|
|
||||||
gb_sort_array(fields, field_index, cmp_enum_order);
|
gb_sort_array(fields, field_index, cmp_enum_order);
|
||||||
|
|
||||||
enum_type->Record.other_fields = fields;
|
enum_type->Record.enum_values = fields;
|
||||||
enum_type->Record.other_field_count = field_index;
|
enum_type->Record.enum_value_count = field_index;
|
||||||
|
|
||||||
enum_type->Record.enum_count = make_entity_constant(c->allocator, NULL,
|
enum_type->Record.enum_count = make_entity_constant(c->allocator, NULL,
|
||||||
make_token_ident(str_lit("count")), t_int, make_exact_value_integer(enum_type->Record.other_field_count));
|
make_token_ident(str_lit("count")), t_int, make_exact_value_integer(enum_type->Record.enum_value_count));
|
||||||
enum_type->Record.min_value = make_entity_constant(c->allocator, NULL,
|
enum_type->Record.min_value = make_entity_constant(c->allocator, NULL,
|
||||||
make_token_ident(str_lit("min_value")), constant_type, make_exact_value_integer(min_value));
|
make_token_ident(str_lit("min_value")), constant_type, make_exact_value_integer(min_value));
|
||||||
enum_type->Record.max_value = make_entity_constant(c->allocator, NULL,
|
enum_type->Record.max_value = make_entity_constant(c->allocator, NULL,
|
||||||
@@ -3599,8 +3555,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
ExactValue value = make_exact_value_string(str_lit(""));
|
ExactValue value = make_exact_value_string(str_lit(""));
|
||||||
if (operand->value.kind == ExactValue_Integer) {
|
if (operand->value.kind == ExactValue_Integer) {
|
||||||
i64 index = operand->value.value_integer;
|
i64 index = operand->value.value_integer;
|
||||||
for (isize i = 0; i < type->Record.other_field_count; i++) {
|
for (isize i = 0; i < type->Record.enum_value_count; i++) {
|
||||||
Entity *f = type->Record.other_fields[i];
|
Entity *f = type->Record.enum_values[i];
|
||||||
if (f->kind == Entity_Constant && f->Constant.value.kind == ExactValue_Integer) {
|
if (f->kind == Entity_Constant && f->Constant.value.kind == ExactValue_Integer) {
|
||||||
i64 fv = f->Constant.value.value_integer;
|
i64 fv = f->Constant.value.value_integer;
|
||||||
if (index == fv) {
|
if (index == fv) {
|
||||||
|
|||||||
+3
-14
@@ -907,9 +907,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
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 (is_type_struct(t) || is_type_enum(t)) {
|
if (is_type_enum(t)) {
|
||||||
for (isize i = 0; i < t->Record.other_field_count; i++) {
|
for (isize i = 0; i < t->Record.enum_value_count; i++) {
|
||||||
Entity *f = t->Record.other_fields[i];
|
Entity *f = t->Record.enum_values[i];
|
||||||
Entity *found = scope_insert_entity(c->context.scope, f);
|
Entity *found = scope_insert_entity(c->context.scope, f);
|
||||||
if (found != NULL) {
|
if (found != NULL) {
|
||||||
gbString expr_str = expr_to_string(expr);
|
gbString expr_str = expr_to_string(expr);
|
||||||
@@ -931,17 +931,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
f->using_parent = e;
|
f->using_parent = e;
|
||||||
}
|
}
|
||||||
for (isize i = 0; i < t->Record.other_field_count; i++) {
|
|
||||||
Entity *f = t->Record.other_fields[i];
|
|
||||||
Entity *found = scope_insert_entity(c->context.scope, f);
|
|
||||||
if (found != NULL) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
f->using_parent = e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
+14
-16
@@ -84,6 +84,8 @@ typedef struct TypeRecord {
|
|||||||
Entity * enum_count;
|
Entity * enum_count;
|
||||||
Entity * min_value;
|
Entity * min_value;
|
||||||
Entity * max_value;
|
Entity * max_value;
|
||||||
|
Entity **enum_values;
|
||||||
|
i32 enum_value_count;
|
||||||
};
|
};
|
||||||
struct { // struct only
|
struct { // struct only
|
||||||
i64 * struct_offsets;
|
i64 * struct_offsets;
|
||||||
@@ -93,10 +95,6 @@ typedef struct TypeRecord {
|
|||||||
Entity **fields_in_src_order; // Entity_Variable
|
Entity **fields_in_src_order; // Entity_Variable
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Entity_Constant or Entity_TypeName
|
|
||||||
Entity **other_fields;
|
|
||||||
i32 other_field_count;
|
|
||||||
} TypeRecord;
|
} TypeRecord;
|
||||||
|
|
||||||
#define TYPE_KINDS \
|
#define TYPE_KINDS \
|
||||||
@@ -984,19 +982,19 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (isize i = 0; i < type->Record.other_field_count; i++) {
|
|
||||||
Entity *f = type->Record.other_fields[i];
|
|
||||||
GB_ASSERT(f->kind != Entity_Variable);
|
|
||||||
String str = f->token.string;
|
|
||||||
|
|
||||||
if (str_eq(field_name, str)) {
|
|
||||||
sel.entity = f;
|
|
||||||
selection_add_index(&sel, i);
|
|
||||||
return sel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_type_enum(type)) {
|
if (is_type_enum(type)) {
|
||||||
|
for (isize i = 0; i < type->Record.enum_value_count; i++) {
|
||||||
|
Entity *f = type->Record.enum_values[i];
|
||||||
|
GB_ASSERT(f->kind != Entity_Variable);
|
||||||
|
String str = f->token.string;
|
||||||
|
|
||||||
|
if (str_eq(field_name, str)) {
|
||||||
|
sel.entity = f;
|
||||||
|
selection_add_index(&sel, i);
|
||||||
|
return sel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (str_eq(field_name, str_lit("count"))) {
|
if (str_eq(field_name, str_lit("count"))) {
|
||||||
sel.entity = type->Record.enum_count;
|
sel.entity = type->Record.enum_count;
|
||||||
return sel;
|
return sel;
|
||||||
|
|||||||
+21
-67
@@ -1646,8 +1646,9 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
|||||||
f->expr_level++;
|
f->expr_level++;
|
||||||
open = expect_token(f, Token_OpenBracket);
|
open = expect_token(f, Token_OpenBracket);
|
||||||
|
|
||||||
if (f->curr_token.kind != Token_Colon)
|
if (f->curr_token.kind != Token_Colon) {
|
||||||
indices[0] = parse_expr(f, false);
|
indices[0] = parse_expr(f, false);
|
||||||
|
}
|
||||||
isize colon_count = 0;
|
isize colon_count = 0;
|
||||||
Token colons[2] = {0};
|
Token colons[2] = {0};
|
||||||
|
|
||||||
@@ -2062,8 +2063,9 @@ AstNode *parse_proc_type(AstFile *f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AstNodeArray parse_parameter_list(AstFile *f, bool allow_using, TokenKind follow) {
|
AstNodeArray parse_parameter_list(AstFile *f, isize *name_count_, bool allow_using, TokenKind separator, TokenKind follow) {
|
||||||
AstNodeArray params = make_ast_node_array(f);
|
AstNodeArray params = make_ast_node_array(f);
|
||||||
|
isize name_count = 0;
|
||||||
|
|
||||||
while (f->curr_token.kind != follow &&
|
while (f->curr_token.kind != follow &&
|
||||||
f->curr_token.kind != Token_EOF) {
|
f->curr_token.kind != Token_EOF) {
|
||||||
@@ -2088,6 +2090,8 @@ AstNodeArray parse_parameter_list(AstFile *f, bool allow_using, TokenKind follow
|
|||||||
is_using = false;
|
is_using = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name_count += names.count;
|
||||||
|
|
||||||
// expect_token_after(f, Token_Colon, "parameter list");
|
// expect_token_after(f, Token_Colon, "parameter list");
|
||||||
|
|
||||||
AstNode *type = NULL;
|
AstNode *type = NULL;
|
||||||
@@ -2114,77 +2118,27 @@ AstNodeArray parse_parameter_list(AstFile *f, bool allow_using, TokenKind follow
|
|||||||
syntax_error(f->curr_token, "Expected a type for this parameter declaration");
|
syntax_error(f->curr_token, "Expected a type for this parameter declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
array_add(¶ms, make_parameter(f, names, type, is_using));
|
AstNode *param = make_parameter(f, names, type, is_using);
|
||||||
if (!allow_token(f, Token_Comma)) {
|
array_add(¶ms, param);
|
||||||
break;
|
|
||||||
|
|
||||||
|
if (separator == Token_Semicolon) {
|
||||||
|
expect_semicolon(f, param);
|
||||||
|
} else {
|
||||||
|
if (!allow_token(f, separator)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name_count_) *name_count_ = name_count;
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AstNodeArray parse_record_params(AstFile *f, isize *decl_count_, bool allow_using, String context) {
|
AstNodeArray parse_record_params(AstFile *f, isize *field_count_, bool allow_using, String context) {
|
||||||
AstNodeArray decls = make_ast_node_array(f);
|
return parse_parameter_list(f, field_count_, allow_using, Token_Semicolon, Token_CloseBrace);
|
||||||
isize decl_count = 0;
|
|
||||||
|
|
||||||
while (f->curr_token.kind != Token_CloseBrace &&
|
|
||||||
f->curr_token.kind != Token_EOF) {
|
|
||||||
AstNode *decl = parse_stmt(f);
|
|
||||||
if (is_ast_node_decl(decl) ||
|
|
||||||
decl->kind == AstNode_UsingStmt ||
|
|
||||||
decl->kind == AstNode_EmptyStmt) {
|
|
||||||
switch (decl->kind) {
|
|
||||||
case AstNode_EmptyStmt:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AstNode_ProcDecl:
|
|
||||||
syntax_error(f->curr_token, "Procedure declarations are not allowed within a %.*s", LIT(context));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AstNode_UsingStmt: {
|
|
||||||
bool is_using = true;
|
|
||||||
if (!allow_using) {
|
|
||||||
syntax_error(f->curr_token, "Cannot apply `using` to members of a %.*s", LIT(context));
|
|
||||||
is_using = false;
|
|
||||||
}
|
|
||||||
if (decl->UsingStmt.node->kind == AstNode_VarDecl) {
|
|
||||||
AstNode *vd = decl->UsingStmt.node;
|
|
||||||
vd->VarDecl.is_using = is_using && allow_using;
|
|
||||||
if (vd->VarDecl.values.count > 0) {
|
|
||||||
syntax_error(f->curr_token, "Default variable assignments within a %.*s will be ignored", LIT(context));
|
|
||||||
}
|
|
||||||
array_add(&decls, vd);
|
|
||||||
} else {
|
|
||||||
syntax_error_node(decl, "Illegal %.*s field", LIT(context));
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case AstNode_VarDecl: {
|
|
||||||
if (decl->VarDecl.values.count > 0) {
|
|
||||||
syntax_error(f->curr_token, "Default variable assignments within a %.*s will be ignored", LIT(context));
|
|
||||||
}
|
|
||||||
array_add(&decls, decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
case AstNode_BadDecl:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AstNode_ConstDecl:
|
|
||||||
case AstNode_TypeDecl:
|
|
||||||
default:
|
|
||||||
decl_count += 1;
|
|
||||||
array_add(&decls, decl);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
syntax_error_node(decl, "Illegal record field: %.*s", LIT(ast_node_strings[decl->kind]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (decl_count_) *decl_count_ = decl_count;
|
|
||||||
|
|
||||||
return decls;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *parse_identifier_or_type(AstFile *f) {
|
AstNode *parse_identifier_or_type(AstFile *f) {
|
||||||
@@ -2380,7 +2334,7 @@ void parse_proc_signature(AstFile *f,
|
|||||||
AstNodeArray *params,
|
AstNodeArray *params,
|
||||||
AstNodeArray *results) {
|
AstNodeArray *results) {
|
||||||
expect_token(f, Token_OpenParen);
|
expect_token(f, Token_OpenParen);
|
||||||
*params = parse_parameter_list(f, true, Token_CloseParen);
|
*params = parse_parameter_list(f, NULL, true, Token_Comma, Token_CloseParen);
|
||||||
expect_token_after(f, Token_CloseParen, "parameter list");
|
expect_token_after(f, Token_CloseParen, "parameter list");
|
||||||
*results = parse_results(f);
|
*results = parse_results(f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2522,15 +2522,8 @@ void ssa_gen_global_type_name(ssaModule *m, Entity *e, String name) {
|
|||||||
ssa_module_add_value(m, e, t);
|
ssa_module_add_value(m, e, t);
|
||||||
map_ssa_value_set(&m->members, hash_string(name), t);
|
map_ssa_value_set(&m->members, hash_string(name), t);
|
||||||
|
|
||||||
Type *bt = base_type(e->type);
|
if (is_type_union(e->type)) {
|
||||||
if (bt->kind == Type_Record) {
|
Type *bt = base_type(e->type);
|
||||||
TypeRecord *s = &bt->Record;
|
|
||||||
for (isize j = 0; j < s->other_field_count; j++) {
|
|
||||||
ssa_mangle_sub_type_name(m, s->other_fields[j], name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_type_union(bt)) {
|
|
||||||
TypeRecord *s = &bt->Record;
|
TypeRecord *s = &bt->Record;
|
||||||
// NOTE(bill): Zeroth entry is null (for `match type` stmts)
|
// NOTE(bill): Zeroth entry is null (for `match type` stmts)
|
||||||
for (isize j = 1; j < s->field_count; j++) {
|
for (isize j = 1; j < s->field_count; j++) {
|
||||||
@@ -5418,13 +5411,12 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
ssaValue *base = ssa_emit_struct_ep(proc, tag, 0);
|
ssaValue *base = ssa_emit_struct_ep(proc, tag, 0);
|
||||||
ssa_emit_store(proc, base, ssa_get_type_info_ptr(proc, type_info_data, enum_base));
|
ssa_emit_store(proc, base, ssa_get_type_info_ptr(proc, type_info_data, enum_base));
|
||||||
|
|
||||||
if (t->Record.other_field_count > 0) {
|
if (t->Record.enum_value_count > 0) {
|
||||||
Entity **fields = t->Record.other_fields;
|
Entity **fields = t->Record.enum_values;
|
||||||
isize count = t->Record.other_field_count;
|
isize count = t->Record.enum_value_count;
|
||||||
ssaValue *value_array = NULL;
|
ssaValue *value_array = NULL;
|
||||||
ssaValue *name_array = NULL;
|
ssaValue *name_array = NULL;
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Token token = {Token_Ident};
|
Token token = {Token_Ident};
|
||||||
i32 id = cast(i32)entry_index;
|
i32 id = cast(i32)entry_index;
|
||||||
|
|||||||
Reference in New Issue
Block a user