Comma for all field separators; Overloaded procedures follow exportation rules

This commit is contained in:
Ginger Bill
2017-01-17 18:47:38 +00:00
parent 383f5b55ad
commit cb59c1cf08
14 changed files with 439 additions and 285 deletions
+11 -6
View File
@@ -1,23 +1,29 @@
#import "atomic.odin"; #import "atomic.odin";
#import "fmt.odin"; #import "fmt.odin";
#import "hash.odin";
#import "math.odin"; #import "math.odin";
#import "mem.odin"; #import "mem.odin";
#import "opengl.odin";
#import "os.odin";
#import "sync.odin";
#import "utf8.odin";
main :: proc() { main :: proc() {
foo :: proc(x: ^int) { foo :: proc(x: ^i32) {
fmt.println("^int"); fmt.println("^int");
} }
foo :: proc(x: rawptr) { foo :: proc(x: rawptr) {
fmt.println("rawptr"); fmt.println("rawptr");
} }
a: ^int; a: i32;
b: ^f32; b: f32;
c: rawptr; c: rawptr;
foo(a); foo(^a);
foo(b); foo(^b);
foo(c); foo(c);
// foo(nil); // foo(nil);
atomic.store(^a, 1);
foo :: proc() { foo :: proc() {
fmt.printf("Zero args\n"); fmt.printf("Zero args\n");
@@ -32,7 +38,6 @@ main :: proc() {
THINGI :: 14451; THINGI :: 14451;
THINGF :: 14451.1; THINGF :: 14451.1;
foo(); foo();
foo(THINGI as int); foo(THINGI as int);
foo(int(THINGI)); foo(int(THINGI));
+56 -56
View File
@@ -14,20 +14,20 @@
// IMPORTANT NOTE(bill): Do not change the order of any of this data // IMPORTANT NOTE(bill): Do not change the order of any of this data
// The compiler relies upon this _exact_ order // The compiler relies upon this _exact_ order
Type_Info_Member :: struct #ordered { 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_Info_Record :: struct #ordered { 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_Info_Enum_Value :: raw_union { Type_Info_Enum_Value :: raw_union {
f: f64; f: f64,
i: i64; i: i64,
} }
// NOTE(bill): This much the same as the compiler's // NOTE(bill): This much the same as the compiler's
@@ -40,55 +40,55 @@ Calling_Convention :: enum {
Type_Info :: union { 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,
convention: Calling_Convention; convention: Calling_Convention,
}; },
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,
names: []string; names: []string,
values: []Type_Info_Enum_Value; values: []Type_Info_Enum_Value,
}; },
} }
type_info_base :: proc(info: ^Type_Info) -> ^Type_Info { 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, size, alignment: int,
old_memory: rawptr, old_size: int, flags: u64) -> rawptr; old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
Allocator :: struct #ordered { Allocator :: struct #ordered {
procedure: Allocator_Proc; procedure: Allocator_Proc,
data: rawptr; data: rawptr,
} }
Context :: struct #ordered { 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 __context: Context; #thread_local __context: Context;
+18 -18
View File
@@ -5,8 +5,8 @@
DEFAULT_BUFFER_SIZE :: 1<<12; DEFAULT_BUFFER_SIZE :: 1<<12;
Buffer :: struct { Buffer :: struct {
data: []byte; data: []byte,
length: int; length: int,
} }
buffer_write :: proc(buf: ^Buffer, b: []byte) { buffer_write :: proc(buf: ^Buffer, b: []byte) {
@@ -38,22 +38,22 @@ buffer_write_rune :: proc(buf: ^Buffer, r: rune) {
} }
Fmt_Info :: struct { Fmt_Info :: struct {
minus: bool; minus: bool,
plus: bool; plus: bool,
space: bool; space: bool,
zero: bool; zero: bool,
hash: bool; hash: bool,
width_set: bool; width_set: bool,
prec_set: bool; prec_set: bool,
width: int; width: int,
prec: int; prec: int,
reordered: bool; reordered: bool,
good_arg_index: bool; good_arg_index: bool,
buf: ^Buffer; buf: ^Buffer,
arg: any; // Temporary 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 { generic_ftoa :: proc(buf: []byte, val: f64, verb: rune, prec, bit_size: int) -> []byte {
Float_Info :: struct { Float_Info :: struct {
mantbits: uint; mantbits: uint,
expbits: uint; expbits: uint,
bias: int; bias: int,
}; };
f32info := Float_Info{23, 8, -127}; f32info := Float_Info{23, 8, -127};
f64info := Float_Info{52, 11, -1023}; f64info := Float_Info{52, 11, -1023};
+7 -7
View File
@@ -68,7 +68,7 @@ align_forward :: proc(ptr: rawptr, align: int) -> rawptr {
Allocation_Header :: struct { Allocation_Header :: struct {
size: int; size: int,
} }
allocation_header_fill :: proc(header: ^Allocation_Header, data: rawptr, 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 // Custom allocators
Arena :: struct { Arena :: struct {
backing: Allocator; backing: Allocator,
offset: int; offset: int,
memory: []byte; memory: []byte,
temp_count: int; temp_count: int,
} }
Arena_Temp_Memory :: struct { Arena_Temp_Memory :: struct {
arena: ^Arena; arena: ^Arena,
original_count: int; original_count: int,
} }
+18 -18
View File
@@ -2,14 +2,14 @@
#import "atomic.odin"; #import "atomic.odin";
Semaphore :: struct { Semaphore :: struct {
handle: win32.HANDLE; handle: win32.HANDLE,
} }
Mutex :: struct { Mutex :: struct {
semaphore: Semaphore; semaphore: Semaphore,
counter: i32; counter: i32,
owner: i32; owner: i32,
recursion: i32; recursion: i32,
} }
current_thread_id :: proc() -> i32 { current_thread_id :: proc() -> i32 {
@@ -36,8 +36,8 @@ semaphore_wait :: proc(s: ^Semaphore) {
mutex_init :: proc(m: ^Mutex) { mutex_init :: proc(m: ^Mutex) {
atomic.store32(^m.counter, 0); atomic.store(^m.counter, 0);
atomic.store32(^m.owner, current_thread_id()); atomic.store(^m.owner, current_thread_id());
semaphore_init(^m.semaphore); semaphore_init(^m.semaphore);
m.recursion = 0; m.recursion = 0;
} }
@@ -46,27 +46,27 @@ mutex_destroy :: proc(m: ^Mutex) {
} }
mutex_lock :: proc(m: ^Mutex) { mutex_lock :: proc(m: ^Mutex) {
thread_id := current_thread_id(); thread_id := current_thread_id();
if atomic.fetch_add32(^m.counter, 1) > 0 { if atomic.fetch_add(^m.counter, 1) > 0 {
if thread_id != atomic.load32(^m.owner) { if thread_id != atomic.load(^m.owner) {
semaphore_wait(^m.semaphore); semaphore_wait(^m.semaphore);
} }
} }
atomic.store32(^m.owner, thread_id); atomic.store(^m.owner, thread_id);
m.recursion += 1; m.recursion += 1;
} }
mutex_try_lock :: proc(m: ^Mutex) -> bool { mutex_try_lock :: proc(m: ^Mutex) -> bool {
thread_id := current_thread_id(); thread_id := current_thread_id();
if atomic.load32(^m.owner) == thread_id { if atomic.load(^m.owner) == thread_id {
atomic.fetch_add32(^m.counter, 1); atomic.fetch_add(^m.counter, 1);
} else { } else {
expected: i32 = 0; expected: i32 = 0;
if atomic.load32(^m.counter) != 0 { if atomic.load(^m.counter) != 0 {
return false; return false;
} }
if atomic.compare_exchange32(^m.counter, expected, 1) == 0 { if atomic.compare_exchange(^m.counter, expected, 1) == 0 {
return false; return false;
} }
atomic.store32(^m.owner, thread_id); atomic.store(^m.owner, thread_id);
} }
m.recursion += 1; m.recursion += 1;
return true; return true;
@@ -74,15 +74,15 @@ mutex_try_lock :: proc(m: ^Mutex) -> bool {
mutex_unlock :: proc(m: ^Mutex) { mutex_unlock :: proc(m: ^Mutex) {
recursion: i32; recursion: i32;
thread_id := current_thread_id(); thread_id := current_thread_id();
assert(thread_id == atomic.load32(^m.owner)); assert(thread_id == atomic.load(^m.owner));
m.recursion -= 1; m.recursion -= 1;
recursion = m.recursion; recursion = m.recursion;
if recursion == 0 { 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 { if recursion == 0 {
semaphore_release(^m.semaphore); semaphore_release(^m.semaphore);
} }
+46 -48
View File
@@ -16,7 +16,7 @@ LPARAM :: int;
LRESULT :: int; LRESULT :: int;
ATOM :: i16; ATOM :: i16;
BOOL :: i32; 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; INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE;
@@ -56,61 +56,61 @@ SW_SHOW :: 5;
POINT :: struct #ordered { POINT :: struct #ordered {
x, y: i32; x, y: i32,
} }
WNDCLASSEXA :: struct #ordered { 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,
} }
MSG :: struct #ordered { MSG :: struct #ordered {
hwnd: HWND; hwnd: HWND,
message: u32; message: u32,
wparam: WPARAM; wparam: WPARAM,
lparam: LPARAM; lparam: LPARAM,
time: u32; time: u32,
pt: POINT; pt: POINT,
} }
RECT :: struct #ordered { RECT :: struct #ordered {
left: i32; left: i32,
top: i32; top: i32,
right: i32; right: i32,
bottom: i32; bottom: i32,
} }
FILETIME :: struct #ordered { FILETIME :: struct #ordered {
lo, hi: u32; lo, hi: u32,
} }
BY_HANDLE_FILE_INFORMATION :: struct #ordered { BY_HANDLE_FILE_INFORMATION :: struct #ordered {
file_attributes: u32; file_attributes: u32,
creation_time, creation_time,
last_access_time, last_access_time,
last_write_time: FILETIME; last_write_time: FILETIME,
volume_serial_number, volume_serial_number,
file_size_high, file_size_high,
file_size_low, file_size_low,
number_of_links, number_of_links,
file_index_high, file_index_high,
file_index_low: u32; file_index_low: u32,
} }
FILE_ATTRIBUTE_DATA :: struct #ordered { FILE_ATTRIBUTE_DATA :: struct #ordered {
file_attributes: u32; file_attributes: u32,
creation_time, creation_time,
last_access_time, last_access_time,
last_write_time: FILETIME; last_write_time: FILETIME,
file_size_high, file_size_high,
file_size_low: u32; file_size_low: u32,
} }
GET_FILEEX_INFO_LEVELS :: i32; GET_FILEEX_INFO_LEVELS :: i32;
@@ -249,9 +249,9 @@ HEAP_ZERO_MEMORY :: 0x00000008;
// Synchronization // Synchronization
SECURITY_ATTRIBUTES :: struct #ordered { SECURITY_ATTRIBUTES :: struct #ordered {
length: u32; length: u32,
security_descriptor: rawptr; security_descriptor: rawptr,
inherit_handle: BOOL; inherit_handle: BOOL,
} }
INFINITE :: 0xffffffff; INFINITE :: 0xffffffff;
@@ -281,25 +281,23 @@ ReadBarrier :: proc() #foreign
// GDI // GDI
BITMAPINFOHEADER :: struct #ordered { 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,
} }
BITMAPINFO :: struct #ordered { BITMAPINFO :: struct #ordered {
using header: BITMAPINFOHEADER; using header: BITMAPINFOHEADER,
colors: [1]RGBQUAD; colors: [1]RGBQUAD,
} }
RGBQUAD :: struct #ordered { RGBQUAD :: struct #ordered { blue, green, red, reserved: byte }
blue, green, red, reserved: byte;
}
BI_RGB :: 0; BI_RGB :: 0;
DIB_RGB_COLORS :: 0x00; DIB_RGB_COLORS :: 0x00;
@@ -354,7 +352,7 @@ wglCreateContextAttribsARBType :: proc(hdc: HDC, hshareContext: rawptr, attribLi
PIXELFORMATDESCRIPTOR :: struct #ordered { PIXELFORMATDESCRIPTOR :: struct #ordered {
size, size,
version, version,
flags: u32; flags: u32,
pixel_type, pixel_type,
color_bits, color_bits,
@@ -375,11 +373,11 @@ 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,
} }
GetDC :: proc(h: HANDLE) -> HDC #foreign GetDC :: proc(h: HANDLE) -> HDC #foreign
+1 -3
View File
@@ -8,9 +8,7 @@ UTF_MAX :: 4;
SURROGATE_MIN :: 0xd800; SURROGATE_MIN :: 0xd800;
SURROGATE_MAX :: 0xdfff; SURROGATE_MAX :: 0xdfff;
Accept_Range :: struct { Accept_Range :: struct { lo, hi: u8 }
lo, hi: u8;
}
accept_ranges := [5]Accept_Range{ accept_ranges := [5]Accept_Range{
{0x80, 0xbf}, {0x80, 0xbf},
+88 -28
View File
@@ -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_extra (Checker *c, AstNode *expression, Type *named_type);
Type * check_type (Checker *c, AstNode *expression); Type * check_type (Checker *c, AstNode *expression);
void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def); 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 check_not_tuple (Checker *c, Operand *operand);
void convert_to_typed (Checker *c, Operand *operand, Type *target_type, i32 level); void convert_to_typed (Checker *c, Operand *operand, Type *target_type, i32 level);
gbString expr_to_string (AstNode *expression); 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 p->flags &= ~FieldFlag_no_alias; // Remove the flag
} }
} }
for_array(j, p->names) { for_array(j, p->names) {
AstNode *name = p->names.e[j]; AstNode *name = p->names.e[j];
if (ast_node_expect(name, AstNode_Ident)) { 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 // Custom Calling convention for variadic parameters
Entity *end = variables[variable_count-1]; Entity *end = variables[variable_count-1];
end->type = make_type_slice(c->allocator, end->type); end->type = make_type_slice(c->allocator, end->type);
end->flags |= EntityFlag_Ellipsis;
} }
Type *tuple = make_type_tuple(c->allocator); 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; Scope *s = e->scope;
bool skip = false; 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) { if (type_hint != NULL) {
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); 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 // NOTE(bill): These should be done
for (isize i = 0; i < overload_count; i++) { for (isize i = 0; i < overload_count; i++) {
Type *t = base_type(procs[i]->type); 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) { if (!skip) {
o->mode = Addressing_Overload; o->mode = Addressing_Overload;
o->type = t_invalid; o->type = t_invalid;
o->overload_count = overload_count; o->overload_count = overload_count;
o->initial_overload_entity = e; o->overload_entities = procs;
return; return;
} }
gb_free(heap_allocator(), procs);
} }
add_entity_use(c, n, e); 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); case_ast_node(se, SelectorExpr, e);
Operand o = {0}; Operand o = {0};
check_selector(c, &o, e); check_selector(c, &o, e, NULL);
switch (o.mode) { switch (o.mode) {
case Addressing_Invalid: case Addressing_Invalid:
@@ -2461,7 +2464,7 @@ bool check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *val
return true; 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); ast_node(se, SelectorExpr, node);
bool check_op_expr = true; bool check_op_expr = true;
@@ -2480,31 +2483,88 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
} }
if (op_expr->kind == AstNode_Ident) { if (op_expr->kind == AstNode_Ident) {
b32 is_not_exported = true;
String name = op_expr->Ident.string; String name = op_expr->Ident.string;
Entity *e = scope_lookup_entity(c->context.scope, name); Entity *e = scope_lookup_entity(c->context.scope, name);
add_entity_use(c, op_expr, e); add_entity_use(c, op_expr, e);
expr_entity = e; expr_entity = e;
if (e != NULL && e->kind == Entity_ImportName && if (e != NULL && e->kind == Entity_ImportName &&
selector->kind == AstNode_Ident) { selector->kind == AstNode_Ident) {
String sel_name = selector->Ident.string; String sel_name = selector->Ident.string;
check_op_expr = false; check_op_expr = false;
entity = scope_lookup_entity(e->ImportName.scope, sel_name); entity = scope_lookup_entity(e->ImportName.scope, sel_name);
if (entity == NULL) { if (entity == NULL) {
error_node(op_expr, "`%.*s` is not declared by `%.*s`", LIT(sel_name), LIT(name)); error_node(op_expr, "`%.*s` is not declared by `%.*s`", LIT(sel_name), LIT(name));
goto error; 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); GB_ASSERT(entity->type != NULL);
b32 is_not_exported = true; bool is_overloaded = false;
Entity **found = map_entity_get(&e->ImportName.scope->implicit, hash_string(sel_name)); isize overload_count = 0;
if (found == NULL) { 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; is_not_exported = false;
} else { } else {
Entity *f = *found; if (entity->kind == Entity_ImportName) {
if (f->kind == Entity_ImportName) {
is_not_exported = true; is_not_exported = true;
} }
} }
@@ -2515,8 +2575,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
gb_string_free(sel_str); gb_string_free(sel_str);
// NOTE(bill): Not really an error so don't goto error // NOTE(bill): Not really an error so don't goto error
} }
add_entity_use(c, selector, entity);
} }
} }
if (check_op_expr) { 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) { if (operand->mode == Addressing_Overload) {
Scope *s = operand->initial_overload_entity->scope; GB_ASSERT(operand->overload_entities != NULL &&
String name = operand->initial_overload_entity->token.string; operand->overload_count > 0);
HashKey key = hash_string(name);
isize overload_count = operand->overload_count; 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); ValidProcAndScore *valids = gb_alloc_array(heap_allocator(), ValidProcAndScore, overload_count);
isize valid_count = 0; 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++) { for (isize i = 0; i < overload_count; i++) {
Entity *e = procs[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; proc_type = t_invalid;
} else { } 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]; Entity *e = procs[valids[0].index];
add_entity_use(c, operand->expr, e); add_entity_use(c, expr, e);
proc_type = e->type; proc_type = e->type;
i64 score = 0; i64 score = 0;
CallArgumentError err = check_call_arguments_internal(c, call, proc_type, operands.e, operands.count, true, &score); 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); case_ast_node(se, SelectorExpr, node);
check_selector(c, o, node); check_selector(c, o, node, type_hint);
case_end; case_end;
@@ -4763,7 +4824,6 @@ gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) {
if (i > 0) { if (i > 0) {
str = gb_string_appendc(str, sep); str = gb_string_appendc(str, sep);
} }
str = write_expr_to_string(str, params.e[i]); str = write_expr_to_string(str, params.e[i]);
} }
return str; return str;
+5 -11
View File
@@ -215,14 +215,9 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
if (op_a->mode == Addressing_Overload) { if (op_a->mode == Addressing_Overload) {
isize overload_count = op_a->overload_count; isize overload_count = op_a->overload_count;
Entity *entity = op_a->initial_overload_entity; Entity **procs = op_a->overload_entities;
String name = entity->token.string; GB_ASSERT(procs != NULL && overload_count > 0);
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);
HashKey key = hash_string(name);
map_entity_multi_get_all(&s->elements, key, procs);
// NOTE(bill): These should be done // NOTE(bill): These should be done
for (isize i = 0; i < overload_count; i++) { for (isize i = 0; i < overload_count; i++) {
Type *t = base_type(procs[i]->type); Type *t = base_type(procs[i]->type);
@@ -238,15 +233,14 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
break; break;
} }
} }
gb_temp_arena_memory_end(tmp);
if (e != NULL) { if (e != NULL) {
// HACK TODO(bill): Should the entities be freed as it's technically a leak
op_a->mode = Addressing_Value; op_a->mode = Addressing_Value;
op_a->type = e->type; op_a->type = e->type;
op_a->overload_count = 0; op_a->overload_count = 0;
op_a->initial_overload_entity = NULL; op_a->overload_entities = NULL;
} }
} else { } else {
if (node->kind == AstNode_Ident) { if (node->kind == AstNode_Ident) {
ast_node(i, Ident, node); 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); e = scope_lookup_entity(c->context.scope, name);
} else if (expr->kind == AstNode_SelectorExpr) { } else if (expr->kind == AstNode_SelectorExpr) {
Operand o = {0}; Operand o = {0};
e = check_selector(c, &o, expr); e = check_selector(c, &o, expr, NULL);
is_selector = true; is_selector = true;
} }
+6 -6
View File
@@ -28,7 +28,7 @@ typedef struct Operand {
AstNode * expr; AstNode * expr;
BuiltinProcId builtin_id; BuiltinProcId builtin_id;
isize overload_count; isize overload_count;
Entity * initial_overload_entity; Entity ** overload_entities;
} Operand; } Operand;
typedef struct TypeAndValue { typedef struct TypeAndValue {
@@ -93,7 +93,7 @@ typedef struct Scope {
Scope * first_child; Scope * first_child;
Scope * last_child; Scope * last_child;
MapEntity elements; // Key: String MapEntity elements; // Key: String
MapEntity implicit; // Key: String MapBool implicit; // Key: Entity *
Array(Scope *) shared; Array(Scope *) shared;
Array(Scope *) imported; Array(Scope *) imported;
@@ -344,7 +344,7 @@ Scope *make_scope(Scope *parent, gbAllocator allocator) {
Scope *s = gb_alloc_item(allocator, Scope); Scope *s = gb_alloc_item(allocator, Scope);
s->parent = parent; s->parent = parent;
map_entity_init(&s->elements, heap_allocator()); 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->shared, heap_allocator());
array_init(&s->imported, 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->elements);
map_entity_destroy(&scope->implicit); map_bool_destroy(&scope->implicit);
array_free(&scope->shared); array_free(&scope->shared);
array_free(&scope->imported); array_free(&scope->imported);
@@ -540,6 +540,7 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
return NULL; return NULL;
} }
void check_scope_usage(Checker *c, Scope *scope) { void check_scope_usage(Checker *c, Scope *scope) {
// TODO(bill): Use this? // 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 // NOTE(bill): Do not add other imported entities
bool ok = add_entity(c, parent_scope, NULL, e); bool ok = add_entity(c, parent_scope, NULL, e);
if (ok && id->is_import) { // `#import`ed entities don't get exported if (ok && id->is_import) { // `#import`ed entities don't get exported
HashKey key = hash_string(e->token.string); map_bool_set(&parent_scope->implicit, hash_pointer(e), true);
map_entity_set(&parent_scope->implicit, key, e);
} }
} }
} else { } else {
+3 -2
View File
@@ -34,8 +34,9 @@ typedef enum EntityFlag {
EntityFlag_Anonymous = 1<<2, EntityFlag_Anonymous = 1<<2,
EntityFlag_Field = 1<<3, EntityFlag_Field = 1<<3,
EntityFlag_Param = 1<<4, EntityFlag_Param = 1<<4,
EntityFlag_VectorElem = 1<<5, EntityFlag_Ellipsis = 1<<5,
EntityFlag_NoAlias = 1<<6, EntityFlag_VectorElem = 1<<6,
EntityFlag_NoAlias = 1<<7,
} EntityFlag; } EntityFlag;
typedef enum OverloadKind { typedef enum OverloadKind {
+167 -77
View File
@@ -432,7 +432,10 @@ Token ast_node_token(AstNode *node) {
case AstNode_CallExpr: case AstNode_CallExpr:
return ast_node_token(node->CallExpr.proc); return ast_node_token(node->CallExpr.proc);
case AstNode_SelectorExpr: 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: case AstNode_IndexExpr:
return node->IndexExpr.open; return node->IndexExpr.open;
case AstNode_SliceExpr: case AstNode_SliceExpr:
@@ -1851,10 +1854,14 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
case Token_Ident: case Token_Ident:
operand = make_selector_expr(f, token, operand, parse_identifier(f)); operand = make_selector_expr(f, token, operand, parse_identifier(f));
break; break;
case Token_Integer:
operand = make_selector_expr(f, token, operand, parse_expr(f, lhs));
break;
default: { default: {
syntax_error(f->curr_token, "Expected a selector"); syntax_error(f->curr_token, "Expected a selector");
next_token(f); 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;
} }
} break; } break;
@@ -2046,7 +2053,7 @@ AstNodeArray parse_rhs_expr_list(AstFile *f) {
return parse_expr_list(f, false); 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); AstNodeArray list = make_ast_node_array(f);
do { 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); 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, AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 flags,
TokenKind separator, TokenKind follow) { TokenKind separator, TokenKind follow) {
AstNodeArray params = make_ast_node_array(f); 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 && while (f->curr_token.kind != follow &&
f->curr_token.kind != Token_Colon &&
f->curr_token.kind != Token_EOF) { f->curr_token.kind != Token_EOF) {
i32 using_count = 0; AstNode *param = parse_var_type(f, allow_ellipsis);
i32 no_alias_count = 0; array_add(&list, param);
while (f->curr_token.kind == Token_using || if (f->curr_token.kind != Token_Comma) {
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");
break; break;
} }
next_token(f);
}
if (names.count > 1 && using_count > 0) { if (f->curr_token.kind == Token_Colon) {
syntax_error(f->curr_token, "Cannot apply `using` to more than one of the same type"); AstNodeArray names = convert_to_ident_list(f, list); // Copy for semantic reasons
using_count = 0; if (names.count == 0) {
syntax_error(f->curr_token, "Empty field declaration");
} }
check_field_prefixes(f, names, flags, &using_count, &no_alias_count);
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;
}
name_count += names.count; name_count += names.count;
expect_token_after(f, Token_Colon, "field list"); expect_token_after(f, Token_Colon, "field list");
AstNode *type = parse_var_type(f, allow_ellipsis);
AstNode *type = NULL; AstNode *param = make_field(f, names, type, field_prefixes_to_flags(using_count, no_alias_count));
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);
array_add(&params, param); array_add(&params, param);
if (separator == Token_Semicolon) { parse_expect_separator(f, separator, type);
expect_semicolon(f, param);
} else { while (f->curr_token.kind != follow &&
if (!allow_token(f, separator)) { 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(&params, param);
if (parse_expect_separator(f, separator, param)) {
break; 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(&params, param);
} }
if (name_count_) *name_count_ = name_count; if (name_count_) *name_count_ = name_count;
return params; return params;
} }
AstNodeArray parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String context) { 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) { AstNode *parse_identifier_or_type(AstFile *f) {
@@ -2753,7 +2843,7 @@ AstNode *parse_for_stmt(AstFile *f) {
} }
Token token = expect_token(f, Token_for); 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); parse_check_name_list_for_reserves(f, names);
Token colon = expect_token_after(f, Token_Colon, "for name list"); Token colon = expect_token_after(f, Token_Colon, "for name list");
+3 -3
View File
@@ -529,7 +529,7 @@ fraction:
// HACK(bill): This may be inefficient // HACK(bill): This may be inefficient
TokenizerState state = save_tokenizer_state(t); TokenizerState state = save_tokenizer_state(t);
advance_to_next_rune(t); advance_to_next_rune(t);
if (t->curr_rune == '.') { if (digit_value(t->curr_rune) >= 10) {
// TODO(bill): Clean up this shit // TODO(bill): Clean up this shit
restore_tokenizer_state(t, &state); restore_tokenizer_state(t, &state);
goto end; goto end;
@@ -837,9 +837,9 @@ Token tokenizer_get_token(Tokenizer *t) {
case '.': case '.':
token.kind = Token_Period; // Default 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); 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); advance_to_next_rune(t);
if (t->curr_rune == '.') { if (t->curr_rune == '.') {
advance_to_next_rune(t); advance_to_next_rune(t);
+10 -2
View File
@@ -1759,9 +1759,17 @@ gbString write_type_to_string(gbString str, Type *type) {
Entity *var = type->Tuple.variables[i]; Entity *var = type->Tuple.variables[i];
if (var != NULL) { if (var != NULL) {
GB_ASSERT(var->kind == Entity_Variable); GB_ASSERT(var->kind == Entity_Variable);
if (i > 0) if (i > 0) {
str = gb_string_appendc(str, ", "); 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);
}
} }
} }
} }