mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 09:22:22 -07:00
Comma for all field separators; Overloaded procedures follow exportation rules
This commit is contained in:
+11
-6
@@ -1,23 +1,29 @@
|
||||
#import "atomic.odin";
|
||||
#import "fmt.odin";
|
||||
#import "hash.odin";
|
||||
#import "math.odin";
|
||||
#import "mem.odin";
|
||||
#import "opengl.odin";
|
||||
#import "os.odin";
|
||||
#import "sync.odin";
|
||||
#import "utf8.odin";
|
||||
|
||||
main :: proc() {
|
||||
foo :: proc(x: ^int) {
|
||||
foo :: proc(x: ^i32) {
|
||||
fmt.println("^int");
|
||||
}
|
||||
foo :: proc(x: rawptr) {
|
||||
fmt.println("rawptr");
|
||||
}
|
||||
|
||||
a: ^int;
|
||||
b: ^f32;
|
||||
a: i32;
|
||||
b: f32;
|
||||
c: rawptr;
|
||||
foo(a);
|
||||
foo(b);
|
||||
foo(^a);
|
||||
foo(^b);
|
||||
foo(c);
|
||||
// foo(nil);
|
||||
atomic.store(^a, 1);
|
||||
|
||||
foo :: proc() {
|
||||
fmt.printf("Zero args\n");
|
||||
@@ -32,7 +38,6 @@ main :: proc() {
|
||||
THINGI :: 14451;
|
||||
THINGF :: 14451.1;
|
||||
|
||||
|
||||
foo();
|
||||
foo(THINGI as int);
|
||||
foo(int(THINGI));
|
||||
|
||||
+56
-56
@@ -14,20 +14,20 @@
|
||||
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
||||
// The compiler relies upon this _exact_ order
|
||||
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_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_Info_Enum_Value :: raw_union {
|
||||
f: f64;
|
||||
i: i64;
|
||||
f: f64,
|
||||
i: i64,
|
||||
}
|
||||
|
||||
// NOTE(bill): This much the same as the compiler's
|
||||
@@ -40,55 +40,55 @@ Calling_Convention :: enum {
|
||||
|
||||
Type_Info :: union {
|
||||
Named: struct #ordered {
|
||||
name: string;
|
||||
base: ^Type_Info; // This will _not_ be a Type_Info.Named
|
||||
};
|
||||
name: string,
|
||||
base: ^Type_Info, // This will _not_ be a Type_Info.Named
|
||||
},
|
||||
Integer: struct #ordered {
|
||||
size: int; // in bytes
|
||||
signed: bool;
|
||||
};
|
||||
size: int, // in bytes
|
||||
signed: bool,
|
||||
},
|
||||
Float: struct #ordered {
|
||||
size: int; // in bytes
|
||||
};
|
||||
Any: struct #ordered {};
|
||||
String: struct #ordered {};
|
||||
Boolean: struct #ordered {};
|
||||
size: int, // in bytes
|
||||
},
|
||||
Any: struct #ordered {},
|
||||
String: struct #ordered {},
|
||||
Boolean: struct #ordered {},
|
||||
Pointer: struct #ordered {
|
||||
elem: ^Type_Info; // nil -> rawptr
|
||||
};
|
||||
elem: ^Type_Info, // nil -> rawptr
|
||||
},
|
||||
Maybe: struct #ordered {
|
||||
elem: ^Type_Info;
|
||||
};
|
||||
elem: ^Type_Info,
|
||||
},
|
||||
Procedure: struct #ordered {
|
||||
params: ^Type_Info; // Type_Info.Tuple
|
||||
results: ^Type_Info; // Type_Info.Tuple
|
||||
variadic: bool;
|
||||
convention: Calling_Convention;
|
||||
};
|
||||
params: ^Type_Info, // Type_Info.Tuple
|
||||
results: ^Type_Info, // Type_Info.Tuple
|
||||
variadic: bool,
|
||||
convention: Calling_Convention,
|
||||
},
|
||||
Array: struct #ordered {
|
||||
elem: ^Type_Info;
|
||||
elem_size: int;
|
||||
count: int;
|
||||
};
|
||||
elem: ^Type_Info,
|
||||
elem_size: int,
|
||||
count: int,
|
||||
},
|
||||
Slice: struct #ordered {
|
||||
elem: ^Type_Info;
|
||||
elem_size: int;
|
||||
};
|
||||
elem: ^Type_Info,
|
||||
elem_size: 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;
|
||||
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;
|
||||
names: []string;
|
||||
values: []Type_Info_Enum_Value;
|
||||
};
|
||||
base: ^Type_Info,
|
||||
names: []string,
|
||||
values: []Type_Info_Enum_Value,
|
||||
},
|
||||
}
|
||||
|
||||
type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
@@ -137,17 +137,17 @@ Allocator_Proc :: type proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
|
||||
Allocator :: struct #ordered {
|
||||
procedure: Allocator_Proc;
|
||||
data: rawptr;
|
||||
procedure: Allocator_Proc,
|
||||
data: rawptr,
|
||||
}
|
||||
|
||||
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 __context: Context;
|
||||
|
||||
+18
-18
@@ -5,8 +5,8 @@
|
||||
DEFAULT_BUFFER_SIZE :: 1<<12;
|
||||
|
||||
Buffer :: struct {
|
||||
data: []byte;
|
||||
length: int;
|
||||
data: []byte,
|
||||
length: int,
|
||||
}
|
||||
|
||||
buffer_write :: proc(buf: ^Buffer, b: []byte) {
|
||||
@@ -38,22 +38,22 @@ buffer_write_rune :: proc(buf: ^Buffer, r: rune) {
|
||||
}
|
||||
|
||||
Fmt_Info :: struct {
|
||||
minus: bool;
|
||||
plus: bool;
|
||||
space: bool;
|
||||
zero: bool;
|
||||
hash: bool;
|
||||
width_set: bool;
|
||||
prec_set: bool;
|
||||
minus: bool,
|
||||
plus: bool,
|
||||
space: bool,
|
||||
zero: bool,
|
||||
hash: bool,
|
||||
width_set: bool,
|
||||
prec_set: bool,
|
||||
|
||||
width: int;
|
||||
prec: int;
|
||||
width: int,
|
||||
prec: int,
|
||||
|
||||
reordered: bool;
|
||||
good_arg_index: bool;
|
||||
reordered: bool,
|
||||
good_arg_index: bool,
|
||||
|
||||
buf: ^Buffer;
|
||||
arg: any; // Temporary
|
||||
buf: ^Buffer,
|
||||
arg: any, // Temporary
|
||||
}
|
||||
|
||||
|
||||
@@ -827,9 +827,9 @@ __real_to_string :: proc(start: ^string, out: []byte, decimal_pos: ^i32, val: f6
|
||||
|
||||
generic_ftoa :: proc(buf: []byte, val: f64, verb: rune, prec, bit_size: int) -> []byte {
|
||||
Float_Info :: struct {
|
||||
mantbits: uint;
|
||||
expbits: uint;
|
||||
bias: int;
|
||||
mantbits: uint,
|
||||
expbits: uint,
|
||||
bias: int,
|
||||
};
|
||||
f32info := Float_Info{23, 8, -127};
|
||||
f64info := Float_Info{52, 11, -1023};
|
||||
|
||||
+7
-7
@@ -68,7 +68,7 @@ align_forward :: proc(ptr: rawptr, align: int) -> rawptr {
|
||||
|
||||
|
||||
Allocation_Header :: struct {
|
||||
size: int;
|
||||
size: int,
|
||||
}
|
||||
|
||||
allocation_header_fill :: proc(header: ^Allocation_Header, data: rawptr, size: int) {
|
||||
@@ -94,15 +94,15 @@ allocation_header :: proc(data: rawptr) -> ^Allocation_Header {
|
||||
|
||||
// Custom allocators
|
||||
Arena :: struct {
|
||||
backing: Allocator;
|
||||
offset: int;
|
||||
memory: []byte;
|
||||
temp_count: int;
|
||||
backing: Allocator,
|
||||
offset: int,
|
||||
memory: []byte,
|
||||
temp_count: int,
|
||||
}
|
||||
|
||||
Arena_Temp_Memory :: struct {
|
||||
arena: ^Arena;
|
||||
original_count: int;
|
||||
arena: ^Arena,
|
||||
original_count: int,
|
||||
}
|
||||
|
||||
|
||||
|
||||
+18
-18
@@ -2,14 +2,14 @@
|
||||
#import "atomic.odin";
|
||||
|
||||
Semaphore :: struct {
|
||||
handle: win32.HANDLE;
|
||||
handle: win32.HANDLE,
|
||||
}
|
||||
|
||||
Mutex :: struct {
|
||||
semaphore: Semaphore;
|
||||
counter: i32;
|
||||
owner: i32;
|
||||
recursion: i32;
|
||||
semaphore: Semaphore,
|
||||
counter: i32,
|
||||
owner: i32,
|
||||
recursion: i32,
|
||||
}
|
||||
|
||||
current_thread_id :: proc() -> i32 {
|
||||
@@ -36,8 +36,8 @@ semaphore_wait :: proc(s: ^Semaphore) {
|
||||
|
||||
|
||||
mutex_init :: proc(m: ^Mutex) {
|
||||
atomic.store32(^m.counter, 0);
|
||||
atomic.store32(^m.owner, current_thread_id());
|
||||
atomic.store(^m.counter, 0);
|
||||
atomic.store(^m.owner, current_thread_id());
|
||||
semaphore_init(^m.semaphore);
|
||||
m.recursion = 0;
|
||||
}
|
||||
@@ -46,27 +46,27 @@ mutex_destroy :: proc(m: ^Mutex) {
|
||||
}
|
||||
mutex_lock :: proc(m: ^Mutex) {
|
||||
thread_id := current_thread_id();
|
||||
if atomic.fetch_add32(^m.counter, 1) > 0 {
|
||||
if thread_id != atomic.load32(^m.owner) {
|
||||
if atomic.fetch_add(^m.counter, 1) > 0 {
|
||||
if thread_id != atomic.load(^m.owner) {
|
||||
semaphore_wait(^m.semaphore);
|
||||
}
|
||||
}
|
||||
atomic.store32(^m.owner, thread_id);
|
||||
atomic.store(^m.owner, thread_id);
|
||||
m.recursion += 1;
|
||||
}
|
||||
mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||
thread_id := current_thread_id();
|
||||
if atomic.load32(^m.owner) == thread_id {
|
||||
atomic.fetch_add32(^m.counter, 1);
|
||||
if atomic.load(^m.owner) == thread_id {
|
||||
atomic.fetch_add(^m.counter, 1);
|
||||
} else {
|
||||
expected: i32 = 0;
|
||||
if atomic.load32(^m.counter) != 0 {
|
||||
if atomic.load(^m.counter) != 0 {
|
||||
return false;
|
||||
}
|
||||
if atomic.compare_exchange32(^m.counter, expected, 1) == 0 {
|
||||
if atomic.compare_exchange(^m.counter, expected, 1) == 0 {
|
||||
return false;
|
||||
}
|
||||
atomic.store32(^m.owner, thread_id);
|
||||
atomic.store(^m.owner, thread_id);
|
||||
}
|
||||
m.recursion += 1;
|
||||
return true;
|
||||
@@ -74,15 +74,15 @@ mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||
mutex_unlock :: proc(m: ^Mutex) {
|
||||
recursion: i32;
|
||||
thread_id := current_thread_id();
|
||||
assert(thread_id == atomic.load32(^m.owner));
|
||||
assert(thread_id == atomic.load(^m.owner));
|
||||
|
||||
m.recursion -= 1;
|
||||
recursion = m.recursion;
|
||||
if recursion == 0 {
|
||||
atomic.store32(^m.owner, thread_id);
|
||||
atomic.store(^m.owner, thread_id);
|
||||
}
|
||||
|
||||
if atomic.fetch_add32(^m.counter, -1) > 1 {
|
||||
if atomic.fetch_add(^m.counter, -1) > 1 {
|
||||
if recursion == 0 {
|
||||
semaphore_release(^m.semaphore);
|
||||
}
|
||||
|
||||
+46
-48
@@ -16,7 +16,7 @@ LPARAM :: int;
|
||||
LRESULT :: int;
|
||||
ATOM :: i16;
|
||||
BOOL :: i32;
|
||||
WNDPROC :: type proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT;
|
||||
WNDPROC :: type proc(HWND, u32, WPARAM, LPARAM) -> LRESULT #cc_c;
|
||||
|
||||
|
||||
INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE;
|
||||
@@ -56,61 +56,61 @@ SW_SHOW :: 5;
|
||||
|
||||
|
||||
POINT :: struct #ordered {
|
||||
x, y: i32;
|
||||
x, y: i32,
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
MSG :: struct #ordered {
|
||||
hwnd: HWND;
|
||||
message: u32;
|
||||
wparam: WPARAM;
|
||||
lparam: LPARAM;
|
||||
time: u32;
|
||||
pt: POINT;
|
||||
hwnd: HWND,
|
||||
message: u32,
|
||||
wparam: WPARAM,
|
||||
lparam: LPARAM,
|
||||
time: u32,
|
||||
pt: POINT,
|
||||
}
|
||||
|
||||
RECT :: struct #ordered {
|
||||
left: i32;
|
||||
top: i32;
|
||||
right: i32;
|
||||
bottom: i32;
|
||||
left: i32,
|
||||
top: i32,
|
||||
right: i32,
|
||||
bottom: i32,
|
||||
}
|
||||
|
||||
FILETIME :: struct #ordered {
|
||||
lo, hi: u32;
|
||||
lo, hi: u32,
|
||||
}
|
||||
|
||||
BY_HANDLE_FILE_INFORMATION :: struct #ordered {
|
||||
file_attributes: u32;
|
||||
file_attributes: u32,
|
||||
creation_time,
|
||||
last_access_time,
|
||||
last_write_time: FILETIME;
|
||||
last_write_time: FILETIME,
|
||||
volume_serial_number,
|
||||
file_size_high,
|
||||
file_size_low,
|
||||
number_of_links,
|
||||
file_index_high,
|
||||
file_index_low: u32;
|
||||
file_index_low: u32,
|
||||
}
|
||||
|
||||
FILE_ATTRIBUTE_DATA :: struct #ordered {
|
||||
file_attributes: u32;
|
||||
file_attributes: u32,
|
||||
creation_time,
|
||||
last_access_time,
|
||||
last_write_time: FILETIME;
|
||||
last_write_time: FILETIME,
|
||||
file_size_high,
|
||||
file_size_low: u32;
|
||||
file_size_low: u32,
|
||||
}
|
||||
|
||||
GET_FILEEX_INFO_LEVELS :: i32;
|
||||
@@ -249,9 +249,9 @@ HEAP_ZERO_MEMORY :: 0x00000008;
|
||||
// Synchronization
|
||||
|
||||
SECURITY_ATTRIBUTES :: struct #ordered {
|
||||
length: u32;
|
||||
security_descriptor: rawptr;
|
||||
inherit_handle: BOOL;
|
||||
length: u32,
|
||||
security_descriptor: rawptr,
|
||||
inherit_handle: BOOL,
|
||||
}
|
||||
|
||||
INFINITE :: 0xffffffff;
|
||||
@@ -281,25 +281,23 @@ ReadBarrier :: proc() #foreign
|
||||
|
||||
// GDI
|
||||
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,
|
||||
}
|
||||
BITMAPINFO :: struct #ordered {
|
||||
using header: BITMAPINFOHEADER;
|
||||
colors: [1]RGBQUAD;
|
||||
using header: BITMAPINFOHEADER,
|
||||
colors: [1]RGBQUAD,
|
||||
}
|
||||
|
||||
|
||||
RGBQUAD :: struct #ordered {
|
||||
blue, green, red, reserved: byte;
|
||||
}
|
||||
RGBQUAD :: struct #ordered { blue, green, red, reserved: byte }
|
||||
|
||||
BI_RGB :: 0;
|
||||
DIB_RGB_COLORS :: 0x00;
|
||||
@@ -354,7 +352,7 @@ wglCreateContextAttribsARBType :: proc(hdc: HDC, hshareContext: rawptr, attribLi
|
||||
PIXELFORMATDESCRIPTOR :: struct #ordered {
|
||||
size,
|
||||
version,
|
||||
flags: u32;
|
||||
flags: u32,
|
||||
|
||||
pixel_type,
|
||||
color_bits,
|
||||
@@ -375,11 +373,11 @@ PIXELFORMATDESCRIPTOR :: struct #ordered {
|
||||
stencil_bits,
|
||||
aux_buffers,
|
||||
layer_type,
|
||||
reserved: byte;
|
||||
reserved: byte,
|
||||
|
||||
layer_mask,
|
||||
visible_mask,
|
||||
damage_mask: u32;
|
||||
damage_mask: u32,
|
||||
}
|
||||
|
||||
GetDC :: proc(h: HANDLE) -> HDC #foreign
|
||||
|
||||
+1
-3
@@ -8,9 +8,7 @@ UTF_MAX :: 4;
|
||||
SURROGATE_MIN :: 0xd800;
|
||||
SURROGATE_MAX :: 0xdfff;
|
||||
|
||||
Accept_Range :: struct {
|
||||
lo, hi: u8;
|
||||
}
|
||||
Accept_Range :: struct { lo, hi: u8 }
|
||||
|
||||
accept_ranges := [5]Accept_Range{
|
||||
{0x80, 0xbf},
|
||||
|
||||
+88
-28
@@ -5,7 +5,7 @@ ExprKind check_expr_base (Checker *c, Operand *operand, AstNode *
|
||||
Type * check_type_extra (Checker *c, AstNode *expression, Type *named_type);
|
||||
Type * check_type (Checker *c, AstNode *expression);
|
||||
void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def);
|
||||
Entity * check_selector (Checker *c, Operand *operand, AstNode *node);
|
||||
Entity * check_selector (Checker *c, Operand *operand, AstNode *node, Type *type_hint);
|
||||
void check_not_tuple (Checker *c, Operand *operand);
|
||||
void convert_to_typed (Checker *c, Operand *operand, Type *target_type, i32 level);
|
||||
gbString expr_to_string (AstNode *expression);
|
||||
@@ -757,6 +757,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_v
|
||||
p->flags &= ~FieldFlag_no_alias; // Remove the flag
|
||||
}
|
||||
}
|
||||
|
||||
for_array(j, p->names) {
|
||||
AstNode *name = p->names.e[j];
|
||||
if (ast_node_expect(name, AstNode_Ident)) {
|
||||
@@ -779,6 +780,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_v
|
||||
// Custom Calling convention for variadic parameters
|
||||
Entity *end = variables[variable_count-1];
|
||||
end->type = make_type_slice(c->allocator, end->type);
|
||||
end->flags |= EntityFlag_Ellipsis;
|
||||
}
|
||||
|
||||
Type *tuple = make_type_tuple(c->allocator);
|
||||
@@ -874,10 +876,10 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Type
|
||||
Scope *s = e->scope;
|
||||
bool skip = false;
|
||||
|
||||
Entity **procs = gb_alloc_array(heap_allocator(), Entity *, overload_count);
|
||||
map_entity_multi_get_all(&s->elements, key, procs);
|
||||
if (type_hint != NULL) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
Entity **procs = gb_alloc_array(c->tmp_allocator, Entity *, overload_count);
|
||||
map_entity_multi_get_all(&s->elements, key, procs);
|
||||
// NOTE(bill): These should be done
|
||||
for (isize i = 0; i < overload_count; i++) {
|
||||
Type *t = base_type(procs[i]->type);
|
||||
@@ -899,12 +901,13 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Type
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
o->mode = Addressing_Overload;
|
||||
o->type = t_invalid;
|
||||
o->overload_count = overload_count;
|
||||
o->initial_overload_entity = e;
|
||||
o->mode = Addressing_Overload;
|
||||
o->type = t_invalid;
|
||||
o->overload_count = overload_count;
|
||||
o->overload_entities = procs;
|
||||
return;
|
||||
}
|
||||
gb_free(heap_allocator(), procs);
|
||||
}
|
||||
|
||||
add_entity_use(c, n, e);
|
||||
@@ -1040,7 +1043,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
|
||||
|
||||
case_ast_node(se, SelectorExpr, e);
|
||||
Operand o = {0};
|
||||
check_selector(c, &o, e);
|
||||
check_selector(c, &o, e, NULL);
|
||||
|
||||
switch (o.mode) {
|
||||
case Addressing_Invalid:
|
||||
@@ -2461,7 +2464,7 @@ bool check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *val
|
||||
return true;
|
||||
}
|
||||
|
||||
Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
|
||||
Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_hint) {
|
||||
ast_node(se, SelectorExpr, node);
|
||||
|
||||
bool check_op_expr = true;
|
||||
@@ -2480,31 +2483,88 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
|
||||
}
|
||||
|
||||
if (op_expr->kind == AstNode_Ident) {
|
||||
b32 is_not_exported = true;
|
||||
String name = op_expr->Ident.string;
|
||||
Entity *e = scope_lookup_entity(c->context.scope, name);
|
||||
|
||||
add_entity_use(c, op_expr, e);
|
||||
expr_entity = e;
|
||||
|
||||
if (e != NULL && e->kind == Entity_ImportName &&
|
||||
selector->kind == AstNode_Ident) {
|
||||
String sel_name = selector->Ident.string;
|
||||
|
||||
check_op_expr = false;
|
||||
entity = scope_lookup_entity(e->ImportName.scope, sel_name);
|
||||
if (entity == NULL) {
|
||||
error_node(op_expr, "`%.*s` is not declared by `%.*s`", LIT(sel_name), LIT(name));
|
||||
goto error;
|
||||
}
|
||||
if (entity->type == NULL) { // Not setup yet
|
||||
check_entity_decl(c, entity, NULL, NULL);
|
||||
}
|
||||
check_entity_decl(c, entity, NULL, NULL);
|
||||
GB_ASSERT(entity->type != NULL);
|
||||
|
||||
b32 is_not_exported = true;
|
||||
Entity **found = map_entity_get(&e->ImportName.scope->implicit, hash_string(sel_name));
|
||||
if (found == NULL) {
|
||||
bool is_overloaded = false;
|
||||
isize overload_count = 0;
|
||||
HashKey key = {0};
|
||||
if (entity->kind == Entity_Procedure) {
|
||||
key = hash_string(entity->token.string);
|
||||
// NOTE(bill): Overloads are only allowed with the same scope
|
||||
Scope *s = entity->scope;
|
||||
overload_count = map_entity_multi_count(&s->elements, key);
|
||||
if (overload_count > 1) {
|
||||
is_overloaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_overloaded) {
|
||||
Scope *s = entity->scope;
|
||||
bool skip = false;
|
||||
|
||||
Entity **procs = gb_alloc_array(heap_allocator(), Entity *, overload_count);
|
||||
map_entity_multi_get_all(&s->elements, key, procs);
|
||||
for (isize i = 0; i < overload_count; /**/) {
|
||||
Type *t = base_type(procs[i]->type);
|
||||
if (t == t_invalid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE(bill): Check to see if it's imported
|
||||
if (map_bool_get(&e->ImportName.scope->implicit, hash_pointer(procs[i]))) {
|
||||
gb_swap(Entity *, procs[i], procs[overload_count-1]);
|
||||
overload_count--;
|
||||
continue;
|
||||
}
|
||||
|
||||
Operand x = {0};
|
||||
x.mode = Addressing_Value;
|
||||
x.type = t;
|
||||
if (type_hint != NULL) {
|
||||
if (check_is_assignable_to(c, &x, type_hint)) {
|
||||
entity = procs[i];
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (overload_count > 0 && !skip) {
|
||||
operand->mode = Addressing_Overload;
|
||||
operand->type = t_invalid;
|
||||
operand->expr = node;
|
||||
operand->overload_count = overload_count;
|
||||
operand->overload_entities = procs;
|
||||
return procs[0];
|
||||
}
|
||||
}
|
||||
|
||||
bool *found = map_bool_get(&e->ImportName.scope->implicit, hash_pointer(entity));
|
||||
|
||||
if (!found) {
|
||||
is_not_exported = false;
|
||||
} else {
|
||||
Entity *f = *found;
|
||||
if (f->kind == Entity_ImportName) {
|
||||
if (entity->kind == Entity_ImportName) {
|
||||
is_not_exported = true;
|
||||
}
|
||||
}
|
||||
@@ -2515,8 +2575,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
|
||||
gb_string_free(sel_str);
|
||||
// NOTE(bill): Not really an error so don't goto error
|
||||
}
|
||||
|
||||
add_entity_use(c, selector, entity);
|
||||
}
|
||||
}
|
||||
if (check_op_expr) {
|
||||
@@ -3606,16 +3664,15 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
||||
|
||||
|
||||
if (operand->mode == Addressing_Overload) {
|
||||
Scope *s = operand->initial_overload_entity->scope;
|
||||
String name = operand->initial_overload_entity->token.string;
|
||||
HashKey key = hash_string(name);
|
||||
GB_ASSERT(operand->overload_entities != NULL &&
|
||||
operand->overload_count > 0);
|
||||
|
||||
isize overload_count = operand->overload_count;
|
||||
Entity ** procs = gb_alloc_array(heap_allocator(), Entity *, overload_count);
|
||||
Entity ** procs = operand->overload_entities;
|
||||
ValidProcAndScore *valids = gb_alloc_array(heap_allocator(), ValidProcAndScore, overload_count);
|
||||
isize valid_count = 0;
|
||||
|
||||
map_entity_multi_get_all(&s->elements, key, procs);
|
||||
String name = procs[0]->token.string;
|
||||
|
||||
for (isize i = 0; i < overload_count; i++) {
|
||||
Entity *e = procs[i];
|
||||
@@ -3666,9 +3723,13 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
||||
}
|
||||
proc_type = t_invalid;
|
||||
} else {
|
||||
GB_ASSERT(operand->expr->kind == AstNode_Ident);
|
||||
AstNode *expr = operand->expr;
|
||||
while (expr->kind == AstNode_SelectorExpr) {
|
||||
expr = expr->SelectorExpr.selector;
|
||||
}
|
||||
GB_ASSERT(expr->kind == AstNode_Ident);
|
||||
Entity *e = procs[valids[0].index];
|
||||
add_entity_use(c, operand->expr, e);
|
||||
add_entity_use(c, expr, e);
|
||||
proc_type = e->type;
|
||||
i64 score = 0;
|
||||
CallArgumentError err = check_call_arguments_internal(c, call, proc_type, operands.e, operands.count, true, &score);
|
||||
@@ -4473,7 +4534,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
||||
|
||||
|
||||
case_ast_node(se, SelectorExpr, node);
|
||||
check_selector(c, o, node);
|
||||
check_selector(c, o, node, type_hint);
|
||||
case_end;
|
||||
|
||||
|
||||
@@ -4763,7 +4824,6 @@ gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) {
|
||||
if (i > 0) {
|
||||
str = gb_string_appendc(str, sep);
|
||||
}
|
||||
|
||||
str = write_expr_to_string(str, params.e[i]);
|
||||
}
|
||||
return str;
|
||||
|
||||
+5
-11
@@ -215,14 +215,9 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
|
||||
if (op_a->mode == Addressing_Overload) {
|
||||
isize overload_count = op_a->overload_count;
|
||||
Entity *entity = op_a->initial_overload_entity;
|
||||
String name = entity->token.string;
|
||||
Scope *s = entity->scope;
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
Entity **procs = gb_alloc_array(c->tmp_allocator, Entity *, overload_count);
|
||||
Entity **procs = op_a->overload_entities;
|
||||
GB_ASSERT(procs != NULL && overload_count > 0);
|
||||
|
||||
HashKey key = hash_string(name);
|
||||
map_entity_multi_get_all(&s->elements, key, procs);
|
||||
// NOTE(bill): These should be done
|
||||
for (isize i = 0; i < overload_count; i++) {
|
||||
Type *t = base_type(procs[i]->type);
|
||||
@@ -238,15 +233,14 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
|
||||
if (e != NULL) {
|
||||
// HACK TODO(bill): Should the entities be freed as it's technically a leak
|
||||
op_a->mode = Addressing_Value;
|
||||
op_a->type = e->type;
|
||||
op_a->overload_count = 0;
|
||||
op_a->initial_overload_entity = NULL;
|
||||
op_a->overload_entities = NULL;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (node->kind == AstNode_Ident) {
|
||||
ast_node(i, Ident, node);
|
||||
@@ -1085,7 +1079,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
e = scope_lookup_entity(c->context.scope, name);
|
||||
} else if (expr->kind == AstNode_SelectorExpr) {
|
||||
Operand o = {0};
|
||||
e = check_selector(c, &o, expr);
|
||||
e = check_selector(c, &o, expr, NULL);
|
||||
is_selector = true;
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -28,7 +28,7 @@ typedef struct Operand {
|
||||
AstNode * expr;
|
||||
BuiltinProcId builtin_id;
|
||||
isize overload_count;
|
||||
Entity * initial_overload_entity;
|
||||
Entity ** overload_entities;
|
||||
} Operand;
|
||||
|
||||
typedef struct TypeAndValue {
|
||||
@@ -93,7 +93,7 @@ typedef struct Scope {
|
||||
Scope * first_child;
|
||||
Scope * last_child;
|
||||
MapEntity elements; // Key: String
|
||||
MapEntity implicit; // Key: String
|
||||
MapBool implicit; // Key: Entity *
|
||||
|
||||
Array(Scope *) shared;
|
||||
Array(Scope *) imported;
|
||||
@@ -344,7 +344,7 @@ Scope *make_scope(Scope *parent, gbAllocator allocator) {
|
||||
Scope *s = gb_alloc_item(allocator, Scope);
|
||||
s->parent = parent;
|
||||
map_entity_init(&s->elements, heap_allocator());
|
||||
map_entity_init(&s->implicit, heap_allocator());
|
||||
map_bool_init(&s->implicit, heap_allocator());
|
||||
array_init(&s->shared, heap_allocator());
|
||||
array_init(&s->imported, heap_allocator());
|
||||
|
||||
@@ -371,7 +371,7 @@ void destroy_scope(Scope *scope) {
|
||||
}
|
||||
|
||||
map_entity_destroy(&scope->elements);
|
||||
map_entity_destroy(&scope->implicit);
|
||||
map_bool_destroy(&scope->implicit);
|
||||
array_free(&scope->shared);
|
||||
array_free(&scope->imported);
|
||||
|
||||
@@ -540,6 +540,7 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void check_scope_usage(Checker *c, Scope *scope) {
|
||||
// TODO(bill): Use this?
|
||||
}
|
||||
@@ -1601,8 +1602,7 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
|
||||
// NOTE(bill): Do not add other imported entities
|
||||
bool ok = add_entity(c, parent_scope, NULL, e);
|
||||
if (ok && id->is_import) { // `#import`ed entities don't get exported
|
||||
HashKey key = hash_string(e->token.string);
|
||||
map_entity_set(&parent_scope->implicit, key, e);
|
||||
map_bool_set(&parent_scope->implicit, hash_pointer(e), true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
+3
-2
@@ -34,8 +34,9 @@ typedef enum EntityFlag {
|
||||
EntityFlag_Anonymous = 1<<2,
|
||||
EntityFlag_Field = 1<<3,
|
||||
EntityFlag_Param = 1<<4,
|
||||
EntityFlag_VectorElem = 1<<5,
|
||||
EntityFlag_NoAlias = 1<<6,
|
||||
EntityFlag_Ellipsis = 1<<5,
|
||||
EntityFlag_VectorElem = 1<<6,
|
||||
EntityFlag_NoAlias = 1<<7,
|
||||
} EntityFlag;
|
||||
|
||||
typedef enum OverloadKind {
|
||||
|
||||
+167
-77
@@ -432,7 +432,10 @@ Token ast_node_token(AstNode *node) {
|
||||
case AstNode_CallExpr:
|
||||
return ast_node_token(node->CallExpr.proc);
|
||||
case AstNode_SelectorExpr:
|
||||
return ast_node_token(node->SelectorExpr.selector);
|
||||
if (node->SelectorExpr.selector != NULL) {
|
||||
return ast_node_token(node->SelectorExpr.selector);
|
||||
}
|
||||
return node->SelectorExpr.token;
|
||||
case AstNode_IndexExpr:
|
||||
return node->IndexExpr.open;
|
||||
case AstNode_SliceExpr:
|
||||
@@ -1851,10 +1854,14 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
||||
case Token_Ident:
|
||||
operand = make_selector_expr(f, token, operand, parse_identifier(f));
|
||||
break;
|
||||
case Token_Integer:
|
||||
operand = make_selector_expr(f, token, operand, parse_expr(f, lhs));
|
||||
break;
|
||||
default: {
|
||||
syntax_error(f->curr_token, "Expected a selector");
|
||||
next_token(f);
|
||||
operand = make_selector_expr(f, f->curr_token, operand, NULL);
|
||||
operand = make_bad_expr(f, ast_node_token(operand), f->curr_token);
|
||||
// operand = make_selector_expr(f, f->curr_token, operand, NULL);
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
@@ -2046,7 +2053,7 @@ AstNodeArray parse_rhs_expr_list(AstFile *f) {
|
||||
return parse_expr_list(f, false);
|
||||
}
|
||||
|
||||
AstNodeArray parse_identifier_list(AstFile *f) {
|
||||
AstNodeArray parse_ident_list(AstFile *f) {
|
||||
AstNodeArray list = make_ast_node_array(f);
|
||||
|
||||
do {
|
||||
@@ -2227,106 +2234,189 @@ AstNode *parse_proc_type(AstFile *f, String *foreign_name_, String *link_name_)
|
||||
return make_proc_type(f, proc_token, params, results, tags, cc);
|
||||
}
|
||||
|
||||
void parse_field_prefixes(AstFile *f, u32 flags, i32 *using_count, i32 *no_alias_count) {
|
||||
while (f->curr_token.kind == Token_using ||
|
||||
f->curr_token.kind == Token_no_alias) {
|
||||
if (allow_token(f, Token_using)) {
|
||||
*using_count += 1;
|
||||
}
|
||||
if (allow_token(f, Token_no_alias)) {
|
||||
*no_alias_count += 1;
|
||||
}
|
||||
}
|
||||
if (*using_count > 1) {
|
||||
syntax_error(f->curr_token, "Multiple `using` in this field list");
|
||||
*using_count = 1;
|
||||
}
|
||||
if (*no_alias_count > 1) {
|
||||
syntax_error(f->curr_token, "Multiple `no_alias` in this field list");
|
||||
*no_alias_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool parse_expect_separator(AstFile *f, TokenKind separator, AstNode *param) {
|
||||
if (separator == Token_Semicolon) {
|
||||
expect_semicolon(f, param);
|
||||
} else {
|
||||
if (!allow_token(f, separator)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
AstNodeArray convert_to_ident_list(AstFile *f, AstNodeArray list) {
|
||||
AstNodeArray idents = {0};
|
||||
array_init_reserve(&idents, heap_allocator(), list.count);
|
||||
// Convert to ident list
|
||||
for_array(i, list) {
|
||||
AstNode *ident = list.e[i];
|
||||
switch (ident->kind) {
|
||||
case AstNode_Ident:
|
||||
case AstNode_BadExpr:
|
||||
break;
|
||||
default:
|
||||
error_node(ident, "Expected an identifier");
|
||||
ident = make_ident(f, blank_token);
|
||||
break;
|
||||
}
|
||||
array_add(&idents, ident);
|
||||
}
|
||||
return idents;
|
||||
}
|
||||
|
||||
AstNode *parse_var_type(AstFile *f, bool allow_ellipsis) {
|
||||
if (allow_ellipsis && f->curr_token.kind == Token_Ellipsis) {
|
||||
Token tok = f->curr_token;
|
||||
next_token(f);
|
||||
AstNode *type = parse_identifier_or_type(f);
|
||||
if (type == NULL) {
|
||||
error(tok, "variadic field missing type after `...`");
|
||||
type = make_bad_expr(f, tok, f->curr_token);
|
||||
}
|
||||
return make_ellipsis(f, tok, type);
|
||||
}
|
||||
AstNode *type = parse_type_attempt(f);
|
||||
if (type == NULL) {
|
||||
Token tok = f->curr_token;
|
||||
error(tok, "Expected a type");
|
||||
type = make_bad_expr(f, tok, f->curr_token);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
void check_field_prefixes(AstFile *f, AstNodeArray names, u32 flags, i32 *using_count, i32 *no_alias_count) {
|
||||
if (names.count > 1 && *using_count > 0) {
|
||||
syntax_error(f->curr_token, "Cannot apply `using` to more than one of the same type");
|
||||
*using_count = 0;
|
||||
}
|
||||
|
||||
if ((flags&FieldFlag_using) == 0 && *using_count > 0) {
|
||||
syntax_error(f->curr_token, "`using` is not allowed within this field list");
|
||||
*using_count = 0;
|
||||
}
|
||||
if ((flags&FieldFlag_no_alias) == 0 && *no_alias_count > 0) {
|
||||
syntax_error(f->curr_token, "`no_alias` is not allowed within this field list");
|
||||
*no_alias_count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
u32 field_prefixes_to_flags(i32 using_count, i32 no_alias_count) {
|
||||
u32 field_flags = 0;
|
||||
if (using_count > 0) field_flags |= FieldFlag_using;
|
||||
if (no_alias_count > 0) field_flags |= FieldFlag_no_alias;
|
||||
return field_flags;
|
||||
}
|
||||
|
||||
AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 flags,
|
||||
TokenKind separator, TokenKind follow) {
|
||||
AstNodeArray params = make_ast_node_array(f);
|
||||
isize name_count = 0;
|
||||
AstNodeArray list = make_ast_node_array(f);
|
||||
isize name_count = 0;
|
||||
bool allow_ellipsis = flags&FieldFlag_ellipsis;
|
||||
|
||||
// TODO(bill): Allow for just a list of types
|
||||
i32 using_count = 0;
|
||||
i32 no_alias_count = 0;
|
||||
parse_field_prefixes(f, flags, &using_count, &no_alias_count);
|
||||
while (f->curr_token.kind != follow &&
|
||||
f->curr_token.kind != Token_Colon &&
|
||||
f->curr_token.kind != Token_EOF) {
|
||||
i32 using_count = 0;
|
||||
i32 no_alias_count = 0;
|
||||
while (f->curr_token.kind == Token_using ||
|
||||
f->curr_token.kind == Token_no_alias) {
|
||||
if (allow_token(f, Token_using)) {
|
||||
using_count++;
|
||||
}
|
||||
if (allow_token(f, Token_no_alias)) {
|
||||
no_alias_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AstNodeArray names = parse_identifier_list(f);
|
||||
if (names.count == 0) {
|
||||
syntax_error(f->curr_token, "Empty field declaration");
|
||||
AstNode *param = parse_var_type(f, allow_ellipsis);
|
||||
array_add(&list, param);
|
||||
if (f->curr_token.kind != Token_Comma) {
|
||||
break;
|
||||
}
|
||||
next_token(f);
|
||||
}
|
||||
|
||||
if (names.count > 1 && using_count > 0) {
|
||||
syntax_error(f->curr_token, "Cannot apply `using` to more than one of the same type");
|
||||
using_count = 0;
|
||||
if (f->curr_token.kind == Token_Colon) {
|
||||
AstNodeArray names = convert_to_ident_list(f, list); // Copy for semantic reasons
|
||||
if (names.count == 0) {
|
||||
syntax_error(f->curr_token, "Empty field declaration");
|
||||
}
|
||||
|
||||
if ((flags&FieldFlag_using) == 0 && using_count > 0) {
|
||||
syntax_error(f->curr_token, "`using` is not allowed within this field list");
|
||||
using_count = 0;
|
||||
}
|
||||
if ((flags&FieldFlag_no_alias) == 0 && no_alias_count > 0) {
|
||||
syntax_error(f->curr_token, "`no_alias` is not allowed within this field list");
|
||||
no_alias_count = 0;
|
||||
}
|
||||
if (using_count > 1) {
|
||||
syntax_error(f->curr_token, "Multiple `using` in this field list");
|
||||
using_count = 1;
|
||||
}
|
||||
if (no_alias_count > 1) {
|
||||
syntax_error(f->curr_token, "Multiple `no_alias` in this field list");
|
||||
no_alias_count = 1;
|
||||
}
|
||||
|
||||
check_field_prefixes(f, names, flags, &using_count, &no_alias_count);
|
||||
|
||||
name_count += names.count;
|
||||
|
||||
expect_token_after(f, Token_Colon, "field list");
|
||||
|
||||
AstNode *type = NULL;
|
||||
if ((flags&FieldFlag_ellipsis) != 0 && f->curr_token.kind == Token_Ellipsis) {
|
||||
Token ellipsis = f->curr_token;
|
||||
next_token(f);
|
||||
type = parse_type_attempt(f);
|
||||
if (type == NULL) {
|
||||
syntax_error(f->curr_token, "variadic field is missing a type after `..`");
|
||||
type = make_bad_expr(f, ellipsis, f->curr_token);
|
||||
} else {
|
||||
if (names.count > 1) {
|
||||
syntax_error(f->curr_token, "mutliple variadic fields, only `..`");
|
||||
} else {
|
||||
type = make_ellipsis(f, ellipsis, type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
type = parse_type_attempt(f);
|
||||
}
|
||||
|
||||
|
||||
if (type == NULL) {
|
||||
syntax_error(f->curr_token, "Expected a type for this field declaration");
|
||||
}
|
||||
|
||||
u32 flags = 0;
|
||||
if (using_count > 0) flags |= FieldFlag_using;
|
||||
if (no_alias_count > 0) flags |= FieldFlag_no_alias;
|
||||
AstNode *param = make_field(f, names, type, flags);
|
||||
AstNode *type = parse_var_type(f, allow_ellipsis);
|
||||
AstNode *param = make_field(f, names, type, field_prefixes_to_flags(using_count, no_alias_count));
|
||||
array_add(¶ms, param);
|
||||
|
||||
if (separator == Token_Semicolon) {
|
||||
expect_semicolon(f, param);
|
||||
} else {
|
||||
if (!allow_token(f, separator)) {
|
||||
parse_expect_separator(f, separator, type);
|
||||
|
||||
while (f->curr_token.kind != follow &&
|
||||
f->curr_token.kind != Token_EOF) {
|
||||
i32 using_count = 0;
|
||||
i32 no_alias_count = 0;
|
||||
parse_field_prefixes(f, flags, &using_count, &no_alias_count);
|
||||
|
||||
AstNodeArray names = parse_ident_list(f);
|
||||
if (names.count == 0) {
|
||||
syntax_error(f->curr_token, "Empty field declaration");
|
||||
break;
|
||||
}
|
||||
check_field_prefixes(f, names, flags, &using_count, &no_alias_count);
|
||||
name_count += names.count;
|
||||
|
||||
expect_token_after(f, Token_Colon, "field list");
|
||||
AstNode *type = parse_var_type(f, allow_ellipsis);
|
||||
|
||||
AstNode *param = make_field(f, names, type, field_prefixes_to_flags(using_count, no_alias_count));
|
||||
array_add(¶ms, param);
|
||||
|
||||
if (parse_expect_separator(f, separator, param)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (name_count_) *name_count_ = name_count;
|
||||
return params;
|
||||
}
|
||||
|
||||
check_field_prefixes(f, list, flags, &using_count, &no_alias_count);
|
||||
for_array(i, list) {
|
||||
AstNodeArray names = {0};
|
||||
AstNode *type = list.e[i];
|
||||
Token token = blank_token;
|
||||
|
||||
array_init_count(&names, heap_allocator(), 1);
|
||||
token.pos = ast_node_token(type).pos;
|
||||
names.e[0] = make_ident(f, token);
|
||||
|
||||
AstNode *param = make_field(f, names, list.e[i], field_prefixes_to_flags(using_count, no_alias_count));
|
||||
array_add(¶ms, param);
|
||||
}
|
||||
|
||||
if (name_count_) *name_count_ = name_count;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
AstNodeArray parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String context) {
|
||||
return parse_field_list(f, field_count_, flags, Token_Semicolon, Token_CloseBrace);
|
||||
return parse_field_list(f, field_count_, flags, Token_Comma, Token_CloseBrace);
|
||||
}
|
||||
|
||||
AstNode *parse_identifier_or_type(AstFile *f) {
|
||||
@@ -2753,7 +2843,7 @@ AstNode *parse_for_stmt(AstFile *f) {
|
||||
}
|
||||
|
||||
Token token = expect_token(f, Token_for);
|
||||
AstNodeArray names = parse_identifier_list(f);
|
||||
AstNodeArray names = parse_ident_list(f);
|
||||
parse_check_name_list_for_reserves(f, names);
|
||||
Token colon = expect_token_after(f, Token_Colon, "for name list");
|
||||
|
||||
|
||||
+3
-3
@@ -529,7 +529,7 @@ fraction:
|
||||
// HACK(bill): This may be inefficient
|
||||
TokenizerState state = save_tokenizer_state(t);
|
||||
advance_to_next_rune(t);
|
||||
if (t->curr_rune == '.') {
|
||||
if (digit_value(t->curr_rune) >= 10) {
|
||||
// TODO(bill): Clean up this shit
|
||||
restore_tokenizer_state(t, &state);
|
||||
goto end;
|
||||
@@ -837,9 +837,9 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
|
||||
case '.':
|
||||
token.kind = Token_Period; // Default
|
||||
if (gb_is_between(t->curr_rune, '0', '9')) { // Might be a number
|
||||
/* if (gb_is_between(t->curr_rune, '0', '9')) { // Might be a number
|
||||
token = scan_number_to_token(t, true);
|
||||
} else if (t->curr_rune == '.') { // Could be an ellipsis
|
||||
} else */ if (t->curr_rune == '.') { // Could be an ellipsis
|
||||
advance_to_next_rune(t);
|
||||
if (t->curr_rune == '.') {
|
||||
advance_to_next_rune(t);
|
||||
|
||||
+10
-2
@@ -1759,9 +1759,17 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
Entity *var = type->Tuple.variables[i];
|
||||
if (var != NULL) {
|
||||
GB_ASSERT(var->kind == Entity_Variable);
|
||||
if (i > 0)
|
||||
if (i > 0) {
|
||||
str = gb_string_appendc(str, ", ");
|
||||
str = write_type_to_string(str, var->type);
|
||||
}
|
||||
if (var->flags&EntityFlag_Ellipsis) {
|
||||
Type *slice = base_type(var->type);
|
||||
str = gb_string_appendc(str, "...");
|
||||
GB_ASSERT(is_type_slice(var->type));
|
||||
str = write_type_to_string(str, slice->Slice.elem);
|
||||
} else {
|
||||
str = write_type_to_string(str, var->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user