mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
This commit is contained in:
+38
-39
@@ -10,17 +10,28 @@
|
|||||||
#import ht "http_test.odin";
|
#import ht "http_test.odin";
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
|
{
|
||||||
|
Fruit :: enum {
|
||||||
|
APPLE,
|
||||||
|
BANANA,
|
||||||
|
COCONUT,
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.println(Fruit.names);
|
||||||
|
}
|
||||||
|
|
||||||
|
when false {
|
||||||
{
|
{
|
||||||
m: map[f32]int;
|
m: map[f32]int;
|
||||||
reserve(^m, 16);
|
reserve(m, 16);
|
||||||
defer free(m);
|
defer free(m);
|
||||||
|
|
||||||
m[1.0] = 1278;
|
m[1.0] = 1278;
|
||||||
m[2.0] = 7643;
|
m[2.0] = 7643;
|
||||||
m[3.0] = 564;
|
m[3.0] = 564;
|
||||||
c := m[3.0];
|
|
||||||
_, ok := m[3.0];
|
_, ok := m[3.0];
|
||||||
// assert(ok && c == 564);
|
c := m[3.0];
|
||||||
|
assert(ok && c == 564);
|
||||||
|
|
||||||
fmt.print("map[");
|
fmt.print("map[");
|
||||||
i := 0;
|
i := 0;
|
||||||
@@ -28,7 +39,7 @@ main :: proc() {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
fmt.print(", ");
|
fmt.print(", ");
|
||||||
}
|
}
|
||||||
fmt.printf("%f=%v", key, val);
|
fmt.printf("%v=%v", key, val);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
fmt.println("]");
|
fmt.println("]");
|
||||||
@@ -48,48 +59,36 @@ main :: proc() {
|
|||||||
fmt.println(m);
|
fmt.println(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fm: map[128, int]f32;
|
|
||||||
|
|
||||||
/*
|
|
||||||
{
|
{
|
||||||
sig: u32;
|
fmt.println("Hellope!");
|
||||||
x := __cpuid(0, ^sig);
|
|
||||||
fmt.println(sig, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
x: [dynamic]f64;
|
||||||
|
reserve(x, 16);
|
||||||
|
defer free(x);
|
||||||
|
append(x, 2_000_000.500_000, 3, 5, 7);
|
||||||
|
|
||||||
|
for p, i in x {
|
||||||
|
if i > 0 { fmt.print(", "); }
|
||||||
|
fmt.print(p);
|
||||||
|
}
|
||||||
|
fmt.println();
|
||||||
|
|
||||||
i: int;
|
{
|
||||||
|
Vec3 :: [vector 3]f32;
|
||||||
|
|
||||||
fmt.println("Hellope!");
|
x := Vec3{1, 2, 3};
|
||||||
|
y := Vec3{4, 5, 6};
|
||||||
|
fmt.println(x < y);
|
||||||
|
fmt.println(x + y);
|
||||||
|
fmt.println(x - y);
|
||||||
|
fmt.println(x * y);
|
||||||
|
fmt.println(x / y);
|
||||||
|
|
||||||
x: [dynamic]f64;
|
for i in x {
|
||||||
defer free(x);
|
fmt.println(i);
|
||||||
append(^x, 2_000_000.500_000, 3, 5, 7);
|
}
|
||||||
|
|
||||||
for p, i in x {
|
|
||||||
if i > 0 { fmt.print(", "); }
|
|
||||||
fmt.print(p);
|
|
||||||
}
|
|
||||||
fmt.println();
|
|
||||||
|
|
||||||
{
|
|
||||||
Vec3 :: [vector 3]f32;
|
|
||||||
|
|
||||||
x := Vec3{1, 2, 3};
|
|
||||||
y := Vec3{4, 5, 6};
|
|
||||||
fmt.println(x < y);
|
|
||||||
fmt.println(x + y);
|
|
||||||
fmt.println(x - y);
|
|
||||||
fmt.println(x * y);
|
|
||||||
fmt.println(x / y);
|
|
||||||
|
|
||||||
for i in x {
|
|
||||||
fmt.println(i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
#foreign_system_library ws2 "Ws2_32.lib" when ODIN_OS == "windows";
|
#foreign_system_library ws2 "Ws2_32.lib" when ODIN_OS == "windows";
|
||||||
|
|
||||||
|
|
||||||
SOCKET :: type uint;
|
SOCKET :: #type uint;
|
||||||
INVALID_SOCKET :: ~(cast(SOCKET)0);
|
INVALID_SOCKET :: ~(cast(SOCKET)0);
|
||||||
|
|
||||||
AF :: enum i32 {
|
AF :: enum i32 {
|
||||||
|
|||||||
+25
-22
@@ -52,15 +52,12 @@ Type_Info :: union {
|
|||||||
Float: struct #ordered {
|
Float: struct #ordered {
|
||||||
size: int, // in bytes
|
size: int, // in bytes
|
||||||
},
|
},
|
||||||
Any: struct #ordered {},
|
|
||||||
String: struct #ordered {},
|
String: struct #ordered {},
|
||||||
Boolean: struct #ordered {},
|
Boolean: struct #ordered {},
|
||||||
|
Any: struct #ordered {},
|
||||||
Pointer: struct #ordered {
|
Pointer: struct #ordered {
|
||||||
elem: ^Type_Info, // nil -> rawptr
|
elem: ^Type_Info, // nil -> rawptr
|
||||||
},
|
},
|
||||||
Maybe: struct #ordered {
|
|
||||||
elem: ^Type_Info,
|
|
||||||
},
|
|
||||||
Procedure: struct #ordered {
|
Procedure: struct #ordered {
|
||||||
params: ^Type_Info, // Type_Info.Tuple
|
params: ^Type_Info, // Type_Info.Tuple
|
||||||
results: ^Type_Info, // Type_Info.Tuple
|
results: ^Type_Info, // Type_Info.Tuple
|
||||||
@@ -112,7 +109,7 @@ type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
base := info;
|
base := info;
|
||||||
match type i in base {
|
match i in base {
|
||||||
case Type_Info.Named:
|
case Type_Info.Named:
|
||||||
base = i.base;
|
base = i.base;
|
||||||
}
|
}
|
||||||
@@ -125,7 +122,7 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info {
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
base := info;
|
base := info;
|
||||||
match type i in base {
|
match i in base {
|
||||||
case Type_Info.Named:
|
case Type_Info.Named:
|
||||||
base = i.base;
|
base = i.base;
|
||||||
case Type_Info.Enum:
|
case Type_Info.Enum:
|
||||||
@@ -146,6 +143,8 @@ __cpuid :: proc(level: u32, sig: ^u32) -> i32 #foreign __llvm_core "__get_cpuid"
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
|
// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
|
||||||
Allocator_Mode :: enum u8 {
|
Allocator_Mode :: enum u8 {
|
||||||
ALLOC,
|
ALLOC,
|
||||||
@@ -153,9 +152,9 @@ Allocator_Mode :: enum u8 {
|
|||||||
FREE_ALL,
|
FREE_ALL,
|
||||||
RESIZE,
|
RESIZE,
|
||||||
}
|
}
|
||||||
Allocator_Proc :: type proc(allocator_data: rawptr, mode: Allocator_Mode,
|
Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||||
size, alignment: int,
|
size, alignment: int,
|
||||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
|
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
|
||||||
Allocator :: struct #ordered {
|
Allocator :: struct #ordered {
|
||||||
procedure: Allocator_Proc,
|
procedure: Allocator_Proc,
|
||||||
data: rawptr,
|
data: rawptr,
|
||||||
@@ -199,23 +198,17 @@ free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline {
|
|||||||
if ptr == nil {
|
if ptr == nil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if a.procedure == nil {
|
||||||
|
return;
|
||||||
|
}
|
||||||
a.procedure(a.data, Allocator_Mode.FREE, 0, 0, ptr, 0, 0);
|
a.procedure(a.data, Allocator_Mode.FREE, 0, 0, ptr, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
__free_raw_dynamic_array :: proc(a: ^Raw_Dynamic_Array) {
|
|
||||||
if a.allocator.procedure == nil {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if a.data == nil {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
free_ptr_with_allocator(a.allocator, a.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
free_ptr :: proc(ptr: rawptr) #inline {
|
free_ptr :: proc(ptr: rawptr) #inline {
|
||||||
__check_context();
|
__check_context();
|
||||||
free_ptr_with_allocator(context.allocator, ptr);
|
free_ptr_with_allocator(context.allocator, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_all :: proc() #inline {
|
free_all :: proc() #inline {
|
||||||
__check_context();
|
__check_context();
|
||||||
a := context.allocator;
|
a := context.allocator;
|
||||||
@@ -306,11 +299,11 @@ __string_eq :: proc(a, b: string) -> bool {
|
|||||||
if a.data == b.data {
|
if a.data == b.data {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return mem.compare(cast(rawptr)a.data, cast(rawptr)b.data, a.count) == 0;
|
return __string_cmp(a, b) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__string_cmp :: proc(a, b: string) -> int {
|
__string_cmp :: proc(a, b: string) -> int {
|
||||||
return mem.compare(cast(rawptr)a.data, cast(rawptr)b.data, min(a.count, b.count));
|
return mem.compare(cast([]byte)a, cast([]byte)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
__string_ne :: proc(a, b: string) -> bool #inline { return !__string_eq(a, b); }
|
__string_ne :: proc(a, b: string) -> bool #inline { return !__string_eq(a, b); }
|
||||||
@@ -504,7 +497,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) {
|
|||||||
nm: Raw_Dynamic_Map;
|
nm: Raw_Dynamic_Map;
|
||||||
new_header.m = ^nm;
|
new_header.m = ^nm;
|
||||||
|
|
||||||
reserve(^nm.hashes, new_count);
|
reserve(nm.hashes, new_count);
|
||||||
nm.hashes.count = nm.hashes.capacity;
|
nm.hashes.count = nm.hashes.capacity;
|
||||||
__dynamic_array_reserve(^nm.entries, entry_size, entry_align, m.entries.count);
|
__dynamic_array_reserve(^nm.entries, entry_size, entry_align, m.entries.count);
|
||||||
for _, i in nm.hashes {
|
for _, i in nm.hashes {
|
||||||
@@ -660,3 +653,13 @@ __dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) {
|
|||||||
m.hashes[last.hash_index] = fr.entry_index;
|
m.hashes[last.hash_index] = fr.entry_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__print_ti_ptr :: proc(ti: ^Type_Info) {
|
||||||
|
fmt.println(ti);
|
||||||
|
match e in ti {
|
||||||
|
case Type_Info.Enum:
|
||||||
|
fmt.println(e.names);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-26
@@ -107,7 +107,7 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
using Type_Info;
|
using Type_Info;
|
||||||
match type info in ti {
|
match info in ti {
|
||||||
case Named:
|
case Named:
|
||||||
buffer_write_string(buf, info.name);
|
buffer_write_string(buf, info.name);
|
||||||
case Integer:
|
case Integer:
|
||||||
@@ -134,9 +134,6 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
|
|||||||
buffer_write_string(buf, "^");
|
buffer_write_string(buf, "^");
|
||||||
buffer_write_type(buf, info.elem);
|
buffer_write_type(buf, info.elem);
|
||||||
}
|
}
|
||||||
case Maybe:
|
|
||||||
buffer_write_string(buf, "?");
|
|
||||||
buffer_write_type(buf, info.elem);
|
|
||||||
case Procedure:
|
case Procedure:
|
||||||
buffer_write_string(buf, "proc");
|
buffer_write_string(buf, "proc");
|
||||||
if info.params == nil {
|
if info.params == nil {
|
||||||
@@ -358,7 +355,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
|
|||||||
if arg_index < args.count {
|
if arg_index < args.count {
|
||||||
arg := args[arg_index];
|
arg := args[arg_index];
|
||||||
arg.type_info = type_info_base(arg.type_info);
|
arg.type_info = type_info_base(arg.type_info);
|
||||||
match type i in arg {
|
match i in arg {
|
||||||
case int: num = i;
|
case int: num = i;
|
||||||
case i8: num = cast(int)i;
|
case i8: num = cast(int)i;
|
||||||
case i16: num = cast(int)i;
|
case i16: num = cast(int)i;
|
||||||
@@ -420,8 +417,9 @@ fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: string) {
|
fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: string) {
|
||||||
negative := signed && cast(i64)u < 0;
|
s := cast(i64)u;
|
||||||
u = abs(u);
|
negative := signed && s < 0;
|
||||||
|
u = cast(u64)abs(s);
|
||||||
buf: [256]byte;
|
buf: [256]byte;
|
||||||
if fi.width_set || fi.prec_set {
|
if fi.width_set || fi.prec_set {
|
||||||
width := fi.width + fi.prec + 3;
|
width := fi.width + fi.prec + 3;
|
||||||
@@ -628,6 +626,7 @@ fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) {
|
|||||||
fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
|
fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
|
||||||
match verb {
|
match verb {
|
||||||
case 'p', 'v':
|
case 'p', 'v':
|
||||||
|
// Okay
|
||||||
default:
|
default:
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
return;
|
return;
|
||||||
@@ -646,7 +645,7 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
using Type_Info;
|
using Type_Info;
|
||||||
match type e in v.type_info {
|
match e in v.type_info {
|
||||||
default:
|
default:
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
return;
|
return;
|
||||||
@@ -659,7 +658,7 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
f: f64;
|
f: f64;
|
||||||
ok := false;
|
ok := false;
|
||||||
a := any{type_info_base(e.base), v.data};
|
a := any{type_info_base(e.base), v.data};
|
||||||
match type v in a {
|
match v in a {
|
||||||
case i8: i = cast(i64)v;
|
case i8: i = cast(i64)v;
|
||||||
case i16: i = cast(i64)v;
|
case i16: i = cast(i64)v;
|
||||||
case i32: i = cast(i64)v;
|
case i32: i = cast(i64)v;
|
||||||
@@ -710,9 +709,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
using Type_Info;
|
using Type_Info;
|
||||||
match type info in v.type_info {
|
match info in v.type_info {
|
||||||
case Named:
|
case Named:
|
||||||
match type b in info.base {
|
match b in info.base {
|
||||||
case Struct:
|
case Struct:
|
||||||
if verb != 'v' {
|
if verb != 'v' {
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
@@ -747,16 +746,6 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
fmt_pointer(fi, (cast(^rawptr)v.data)^, verb);
|
fmt_pointer(fi, (cast(^rawptr)v.data)^, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Maybe:
|
|
||||||
// TODO(bill): Correct verbs for Maybe types?
|
|
||||||
size := mem.size_of_type_info(info.elem);
|
|
||||||
data := slice_ptr(cast(^byte)v.data, size+1);
|
|
||||||
if data[size] != 0 {
|
|
||||||
fmt_arg(fi, any{info.elem, v.data}, verb);
|
|
||||||
} else {
|
|
||||||
buffer_write_string(fi.buf, "nil");
|
|
||||||
}
|
|
||||||
|
|
||||||
case Array:
|
case Array:
|
||||||
if verb != 'v' {
|
if verb != 'v' {
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
@@ -799,9 +788,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
buffer_write_string(fi.buf, "map[");
|
buffer_write_string(fi.buf, "map[");
|
||||||
defer buffer_write_byte(fi.buf, ']');
|
defer buffer_write_byte(fi.buf, ']');
|
||||||
entries := ^(cast(^Raw_Dynamic_Map)v.data).entries;
|
entries := ^(cast(^Raw_Dynamic_Map)v.data).entries;
|
||||||
gs, _ := union_cast(^Struct)info.generated_struct;
|
gs, gs_ok := union_cast(^Struct)type_info_base(info.generated_struct); assert(gs_ok);
|
||||||
ed, _ := union_cast(^Dynamic_Array)gs.fields[1].type_info;
|
ed, ed_ok := union_cast(^Dynamic_Array)type_info_base(gs.fields[1].type_info); assert(ed_ok);
|
||||||
entry_type, _ := union_cast(^Struct)ed.elem;
|
|
||||||
|
entry_type, et_ok := union_cast(^Struct)ed.elem; assert(et_ok);
|
||||||
entry_size := ed.elem_size;
|
entry_size := ed.elem_size;
|
||||||
for i in 0..<entries.count {
|
for i in 0..<entries.count {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
@@ -892,7 +882,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
|||||||
|
|
||||||
if verb == 'T' {
|
if verb == 'T' {
|
||||||
ti := arg.type_info;
|
ti := arg.type_info;
|
||||||
match type a in arg {
|
match a in arg {
|
||||||
case ^Type_Info: ti = a;
|
case ^Type_Info: ti = a;
|
||||||
}
|
}
|
||||||
buffer_write_type(fi.buf, ti);
|
buffer_write_type(fi.buf, ti);
|
||||||
@@ -902,7 +892,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
|||||||
|
|
||||||
base_arg := arg;
|
base_arg := arg;
|
||||||
base_arg.type_info = type_info_base(base_arg.type_info);
|
base_arg.type_info = type_info_base(base_arg.type_info);
|
||||||
match type a in base_arg {
|
match a in base_arg {
|
||||||
case bool: fmt_bool(fi, a, verb);
|
case bool: fmt_bool(fi, a, verb);
|
||||||
case f32: fmt_float(fi, cast(f64)a, 32, verb);
|
case f32: fmt_float(fi, cast(f64)a, 32, verb);
|
||||||
case f64: fmt_float(fi, a, 64, verb);
|
case f64: fmt_float(fi, a, 64, verb);
|
||||||
|
|||||||
@@ -46,10 +46,6 @@ bit_reverse :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bitreverse.i16";
|
|||||||
bit_reverse :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bitreverse.i32";
|
bit_reverse :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bitreverse.i32";
|
||||||
bit_reverse :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bitreverse.i64";
|
bit_reverse :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bitreverse.i64";
|
||||||
|
|
||||||
byte_swap :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bswap.i16";
|
|
||||||
byte_swap :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bswap.i32";
|
|
||||||
byte_swap :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bswap.i64";
|
|
||||||
|
|
||||||
fmuladd :: proc(a, b, c: f32) -> f32 #foreign __llvm_core "llvm.fmuladd.f32";
|
fmuladd :: proc(a, b, c: f32) -> f32 #foreign __llvm_core "llvm.fmuladd.f32";
|
||||||
fmuladd :: proc(a, b, c: f64) -> f64 #foreign __llvm_core "llvm.fmuladd.f64";
|
fmuladd :: proc(a, b, c: f64) -> f64 #foreign __llvm_core "llvm.fmuladd.f64";
|
||||||
|
|
||||||
|
|||||||
+36
-37
@@ -1,6 +1,11 @@
|
|||||||
#import "fmt.odin";
|
#import "fmt.odin";
|
||||||
#import "os.odin";
|
#import "os.odin";
|
||||||
|
|
||||||
|
swap :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bswap.i16";
|
||||||
|
swap :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bswap.i32";
|
||||||
|
swap :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bswap.i64";
|
||||||
|
|
||||||
|
|
||||||
set :: proc(data: rawptr, value: i32, len: int) -> rawptr #link_name "__mem_set" {
|
set :: proc(data: rawptr, value: i32, len: int) -> rawptr #link_name "__mem_set" {
|
||||||
llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memset.p0i8.i64";
|
llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memset.p0i8.i64";
|
||||||
llvm_memset_64bit(data, cast(byte)value, len, 1, false);
|
llvm_memset_64bit(data, cast(byte)value, len, 1, false);
|
||||||
@@ -12,22 +17,21 @@ zero :: proc(data: rawptr, len: int) -> rawptr #link_name "__mem_zero" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copy :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy" {
|
copy :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy" {
|
||||||
// NOTE(bill): This _must_ implemented like C's memmove
|
// NOTE(bill): This _must_ be implemented like C's memmove
|
||||||
llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memmove.p0i8.p0i8.i64";
|
llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memmove.p0i8.p0i8.i64";
|
||||||
llvm_memmove_64bit(dst, src, len, 1, false);
|
llvm_memmove_64bit(dst, src, len, 1, false);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy_non_overlapping" {
|
copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy_non_overlapping" {
|
||||||
// NOTE(bill): This _must_ implemented like C's memcpy
|
// NOTE(bill): This _must_ be implemented like C's memcpy
|
||||||
llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memcpy.p0i8.p0i8.i64";
|
llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memcpy.p0i8.p0i8.i64";
|
||||||
llvm_memcpy_64bit(dst, src, len, 1, false);
|
llvm_memcpy_64bit(dst, src, len, 1, false);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" {
|
compare :: proc(a, b: []byte) -> int #link_name "__mem_compare" {
|
||||||
a := slice_ptr(cast(^byte)dst, n);
|
n := min(a.count, b.count);
|
||||||
b := slice_ptr(cast(^byte)src, n);
|
|
||||||
for i in 0..<n {
|
for i in 0..<n {
|
||||||
match {
|
match {
|
||||||
case a[i] < b[i]:
|
case a[i] < b[i]:
|
||||||
@@ -43,8 +47,8 @@ compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" {
|
|||||||
|
|
||||||
kilobytes :: proc(x: int) -> int #inline { return (x) * 1024; }
|
kilobytes :: proc(x: int) -> int #inline { return (x) * 1024; }
|
||||||
megabytes :: proc(x: int) -> int #inline { return kilobytes(x) * 1024; }
|
megabytes :: proc(x: int) -> int #inline { return kilobytes(x) * 1024; }
|
||||||
gigabytes :: proc(x: int) -> int #inline { return gigabytes(x) * 1024; }
|
gigabytes :: proc(x: int) -> int #inline { return megabytes(x) * 1024; }
|
||||||
terabytes :: proc(x: int) -> int #inline { return terabytes(x) * 1024; }
|
terabytes :: proc(x: int) -> int #inline { return gigabytes(x) * 1024; }
|
||||||
|
|
||||||
is_power_of_two :: proc(x: int) -> bool {
|
is_power_of_two :: proc(x: int) -> bool {
|
||||||
if x <= 0 {
|
if x <= 0 {
|
||||||
@@ -213,8 +217,7 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
|||||||
WORD_SIZE :: size_of(int);
|
WORD_SIZE :: size_of(int);
|
||||||
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
||||||
using Type_Info;
|
using Type_Info;
|
||||||
|
match info in type_info {
|
||||||
match type info in type_info {
|
|
||||||
case Named:
|
case Named:
|
||||||
return align_of_type_info(info.base);
|
return align_of_type_info(info.base);
|
||||||
case Integer:
|
case Integer:
|
||||||
@@ -225,14 +228,16 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
|||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Boolean:
|
case Boolean:
|
||||||
return 1;
|
return 1;
|
||||||
|
case Any:
|
||||||
|
return WORD_SIZE;
|
||||||
case Pointer:
|
case Pointer:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Maybe:
|
|
||||||
return max(align_of_type_info(info.elem), 1);
|
|
||||||
case Procedure:
|
case Procedure:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Array:
|
case Array:
|
||||||
return align_of_type_info(info.elem);
|
return align_of_type_info(info.elem);
|
||||||
|
case Dynamic_Array:
|
||||||
|
return WORD_SIZE;
|
||||||
case Slice:
|
case Slice:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Vector:
|
case Vector:
|
||||||
@@ -240,12 +245,18 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
|||||||
count := cast(int)max(prev_pow2(cast(i64)info.count), 1);
|
count := cast(int)max(prev_pow2(cast(i64)info.count), 1);
|
||||||
total := size * count;
|
total := size * count;
|
||||||
return clamp(total, 1, MAX_ALIGN);
|
return clamp(total, 1, MAX_ALIGN);
|
||||||
|
case Tuple:
|
||||||
|
return info.align;
|
||||||
case Struct:
|
case Struct:
|
||||||
return info.align;
|
return info.align;
|
||||||
case Union:
|
case Union:
|
||||||
return info.align;
|
return info.align;
|
||||||
case Raw_Union:
|
case Raw_Union:
|
||||||
return info.align;
|
return info.align;
|
||||||
|
case Enum:
|
||||||
|
return align_of_type_info(info.base);
|
||||||
|
case Map:
|
||||||
|
return align_of_type_info(info.generated_struct);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -259,23 +270,21 @@ align_formula :: proc(size, align: int) -> int {
|
|||||||
size_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
size_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
||||||
WORD_SIZE :: size_of(int);
|
WORD_SIZE :: size_of(int);
|
||||||
using Type_Info;
|
using Type_Info;
|
||||||
match type info in type_info {
|
match info in type_info {
|
||||||
case Named:
|
case Named:
|
||||||
return size_of_type_info(info.base);
|
return size_of_type_info(info.base);
|
||||||
case Integer:
|
case Integer:
|
||||||
return info.size;
|
return info.size;
|
||||||
case Float:
|
case Float:
|
||||||
return info.size;
|
return info.size;
|
||||||
case Any:
|
|
||||||
return 2*WORD_SIZE;
|
|
||||||
case String:
|
case String:
|
||||||
return 2*WORD_SIZE;
|
return 2*WORD_SIZE;
|
||||||
case Boolean:
|
case Boolean:
|
||||||
return 1;
|
return 1;
|
||||||
|
case Any:
|
||||||
|
return 2*WORD_SIZE;
|
||||||
case Pointer:
|
case Pointer:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Maybe:
|
|
||||||
return size_of_type_info(info.elem) + 1;
|
|
||||||
case Procedure:
|
case Procedure:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Array:
|
case Array:
|
||||||
@@ -287,39 +296,29 @@ size_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
|||||||
align := align_of_type_info(info.elem);
|
align := align_of_type_info(info.elem);
|
||||||
alignment := align_formula(size, align);
|
alignment := align_formula(size, align);
|
||||||
return alignment*(count-1) + size;
|
return alignment*(count-1) + size;
|
||||||
|
case Dynamic_Array:
|
||||||
|
return size_of(rawptr) + 2*size_of(int) + size_of(Allocator);
|
||||||
case Slice:
|
case Slice:
|
||||||
return 3*WORD_SIZE;
|
return 2*WORD_SIZE;
|
||||||
case Vector:
|
case Vector:
|
||||||
is_bool :: proc(type_info: ^Type_Info) -> bool {
|
|
||||||
match type info in type_info {
|
|
||||||
case Named:
|
|
||||||
return is_bool(info.base);
|
|
||||||
case Boolean:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
count := info.count;
|
count := info.count;
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
bit_size := 8*size_of_type_info(info.elem);
|
size := size_of_type_info(info.elem);
|
||||||
if is_bool(info.elem) {
|
align := align_of_type_info(info.elem);
|
||||||
// NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1`
|
alignment := align_formula(size, align);
|
||||||
// Silly LLVM spec
|
return alignment*(count-1) + size;
|
||||||
bit_size = 1;
|
|
||||||
}
|
|
||||||
total_size_in_bits := bit_size * count;
|
|
||||||
total_size := (total_size_in_bits+7)/8;
|
|
||||||
return total_size;
|
|
||||||
|
|
||||||
case Struct:
|
case Struct:
|
||||||
return info.size;
|
return info.size;
|
||||||
case Union:
|
case Union:
|
||||||
return info.size;
|
return info.size;
|
||||||
case Raw_Union:
|
case Raw_Union:
|
||||||
return info.size;
|
return info.size;
|
||||||
|
case Enum:
|
||||||
|
return size_of_type_info(info.base);
|
||||||
|
case Map:
|
||||||
|
return size_of_type_info(info.generated_struct);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
_ := compile_assert(ODIN_OS == "windows");
|
||||||
#foreign_system_library "kernel32.lib";
|
#foreign_system_library "kernel32.lib";
|
||||||
#foreign_system_library "user32.lib";
|
#foreign_system_library "user32.lib";
|
||||||
#foreign_system_library "gdi32.lib";
|
#foreign_system_library "gdi32.lib";
|
||||||
@@ -19,7 +20,7 @@ LPARAM :: int;
|
|||||||
LRESULT :: int;
|
LRESULT :: int;
|
||||||
ATOM :: i16;
|
ATOM :: i16;
|
||||||
BOOL :: i32;
|
BOOL :: i32;
|
||||||
WNDPROC :: type proc(HWND, u32, WPARAM, LPARAM) -> LRESULT #cc_c;
|
WNDPROC :: #type proc(HWND, u32, WPARAM, LPARAM) -> LRESULT #cc_c;
|
||||||
|
|
||||||
|
|
||||||
INVALID_HANDLE_VALUE :: cast(HANDLE)(~cast(int)0);
|
INVALID_HANDLE_VALUE :: cast(HANDLE)(~cast(int)0);
|
||||||
@@ -358,8 +359,8 @@ PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000;
|
|||||||
PFD_STEREO_DONTCARE :: 0x80000000;
|
PFD_STEREO_DONTCARE :: 0x80000000;
|
||||||
|
|
||||||
HGLRC :: HANDLE;
|
HGLRC :: HANDLE;
|
||||||
PROC :: type proc() #cc_c;
|
PROC :: #type proc() #cc_c;
|
||||||
wglCreateContextAttribsARBType :: type proc(hdc: HDC, hshareContext: rawptr, attribList: ^i32) -> HGLRC;
|
wglCreateContextAttribsARBType :: #type proc(hdc: HDC, hshareContext: rawptr, attribList: ^i32) -> HGLRC;
|
||||||
|
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR :: struct #ordered {
|
PIXELFORMATDESCRIPTOR :: struct #ordered {
|
||||||
|
|||||||
+24
-24
@@ -11,7 +11,7 @@ is_signed :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_integer :: proc(info: ^Type_Info) -> bool {
|
is_integer :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Integer: return true;
|
case Type_Info.Integer: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -19,7 +19,7 @@ is_integer :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_float :: proc(info: ^Type_Info) -> bool {
|
is_float :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Float: return true;
|
case Type_Info.Float: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -27,7 +27,7 @@ is_float :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_any :: proc(info: ^Type_Info) -> bool {
|
is_any :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Any: return true;
|
case Type_Info.Any: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -35,7 +35,7 @@ is_any :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_string :: proc(info: ^Type_Info) -> bool {
|
is_string :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.String: return true;
|
case Type_Info.String: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -43,7 +43,7 @@ is_string :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_boolean :: proc(info: ^Type_Info) -> bool {
|
is_boolean :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Boolean: return true;
|
case Type_Info.Boolean: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -51,23 +51,15 @@ is_boolean :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_pointer :: proc(info: ^Type_Info) -> bool {
|
is_pointer :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Pointer: return true;
|
case Type_Info.Pointer: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
is_maybe :: proc(info: ^Type_Info) -> bool {
|
|
||||||
if info == nil { return false; }
|
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
|
||||||
case Type_Info.Maybe: return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
is_procedure :: proc(info: ^Type_Info) -> bool {
|
is_procedure :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Procedure: return true;
|
case Type_Info.Procedure: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -75,7 +67,7 @@ is_procedure :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_array :: proc(info: ^Type_Info) -> bool {
|
is_array :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Array: return true;
|
case Type_Info.Array: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -83,15 +75,23 @@ is_array :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_dynamic_array :: proc(info: ^Type_Info) -> bool {
|
is_dynamic_array :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Dynamic_Array: return true;
|
case Type_Info.Dynamic_Array: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
is_dynamic_map :: proc(info: ^Type_Info) -> bool {
|
||||||
|
if info == nil { return false; }
|
||||||
|
|
||||||
|
match i in type_info_base(info) {
|
||||||
|
case Type_Info.Map: return i.count == 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
is_slice :: proc(info: ^Type_Info) -> bool {
|
is_slice :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Slice: return true;
|
case Type_Info.Slice: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -99,7 +99,7 @@ is_slice :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_vector :: proc(info: ^Type_Info) -> bool {
|
is_vector :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Vector: return true;
|
case Type_Info.Vector: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -107,7 +107,7 @@ is_vector :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_tuple :: proc(info: ^Type_Info) -> bool {
|
is_tuple :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Tuple: return true;
|
case Type_Info.Tuple: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -115,7 +115,7 @@ is_tuple :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_struct :: proc(info: ^Type_Info) -> bool {
|
is_struct :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Struct: return true;
|
case Type_Info.Struct: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -123,7 +123,7 @@ is_struct :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_union :: proc(info: ^Type_Info) -> bool {
|
is_union :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Union: return true;
|
case Type_Info.Union: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -131,7 +131,7 @@ is_union :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_raw_union :: proc(info: ^Type_Info) -> bool {
|
is_raw_union :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Raw_Union: return true;
|
case Type_Info.Raw_Union: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -139,7 +139,7 @@ is_raw_union :: proc(info: ^Type_Info) -> bool {
|
|||||||
is_enum :: proc(info: ^Type_Info) -> bool {
|
is_enum :: proc(info: ^Type_Info) -> bool {
|
||||||
if info == nil { return false; }
|
if info == nil { return false; }
|
||||||
|
|
||||||
match type i in type_info_base(info) {
|
match i in type_info_base(info) {
|
||||||
case Type_Info.Enum: return true;
|
case Type_Info.Enum: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+58
-123
File diff suppressed because one or more lines are too long
+25
-5
@@ -942,7 +942,25 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
bool is_union_ptr = false;
|
bool is_union_ptr = false;
|
||||||
bool is_any = false;
|
bool is_any = false;
|
||||||
|
|
||||||
check_expr(c, &x, ms->tag);
|
if (ms->tag->kind != AstNode_AssignStmt) {
|
||||||
|
error_node(ms->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);
|
||||||
|
if (as->lhs.count != 1) {
|
||||||
|
syntax_error(as_token, "Expected 1 name before `in`");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (as->rhs.count != 1) {
|
||||||
|
syntax_error(as_token, "Expected 1 expression after `in`");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
AstNode *lhs = as->lhs.e[0];
|
||||||
|
AstNode *rhs = as->rhs.e[0];
|
||||||
|
|
||||||
|
check_expr(c, &x, rhs);
|
||||||
check_assignment(c, &x, NULL, str_lit("type match expression"));
|
check_assignment(c, &x, NULL, str_lit("type match expression"));
|
||||||
if (!check_valid_type_match_type(x.type, &is_union_ptr, &is_any)) {
|
if (!check_valid_type_match_type(x.type, &is_union_ptr, &is_any)) {
|
||||||
gbString str = type_to_string(x.type);
|
gbString str = type_to_string(x.type);
|
||||||
@@ -980,7 +998,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ms->var->kind != AstNode_Ident) {
|
|
||||||
|
if (unparen_expr(lhs)->kind != AstNode_Ident) {
|
||||||
|
error_node(rhs, "Expected an identifier, got `%.*s`", LIT(ast_node_strings[rhs->kind]));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1056,10 +1076,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
tt = make_type_pointer(c->allocator, case_type);
|
tt = make_type_pointer(c->allocator, case_type);
|
||||||
add_type_info_type(c, tt);
|
add_type_info_type(c, tt);
|
||||||
}
|
}
|
||||||
Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, ms->var->Ident, tt, true);
|
Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, lhs->Ident, tt, true);
|
||||||
tag_var->flags |= EntityFlag_Used;
|
tag_var->flags |= EntityFlag_Used;
|
||||||
add_entity(c, c->context.scope, ms->var, tag_var);
|
add_entity(c, c->context.scope, lhs, tag_var);
|
||||||
add_entity_use(c, ms->var, tag_var);
|
add_entity_use(c, lhs, tag_var);
|
||||||
}
|
}
|
||||||
check_stmt_list(c, cc->stmts, mod_flags);
|
check_stmt_list(c, cc->stmts, mod_flags);
|
||||||
check_close_scope(c);
|
check_close_scope(c);
|
||||||
|
|||||||
+52
-45
@@ -630,11 +630,12 @@ void init_universal_scope(BuildContext *bc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
t_u8_ptr = make_type_pointer(a, t_u8);
|
t_u8_ptr = make_type_pointer(a, t_u8);
|
||||||
t_int_ptr = make_type_pointer(a, t_int);
|
t_int_ptr = make_type_pointer(a, t_int);
|
||||||
t_i64_ptr = make_type_pointer(a, t_i64);
|
t_i64_ptr = make_type_pointer(a, t_i64);
|
||||||
t_f64_ptr = make_type_pointer(a, t_f64);
|
t_f64_ptr = make_type_pointer(a, t_f64);
|
||||||
t_byte_slice = make_type_slice(a, t_byte);
|
t_byte_slice = make_type_slice(a, t_byte);
|
||||||
|
t_string_slice = make_type_slice(a, t_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -911,11 +912,6 @@ void add_type_info_type(Checker *c, Type *t) {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Maybe:
|
|
||||||
add_type_info_type(c, bt->Maybe.elem);
|
|
||||||
add_type_info_type(c, t_bool);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type_Pointer:
|
case Type_Pointer:
|
||||||
add_type_info_type(c, bt->Pointer.elem);
|
add_type_info_type(c, bt->Pointer.elem);
|
||||||
break;
|
break;
|
||||||
@@ -1099,48 +1095,46 @@ void init_preload(Checker *c) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (record->field_count != 20) {
|
if (record->field_count != 19) {
|
||||||
compiler_error("Invalid `Type_Info` layout");
|
compiler_error("Invalid `Type_Info` layout");
|
||||||
}
|
}
|
||||||
t_type_info_named = record->fields[ 1]->type;
|
t_type_info_named = record->fields[ 1]->type;
|
||||||
t_type_info_integer = record->fields[ 2]->type;
|
t_type_info_integer = record->fields[ 2]->type;
|
||||||
t_type_info_float = record->fields[ 3]->type;
|
t_type_info_float = record->fields[ 3]->type;
|
||||||
t_type_info_any = record->fields[ 4]->type;
|
t_type_info_string = record->fields[ 4]->type;
|
||||||
t_type_info_string = record->fields[ 5]->type;
|
t_type_info_boolean = record->fields[ 5]->type;
|
||||||
t_type_info_boolean = record->fields[ 6]->type;
|
t_type_info_any = record->fields[ 6]->type;
|
||||||
t_type_info_pointer = record->fields[ 7]->type;
|
t_type_info_pointer = record->fields[ 7]->type;
|
||||||
t_type_info_maybe = record->fields[ 8]->type;
|
t_type_info_procedure = record->fields[ 8]->type;
|
||||||
t_type_info_procedure = record->fields[ 9]->type;
|
t_type_info_array = record->fields[ 9]->type;
|
||||||
t_type_info_array = record->fields[10]->type;
|
t_type_info_dynamic_array = record->fields[10]->type;
|
||||||
t_type_info_dynamic_array = record->fields[11]->type;
|
t_type_info_slice = record->fields[11]->type;
|
||||||
t_type_info_slice = record->fields[12]->type;
|
t_type_info_vector = record->fields[12]->type;
|
||||||
t_type_info_vector = record->fields[13]->type;
|
t_type_info_tuple = record->fields[13]->type;
|
||||||
t_type_info_tuple = record->fields[14]->type;
|
t_type_info_struct = record->fields[14]->type;
|
||||||
t_type_info_struct = record->fields[15]->type;
|
t_type_info_union = record->fields[15]->type;
|
||||||
t_type_info_union = record->fields[16]->type;
|
t_type_info_raw_union = record->fields[16]->type;
|
||||||
t_type_info_raw_union = record->fields[17]->type;
|
t_type_info_enum = record->fields[17]->type;
|
||||||
t_type_info_enum = record->fields[18]->type;
|
t_type_info_map = record->fields[18]->type;
|
||||||
t_type_info_map = record->fields[19]->type;
|
|
||||||
|
|
||||||
t_type_info_named_ptr = make_type_pointer(heap_allocator(), t_type_info_named);
|
t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named);
|
||||||
t_type_info_integer_ptr = make_type_pointer(heap_allocator(), t_type_info_integer);
|
t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer);
|
||||||
t_type_info_float_ptr = make_type_pointer(heap_allocator(), t_type_info_float);
|
t_type_info_float_ptr = make_type_pointer(c->allocator, t_type_info_float);
|
||||||
t_type_info_any_ptr = make_type_pointer(heap_allocator(), t_type_info_any);
|
t_type_info_string_ptr = make_type_pointer(c->allocator, t_type_info_string);
|
||||||
t_type_info_string_ptr = make_type_pointer(heap_allocator(), t_type_info_string);
|
t_type_info_boolean_ptr = make_type_pointer(c->allocator, t_type_info_boolean);
|
||||||
t_type_info_boolean_ptr = make_type_pointer(heap_allocator(), t_type_info_boolean);
|
t_type_info_any_ptr = make_type_pointer(c->allocator, t_type_info_any);
|
||||||
t_type_info_pointer_ptr = make_type_pointer(heap_allocator(), t_type_info_pointer);
|
t_type_info_pointer_ptr = make_type_pointer(c->allocator, t_type_info_pointer);
|
||||||
t_type_info_maybe_ptr = make_type_pointer(heap_allocator(), t_type_info_maybe);
|
t_type_info_procedure_ptr = make_type_pointer(c->allocator, t_type_info_procedure);
|
||||||
t_type_info_procedure_ptr = make_type_pointer(heap_allocator(), t_type_info_procedure);
|
t_type_info_array_ptr = make_type_pointer(c->allocator, t_type_info_array);
|
||||||
t_type_info_array_ptr = make_type_pointer(heap_allocator(), t_type_info_array);
|
t_type_info_dynamic_array_ptr = make_type_pointer(c->allocator, t_type_info_dynamic_array);
|
||||||
t_type_info_dynamic_array_ptr = make_type_pointer(heap_allocator(), t_type_info_dynamic_array);
|
t_type_info_slice_ptr = make_type_pointer(c->allocator, t_type_info_slice);
|
||||||
t_type_info_slice_ptr = make_type_pointer(heap_allocator(), t_type_info_slice);
|
t_type_info_vector_ptr = make_type_pointer(c->allocator, t_type_info_vector);
|
||||||
t_type_info_vector_ptr = make_type_pointer(heap_allocator(), t_type_info_vector);
|
t_type_info_tuple_ptr = make_type_pointer(c->allocator, t_type_info_tuple);
|
||||||
t_type_info_tuple_ptr = make_type_pointer(heap_allocator(), t_type_info_tuple);
|
t_type_info_struct_ptr = make_type_pointer(c->allocator, t_type_info_struct);
|
||||||
t_type_info_struct_ptr = make_type_pointer(heap_allocator(), t_type_info_struct);
|
t_type_info_union_ptr = make_type_pointer(c->allocator, t_type_info_union);
|
||||||
t_type_info_union_ptr = make_type_pointer(heap_allocator(), t_type_info_union);
|
t_type_info_raw_union_ptr = make_type_pointer(c->allocator, t_type_info_raw_union);
|
||||||
t_type_info_raw_union_ptr = make_type_pointer(heap_allocator(), t_type_info_raw_union);
|
t_type_info_enum_ptr = make_type_pointer(c->allocator, t_type_info_enum);
|
||||||
t_type_info_enum_ptr = make_type_pointer(heap_allocator(), t_type_info_enum);
|
t_type_info_map_ptr = make_type_pointer(c->allocator, t_type_info_map);
|
||||||
t_type_info_map_ptr = make_type_pointer(heap_allocator(), t_type_info_map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t_allocator == NULL) {
|
if (t_allocator == NULL) {
|
||||||
@@ -1727,6 +1721,19 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
|
|||||||
file_str = import_file;
|
file_str = import_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fl->cond != NULL) {
|
||||||
|
Operand operand = {Addressing_Invalid};
|
||||||
|
check_expr(c, &operand, fl->cond);
|
||||||
|
if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
|
||||||
|
error_node(fl->cond, "Non-constant boolean `when` condition");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (operand.value.kind == ExactValue_Bool &&
|
||||||
|
!operand.value.value_bool) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String library_name = path_to_entity_name(fl->library_name.string, file_str);
|
String library_name = path_to_entity_name(fl->library_name.string, file_str);
|
||||||
if (str_eq(library_name, str_lit("_"))) {
|
if (str_eq(library_name, str_lit("_"))) {
|
||||||
error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));
|
error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ typedef enum EntityFlag {
|
|||||||
EntityFlag_VectorElem = 1<<5,
|
EntityFlag_VectorElem = 1<<5,
|
||||||
EntityFlag_Ellipsis = 1<<6,
|
EntityFlag_Ellipsis = 1<<6,
|
||||||
EntityFlag_NoAlias = 1<<7,
|
EntityFlag_NoAlias = 1<<7,
|
||||||
|
EntityFlag_EnumField = 1<<8,
|
||||||
} EntityFlag;
|
} EntityFlag;
|
||||||
|
|
||||||
typedef enum OverloadKind {
|
typedef enum OverloadKind {
|
||||||
|
|||||||
@@ -1788,11 +1788,6 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
|
|||||||
case 0: result_type = make_type_pointer(a, t_type_info_ptr); break;
|
case 0: result_type = make_type_pointer(a, t_type_info_ptr); break;
|
||||||
case 1: result_type = make_type_pointer(a, t_rawptr); break;
|
case 1: result_type = make_type_pointer(a, t_rawptr); break;
|
||||||
}
|
}
|
||||||
} else if (is_type_maybe(t)) {
|
|
||||||
switch (index) {
|
|
||||||
case 0: result_type = make_type_pointer(a, t->Maybe.elem); break;
|
|
||||||
case 1: result_type = make_type_pointer(a, t_bool); break;
|
|
||||||
}
|
|
||||||
} else if (is_type_dynamic_array(t)) {
|
} else if (is_type_dynamic_array(t)) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->DynamicArray.elem)); break;
|
case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->DynamicArray.elem)); break;
|
||||||
@@ -1848,11 +1843,6 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
|||||||
case 0: result_type = t_type_info_ptr; break;
|
case 0: result_type = t_type_info_ptr; break;
|
||||||
case 1: result_type = t_rawptr; break;
|
case 1: result_type = t_rawptr; break;
|
||||||
}
|
}
|
||||||
} else if (is_type_maybe(t)) {
|
|
||||||
switch (index) {
|
|
||||||
case 0: result_type = t->Maybe.elem; break;
|
|
||||||
case 1: result_type = t_bool; break;
|
|
||||||
}
|
|
||||||
} else if (is_type_dynamic_array(t)) {
|
} else if (is_type_dynamic_array(t)) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0: result_type = make_type_pointer(a, t->DynamicArray.elem); break;
|
case 0: result_type = make_type_pointer(a, t->DynamicArray.elem); break;
|
||||||
@@ -2165,15 +2155,6 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_type_maybe(dst)) {
|
|
||||||
irValue *maybe = ir_add_local_generated(proc, dst);
|
|
||||||
irValue *val = ir_emit_struct_ep(proc, maybe, 0);
|
|
||||||
irValue *set = ir_emit_struct_ep(proc, maybe, 1);
|
|
||||||
ir_emit_store(proc, val, value);
|
|
||||||
ir_emit_store(proc, set, v_true);
|
|
||||||
return ir_emit_load(proc, maybe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// integer -> integer
|
// integer -> integer
|
||||||
if (is_type_integer(src) && is_type_integer(dst)) {
|
if (is_type_integer(src) && is_type_integer(dst)) {
|
||||||
GB_ASSERT(src->kind == Type_Basic &&
|
GB_ASSERT(src->kind == Type_Basic &&
|
||||||
@@ -2396,7 +2377,6 @@ bool ir_is_type_aggregate(Type *t) {
|
|||||||
|
|
||||||
case Type_Array:
|
case Type_Array:
|
||||||
case Type_Slice:
|
case Type_Slice:
|
||||||
case Type_Maybe:
|
|
||||||
case Type_Record:
|
case Type_Record:
|
||||||
case Type_Tuple:
|
case Type_Tuple:
|
||||||
return true;
|
return true;
|
||||||
@@ -3130,22 +3110,33 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|||||||
args[1] = ptr;
|
args[1] = ptr;
|
||||||
return ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
|
return ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
|
||||||
} else if (is_type_dynamic_map(type)) {
|
} else if (is_type_dynamic_map(type)) {
|
||||||
// irValue *val = ir_build_expr(proc, node);
|
irValue *map = ir_build_expr(proc, node);
|
||||||
// irValue *map_ptr = ir_address_from_load_or_generate_local(proc, val);
|
irValue *map_ptr = ir_address_from_load_or_generate_local(proc, map);
|
||||||
|
|
||||||
// {
|
{
|
||||||
// irValue *array = ir_emit_conv(proc, ir_emit_struct_ep(proc, map_ptr, 0), t_raw_dynamic_array_ptr);
|
irValue *array = ir_emit_struct_ep(proc, map_ptr, 0);
|
||||||
// irValue **args = gb_alloc_array(a, irValue *, 1);
|
|
||||||
// args[0] = array;
|
|
||||||
// ir_emit_global_call(proc, "__free_raw_dynamic_array", args, 1);
|
|
||||||
// }
|
|
||||||
// {
|
|
||||||
// irValue *array = ir_emit_conv(proc, ir_emit_struct_ep(proc, map_ptr, 1), t_raw_dynamic_array_ptr);
|
|
||||||
// irValue **args = gb_alloc_array(a, irValue *, 1);
|
|
||||||
// args[0] = array;
|
|
||||||
// ir_emit_global_call(proc, "__free_raw_dynamic_array", args, 1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3));
|
||||||
|
irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0));
|
||||||
|
da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr);
|
||||||
|
|
||||||
|
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||||
|
args[0] = da_allocator;
|
||||||
|
args[1] = da_ptr;
|
||||||
|
ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
irValue *array = ir_emit_struct_ep(proc, map_ptr, 1);
|
||||||
|
|
||||||
|
irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3));
|
||||||
|
irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0));
|
||||||
|
da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr);
|
||||||
|
|
||||||
|
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||||
|
args[0] = da_allocator;
|
||||||
|
args[1] = da_ptr;
|
||||||
|
ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3176,7 +3167,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|||||||
ir_emit_comment(proc, str_lit("reserve"));
|
ir_emit_comment(proc, str_lit("reserve"));
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
|
|
||||||
irValue *ptr = ir_build_expr(proc, ce->args.e[0]);
|
irValue *ptr = ir_build_addr(proc, ce->args.e[0]).addr;
|
||||||
Type *type = ir_type(ptr);
|
Type *type = ir_type(ptr);
|
||||||
GB_ASSERT(is_type_pointer(type));
|
GB_ASSERT(is_type_pointer(type));
|
||||||
type = base_type(type_deref(type));
|
type = base_type(type_deref(type));
|
||||||
@@ -3208,8 +3199,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_clear: {
|
case BuiltinProc_clear: {
|
||||||
ir_emit_comment(proc, str_lit("reserve"));
|
ir_emit_comment(proc, str_lit("clear"));
|
||||||
irValue *ptr = ir_build_expr(proc, ce->args.e[0]);
|
irValue *ptr = ir_build_addr(proc, ce->args.e[0]).addr;
|
||||||
Type *t = base_type(type_deref(ir_type(ptr)));
|
Type *t = base_type(type_deref(ir_type(ptr)));
|
||||||
if (is_type_dynamic_array(t)) {
|
if (is_type_dynamic_array(t)) {
|
||||||
irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1);
|
irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1);
|
||||||
@@ -3229,7 +3220,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|||||||
ir_emit_comment(proc, str_lit("append"));
|
ir_emit_comment(proc, str_lit("append"));
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
|
|
||||||
irValue *array_ptr = ir_build_expr(proc, ce->args.e[0]);
|
irValue *array_ptr = ir_build_addr(proc, ce->args.e[0]).addr;
|
||||||
Type *type = ir_type(array_ptr);
|
Type *type = ir_type(array_ptr);
|
||||||
GB_ASSERT(is_type_pointer(type));
|
GB_ASSERT(is_type_pointer(type));
|
||||||
type = base_type(type_deref(type));
|
type = base_type(type_deref(type));
|
||||||
@@ -3348,7 +3339,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|||||||
ir_emit_jump(proc, done);
|
ir_emit_jump(proc, done);
|
||||||
ir_start_block(proc, done);
|
ir_start_block(proc, done);
|
||||||
|
|
||||||
return NULL;
|
return cond;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_panic: {
|
case BuiltinProc_panic: {
|
||||||
@@ -3596,10 +3587,6 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|||||||
return ir_emit_call(proc, value, args, arg_count);
|
return ir_emit_call(proc, value, args, arg_count);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(de, DemaybeExpr, expr);
|
|
||||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(se, SliceExpr, expr);
|
case_ast_node(se, SliceExpr, expr);
|
||||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||||
case_end;
|
case_end;
|
||||||
@@ -3722,7 +3709,34 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
AstNode *sel = unparen_expr(se->selector);
|
AstNode *sel = unparen_expr(se->selector);
|
||||||
if (sel->kind == AstNode_Ident) {
|
if (sel->kind == AstNode_Ident) {
|
||||||
String selector = sel->Ident.string;
|
String selector = sel->Ident.string;
|
||||||
Type *type = base_type(type_of_expr(proc->module->info, se->expr));
|
Type *type = type_of_expr(proc->module->info, se->expr);
|
||||||
|
|
||||||
|
if (is_type_enum(type)) {
|
||||||
|
Selection sel = lookup_field(proc->module->allocator, type, selector, true);
|
||||||
|
Entity *e = sel.entity;
|
||||||
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
i32 index = e->Variable.field_index;
|
||||||
|
switch (index) {
|
||||||
|
case 0: {
|
||||||
|
irValue *ti_ptr = ir_type_info(proc, type);
|
||||||
|
{
|
||||||
|
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 1);
|
||||||
|
args[0] = ti_ptr;
|
||||||
|
ti_ptr = ir_emit_global_call(proc, "type_info_base", args, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
irValue *enum_info = ir_emit_conv(proc, ti_ptr, t_type_info_enum_ptr);
|
||||||
|
irValue *names_ptr = ir_emit_struct_ep(proc, enum_info, 1);
|
||||||
|
return ir_make_addr(names_ptr);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
GB_PANIC("Unhandled enum index %d %.*s", index, LIT(selector));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type = base_type(type);
|
||||||
|
|
||||||
if (type == t_invalid) {
|
if (type == t_invalid) {
|
||||||
// NOTE(bill): Imports
|
// NOTE(bill): Imports
|
||||||
@@ -4056,18 +4070,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
return ir_make_addr(addr);
|
return ir_make_addr(addr);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(de, DemaybeExpr, expr);
|
|
||||||
ir_emit_comment(proc, str_lit("DemaybeExpr"));
|
|
||||||
irValue *maybe = ir_build_expr(proc, de->expr);
|
|
||||||
Type *t = default_type(type_of_expr(proc->module->info, expr));
|
|
||||||
GB_ASSERT(is_type_tuple(t));
|
|
||||||
|
|
||||||
irValue *result = ir_add_local_generated(proc, t);
|
|
||||||
ir_emit_store(proc, result, maybe);
|
|
||||||
|
|
||||||
return ir_make_addr(result);
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(ce, CallExpr, expr);
|
case_ast_node(ce, CallExpr, expr);
|
||||||
// NOTE(bill): This is make sure you never need to have an `array_ev`
|
// NOTE(bill): This is make sure you never need to have an `array_ev`
|
||||||
irValue *e = ir_build_expr(proc, expr);
|
irValue *e = ir_build_expr(proc, expr);
|
||||||
@@ -5253,7 +5255,13 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
ir_emit_comment(proc, str_lit("TypeMatchStmt"));
|
ir_emit_comment(proc, str_lit("TypeMatchStmt"));
|
||||||
gbAllocator allocator = proc->module->allocator;
|
gbAllocator allocator = proc->module->allocator;
|
||||||
|
|
||||||
irValue *parent = ir_build_expr(proc, ms->tag);
|
ast_node(as, AssignStmt, ms->tag);
|
||||||
|
GB_ASSERT(as->lhs.count == 1);
|
||||||
|
GB_ASSERT(as->rhs.count == 1);
|
||||||
|
AstNode *lhs = as->lhs.e[0];
|
||||||
|
AstNode *rhs = as->rhs.e[0];
|
||||||
|
|
||||||
|
irValue *parent = ir_build_expr(proc, rhs);
|
||||||
bool is_union_ptr = false;
|
bool is_union_ptr = false;
|
||||||
bool is_any = false;
|
bool is_any = false;
|
||||||
GB_ASSERT(check_valid_type_match_type(ir_type(parent), &is_union_ptr, &is_any));
|
GB_ASSERT(check_valid_type_match_type(ir_type(parent), &is_union_ptr, &is_any));
|
||||||
@@ -5274,7 +5282,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
ast_node(body, BlockStmt, ms->body);
|
ast_node(body, BlockStmt, ms->body);
|
||||||
|
|
||||||
String tag_var_name = ms->var->Ident.string;
|
String tag_var_name = lhs->Ident.string;
|
||||||
|
|
||||||
|
|
||||||
AstNodeArray default_stmts = {0};
|
AstNodeArray default_stmts = {0};
|
||||||
irBlock *default_block = NULL;
|
irBlock *default_block = NULL;
|
||||||
@@ -5291,19 +5300,32 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
default_block = ir_new_block(proc, clause, "type-match.dflt.body");
|
default_block = ir_new_block(proc, clause, "type-match.dflt.body");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
GB_ASSERT(cc->list.count == 1);
|
||||||
|
|
||||||
|
|
||||||
irBlock *body = ir_new_block(proc, clause, "type-match.case.body");
|
irBlock *body = ir_new_block(proc, clause, "type-match.case.body");
|
||||||
|
|
||||||
Scope *scope = *map_scope_get(&proc->module->info->scopes, hash_pointer(clause));
|
Entity *tag_var_entity = NULL;
|
||||||
Entity *tag_var_entity = current_scope_lookup_entity(scope, tag_var_name);
|
Type *tag_var_type = NULL;
|
||||||
GB_ASSERT_MSG(tag_var_entity != NULL, "%.*s", LIT(tag_var_name));
|
if (str_eq(tag_var_name, str_lit("_"))) {
|
||||||
|
Type *t = type_of_expr(proc->module->info, cc->list.e[0]);
|
||||||
|
if (is_union_ptr) {
|
||||||
|
t = make_type_pointer(proc->module->allocator, t);
|
||||||
|
}
|
||||||
|
tag_var_type = t;
|
||||||
|
} else {
|
||||||
|
Scope *scope = *map_scope_get(&proc->module->info->scopes, hash_pointer(clause));
|
||||||
|
tag_var_entity = current_scope_lookup_entity(scope, tag_var_name);
|
||||||
|
GB_ASSERT_MSG(tag_var_entity != NULL, "%.*s", LIT(tag_var_name));
|
||||||
|
tag_var_type = tag_var_entity->type;
|
||||||
|
}
|
||||||
|
GB_ASSERT(tag_var_type != NULL);
|
||||||
|
|
||||||
irBlock *next_cond = NULL;
|
irBlock *next_cond = NULL;
|
||||||
irValue *cond = NULL;
|
irValue *cond = NULL;
|
||||||
|
|
||||||
if (is_union_ptr) {
|
if (is_union_ptr) {
|
||||||
Type *bt = type_deref(tag_var_entity->type);
|
Type *bt = type_deref(tag_var_type);
|
||||||
irValue *index = NULL;
|
irValue *index = NULL;
|
||||||
Type *ut = base_type(type_deref(ir_type(parent)));
|
Type *ut = base_type(type_deref(ir_type(parent)));
|
||||||
GB_ASSERT(ut->Record.kind == TypeRecord_Union);
|
GB_ASSERT(ut->Record.kind == TypeRecord_Union);
|
||||||
@@ -5316,16 +5338,25 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
}
|
}
|
||||||
GB_ASSERT(index != NULL);
|
GB_ASSERT(index != NULL);
|
||||||
|
|
||||||
irValue *tag_var = ir_add_local(proc, tag_var_entity);
|
irValue *tag_var = NULL;
|
||||||
irValue *data_ptr = ir_emit_conv(proc, union_data, tag_var_entity->type);
|
if (tag_var_entity != NULL) {
|
||||||
|
tag_var = ir_add_local(proc, tag_var_entity);
|
||||||
|
} else {
|
||||||
|
tag_var = ir_add_local_generated(proc, tag_var_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
irValue *data_ptr = ir_emit_conv(proc, union_data, tag_var_type);
|
||||||
ir_emit_store(proc, tag_var, data_ptr);
|
ir_emit_store(proc, tag_var, data_ptr);
|
||||||
|
|
||||||
cond = ir_emit_comp(proc, Token_CmpEq, tag_index, index);
|
cond = ir_emit_comp(proc, Token_CmpEq, tag_index, index);
|
||||||
} else if (is_any) {
|
} else if (is_any) {
|
||||||
Type *type = tag_var_entity->type;
|
Type *type = tag_var_type;
|
||||||
irValue *any_data = ir_emit_struct_ev(proc, parent, 1);
|
irValue *any_data = ir_emit_struct_ev(proc, parent, 1);
|
||||||
irValue *data = ir_emit_conv(proc, any_data, make_type_pointer(proc->module->allocator, type));
|
irValue *data = ir_emit_conv(proc, any_data, make_type_pointer(proc->module->allocator, type));
|
||||||
ir_module_add_value(proc->module, tag_var_entity, data);
|
if (tag_var_entity != NULL) {
|
||||||
|
ir_module_add_value(proc->module, tag_var_entity, data);
|
||||||
|
}
|
||||||
|
|
||||||
irValue *any_ti = ir_emit_struct_ev(proc, parent, 0);
|
irValue *any_ti = ir_emit_struct_ev(proc, parent, 0);
|
||||||
irValue *case_ti = ir_type_info(proc, type);
|
irValue *case_ti = ir_type_info(proc, type);
|
||||||
@@ -6228,11 +6259,6 @@ void ir_gen_tree(irGen *s) {
|
|||||||
irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Pointer.elem);
|
irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Pointer.elem);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
||||||
} break;
|
} break;
|
||||||
case Type_Maybe: {
|
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_maybe_ptr);
|
|
||||||
irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Maybe.elem);
|
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
|
||||||
} break;
|
|
||||||
case Type_Array: {
|
case Type_Array: {
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_array_ptr);
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_array_ptr);
|
||||||
irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Array.elem);
|
irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Array.elem);
|
||||||
|
|||||||
@@ -172,13 +172,6 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
|||||||
ir_print_type(f, m, t->Pointer.elem);
|
ir_print_type(f, m, t->Pointer.elem);
|
||||||
ir_fprintf(f, "*");
|
ir_fprintf(f, "*");
|
||||||
return;
|
return;
|
||||||
case Type_Maybe:
|
|
||||||
ir_fprintf(f, "{");
|
|
||||||
ir_print_type(f, m, t->Maybe.elem);
|
|
||||||
ir_fprintf(f, ", ");
|
|
||||||
ir_print_type(f, m, t_bool);
|
|
||||||
ir_fprintf(f, "}");
|
|
||||||
return;
|
|
||||||
case Type_Array:
|
case Type_Array:
|
||||||
ir_fprintf(f, "[%lld x ", t->Array.count);
|
ir_fprintf(f, "[%lld x ", t->Array.count);
|
||||||
ir_print_type(f, m, t->Array.elem);
|
ir_print_type(f, m, t->Array.elem);
|
||||||
@@ -306,25 +299,11 @@ void ir_print_compound_element(irFileBuffer *f, irModule *m, ExactValue v, Type
|
|||||||
ir_print_type(f, m, elem_type);
|
ir_print_type(f, m, elem_type);
|
||||||
ir_fprintf(f, " ");
|
ir_fprintf(f, " ");
|
||||||
|
|
||||||
if (v.kind != ExactValue_Invalid && is_type_maybe(elem_type)) {
|
|
||||||
Type *t = base_type(elem_type)->Maybe.elem;
|
|
||||||
ir_fprintf(f, "{");
|
|
||||||
ir_print_type(f, m, t);
|
|
||||||
ir_fprintf(f, " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v.kind == ExactValue_Invalid || base_type(elem_type) == t_any) {
|
if (v.kind == ExactValue_Invalid || base_type(elem_type) == t_any) {
|
||||||
ir_fprintf(f, "zeroinitializer");
|
ir_fprintf(f, "zeroinitializer");
|
||||||
} else {
|
} else {
|
||||||
ir_print_exact_value(f, m, v, elem_type);
|
ir_print_exact_value(f, m, v, elem_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v.kind != ExactValue_Invalid && is_type_maybe(elem_type)) {
|
|
||||||
ir_fprintf(f, ", ");
|
|
||||||
ir_print_type(f, m, t_bool);
|
|
||||||
ir_fprintf(f, " ");
|
|
||||||
ir_fprintf(f, "true}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type) {
|
void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type) {
|
||||||
|
|||||||
+38
-80
@@ -147,7 +147,6 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
|
|||||||
AST_NODE_KIND(SelectorExpr, "selector expression", struct { Token token; AstNode *expr, *selector; }) \
|
AST_NODE_KIND(SelectorExpr, "selector expression", struct { Token token; AstNode *expr, *selector; }) \
|
||||||
AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \
|
AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \
|
||||||
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
|
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
|
||||||
AST_NODE_KIND(DemaybeExpr, "demaybe expression", struct { Token op; AstNode *expr; }) \
|
|
||||||
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
|
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
|
||||||
AstNode *expr; \
|
AstNode *expr; \
|
||||||
Token open, close, interval; \
|
Token open, close, interval; \
|
||||||
@@ -251,7 +250,6 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
|
|||||||
AST_NODE_KIND(TypeMatchStmt, "type match statement", struct { \
|
AST_NODE_KIND(TypeMatchStmt, "type match statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *tag; \
|
AstNode *tag; \
|
||||||
AstNode *var; \
|
|
||||||
AstNode *body; \
|
AstNode *body; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(DeferStmt, "defer statement", struct { Token token; AstNode *stmt; }) \
|
AST_NODE_KIND(DeferStmt, "defer statement", struct { Token token; AstNode *stmt; }) \
|
||||||
@@ -333,10 +331,6 @@ AST_NODE_KIND(_TypeBegin, "", i32) \
|
|||||||
Token token; \
|
Token token; \
|
||||||
AstNode *type; \
|
AstNode *type; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(MaybeType, "maybe type", struct { \
|
|
||||||
Token token; \
|
|
||||||
AstNode *type; \
|
|
||||||
}) \
|
|
||||||
AST_NODE_KIND(ArrayType, "array type", struct { \
|
AST_NODE_KIND(ArrayType, "array type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *count; \
|
AstNode *count; \
|
||||||
@@ -469,7 +463,6 @@ Token ast_node_token(AstNode *node) {
|
|||||||
case AstNode_CastExpr: return node->CastExpr.token;
|
case AstNode_CastExpr: return node->CastExpr.token;
|
||||||
case AstNode_FieldValue: return node->FieldValue.eq;
|
case AstNode_FieldValue: return node->FieldValue.eq;
|
||||||
case AstNode_DerefExpr: return node->DerefExpr.op;
|
case AstNode_DerefExpr: return node->DerefExpr.op;
|
||||||
case AstNode_DemaybeExpr: return node->DemaybeExpr.op;
|
|
||||||
case AstNode_BlockExpr: return node->BlockExpr.open;
|
case AstNode_BlockExpr: return node->BlockExpr.open;
|
||||||
case AstNode_GiveExpr: return node->GiveExpr.token;
|
case AstNode_GiveExpr: return node->GiveExpr.token;
|
||||||
case AstNode_IfExpr: return node->IfExpr.token;
|
case AstNode_IfExpr: return node->IfExpr.token;
|
||||||
@@ -513,7 +506,6 @@ Token ast_node_token(AstNode *node) {
|
|||||||
case AstNode_HelperType: return node->HelperType.token;
|
case AstNode_HelperType: return node->HelperType.token;
|
||||||
case AstNode_ProcType: return node->ProcType.token;
|
case AstNode_ProcType: return node->ProcType.token;
|
||||||
case AstNode_PointerType: return node->PointerType.token;
|
case AstNode_PointerType: return node->PointerType.token;
|
||||||
case AstNode_MaybeType: return node->MaybeType.token;
|
|
||||||
case AstNode_ArrayType: return node->ArrayType.token;
|
case AstNode_ArrayType: return node->ArrayType.token;
|
||||||
case AstNode_DynamicArrayType: return node->DynamicArrayType.token;
|
case AstNode_DynamicArrayType: return node->DynamicArrayType.token;
|
||||||
case AstNode_VectorType: return node->VectorType.token;
|
case AstNode_VectorType: return node->VectorType.token;
|
||||||
@@ -693,13 +685,6 @@ AstNode *ast_deref_expr(AstFile *f, AstNode *expr, Token op) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *ast_demaybe_expr(AstFile *f, AstNode *expr, Token op) {
|
|
||||||
AstNode *result = make_ast_node(f, AstNode_DemaybeExpr);
|
|
||||||
result->DemaybeExpr.expr = expr;
|
|
||||||
result->DemaybeExpr.op = op;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *ast_interval_expr(AstFile *f, Token op, AstNode *left, AstNode *right) {
|
AstNode *ast_interval_expr(AstFile *f, Token op, AstNode *left, AstNode *right) {
|
||||||
AstNode *result = make_ast_node(f, AstNode_IntervalExpr);
|
AstNode *result = make_ast_node(f, AstNode_IntervalExpr);
|
||||||
|
|
||||||
@@ -907,11 +892,10 @@ AstNode *ast_match_stmt(AstFile *f, Token token, AstNode *init, AstNode *tag, As
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AstNode *ast_type_match_stmt(AstFile *f, Token token, AstNode *tag, AstNode *var, AstNode *body) {
|
AstNode *ast_type_match_stmt(AstFile *f, Token token, AstNode *tag, AstNode *body) {
|
||||||
AstNode *result = make_ast_node(f, AstNode_TypeMatchStmt);
|
AstNode *result = make_ast_node(f, AstNode_TypeMatchStmt);
|
||||||
result->TypeMatchStmt.token = token;
|
result->TypeMatchStmt.token = token;
|
||||||
result->TypeMatchStmt.tag = tag;
|
result->TypeMatchStmt.tag = tag;
|
||||||
result->TypeMatchStmt.var = var;
|
|
||||||
result->TypeMatchStmt.body = body;
|
result->TypeMatchStmt.body = body;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1031,13 +1015,6 @@ AstNode *ast_pointer_type(AstFile *f, Token token, AstNode *type) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *ast_maybe_type(AstFile *f, Token token, AstNode *type) {
|
|
||||||
AstNode *result = make_ast_node(f, AstNode_MaybeType);
|
|
||||||
result->MaybeType.token = token;
|
|
||||||
result->MaybeType.type = type;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *ast_array_type(AstFile *f, Token token, AstNode *count, AstNode *elem) {
|
AstNode *ast_array_type(AstFile *f, Token token, AstNode *count, AstNode *elem) {
|
||||||
AstNode *result = make_ast_node(f, AstNode_ArrayType);
|
AstNode *result = make_ast_node(f, AstNode_ArrayType);
|
||||||
result->ArrayType.token = token;
|
result->ArrayType.token = token;
|
||||||
@@ -1777,6 +1754,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
} else if (str_eq(name.string, str_lit("file"))) { return ast_basic_directive(f, token, name.string);
|
} else if (str_eq(name.string, str_lit("file"))) { return ast_basic_directive(f, token, name.string);
|
||||||
} else if (str_eq(name.string, str_lit("line"))) { return ast_basic_directive(f, token, name.string);
|
} else if (str_eq(name.string, str_lit("line"))) { return ast_basic_directive(f, token, name.string);
|
||||||
} else if (str_eq(name.string, str_lit("procedure"))) { return ast_basic_directive(f, token, name.string);
|
} else if (str_eq(name.string, str_lit("procedure"))) { return ast_basic_directive(f, token, name.string);
|
||||||
|
} else if (str_eq(name.string, str_lit("type"))) { return ast_helper_type(f, token, parse_type(f));
|
||||||
} else {
|
} else {
|
||||||
operand = ast_tag_expr(f, token, name, parse_expr(f, false));
|
operand = ast_tag_expr(f, token, name, parse_expr(f, false));
|
||||||
}
|
}
|
||||||
@@ -1999,10 +1977,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
|||||||
operand = ast_deref_expr(f, operand, expect_token(f, Token_Pointer));
|
operand = ast_deref_expr(f, operand, expect_token(f, Token_Pointer));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Token_Maybe: // Demaybe
|
|
||||||
operand = ast_demaybe_expr(f, operand, expect_token(f, Token_Maybe));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Token_OpenBrace:
|
case Token_OpenBrace:
|
||||||
if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
|
if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
|
||||||
operand = parse_literal_value(f, operand);
|
operand = parse_literal_value(f, operand);
|
||||||
@@ -2205,9 +2179,7 @@ AstNode *parse_value_decl(AstFile *f, AstNodeArray lhs) {
|
|||||||
bool is_mutable = true;
|
bool is_mutable = true;
|
||||||
|
|
||||||
if (allow_token(f, Token_Colon)) {
|
if (allow_token(f, Token_Colon)) {
|
||||||
if (!allow_token(f, Token_type)) {
|
type = parse_type_attempt(f);
|
||||||
type = parse_type_attempt(f);
|
|
||||||
}
|
|
||||||
} else if (f->curr_token.kind != Token_Eq &&
|
} else if (f->curr_token.kind != Token_Eq &&
|
||||||
f->curr_token.kind != Token_Semicolon) {
|
f->curr_token.kind != Token_Semicolon) {
|
||||||
syntax_error(f->curr_token, "Expected a type separator `:` or `=`");
|
syntax_error(f->curr_token, "Expected a type separator `:` or `=`");
|
||||||
@@ -2553,10 +2525,16 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Token_type: {
|
case Token_Hash: {
|
||||||
Token token = expect_token(f, Token_type);
|
Token hash_token = expect_token(f, Token_Hash);
|
||||||
AstNode *type = parse_type(f);
|
Token name = expect_token(f, Token_Ident);
|
||||||
return ast_helper_type(f, token, type);
|
String tag = name.string;
|
||||||
|
if (str_eq(tag, str_lit("type"))) {
|
||||||
|
AstNode *type = parse_type(f);
|
||||||
|
return ast_helper_type(f, hash_token, type);
|
||||||
|
}
|
||||||
|
syntax_error(name, "Expected `type` after #");
|
||||||
|
return ast_bad_expr(f, hash_token, f->curr_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Token_Pointer: {
|
case Token_Pointer: {
|
||||||
@@ -2565,12 +2543,6 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
|||||||
return ast_pointer_type(f, token, elem);
|
return ast_pointer_type(f, token, elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Token_Maybe: {
|
|
||||||
Token token = expect_token(f, Token_Maybe);
|
|
||||||
AstNode *elem = parse_type(f);
|
|
||||||
return ast_maybe_type(f, token, elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
case Token_OpenBracket: {
|
case Token_OpenBracket: {
|
||||||
Token token = expect_token(f, Token_OpenBracket);
|
Token token = expect_token(f, Token_OpenBracket);
|
||||||
AstNode *count_expr = NULL;
|
AstNode *count_expr = NULL;
|
||||||
@@ -2972,8 +2944,7 @@ AstNode *parse_for_stmt(AstFile *f) {
|
|||||||
f->expr_level = -1;
|
f->expr_level = -1;
|
||||||
if (f->curr_token.kind != Token_Semicolon) {
|
if (f->curr_token.kind != Token_Semicolon) {
|
||||||
cond = parse_simple_stmt(f, true);
|
cond = parse_simple_stmt(f, true);
|
||||||
if (cond->kind == AstNode_AssignStmt &&
|
if (cond->kind == AstNode_AssignStmt && cond->AssignStmt.op.kind == Token_in) {
|
||||||
cond->AssignStmt.op.kind == Token_in) {
|
|
||||||
is_range = true;
|
is_range = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3065,6 +3036,7 @@ AstNode *parse_for_stmt(AstFile *f) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AstNode *parse_case_clause(AstFile *f) {
|
AstNode *parse_case_clause(AstFile *f) {
|
||||||
Token token = f->curr_token;
|
Token token = f->curr_token;
|
||||||
AstNodeArray list = make_ast_node_array(f);
|
AstNodeArray list = make_ast_node_array(f);
|
||||||
@@ -3097,6 +3069,7 @@ AstNode *parse_type_case_clause(AstFile *f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AstNode *parse_match_stmt(AstFile *f) {
|
AstNode *parse_match_stmt(AstFile *f) {
|
||||||
if (f->curr_proc == NULL) {
|
if (f->curr_proc == NULL) {
|
||||||
syntax_error(f->curr_token, "You cannot use a match statement in the file scope");
|
syntax_error(f->curr_token, "You cannot use a match statement in the file scope");
|
||||||
@@ -3108,37 +3081,16 @@ AstNode *parse_match_stmt(AstFile *f) {
|
|||||||
AstNode *tag = NULL;
|
AstNode *tag = NULL;
|
||||||
AstNode *body = NULL;
|
AstNode *body = NULL;
|
||||||
Token open, close;
|
Token open, close;
|
||||||
|
bool is_type_match = false;
|
||||||
|
|
||||||
if (allow_token(f, Token_type)) {
|
if (f->curr_token.kind != Token_OpenBrace) {
|
||||||
isize prev_level = f->expr_level;
|
isize prev_level = f->expr_level;
|
||||||
f->expr_level = -1;
|
f->expr_level = -1;
|
||||||
|
|
||||||
AstNode *var = parse_ident(f);
|
tag = parse_simple_stmt(f, true);
|
||||||
expect_token_after(f, Token_in, "match type name");
|
if (tag->kind == AstNode_AssignStmt && tag->AssignStmt.op.kind == Token_in) {
|
||||||
tag = parse_simple_stmt(f, false);
|
is_type_match = true;
|
||||||
|
} else {
|
||||||
f->expr_level = prev_level;
|
|
||||||
|
|
||||||
open = expect_token(f, Token_OpenBrace);
|
|
||||||
AstNodeArray list = make_ast_node_array(f);
|
|
||||||
|
|
||||||
while (f->curr_token.kind == Token_case ||
|
|
||||||
f->curr_token.kind == Token_default) {
|
|
||||||
array_add(&list, parse_type_case_clause(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
close = expect_token(f, Token_CloseBrace);
|
|
||||||
body = ast_block_stmt(f, list, open, close);
|
|
||||||
|
|
||||||
tag = convert_stmt_to_expr(f, tag, str_lit("type match expression"));
|
|
||||||
return ast_type_match_stmt(f, token, tag, var, body);
|
|
||||||
} else {
|
|
||||||
if (f->curr_token.kind != Token_OpenBrace) {
|
|
||||||
isize prev_level = f->expr_level;
|
|
||||||
f->expr_level = -1;
|
|
||||||
if (f->curr_token.kind != Token_Semicolon) {
|
|
||||||
tag = parse_simple_stmt(f, false);
|
|
||||||
}
|
|
||||||
if (allow_token(f, Token_Semicolon)) {
|
if (allow_token(f, Token_Semicolon)) {
|
||||||
init = tag;
|
init = tag;
|
||||||
tag = NULL;
|
tag = NULL;
|
||||||
@@ -3146,28 +3098,33 @@ AstNode *parse_match_stmt(AstFile *f) {
|
|||||||
tag = parse_simple_stmt(f, false);
|
tag = parse_simple_stmt(f, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f->expr_level = prev_level;
|
|
||||||
}
|
}
|
||||||
|
f->expr_level = prev_level;
|
||||||
|
}
|
||||||
|
open = expect_token(f, Token_OpenBrace);
|
||||||
|
AstNodeArray list = make_ast_node_array(f);
|
||||||
|
|
||||||
open = expect_token(f, Token_OpenBrace);
|
while (f->curr_token.kind == Token_case ||
|
||||||
AstNodeArray list = make_ast_node_array(f);
|
f->curr_token.kind == Token_default) {
|
||||||
|
if (is_type_match) {
|
||||||
while (f->curr_token.kind == Token_case ||
|
array_add(&list, parse_type_case_clause(f));
|
||||||
f->curr_token.kind == Token_default) {
|
} else {
|
||||||
array_add(&list, parse_case_clause(f));
|
array_add(&list, parse_case_clause(f));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
close = expect_token(f, Token_CloseBrace);
|
close = expect_token(f, Token_CloseBrace);
|
||||||
|
|
||||||
body = ast_block_stmt(f, list, open, close);
|
body = ast_block_stmt(f, list, open, close);
|
||||||
|
|
||||||
|
if (!is_type_match) {
|
||||||
tag = convert_stmt_to_expr(f, tag, str_lit("match expression"));
|
tag = convert_stmt_to_expr(f, tag, str_lit("match expression"));
|
||||||
return ast_match_stmt(f, token, init, tag, body);
|
return ast_match_stmt(f, token, init, tag, body);
|
||||||
|
} else {
|
||||||
|
return ast_type_match_stmt(f, token, tag, body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AstNode *parse_defer_stmt(AstFile *f) {
|
AstNode *parse_defer_stmt(AstFile *f) {
|
||||||
if (f->curr_proc == NULL) {
|
if (f->curr_proc == NULL) {
|
||||||
syntax_error(f->curr_token, "You cannot use a defer statement in the file scope");
|
syntax_error(f->curr_token, "You cannot use a defer statement in the file scope");
|
||||||
@@ -3359,6 +3316,7 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
Token hash_token = expect_token(f, Token_Hash);
|
Token hash_token = expect_token(f, Token_Hash);
|
||||||
Token name = expect_token(f, Token_Ident);
|
Token name = expect_token(f, Token_Ident);
|
||||||
String tag = name.string;
|
String tag = name.string;
|
||||||
|
|
||||||
if (str_eq(tag, str_lit("import"))) {
|
if (str_eq(tag, str_lit("import"))) {
|
||||||
AstNode *cond = NULL;
|
AstNode *cond = NULL;
|
||||||
Token import_name = {0};
|
Token import_name = {0};
|
||||||
|
|||||||
+84
-123
@@ -12,23 +12,24 @@ TOKEN_KIND(Token__LiteralBegin, "_LiteralBegin"), \
|
|||||||
TOKEN_KIND(Token__LiteralEnd, "_LiteralEnd"), \
|
TOKEN_KIND(Token__LiteralEnd, "_LiteralEnd"), \
|
||||||
\
|
\
|
||||||
TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
|
TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
|
||||||
TOKEN_KIND(Token_Eq, "="), \
|
TOKEN_KIND(Token_Eq, "="), \
|
||||||
TOKEN_KIND(Token_Not, "!"), \
|
TOKEN_KIND(Token_Not, "!"), \
|
||||||
TOKEN_KIND(Token_Hash, "#"), \
|
TOKEN_KIND(Token_Hash, "#"), \
|
||||||
TOKEN_KIND(Token_At, "@"), \
|
TOKEN_KIND(Token_At, "@"), \
|
||||||
TOKEN_KIND(Token_Pointer, "^"), \
|
TOKEN_KIND(Token_Dollar, "$"), \
|
||||||
TOKEN_KIND(Token_Maybe, "?"), \
|
TOKEN_KIND(Token_Pointer, "^"), \
|
||||||
TOKEN_KIND(Token_Add, "+"), \
|
TOKEN_KIND(Token_Question, "?"), \
|
||||||
TOKEN_KIND(Token_Sub, "-"), \
|
TOKEN_KIND(Token_Add, "+"), \
|
||||||
TOKEN_KIND(Token_Mul, "*"), \
|
TOKEN_KIND(Token_Sub, "-"), \
|
||||||
TOKEN_KIND(Token_Quo, "/"), \
|
TOKEN_KIND(Token_Mul, "*"), \
|
||||||
TOKEN_KIND(Token_Mod, "%"), \
|
TOKEN_KIND(Token_Quo, "/"), \
|
||||||
TOKEN_KIND(Token_And, "&"), \
|
TOKEN_KIND(Token_Mod, "%"), \
|
||||||
TOKEN_KIND(Token_Or, "|"), \
|
TOKEN_KIND(Token_And, "&"), \
|
||||||
TOKEN_KIND(Token_Xor, "~"), \
|
TOKEN_KIND(Token_Or, "|"), \
|
||||||
TOKEN_KIND(Token_AndNot, "&~"), \
|
TOKEN_KIND(Token_Xor, "~"), \
|
||||||
TOKEN_KIND(Token_Shl, "<<"), \
|
TOKEN_KIND(Token_AndNot, "&~"), \
|
||||||
TOKEN_KIND(Token_Shr, ">>"), \
|
TOKEN_KIND(Token_Shl, "<<"), \
|
||||||
|
TOKEN_KIND(Token_Shr, ">>"), \
|
||||||
\
|
\
|
||||||
/*TOKEN_KIND(Token_as, "as"), */\
|
/*TOKEN_KIND(Token_as, "as"), */\
|
||||||
/*TOKEN_KIND(Token_transmute, "transmute"), */\
|
/*TOKEN_KIND(Token_transmute, "transmute"), */\
|
||||||
@@ -55,6 +56,8 @@ TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
|
|||||||
TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \
|
TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \
|
||||||
TOKEN_KIND(Token_ArrowRight, "->"), \
|
TOKEN_KIND(Token_ArrowRight, "->"), \
|
||||||
TOKEN_KIND(Token_ArrowLeft, "<-"), \
|
TOKEN_KIND(Token_ArrowLeft, "<-"), \
|
||||||
|
TOKEN_KIND(Token_Increment, "++"), \
|
||||||
|
TOKEN_KIND(Token_Decrement, "--"), \
|
||||||
\
|
\
|
||||||
TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \
|
TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \
|
||||||
TOKEN_KIND(Token_CmpEq, "=="), \
|
TOKEN_KIND(Token_CmpEq, "=="), \
|
||||||
@@ -80,45 +83,45 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
|
|||||||
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
||||||
\
|
\
|
||||||
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||||
/* TODO(bill): So of these keywords are not used but "reserved", why not remove them? */ \
|
/* TODO(bill): Of these keywords are not used but "reserved", why not remove them? */ \
|
||||||
TOKEN_KIND(Token_when, "when"), \
|
TOKEN_KIND(Token_when, "when"), \
|
||||||
TOKEN_KIND(Token_if, "if"), \
|
TOKEN_KIND(Token_if, "if"), \
|
||||||
TOKEN_KIND(Token_else, "else"), \
|
TOKEN_KIND(Token_else, "else"), \
|
||||||
TOKEN_KIND(Token_for, "for"), \
|
TOKEN_KIND(Token_for, "for"), \
|
||||||
TOKEN_KIND(Token_in, "in"), \
|
TOKEN_KIND(Token_in, "in"), \
|
||||||
TOKEN_KIND(Token_break, "break"), \
|
TOKEN_KIND(Token_break, "break"), \
|
||||||
TOKEN_KIND(Token_continue, "continue"), \
|
TOKEN_KIND(Token_continue, "continue"), \
|
||||||
TOKEN_KIND(Token_fallthrough, "fallthrough"), \
|
TOKEN_KIND(Token_fallthrough, "fallthrough"), \
|
||||||
TOKEN_KIND(Token_match, "match"), \
|
TOKEN_KIND(Token_match, "match"), \
|
||||||
TOKEN_KIND(Token_type, "type"), \
|
/* TOKEN_KIND(Token_type, "type"), */ \
|
||||||
TOKEN_KIND(Token_default, "default"), \
|
TOKEN_KIND(Token_default, "default"), \
|
||||||
TOKEN_KIND(Token_case, "case"), \
|
TOKEN_KIND(Token_case, "case"), \
|
||||||
TOKEN_KIND(Token_defer, "defer"), \
|
TOKEN_KIND(Token_defer, "defer"), \
|
||||||
TOKEN_KIND(Token_return, "return"), \
|
TOKEN_KIND(Token_return, "return"), \
|
||||||
TOKEN_KIND(Token_give, "give"), \
|
TOKEN_KIND(Token_give, "give"), \
|
||||||
TOKEN_KIND(Token_proc, "proc"), \
|
TOKEN_KIND(Token_proc, "proc"), \
|
||||||
TOKEN_KIND(Token_macro, "macro"), \
|
TOKEN_KIND(Token_macro, "macro"), \
|
||||||
TOKEN_KIND(Token_struct, "struct"), \
|
TOKEN_KIND(Token_struct, "struct"), \
|
||||||
TOKEN_KIND(Token_union, "union"), \
|
TOKEN_KIND(Token_union, "union"), \
|
||||||
TOKEN_KIND(Token_raw_union, "raw_union"), \
|
TOKEN_KIND(Token_raw_union, "raw_union"), \
|
||||||
TOKEN_KIND(Token_enum, "enum"), \
|
TOKEN_KIND(Token_enum, "enum"), \
|
||||||
TOKEN_KIND(Token_vector, "vector"), \
|
TOKEN_KIND(Token_vector, "vector"), \
|
||||||
TOKEN_KIND(Token_map, "map"), \
|
TOKEN_KIND(Token_map, "map"), \
|
||||||
TOKEN_KIND(Token_static, "static"), \
|
TOKEN_KIND(Token_static, "static"), \
|
||||||
TOKEN_KIND(Token_dynamic, "dynamic"), \
|
TOKEN_KIND(Token_dynamic, "dynamic"), \
|
||||||
TOKEN_KIND(Token_using, "using"), \
|
TOKEN_KIND(Token_using, "using"), \
|
||||||
TOKEN_KIND(Token_no_alias, "no_alias"), \
|
TOKEN_KIND(Token_no_alias, "no_alias"), \
|
||||||
/* TOKEN_KIND(Token_mutable, "mutable"), */\
|
/* TOKEN_KIND(Token_mutable, "mutable"), */ \
|
||||||
/* TOKEN_KIND(Token_immutable, "immutable"), */\
|
/* TOKEN_KIND(Token_immutable, "immutable"), */\
|
||||||
TOKEN_KIND(Token_thread_local, "thread_local"), \
|
TOKEN_KIND(Token_thread_local, "thread_local"), \
|
||||||
TOKEN_KIND(Token_cast, "cast"), \
|
TOKEN_KIND(Token_cast, "cast"), \
|
||||||
TOKEN_KIND(Token_transmute, "transmute"), \
|
TOKEN_KIND(Token_transmute, "transmute"), \
|
||||||
TOKEN_KIND(Token_down_cast, "down_cast"), \
|
TOKEN_KIND(Token_down_cast, "down_cast"), \
|
||||||
TOKEN_KIND(Token_union_cast, "union_cast"), \
|
TOKEN_KIND(Token_union_cast, "union_cast"), \
|
||||||
TOKEN_KIND(Token_context, "context"), \
|
TOKEN_KIND(Token_context, "context"), \
|
||||||
TOKEN_KIND(Token_push_context, "push_context"), \
|
TOKEN_KIND(Token_push_context, "push_context"), \
|
||||||
TOKEN_KIND(Token_push_allocator, "push_allocator"), \
|
TOKEN_KIND(Token_push_allocator, "push_allocator"), \
|
||||||
TOKEN_KIND(Token_asm, "asm"), \
|
TOKEN_KIND(Token_asm, "asm"), \
|
||||||
TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \
|
TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \
|
||||||
TOKEN_KIND(Token_Count, "")
|
TOKEN_KIND(Token_Count, "")
|
||||||
|
|
||||||
@@ -478,7 +481,6 @@ gb_inline void scan_mantissa(Tokenizer *t, i32 base, bool allow_underscore) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
|
Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
|
||||||
Token token = {0};
|
Token token = {0};
|
||||||
token.kind = Token_Integer;
|
token.kind = Token_Integer;
|
||||||
@@ -734,20 +736,10 @@ Token tokenizer_get_token(Tokenizer *t) {
|
|||||||
|
|
||||||
// NOTE(bill): All keywords are > 1
|
// NOTE(bill): All keywords are > 1
|
||||||
if (token.string.len > 1) {
|
if (token.string.len > 1) {
|
||||||
/* if (str_eq(token.string, token_strings[Token_as])) {
|
for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
|
||||||
token.kind = Token_as;
|
if (str_eq(token.string, token_strings[k])) {
|
||||||
} else if (str_eq(token.string, token_strings[Token_transmute])) {
|
token.kind = cast(TokenKind)k;
|
||||||
token.kind = Token_transmute;
|
break;
|
||||||
} else if (str_eq(token.string, token_strings[Token_down_cast])) {
|
|
||||||
token.kind = Token_down_cast;
|
|
||||||
} else if (str_eq(token.string, token_strings[Token_union_cast])) {
|
|
||||||
token.kind = Token_union_cast;
|
|
||||||
} else */{
|
|
||||||
for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
|
|
||||||
if (str_eq(token.string, token_strings[k])) {
|
|
||||||
token.kind = cast(TokenKind)k;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -861,57 +853,28 @@ Token tokenizer_get_token(Tokenizer *t) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '#':
|
case '#': token.kind = Token_Hash; break;
|
||||||
token.kind = Token_Hash;
|
case '@': token.kind = Token_At; break;
|
||||||
break;
|
case '$': token.kind = Token_Dollar; break;
|
||||||
case '@':
|
case '?': token.kind = Token_Question; break;
|
||||||
token.kind = Token_At;
|
case '^': token.kind = Token_Pointer; break;
|
||||||
break;
|
case ';': token.kind = Token_Semicolon; break;
|
||||||
case '^':
|
case ',': token.kind = Token_Comma; break;
|
||||||
token.kind = Token_Pointer;
|
case ':': token.kind = Token_Colon; break;
|
||||||
break;
|
case '(': token.kind = Token_OpenParen; break;
|
||||||
case '?':
|
case ')': token.kind = Token_CloseParen; break;
|
||||||
token.kind = Token_Maybe;
|
case '[': token.kind = Token_OpenBracket; break;
|
||||||
break;
|
case ']': token.kind = Token_CloseBracket; break;
|
||||||
case ';':
|
case '{': token.kind = Token_OpenBrace; break;
|
||||||
token.kind = Token_Semicolon;
|
case '}': token.kind = Token_CloseBrace; break;
|
||||||
break;
|
|
||||||
case ',':
|
|
||||||
token.kind = Token_Comma;
|
|
||||||
break;
|
|
||||||
case ':':
|
|
||||||
token.kind = Token_Colon;
|
|
||||||
break;
|
|
||||||
case '(':
|
|
||||||
token.kind = Token_OpenParen;
|
|
||||||
break;
|
|
||||||
case ')':
|
|
||||||
token.kind = Token_CloseParen;
|
|
||||||
break;
|
|
||||||
case '[':
|
|
||||||
token.kind = Token_OpenBracket;
|
|
||||||
break;
|
|
||||||
case ']':
|
|
||||||
token.kind = Token_CloseBracket;
|
|
||||||
break;
|
|
||||||
case '{':
|
|
||||||
token.kind = Token_OpenBrace;
|
|
||||||
break;
|
|
||||||
case '}':
|
|
||||||
token.kind = Token_CloseBrace;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break;
|
case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break;
|
||||||
case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break;
|
case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break;
|
||||||
case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break;
|
case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break;
|
||||||
case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break;
|
case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break;
|
||||||
case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break;
|
case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break;
|
||||||
case '+':
|
case '+': token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Increment); break;
|
||||||
token.kind = token_kind_variant2(t, Token_Add, Token_AddEq);
|
case '-': token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Decrement, '>', Token_ArrowRight); break;
|
||||||
break;
|
|
||||||
case '-':
|
|
||||||
token.kind = token_kind_variant3(t, Token_Sub, Token_SubEq, '>', Token_ArrowRight);
|
|
||||||
break;
|
|
||||||
case '/': {
|
case '/': {
|
||||||
if (t->curr_rune == '/') {
|
if (t->curr_rune == '/') {
|
||||||
while (t->curr_rune != '\n' && t->curr_rune != GB_RUNE_EOF) {
|
while (t->curr_rune != '\n' && t->curr_rune != GB_RUNE_EOF) {
|
||||||
@@ -951,9 +914,7 @@ Token tokenizer_get_token(Tokenizer *t) {
|
|||||||
token.kind = token_kind_dub_eq(t, '<', Token_Lt, Token_LtEq, Token_Shl, Token_ShlEq);
|
token.kind = token_kind_dub_eq(t, '<', Token_Lt, Token_LtEq, Token_Shl, Token_ShlEq);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>': token.kind = token_kind_dub_eq(t, '>', Token_Gt, Token_GtEq, Token_Shr, Token_ShrEq); break;
|
||||||
token.kind = token_kind_dub_eq(t, '>', Token_Gt, Token_GtEq, Token_Shr, Token_ShrEq);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '&':
|
case '&':
|
||||||
token.kind = Token_And;
|
token.kind = Token_And;
|
||||||
|
|||||||
+31
-60
@@ -11,6 +11,20 @@ typedef enum BasicKind {
|
|||||||
Basic_u32,
|
Basic_u32,
|
||||||
Basic_i64,
|
Basic_i64,
|
||||||
Basic_u64,
|
Basic_u64,
|
||||||
|
|
||||||
|
/* Basic_i16le,
|
||||||
|
Basic_i16be,
|
||||||
|
Basic_u16le,
|
||||||
|
Basic_u16be,
|
||||||
|
Basic_i32le,
|
||||||
|
Basic_i32be,
|
||||||
|
Basic_u32le,
|
||||||
|
Basic_u32be,
|
||||||
|
Basic_i64le,
|
||||||
|
Basic_i64be,
|
||||||
|
Basic_u64le,
|
||||||
|
Basic_u64be, */
|
||||||
|
|
||||||
// Basic_i128,
|
// Basic_i128,
|
||||||
// Basic_u128,
|
// Basic_u128,
|
||||||
// Basic_f16,
|
// Basic_f16,
|
||||||
@@ -93,6 +107,7 @@ typedef struct TypeRecord {
|
|||||||
Entity * enum_count;
|
Entity * enum_count;
|
||||||
Entity * enum_min_value;
|
Entity * enum_min_value;
|
||||||
Entity * enum_max_value;
|
Entity * enum_max_value;
|
||||||
|
Entity * enum_names;
|
||||||
} TypeRecord;
|
} TypeRecord;
|
||||||
|
|
||||||
#define TYPE_KINDS \
|
#define TYPE_KINDS \
|
||||||
@@ -102,7 +117,6 @@ typedef struct TypeRecord {
|
|||||||
TYPE_KIND(DynamicArray, struct { Type *elem; }) \
|
TYPE_KIND(DynamicArray, struct { Type *elem; }) \
|
||||||
TYPE_KIND(Vector, struct { Type *elem; i64 count; }) \
|
TYPE_KIND(Vector, struct { Type *elem; i64 count; }) \
|
||||||
TYPE_KIND(Slice, struct { Type *elem; }) \
|
TYPE_KIND(Slice, struct { Type *elem; }) \
|
||||||
TYPE_KIND(Maybe, struct { Type *elem; }) \
|
|
||||||
TYPE_KIND(Record, TypeRecord) \
|
TYPE_KIND(Record, TypeRecord) \
|
||||||
TYPE_KIND(Named, struct { \
|
TYPE_KIND(Named, struct { \
|
||||||
String name; \
|
String name; \
|
||||||
@@ -177,16 +191,16 @@ typedef struct BaseTypeSizes {
|
|||||||
} BaseTypeSizes;
|
} BaseTypeSizes;
|
||||||
|
|
||||||
|
|
||||||
typedef Array(isize) Array_isize;
|
typedef Array(i32) Array_i32;
|
||||||
|
|
||||||
typedef struct Selection {
|
typedef struct Selection {
|
||||||
Entity * entity;
|
Entity * entity;
|
||||||
Array_isize index;
|
Array_i32 index;
|
||||||
bool indirect; // Set if there was a pointer deref anywhere down the line
|
bool indirect; // Set if there was a pointer deref anywhere down the line
|
||||||
} Selection;
|
} Selection;
|
||||||
Selection empty_selection = {0};
|
Selection empty_selection = {0};
|
||||||
|
|
||||||
Selection make_selection(Entity *entity, Array_isize index, bool indirect) {
|
Selection make_selection(Entity *entity, Array_i32 index, bool indirect) {
|
||||||
Selection s = {entity, index, indirect};
|
Selection s = {entity, index, indirect};
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -273,6 +287,7 @@ gb_global Type *t_int_ptr = NULL;
|
|||||||
gb_global Type *t_i64_ptr = NULL;
|
gb_global Type *t_i64_ptr = NULL;
|
||||||
gb_global Type *t_f64_ptr = NULL;
|
gb_global Type *t_f64_ptr = NULL;
|
||||||
gb_global Type *t_byte_slice = NULL;
|
gb_global Type *t_byte_slice = NULL;
|
||||||
|
gb_global Type *t_string_slice = NULL;
|
||||||
|
|
||||||
|
|
||||||
gb_global Type *t_type_info = NULL;
|
gb_global Type *t_type_info = NULL;
|
||||||
@@ -289,7 +304,6 @@ gb_global Type *t_type_info_any = NULL;
|
|||||||
gb_global Type *t_type_info_string = NULL;
|
gb_global Type *t_type_info_string = NULL;
|
||||||
gb_global Type *t_type_info_boolean = NULL;
|
gb_global Type *t_type_info_boolean = NULL;
|
||||||
gb_global Type *t_type_info_pointer = NULL;
|
gb_global Type *t_type_info_pointer = NULL;
|
||||||
gb_global Type *t_type_info_maybe = NULL;
|
|
||||||
gb_global Type *t_type_info_procedure = NULL;
|
gb_global Type *t_type_info_procedure = NULL;
|
||||||
gb_global Type *t_type_info_array = NULL;
|
gb_global Type *t_type_info_array = NULL;
|
||||||
gb_global Type *t_type_info_dynamic_array = NULL;
|
gb_global Type *t_type_info_dynamic_array = NULL;
|
||||||
@@ -310,7 +324,6 @@ gb_global Type *t_type_info_any_ptr = NULL;
|
|||||||
gb_global Type *t_type_info_string_ptr = NULL;
|
gb_global Type *t_type_info_string_ptr = NULL;
|
||||||
gb_global Type *t_type_info_boolean_ptr = NULL;
|
gb_global Type *t_type_info_boolean_ptr = NULL;
|
||||||
gb_global Type *t_type_info_pointer_ptr = NULL;
|
gb_global Type *t_type_info_pointer_ptr = NULL;
|
||||||
gb_global Type *t_type_info_maybe_ptr = NULL;
|
|
||||||
gb_global Type *t_type_info_procedure_ptr = NULL;
|
gb_global Type *t_type_info_procedure_ptr = NULL;
|
||||||
gb_global Type *t_type_info_array_ptr = NULL;
|
gb_global Type *t_type_info_array_ptr = NULL;
|
||||||
gb_global Type *t_type_info_dynamic_array_ptr = NULL;
|
gb_global Type *t_type_info_dynamic_array_ptr = NULL;
|
||||||
@@ -393,12 +406,6 @@ Type *make_type_pointer(gbAllocator a, Type *elem) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *make_type_maybe(gbAllocator a, Type *elem) {
|
|
||||||
Type *t = alloc_type(a, Type_Maybe);
|
|
||||||
t->Maybe.elem = elem;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
|
Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
|
||||||
Type *t = alloc_type(a, Type_Array);
|
Type *t = alloc_type(a, Type_Array);
|
||||||
t->Array.elem = elem;
|
t->Array.elem = elem;
|
||||||
@@ -630,10 +637,6 @@ bool is_type_pointer(Type *t) {
|
|||||||
}
|
}
|
||||||
return t->kind == Type_Pointer;
|
return t->kind == Type_Pointer;
|
||||||
}
|
}
|
||||||
bool is_type_maybe(Type *t) {
|
|
||||||
t = base_type(t);
|
|
||||||
return t->kind == Type_Maybe;
|
|
||||||
}
|
|
||||||
bool is_type_tuple(Type *t) {
|
bool is_type_tuple(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
return t->kind == Type_Tuple;
|
return t->kind == Type_Tuple;
|
||||||
@@ -780,7 +783,6 @@ bool type_has_nil(Type *t) {
|
|||||||
case Type_DynamicArray:
|
case Type_DynamicArray:
|
||||||
case Type_Proc:
|
case Type_Proc:
|
||||||
case Type_Pointer:
|
case Type_Pointer:
|
||||||
case Type_Maybe:
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -890,12 +892,6 @@ bool are_types_identical(Type *x, Type *y) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type_Maybe:
|
|
||||||
if (y->kind == Type_Maybe) {
|
|
||||||
return are_types_identical(x->Maybe.elem, y->Maybe.elem);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type_Named:
|
case Type_Named:
|
||||||
if (y->kind == Type_Named) {
|
if (y->kind == Type_Named) {
|
||||||
return x->Named.base == y->Named.base;
|
return x->Named.base == y->Named.base;
|
||||||
@@ -981,9 +977,6 @@ bool is_type_cte_safe(Type *type) {
|
|||||||
case Type_Slice:
|
case Type_Slice:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case Type_Maybe:
|
|
||||||
return is_type_cte_safe(type->Maybe.elem);
|
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
if (type->Record.kind != TypeRecord_Struct) {
|
if (type->Record.kind != TypeRecord_Struct) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1026,12 +1019,14 @@ typedef enum ProcTypeOverloadKind {
|
|||||||
ProcOverload_ResultCount,
|
ProcOverload_ResultCount,
|
||||||
ProcOverload_ResultTypes,
|
ProcOverload_ResultTypes,
|
||||||
|
|
||||||
|
ProcOverload_NotProcedure,
|
||||||
|
|
||||||
} ProcTypeOverloadKind;
|
} ProcTypeOverloadKind;
|
||||||
|
|
||||||
|
|
||||||
ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
|
ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
|
||||||
GB_ASSERT(is_type_proc(x));
|
if (!is_type_proc(x)) return ProcOverload_NotProcedure;
|
||||||
GB_ASSERT(is_type_proc(y));
|
if (!is_type_proc(y)) return ProcOverload_NotProcedure;
|
||||||
TypeProc *px = &base_type(x)->Proc;
|
TypeProc *px = &base_type(x)->Proc;
|
||||||
TypeProc *py = &base_type(y)->Proc;
|
TypeProc *py = &base_type(y)->Proc;
|
||||||
|
|
||||||
@@ -1113,7 +1108,7 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
|
|||||||
Entity *f = type->Record.fields[i];
|
Entity *f = type->Record.fields[i];
|
||||||
if (f->kind == Entity_Variable) {
|
if (f->kind == Entity_Variable) {
|
||||||
if (f->Variable.field_src_index == index) {
|
if (f->Variable.field_src_index == index) {
|
||||||
Array_isize sel_array = {0};
|
Array_i32 sel_array = {0};
|
||||||
array_init_count(&sel_array, a, 1);
|
array_init_count(&sel_array, a, 1);
|
||||||
sel_array.e[0] = i;
|
sel_array.e[0] = i;
|
||||||
return make_selection(f, sel_array, false);
|
return make_selection(f, sel_array, false);
|
||||||
@@ -1125,7 +1120,7 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
|
|||||||
for (isize i = 0; i < max_count; i++) {
|
for (isize i = 0; i < max_count; i++) {
|
||||||
Entity *f = type->Tuple.variables[i];
|
Entity *f = type->Tuple.variables[i];
|
||||||
if (i == index) {
|
if (i == index) {
|
||||||
Array_isize sel_array = {0};
|
Array_i32 sel_array = {0};
|
||||||
array_init_count(&sel_array, a, 1);
|
array_init_count(&sel_array, a, 1);
|
||||||
sel_array.e[0] = i;
|
sel_array.e[0] = i;
|
||||||
return make_selection(f, sel_array, false);
|
return make_selection(f, sel_array, false);
|
||||||
@@ -1352,6 +1347,10 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
|||||||
sel.entity = type->Record.enum_max_value;
|
sel.entity = type->Record.enum_max_value;
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
|
if (str_eq(field_name, str_lit("names"))) {
|
||||||
|
sel.entity = type->Record.enum_names;
|
||||||
|
return sel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (isize i = 0; i < type->Record.field_count; i++) {
|
for (isize i = 0; i < type->Record.field_count; i++) {
|
||||||
@@ -1558,17 +1557,6 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type
|
|||||||
return max;
|
return max;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Maybe: {
|
|
||||||
Type *elem = t->Maybe.elem;
|
|
||||||
type_path_push(path, elem);
|
|
||||||
if (path->failure) {
|
|
||||||
return FAILURE_ALIGNMENT;
|
|
||||||
}
|
|
||||||
i64 align = gb_max(type_align_of_internal(s, allocator, t->Maybe.elem, path), type_align_of_internal(s, allocator, t_bool, path));
|
|
||||||
type_path_pop(path);
|
|
||||||
return align;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Type_Map: {
|
case Type_Map: {
|
||||||
if (t->Map.count == 0) { // Dynamic
|
if (t->Map.count == 0) { // Dynamic
|
||||||
return type_align_of_internal(s, allocator, t->Map.generated_struct_type, path);
|
return type_align_of_internal(s, allocator, t->Map.generated_struct_type, path);
|
||||||
@@ -1773,18 +1761,6 @@ i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypeP
|
|||||||
case Type_Slice: // ptr + count
|
case Type_Slice: // ptr + count
|
||||||
return 2 * s.word_size;
|
return 2 * s.word_size;
|
||||||
|
|
||||||
case Type_Maybe: { // value + bool
|
|
||||||
i64 align, size;
|
|
||||||
Type *elem = t->Maybe.elem;
|
|
||||||
align = type_align_of_internal(s, allocator, elem, path);
|
|
||||||
if (path->failure) {
|
|
||||||
return FAILURE_SIZE;
|
|
||||||
}
|
|
||||||
size = align_formula(type_size_of_internal(s, allocator, elem, path), align);
|
|
||||||
size += type_size_of_internal(s, allocator, t_bool, path);
|
|
||||||
return align_formula(size, align);
|
|
||||||
}
|
|
||||||
|
|
||||||
case Type_Map: {
|
case Type_Map: {
|
||||||
if (t->Map.count == 0) { // Dynamic
|
if (t->Map.count == 0) { // Dynamic
|
||||||
return type_size_of_internal(s, allocator, t->Map.generated_struct_type, path);
|
return type_size_of_internal(s, allocator, t->Map.generated_struct_type, path);
|
||||||
@@ -1969,11 +1945,6 @@ gbString write_type_to_string(gbString str, Type *type) {
|
|||||||
str = write_type_to_string(str, type->Pointer.elem);
|
str = write_type_to_string(str, type->Pointer.elem);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type_Maybe:
|
|
||||||
str = gb_string_appendc(str, "?");
|
|
||||||
str = write_type_to_string(str, type->Maybe.elem);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type_Array:
|
case Type_Array:
|
||||||
str = gb_string_appendc(str, gb_bprintf("[%lld]", type->Array.count));
|
str = gb_string_appendc(str, gb_bprintf("[%lld]", type->Array.count));
|
||||||
str = write_type_to_string(str, type->Array.elem);
|
str = write_type_to_string(str, type->Array.elem);
|
||||||
|
|||||||
Reference in New Issue
Block a user