mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-18 20:40:28 +00:00
match to switch; Optional semicolons after "import" statements
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
#shared_global_scope;
|
||||
#shared_global_scope
|
||||
|
||||
import "core:os.odin";
|
||||
import "core:fmt.odin"; // TODO(bill): Remove the need for `fmt` here
|
||||
import "core:utf8.odin";
|
||||
import "core:raw.odin";
|
||||
import "core:os.odin"
|
||||
import "core:fmt.odin" // TODO(bill): Remove the need for `fmt` here
|
||||
import "core:utf8.odin"
|
||||
import "core:raw.odin"
|
||||
|
||||
// Naming Conventions:
|
||||
// In general, Ada_Case for types and snake_case for values
|
||||
@@ -43,7 +43,6 @@ Type_Info_Enum_Value :: union {
|
||||
f32, f64,
|
||||
};
|
||||
|
||||
|
||||
// Variant Types
|
||||
Type_Info_Named :: struct #ordered {name: string, base: ^Type_Info};
|
||||
Type_Info_Integer :: struct #ordered {signed: bool};
|
||||
@@ -106,7 +105,6 @@ Type_Info_Bit_Field :: struct #ordered {
|
||||
|
||||
|
||||
Type_Info :: struct #ordered {
|
||||
// Fields
|
||||
size: int,
|
||||
align: int,
|
||||
|
||||
@@ -217,7 +215,7 @@ type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil do return nil;
|
||||
|
||||
base := info;
|
||||
match i in base.variant {
|
||||
switch i in base.variant {
|
||||
case Type_Info_Named: base = i.base;
|
||||
}
|
||||
return base;
|
||||
@@ -228,7 +226,7 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil do return nil;
|
||||
|
||||
base := info;
|
||||
match i in base.variant {
|
||||
switch i in base.variant {
|
||||
case Type_Info_Named: base = i.base;
|
||||
case Type_Info_Enum: base = i.base;
|
||||
}
|
||||
@@ -444,9 +442,9 @@ __get_map_header :: proc(m: ^$T/map[$K]$V) -> __Map_Header #cc_contextless {
|
||||
__get_map_key :: proc(key: $K) -> __Map_Key #cc_contextless {
|
||||
map_key: __Map_Key;
|
||||
ti := type_info_base_without_enum(type_info_of(K));
|
||||
match _ in ti.variant {
|
||||
switch _ in ti.variant {
|
||||
case Type_Info_Integer:
|
||||
match 8*size_of(key) {
|
||||
switch 8*size_of(key) {
|
||||
case 8: map_key.hash = u128(( ^u8)(&key)^);
|
||||
case 16: map_key.hash = u128(( ^u16)(&key)^);
|
||||
case 32: map_key.hash = u128(( ^u32)(&key)^);
|
||||
@@ -459,7 +457,7 @@ __get_map_key :: proc(key: $K) -> __Map_Key #cc_contextless {
|
||||
case Type_Info_Pointer:
|
||||
map_key.hash = u128(uint((^rawptr)(&key)^));
|
||||
case Type_Info_Float:
|
||||
match 8*size_of(key) {
|
||||
switch 8*size_of(key) {
|
||||
case 32: map_key.hash = u128((^u32)(&key)^);
|
||||
case 64: map_key.hash = u128((^u64)(&key)^);
|
||||
case: panic("Unhandled float size");
|
||||
@@ -575,7 +573,7 @@ default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
||||
using Allocator_Mode;
|
||||
|
||||
match mode {
|
||||
switch mode {
|
||||
case Alloc:
|
||||
return os.heap_alloc(size);
|
||||
|
||||
@@ -626,7 +624,7 @@ panic :: proc(message := "", using location := #caller_location) #cc_contextless
|
||||
|
||||
|
||||
__string_eq :: proc(a, b: string) -> bool #cc_contextless {
|
||||
match {
|
||||
switch {
|
||||
case len(a) != len(b): return false;
|
||||
case len(a) == 0: return true;
|
||||
case &a[0] == &b[0]: return true;
|
||||
@@ -731,7 +729,7 @@ __mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #cc_con
|
||||
|
||||
__mem_compare :: proc(a, b: ^u8, n: int) -> int #cc_contextless {
|
||||
for i in 0..n {
|
||||
match {
|
||||
switch {
|
||||
case (a+i)^ < (b+i)^: return -1;
|
||||
case (a+i)^ > (b+i)^: return +1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#shared_global_scope;
|
||||
#shared_global_scope
|
||||
|
||||
__multi3 :: proc(a, b: u128) -> u128 #cc_c #link_name "__multi3" {
|
||||
bits_in_dword_2 :: size_of(i64) * 4;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Inline vs external file?
|
||||
|
||||
when ODIN_OS == "windows" {
|
||||
import win32 "core:sys/windows.odin";
|
||||
import win32 "core:sys/windows.odin"
|
||||
}
|
||||
_ :: compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ shift :: proc(a: ^Decimal, k: int) {
|
||||
uint_size :: 8*size_of(uint);
|
||||
max_shift :: uint_size-4;
|
||||
|
||||
match {
|
||||
switch {
|
||||
case a.count == 0:
|
||||
// no need to update
|
||||
case k > 0:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import "core:os.odin";
|
||||
import "core:mem.odin";
|
||||
import "core:utf8.odin";
|
||||
import "core:types.odin";
|
||||
import "core:strconv.odin";
|
||||
import "core:raw.odin";
|
||||
import "core:os.odin"
|
||||
import "core:mem.odin"
|
||||
import "core:utf8.odin"
|
||||
import "core:types.odin"
|
||||
import "core:strconv.odin"
|
||||
import "core:raw.odin"
|
||||
|
||||
|
||||
_BUFFER_SIZE :: 1<<12;
|
||||
@@ -36,14 +36,14 @@ Fmt_Info :: struct {
|
||||
|
||||
|
||||
string_buffer_data :: proc(buf: ^String_Buffer) -> []u8 {
|
||||
match b in buf {
|
||||
switch b in buf {
|
||||
case []u8: return b[..];
|
||||
case [dynamic]u8: return b[..];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
string_buffer_data :: proc(buf: String_Buffer) -> []u8 {
|
||||
match b in buf {
|
||||
switch b in buf {
|
||||
case []u8: return b[..];
|
||||
case [dynamic]u8: return b[..];
|
||||
}
|
||||
@@ -58,13 +58,13 @@ write_string :: proc(buf: ^String_Buffer, s: string) {
|
||||
write_bytes(buf, cast([]u8)s);
|
||||
}
|
||||
write_bytes :: proc(buf: ^String_Buffer, data: []u8) {
|
||||
match b in buf {
|
||||
switch b in buf {
|
||||
case []u8: append(b, ...data);
|
||||
case [dynamic]u8: append(b, ...data);
|
||||
}
|
||||
}
|
||||
write_byte :: proc(buf: ^String_Buffer, data: u8) {
|
||||
match b in buf {
|
||||
switch b in buf {
|
||||
case []u8: append(b, data);
|
||||
case [dynamic]u8: append(b, data);
|
||||
}
|
||||
@@ -179,11 +179,11 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
||||
return;
|
||||
}
|
||||
|
||||
match info in ti.variant {
|
||||
switch info in ti.variant {
|
||||
case Type_Info_Named:
|
||||
write_string(buf, info.name);
|
||||
case Type_Info_Integer:
|
||||
match {
|
||||
switch {
|
||||
case ti == type_info_of(int): write_string(buf, "int");
|
||||
case ti == type_info_of(uint): write_string(buf, "uint");
|
||||
case:
|
||||
@@ -194,13 +194,13 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
||||
case Type_Info_Rune:
|
||||
write_string(buf, "rune");
|
||||
case Type_Info_Float:
|
||||
match ti.size {
|
||||
switch ti.size {
|
||||
case 2: write_string(buf, "f16");
|
||||
case 4: write_string(buf, "f32");
|
||||
case 8: write_string(buf, "f64");
|
||||
}
|
||||
case Type_Info_Complex:
|
||||
match ti.size {
|
||||
switch ti.size {
|
||||
case 4: write_string(buf, "complex32");
|
||||
case 8: write_string(buf, "complex64");
|
||||
case 16: write_string(buf, "complex128");
|
||||
@@ -388,7 +388,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
|
||||
if arg_index < len(args) {
|
||||
arg := args[arg_index];
|
||||
arg.type_info = type_info_base(arg.type_info);
|
||||
match i in arg {
|
||||
switch i in arg {
|
||||
case int: num = i;
|
||||
case i8: num = int(i);
|
||||
case i16: num = int(i);
|
||||
@@ -423,7 +423,7 @@ fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) {
|
||||
}
|
||||
|
||||
fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) {
|
||||
match verb {
|
||||
switch verb {
|
||||
case 't', 'v':
|
||||
s := "false";
|
||||
if b do s = "true";
|
||||
@@ -475,7 +475,7 @@ _fmt_int :: proc(fi: ^Fmt_Info, u: u128, base: int, is_signed: bool, bit_size: i
|
||||
}
|
||||
}
|
||||
|
||||
match base {
|
||||
switch base {
|
||||
case 2, 8, 10, 12, 16:
|
||||
break;
|
||||
case:
|
||||
@@ -493,7 +493,7 @@ _fmt_int :: proc(fi: ^Fmt_Info, u: u128, base: int, is_signed: bool, bit_size: i
|
||||
|
||||
if fi.hash && fi.zero {
|
||||
c: u8;
|
||||
match base {
|
||||
switch base {
|
||||
case 2: c = 'b';
|
||||
case 8: c = 'o';
|
||||
case 10: c = 'd';
|
||||
@@ -517,7 +517,7 @@ __DIGITS_LOWER := "0123456789abcdefx";
|
||||
__DIGITS_UPPER := "0123456789ABCDEFX";
|
||||
|
||||
fmt_rune :: proc(fi: ^Fmt_Info, r: rune, verb: rune) {
|
||||
match verb {
|
||||
switch verb {
|
||||
case 'c', 'r', 'v':
|
||||
write_rune(fi.buf, r);
|
||||
case:
|
||||
@@ -526,7 +526,7 @@ fmt_rune :: proc(fi: ^Fmt_Info, r: rune, verb: rune) {
|
||||
}
|
||||
|
||||
fmt_int :: proc(fi: ^Fmt_Info, u: u128, is_signed: bool, bit_size: int, verb: rune) {
|
||||
match verb {
|
||||
switch verb {
|
||||
case 'v': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER);
|
||||
case 'b': _fmt_int(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER);
|
||||
case 'o': _fmt_int(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER);
|
||||
@@ -568,7 +568,7 @@ _pad :: proc(fi: ^Fmt_Info, s: string) {
|
||||
}
|
||||
|
||||
fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) {
|
||||
match verb {
|
||||
switch verb {
|
||||
// case 'e', 'E', 'f', 'F', 'g', 'G', 'v':
|
||||
// case 'f', 'F', 'v':
|
||||
|
||||
@@ -611,7 +611,7 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) {
|
||||
}
|
||||
}
|
||||
fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) {
|
||||
match verb {
|
||||
switch verb {
|
||||
case 's', 'v':
|
||||
write_string(fi.buf, s);
|
||||
|
||||
@@ -633,7 +633,7 @@ fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) {
|
||||
}
|
||||
|
||||
fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
|
||||
match verb {
|
||||
switch verb {
|
||||
case 'p', 'v':
|
||||
// Okay
|
||||
case:
|
||||
@@ -650,7 +650,7 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
|
||||
enum_value_to_string :: proc(v: any) -> (string, bool) {
|
||||
v.type_info = type_info_base(v.type_info);
|
||||
|
||||
match e in v.type_info.variant {
|
||||
switch e in v.type_info.variant {
|
||||
case: return "", false;
|
||||
case Type_Info_Enum:
|
||||
get_str :: proc(i: $T, e: Type_Info_Enum) -> (string, bool) {
|
||||
@@ -673,7 +673,7 @@ enum_value_to_string :: proc(v: any) -> (string, bool) {
|
||||
}
|
||||
|
||||
a := any{v.data, type_info_base(e.base)};
|
||||
match v in a {
|
||||
switch v in a {
|
||||
case rune: return get_str(v, e);
|
||||
case i8: return get_str(v, e);
|
||||
case i16: return get_str(v, e);
|
||||
@@ -716,10 +716,10 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
return;
|
||||
}
|
||||
|
||||
match e in v.type_info.variant {
|
||||
switch e in v.type_info.variant {
|
||||
case: fmt_bad_verb(fi, verb);
|
||||
case Type_Info_Enum:
|
||||
match verb {
|
||||
switch verb {
|
||||
case: fmt_bad_verb(fi, verb);
|
||||
case 'd', 'f':
|
||||
fmt_arg(fi, any{v.data, type_info_base(e.base)}, verb);
|
||||
@@ -738,9 +738,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
return;
|
||||
}
|
||||
|
||||
match info in v.type_info.variant {
|
||||
switch info in v.type_info.variant {
|
||||
case Type_Info_Named:
|
||||
match b in info.base.variant {
|
||||
switch b in info.base.variant {
|
||||
case Type_Info_Struct:
|
||||
if verb != 'v' {
|
||||
fmt_bad_verb(fi, verb);
|
||||
@@ -939,7 +939,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
}
|
||||
|
||||
fmt_complex :: proc(fi: ^Fmt_Info, c: complex128, bits: int, verb: rune) {
|
||||
match verb {
|
||||
switch verb {
|
||||
case 'f', 'F', 'v':
|
||||
r, i := real(c), imag(c);
|
||||
fmt_float(fi, r, bits/2, verb);
|
||||
@@ -972,7 +972,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
||||
|
||||
if verb == 'T' {
|
||||
ti := arg.type_info;
|
||||
match a in arg {
|
||||
switch a in arg {
|
||||
case ^Type_Info: ti = a;
|
||||
}
|
||||
write_type(fi.buf, ti);
|
||||
@@ -982,7 +982,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
||||
|
||||
base_arg := arg;
|
||||
base_arg.type_info = type_info_base(base_arg.type_info);
|
||||
match a in base_arg {
|
||||
switch a in base_arg {
|
||||
case any: fmt_arg(fi, a, verb);
|
||||
case bool: fmt_bool(fi, a, verb);
|
||||
case rune: fmt_rune(fi, a, verb);
|
||||
@@ -1073,7 +1073,7 @@ sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ...any) -> string {
|
||||
i += 1;
|
||||
|
||||
prefix_loop: for ; i < end; i += 1 {
|
||||
match fmt[i] {
|
||||
switch fmt[i] {
|
||||
case '+':
|
||||
fi.plus = true;
|
||||
case '-':
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import "core:mem.odin";
|
||||
import "core:mem.odin"
|
||||
|
||||
adler32 :: proc(data: []u8) -> u32 {
|
||||
ADLER_CONST :: 65521;
|
||||
@@ -80,7 +80,7 @@ murmur32 :: proc(data: []u8) -> u32 {
|
||||
|
||||
tail := data[nblocks*4 ..];
|
||||
k1: u32;
|
||||
match len(tail)&3 {
|
||||
switch len(tail)&3 {
|
||||
case 3:
|
||||
k1 ~= u32(tail[2]) << 16;
|
||||
fallthrough;
|
||||
@@ -127,7 +127,7 @@ murmur64 :: proc(data: []u8) -> u64 {
|
||||
h *= m;
|
||||
}
|
||||
|
||||
match len(data)&7 {
|
||||
switch len(data)&7 {
|
||||
case 7: h ~= u64(data[6]) << 48; fallthrough;
|
||||
case 6: h ~= u64(data[5]) << 40; fallthrough;
|
||||
case 5: h ~= u64(data[4]) << 32; fallthrough;
|
||||
@@ -186,7 +186,7 @@ murmur64 :: proc(data: []u8) -> u64 {
|
||||
|
||||
// TODO(bill): Fix this
|
||||
#no_bounds_check data8 := slice_to_bytes(data32[i..])[..3];
|
||||
match len {
|
||||
switch len {
|
||||
case 3:
|
||||
h2 ~= u32(data8[2]) << 16;
|
||||
fallthrough;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import "core:raw.odin";
|
||||
import "core:raw.odin"
|
||||
|
||||
foreign __llvm_core {
|
||||
swap :: proc(b: u16) -> u16 #link_name "llvm.bswap.i16" ---;
|
||||
@@ -137,7 +137,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
using Allocator_Mode;
|
||||
arena := cast(^Arena)allocator_data;
|
||||
|
||||
match mode {
|
||||
switch mode {
|
||||
case Alloc:
|
||||
total_size := size + alignment;
|
||||
|
||||
@@ -200,7 +200,7 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
||||
|
||||
WORD_SIZE :: size_of(int);
|
||||
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
||||
match info in type_info.variant {
|
||||
switch info in type_info.variant {
|
||||
case Type_Info_Named:
|
||||
return align_of_type_info(info.base);
|
||||
case Type_Info_Integer:
|
||||
@@ -252,7 +252,7 @@ align_formula :: proc(size, align: int) -> int {
|
||||
|
||||
size_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
||||
WORD_SIZE :: size_of(int);
|
||||
match info in type_info.variant {
|
||||
switch info in type_info.variant {
|
||||
case Type_Info_Named:
|
||||
return size_of_type_info(info.base);
|
||||
case Type_Info_Integer:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
when ODIN_OS == "windows" do foreign_system_library lib "opengl32.lib";
|
||||
when ODIN_OS == "linux" do foreign_system_library lib "gl";
|
||||
|
||||
when ODIN_OS == "windows" {
|
||||
import win32 "core:sys/windows.odin";
|
||||
import "core:sys/wgl.odin";
|
||||
foreign_system_library lib "opengl32.lib"
|
||||
import win32 "core:sys/windows.odin"
|
||||
import "core:sys/wgl.odin"
|
||||
} else when ODIN_OS == "linux" {
|
||||
foreign_system_library lib "gl"
|
||||
}
|
||||
|
||||
export "core:opengl_constants.odin";
|
||||
export "core:opengl_constants.odin"
|
||||
|
||||
_ := compile_assert(ODIN_OS != "osx");
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
foreign_system_library dl "dl";
|
||||
foreign_system_library libc "c";
|
||||
foreign_system_library dl "dl"
|
||||
foreign_system_library libc "c"
|
||||
|
||||
import "core:strings.odin";
|
||||
import "core:strings.odin"
|
||||
|
||||
Handle :: i32;
|
||||
File_Time :: u64;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import win32 "core:sys/windows.odin";
|
||||
import "core:mem.odin";
|
||||
import win32 "core:sys/windows.odin"
|
||||
import "core:mem.odin"
|
||||
|
||||
Handle :: int;
|
||||
File_Time :: u64;
|
||||
@@ -60,7 +60,7 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn
|
||||
if len(path) == 0 do return INVALID_HANDLE, ERROR_FILE_NOT_FOUND;
|
||||
|
||||
access: u32;
|
||||
match mode & (O_RDONLY|O_WRONLY|O_RDWR) {
|
||||
switch mode & (O_RDONLY|O_WRONLY|O_RDWR) {
|
||||
case O_RDONLY: access = win32.FILE_GENERIC_READ;
|
||||
case O_WRONLY: access = win32.FILE_GENERIC_WRITE;
|
||||
case O_RDWR: access = win32.FILE_GENERIC_READ | win32.FILE_GENERIC_WRITE;
|
||||
@@ -82,7 +82,7 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn
|
||||
}
|
||||
|
||||
create_mode: u32;
|
||||
match {
|
||||
switch {
|
||||
case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
|
||||
create_mode = win32.CREATE_NEW;
|
||||
case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
|
||||
@@ -156,7 +156,7 @@ read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||
w: u32;
|
||||
match whence {
|
||||
switch whence {
|
||||
case 0: w = win32.FILE_BEGIN;
|
||||
case 1: w = win32.FILE_CURRENT;
|
||||
case 2: w = win32.FILE_END;
|
||||
@@ -272,7 +272,7 @@ _alloc_command_line_arguments :: proc() -> []string {
|
||||
|
||||
i, j := 0, 0;
|
||||
for str[j] != 0 {
|
||||
match {
|
||||
switch {
|
||||
case str[j] < 0x80:
|
||||
if i+1 > len do return "";
|
||||
buf[i] = u8(str[j]); i += 1;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
foreign_system_library dl "dl";
|
||||
foreign_system_library libc "c";
|
||||
foreign_system_library dl "dl"
|
||||
foreign_system_library libc "c"
|
||||
|
||||
import "core:strings.odin";
|
||||
import "core:strings.odin"
|
||||
|
||||
Handle :: i32;
|
||||
File_Time :: u64;
|
||||
|
||||
@@ -187,7 +187,7 @@ merge_sort :: proc(array: $A/[]$T) {
|
||||
|
||||
|
||||
compare_ints :: proc(a, b: int) -> int {
|
||||
match delta := a - b; {
|
||||
switch delta := a - b; {
|
||||
case delta < 0: return -1;
|
||||
case delta > 0: return +1;
|
||||
}
|
||||
@@ -195,14 +195,14 @@ compare_ints :: proc(a, b: int) -> int {
|
||||
}
|
||||
|
||||
compare_f32s :: proc(a, b: f32) -> int {
|
||||
match delta := a - b; {
|
||||
switch delta := a - b; {
|
||||
case delta < 0: return -1;
|
||||
case delta > 0: return +1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
compare_f64s :: proc(a, b: f64) -> int {
|
||||
match delta := a - b; {
|
||||
switch delta := a - b; {
|
||||
case delta < 0: return -1;
|
||||
case delta > 0: return +1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using import "core:decimal.odin";
|
||||
using import "core:decimal.odin"
|
||||
|
||||
Int_Flag :: enum {
|
||||
Prefix = 1<<0,
|
||||
@@ -8,7 +8,7 @@ Int_Flag :: enum {
|
||||
|
||||
|
||||
parse_bool :: proc(s: string) -> (result: bool = false, ok: bool) {
|
||||
match s {
|
||||
switch s {
|
||||
case "1", "t", "T", "true", "TRUE", "True":
|
||||
return true, true;
|
||||
case "0", "f", "F", "false", "FALSE", "False":
|
||||
@@ -20,7 +20,7 @@ parse_bool :: proc(s: string) -> (result: bool = false, ok: bool) {
|
||||
_digit_value :: proc(r: rune) -> int {
|
||||
ri := int(r);
|
||||
v: int = 16;
|
||||
match r {
|
||||
switch r {
|
||||
case '0'...'9': v = ri-'0';
|
||||
case 'a'...'z': v = ri-'a'+10;
|
||||
case 'A'...'Z': v = ri-'A'+10;
|
||||
@@ -31,7 +31,7 @@ _digit_value :: proc(r: rune) -> int {
|
||||
parse_i128 :: proc(s: string) -> i128 {
|
||||
neg := false;
|
||||
if len(s) > 1 {
|
||||
match s[0] {
|
||||
switch s[0] {
|
||||
case '-':
|
||||
neg = true;
|
||||
s = s[1..];
|
||||
@@ -43,7 +43,7 @@ parse_i128 :: proc(s: string) -> i128 {
|
||||
|
||||
base: i128 = 10;
|
||||
if len(s) > 2 && s[0] == '0' {
|
||||
match s[1] {
|
||||
switch s[1] {
|
||||
case 'b': base = 2; s = s[2..];
|
||||
case 'o': base = 8; s = s[2..];
|
||||
case 'd': base = 10; s = s[2..];
|
||||
@@ -80,7 +80,7 @@ parse_u128 :: proc(s: string) -> u128 {
|
||||
|
||||
base := u128(10);
|
||||
if len(s) > 2 && s[0] == '0' {
|
||||
match s[1] {
|
||||
switch s[1] {
|
||||
case 'b': base = 2; s = s[2..];
|
||||
case 'o': base = 8; s = s[2..];
|
||||
case 'd': base = 10; s = s[2..];
|
||||
@@ -115,7 +115,7 @@ parse_f64 :: proc(s: string) -> f64 {
|
||||
i := 0;
|
||||
|
||||
sign: f64 = 1;
|
||||
match s[i] {
|
||||
switch s[i] {
|
||||
case '-': i += 1; sign = -1;
|
||||
case '+': i += 1;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ parse_f64 :: proc(s: string) -> f64 {
|
||||
i += 1;
|
||||
|
||||
if i < len(s) {
|
||||
match s[i] {
|
||||
switch s[i] {
|
||||
case '-': i += 1; frac = true;
|
||||
case '+': i += 1;
|
||||
}
|
||||
@@ -223,7 +223,7 @@ _f64_info := FloatInfo{52, 11, -1023};
|
||||
generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8 {
|
||||
bits: u64;
|
||||
flt: ^FloatInfo;
|
||||
match bit_size {
|
||||
switch bit_size {
|
||||
case 32:
|
||||
bits = u64(transmute(u32)f32(val));
|
||||
flt = &_f32_info;
|
||||
@@ -238,7 +238,7 @@ generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8
|
||||
exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1);
|
||||
mant := bits & (u64(1) << flt.mantbits - 1);
|
||||
|
||||
match exp {
|
||||
switch exp {
|
||||
case 1<<flt.expbits - 1:
|
||||
s: string;
|
||||
if mant != 0 {
|
||||
@@ -269,13 +269,13 @@ generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8
|
||||
if shortest {
|
||||
round_shortest(d, mant, exp, flt);
|
||||
digs = DecimalSlice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point};
|
||||
match fmt {
|
||||
switch fmt {
|
||||
case 'e', 'E': prec = digs.count-1;
|
||||
case 'f', 'F': prec = max(digs.count-digs.decimal_point, 0);
|
||||
case 'g', 'G': prec = digs.count;
|
||||
}
|
||||
} else {
|
||||
match fmt {
|
||||
switch fmt {
|
||||
case 'e', 'E': round(d, prec+1);
|
||||
case 'f', 'F': round(d, d.decimal_point+prec);
|
||||
case 'g', 'G':
|
||||
@@ -293,7 +293,7 @@ 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 {
|
||||
match fmt {
|
||||
switch fmt {
|
||||
case 'f', 'F':
|
||||
append(&buf, neg ? '-' : '+');
|
||||
|
||||
@@ -410,7 +410,7 @@ digits := "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
is_integer_negative :: proc(u: u128, is_signed: bool, bit_size: int) -> (unsigned: u128, neg: bool) {
|
||||
neg := false;
|
||||
if is_signed {
|
||||
match bit_size {
|
||||
switch bit_size {
|
||||
case 8:
|
||||
i := i8(u);
|
||||
neg = i < 0;
|
||||
@@ -456,7 +456,7 @@ append_bits :: proc(buf: []u8, u: u128, base: int, is_signed: bool, bit_size: in
|
||||
|
||||
if flags&Int_Flag.Prefix != 0 {
|
||||
ok := true;
|
||||
match base {
|
||||
switch base {
|
||||
case 2: i-=1; a[i] = 'b';
|
||||
case 8: i-=1; a[i] = 'o';
|
||||
case 10: i-=1; a[i] = 'd';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import "core:mem.odin";
|
||||
import "core:mem.odin"
|
||||
|
||||
new_string :: proc(s: string) -> string {
|
||||
c := make([]u8, len(s)+1);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import "core:atomics.odin";
|
||||
import "core:os.odin";
|
||||
import "core:atomics.odin"
|
||||
import "core:os.odin"
|
||||
|
||||
Semaphore :: struct {
|
||||
// _handle: win32.Handle,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
when ODIN_OS == "windows" do import win32 "core:sys/windows.odin";
|
||||
import "core:atomics.odin";
|
||||
when ODIN_OS == "windows" {
|
||||
import win32 "core:sys/windows.odin";
|
||||
}
|
||||
import "core:atomics.odin"
|
||||
|
||||
Semaphore :: struct {
|
||||
_handle: win32.Handle,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
when ODIN_OS == "windows" do foreign_system_library "opengl32.lib";
|
||||
using import "core:sys/windows.odin";
|
||||
when ODIN_OS == "windows" {
|
||||
foreign_system_library "opengl32.lib"
|
||||
}
|
||||
using import "core:sys/windows.odin"
|
||||
|
||||
|
||||
CONTEXT_MAJOR_VERSION_ARB :: 0x2091;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
when ODIN_OS == "windows" {
|
||||
foreign_system_library "kernel32.lib";
|
||||
foreign_system_library "user32.lib";
|
||||
foreign_system_library "gdi32.lib";
|
||||
foreign_system_library "winmm.lib";
|
||||
foreign_system_library "shell32.lib";
|
||||
foreign_system_library "kernel32.lib"
|
||||
foreign_system_library "user32.lib"
|
||||
foreign_system_library "gdi32.lib"
|
||||
foreign_system_library "winmm.lib"
|
||||
foreign_system_library "shell32.lib"
|
||||
}
|
||||
|
||||
Handle :: rawptr;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
_ :: compile_assert(ODIN_OS == "windows");
|
||||
|
||||
when ODIN_OS == "windows" {
|
||||
import win32 "core:sys/windows.odin";
|
||||
import win32 "core:sys/windows.odin"
|
||||
}
|
||||
|
||||
Thread_Proc :: #type proc(^Thread) -> int;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
is_signed :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
match i in type_info_base(info).variant {
|
||||
switch i in type_info_base(info).variant {
|
||||
case Type_Info_Integer: return i.signed;
|
||||
case Type_Info_Float: return true;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ encode :: proc(d: []u16, s: []rune) {
|
||||
n = 0;
|
||||
|
||||
for r in s {
|
||||
match r {
|
||||
switch r {
|
||||
case 0.._surr1, _surr3.._surr_self:
|
||||
d[n] = u16(r);
|
||||
n += 1;
|
||||
|
||||
@@ -254,7 +254,7 @@ rune_count :: proc(s: []u8) -> int {
|
||||
|
||||
|
||||
rune_size :: proc(r: rune) -> int {
|
||||
match {
|
||||
switch {
|
||||
case r < 0: return -1;
|
||||
case r <= 1<<7 - 1: return 1;
|
||||
case r <= 1<<11 - 1: return 2;
|
||||
|
||||
@@ -150,7 +150,7 @@ union_type :: proc() {
|
||||
|
||||
val = nil;
|
||||
|
||||
match v in val {
|
||||
switch v in val {
|
||||
case int: fmt.println("int", v);
|
||||
case bool: fmt.println("bool", v);
|
||||
case: fmt.println("nil");
|
||||
@@ -171,7 +171,7 @@ union_type :: proc() {
|
||||
|
||||
val = nil;
|
||||
|
||||
match v in val {
|
||||
switch v in val {
|
||||
case int: fmt.println("int", v);
|
||||
case bool: fmt.println("bool", v);
|
||||
case: fmt.println("nil");
|
||||
@@ -218,7 +218,7 @@ union_type :: proc() {
|
||||
|
||||
entity := new_entity(Monster);
|
||||
|
||||
match e in entity.derived {
|
||||
switch e in entity.derived {
|
||||
case Frog:
|
||||
fmt.println("Ribbit");
|
||||
case Monster:
|
||||
@@ -262,7 +262,7 @@ union_type :: proc() {
|
||||
|
||||
entity := new_entity(Monster);
|
||||
|
||||
match e in entity.derived {
|
||||
switch e in entity.derived {
|
||||
case Frog:
|
||||
fmt.println("Ribbit");
|
||||
case Monster:
|
||||
|
||||
@@ -234,7 +234,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
||||
d->type_expr = d->init_expr;
|
||||
check_type_decl(c, e, d->type_expr, named_type);
|
||||
return;
|
||||
} break;
|
||||
}
|
||||
|
||||
// NOTE(bill): Check to see if the expression it to be aliases
|
||||
#if 1
|
||||
@@ -446,6 +446,13 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
error(e->token, "Procedure `main` cannot have a custom calling convention");
|
||||
}
|
||||
pt->calling_convention = ProcCC_Contextless;
|
||||
if (d->scope->is_init) {
|
||||
if (c->info.entry_point != nullptr) {
|
||||
error(e->token, "Redeclaration of the entry pointer procedure `main`");
|
||||
} else {
|
||||
c->info.entry_point = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_inline && is_no_inline) {
|
||||
|
||||
@@ -2469,7 +2469,8 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
|
||||
if (sz > 8 && build_context.word_size < 8) {
|
||||
new_type = make_type_pointer(a, original_type);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Pointer: break;
|
||||
case Type_Proc: break; // NOTE(bill): Just a pointer
|
||||
|
||||
@@ -2495,7 +2496,9 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
|
||||
new_type = make_type_pointer(a, original_type);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (build_context.ODIN_OS == "linux" ||
|
||||
build_context.ODIN_OS == "osx") {
|
||||
@@ -2508,7 +2511,9 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
|
||||
if (sz > 8 && build_context.word_size < 8) {
|
||||
new_type = make_type_pointer(a, original_type);
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
case Type_Pointer: break;
|
||||
case Type_Proc: break; // NOTE(bill): Just a pointer
|
||||
|
||||
@@ -2528,7 +2533,9 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
|
||||
if (8*size > 16) {
|
||||
new_type = make_type_pointer(a, original_type);
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// IMPORTANT TODO(bill): figure out the ABI settings for Linux, OSX etc. for
|
||||
@@ -2579,7 +2586,9 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) {
|
||||
case 64: new_type = t_u64; break;
|
||||
#endif
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (build_context.ODIN_OS == "linux") {
|
||||
|
||||
@@ -3031,26 +3040,29 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
|
||||
|
||||
switch (e->kind) {
|
||||
case_ast_node(i, Ident, e);
|
||||
|
||||
Operand o = {};
|
||||
check_ident(c, &o, e, named_type, nullptr, false);
|
||||
|
||||
gbString err_str;
|
||||
switch (o.mode) {
|
||||
case Addressing_Invalid:
|
||||
break;
|
||||
case Addressing_Type: {
|
||||
case Addressing_Type:
|
||||
*type = o.type;
|
||||
return true;
|
||||
} break;
|
||||
case Addressing_NoValue: {
|
||||
gbString err_str = expr_to_string(e);
|
||||
|
||||
case Addressing_NoValue:
|
||||
err_str = expr_to_string(e);
|
||||
error(e, "`%s` used as a type", err_str);
|
||||
gb_string_free(err_str);
|
||||
} break;
|
||||
default: {
|
||||
gbString err_str = expr_to_string(e);
|
||||
break;
|
||||
|
||||
default:
|
||||
err_str = expr_to_string(e);
|
||||
error(e, "`%s` used as a type when not a type", err_str);
|
||||
gb_string_free(err_str);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case_end;
|
||||
|
||||
@@ -3104,6 +3116,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
|
||||
Operand o = {};
|
||||
check_selector(c, &o, e, nullptr);
|
||||
|
||||
gbString err_str;
|
||||
switch (o.mode) {
|
||||
case Addressing_Invalid:
|
||||
break;
|
||||
@@ -3111,16 +3124,16 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
|
||||
GB_ASSERT(o.type != nullptr);
|
||||
*type = o.type;
|
||||
return true;
|
||||
case Addressing_NoValue: {
|
||||
gbString err_str = expr_to_string(e);
|
||||
case Addressing_NoValue:
|
||||
err_str = expr_to_string(e);
|
||||
error(e, "`%s` used as a type", err_str);
|
||||
gb_string_free(err_str);
|
||||
} break;
|
||||
default: {
|
||||
gbString err_str = expr_to_string(e);
|
||||
break;
|
||||
default:
|
||||
err_str = expr_to_string(e);
|
||||
error(e, "`%s` is not a type", err_str);
|
||||
gb_string_free(err_str);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case_end;
|
||||
|
||||
@@ -3533,7 +3546,8 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
|
||||
if (out_value) *out_value = exact_binary_operator_value(Token_Add, real, exact_value_make_imag(imag));
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Basic_UntypedComplex:
|
||||
return true;
|
||||
|
||||
@@ -3724,9 +3738,9 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) {
|
||||
case Token_Lt:
|
||||
case Token_Gt:
|
||||
case Token_LtEq:
|
||||
case Token_GtEq: {
|
||||
case Token_GtEq:
|
||||
defined = is_type_ordered(x->type);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!defined) {
|
||||
@@ -4176,7 +4190,9 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
||||
if (xt) error_operand_not_expression(x);
|
||||
if (yt) error_operand_not_expression(y);
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
check_expr(c, x, be->left);
|
||||
@@ -4522,7 +4538,9 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
|
||||
convert_untyped_error(c, operand, target_type);
|
||||
return;
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Union:
|
||||
if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) {
|
||||
@@ -5112,7 +5130,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
operand->type = t_source_code_location;
|
||||
operand->mode = Addressing_Value;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_len:
|
||||
case BuiltinProc_cap: {
|
||||
@@ -5159,7 +5179,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
operand->mode = mode;
|
||||
operand->value = value;
|
||||
operand->type = type;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
case BuiltinProc_new: {
|
||||
@@ -5173,7 +5195,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
}
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = make_type_pointer(c->allocator, type);
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
case BuiltinProc_new_slice: {
|
||||
@@ -5212,7 +5236,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = make_type_slice(c->allocator, type);
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case BuiltinProc_make: {
|
||||
// proc make(Type, len: int) -> Type
|
||||
@@ -5268,7 +5294,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = type;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
case BuiltinProc_free: {
|
||||
@@ -5299,7 +5327,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
|
||||
operand->mode = Addressing_NoValue;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5329,7 +5359,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
operand->type = nullptr;
|
||||
operand->mode = Addressing_NoValue;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
case BuiltinProc_clear: {
|
||||
@@ -5345,7 +5377,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
operand->type = nullptr;
|
||||
operand->mode = Addressing_NoValue;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
case BuiltinProc_append: {
|
||||
@@ -5394,7 +5428,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
}
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = t_int;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
case BuiltinProc_delete: {
|
||||
@@ -5426,7 +5462,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
}
|
||||
|
||||
operand->mode = Addressing_NoValue;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5447,7 +5485,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->value = exact_value_i64(type_size_of(c->allocator, t));
|
||||
operand->type = t_untyped_integer;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_align_of: {
|
||||
// proc align_of(Type or expr) -> untyped int
|
||||
@@ -5466,7 +5506,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->value = exact_value_i64(type_align_of(c->allocator, t));
|
||||
operand->type = t_untyped_integer;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case BuiltinProc_offset_of: {
|
||||
@@ -5511,7 +5553,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->value = exact_value_i64(type_offset_of_from_selection(c->allocator, type, sel));
|
||||
operand->type = t_untyped_integer;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case BuiltinProc_type_of:
|
||||
@@ -5557,7 +5601,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = t_type_info_ptr;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_compile_assert:
|
||||
// proc compile_assert(cond: bool) -> bool
|
||||
@@ -5630,7 +5676,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
Type *elem_type = vector_type->Vector.elem;
|
||||
operand->type = make_type_vector(c->allocator, elem_type, arg_count);
|
||||
operand->mode = Addressing_Value;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_complex: {
|
||||
// proc complex(real, imag: float_type) -> complex_type
|
||||
@@ -5689,7 +5737,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
case Basic_UntypedFloat: operand->type = t_untyped_complex; break;
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_real:
|
||||
case BuiltinProc_imag: {
|
||||
@@ -5733,7 +5783,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
case Basic_UntypedComplex: x->type = t_untyped_float; break;
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_conj: {
|
||||
// proc conj(x: type) -> type
|
||||
@@ -5755,7 +5807,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
return false;
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
case BuiltinProc_slice_ptr: {
|
||||
@@ -5799,7 +5853,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
}
|
||||
operand->type = make_type_slice(c->allocator, ptr_type->Pointer.elem);
|
||||
operand->mode = Addressing_Value;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_slice_to_bytes: {
|
||||
// proc slice_to_bytes(a: []T) -> []u8
|
||||
@@ -5813,7 +5869,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
operand->type = t_u8_slice;
|
||||
operand->mode = Addressing_Value;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case BuiltinProc_expand_to_tuple: {
|
||||
Type *type = base_type(operand->type);
|
||||
@@ -5834,7 +5892,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
operand->type = tuple;
|
||||
operand->mode = Addressing_Value;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_min: {
|
||||
// proc min(a, b: ordered) -> ordered
|
||||
@@ -5900,7 +5960,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_max: {
|
||||
// proc min(a, b: ordered) -> ordered
|
||||
@@ -5968,7 +6030,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_abs: {
|
||||
// proc abs(n: numeric) -> numeric
|
||||
@@ -5991,7 +6055,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
f64 r = operand->value.value_complex.real;
|
||||
f64 i = operand->value.value_complex.imag;
|
||||
operand->value = exact_value_float(gb_sqrt(r*r + i*i));
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GB_PANIC("Invalid numeric constant");
|
||||
break;
|
||||
@@ -6004,7 +6070,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
operand->type = base_complex_elem_type(operand->type);
|
||||
}
|
||||
GB_ASSERT(!is_type_complex(operand->type));
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_clamp: {
|
||||
// proc clamp(a, min, max: ordered) -> ordered
|
||||
@@ -6092,7 +6160,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
case BuiltinProc_transmute: {
|
||||
@@ -6143,7 +6213,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
o->mode = Addressing_Value;
|
||||
o->type = t;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -7103,7 +7175,9 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
||||
if (operand->mode != Addressing_Invalid) {
|
||||
check_cast(c, operand, t);
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Expr_Expr;
|
||||
@@ -7330,7 +7404,9 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
switch (r) {
|
||||
case 'i': t = t_untyped_complex; break;
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
default: GB_PANIC("Unknown literal"); break;
|
||||
}
|
||||
o->mode = Addressing_Constant;
|
||||
@@ -7663,7 +7739,8 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Slice:
|
||||
case Type_Array:
|
||||
@@ -7740,7 +7817,9 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
if (t->kind == Type_Array && is_to_be_determined_array_count) {
|
||||
t->Array.count = max;
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Basic: {
|
||||
if (!is_type_any(t)) {
|
||||
@@ -7819,7 +7898,9 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Map: {
|
||||
if (cl->elems.count == 0) {
|
||||
@@ -7844,7 +7925,9 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
check_assignment(c, o, t->Map.value, str_lit("map literal"));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
if (cl->elems.count == 0) {
|
||||
@@ -7855,7 +7938,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
error(node, "Invalid compound literal type `%s`", str);
|
||||
gb_string_free(str);
|
||||
return kind;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_constant) {
|
||||
|
||||
@@ -138,10 +138,10 @@ bool check_is_terminating(AstNode *node) {
|
||||
return false;
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, MatchStmt, node);
|
||||
case_ast_node(ss, SwitchStmt, node);
|
||||
bool has_default = false;
|
||||
for_array(i, ms->body->BlockStmt.stmts) {
|
||||
AstNode *clause = ms->body->BlockStmt.stmts[i];
|
||||
for_array(i, ss->body->BlockStmt.stmts) {
|
||||
AstNode *clause = ss->body->BlockStmt.stmts[i];
|
||||
ast_node(cc, CaseClause, clause);
|
||||
if (cc->list.count == 0) {
|
||||
has_default = true;
|
||||
@@ -154,10 +154,10 @@ bool check_is_terminating(AstNode *node) {
|
||||
return has_default;
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, TypeMatchStmt, node);
|
||||
case_ast_node(ss, TypeSwitchStmt, node);
|
||||
bool has_default = false;
|
||||
for_array(i, ms->body->BlockStmt.stmts) {
|
||||
AstNode *clause = ms->body->BlockStmt.stmts[i];
|
||||
for_array(i, ss->body->BlockStmt.stmts) {
|
||||
AstNode *clause = ss->body->BlockStmt.stmts[i];
|
||||
ast_node(cc, CaseClause, clause);
|
||||
if (cc->list.count == 0) {
|
||||
has_default = true;
|
||||
@@ -309,7 +309,9 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
if (lhs.expr->kind == AstNode_SelectorExpr) {
|
||||
@@ -332,7 +334,9 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
|
||||
error(lhs.expr, "Cannot assign to `%s`", str);
|
||||
}
|
||||
gb_string_free(str);
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
check_assignment(c, rhs, assignment_type, str_lit("assignment"));
|
||||
@@ -490,7 +494,9 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
|
||||
} else {
|
||||
error(us->token, "`using` can be only applied to enum type entities");
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Entity_ImportName: {
|
||||
Scope *scope = e->ImportName.scope;
|
||||
@@ -511,7 +517,9 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Entity_Variable: {
|
||||
Type *t = base_type(type_deref(e->type));
|
||||
@@ -538,7 +546,9 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
|
||||
error(us->token, "`using` can only be applied to variables of type struct or raw_union");
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Entity_Constant:
|
||||
error(us->token, "`using` cannot be applied to a constant");
|
||||
@@ -583,7 +593,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
gbString str = type_to_string(operand.type);
|
||||
error(node, "`%s` is not an expression", str);
|
||||
gb_string_free(str);
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
case Addressing_NoValue:
|
||||
return;
|
||||
default: {
|
||||
@@ -605,7 +617,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
gbString expr_str = expr_to_string(operand.expr);
|
||||
error(node, "Expression is not used: `%s`", expr_str);
|
||||
gb_string_free(expr_str);
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
|
||||
@@ -695,7 +709,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
error(as->lhs[0], "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// a += 1; // Single-sided
|
||||
@@ -723,7 +739,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
// NOTE(bill): Only use the first one will be used
|
||||
check_assignment_variable(c, &operand, as->lhs[0]);
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
|
||||
@@ -1161,18 +1179,18 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
check_close_scope(c);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, MatchStmt, node);
|
||||
case_ast_node(ss, SwitchStmt, node);
|
||||
Operand x = {};
|
||||
|
||||
mod_flags |= Stmt_BreakAllowed;
|
||||
check_open_scope(c, node);
|
||||
check_label(c, ms->label); // TODO(bill): What should the label's "scope" be?
|
||||
check_label(c, ss->label); // TODO(bill): What should the label's "scope" be?
|
||||
|
||||
if (ms->init != nullptr) {
|
||||
check_stmt(c, ms->init, 0);
|
||||
if (ss->init != nullptr) {
|
||||
check_stmt(c, ss->init, 0);
|
||||
}
|
||||
if (ms->tag != nullptr) {
|
||||
check_expr(c, &x, ms->tag);
|
||||
if (ss->tag != nullptr) {
|
||||
check_expr(c, &x, ss->tag);
|
||||
check_assignment(c, &x, nullptr, str_lit("match expression"));
|
||||
} else {
|
||||
x.mode = Addressing_Constant;
|
||||
@@ -1180,7 +1198,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
x.value = exact_value_bool(true);
|
||||
|
||||
Token token = {};
|
||||
token.pos = ast_node_token(ms->body).pos;
|
||||
token.pos = ast_node_token(ss->body).pos;
|
||||
token.string = str_lit("true");
|
||||
x.expr = ast_ident(c->curr_ast_file, token);
|
||||
}
|
||||
@@ -1194,7 +1212,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
// NOTE(bill): Check for multiple defaults
|
||||
AstNode *first_default = nullptr;
|
||||
ast_node(bs, BlockStmt, ms->body);
|
||||
ast_node(bs, BlockStmt, ss->body);
|
||||
for_array(i, bs->stmts) {
|
||||
AstNode *stmt = bs->stmts[i];
|
||||
AstNode *default_stmt = nullptr;
|
||||
@@ -1365,22 +1383,22 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
check_close_scope(c);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, TypeMatchStmt, node);
|
||||
case_ast_node(ss, TypeSwitchStmt, node);
|
||||
Operand x = {};
|
||||
|
||||
mod_flags |= Stmt_BreakAllowed;
|
||||
check_open_scope(c, node);
|
||||
check_label(c, ms->label); // TODO(bill): What should the label's "scope" be?
|
||||
check_label(c, ss->label); // TODO(bill): What should the label's "scope" be?
|
||||
|
||||
MatchTypeKind match_type_kind = MatchType_Invalid;
|
||||
|
||||
if (ms->tag->kind != AstNode_AssignStmt) {
|
||||
error(ms->tag, "Expected an `in` assignment for this type match statement");
|
||||
if (ss->tag->kind != AstNode_AssignStmt) {
|
||||
error(ss->tag, "Expected an `in` assignment for this type match statement");
|
||||
break;
|
||||
}
|
||||
|
||||
ast_node(as, AssignStmt, ms->tag);
|
||||
Token as_token = ast_node_token(ms->tag);
|
||||
ast_node(as, AssignStmt, ss->tag);
|
||||
Token as_token = ast_node_token(ss->tag);
|
||||
if (as->lhs.count != 1) {
|
||||
syntax_error(as_token, "Expected 1 name before `in`");
|
||||
break;
|
||||
@@ -1406,7 +1424,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
// NOTE(bill): Check for multiple defaults
|
||||
AstNode *first_default = nullptr;
|
||||
ast_node(bs, BlockStmt, ms->body);
|
||||
ast_node(bs, BlockStmt, ss->body);
|
||||
for_array(i, bs->stmts) {
|
||||
AstNode *stmt = bs->stmts[i];
|
||||
AstNode *default_stmt = nullptr;
|
||||
|
||||
122
src/checker.cpp
122
src/checker.cpp
@@ -448,8 +448,9 @@ struct CheckerInfo {
|
||||
Map<isize> type_info_map; // Key: Type *
|
||||
isize type_info_count;
|
||||
|
||||
Scope * init_scope;
|
||||
Entity * entry_point;
|
||||
PtrSet<Entity *> minimum_dependency_map;
|
||||
PtrSet<Entity *> minimum_dependency_set;
|
||||
|
||||
};
|
||||
|
||||
@@ -1293,7 +1294,7 @@ void add_type_info_type(Checker *c, Type *t) {
|
||||
add_type_info_type(c, bt);
|
||||
|
||||
switch (bt->kind) {
|
||||
case Type_Basic: {
|
||||
case Type_Basic:
|
||||
switch (bt->Basic.kind) {
|
||||
case Basic_string:
|
||||
add_type_info_type(c, t_u8_ptr);
|
||||
@@ -1313,7 +1314,7 @@ void add_type_info_type(Checker *c, Type *t) {
|
||||
add_type_info_type(c, t_f64);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
|
||||
case Type_Pointer:
|
||||
add_type_info_type(c, bt->Pointer.elem);
|
||||
@@ -1352,7 +1353,7 @@ void add_type_info_type(Checker *c, Type *t) {
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Struct: {
|
||||
case Type_Struct:
|
||||
if (bt->Struct.scope != nullptr) {
|
||||
for_array(i, bt->Struct.scope->elements.entries) {
|
||||
Entity *e = bt->Struct.scope->elements.entries[i].value;
|
||||
@@ -1363,14 +1364,14 @@ void add_type_info_type(Checker *c, Type *t) {
|
||||
Entity *f = bt->Struct.fields[i];
|
||||
add_type_info_type(c, f->type);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
|
||||
case Type_Map: {
|
||||
case Type_Map:
|
||||
generate_map_internal_types(c->allocator, bt);
|
||||
add_type_info_type(c, bt->Map.key);
|
||||
add_type_info_type(c, bt->Map.value);
|
||||
add_type_info_type(c, bt->Map.generated_struct_type);
|
||||
} break;
|
||||
break;
|
||||
|
||||
case Type_Tuple:
|
||||
for_array(i, bt->Tuple.variables) {
|
||||
@@ -1457,7 +1458,7 @@ void add_dependency_to_map(PtrSet<Entity *> *map, CheckerInfo *info, Entity *ent
|
||||
}
|
||||
}
|
||||
|
||||
PtrSet<Entity *> generate_minimum_dependency_map(CheckerInfo *info, Entity *start) {
|
||||
PtrSet<Entity *> generate_minimum_dependency_set(CheckerInfo *info, Entity *start) {
|
||||
PtrSet<Entity *> map = {}; // Key: Entity *
|
||||
ptr_set_init(&map, heap_allocator());
|
||||
|
||||
@@ -2360,7 +2361,9 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *
|
||||
for_array(i, stmts) {
|
||||
add_import_dependency_node(c, stmts[i], M);
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
case AstNode_WhenStmt:
|
||||
add_import_dependency_node(c, ws->else_stmt, M);
|
||||
break;
|
||||
@@ -2839,17 +2842,15 @@ void check_import_entities(Checker *c) {
|
||||
};
|
||||
|
||||
|
||||
if (path.count > 0) {
|
||||
Scope *s = path[path.count-1];
|
||||
Token token = mt(s);
|
||||
error(token, "Cyclic importation of `%.*s`", LIT(token.string));
|
||||
for (isize i = 0; i < path.count; i++) {
|
||||
gb_printf_err("\t`%.*s` refers to\n", LIT(token.string));
|
||||
s = path[i];
|
||||
token = mt(s);
|
||||
}
|
||||
gb_printf_err("\t`%.*s`\n", LIT(token.string));
|
||||
Scope *s = path[path.count-1];
|
||||
Token token = mt(s);
|
||||
error(token, "Cyclic importation of `%.*s`", LIT(token.string));
|
||||
for (isize i = 0; i < path.count; i++) {
|
||||
gb_printf_err("\t`%.*s` refers to\n", LIT(token.string));
|
||||
s = path[i];
|
||||
token = mt(s);
|
||||
}
|
||||
gb_printf_err("\t`%.*s`\n", LIT(token.string));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3059,11 +3060,14 @@ void check_parsed_files(Checker *c) {
|
||||
for_array(i, c->parser->files) {
|
||||
AstFile *f = c->parser->files[i];
|
||||
Scope *scope = create_scope_from_file(c, f);
|
||||
|
||||
f->decl_info = make_declaration_info(c->allocator, f->scope, c->context.decl);
|
||||
HashKey key = hash_string(f->tokenizer.fullpath);
|
||||
map_set(&c->file_scopes, key, scope);
|
||||
map_set(&c->info.files, key, f);
|
||||
|
||||
if (scope->is_init) {
|
||||
c->info.init_scope = scope;
|
||||
}
|
||||
}
|
||||
|
||||
// Collect Entities
|
||||
@@ -3077,7 +3081,7 @@ void check_parsed_files(Checker *c) {
|
||||
|
||||
check_import_entities(c);
|
||||
check_all_global_entities(c);
|
||||
init_preload(c); // NOTE(bill): This could be setup previously through the use of `type_info(_of_val)`
|
||||
init_preload(c); // NOTE(bill): This could be setup previously through the use of `type_info_of`
|
||||
|
||||
// Check procedure bodies
|
||||
// NOTE(bill): Nested procedures bodies will be added to this "queue"
|
||||
@@ -3112,25 +3116,12 @@ void check_parsed_files(Checker *c) {
|
||||
check_proc_body(c, pi->token, pi->decl, pi->type, pi->body);
|
||||
}
|
||||
|
||||
{
|
||||
for_array(i, c->info.entities.entries) {
|
||||
auto *entry = &c->info.entities.entries[i];
|
||||
Entity *e = cast(Entity *)entry->key.ptr;
|
||||
String name = e->token.string;
|
||||
if (e->kind == Entity_Procedure && !e->scope->is_global) {
|
||||
if (e->scope->is_init && name == "main") {
|
||||
c->info.entry_point = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
c->info.minimum_dependency_map = generate_minimum_dependency_map(&c->info, c->info.entry_point);
|
||||
}
|
||||
c->info.minimum_dependency_set = generate_minimum_dependency_set(&c->info, c->info.entry_point);
|
||||
|
||||
|
||||
// Calculate initialization order of global variables
|
||||
calculate_global_init_order(c);
|
||||
|
||||
|
||||
// Add untyped expression values
|
||||
for_array(i, c->info.untyped.entries) {
|
||||
auto *entry = &c->info.untyped.entries[i];
|
||||
@@ -3148,8 +3139,6 @@ void check_parsed_files(Checker *c) {
|
||||
// TODO(bill): Check for unused imports (and remove) or even warn/err
|
||||
// TODO(bill): Any other checks?
|
||||
|
||||
|
||||
#if 1
|
||||
// Add "Basic" type information
|
||||
for (isize i = 0; i < gb_count_of(basic_types)-1; i++) {
|
||||
Type *t = &basic_types[i];
|
||||
@@ -3158,53 +3147,34 @@ void check_parsed_files(Checker *c) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for (isize i = 0; i < gb_count_of(basic_type_aliases)-1; i++) {
|
||||
Type *t = &basic_type_aliases[i];
|
||||
if (t->Basic.size > 0) {
|
||||
add_type_info_type(c, t);
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
// NOTE(bill): Check for illegal cyclic type declarations
|
||||
for_array(i, c->info.definitions.entries) {
|
||||
Entity *e = c->info.definitions.entries[i].value;
|
||||
if (e->kind == Entity_TypeName) {
|
||||
if (e->type != nullptr) {
|
||||
// i64 size = type_size_of(c->sizes, c->allocator, e->type);
|
||||
i64 align = type_align_of(c->allocator, e->type);
|
||||
if (align > 0) {
|
||||
add_type_info_type(c, e->type);
|
||||
}
|
||||
if (e->kind == Entity_TypeName && e->type != nullptr) {
|
||||
// i64 size = type_size_of(c->sizes, c->allocator, e->type);
|
||||
i64 align = type_align_of(c->allocator, e->type);
|
||||
if (align > 0) {
|
||||
add_type_info_type(c, e->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gb_printf_err("Count: %td\n", c->info.type_info_count++);
|
||||
|
||||
if (!build_context.is_dll) {
|
||||
for_array(i, c->file_scopes.entries) {
|
||||
Scope *s = c->file_scopes.entries[i].value;
|
||||
if (s->is_init) {
|
||||
Entity *e = current_scope_lookup_entity(s, str_lit("main"));
|
||||
if (e == nullptr) {
|
||||
Token token = {};
|
||||
if (s->file->tokens.count > 0) {
|
||||
token = s->file->tokens[0];
|
||||
} else {
|
||||
token.pos.file = s->file->tokenizer.fullpath;
|
||||
token.pos.line = 1;
|
||||
token.pos.column = 1;
|
||||
}
|
||||
|
||||
error(token, "Undefined entry point procedure `main`");
|
||||
}
|
||||
|
||||
break;
|
||||
Scope *s = c->info.init_scope;
|
||||
GB_ASSERT(s != nullptr);
|
||||
GB_ASSERT(s->is_init);
|
||||
Entity *e = current_scope_lookup_entity(s, str_lit("main"));
|
||||
if (e == nullptr) {
|
||||
Token token = {};
|
||||
if (s->file->tokens.count > 0) {
|
||||
token = s->file->tokens[0];
|
||||
} else {
|
||||
token.pos.file = s->file->tokenizer.fullpath;
|
||||
token.pos.line = 1;
|
||||
token.pos.column = 1;
|
||||
}
|
||||
|
||||
error(token, "Undefined entry point procedure `main`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,16 +50,19 @@ GB_ALLOCATOR_PROC(heap_allocator_proc) {
|
||||
if (flags & gbAllocatorFlag_ClearToZero) {
|
||||
gb_zero_size(ptr, size);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case gbAllocation_Free: {
|
||||
free(old_memory);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case gbAllocation_Resize: {
|
||||
// ptr = realloc(old_memory, size);
|
||||
ptr = gb_default_resize_align(heap_allocator(), old_memory, old_size, size, alignment);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
// TODO(bill): *nix version that's decent
|
||||
case gbAllocation_Alloc: {
|
||||
@@ -68,15 +71,18 @@ GB_ALLOCATOR_PROC(heap_allocator_proc) {
|
||||
if (flags & gbAllocatorFlag_ClearToZero) {
|
||||
gb_zero_size(ptr, size);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case gbAllocation_Free: {
|
||||
free(old_memory);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case gbAllocation_Resize: {
|
||||
ptr = gb_default_resize_align(heap_allocator(), old_memory, old_size, size, alignment);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case gbAllocation_FreeAll:
|
||||
|
||||
@@ -270,7 +270,8 @@ ExactValue exact_value_to_integer(ExactValue v) {
|
||||
if (f == v.value_float) {
|
||||
return exact_value_i128(i);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Pointer:
|
||||
return exact_value_i64(cast(i64)cast(intptr)v.value_pointer);
|
||||
@@ -352,7 +353,8 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
|
||||
case ExactValue_Complex:
|
||||
return v;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Token_Sub: {
|
||||
switch (v.kind) {
|
||||
@@ -374,7 +376,8 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
|
||||
return exact_value_complex(-real, -imag);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Token_Xor: {
|
||||
i128 i = I128_ZERO;
|
||||
@@ -396,7 +399,8 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
|
||||
}
|
||||
|
||||
return exact_value_i128(i);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Token_Not: {
|
||||
switch (v.kind) {
|
||||
@@ -404,7 +408,8 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
|
||||
case ExactValue_Bool:
|
||||
return exact_value_bool(!v.value_bool);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
failure:
|
||||
@@ -521,7 +526,8 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
|
||||
}
|
||||
|
||||
return exact_value_i128(c);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Float: {
|
||||
f64 a = x.value_float;
|
||||
@@ -533,7 +539,8 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
|
||||
case Token_Quo: return exact_value_float(a / b);
|
||||
default: goto error;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Complex: {
|
||||
y = exact_value_to_complex(y);
|
||||
@@ -560,11 +567,13 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
|
||||
f64 s = c*c + d*d;
|
||||
real = (a*c + b*d)/s;
|
||||
imag = (b*c - a*d)/s;
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
default: goto error;
|
||||
}
|
||||
return exact_value_complex(real, imag);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_String: {
|
||||
if (op != Token_Add) goto error;
|
||||
@@ -577,7 +586,8 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
|
||||
gb_memmove(data, sx.text, sx.len);
|
||||
gb_memmove(data+sx.len, sy.text, sy.len);
|
||||
return exact_value_string(make_string(data, len));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
error:; // NOTE(bill): MSVC accepts this??? apparently you cannot declare variables immediately after labels...
|
||||
@@ -620,7 +630,8 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
|
||||
case Token_Gt: return a > b;
|
||||
case Token_GtEq: return a >= b;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Float: {
|
||||
f64 a = x.value_float;
|
||||
@@ -633,7 +644,8 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
|
||||
case Token_Gt: return cmp_f64(a, b) > 0;
|
||||
case Token_GtEq: return cmp_f64(a, b) >= 0;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Complex: {
|
||||
f64 a = x.value_complex.real;
|
||||
@@ -644,7 +656,8 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
|
||||
case Token_CmpEq: return cmp_f64(a, c) == 0 && cmp_f64(b, d) == 0;
|
||||
case Token_NotEq: return cmp_f64(a, c) != 0 || cmp_f64(b, d) != 0;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_String: {
|
||||
String a = x.value_string;
|
||||
@@ -658,7 +671,8 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
|
||||
case Token_Gt: return a > b;
|
||||
case Token_GtEq: return a >= b;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Type:
|
||||
switch (op) {
|
||||
|
||||
283
src/ir.cpp
283
src/ir.cpp
@@ -19,7 +19,7 @@ struct irModule {
|
||||
String layout;
|
||||
// String triple;
|
||||
|
||||
PtrSet<Entity *> min_dep_map;
|
||||
PtrSet<Entity *> min_dep_set;
|
||||
Map<irValue *> values; // Key: Entity *
|
||||
Map<irValue *> members; // Key: String
|
||||
Map<String> entity_names; // Key: Entity * of the typename
|
||||
@@ -623,7 +623,7 @@ Type *ir_instr_type(irInstr *instr) {
|
||||
return pt;
|
||||
}
|
||||
return nullptr;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -741,7 +741,8 @@ Array<irValue *> *ir_value_referrers(irValue *v) {
|
||||
case irInstr_Local:
|
||||
return &i->Local.referrers;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -2107,7 +2108,8 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
||||
irValue *z = ir_emit_arith(proc, Token_Mul, b, c, ft);
|
||||
irValue *w = ir_emit_arith(proc, Token_Mul, a, d, ft);
|
||||
imag = ir_emit_arith(proc, Token_Add, z, w, ft);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Token_Quo: {
|
||||
irValue *s1 = ir_emit_arith(proc, Token_Mul, c, c, ft);
|
||||
irValue *s2 = ir_emit_arith(proc, Token_Mul, d, d, ft);
|
||||
@@ -2122,7 +2124,8 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
||||
irValue *w = ir_emit_arith(proc, Token_Mul, a, d, ft);
|
||||
imag = ir_emit_arith(proc, Token_Sub, z, w, ft);
|
||||
imag = ir_emit_arith(proc, Token_Quo, imag, s, ft);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), real);
|
||||
@@ -2473,7 +2476,8 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
||||
case 0: result_type = ft; break;
|
||||
case 1: result_type = ft; break;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Type_Struct:
|
||||
@@ -2509,7 +2513,8 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
||||
case 0: result_type = gst->Struct.fields[0]->type; break;
|
||||
case 1: result_type = gst->Struct.fields[1]->type; break;
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
GB_PANIC("TODO(bill): struct_ev type: %s, %d", type_to_string(ir_type(s)), index);
|
||||
@@ -2558,7 +2563,8 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, irValue *e, Selection sel) {
|
||||
type = t_type_info_ptr;
|
||||
}
|
||||
e = ir_emit_struct_ep(proc, e, index);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Basic_string:
|
||||
e = ir_emit_struct_ep(proc, e, index);
|
||||
@@ -2924,12 +2930,14 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||
args[0] = value;
|
||||
return ir_emit_global_call(proc, "__gnu_h2f_ieee", args, 1);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||
args[0] = value;
|
||||
return ir_emit_global_call(proc, "__f16_to_f64", args, 1);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (dz == 2) {
|
||||
switch (sz) {
|
||||
@@ -2938,12 +2946,14 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||
args[0] = value;
|
||||
return ir_emit_global_call(proc, "__gnu_f2h_ieee", args, 1);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||
args[0] = value;
|
||||
return ir_emit_global_call(proc, "__truncdfhf2", args, 1);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3897,12 +3907,14 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
|
||||
}
|
||||
return ir_emit_source_code_location(proc, procedure, pos);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_type_info_of: {
|
||||
Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
|
||||
return ir_type_info(proc, t);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_len: {
|
||||
irValue *v = ir_build_expr(proc, ce->args[0]);
|
||||
@@ -3929,7 +3941,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
}
|
||||
|
||||
GB_PANIC("Unreachable");
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_cap: {
|
||||
irValue *v = ir_build_expr(proc, ce->args[0]);
|
||||
@@ -3956,7 +3969,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
|
||||
GB_PANIC("Unreachable");
|
||||
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
case BuiltinProc_new: {
|
||||
@@ -3993,7 +4007,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
ir_emit_store(proc, tag_ptr, ir_const_int(a, variant_index));
|
||||
}
|
||||
return v;
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case BuiltinProc_make: {
|
||||
@@ -4079,7 +4094,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
|
||||
return ir_emit_load(proc, array);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
case BuiltinProc_free: {
|
||||
@@ -4154,7 +4170,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||
args[0] = ptr;
|
||||
return ir_emit_global_call(proc, "free_ptr", args, 1);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
case BuiltinProc_reserve: {
|
||||
@@ -4190,7 +4207,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
} else {
|
||||
GB_PANIC("Unknown type for `reserve`");
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
case BuiltinProc_clear: {
|
||||
@@ -4217,7 +4235,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
GB_PANIC("TODO(bill): ir clear for `%s`", type_to_string(t));
|
||||
}
|
||||
return nullptr;
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
case BuiltinProc_append: {
|
||||
@@ -4327,7 +4346,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
return ir_emit_global_call(proc, "__slice_append", daa_args, 5);
|
||||
}
|
||||
return ir_emit_global_call(proc, "__dynamic_array_append", daa_args, 5);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
case BuiltinProc_delete: {
|
||||
@@ -4345,7 +4365,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
args[0] = ir_gen_map_header(proc, addr, map_type);
|
||||
args[1] = ir_gen_map_key(proc, key, key_type);
|
||||
return ir_emit_global_call(proc, "__dynamic_map_delete", args, 2);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case BuiltinProc_swizzle: {
|
||||
@@ -4374,7 +4395,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
ir_emit_comment(proc, str_lit("swizzle.end"));
|
||||
return ir_emit_load(proc, dst);
|
||||
// return ir_emit(proc, ir_instr_vector_shuffle(proc, vector, indices, index_count));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_complex: {
|
||||
ir_emit_comment(proc, str_lit("complex"));
|
||||
@@ -4389,20 +4411,23 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 1), imag);
|
||||
|
||||
return ir_emit_load(proc, dst);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_real: {
|
||||
ir_emit_comment(proc, str_lit("real"));
|
||||
irValue *val = ir_build_expr(proc, ce->args[0]);
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 0);
|
||||
return ir_emit_conv(proc, real, tv.type);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case BuiltinProc_imag: {
|
||||
ir_emit_comment(proc, str_lit("imag"));
|
||||
irValue *val = ir_build_expr(proc, ce->args[0]);
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 1);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_conj: {
|
||||
ir_emit_comment(proc, str_lit("conj"));
|
||||
@@ -4418,7 +4443,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), imag);
|
||||
}
|
||||
return ir_emit_load(proc, res);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
case BuiltinProc_slice_ptr: {
|
||||
@@ -4436,7 +4462,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
irValue *slice = ir_add_local_generated(proc, slice_type);
|
||||
ir_fill_slice(proc, slice, ptr, count, capacity);
|
||||
return ir_emit_load(proc, slice);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_slice_to_bytes: {
|
||||
ir_emit_comment(proc, str_lit("slice_to_bytes"));
|
||||
@@ -4455,7 +4482,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
capacity = ir_emit_arith(proc, Token_Mul, capacity, ir_const_int(proc->module->allocator, elem_size), t_int);
|
||||
ir_fill_slice(proc, slice, ptr, count, capacity);
|
||||
return ir_emit_load(proc, slice);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case BuiltinProc_expand_to_tuple: {
|
||||
@@ -4475,7 +4503,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
ir_emit_store(proc, ep, f);
|
||||
}
|
||||
return ir_emit_load(proc, tuple);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_min: {
|
||||
ir_emit_comment(proc, str_lit("min"));
|
||||
@@ -4484,7 +4513,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
irValue *y = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t);
|
||||
irValue *cond = ir_emit_comp(proc, Token_Lt, x, y);
|
||||
return ir_emit_select(proc, cond, x, y);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_max: {
|
||||
ir_emit_comment(proc, str_lit("max"));
|
||||
@@ -4493,7 +4523,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
irValue *y = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t);
|
||||
irValue *cond = ir_emit_comp(proc, Token_Gt, x, y);
|
||||
return ir_emit_select(proc, cond, x, y);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_abs: {
|
||||
ir_emit_comment(proc, str_lit("abs"));
|
||||
@@ -4514,7 +4545,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
irValue *cond = ir_emit_comp(proc, Token_Lt, x, zero);
|
||||
irValue *neg = ir_emit(proc, ir_instr_unary_op(proc, Token_Sub, x, t));
|
||||
return ir_emit_select(proc, cond, neg, x);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_clamp: {
|
||||
ir_emit_comment(proc, str_lit("clamp"));
|
||||
@@ -4523,7 +4555,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
ir_build_expr(proc, ce->args[0]),
|
||||
ir_build_expr(proc, ce->args[1]),
|
||||
ir_build_expr(proc, ce->args[2]));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GB_PANIC("Unhandled built-in procedure");
|
||||
@@ -4775,7 +4808,8 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||
irValue *right = ir_build_expr(proc, be->right);
|
||||
irValue *cmp = ir_emit_comp(proc, be->op.kind, left, right);
|
||||
return ir_emit_conv(proc, cmp, type);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Token_CmpAnd:
|
||||
case Token_CmpOr:
|
||||
@@ -5307,7 +5341,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
irValue *len = ir_const_int(a, t->Vector.count);
|
||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
return ir_addr(elem);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Array: {
|
||||
irValue *array = nullptr;
|
||||
@@ -5324,7 +5359,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
irValue *len = ir_const_int(a, t->Vector.count);
|
||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
return ir_addr(elem);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Slice: {
|
||||
irValue *slice = nullptr;
|
||||
@@ -5342,7 +5378,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
irValue *v = ir_emit_ptr_offset(proc, elem, index);
|
||||
return ir_addr(v);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_DynamicArray: {
|
||||
irValue *dynamic_array = nullptr;
|
||||
@@ -5360,7 +5397,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
irValue *v = ir_emit_ptr_offset(proc, elem, index);
|
||||
return ir_addr(v);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Type_Basic: { // Basic_string
|
||||
@@ -5384,7 +5422,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
|
||||
return ir_addr(ir_emit_ptr_offset(proc, elem, index));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
|
||||
@@ -5485,7 +5524,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
irValue *str = ir_add_local_generated(proc, t_string);
|
||||
ir_fill_string(proc, str, elem, len);
|
||||
return ir_addr(str);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GB_PANIC("Unknown slicable type");
|
||||
@@ -5544,7 +5584,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
ir_emit_store(proc, gep, ev);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Struct: {
|
||||
// TODO(bill): "constant" unions are not initialized constantly at the moment.
|
||||
@@ -5590,7 +5631,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
ir_emit_store(proc, gep, fv);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Map: {
|
||||
if (cl->elems.count == 0) {
|
||||
@@ -5611,7 +5653,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
irValue *value = ir_build_expr(proc, fv->value);
|
||||
ir_insert_dynamic_map_key_and_value(proc, v, type, key, value);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_DynamicArray: {
|
||||
if (cl->elems.count == 0) {
|
||||
@@ -5649,7 +5692,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
args[4] = ir_const_int(a, item_count);
|
||||
ir_emit_global_call(proc, "__dynamic_array_append", args, 5);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Array: {
|
||||
if (cl->elems.count > 0) {
|
||||
@@ -5667,7 +5711,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
ir_emit_store(proc, gep, ev);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Slice: {
|
||||
if (cl->elems.count > 0) {
|
||||
Type *elem_type = bt->Slice.elem;
|
||||
@@ -5695,7 +5740,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
irValue *count = ir_const_int(proc->module->allocator, slice->ConstantSlice.count);
|
||||
ir_fill_slice(proc, v, data, count, count);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Basic: {
|
||||
GB_ASSERT(is_type_any(bt));
|
||||
@@ -5814,7 +5860,7 @@ irValue *ir_build_cond(irProcedure *proc, AstNode *cond, irBlock *true_block, ir
|
||||
void ir_build_poly_proc(irProcedure *proc, AstNodeProcLit *pd, Entity *e) {
|
||||
GB_ASSERT(pd->body != nullptr);
|
||||
|
||||
if (ptr_set_exists(&proc->module->min_dep_map, e) == false) {
|
||||
if (ptr_set_exists(&proc->module->min_dep_set, e) == false) {
|
||||
// NOTE(bill): Nothing depends upon it so doesn't need to be built
|
||||
return;
|
||||
}
|
||||
@@ -5876,7 +5922,7 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!polymorphic_struct && !ptr_set_exists(&proc->module->min_dep_map, e)) {
|
||||
if (!polymorphic_struct && !ptr_set_exists(&proc->module->min_dep_set, e)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -5905,7 +5951,7 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) {
|
||||
auto procs = *found;
|
||||
for_array(i, procs) {
|
||||
Entity *e = procs[i];
|
||||
if (!ptr_set_exists(&proc->module->min_dep_map, e)) {
|
||||
if (!ptr_set_exists(&proc->module->min_dep_set, e)) {
|
||||
continue;
|
||||
}
|
||||
DeclInfo *d = decl_info_of_entity(info, e);
|
||||
@@ -6061,19 +6107,23 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir
|
||||
switch (expr_type->kind) {
|
||||
case Type_Array: {
|
||||
val = ir_emit_load(proc, ir_emit_array_ep(proc, expr, idx));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Vector: {
|
||||
val = ir_emit_load(proc, ir_emit_array_ep(proc, expr, idx));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Slice: {
|
||||
irValue *elem = ir_slice_elem(proc, expr);
|
||||
val = ir_emit_load(proc, ir_emit_ptr_offset(proc, elem, idx));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_DynamicArray: {
|
||||
irValue *elem = ir_emit_struct_ep(proc, expr, 0);
|
||||
elem = ir_emit_load(proc, elem);
|
||||
val = ir_emit_load(proc, ir_emit_ptr_offset(proc, elem, idx));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Map: {
|
||||
irValue *entries = ir_emit_struct_ep(proc, expr, 1);
|
||||
irValue *elem = ir_emit_struct_ep(proc, entries, 0);
|
||||
@@ -6093,7 +6143,8 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir
|
||||
}
|
||||
|
||||
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GB_PANIC("Cannot do range_indexed of %s", type_to_string(expr_type));
|
||||
break;
|
||||
@@ -6393,7 +6444,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// NOTE(bill): Only 1 += 1 is allowed, no tuples
|
||||
@@ -6403,7 +6455,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
irAddr lhs = ir_build_addr(proc, as->lhs[0]);
|
||||
irValue *value = ir_build_expr(proc, as->rhs[0]);
|
||||
ir_build_assign_op(proc, lhs, value, cast(TokenKind)op);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
@@ -6726,7 +6779,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
irValue *entries_ptr = ir_emit_struct_ep(proc, map, 1);
|
||||
irValue *count_ptr = ir_emit_struct_ep(proc, entries_ptr, 1);
|
||||
ir_build_range_indexed(proc, map, val_type, count_ptr, &val, &index, &loop, &done);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Array: {
|
||||
irValue *count_ptr = nullptr;
|
||||
irValue *array = ir_build_addr(proc, rs->expr).addr;
|
||||
@@ -6736,7 +6790,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
count_ptr = ir_add_local_generated(proc, t_int);
|
||||
ir_emit_store(proc, count_ptr, ir_const_int(proc->module->allocator, et->Array.count));
|
||||
ir_build_range_indexed(proc, array, val_type, count_ptr, &val, &index, &loop, &done);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Vector: {
|
||||
irValue *count_ptr = nullptr;
|
||||
irValue *vector = ir_build_addr(proc, rs->expr).addr;
|
||||
@@ -6746,7 +6801,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
count_ptr = ir_add_local_generated(proc, t_int);
|
||||
ir_emit_store(proc, count_ptr, ir_const_int(proc->module->allocator, et->Vector.count));
|
||||
ir_build_range_indexed(proc, vector, val_type, count_ptr, &val, &index, &loop, &done);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_DynamicArray: {
|
||||
irValue *count_ptr = nullptr;
|
||||
irValue *array = ir_build_addr(proc, rs->expr).addr;
|
||||
@@ -6755,7 +6811,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
}
|
||||
count_ptr = ir_emit_struct_ep(proc, array, 1);
|
||||
ir_build_range_indexed(proc, array, val_type, count_ptr, &val, &index, &loop, &done);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Slice: {
|
||||
irValue *count_ptr = nullptr;
|
||||
irValue *slice = ir_build_expr(proc, rs->expr);
|
||||
@@ -6767,7 +6824,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
ir_emit_store(proc, count_ptr, ir_slice_count(proc, slice));
|
||||
}
|
||||
ir_build_range_indexed(proc, slice, val_type, count_ptr, &val, &index, &loop, &done);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Basic: {
|
||||
irValue *string = ir_build_expr(proc, rs->expr);
|
||||
if (is_type_pointer(ir_type(string))) {
|
||||
@@ -6779,7 +6837,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
string = ir_emit_load(proc, s);
|
||||
}
|
||||
ir_build_range_string(proc, string, val_type, &val, &index, &loop, &done);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GB_PANIC("Cannot range over %s", type_to_string(expr_type));
|
||||
break;
|
||||
@@ -6812,18 +6871,18 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
ir_start_block(proc, done);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, MatchStmt, node);
|
||||
ir_emit_comment(proc, str_lit("MatchStmt"));
|
||||
if (ms->init != nullptr) {
|
||||
ir_build_stmt(proc, ms->init);
|
||||
case_ast_node(ss, SwitchStmt, node);
|
||||
ir_emit_comment(proc, str_lit("SwitchStmt"));
|
||||
if (ss->init != nullptr) {
|
||||
ir_build_stmt(proc, ss->init);
|
||||
}
|
||||
irValue *tag = v_true;
|
||||
if (ms->tag != nullptr) {
|
||||
tag = ir_build_expr(proc, ms->tag);
|
||||
if (ss->tag != nullptr) {
|
||||
tag = ir_build_expr(proc, ss->tag);
|
||||
}
|
||||
irBlock *done = ir_new_block(proc, node, "match.done"); // NOTE(bill): Append later
|
||||
irBlock *done = ir_new_block(proc, node, "switch.done"); // NOTE(bill): Append later
|
||||
|
||||
ast_node(body, BlockStmt, ms->body);
|
||||
ast_node(body, BlockStmt, ss->body);
|
||||
|
||||
Array<AstNode *> default_stmts = {};
|
||||
irBlock *default_fall = nullptr;
|
||||
@@ -6841,9 +6900,9 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
|
||||
if (body == nullptr) {
|
||||
if (cc->list.count == 0) {
|
||||
body = ir_new_block(proc, clause, "match.dflt.body");
|
||||
body = ir_new_block(proc, clause, "switch.dflt.body");
|
||||
} else {
|
||||
body = ir_new_block(proc, clause, "match.case.body");
|
||||
body = ir_new_block(proc, clause, "switch.case.body");
|
||||
}
|
||||
}
|
||||
if (append_fall && body == fall) {
|
||||
@@ -6853,7 +6912,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
fall = done;
|
||||
if (i+1 < case_count) {
|
||||
append_fall = true;
|
||||
fall = ir_new_block(proc, clause, "match.fall.body");
|
||||
fall = ir_new_block(proc, clause, "switch.fall.body");
|
||||
}
|
||||
|
||||
if (cc->list.count == 0) {
|
||||
@@ -6867,7 +6926,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
irBlock *next_cond = nullptr;
|
||||
for_array(j, cc->list) {
|
||||
AstNode *expr = unparen_expr(cc->list[j]);
|
||||
next_cond = ir_new_block(proc, clause, "match.case.next");
|
||||
next_cond = ir_new_block(proc, clause, "switch.case.next");
|
||||
irValue *cond = v_false;
|
||||
if (is_ast_node_a_range(expr)) {
|
||||
ast_node(ie, BinaryExpr, expr);
|
||||
@@ -6891,7 +6950,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
}
|
||||
ir_start_block(proc, body);
|
||||
|
||||
ir_push_target_list(proc, ms->label, done, nullptr, fall);
|
||||
ir_push_target_list(proc, ss->label, done, nullptr, fall);
|
||||
ir_open_scope(proc);
|
||||
ir_build_stmt_list(proc, cc->stmts);
|
||||
ir_close_scope(proc, irDeferExit_Default, body);
|
||||
@@ -6906,7 +6965,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
ir_emit_jump(proc, default_block);
|
||||
ir_start_block(proc, default_block);
|
||||
|
||||
ir_push_target_list(proc, ms->label, done, nullptr, default_fall);
|
||||
ir_push_target_list(proc, ss->label, done, nullptr, default_fall);
|
||||
ir_open_scope(proc);
|
||||
ir_build_stmt_list(proc, default_stmts);
|
||||
ir_close_scope(proc, irDeferExit_Default, default_block);
|
||||
@@ -6918,11 +6977,11 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(ms, TypeMatchStmt, node);
|
||||
ir_emit_comment(proc, str_lit("TypeMatchStmt"));
|
||||
case_ast_node(ss, TypeSwitchStmt, node);
|
||||
ir_emit_comment(proc, str_lit("TypeSwitchStmt"));
|
||||
gbAllocator allocator = proc->module->allocator;
|
||||
|
||||
ast_node(as, AssignStmt, ms->tag);
|
||||
ast_node(as, AssignStmt, ss->tag);
|
||||
GB_ASSERT(as->lhs.count == 1);
|
||||
GB_ASSERT(as->rhs.count == 1);
|
||||
|
||||
@@ -6948,15 +7007,15 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
union_data = ir_emit_conv(proc, parent_ptr, t_rawptr);
|
||||
}
|
||||
|
||||
irBlock *start_block = ir_new_block(proc, node, "typematch.case.first");
|
||||
irBlock *start_block = ir_new_block(proc, node, "typeswitch.case.first");
|
||||
ir_emit_jump(proc, start_block);
|
||||
ir_start_block(proc, start_block);
|
||||
|
||||
// NOTE(bill): Append this later
|
||||
irBlock *done = ir_new_block(proc, node, "typematch.done");
|
||||
irBlock *done = ir_new_block(proc, node, "typeswitch.done");
|
||||
AstNode *default_ = nullptr;
|
||||
|
||||
ast_node(body, BlockStmt, ms->body);
|
||||
ast_node(body, BlockStmt, ss->body);
|
||||
|
||||
gb_local_persist i32 weird_count = 0;
|
||||
|
||||
@@ -6968,11 +7027,11 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
irBlock *body = ir_new_block(proc, clause, "typematch.body");
|
||||
irBlock *body = ir_new_block(proc, clause, "typeswitch.body");
|
||||
irBlock *next = nullptr;
|
||||
Type *case_type = nullptr;
|
||||
for_array(type_index, cc->list) {
|
||||
next = ir_new_block(proc, nullptr, "typematch.next");
|
||||
next = ir_new_block(proc, nullptr, "typeswitch.next");
|
||||
case_type = type_of_expr(proc->module->info, cc->list[type_index]);
|
||||
irValue *cond = nullptr;
|
||||
if (match_type_kind == MatchType_Union) {
|
||||
@@ -7028,13 +7087,13 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
}
|
||||
|
||||
ir_store_type_case_implicit(proc, clause, value);
|
||||
ir_type_case_body(proc, ms->label, clause, body, done);
|
||||
ir_type_case_body(proc, ss->label, clause, body, done);
|
||||
ir_start_block(proc, next);
|
||||
}
|
||||
|
||||
if (default_ != nullptr) {
|
||||
ir_store_type_case_implicit(proc, default_, parent_value);
|
||||
ir_type_case_body(proc, ms->label, default_, proc->curr_block, done);
|
||||
ir_type_case_body(proc, ss->label, default_, proc->curr_block, done);
|
||||
} else {
|
||||
ir_emit_jump(proc, done);
|
||||
}
|
||||
@@ -7635,7 +7694,7 @@ void ir_gen_tree(irGen *s) {
|
||||
array_init(&global_variables, m->tmp_allocator, global_variable_max_count);
|
||||
|
||||
m->entry_point_entity = entry_point;
|
||||
m->min_dep_map = info->minimum_dependency_map;
|
||||
m->min_dep_set = info->minimum_dependency_set;
|
||||
|
||||
for_array(i, info->variable_init_order) {
|
||||
DeclInfo *d = info->variable_init_order[i];
|
||||
@@ -7647,7 +7706,7 @@ void ir_gen_tree(irGen *s) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ptr_set_exists(&m->min_dep_map, e)) {
|
||||
if (!ptr_set_exists(&m->min_dep_set, e)) {
|
||||
continue;
|
||||
}
|
||||
DeclInfo *decl = decl_info_of_entity(info, e);
|
||||
@@ -7717,7 +7776,7 @@ void ir_gen_tree(irGen *s) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!polymorphic_struct && !ptr_set_exists(&m->min_dep_map, e)) {
|
||||
if (!polymorphic_struct && !ptr_set_exists(&m->min_dep_set, e)) {
|
||||
// NOTE(bill): Nothing depends upon it so doesn't need to be built
|
||||
continue;
|
||||
}
|
||||
@@ -7766,7 +7825,8 @@ void ir_gen_tree(irGen *s) {
|
||||
if (map_get(&m->members, hash_name) == nullptr) {
|
||||
multi_map_insert(&m->members, hash_name, p);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8068,7 +8128,8 @@ void ir_gen_tree(irGen *s) {
|
||||
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), name);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), gtip);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Basic:
|
||||
ir_emit_comment(proc, str_lit("TypeInfoBasic"));
|
||||
@@ -8092,7 +8153,8 @@ void ir_gen_tree(irGen *s) {
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_integer_ptr);
|
||||
irValue *is_signed = ir_const_bool(a, (t->Basic.flags & BasicFlag_Unsigned) == 0);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), is_signed);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Basic_rune:
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_rune_ptr);
|
||||
@@ -8129,7 +8191,8 @@ void ir_gen_tree(irGen *s) {
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_pointer_ptr);
|
||||
irValue *gep = ir_get_type_info_ptr(proc, t->Pointer.elem);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Array: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoArray"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_array_ptr);
|
||||
@@ -8143,7 +8206,8 @@ void ir_gen_tree(irGen *s) {
|
||||
irValue *count = ir_emit_struct_ep(proc, tag, 2);
|
||||
ir_emit_store(proc, count, ir_const_int(a, t->Array.count));
|
||||
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_DynamicArray: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoDynamicArray"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_dynamic_array_ptr);
|
||||
@@ -8153,7 +8217,8 @@ void ir_gen_tree(irGen *s) {
|
||||
isize ez = type_size_of(a, t->DynamicArray.elem);
|
||||
irValue *elem_size = ir_emit_struct_ep(proc, tag, 1);
|
||||
ir_emit_store(proc, elem_size, ir_const_int(a, ez));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Slice: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoSlice"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_slice_ptr);
|
||||
@@ -8163,7 +8228,8 @@ void ir_gen_tree(irGen *s) {
|
||||
isize ez = type_size_of(a, t->Slice.elem);
|
||||
irValue *elem_size = ir_emit_struct_ep(proc, tag, 1);
|
||||
ir_emit_store(proc, elem_size, ir_const_int(a, ez));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Vector: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoVector"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_vector_ptr);
|
||||
@@ -8174,7 +8240,8 @@ void ir_gen_tree(irGen *s) {
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), ir_const_int(a, ez));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), ir_const_int(a, t->Vector.count));
|
||||
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Proc: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoProc"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_procedure_ptr);
|
||||
@@ -8194,7 +8261,8 @@ void ir_gen_tree(irGen *s) {
|
||||
ir_emit_store(proc, convention, ir_const_int(a, t->Proc.calling_convention));
|
||||
|
||||
// TODO(bill): TypeInfo for procedures
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Tuple: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoTuple"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_tuple_ptr);
|
||||
@@ -8219,7 +8287,8 @@ void ir_gen_tree(irGen *s) {
|
||||
irValue *count = ir_const_int(a, t->Tuple.variables.count);
|
||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types, count, count);
|
||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count, count);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Enum:
|
||||
ir_emit_comment(proc, str_lit("TypeInfoEnum"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_enum_ptr);
|
||||
@@ -8293,7 +8362,8 @@ void ir_gen_tree(irGen *s) {
|
||||
ir_emit_store(proc, tag_offset_ptr, ir_const_int(a, tag_offset));
|
||||
}
|
||||
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Struct: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoStruct"));
|
||||
@@ -8347,7 +8417,8 @@ void ir_gen_tree(irGen *s) {
|
||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, cv, cv);
|
||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, cv, cv);
|
||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 3), memory_usings, cv, cv);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case Type_Map: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoMap"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_map_ptr);
|
||||
@@ -8360,7 +8431,8 @@ void ir_gen_tree(irGen *s) {
|
||||
ir_emit_store(proc, key, ir_get_type_info_ptr(proc, t->Map.key));
|
||||
ir_emit_store(proc, value, ir_get_type_info_ptr(proc, t->Map.value));
|
||||
ir_emit_store(proc, generated_struct, ir_get_type_info_ptr(proc, t->Map.generated_struct_type));
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_BitField: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoBitField"));
|
||||
@@ -8403,7 +8475,8 @@ void ir_gen_tree(irGen *s) {
|
||||
irValue *offset_array_elem = ir_array_elem(proc, offset_array);
|
||||
ir_fill_slice(proc, offsets, offset_array_elem, v_count, v_count);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -281,14 +281,14 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
|
||||
Array<AstNode *> list; \
|
||||
Array<AstNode *> stmts; \
|
||||
}) \
|
||||
AST_NODE_KIND(MatchStmt, "match statement", struct { \
|
||||
AST_NODE_KIND(SwitchStmt, "switch statement", struct { \
|
||||
Token token; \
|
||||
AstNode *label; \
|
||||
AstNode *init; \
|
||||
AstNode *tag; \
|
||||
AstNode *body; \
|
||||
}) \
|
||||
AST_NODE_KIND(TypeMatchStmt, "type match statement", struct { \
|
||||
AST_NODE_KIND(TypeSwitchStmt, "type switch statement", struct { \
|
||||
Token token; \
|
||||
AstNode *label; \
|
||||
AstNode *tag; \
|
||||
@@ -575,8 +575,8 @@ Token ast_node_token(AstNode *node) {
|
||||
case AstNode_ForStmt: return node->ForStmt.token;
|
||||
case AstNode_RangeStmt: return node->RangeStmt.token;
|
||||
case AstNode_CaseClause: return node->CaseClause.token;
|
||||
case AstNode_MatchStmt: return node->MatchStmt.token;
|
||||
case AstNode_TypeMatchStmt: return node->TypeMatchStmt.token;
|
||||
case AstNode_SwitchStmt: return node->SwitchStmt.token;
|
||||
case AstNode_TypeSwitchStmt: return node->TypeSwitchStmt.token;
|
||||
case AstNode_DeferStmt: return node->DeferStmt.token;
|
||||
case AstNode_BranchStmt: return node->BranchStmt.token;
|
||||
case AstNode_UsingStmt: return node->UsingStmt.token;
|
||||
@@ -783,16 +783,16 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
|
||||
n->CaseClause.list = clone_ast_node_array(a, n->CaseClause.list);
|
||||
n->CaseClause.stmts = clone_ast_node_array(a, n->CaseClause.stmts);
|
||||
break;
|
||||
case AstNode_MatchStmt:
|
||||
n->MatchStmt.label = clone_ast_node(a, n->MatchStmt.label);
|
||||
n->MatchStmt.init = clone_ast_node(a, n->MatchStmt.init);
|
||||
n->MatchStmt.tag = clone_ast_node(a, n->MatchStmt.tag);
|
||||
n->MatchStmt.body = clone_ast_node(a, n->MatchStmt.body);
|
||||
case AstNode_SwitchStmt:
|
||||
n->SwitchStmt.label = clone_ast_node(a, n->SwitchStmt.label);
|
||||
n->SwitchStmt.init = clone_ast_node(a, n->SwitchStmt.init);
|
||||
n->SwitchStmt.tag = clone_ast_node(a, n->SwitchStmt.tag);
|
||||
n->SwitchStmt.body = clone_ast_node(a, n->SwitchStmt.body);
|
||||
break;
|
||||
case AstNode_TypeMatchStmt:
|
||||
n->TypeMatchStmt.label = clone_ast_node(a, n->TypeMatchStmt.label);
|
||||
n->TypeMatchStmt.tag = clone_ast_node(a, n->TypeMatchStmt.tag);
|
||||
n->TypeMatchStmt.body = clone_ast_node(a, n->TypeMatchStmt.body);
|
||||
case AstNode_TypeSwitchStmt:
|
||||
n->TypeSwitchStmt.label = clone_ast_node(a, n->TypeSwitchStmt.label);
|
||||
n->TypeSwitchStmt.tag = clone_ast_node(a, n->TypeSwitchStmt.tag);
|
||||
n->TypeSwitchStmt.body = clone_ast_node(a, n->TypeSwitchStmt.body);
|
||||
break;
|
||||
case AstNode_DeferStmt:
|
||||
n->DeferStmt.stmt = clone_ast_node(a, n->DeferStmt.stmt);
|
||||
@@ -1266,20 +1266,20 @@ AstNode *ast_range_stmt(AstFile *f, Token token, AstNode *value, AstNode *index,
|
||||
}
|
||||
|
||||
AstNode *ast_match_stmt(AstFile *f, Token token, AstNode *init, AstNode *tag, AstNode *body) {
|
||||
AstNode *result = make_ast_node(f, AstNode_MatchStmt);
|
||||
result->MatchStmt.token = token;
|
||||
result->MatchStmt.init = init;
|
||||
result->MatchStmt.tag = tag;
|
||||
result->MatchStmt.body = body;
|
||||
AstNode *result = make_ast_node(f, AstNode_SwitchStmt);
|
||||
result->SwitchStmt.token = token;
|
||||
result->SwitchStmt.init = init;
|
||||
result->SwitchStmt.tag = tag;
|
||||
result->SwitchStmt.body = body;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *ast_type_match_stmt(AstFile *f, Token token, AstNode *tag, AstNode *body) {
|
||||
AstNode *result = make_ast_node(f, AstNode_TypeMatchStmt);
|
||||
result->TypeMatchStmt.token = token;
|
||||
result->TypeMatchStmt.tag = tag;
|
||||
result->TypeMatchStmt.body = body;
|
||||
AstNode *result = make_ast_node(f, AstNode_TypeSwitchStmt);
|
||||
result->TypeSwitchStmt.token = token;
|
||||
result->TypeSwitchStmt.tag = tag;
|
||||
result->TypeSwitchStmt.body = body;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1774,7 +1774,7 @@ void fix_advance_to_next_stmt(AstFile *f) {
|
||||
case Token_for:
|
||||
case Token_when:
|
||||
case Token_return:
|
||||
case Token_match:
|
||||
case Token_switch:
|
||||
case Token_defer:
|
||||
case Token_asm:
|
||||
case Token_using:
|
||||
@@ -1823,12 +1823,15 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
}
|
||||
|
||||
switch (s->kind) {
|
||||
case AstNode_EmptyStmt:
|
||||
return true;
|
||||
|
||||
case AstNode_IfStmt:
|
||||
case AstNode_WhenStmt:
|
||||
case AstNode_ForStmt:
|
||||
case AstNode_RangeStmt:
|
||||
case AstNode_MatchStmt:
|
||||
case AstNode_TypeMatchStmt:
|
||||
case AstNode_SwitchStmt:
|
||||
case AstNode_TypeSwitchStmt:
|
||||
return true;
|
||||
|
||||
case AstNode_PointerType:
|
||||
@@ -1842,6 +1845,11 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
case AstNode_ProcLit:
|
||||
return s->ProcLit.body != nullptr;
|
||||
|
||||
case AstNode_ImportDecl:
|
||||
case AstNode_ExportDecl:
|
||||
case AstNode_ForeignLibraryDecl:
|
||||
return true;
|
||||
|
||||
case AstNode_ValueDecl:
|
||||
if (s->ValueDecl.is_mutable) {
|
||||
return false;
|
||||
@@ -3176,7 +3184,7 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) {
|
||||
TokenKind next = look_ahead_token_kind(f, 1);
|
||||
switch (next) {
|
||||
case Token_for:
|
||||
case Token_match: {
|
||||
case Token_switch: {
|
||||
expect_token_after(f, Token_Colon, "identifier list");
|
||||
AstNode *name = lhs[0];
|
||||
AstNode *label = ast_label_decl(f, ast_node_token(name), name);
|
||||
@@ -3185,8 +3193,8 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) {
|
||||
switch (stmt->kind) {
|
||||
_SET_LABEL(ForStmt, label);
|
||||
_SET_LABEL(RangeStmt, label);
|
||||
_SET_LABEL(MatchStmt, label);
|
||||
_SET_LABEL(TypeMatchStmt, label);
|
||||
_SET_LABEL(SwitchStmt, label);
|
||||
_SET_LABEL(TypeSwitchStmt, label);
|
||||
default:
|
||||
syntax_error(token, "Labels can only be applied to a loop or match statement");
|
||||
break;
|
||||
@@ -4238,7 +4246,7 @@ AstNode *parse_match_stmt(AstFile *f) {
|
||||
return ast_bad_stmt(f, f->curr_token, f->curr_token);
|
||||
}
|
||||
|
||||
Token token = expect_token(f, Token_match);
|
||||
Token token = expect_token(f, Token_switch);
|
||||
AstNode *init = nullptr;
|
||||
AstNode *tag = nullptr;
|
||||
AstNode *body = nullptr;
|
||||
@@ -4366,12 +4374,15 @@ AstNode *parse_import_decl(AstFile *f, bool is_using) {
|
||||
cond = parse_expr(f, false);
|
||||
}
|
||||
|
||||
expect_semicolon(f, nullptr);
|
||||
AstNode *s = nullptr;
|
||||
if (f->curr_proc != nullptr) {
|
||||
syntax_error(import_name, "You cannot use `import` within a procedure. This must be done at the file scope");
|
||||
return ast_bad_decl(f, import_name, file_path);
|
||||
s = ast_bad_decl(f, import_name, file_path);
|
||||
} else {
|
||||
s = ast_import_decl(f, token, is_using, file_path, import_name, cond, docs, f->line_comment);
|
||||
}
|
||||
return ast_import_decl(f, token, is_using, file_path, import_name, cond, docs, f->line_comment);
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
AstNode *parse_export_decl(AstFile *f) {
|
||||
@@ -4383,12 +4394,16 @@ AstNode *parse_export_decl(AstFile *f) {
|
||||
if (allow_token(f, Token_when)) {
|
||||
cond = parse_expr(f, false);
|
||||
}
|
||||
expect_semicolon(f, nullptr);
|
||||
|
||||
AstNode *s = nullptr;
|
||||
if (f->curr_proc != nullptr) {
|
||||
syntax_error(token, "You cannot use `export` within a procedure. This must be done at the file scope");
|
||||
return ast_bad_decl(f, token, file_path);
|
||||
s = ast_bad_decl(f, token, file_path);
|
||||
} else {
|
||||
s = ast_export_decl(f, token, file_path, cond, docs, f->line_comment);
|
||||
}
|
||||
return ast_export_decl(f, token, file_path, cond, docs, f->line_comment);
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
AstNode *parse_foreign_decl(AstFile *f) {
|
||||
@@ -4425,14 +4440,16 @@ AstNode *parse_foreign_decl(AstFile *f) {
|
||||
cond = parse_expr(f, false);
|
||||
}
|
||||
|
||||
expect_semicolon(f, nullptr);
|
||||
|
||||
AstNode *s = nullptr;
|
||||
if (f->curr_proc != nullptr) {
|
||||
syntax_error(lib_name, "You cannot use foreign_system_library within a procedure. This must be done at the file scope");
|
||||
return ast_bad_decl(f, lib_name, file_path);
|
||||
s = ast_bad_decl(f, lib_name, file_path);
|
||||
} else {
|
||||
s = ast_foreign_library_decl(f, token, file_path, lib_name, cond, docs, f->line_comment);
|
||||
}
|
||||
|
||||
return ast_foreign_library_decl(f, token, file_path, lib_name, cond, docs, f->line_comment);
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -4478,7 +4495,7 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
case Token_if: return parse_if_stmt(f);
|
||||
case Token_when: return parse_when_stmt(f);
|
||||
case Token_for: return parse_for_stmt(f);
|
||||
case Token_match: return parse_match_stmt(f);
|
||||
case Token_switch: return parse_match_stmt(f);
|
||||
case Token_defer: return parse_defer_stmt(f);
|
||||
case Token_asm: return parse_asm_stmt(f);
|
||||
case Token_return: return parse_return_stmt(f);
|
||||
|
||||
10
src/ssa.cpp
10
src/ssa.cpp
@@ -2138,12 +2138,12 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
|
||||
GB_PANIC("TODO: RangeStmt");
|
||||
case_end;
|
||||
|
||||
case_ast_node(rs, MatchStmt, node);
|
||||
GB_PANIC("TODO: MatchStmt");
|
||||
case_ast_node(rs, SwitchStmt, node);
|
||||
GB_PANIC("TODO: SwitchStmt");
|
||||
case_end;
|
||||
|
||||
case_ast_node(rs, TypeMatchStmt, node);
|
||||
GB_PANIC("TODO: TypeMatchStmt");
|
||||
case_ast_node(rs, TypeSwitchStmt, node);
|
||||
GB_PANIC("TODO: TypeSwitchStmt");
|
||||
case_end;
|
||||
|
||||
case_ast_node(bs, BranchStmt, node);
|
||||
@@ -2445,7 +2445,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
|
||||
|
||||
|
||||
m.entry_point_entity = entry_point;
|
||||
m.min_dep_map = generate_minimum_dependency_map(info, entry_point);
|
||||
m.min_dep_map = generate_minimum_dependency_set(info, entry_point);
|
||||
|
||||
for_array(i, info->entities.entries) {
|
||||
auto *entry = &info->entities.entries[i];
|
||||
|
||||
@@ -94,7 +94,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||
TOKEN_KIND(Token_if, "if"), \
|
||||
TOKEN_KIND(Token_else, "else"), \
|
||||
TOKEN_KIND(Token_for, "for"), \
|
||||
TOKEN_KIND(Token_match, "match"), \
|
||||
TOKEN_KIND(Token_switch, "switch"), \
|
||||
TOKEN_KIND(Token_in, "in"), \
|
||||
TOKEN_KIND(Token_do, "do"), \
|
||||
TOKEN_KIND(Token_case, "case"), \
|
||||
|
||||
Reference in New Issue
Block a user