mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-03 11:42:28 +00:00
Change record field syntax
This commit is contained in:
@@ -13,67 +13,67 @@
|
||||
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
||||
// The compiler relies upon this _exact_ order
|
||||
type Type_Info_Member struct #ordered {
|
||||
name: string; // can be empty if tuple
|
||||
type_info: ^Type_Info;
|
||||
offset: int; // offsets are not used in tuples
|
||||
};
|
||||
name string; // can be empty if tuple
|
||||
type_info ^Type_Info;
|
||||
offset int; // offsets are not used in tuples
|
||||
}
|
||||
type Type_Info_Record struct #ordered {
|
||||
fields: []Type_Info_Member;
|
||||
size: int; // in bytes
|
||||
align: int; // in bytes
|
||||
packed: bool;
|
||||
ordered: bool;
|
||||
};
|
||||
fields []Type_Info_Member;
|
||||
size int; // in bytes
|
||||
align int; // in bytes
|
||||
packed bool;
|
||||
ordered bool;
|
||||
}
|
||||
|
||||
type Type_Info union {
|
||||
Named: struct #ordered {
|
||||
name: string;
|
||||
base: ^Type_Info; // This will _not_ be a Type_Info.Named
|
||||
Named struct #ordered {
|
||||
name string;
|
||||
base ^Type_Info; // This will _not_ be a Type_Info.Named
|
||||
};
|
||||
Integer: struct #ordered {
|
||||
size: int; // in bytes
|
||||
signed: bool;
|
||||
Integer struct #ordered {
|
||||
size int; // in bytes
|
||||
signed bool;
|
||||
};
|
||||
Float: struct #ordered {
|
||||
size: int; // in bytes
|
||||
Float struct #ordered {
|
||||
size int; // in bytes
|
||||
};
|
||||
Any: struct #ordered {};
|
||||
String: struct #ordered {};
|
||||
Boolean: struct #ordered {};
|
||||
Pointer: struct #ordered {
|
||||
elem: ^Type_Info; // nil -> rawptr
|
||||
Any struct #ordered {};
|
||||
String struct #ordered {};
|
||||
Boolean struct #ordered {};
|
||||
Pointer struct #ordered {
|
||||
elem ^Type_Info; // nil -> rawptr
|
||||
};
|
||||
Maybe: struct #ordered {
|
||||
elem: ^Type_Info;
|
||||
Maybe struct #ordered {
|
||||
elem ^Type_Info;
|
||||
};
|
||||
Procedure: struct #ordered {
|
||||
params: ^Type_Info; // Type_Info.Tuple
|
||||
results: ^Type_Info; // Type_Info.Tuple
|
||||
variadic: bool;
|
||||
Procedure struct #ordered {
|
||||
params ^Type_Info; // Type_Info.Tuple
|
||||
results ^Type_Info; // Type_Info.Tuple
|
||||
variadic bool;
|
||||
};
|
||||
Array: struct #ordered {
|
||||
elem: ^Type_Info;
|
||||
elem_size: int;
|
||||
count: int;
|
||||
Array struct #ordered {
|
||||
elem ^Type_Info;
|
||||
elem_size int;
|
||||
count int;
|
||||
};
|
||||
Slice: struct #ordered {
|
||||
elem: ^Type_Info;
|
||||
elem_size: int;
|
||||
Slice struct #ordered {
|
||||
elem ^Type_Info;
|
||||
elem_size int;
|
||||
};
|
||||
Vector: struct #ordered {
|
||||
elem: ^Type_Info;
|
||||
elem_size: int;
|
||||
count: int;
|
||||
align: int;
|
||||
Vector struct #ordered {
|
||||
elem ^Type_Info;
|
||||
elem_size int;
|
||||
count int;
|
||||
align int;
|
||||
};
|
||||
Tuple: Type_Info_Record;
|
||||
Struct: Type_Info_Record;
|
||||
Union: Type_Info_Record;
|
||||
Raw_Union: Type_Info_Record;
|
||||
Enum: struct #ordered {
|
||||
base: ^Type_Info;
|
||||
values: []i64;
|
||||
names: []string;
|
||||
Tuple Type_Info_Record;
|
||||
Struct Type_Info_Record;
|
||||
Union Type_Info_Record;
|
||||
Raw_Union Type_Info_Record;
|
||||
Enum struct #ordered {
|
||||
base ^Type_Info;
|
||||
values []i64;
|
||||
names []string;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -126,18 +126,18 @@ type Allocator_Proc proc(allocator_data rawptr, mode Allocator_Mode,
|
||||
|
||||
|
||||
type Allocator struct #ordered {
|
||||
procedure: Allocator_Proc;
|
||||
data: rawptr;
|
||||
procedure Allocator_Proc;
|
||||
data rawptr;
|
||||
}
|
||||
|
||||
|
||||
type Context struct #ordered {
|
||||
thread_id: int;
|
||||
thread_id int;
|
||||
|
||||
allocator: Allocator;
|
||||
allocator Allocator;
|
||||
|
||||
user_data: rawptr;
|
||||
user_index: int;
|
||||
user_data rawptr;
|
||||
user_index int;
|
||||
}
|
||||
|
||||
#thread_local var __context Context;
|
||||
|
||||
@@ -90,7 +90,7 @@ proc align_forward(ptr rawptr, align int) -> rawptr {
|
||||
|
||||
|
||||
type Allocation_Header struct {
|
||||
size: int;
|
||||
size int;
|
||||
}
|
||||
proc allocation_header_fill(header ^Allocation_Header, data rawptr, size int) {
|
||||
header.size = size;
|
||||
@@ -115,14 +115,14 @@ proc allocation_header(data rawptr) -> ^Allocation_Header {
|
||||
// Custom allocators
|
||||
|
||||
type Arena struct {
|
||||
backing: Allocator;
|
||||
memory: []byte;
|
||||
temp_count: int;
|
||||
backing Allocator;
|
||||
memory []byte;
|
||||
temp_count int;
|
||||
}
|
||||
|
||||
type Arena_Temp_Memory struct {
|
||||
arena: ^Arena;
|
||||
original_count: int;
|
||||
arena ^Arena;
|
||||
original_count int;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
type File_Time u64;
|
||||
|
||||
type File_Handle raw_union {
|
||||
p: rawptr;
|
||||
i: int;
|
||||
p rawptr;
|
||||
i int;
|
||||
}
|
||||
|
||||
type File struct {
|
||||
handle: File_Handle;
|
||||
last_write_time: File_Time;
|
||||
handle File_Handle;
|
||||
last_write_time File_Time;
|
||||
}
|
||||
|
||||
proc open(name string) -> (File, bool) {
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
#import "atomic.odin";
|
||||
|
||||
type Semaphore struct {
|
||||
handle: win32.HANDLE;
|
||||
handle win32.HANDLE;
|
||||
}
|
||||
|
||||
type Mutex struct {
|
||||
semaphore: Semaphore;
|
||||
counter: i32;
|
||||
owner: i32;
|
||||
recursion: i32;
|
||||
semaphore Semaphore;
|
||||
counter i32;
|
||||
owner i32;
|
||||
recursion i32;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -51,62 +51,62 @@ const SM_CYSCREEN = 1;
|
||||
const SW_SHOW = 5;
|
||||
|
||||
type POINT struct #ordered {
|
||||
x, y: i32;
|
||||
x, y i32;
|
||||
}
|
||||
|
||||
|
||||
type WNDCLASSEXA struct #ordered {
|
||||
size, style: u32;
|
||||
wnd_proc: WNDPROC;
|
||||
cls_extra, wnd_extra: i32;
|
||||
instance: HINSTANCE;
|
||||
icon: HICON;
|
||||
cursor: HCURSOR;
|
||||
background: HBRUSH;
|
||||
menu_name, class_name: ^u8;
|
||||
sm: HICON;
|
||||
size, style u32;
|
||||
wnd_proc WNDPROC;
|
||||
cls_extra, wnd_extra i32;
|
||||
instance HINSTANCE;
|
||||
icon HICON;
|
||||
cursor HCURSOR;
|
||||
background HBRUSH;
|
||||
menu_name, class_name ^u8;
|
||||
sm HICON;
|
||||
}
|
||||
|
||||
type MSG struct #ordered {
|
||||
hwnd: HWND;
|
||||
message: u32;
|
||||
wparam: WPARAM;
|
||||
lparam: LPARAM;
|
||||
time: u32;
|
||||
pt: POINT;
|
||||
hwnd HWND;
|
||||
message u32;
|
||||
wparam WPARAM;
|
||||
lparam LPARAM;
|
||||
time u32;
|
||||
pt POINT;
|
||||
}
|
||||
|
||||
type RECT struct #ordered {
|
||||
left: i32;
|
||||
top: i32;
|
||||
right: i32;
|
||||
bottom: i32;
|
||||
left i32;
|
||||
top i32;
|
||||
right i32;
|
||||
bottom i32;
|
||||
}
|
||||
|
||||
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 {
|
||||
file_attributes: u32;
|
||||
file_attributes u32;
|
||||
creation_time,
|
||||
last_access_time,
|
||||
last_write_time: FILETIME;
|
||||
last_write_time FILETIME;
|
||||
volume_serial_number,
|
||||
file_size_high,
|
||||
file_size_low,
|
||||
number_of_links,
|
||||
file_index_high,
|
||||
file_index_low: u32;
|
||||
file_index_low u32;
|
||||
}
|
||||
|
||||
type WIN32_FILE_ATTRIBUTE_DATA struct #ordered {
|
||||
file_attributes: u32;
|
||||
file_attributes u32;
|
||||
creation_time,
|
||||
last_access_time,
|
||||
last_write_time: FILETIME;
|
||||
last_write_time FILETIME;
|
||||
file_size_high,
|
||||
file_size_low: u32;
|
||||
file_size_low u32;
|
||||
}
|
||||
|
||||
type GET_FILEEX_INFO_LEVELS i32;
|
||||
@@ -209,9 +209,9 @@ const HEAP_ZERO_MEMORY = 0x00000008;
|
||||
// Synchronization
|
||||
|
||||
type SECURITY_ATTRIBUTES struct #ordered {
|
||||
length: u32;
|
||||
security_descriptor: rawptr;
|
||||
inherit_handle: BOOL;
|
||||
length u32;
|
||||
security_descriptor rawptr;
|
||||
inherit_handle BOOL;
|
||||
}
|
||||
|
||||
const INFINITE = 0xffffffff;
|
||||
@@ -242,24 +242,24 @@ proc ReadBarrier () #foreign
|
||||
// GDI
|
||||
|
||||
type BITMAPINFOHEADER struct #ordered {
|
||||
size: u32;
|
||||
width, height: i32;
|
||||
planes, bit_count: i16;
|
||||
compression: u32;
|
||||
size_image: u32;
|
||||
x_pels_per_meter: i32;
|
||||
y_pels_per_meter: i32;
|
||||
clr_used: u32;
|
||||
clr_important: u32;
|
||||
size u32;
|
||||
width, height i32;
|
||||
planes, bit_count i16;
|
||||
compression u32;
|
||||
size_image u32;
|
||||
x_pels_per_meter i32;
|
||||
y_pels_per_meter i32;
|
||||
clr_used u32;
|
||||
clr_important u32;
|
||||
}
|
||||
type BITMAPINFO struct #ordered {
|
||||
using header: BITMAPINFOHEADER;
|
||||
colors: [1]RGBQUAD;
|
||||
using header BITMAPINFOHEADER;
|
||||
colors [1]RGBQUAD;
|
||||
}
|
||||
|
||||
|
||||
type RGBQUAD struct #ordered {
|
||||
blue, green, red, reserved: byte;
|
||||
blue, green, red, reserved byte;
|
||||
}
|
||||
|
||||
const BI_RGB = 0;
|
||||
@@ -315,7 +315,7 @@ type wglCreateContextAttribsARBType proc(hdc HDC, hshareContext rawptr, attribLi
|
||||
type PIXELFORMATDESCRIPTOR struct #ordered {
|
||||
size,
|
||||
version,
|
||||
flags: u32;
|
||||
flags u32;
|
||||
|
||||
pixel_type,
|
||||
color_bits,
|
||||
@@ -336,11 +336,11 @@ type PIXELFORMATDESCRIPTOR struct #ordered {
|
||||
stencil_bits,
|
||||
aux_buffers,
|
||||
layer_type,
|
||||
reserved: byte;
|
||||
reserved byte;
|
||||
|
||||
layer_mask,
|
||||
visible_mask,
|
||||
damage_mask: u32;
|
||||
damage_mask u32;
|
||||
}
|
||||
|
||||
proc GetDC (h HANDLE) -> HDC #foreign
|
||||
|
||||
@@ -11,7 +11,7 @@ const SURROGATE_MAX = 0xdfff;
|
||||
|
||||
|
||||
type Accept_Range struct {
|
||||
lo, hi: u8;
|
||||
lo, hi u8;
|
||||
};
|
||||
|
||||
accept_ranges := [5]Accept_Range{
|
||||
|
||||
@@ -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,
|
||||
Entity **fields, isize field_count,
|
||||
Entity **other_fields, isize other_field_count,
|
||||
String context) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
|
||||
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;
|
||||
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) {
|
||||
isize field_index = 0;
|
||||
fields[field_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL);
|
||||
for_array(decl_index, decls) {
|
||||
AstNode *decl = decls.e[decl_index];
|
||||
if (decl->kind != AstNode_VarDecl) {
|
||||
if (decl->kind != AstNode_Parameter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ast_node(vd, VarDecl, decl);
|
||||
Type *base_type = check_type_extra(c, vd->type, NULL);
|
||||
ast_node(p, Parameter, decl);
|
||||
Type *base_type = check_type_extra(c, p->type, NULL);
|
||||
|
||||
for_array(name_index, vd->names) {
|
||||
AstNode *name = vd->names.e[name_index];
|
||||
for_array(name_index, p->names) {
|
||||
AstNode *name = p->names.e[name_index];
|
||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
||||
continue;
|
||||
}
|
||||
@@ -526,28 +518,28 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||
isize field_index = 0;
|
||||
for_array(decl_index, decls) {
|
||||
AstNode *decl = decls.e[decl_index];
|
||||
if (decl->kind != AstNode_VarDecl) {
|
||||
if (decl->kind != AstNode_Parameter) {
|
||||
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 (vd->names.count > 1) {
|
||||
error_node(vd->names.e[0], "Cannot apply `using` to more than one of the same type");
|
||||
if (param->is_using) {
|
||||
if (param->names.count > 1) {
|
||||
error_node(param->names.e[0], "Cannot apply `using` to more than one of the same type");
|
||||
}
|
||||
}
|
||||
|
||||
for_array(name_index, vd->names) {
|
||||
AstNode *name = vd->names.e[name_index];
|
||||
for_array(name_index, param->names) {
|
||||
AstNode *name = param->names.e[name_index];
|
||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
if (str_eq(name_token.string, str_lit("_"))) {
|
||||
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));
|
||||
if (!is_type_struct(t) && !is_type_raw_union(t) &&
|
||||
vd->names.count >= 1 &&
|
||||
vd->names.e[0]->kind == AstNode_Ident) {
|
||||
Token name_token = vd->names.e[0]->Ident;
|
||||
param->names.count >= 1 &&
|
||||
param->names.e[0]->kind == AstNode_Ident) {
|
||||
Token name_token = param->names.e[0]->Ident;
|
||||
if (is_type_indexable(t)) {
|
||||
bool ok = true;
|
||||
for_array(emi, entity_map.entries) {
|
||||
Entity *e = entity_map.entries.e[emi].value;
|
||||
if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) {
|
||||
if (is_type_indexable(e->type)) {
|
||||
if (e->identifier != vd->names.e[0]) {
|
||||
if (e->identifier != param->names.e[0]) {
|
||||
ok = false;
|
||||
using_index_expr = e;
|
||||
break;
|
||||
@@ -643,36 +635,24 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
|
||||
ast_node(st, StructType, node);
|
||||
|
||||
isize field_count = 0;
|
||||
isize other_field_count = 0;
|
||||
for_array(field_index, st->fields) {
|
||||
AstNode *field = st->fields.e[field_index];
|
||||
switch (field->kind) {
|
||||
case_ast_node(vd, VarDecl, field);
|
||||
field_count += vd->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_ast_node(p, Parameter, field);
|
||||
field_count += p->names.count;
|
||||
case_end;
|
||||
}
|
||||
}
|
||||
|
||||
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_ordered = st->is_ordered;
|
||||
struct_type->Record.fields = fields;
|
||||
struct_type->Record.fields_in_src_order = fields;
|
||||
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) {
|
||||
// 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);
|
||||
|
||||
isize field_count = 1;
|
||||
isize other_field_count = 0;
|
||||
for_array(field_index, ut->fields) {
|
||||
AstNode *field = ut->fields.e[field_index];
|
||||
switch (field->kind) {
|
||||
case_ast_node(vd, VarDecl, field);
|
||||
field_count += vd->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_ast_node(p, Parameter, field);
|
||||
field_count += p->names.count;
|
||||
case_end;
|
||||
}
|
||||
}
|
||||
|
||||
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.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) {
|
||||
@@ -739,33 +707,21 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||
ast_node(ut, RawUnionType, node);
|
||||
|
||||
isize field_count = 0;
|
||||
isize other_field_count = 0;
|
||||
for_array(field_index, ut->fields) {
|
||||
AstNode *field = ut->fields.e[field_index];
|
||||
switch (field->kind) {
|
||||
case_ast_node(vd, VarDecl, field);
|
||||
field_count += vd->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_ast_node(p, Parameter, field);
|
||||
field_count += p->names.count;
|
||||
case_end;
|
||||
}
|
||||
}
|
||||
|
||||
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.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) {
|
||||
@@ -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);
|
||||
|
||||
enum_type->Record.other_fields = fields;
|
||||
enum_type->Record.other_field_count = field_index;
|
||||
enum_type->Record.enum_values = fields;
|
||||
enum_type->Record.enum_value_count = field_index;
|
||||
|
||||
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,
|
||||
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,
|
||||
@@ -3599,8 +3555,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
ExactValue value = make_exact_value_string(str_lit(""));
|
||||
if (operand->value.kind == ExactValue_Integer) {
|
||||
i64 index = operand->value.value_integer;
|
||||
for (isize i = 0; i < type->Record.other_field_count; i++) {
|
||||
Entity *f = type->Record.other_fields[i];
|
||||
for (isize i = 0; i < type->Record.enum_value_count; i++) {
|
||||
Entity *f = type->Record.enum_values[i];
|
||||
if (f->kind == Entity_Constant && f->Constant.value.kind == ExactValue_Integer) {
|
||||
i64 fv = f->Constant.value.value_integer;
|
||||
if (index == fv) {
|
||||
|
||||
@@ -907,9 +907,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
switch (e->kind) {
|
||||
case Entity_TypeName: {
|
||||
Type *t = base_type(e->type);
|
||||
if (is_type_struct(t) || is_type_enum(t)) {
|
||||
for (isize i = 0; i < t->Record.other_field_count; i++) {
|
||||
Entity *f = t->Record.other_fields[i];
|
||||
if (is_type_enum(t)) {
|
||||
for (isize i = 0; i < t->Record.enum_value_count; i++) {
|
||||
Entity *f = t->Record.enum_values[i];
|
||||
Entity *found = scope_insert_entity(c->context.scope, f);
|
||||
if (found != NULL) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ typedef struct TypeRecord {
|
||||
Entity * enum_count;
|
||||
Entity * min_value;
|
||||
Entity * max_value;
|
||||
Entity **enum_values;
|
||||
i32 enum_value_count;
|
||||
};
|
||||
struct { // struct only
|
||||
i64 * struct_offsets;
|
||||
@@ -93,10 +95,6 @@ typedef struct TypeRecord {
|
||||
Entity **fields_in_src_order; // Entity_Variable
|
||||
};
|
||||
};
|
||||
|
||||
// Entity_Constant or Entity_TypeName
|
||||
Entity **other_fields;
|
||||
i32 other_field_count;
|
||||
} TypeRecord;
|
||||
|
||||
#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)) {
|
||||
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"))) {
|
||||
sel.entity = type->Record.enum_count;
|
||||
return sel;
|
||||
|
||||
88
src/parser.c
88
src/parser.c
@@ -1646,8 +1646,9 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
||||
f->expr_level++;
|
||||
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);
|
||||
}
|
||||
isize colon_count = 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);
|
||||
isize name_count = 0;
|
||||
|
||||
while (f->curr_token.kind != follow &&
|
||||
f->curr_token.kind != Token_EOF) {
|
||||
@@ -2088,6 +2090,8 @@ AstNodeArray parse_parameter_list(AstFile *f, bool allow_using, TokenKind follow
|
||||
is_using = false;
|
||||
}
|
||||
|
||||
name_count += names.count;
|
||||
|
||||
// expect_token_after(f, Token_Colon, "parameter list");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
array_add(¶ms, make_parameter(f, names, type, is_using));
|
||||
if (!allow_token(f, Token_Comma)) {
|
||||
break;
|
||||
AstNode *param = make_parameter(f, names, type, is_using);
|
||||
array_add(¶ms, param);
|
||||
|
||||
|
||||
if (separator == Token_Semicolon) {
|
||||
expect_semicolon(f, param);
|
||||
} else {
|
||||
if (!allow_token(f, separator)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (name_count_) *name_count_ = name_count;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
AstNodeArray parse_record_params(AstFile *f, isize *decl_count_, bool allow_using, String context) {
|
||||
AstNodeArray decls = make_ast_node_array(f);
|
||||
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;
|
||||
AstNodeArray parse_record_params(AstFile *f, isize *field_count_, bool allow_using, String context) {
|
||||
return parse_parameter_list(f, field_count_, allow_using, Token_Semicolon, Token_CloseBrace);
|
||||
}
|
||||
|
||||
AstNode *parse_identifier_or_type(AstFile *f) {
|
||||
@@ -2380,7 +2334,7 @@ void parse_proc_signature(AstFile *f,
|
||||
AstNodeArray *params,
|
||||
AstNodeArray *results) {
|
||||
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");
|
||||
*results = parse_results(f);
|
||||
}
|
||||
|
||||
18
src/ssa.c
18
src/ssa.c
@@ -2522,15 +2522,8 @@ void ssa_gen_global_type_name(ssaModule *m, Entity *e, String name) {
|
||||
ssa_module_add_value(m, e, t);
|
||||
map_ssa_value_set(&m->members, hash_string(name), t);
|
||||
|
||||
Type *bt = base_type(e->type);
|
||||
if (bt->kind == Type_Record) {
|
||||
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)) {
|
||||
if (is_type_union(e->type)) {
|
||||
Type *bt = base_type(e->type);
|
||||
TypeRecord *s = &bt->Record;
|
||||
// NOTE(bill): Zeroth entry is null (for `match type` stmts)
|
||||
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);
|
||||
ssa_emit_store(proc, base, ssa_get_type_info_ptr(proc, type_info_data, enum_base));
|
||||
|
||||
if (t->Record.other_field_count > 0) {
|
||||
Entity **fields = t->Record.other_fields;
|
||||
isize count = t->Record.other_field_count;
|
||||
if (t->Record.enum_value_count > 0) {
|
||||
Entity **fields = t->Record.enum_values;
|
||||
isize count = t->Record.enum_value_count;
|
||||
ssaValue *value_array = NULL;
|
||||
ssaValue *name_array = NULL;
|
||||
|
||||
|
||||
{
|
||||
Token token = {Token_Ident};
|
||||
i32 id = cast(i32)entry_index;
|
||||
|
||||
Reference in New Issue
Block a user