mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 08:08:50 +00:00
Add hidden __tag for union variables.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#import "fmt.odin";
|
#import "fmt.odin";
|
||||||
|
#import "os.odin";
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
immutable program := "+ + * - /";
|
immutable program := "+ + * - /";
|
||||||
|
|||||||
+2
-1
@@ -194,7 +194,6 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
fi := Fmt_Info{buf = buf};
|
fi := Fmt_Info{buf = buf};
|
||||||
fmt_int(&fi, u64(8*info.size), false, 64, 'd');
|
fmt_int(&fi, u64(8*info.size), false, 64, 'd');
|
||||||
}
|
}
|
||||||
|
|
||||||
case Float:
|
case Float:
|
||||||
match info.size {
|
match info.size {
|
||||||
case 4: write_string(buf, "f32");
|
case 4: write_string(buf, "f32");
|
||||||
@@ -212,6 +211,8 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
}
|
}
|
||||||
case String: write_string(buf, "string");
|
case String: write_string(buf, "string");
|
||||||
case Boolean: write_string(buf, "bool");
|
case Boolean: write_string(buf, "bool");
|
||||||
|
case Any:
|
||||||
|
write_string(buf, "any");
|
||||||
case Atomic:
|
case Atomic:
|
||||||
write_string(buf, "atomic ");
|
write_string(buf, "atomic ");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
|
|||||||
+36
-2
@@ -1,3 +1,37 @@
|
|||||||
#load "os_windows.odin" when ODIN_OS == "windows";
|
#load "os_windows.odin" when ODIN_OS == "windows";
|
||||||
#load "os_x.odin" when ODIN_OS == "osx";
|
#load "os_x.odin" when ODIN_OS == "osx";
|
||||||
#load "os_linux.odin" when ODIN_OS == "linux";
|
#load "os_linux.odin" when ODIN_OS == "linux";
|
||||||
|
|
||||||
|
write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
|
||||||
|
return write(fd, []byte(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
||||||
|
fd, err := open(name, O_RDONLY, 0);
|
||||||
|
if err != ERROR_NONE {
|
||||||
|
return nil, false;
|
||||||
|
}
|
||||||
|
defer close(fd);
|
||||||
|
|
||||||
|
length: i64;
|
||||||
|
if length, err = file_size(fd); err != ERROR_NONE {
|
||||||
|
return nil, false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if length == 0 {
|
||||||
|
return nil, true;
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make([]byte, length);
|
||||||
|
if data == nil {
|
||||||
|
return nil, false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_read, read_err := read(fd, data);
|
||||||
|
if read_err != ERROR_NONE {
|
||||||
|
free(data);
|
||||||
|
return nil, false;
|
||||||
|
}
|
||||||
|
return data[0..<bytes_read], true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+40
-31
@@ -179,6 +179,13 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
|||||||
return res, 0;
|
return res, 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file_size :: proc(fd: Handle) -> (i64, bool) {
|
||||||
|
prev, _ := seek(fd, 0, SEEK_CUR);
|
||||||
|
size, err := seek(fd, 0, SEEK_END);
|
||||||
|
seek(fd, prev, SEEK_SET);
|
||||||
|
return size, err != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE(bill): Uses startup to initialize it
|
// NOTE(bill): Uses startup to initialize it
|
||||||
stdin: Handle = 0;
|
stdin: Handle = 0;
|
||||||
@@ -204,44 +211,46 @@ access :: proc(path: string, mask: int) -> bool #inline {
|
|||||||
return _unix_access(cstr, mask) == 0;
|
return _unix_access(cstr, mask) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
|
||||||
fd: Handle;
|
|
||||||
err: Errno;
|
|
||||||
size: i64;
|
|
||||||
|
|
||||||
fd, err = open_simple(name, O_RDONLY);
|
|
||||||
if(err != 0) {
|
|
||||||
fmt.println("Failed to open file.");
|
|
||||||
return nil, false;
|
|
||||||
}
|
|
||||||
defer close(fd);
|
|
||||||
|
|
||||||
// We have a file
|
// read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
||||||
size, err = seek(fd, 0, SEEK_END);
|
// fd: Handle;
|
||||||
if(err != 0) {
|
// err: Errno;
|
||||||
fmt.println("Failed to seek to end of file.");
|
// size: i64;
|
||||||
return nil, false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = seek(fd, 0, SEEK_SET);
|
// fd, err = open_simple(name, O_RDONLY);
|
||||||
if(err != 0) {
|
// if(err != 0) {
|
||||||
fmt.println("Failed to seek to beginning of file.");
|
// fmt.println("Failed to open file.");
|
||||||
return nil, false;
|
// return nil, false;
|
||||||
}
|
// }
|
||||||
|
// defer close(fd);
|
||||||
|
|
||||||
// We have a file size!
|
// // We have a file
|
||||||
|
// size, err = seek(fd, 0, SEEK_END);
|
||||||
|
// if(err != 0) {
|
||||||
|
// fmt.println("Failed to seek to end of file.");
|
||||||
|
// return nil, false;
|
||||||
|
// }
|
||||||
|
|
||||||
data := make([]u8, size+1);
|
// _, err = seek(fd, 0, SEEK_SET);
|
||||||
if data == nil {
|
// if(err != 0) {
|
||||||
fmt.println("Failed to allocate file buffer.");
|
// fmt.println("Failed to seek to beginning of file.");
|
||||||
return nil, false;
|
// return nil, false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
read(fd, data);
|
// // We have a file size!
|
||||||
data[size] = 0;
|
|
||||||
|
|
||||||
return data, true;
|
// data := make([]u8, size+1);
|
||||||
}
|
// if data == nil {
|
||||||
|
// fmt.println("Failed to allocate file buffer.");
|
||||||
|
// return nil, false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// read(fd, data);
|
||||||
|
// data[size] = 0;
|
||||||
|
|
||||||
|
// return data, true;
|
||||||
|
// }
|
||||||
|
|
||||||
heap_alloc :: proc(size: int) -> rawptr {
|
heap_alloc :: proc(size: int) -> rawptr {
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
|
|||||||
+53
-65
@@ -109,33 +109,61 @@ close :: proc(fd: Handle) {
|
|||||||
win32.CloseHandle(win32.Handle(fd));
|
win32.CloseHandle(win32.Handle(fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
|
|
||||||
return write(fd, []byte(str));
|
|
||||||
}
|
|
||||||
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return 0, ERROR_NONE;
|
return 0, ERROR_NONE;
|
||||||
}
|
}
|
||||||
bytes_written: i32;
|
single_write_length: i32;
|
||||||
e := win32.WriteFile(win32.Handle(fd), &data[0], i32(len(data)), &bytes_written, nil);
|
total_write: i64;
|
||||||
if e == win32.FALSE {
|
length := i64(len(data));
|
||||||
err := win32.GetLastError();
|
|
||||||
return 0, Errno(err);
|
for total_write < length {
|
||||||
|
remaining := length - total_write;
|
||||||
|
to_read: i32;
|
||||||
|
MAX :: 1<<31-1;
|
||||||
|
if remaining <= MAX {
|
||||||
|
to_read = i32(remaining);
|
||||||
|
} else {
|
||||||
|
to_read = MAX;
|
||||||
|
}
|
||||||
|
e := win32.WriteFile(win32.Handle(fd), &data[total_write], to_read, &single_write_length, nil);
|
||||||
|
if single_write_length <= 0 || e == win32.FALSE {
|
||||||
|
err := win32.GetLastError();
|
||||||
|
return int(total_write), Errno(e);
|
||||||
|
}
|
||||||
|
total_write += i64(single_write_length);
|
||||||
}
|
}
|
||||||
return int(bytes_written), ERROR_NONE;
|
return int(total_write), ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return 0, ERROR_NONE;
|
return 0, ERROR_NONE;
|
||||||
}
|
}
|
||||||
bytes_read: i32;
|
|
||||||
e := win32.ReadFile(win32.Handle(fd), &data[0], u32(len(data)), &bytes_read, nil);
|
single_read_length: i32;
|
||||||
if e == win32.FALSE {
|
total_read: i64;
|
||||||
err := win32.GetLastError();
|
length := i64(len(data));
|
||||||
return 0, Errno(err);
|
|
||||||
|
for total_read < length {
|
||||||
|
remaining := length - total_read;
|
||||||
|
to_read: u32;
|
||||||
|
MAX :: 1<<32-1;
|
||||||
|
if remaining <= MAX {
|
||||||
|
to_read = u32(remaining);
|
||||||
|
} else {
|
||||||
|
to_read = MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
e := win32.ReadFile(win32.Handle(fd), &data[total_read], to_read, &single_read_length, nil);
|
||||||
|
if single_read_length <= 0 || e == win32.FALSE {
|
||||||
|
err := win32.GetLastError();
|
||||||
|
return int(total_read), Errno(e);
|
||||||
|
}
|
||||||
|
total_read += i64(single_read_length);
|
||||||
}
|
}
|
||||||
return int(bytes_read), ERROR_NONE;
|
return int(total_read), ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||||
@@ -159,6 +187,16 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
|||||||
return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE;
|
return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file_size :: proc(fd: Handle) -> (i64, Errno) {
|
||||||
|
length: i64;
|
||||||
|
err: Errno;
|
||||||
|
if win32.GetFileSizeEx(win32.Handle(fd), &length) == 0 {
|
||||||
|
err = Errno(win32.GetLastError());
|
||||||
|
}
|
||||||
|
return length, err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE(bill): Uses startup to initialize it
|
// NOTE(bill): Uses startup to initialize it
|
||||||
stdin := get_std_handle(win32.STD_INPUT_HANDLE);
|
stdin := get_std_handle(win32.STD_INPUT_HANDLE);
|
||||||
@@ -204,56 +242,6 @@ last_write_time_by_name :: proc(name: string) -> File_Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
|
||||||
buf: [300]byte;
|
|
||||||
copy(buf[..], []byte(name));
|
|
||||||
|
|
||||||
fd, err := open(name, O_RDONLY, 0);
|
|
||||||
if err != ERROR_NONE {
|
|
||||||
return nil, false;
|
|
||||||
}
|
|
||||||
defer close(fd);
|
|
||||||
|
|
||||||
length: i64;
|
|
||||||
if ok := win32.GetFileSizeEx(win32.Handle(fd), &length) != 0; !ok {
|
|
||||||
return nil, false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if length == 0 {
|
|
||||||
return nil, true;
|
|
||||||
}
|
|
||||||
|
|
||||||
data := make([]byte, length);
|
|
||||||
if data == nil {
|
|
||||||
return nil, false;
|
|
||||||
}
|
|
||||||
|
|
||||||
single_read_length: i32;
|
|
||||||
total_read: i64;
|
|
||||||
|
|
||||||
for total_read < length {
|
|
||||||
remaining := length - total_read;
|
|
||||||
to_read: u32;
|
|
||||||
MAX :: 1<<32-1;
|
|
||||||
if remaining <= MAX {
|
|
||||||
to_read = u32(remaining);
|
|
||||||
} else {
|
|
||||||
to_read = MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
win32.ReadFile(win32.Handle(fd), &data[total_read], to_read, &single_read_length, nil);
|
|
||||||
if single_read_length <= 0 {
|
|
||||||
free(data);
|
|
||||||
return nil, false;
|
|
||||||
}
|
|
||||||
|
|
||||||
total_read += i64(single_read_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
heap_alloc :: proc(size: int) -> rawptr {
|
heap_alloc :: proc(size: int) -> rawptr {
|
||||||
return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, size);
|
return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, size);
|
||||||
|
|||||||
+37
-29
@@ -196,6 +196,14 @@ seek :: proc(fd: Handle, offset: AddressSize, whence: int) -> (AddressSize, Errn
|
|||||||
return final_offset, 0;
|
return final_offset, 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file_size :: proc(fd: Handle) -> (i64, bool) {
|
||||||
|
prev, _ := seek(fd, 0, SEEK_CUR);
|
||||||
|
size, err := seek(fd, 0, SEEK_END);
|
||||||
|
seek(fd, prev, SEEK_SET);
|
||||||
|
return size, err != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE(bill): Uses startup to initialize it
|
// NOTE(bill): Uses startup to initialize it
|
||||||
stdin: Handle = 0; // get_std_handle(win32.STD_INPUT_HANDLE);
|
stdin: Handle = 0; // get_std_handle(win32.STD_INPUT_HANDLE);
|
||||||
@@ -221,43 +229,43 @@ access :: proc(path: string, mask: int) -> bool #inline {
|
|||||||
return unix_access(cstr, mask) == 0;
|
return unix_access(cstr, mask) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
// read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
||||||
|
|
||||||
handle, err := open_simple(name, O_RDONLY);
|
// handle, err := open_simple(name, O_RDONLY);
|
||||||
if(err != 0) {
|
// if(err != 0) {
|
||||||
fmt.println("Failed to open file.");
|
// fmt.println("Failed to open file.");
|
||||||
return nil, false;
|
// return nil, false;
|
||||||
}
|
// }
|
||||||
defer(close(handle));
|
// defer(close(handle));
|
||||||
|
|
||||||
// We have a file!
|
// // We have a file!
|
||||||
|
|
||||||
size: AddressSize;
|
// size: AddressSize;
|
||||||
size, err = seek(handle, 0, SEEK_END);
|
// size, err = seek(handle, 0, SEEK_END);
|
||||||
if(err != 0) {
|
// if(err != 0) {
|
||||||
fmt.println("Failed to seek to end of file.");
|
// fmt.println("Failed to seek to end of file.");
|
||||||
return nil, false;
|
// return nil, false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
_, err = seek(handle, 0, SEEK_SET);
|
// _, err = seek(handle, 0, SEEK_SET);
|
||||||
if(err != 0) {
|
// if(err != 0) {
|
||||||
fmt.println("Failed to seek to beginning of file.");
|
// fmt.println("Failed to seek to beginning of file.");
|
||||||
return nil, false;
|
// return nil, false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// We have a file size!
|
// // We have a file size!
|
||||||
|
|
||||||
data := make([]u8, size+1);
|
// data := make([]u8, size+1);
|
||||||
if data == nil {
|
// if data == nil {
|
||||||
fmt.println("Failed to allocate file buffer.");
|
// fmt.println("Failed to allocate file buffer.");
|
||||||
return nil, false;
|
// return nil, false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
read(handle, data);
|
// read(handle, data);
|
||||||
data[size] = 0;
|
// data[size] = 0;
|
||||||
|
|
||||||
return data, true;
|
// return data, true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
heap_alloc :: proc(size: int) -> rawptr #inline {
|
heap_alloc :: proc(size: int) -> rawptr #inline {
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
|
|||||||
@@ -422,6 +422,8 @@ isize check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
e->identifier = name;
|
e->identifier = name;
|
||||||
if (str_eq(name_token.string, str_lit("_"))) {
|
if (str_eq(name_token.string, str_lit("_"))) {
|
||||||
fields[field_index++] = e;
|
fields[field_index++] = e;
|
||||||
|
} else if (str_eq(name_token.string, str_lit("__tag"))) {
|
||||||
|
error_node(name, "`__tag` is a reserved identifier for fields");
|
||||||
} else {
|
} else {
|
||||||
HashKey key = hash_string(name_token.string);
|
HashKey key = hash_string(name_token.string);
|
||||||
Entity **found = map_entity_get(&entity_map, key);
|
Entity **found = map_entity_get(&entity_map, key);
|
||||||
@@ -660,6 +662,10 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
|
|||||||
union_type->Record.field_count = field_count;
|
union_type->Record.field_count = field_count;
|
||||||
union_type->Record.are_offsets_set = false;
|
union_type->Record.are_offsets_set = false;
|
||||||
union_type->Record.is_ordered = true;
|
union_type->Record.is_ordered = true;
|
||||||
|
{
|
||||||
|
Entity *__tag = make_entity_field(c->allocator, NULL, make_token_ident(str_lit("__tag")), t_int, false, -1);
|
||||||
|
union_type->Record.union__tag = __tag;
|
||||||
|
}
|
||||||
|
|
||||||
for_array(i, ut->variants) {
|
for_array(i, ut->variants) {
|
||||||
AstNode *variant = ut->variants.e[i];
|
AstNode *variant = ut->variants.e[i];
|
||||||
|
|||||||
@@ -2244,8 +2244,13 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
|
|||||||
} else if (is_type_union(t)) {
|
} else if (is_type_union(t)) {
|
||||||
type_set_offsets(a, t);
|
type_set_offsets(a, t);
|
||||||
GB_ASSERT(t->Record.field_count > 0);
|
GB_ASSERT(t->Record.field_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
if (index == -1) {
|
||||||
result_type = make_type_pointer(a, t->Record.fields[index]->type);
|
index = t->Record.field_count+1;
|
||||||
|
result_type = t_int_ptr;
|
||||||
|
} else {
|
||||||
|
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||||
|
result_type = make_type_pointer(a, t->Record.fields[index]->type);
|
||||||
|
}
|
||||||
} else if (is_type_tuple(t)) {
|
} else if (is_type_tuple(t)) {
|
||||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
||||||
@@ -2316,8 +2321,12 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
|||||||
result_type = t->Record.fields[index]->type;
|
result_type = t->Record.fields[index]->type;
|
||||||
} else if (is_type_union(t)) {
|
} else if (is_type_union(t)) {
|
||||||
type_set_offsets(a, t);
|
type_set_offsets(a, t);
|
||||||
GB_ASSERT(t->Record.field_count > 0);
|
if (index == -1) {
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
index = t->Record.field_count+1;
|
||||||
|
result_type = t_int_ptr;
|
||||||
|
} else {
|
||||||
|
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||||
|
}
|
||||||
result_type = t->Record.fields[index]->type;
|
result_type = t->Record.fields[index]->type;
|
||||||
} else if (is_type_tuple(t)) {
|
} else if (is_type_tuple(t)) {
|
||||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||||
@@ -2394,7 +2403,11 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, irValue *e, Selection sel) {
|
|||||||
type = type->Record.fields[index]->type;
|
type = type->Record.fields[index]->type;
|
||||||
e = ir_emit_conv(proc, e, make_type_pointer(proc->module->allocator, type));
|
e = ir_emit_conv(proc, e, make_type_pointer(proc->module->allocator, type));
|
||||||
} else if (type->kind == Type_Record) {
|
} else if (type->kind == Type_Record) {
|
||||||
type = type->Record.fields[index]->type;
|
if (index == -1) {
|
||||||
|
type = t_int;
|
||||||
|
} else {
|
||||||
|
type = type->Record.fields[index]->type;
|
||||||
|
}
|
||||||
e = ir_emit_struct_ep(proc, e, index);
|
e = ir_emit_struct_ep(proc, e, index);
|
||||||
} else if (type->kind == Type_Tuple) {
|
} else if (type->kind == Type_Tuple) {
|
||||||
type = type->Tuple.variables[index]->type;
|
type = type->Tuple.variables[index]->type;
|
||||||
|
|||||||
+1
-1
@@ -1844,7 +1844,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
return ast_proc_lit(f, type, NULL, tags, foreign_library, foreign_name, link_name);
|
return ast_proc_lit(f, type, NULL, tags, foreign_library, foreign_name, link_name);
|
||||||
}
|
}
|
||||||
if (tags != 0) {
|
if (tags != 0) {
|
||||||
syntax_error(token, "A procedure type cannot have tags");
|
// syntax_error(token, "A procedure type cannot have tags");
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
|
|||||||
+11
@@ -92,6 +92,8 @@ typedef struct TypeRecord {
|
|||||||
// Entity_TypeName - union
|
// Entity_TypeName - union
|
||||||
Entity **variants;
|
Entity **variants;
|
||||||
i32 variant_count;
|
i32 variant_count;
|
||||||
|
Entity * union__tag;
|
||||||
|
|
||||||
|
|
||||||
i64 * offsets;
|
i64 * offsets;
|
||||||
bool are_offsets_set;
|
bool are_offsets_set;
|
||||||
@@ -1415,6 +1417,15 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
|||||||
sel.index.count = prev_count;
|
sel.index.count = prev_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (type->Record.kind == TypeRecord_Union) {
|
||||||
|
if (str_eq(field_name, str_lit("__tag"))) {
|
||||||
|
Entity *e = type->Record.union__tag;
|
||||||
|
GB_ASSERT(e != NULL);
|
||||||
|
selection_add_index(&sel, -1); // HACK(bill): Leaky memory
|
||||||
|
sel.entity = e;
|
||||||
|
return sel;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sel;
|
return sel;
|
||||||
|
|||||||
Reference in New Issue
Block a user