mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 16:18:52 +00:00
Allow for overloading of polymorphic procedures
This commit is contained in:
+32
-7
@@ -19,6 +19,7 @@ import (
|
|||||||
*/
|
*/
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
general_stuff :: proc() {
|
general_stuff :: proc() {
|
||||||
// Complex numbers
|
// Complex numbers
|
||||||
a := 3 + 4i;
|
a := 3 + 4i;
|
||||||
@@ -316,7 +317,7 @@ explicit_parametric_polymorphic_procedures :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
new_batch := new(EntityBatch);
|
new_batch := new(EntityBatch);
|
||||||
append(manager.batches, new_batch);
|
append(&manager.batches, new_batch);
|
||||||
new_batch.batch_index = u32(len(manager.batches)-1);
|
new_batch.batch_index = u32(len(manager.batches)-1);
|
||||||
|
|
||||||
return use_empty_slot(manager, new_batch);
|
return use_empty_slot(manager, new_batch);
|
||||||
@@ -324,14 +325,14 @@ explicit_parametric_polymorphic_procedures :: proc() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
new_entity :: proc(manager: ^EntityManager, T: type, x, y: int) -> ^T {
|
new_entity :: proc(manager: ^EntityManager, T: type, x, y: f32) -> ^T {
|
||||||
result := new(T);
|
result := new(T);
|
||||||
result.entity = gen_new_entity(manager);
|
result.entity = gen_new_entity(manager);
|
||||||
result.derived.data = result;
|
result.derived.data = result;
|
||||||
result.derived.type_info = type_info(T);
|
result.derived.type_info = type_info(T);
|
||||||
|
|
||||||
result.position.x = f32(x);
|
result.position.x = x;
|
||||||
result.position.y = f32(y);
|
result.position.y = y;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -352,7 +353,7 @@ explicit_parametric_polymorphic_procedures :: proc() {
|
|||||||
T = Monster,
|
T = Monster,
|
||||||
);
|
);
|
||||||
|
|
||||||
append(entities, rock, door, monster);
|
append(&entities, rock, door, monster);
|
||||||
|
|
||||||
// An alternative to `union`s
|
// An alternative to `union`s
|
||||||
for entity in entities {
|
for entity in entities {
|
||||||
@@ -365,7 +366,32 @@ explicit_parametric_polymorphic_procedures :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pop :: proc(array: ^[]$T) -> T {
|
||||||
|
last: T;
|
||||||
|
if len(array) == 0 {
|
||||||
|
panic("Attempt to pop an empty slice");
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = array[len(array)-1];
|
||||||
|
^raw.Slice(array).len -= 1;
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
pop :: proc(a: ^[dynamic]$T) -> T {
|
||||||
|
last: T;
|
||||||
|
if len(a) == 0 {
|
||||||
|
panic("Attempt to pop an empty dynamic array");
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = array[len(array)-1];
|
||||||
|
^raw.DynamicArray(array).len -= 1;
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
|
when true {
|
||||||
foo :: proc(x: i64, y: f32) do fmt.println("#1", x, y);
|
foo :: proc(x: i64, y: f32) do fmt.println("#1", x, y);
|
||||||
foo :: proc(x: type, y: f32) do fmt.println("#2", type_info(x), y);
|
foo :: proc(x: type, y: f32) do fmt.println("#2", type_info(x), y);
|
||||||
foo :: proc(x: type) do fmt.println("#3", type_info(x));
|
foo :: proc(x: type) do fmt.println("#3", type_info(x));
|
||||||
@@ -375,7 +401,6 @@ main :: proc() {
|
|||||||
f(y = 3785.1546, x = 123);
|
f(y = 3785.1546, x = 123);
|
||||||
f(x = int, y = 897.513);
|
f(x = int, y = 897.513);
|
||||||
f(x = f32);
|
f(x = f32);
|
||||||
/*
|
|
||||||
general_stuff();
|
general_stuff();
|
||||||
foreign_blocks();
|
foreign_blocks();
|
||||||
default_arguments();
|
default_arguments();
|
||||||
@@ -402,7 +427,7 @@ main :: proc() {
|
|||||||
|
|
||||||
fmt.printf("The program \"%s\" calculates the value %d\n",
|
fmt.printf("The program \"%s\" calculates the value %d\n",
|
||||||
program, accumulator);
|
program, accumulator);
|
||||||
*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+39
-41
@@ -255,50 +255,51 @@ resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_AL
|
|||||||
return a.procedure(a.data, AllocatorMode.Resize, new_size, alignment, ptr, old_size, 0);
|
return a.procedure(a.data, AllocatorMode.Resize, new_size, alignment, ptr, old_size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// append :: proc(s: ^[]$T, args: ..T) -> int {
|
|
||||||
// if s == nil {
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
// slice := ^raw.Slice(s);
|
|
||||||
// arg_len := len(args);
|
|
||||||
// if arg_len <= 0 {
|
|
||||||
// return slice.len;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// arg_len = min(slice.cap-slice.len, arg_len);
|
append :: proc(array: ^[]$T, args: ..T) -> int {
|
||||||
// if arg_len > 0 {
|
if array == nil {
|
||||||
// data := ^T(slice.data);
|
return 0;
|
||||||
// assert(data != nil);
|
}
|
||||||
// sz :: size_of(T);
|
slice := ^raw.Slice(array);
|
||||||
// __mem_copy(data + slice.len, &args[0], sz*arg_len);
|
arg_len := len(args);
|
||||||
// slice.len += arg_len;
|
if arg_len <= 0 {
|
||||||
// }
|
return slice.len;
|
||||||
// return slice.len;
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// append :: proc(a: ^[dynamic]$T, args: ..T) -> int {
|
arg_len = min(slice.cap-slice.len, arg_len);
|
||||||
// array := ^raw.DynamicArray(a);
|
if arg_len > 0 {
|
||||||
|
data := ^T(slice.data);
|
||||||
|
assert(data != nil);
|
||||||
|
sz :: size_of(T);
|
||||||
|
__mem_copy(data + slice.len, &args[0], sz*arg_len);
|
||||||
|
slice.len += arg_len;
|
||||||
|
}
|
||||||
|
return slice.len;
|
||||||
|
}
|
||||||
|
|
||||||
// arg_len := len(args);
|
append :: proc(array_: ^[dynamic]$T, args: ..T) -> int {
|
||||||
// if arg_len <= 0 || items == nil {
|
array := ^raw.DynamicArray(array_);
|
||||||
// return array.len;
|
|
||||||
// }
|
arg_len := len(args);
|
||||||
|
if arg_len <= 0 {
|
||||||
|
return array.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ok := true;
|
ok := true;
|
||||||
// if array.cap <= array.len+arg_len {
|
if array.cap <= array.len+arg_len {
|
||||||
// cap := 2 * array.cap + max(8, arg_len);
|
cap := 2 * array.cap + max(8, arg_len);
|
||||||
// ok = __dynamic_array_reserve(array, size_of(T), align_of(T), cap);
|
ok = __dynamic_array_reserve(array, size_of(T), align_of(T), cap);
|
||||||
// }
|
}
|
||||||
// // TODO(bill): Better error handling for failed reservation
|
// TODO(bill): Better error handling for failed reservation
|
||||||
// if !ok do return array.len;
|
if !ok do return array.len;
|
||||||
|
|
||||||
// data := ^T(array.data);
|
data := ^T(array.data);
|
||||||
// assert(data != nil);
|
assert(data != nil);
|
||||||
// __mem_copy(data + array.len, items, size_of(T) * arg_len);
|
__mem_copy(data + array.len, &args[0], size_of(T) * arg_len);
|
||||||
// array.len += arg_len;
|
array.len += arg_len;
|
||||||
// return array.len;
|
return array.len;
|
||||||
// }
|
}
|
||||||
|
|
||||||
copy :: proc(dst, src: []$T) -> int #cc_contextless {
|
copy :: proc(dst, src: []$T) -> int #cc_contextless {
|
||||||
n := max(0, min(len(dst), len(src)));
|
n := max(0, min(len(dst), len(src)));
|
||||||
@@ -309,12 +310,10 @@ copy :: proc(dst, src: []$T) -> int #cc_contextless {
|
|||||||
|
|
||||||
new :: proc(T: type) -> ^T #inline do return ^T(alloc(size_of(T), align_of(T)));
|
new :: proc(T: type) -> ^T #inline do return ^T(alloc(size_of(T), align_of(T)));
|
||||||
|
|
||||||
/*
|
|
||||||
free :: proc(array: [dynamic]$T) do free_ptr(^raw.DynamicArray(&array).data);
|
free :: proc(array: [dynamic]$T) do free_ptr(^raw.DynamicArray(&array).data);
|
||||||
free :: proc(slice: []$T) do free_ptr(^raw.Slice(&slice).data);
|
free :: proc(slice: []$T) do free_ptr(^raw.Slice(&slice).data);
|
||||||
free :: proc(str: string) do free_ptr(^raw.String(&str).data);
|
free :: proc(str: string) do free_ptr(^raw.String(&str).data);
|
||||||
free :: proc(ptr: rawptr) do free_ptr(ptr);
|
free :: proc(ptr: rawptr) do free_ptr(ptr);
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -814,7 +813,6 @@ __dynamic_map_add_entry :: proc(using h: __MapHeader, key: __MapKey) -> int {
|
|||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
__dynamic_map_delete :: proc(using h: __MapHeader, key: __MapKey) {
|
__dynamic_map_delete :: proc(using h: __MapHeader, key: __MapKey) {
|
||||||
fr := __dynamic_map_find(h, key);
|
fr := __dynamic_map_find(h, key);
|
||||||
if fr.entry_index >= 0 {
|
if fr.entry_index >= 0 {
|
||||||
|
|||||||
+5
-5
@@ -70,17 +70,17 @@ write_string :: proc(buf: ^StringBuffer, s: string) {
|
|||||||
write_bytes :: proc(buf: ^StringBuffer, data: []u8) {
|
write_bytes :: proc(buf: ^StringBuffer, data: []u8) {
|
||||||
match b in buf {
|
match b in buf {
|
||||||
case StringBuffer.Static:
|
case StringBuffer.Static:
|
||||||
append(b.buf, ..data);
|
append(&b.buf, ..data);
|
||||||
case StringBuffer.Dynamic:
|
case StringBuffer.Dynamic:
|
||||||
append(b.buf, ..data);
|
append(&b.buf, ..data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write_byte :: proc(buf: ^StringBuffer, data: u8) {
|
write_byte :: proc(buf: ^StringBuffer, data: u8) {
|
||||||
match b in buf {
|
match b in buf {
|
||||||
case StringBuffer.Static:
|
case StringBuffer.Static:
|
||||||
append(b.buf, data);
|
append(&b.buf, data);
|
||||||
case StringBuffer.Dynamic:
|
case StringBuffer.Dynamic:
|
||||||
append(b.buf, data);
|
append(&b.buf, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write_rune :: proc(buf: ^StringBuffer, r: rune) {
|
write_rune :: proc(buf: ^StringBuffer, r: rune) {
|
||||||
@@ -484,7 +484,7 @@ fmt_bool :: proc(using fi: ^FmtInfo, b: bool, verb: rune) {
|
|||||||
fmt_write_padding :: proc(fi: ^FmtInfo, width: int) {
|
fmt_write_padding :: proc(fi: ^FmtInfo, width: int) {
|
||||||
if width <= 0 do return;
|
if width <= 0 do return;
|
||||||
|
|
||||||
pad_byte: u8 = fi.space ? ' ' : '0';
|
pad_byte := u8(fi.space ? ' ' : '0');
|
||||||
|
|
||||||
data := string_buffer_data(fi.buf^);
|
data := string_buffer_data(fi.buf^);
|
||||||
count := min(width, cap(data)-len(data));
|
count := min(width, cap(data)-len(data));
|
||||||
|
|||||||
@@ -103,8 +103,8 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn
|
|||||||
handle := Handle(win32.create_file_a(&buf[0], access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil));
|
handle := Handle(win32.create_file_a(&buf[0], access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil));
|
||||||
if handle != INVALID_HANDLE do return handle, ERROR_NONE;
|
if handle != INVALID_HANDLE do return handle, ERROR_NONE;
|
||||||
|
|
||||||
err := win32.get_last_error();
|
err := Errno(win32.get_last_error());
|
||||||
return INVALID_HANDLE, Errno(err);
|
return INVALID_HANDLE, err;
|
||||||
}
|
}
|
||||||
|
|
||||||
close :: proc(fd: Handle) {
|
close :: proc(fd: Handle) {
|
||||||
@@ -126,8 +126,8 @@ write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
|||||||
|
|
||||||
e := win32.write_file(win32.Handle(fd), &data[total_write], to_write, &single_write_length, nil);
|
e := win32.write_file(win32.Handle(fd), &data[total_write], to_write, &single_write_length, nil);
|
||||||
if single_write_length <= 0 || e == win32.FALSE {
|
if single_write_length <= 0 || e == win32.FALSE {
|
||||||
err := win32.get_last_error();
|
err := Errno(win32.get_last_error());
|
||||||
return int(total_write), Errno(e);
|
return int(total_write), err;
|
||||||
}
|
}
|
||||||
total_write += i64(single_write_length);
|
total_write += i64(single_write_length);
|
||||||
}
|
}
|
||||||
@@ -148,8 +148,8 @@ read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
|||||||
|
|
||||||
e := win32.read_file(win32.Handle(fd), &data[total_read], to_read, &single_read_length, nil);
|
e := win32.read_file(win32.Handle(fd), &data[total_read], to_read, &single_read_length, nil);
|
||||||
if single_read_length <= 0 || e == win32.FALSE {
|
if single_read_length <= 0 || e == win32.FALSE {
|
||||||
err := win32.get_last_error();
|
err := Errno(win32.get_last_error());
|
||||||
return int(total_read), Errno(e);
|
return int(total_read), err;
|
||||||
}
|
}
|
||||||
total_read += i64(single_read_length);
|
total_read += i64(single_read_length);
|
||||||
}
|
}
|
||||||
@@ -170,8 +170,8 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
|||||||
|
|
||||||
dw_ptr := win32.set_file_pointer(win32.Handle(fd), lo, &hi, w);
|
dw_ptr := win32.set_file_pointer(win32.Handle(fd), lo, &hi, w);
|
||||||
if dw_ptr == win32.INVALID_SET_FILE_POINTER {
|
if dw_ptr == win32.INVALID_SET_FILE_POINTER {
|
||||||
err := win32.get_last_error();
|
err := Errno(win32.get_last_error());
|
||||||
return 0, Errno(err);
|
return 0, err;
|
||||||
}
|
}
|
||||||
return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE;
|
return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -191,7 +191,7 @@ parse_f64 :: proc(s: string) -> f64 {
|
|||||||
|
|
||||||
append_bool :: proc(buf: []u8, b: bool) -> string {
|
append_bool :: proc(buf: []u8, b: bool) -> string {
|
||||||
s := b ? "true" : "false";
|
s := b ? "true" : "false";
|
||||||
append(buf, ..[]u8(s));
|
append(&buf, ..[]u8(s));
|
||||||
return string(buf);
|
return string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8
|
|||||||
} else {
|
} else {
|
||||||
s = "+Inf";
|
s = "+Inf";
|
||||||
}
|
}
|
||||||
append(buf, ..[]u8(s));
|
append(&buf, ..[]u8(s));
|
||||||
return buf;
|
return buf;
|
||||||
|
|
||||||
case 0: // denormalized
|
case 0: // denormalized
|
||||||
@@ -304,29 +304,29 @@ generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8
|
|||||||
format_digits :: proc(buf: []u8, shortest: bool, neg: bool, digs: DecimalSlice, prec: int, fmt: u8) -> []u8 {
|
format_digits :: proc(buf: []u8, shortest: bool, neg: bool, digs: DecimalSlice, prec: int, fmt: u8) -> []u8 {
|
||||||
match fmt {
|
match fmt {
|
||||||
case 'f', 'F':
|
case 'f', 'F':
|
||||||
append(buf, neg ? '-' : '+');
|
append(&buf, neg ? '-' : '+');
|
||||||
|
|
||||||
// integer, padded with zeros when needed
|
// integer, padded with zeros when needed
|
||||||
if digs.decimal_point > 0 {
|
if digs.decimal_point > 0 {
|
||||||
m := min(digs.count, digs.decimal_point);
|
m := min(digs.count, digs.decimal_point);
|
||||||
append(buf, ..digs.digits[0..<m]);
|
append(&buf, ..digs.digits[0..<m]);
|
||||||
for ; m < digs.decimal_point; m++ {
|
for ; m < digs.decimal_point; m++ {
|
||||||
append(buf, '0');
|
append(&buf, '0');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
append(buf, '0');
|
append(&buf, '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// fractional part
|
// fractional part
|
||||||
if prec > 0 {
|
if prec > 0 {
|
||||||
append(buf, '.');
|
append(&buf, '.');
|
||||||
for i in 0..<prec {
|
for i in 0..<prec {
|
||||||
c: u8 = '0';
|
c: u8 = '0';
|
||||||
if j := digs.decimal_point + i; 0 <= j && j < digs.count {
|
if j := digs.decimal_point + i; 0 <= j && j < digs.count {
|
||||||
c = digs.digits[j];
|
c = digs.digits[j];
|
||||||
}
|
}
|
||||||
append(buf, c);
|
append(&buf, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +342,7 @@ format_digits :: proc(buf: []u8, shortest: bool, neg: bool, digs: DecimalSlice,
|
|||||||
}
|
}
|
||||||
|
|
||||||
c := [2]u8{'%', fmt};
|
c := [2]u8{'%', fmt};
|
||||||
append(buf, ..c[..]);
|
append(&buf, ..c[..]);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,7 +492,7 @@ append_bits :: proc(buf: []u8, u: u128, base: int, is_signed: bool, bit_size: in
|
|||||||
i--; a[i] = ' ';
|
i--; a[i] = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
append(buf, ..a[i..]);
|
append(&buf, ..a[i..]);
|
||||||
return string(buf);
|
return string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-3
@@ -207,6 +207,9 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
|||||||
e->kind = Entity_TypeName;
|
e->kind = Entity_TypeName;
|
||||||
|
|
||||||
DeclInfo *d = c->context.decl;
|
DeclInfo *d = c->context.decl;
|
||||||
|
if (d->type_expr != NULL) {
|
||||||
|
error(e->token, "A type declaration cannot have an type parameter");
|
||||||
|
}
|
||||||
d->type_expr = d->init_expr;
|
d->type_expr = d->init_expr;
|
||||||
check_type_decl(c, e, d->type_expr, named_type);
|
check_type_decl(c, e, d->type_expr, named_type);
|
||||||
return;
|
return;
|
||||||
@@ -433,7 +436,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_foreign) {
|
if (is_foreign) {
|
||||||
error(e->token, "A foreign procedures cannot be a polymorphic");
|
error(e->token, "A foreign procedure cannot be a polymorphic");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -443,13 +446,15 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
error(pl->body, "A foreign procedure cannot have a body");
|
error(pl->body, "A foreign procedure cannot have a body");
|
||||||
}
|
}
|
||||||
if (proc_type->Proc.c_vararg) {
|
if (proc_type->Proc.c_vararg) {
|
||||||
error(pl->body, "A procedure with a `#c_vararg` field cannot have a body");
|
error(pl->body, "A procedure with a `#c_vararg` field cannot have a body and must be foreign");
|
||||||
}
|
}
|
||||||
|
|
||||||
d->scope = c->context.scope;
|
d->scope = c->context.scope;
|
||||||
|
|
||||||
GB_ASSERT(pl->body->kind == AstNode_BlockStmt);
|
GB_ASSERT(pl->body->kind == AstNode_BlockStmt);
|
||||||
check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pl->body, pl->tags);
|
if (!pt->is_polymorphic) {
|
||||||
|
check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pl->body, pl->tags);
|
||||||
|
}
|
||||||
} else if (!is_foreign) {
|
} else if (!is_foreign) {
|
||||||
error(e->token, "Only a foreign procedure cannot have a body");
|
error(e->token, "Only a foreign procedure cannot have a body");
|
||||||
}
|
}
|
||||||
|
|||||||
+87
-33
@@ -193,6 +193,11 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
|
|||||||
if (check_representable_as_constant(c, operand->value, dst, NULL)) {
|
if (check_representable_as_constant(c, operand->value, dst, NULL)) {
|
||||||
if (is_type_typed(dst) && src->kind == Type_Basic) {
|
if (is_type_typed(dst) && src->kind == Type_Basic) {
|
||||||
switch (src->Basic.kind) {
|
switch (src->Basic.kind) {
|
||||||
|
case Basic_UntypedRune:
|
||||||
|
if (is_type_integer(dst) || is_type_rune(dst)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Basic_UntypedInteger:
|
case Basic_UntypedInteger:
|
||||||
if (is_type_integer(dst) || is_type_rune(dst)) {
|
if (is_type_integer(dst) || is_type_rune(dst)) {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -214,6 +219,15 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (src->kind == Type_Basic && src->Basic.kind == Basic_UntypedRune) {
|
||||||
|
if (is_type_integer(dst) || is_type_rune(dst)) {
|
||||||
|
if (is_type_typed(type)) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (src->kind == Type_Basic && src->Basic.kind == Basic_UntypedBool) {
|
if (src->kind == Type_Basic && src->Basic.kind == Basic_UntypedBool) {
|
||||||
if (is_type_boolean(dst)) {
|
if (is_type_boolean(dst)) {
|
||||||
if (is_type_typed(type)) {
|
if (is_type_typed(type)) {
|
||||||
@@ -1098,8 +1112,7 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
|
|||||||
}
|
}
|
||||||
case Type_Pointer:
|
case Type_Pointer:
|
||||||
if (source->kind == Type_Pointer) {
|
if (source->kind == Type_Pointer) {
|
||||||
if (compound) return are_types_identical(poly, source);
|
return is_polymorphic_type_assignable(c, poly->Pointer.elem, source->Atomic.elem, true, modify_type);
|
||||||
return check_is_assignable_to(c, &o, poly);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case Type_Atomic:
|
case Type_Atomic:
|
||||||
@@ -3983,10 +3996,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
|
|
||||||
|
|
||||||
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
||||||
if (vari_expand && id != BuiltinProc_append) {
|
// if (vari_expand && id != BuiltinProc_append) {
|
||||||
// error(ce->ellipsis, "Invalid use of `..` with built-in procedure `append`");
|
// error(ce->ellipsis, "Invalid use of `..` with built-in procedure `append`");
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@@ -4268,6 +4281,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
operand->mode = Addressing_NoValue;
|
operand->mode = Addressing_NoValue;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
case BuiltinProc_append: {
|
case BuiltinProc_append: {
|
||||||
// proc append([dynamic]Type, item: ..Type)
|
// proc append([dynamic]Type, item: ..Type)
|
||||||
// proc append([]Type, item: ..Type)
|
// proc append([]Type, item: ..Type)
|
||||||
@@ -4315,6 +4329,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
operand->mode = Addressing_Value;
|
operand->mode = Addressing_Value;
|
||||||
operand->type = t_int;
|
operand->type = t_int;
|
||||||
} break;
|
} break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case BuiltinProc_delete: {
|
case BuiltinProc_delete: {
|
||||||
// proc delete(map[Key]Value, key: Key)
|
// proc delete(map[Key]Value, key: Key)
|
||||||
@@ -5155,6 +5170,7 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, AstNode *call, Entity
|
|||||||
Scope *scope = make_scope(base_entity->scope, a);
|
Scope *scope = make_scope(base_entity->scope, a);
|
||||||
scope->is_proc = true;
|
scope->is_proc = true;
|
||||||
c->context.scope = scope;
|
c->context.scope = scope;
|
||||||
|
c->context.allow_polymorphic_types = true;
|
||||||
|
|
||||||
bool generate_type_again = c->context.no_polymorphic_errors;
|
bool generate_type_again = c->context.no_polymorphic_errors;
|
||||||
|
|
||||||
@@ -5219,6 +5235,7 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, AstNode *call, Entity
|
|||||||
// NOTE(bill): Associate the scope declared above with this procedure declaration's type
|
// NOTE(bill): Associate the scope declared above with this procedure declaration's type
|
||||||
add_scope(c, pl->type, final_proc_type->Proc.scope);
|
add_scope(c, pl->type, final_proc_type->Proc.scope);
|
||||||
final_proc_type->Proc.is_poly_specialized = true;
|
final_proc_type->Proc.is_poly_specialized = true;
|
||||||
|
final_proc_type->Proc.is_polymorphic = true;
|
||||||
|
|
||||||
u64 tags = base_entity->Procedure.tags;
|
u64 tags = base_entity->Procedure.tags;
|
||||||
AstNode *ident = clone_ast_node(a, base_entity->identifier);
|
AstNode *ident = clone_ast_node(a, base_entity->identifier);
|
||||||
@@ -5236,17 +5253,24 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, AstNode *call, Entity
|
|||||||
// NOTE(bill): Set the scope afterwards as this is not real overloading
|
// NOTE(bill): Set the scope afterwards as this is not real overloading
|
||||||
entity->scope = scope->parent;
|
entity->scope = scope->parent;
|
||||||
|
|
||||||
ProcedureInfo proc_info = {};
|
AstFile *file = NULL;
|
||||||
if (success) {
|
{
|
||||||
proc_info.file = c->curr_ast_file;
|
Scope *s = entity->scope;
|
||||||
proc_info.token = token;
|
while (s != NULL && s->file == NULL) {
|
||||||
proc_info.decl = d;
|
s = s->parent;
|
||||||
proc_info.type = final_proc_type;
|
}
|
||||||
proc_info.body = pl->body;
|
file = s->file;
|
||||||
proc_info.tags = tags;
|
|
||||||
proc_info.generated_from_polymorphic = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcedureInfo proc_info = {};
|
||||||
|
proc_info.file = file;
|
||||||
|
proc_info.token = token;
|
||||||
|
proc_info.decl = d;
|
||||||
|
proc_info.type = final_proc_type;
|
||||||
|
proc_info.body = pl->body;
|
||||||
|
proc_info.tags = tags;
|
||||||
|
proc_info.generated_from_polymorphic = true;
|
||||||
|
|
||||||
if (found_gen_procs) {
|
if (found_gen_procs) {
|
||||||
array_add(found_gen_procs, entity);
|
array_add(found_gen_procs, entity);
|
||||||
} else {
|
} else {
|
||||||
@@ -5436,6 +5460,10 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gen_entity != NULL && gen_entity->token.string == "append" && err != CallArgumentError_None) {
|
||||||
|
gb_printf_err("append %s with score %lld %d\n", type_to_string(final_proc_type), score, err);
|
||||||
|
}
|
||||||
|
|
||||||
if (gen_entity != NULL && err == CallArgumentError_None) {
|
if (gen_entity != NULL && err == CallArgumentError_None) {
|
||||||
if (proc_info.decl != NULL) {
|
if (proc_info.decl != NULL) {
|
||||||
// NOTE(bill): Check the newly generated procedure body
|
// NOTE(bill): Check the newly generated procedure body
|
||||||
@@ -5690,11 +5718,13 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
|
|||||||
Entity *p = procs[i];
|
Entity *p = procs[i];
|
||||||
Type *pt = base_type(p->type);
|
Type *pt = base_type(p->type);
|
||||||
if (pt != NULL && is_type_proc(pt)) {
|
if (pt != NULL && is_type_proc(pt)) {
|
||||||
|
CallArgumentError err = CallArgumentError_None;
|
||||||
CallArgumentData data = {};
|
CallArgumentData data = {};
|
||||||
bool prev = c->context.no_polymorphic_errors;
|
CheckerContext prev_context = c->context;
|
||||||
defer (c->context.no_polymorphic_errors = prev);
|
|
||||||
c->context.no_polymorphic_errors = true;
|
c->context.no_polymorphic_errors = true;
|
||||||
CallArgumentError err = call_checker(c, call, pt, p, operands, CallArgumentMode_NoErrors, &data);
|
c->context.allow_polymorphic_types = is_type_polymorphic(pt);
|
||||||
|
err = call_checker(c, call, pt, p, operands, CallArgumentMode_NoErrors, &data);
|
||||||
|
c->context = prev_context;
|
||||||
|
|
||||||
if (err == CallArgumentError_None) {
|
if (err == CallArgumentError_None) {
|
||||||
valids[valid_count].index = i;
|
valids[valid_count].index = i;
|
||||||
@@ -5747,24 +5777,39 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
|
|||||||
}
|
}
|
||||||
result_type = t_invalid;
|
result_type = t_invalid;
|
||||||
} else {
|
} else {
|
||||||
AstNode *expr = operand->expr;
|
AstNode *ident = operand->expr;
|
||||||
while (expr->kind == AstNode_SelectorExpr) {
|
while (ident->kind == AstNode_SelectorExpr) {
|
||||||
expr = expr->SelectorExpr.selector;
|
AstNode *s = ident->SelectorExpr.selector;
|
||||||
|
ident = s;
|
||||||
}
|
}
|
||||||
GB_ASSERT(expr->kind == AstNode_Ident);
|
|
||||||
Entity *e = procs[valids[0].index];
|
Entity *e = procs[valids[0].index];
|
||||||
add_entity_use(c, expr, e);
|
|
||||||
proc_type = e->type;
|
proc_type = e->type;
|
||||||
CallArgumentData data = {};
|
CallArgumentData data = {};
|
||||||
CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
|
CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
|
||||||
if (data.gen_entity != NULL) add_entity_use(c, ce->proc, data.gen_entity);
|
if (data.gen_entity != NULL) {
|
||||||
|
add_entity_use(c, ident, data.gen_entity);
|
||||||
|
} else {
|
||||||
|
add_entity_use(c, ident, e);
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Entity *e = entity_of_ident(&c->info, operand->expr);
|
AstNode *ident = operand->expr;
|
||||||
|
while (ident->kind == AstNode_SelectorExpr) {
|
||||||
|
AstNode *s = ident->SelectorExpr.selector;
|
||||||
|
ident = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity *e = entity_of_ident(&c->info, ident);
|
||||||
CallArgumentData data = {};
|
CallArgumentData data = {};
|
||||||
CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
|
CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
|
||||||
if (data.gen_entity != NULL) add_entity_use(c, ce->proc, data.gen_entity);
|
if (data.gen_entity != NULL) {
|
||||||
|
add_entity_use(c, ident, data.gen_entity);
|
||||||
|
} else {
|
||||||
|
add_entity_use(c, ident, e);
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5908,9 +5953,6 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
|||||||
|
|
||||||
CallArgumentData data = check_call_arguments(c, operand, proc_type, call);
|
CallArgumentData data = check_call_arguments(c, operand, proc_type, call);
|
||||||
Type *result_type = data.result_type;
|
Type *result_type = data.result_type;
|
||||||
if (data.gen_entity != NULL) {
|
|
||||||
add_entity_use(c, ce->proc, data.gen_entity);
|
|
||||||
}
|
|
||||||
gb_zero_item(operand);
|
gb_zero_item(operand);
|
||||||
operand->expr = call;
|
operand->expr = call;
|
||||||
|
|
||||||
@@ -7130,6 +7172,15 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
str = write_expr_to_string(str, be->right);
|
str = write_expr_to_string(str, be->right);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(te, TernaryExpr, node);
|
||||||
|
str = write_expr_to_string(str, te->cond);
|
||||||
|
str = gb_string_appendc(str, " ? ");
|
||||||
|
str = write_expr_to_string(str, te->x);
|
||||||
|
str = gb_string_appendc(str, " : ");
|
||||||
|
str = write_expr_to_string(str, te->y);
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
|
||||||
case_ast_node(pe, ParenExpr, node);
|
case_ast_node(pe, ParenExpr, node);
|
||||||
str = gb_string_appendc(str, "(");
|
str = gb_string_appendc(str, "(");
|
||||||
str = write_expr_to_string(str, pe->expr);
|
str = write_expr_to_string(str, pe->expr);
|
||||||
@@ -7171,6 +7222,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
|
|
||||||
case_ast_node(e, Ellipsis, node);
|
case_ast_node(e, Ellipsis, node);
|
||||||
str = gb_string_appendc(str, "..");
|
str = gb_string_appendc(str, "..");
|
||||||
|
str = write_expr_to_string(str, e->expr);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(fv, FieldValue, node);
|
case_ast_node(fv, FieldValue, node);
|
||||||
@@ -7184,6 +7236,12 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
str = write_expr_to_string(str, ht->type);
|
str = write_expr_to_string(str, ht->type);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|
||||||
|
case_ast_node(pt, PolyType, node);
|
||||||
|
str = gb_string_appendc(str, "$");
|
||||||
|
str = write_expr_to_string(str, pt->type);
|
||||||
|
case_end;
|
||||||
|
|
||||||
case_ast_node(pt, PointerType, node);
|
case_ast_node(pt, PointerType, node);
|
||||||
str = gb_string_appendc(str, "^");
|
str = gb_string_appendc(str, "^");
|
||||||
str = write_expr_to_string(str, pt->type);
|
str = write_expr_to_string(str, pt->type);
|
||||||
@@ -7203,7 +7261,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(at, DynamicArrayType, node);
|
case_ast_node(at, DynamicArrayType, node);
|
||||||
str = gb_string_appendc(str, "[..]");
|
str = gb_string_appendc(str, "[dynamic]");
|
||||||
str = write_expr_to_string(str, at->elem);
|
str = write_expr_to_string(str, at->elem);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
@@ -7235,9 +7293,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
if (f->names.count > 0) {
|
if (f->names.count > 0) {
|
||||||
str = gb_string_appendc(str, ": ");
|
str = gb_string_appendc(str, ": ");
|
||||||
}
|
}
|
||||||
if (f->flags&FieldFlag_ellipsis) {
|
|
||||||
str = gb_string_appendc(str, "..");
|
|
||||||
}
|
|
||||||
str = write_expr_to_string(str, f->type);
|
str = write_expr_to_string(str, f->type);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
@@ -7261,7 +7316,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for_array(i, f->list) {
|
for_array(i, f->list) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
str = gb_string_appendc(str, ", ");
|
str = gb_string_appendc(str, ", ");
|
||||||
|
|||||||
+10
-10
@@ -33,7 +33,7 @@ enum BuiltinProcId {
|
|||||||
|
|
||||||
BuiltinProc_reserve,
|
BuiltinProc_reserve,
|
||||||
BuiltinProc_clear,
|
BuiltinProc_clear,
|
||||||
BuiltinProc_append,
|
// BuiltinProc_append,
|
||||||
BuiltinProc_delete,
|
BuiltinProc_delete,
|
||||||
|
|
||||||
BuiltinProc_size_of,
|
BuiltinProc_size_of,
|
||||||
@@ -85,7 +85,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
|||||||
|
|
||||||
{STR_LIT("reserve"), 2, false, Expr_Stmt},
|
{STR_LIT("reserve"), 2, false, Expr_Stmt},
|
||||||
{STR_LIT("clear"), 1, false, Expr_Stmt},
|
{STR_LIT("clear"), 1, false, Expr_Stmt},
|
||||||
{STR_LIT("append"), 1, true, Expr_Expr},
|
// {STR_LIT("append"), 1, true, Expr_Expr},
|
||||||
{STR_LIT("delete"), 2, false, Expr_Stmt},
|
{STR_LIT("delete"), 2, false, Expr_Stmt},
|
||||||
|
|
||||||
{STR_LIT("size_of"), 1, false, Expr_Expr},
|
{STR_LIT("size_of"), 1, false, Expr_Expr},
|
||||||
@@ -591,11 +591,9 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev != NULL &&
|
if (prev != NULL && entity->kind == Entity_Procedure) {
|
||||||
entity->kind == Entity_Procedure) {
|
// if (s->is_global) return prev;
|
||||||
if (s->is_global) {
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
multi_map_insert(&s->elements, key, entity);
|
multi_map_insert(&s->elements, key, entity);
|
||||||
} else {
|
} else {
|
||||||
map_set(&s->elements, key, entity);
|
map_set(&s->elements, key, entity);
|
||||||
@@ -1709,6 +1707,9 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
|||||||
|
|
||||||
if (is_ast_node_type(init)) {
|
if (is_ast_node_type(init)) {
|
||||||
e = make_entity_type_name(c->allocator, d->scope, name->Ident.token, NULL);
|
e = make_entity_type_name(c->allocator, d->scope, name->Ident.token, NULL);
|
||||||
|
if (vd->type != NULL) {
|
||||||
|
error(name, "A type declaration cannot have an type parameter");
|
||||||
|
}
|
||||||
d->type_expr = init;
|
d->type_expr = init;
|
||||||
d->init_expr = init;
|
d->init_expr = init;
|
||||||
} else if (init->kind == AstNode_ProcLit) {
|
} else if (init->kind == AstNode_ProcLit) {
|
||||||
@@ -2285,10 +2286,9 @@ void check_parsed_files(Checker *c) {
|
|||||||
defer (c->context = prev_context);
|
defer (c->context = prev_context);
|
||||||
|
|
||||||
TypeProc *pt = &pi->type->Proc;
|
TypeProc *pt = &pi->type->Proc;
|
||||||
|
String name = pi->token.string;
|
||||||
if (pt->is_polymorphic) {
|
if (pt->is_polymorphic) {
|
||||||
if (pi->decl->gen_proc_type == NULL) {
|
GB_ASSERT_MSG(pt->is_poly_specialized, "%.*s", LIT(name));
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add_curr_ast_file(c, pi->file);
|
add_curr_ast_file(c, pi->file);
|
||||||
|
|||||||
+2
-3
@@ -4059,6 +4059,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
return NULL;
|
return NULL;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
case BuiltinProc_append: {
|
case BuiltinProc_append: {
|
||||||
ir_emit_comment(proc, str_lit("append"));
|
ir_emit_comment(proc, str_lit("append"));
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
@@ -4167,6 +4168,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
}
|
}
|
||||||
return ir_emit_global_call(proc, "__dynamic_array_append", daa_args, 5);
|
return ir_emit_global_call(proc, "__dynamic_array_append", daa_args, 5);
|
||||||
} break;
|
} break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case BuiltinProc_delete: {
|
case BuiltinProc_delete: {
|
||||||
ir_emit_comment(proc, str_lit("delete"));
|
ir_emit_comment(proc, str_lit("delete"));
|
||||||
@@ -7422,9 +7424,6 @@ void ir_gen_tree(irGen *s) {
|
|||||||
}
|
}
|
||||||
} else if (check_is_entity_overloaded(e)) {
|
} else if (check_is_entity_overloaded(e)) {
|
||||||
name = ir_mangle_name(s, e->token.pos.file, e);
|
name = ir_mangle_name(s, e->token.pos.file, e);
|
||||||
|
|
||||||
gb_printf_err("%.*s|%.*s :: %s\n", LIT(original_name), LIT(name), type_to_string(e->type));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
map_set(&m->entity_names, hash_entity(e), name);
|
map_set(&m->entity_names, hash_entity(e), name);
|
||||||
|
|||||||
+1
-1
@@ -664,7 +664,7 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
|
|||||||
n->RunExpr.expr = clone_ast_node(a, n->RunExpr.expr);
|
n->RunExpr.expr = clone_ast_node(a, n->RunExpr.expr);
|
||||||
break;
|
break;
|
||||||
case AstNode_UnaryExpr:
|
case AstNode_UnaryExpr:
|
||||||
n->RunExpr.expr = clone_ast_node(a, n->RunExpr.expr);
|
n->UnaryExpr.expr = clone_ast_node(a, n->UnaryExpr.expr);
|
||||||
break;
|
break;
|
||||||
case AstNode_BinaryExpr:
|
case AstNode_BinaryExpr:
|
||||||
n->BinaryExpr.left = clone_ast_node(a, n->BinaryExpr.left);
|
n->BinaryExpr.left = clone_ast_node(a, n->BinaryExpr.left);
|
||||||
|
|||||||
+1
-1
@@ -2445,7 +2445,7 @@ gbString write_type_to_string(gbString str, Type *type) {
|
|||||||
if (var->flags&EntityFlag_Ellipsis) {
|
if (var->flags&EntityFlag_Ellipsis) {
|
||||||
Type *slice = base_type(var->type);
|
Type *slice = base_type(var->type);
|
||||||
str = gb_string_appendc(str, "..");
|
str = gb_string_appendc(str, "..");
|
||||||
GB_ASSERT(is_type_slice(var->type));
|
GB_ASSERT(var->type->kind == Type_Slice);
|
||||||
str = write_type_to_string(str, slice->Slice.elem);
|
str = write_type_to_string(str, slice->Slice.elem);
|
||||||
} else {
|
} else {
|
||||||
str = write_type_to_string(str, var->type);
|
str = write_type_to_string(str, var->type);
|
||||||
|
|||||||
Reference in New Issue
Block a user