diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-07-13 16:20:07 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-07-13 16:20:07 +0100 |
| commit | b8697fb4ed34d0da0fa0888b57e6edcc37a0ce81 (patch) | |
| tree | fe3dd4008b6878b1b0b5015131e9a35129845123 | |
| parent | 03570275c1cfd14014d81bcdf085c320c1902c40 (diff) | |
Change precedence order for types e.g. ^T(x) == ^(T(x))
| -rw-r--r-- | code/demo.odin | 7 | ||||
| -rw-r--r-- | core/_preload.odin | 88 | ||||
| -rw-r--r-- | core/fmt.odin | 28 | ||||
| -rw-r--r-- | core/hash.odin | 6 | ||||
| -rw-r--r-- | core/mem.odin | 16 | ||||
| -rw-r--r-- | core/opengl.odin | 2 | ||||
| -rw-r--r-- | core/os.odin | 2 | ||||
| -rw-r--r-- | core/os_windows.odin | 4 | ||||
| -rw-r--r-- | core/strconv.odin | 4 | ||||
| -rw-r--r-- | core/strings.odin | 4 | ||||
| -rw-r--r-- | core/utf8.odin | 6 | ||||
| -rw-r--r-- | src/check_decl.cpp | 2 | ||||
| -rw-r--r-- | src/check_expr.cpp | 28 | ||||
| -rw-r--r-- | src/check_stmt.cpp | 11 | ||||
| -rw-r--r-- | src/checker.cpp | 8 | ||||
| -rw-r--r-- | src/ir.cpp | 31 | ||||
| -rw-r--r-- | src/ir_print.cpp | 3 | ||||
| -rw-r--r-- | src/parser.cpp | 465 | ||||
| -rw-r--r-- | src/types.cpp | 2 |
19 files changed, 479 insertions, 238 deletions
diff --git a/code/demo.odin b/code/demo.odin index d84539bce..8eeaeb357 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -219,7 +219,7 @@ call_location :: proc() { explicit_parametric_polymorphic_procedures :: proc() { // This is how `new` is actually implemented, see _preload.odin - alloc_type :: proc(T: type) -> ^T do return ^T(alloc(size_of(T), align_of(T))); + alloc_type :: proc(T: type) -> ^T do return cast(^T)alloc(size_of(T), align_of(T)); int_ptr := alloc_type(int); defer free(int_ptr); @@ -340,7 +340,7 @@ explicit_parametric_polymorphic_procedures :: proc() { result.x = x; result.y = y; - return ^T(&result.variant); + return cast(^T)&result.variant; } entities: [dynamic]^Entity; @@ -386,6 +386,7 @@ implicit_polymorphic_assignment :: proc() { main :: proc() { +/* foo :: proc(x: i64, y: f32) do fmt.println("#1", x, y); foo :: proc(x: type, y: f32) do fmt.println("#2", type_info(x), y); foo :: proc(x: type) do fmt.println("#3", type_info(x)); @@ -408,7 +409,7 @@ main :: proc() { // Command line argument(s)! // -opt=0,1,2,3 - +*/ /* program := "+ + * - /"; accumulator := 0; diff --git a/core/_preload.odin b/core/_preload.odin index 597ef284b..7e28735f3 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -319,8 +319,8 @@ append :: proc(array: ^[]$T, args: ...T) -> int #cc_contextless { arg_len = min(cap(array)-len(array), arg_len); if arg_len > 0 { - s := ^raw.Slice(array); - data := ^T(s.data); + s := cast(^raw.Slice)array; + data := cast(^T)s.data; assert(data != nil); sz :: size_of(T); __mem_copy(data + s.len, &args[0], sz*arg_len); @@ -344,8 +344,8 @@ append :: proc(array: ^[dynamic]$T, args: ...T) -> int { // TODO(bill): Better error handling for failed reservation if !ok do return len(array); - a := ^raw.DynamicArray(array); - data := ^T(a.data); + a := cast(^raw.DynamicArray)array; + data := cast(^T)a.data; assert(data != nil); __mem_copy(data + a.len, &args[0], size_of(T) * arg_len); a.len += arg_len; @@ -357,7 +357,7 @@ pop :: proc(array: ^[]$T) -> T #cc_contextless { if array != nil do return res; assert(len(array) > 0); res = array[len(array)-1]; - ^raw.Slice(array).len -= 1; + (cast(^raw.Slice)array).len -= 1; return res; } @@ -366,28 +366,28 @@ pop :: proc(array: ^[dynamic]$T) -> T #cc_contextless { if array != nil do return res; assert(len(array) > 0); res = array[len(array)-1]; - ^raw.DynamicArray(array).len -= 1; + (cast(^raw.DynamicArray)array).len -= 1; return res; } clear :: proc(slice: ^[]$T) #cc_contextless #inline { - if slice != nil do ^raw.Slice(slice).len = 0; + if slice != nil do (cast(^raw.Slice)slice).len = 0; } clear :: proc(array: ^[dynamic]$T) #cc_contextless #inline { - if array != nil do ^raw.DynamicArray(array).len = 0; + if array != nil do (cast(^raw.DynamicArray)array).len = 0; } clear :: proc(m: ^map[$K]$V) #cc_contextless #inline { if m == nil do return; - raw_map := ^raw.DynamicMap(m); - hashes := ^raw.DynamicArray(&raw_map.hashes); - entries := ^raw.DynamicArray(&raw_map.entries); + raw_map := cast(^raw.DynamicMap)m; + hashes := cast(^raw.DynamicArray)&raw_map.hashes; + entries := cast(^raw.DynamicArray)&raw_map.entries; hashes.len = 0; entries.len = 0; } reserve :: proc(array: ^[dynamic]$T, capacity: int) -> bool { if array == nil do return false; - a := ^raw.DynamicArray(array); + a := cast(^raw.DynamicArray)array; if capacity <= a.cap do return true; @@ -410,7 +410,7 @@ reserve :: proc(array: ^[dynamic]$T, capacity: int) -> bool { __get_map_header :: proc(m: ^map[$K]$V) -> __MapHeader #cc_contextless { - header := __MapHeader{m = ^raw.DynamicMap(m)}; + header := __MapHeader{m = cast(^raw.DynamicMap)m}; Entry :: struct { key: __MapKey; next: int; @@ -432,24 +432,24 @@ __get_map_key :: proc(key: $K) -> __MapKey #cc_contextless { match _ in ti { case TypeInfo.Integer: match 8*size_of(key) { - case 8: map_key.hash = u128( ^u8(&key)^); - case 16: map_key.hash = u128( ^u16(&key)^); - case 32: map_key.hash = u128( ^u32(&key)^); - case 64: map_key.hash = u128( ^u64(&key)^); - case 128: map_key.hash = u128(^u128(&key)^); + case 8: map_key.hash = u128((cast( ^u8)&key)^); + case 16: map_key.hash = u128((cast( ^u16)&key)^); + case 32: map_key.hash = u128((cast( ^u32)&key)^); + case 64: map_key.hash = u128((cast( ^u64)&key)^); + case 128: map_key.hash = u128((cast(^u128)&key)^); } case TypeInfo.Rune: - map_key.hash = u128(^rune(&key)^); + map_key.hash = u128((cast(^rune)&key)^); case TypeInfo.Pointer: - map_key.hash = u128(uint(^rawptr(&key)^)); + map_key.hash = u128(uint((cast(^rawptr)&key)^)); case TypeInfo.Float: match 8*size_of(key) { - case 32: map_key.hash = u128(^u32(&key)^); - case 64: map_key.hash = u128(^u64(&key)^); + case 32: map_key.hash = u128((cast(^u32)&key)^); + case 64: map_key.hash = u128((cast(^u64)&key)^); case: panic("Unhandled float size"); } case TypeInfo.String: - str := ^string(&key)^; + str := (cast(^string)&key)^; map_key.hash = __default_hash_string(str); map_key.str = str; case: @@ -468,12 +468,12 @@ delete :: proc(m: ^map[$K]$V, key: K) { -new :: proc(T: type) -> ^T #inline do return ^T(alloc(size_of(T), align_of(T))); +new :: proc(T: type) -> ^T #inline do return cast(^T)alloc(size_of(T), align_of(T)); free :: proc(ptr: rawptr) do free_ptr(ptr); -free :: proc(str: string) do free_ptr(^raw.String(&str).data); -free :: proc(array: [dynamic]$T) do free_ptr(^raw.DynamicArray(&array).data); -free :: proc(slice: []$T) do free_ptr(^raw.Slice(&slice).data); +free :: proc(str: string) do free_ptr((cast(^raw.String)&str).data); +free :: proc(array: [dynamic]$T) do free_ptr((cast(^raw.DynamicArray)&array).data); +free :: proc(slice: []$T) do free_ptr((cast(^raw.Slice)&slice).data); free :: proc(m: map[$K]$V) { raw := ^raw.DynamicMap(&m); free(raw.hashes); @@ -688,7 +688,7 @@ __abs_complex128 :: proc(x: complex128) -> f64 #inline #cc_contextless { __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int) { - array := ^raw.DynamicArray(array_); + array := cast(^raw.DynamicArray)array_; array.allocator = context.allocator; assert(array.allocator.procedure != nil); @@ -699,7 +699,7 @@ __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, ca } __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int) -> bool { - array := ^raw.DynamicArray(array_); + array := cast(^raw.DynamicArray)array_; if cap <= array.cap do return true; @@ -721,7 +721,7 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: } __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int) -> bool { - array := ^raw.DynamicArray(array_); + array := cast(^raw.DynamicArray)array_; ok := __dynamic_array_reserve(array_, elem_size, elem_align, len); if ok do array.len = len; @@ -731,7 +731,7 @@ __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int, items: rawptr, item_count: int) -> int { - array := ^raw.DynamicArray(array_); + array := cast(^raw.DynamicArray)array_; if items == nil do return 0; if item_count <= 0 do return 0; @@ -745,7 +745,7 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int, // TODO(bill): Better error handling for failed reservation if !ok do return array.len; - data := ^u8(array.data); + data := cast(^u8)array.data; assert(data != nil); __mem_copy(data + (elem_size*array.len), items, elem_size * item_count); array.len += item_count; @@ -753,7 +753,7 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int, } __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int) -> int { - array := ^raw.DynamicArray(array_); + array := cast(^raw.DynamicArray)array_; ok := true; if array.cap <= array.len+1 { @@ -763,7 +763,7 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in // TODO(bill): Better error handling for failed reservation if !ok do return array.len; - data := ^u8(array.data); + data := cast(^u8)array.data; assert(data != nil); __mem_zero(data + (elem_size*array.len), elem_size); array.len++; @@ -772,7 +772,7 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int, items: rawptr, item_count: int) -> int { - slice := ^raw.Slice(slice_); + slice := cast(^raw.Slice)slice_; if item_count <= 0 || items == nil { return slice.len; @@ -780,7 +780,7 @@ __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int, item_count = min(slice.cap-slice.len, item_count); if item_count > 0 { - data := ^u8(slice.data); + data := cast(^u8)slice.data; assert(data != nil); __mem_copy(data + (elem_size*slice.len), items, elem_size * item_count); slice.len += item_count; @@ -800,7 +800,7 @@ __default_hash :: proc(data: []u8) -> u128 { } return fnv128a(data); } -__default_hash_string :: proc(s: string) -> u128 do return __default_hash([]u8(s)); +__default_hash_string :: proc(s: string) -> u128 do return __default_hash(cast([]u8)s); __dynamic_map_reserve :: proc(using header: __MapHeader, cap: int) { __dynamic_array_reserve(&m.hashes, size_of(int), align_of(int), cap); @@ -812,8 +812,8 @@ __dynamic_map_rehash :: proc(using header: __MapHeader, new_count: int) { nm: raw.DynamicMap; new_header.m = &nm; - header_hashes := ^raw.DynamicArray(&header.m.hashes); - nm_hashes := ^raw.DynamicArray(&nm.hashes); + header_hashes := cast(^raw.DynamicArray)&header.m.hashes; + nm_hashes := cast(^raw.DynamicArray)&nm.hashes; __dynamic_array_resize(nm_hashes, size_of(int), align_of(int), new_count); __dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len); @@ -823,7 +823,7 @@ __dynamic_map_rehash :: proc(using header: __MapHeader, new_count: int) { if len(nm.hashes) == 0 do __dynamic_map_grow(new_header); entry_header := __dynamic_map_get_entry(header, i); - data := ^u8(entry_header); + data := cast(^u8)entry_header; fr := __dynamic_map_find(new_header, entry_header.key); j := __dynamic_map_add_entry(new_header, entry_header.key); @@ -836,7 +836,7 @@ __dynamic_map_rehash :: proc(using header: __MapHeader, new_count: int) { e := __dynamic_map_get_entry(new_header, j); e.next = fr.entry_index; - ndata := ^u8(e); + ndata := cast(^u8)e; __mem_copy(ndata+value_offset, data+value_offset, value_size); if __dynamic_map_full(new_header) do __dynamic_map_grow(new_header); @@ -849,7 +849,7 @@ __dynamic_map_rehash :: proc(using header: __MapHeader, new_count: int) { __dynamic_map_get :: proc(h: __MapHeader, key: __MapKey) -> rawptr { index := __dynamic_map_find(h, key).entry_index; if index >= 0 { - data := ^u8(__dynamic_map_get_entry(h, index)); + data := cast(^u8)__dynamic_map_get_entry(h, index); return data + h.value_offset; } return nil; @@ -880,7 +880,7 @@ __dynamic_map_set :: proc(using h: __MapHeader, key: __MapKey, value: rawptr) { { e := __dynamic_map_get_entry(h, index); e.key = key; - val := ^u8(e) + value_offset; + val := cast(^u8)e + value_offset; __mem_copy(val, value, value_size); } @@ -942,7 +942,7 @@ __dynamic_map_delete :: proc(using h: __MapHeader, key: __MapKey) { } __dynamic_map_get_entry :: proc(using h: __MapHeader, index: int) -> ^__MapEntryHeader { - return ^__MapEntryHeader(^u8(m.entries.data) + index*entry_size); + return cast(^__MapEntryHeader)(cast(^u8)m.entries.data + index*entry_size); } __dynamic_map_erase :: proc(using h: __MapHeader, fr: __MapFindResult) { diff --git a/core/fmt.odin b/core/fmt.odin index 3a6948410..7d5a6ed6b 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -55,7 +55,7 @@ to_string :: proc(buf: StringBuffer) -> string { write_string :: proc(buf: ^StringBuffer, s: string) { - write_bytes(buf, []u8(s)); + write_bytes(buf, cast([]u8)s); } write_bytes :: proc(buf: ^StringBuffer, data: []u8) { match b in buf { @@ -747,7 +747,7 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) { if t := b.types[i]; types.is_any(t) { write_string(fi.buf, "any{}"); } else { - data := ^u8(v.data) + b.offsets[i]; + data := cast(^u8)v.data + b.offsets[i]; fmt_arg(fi, any{rawptr(data), t}, 'v'); } } @@ -766,9 +766,9 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) { case Pointer: if v.type_info == type_info(^TypeInfo) { - write_type(fi.buf, ^^TypeInfo(v.data)^); + write_type(fi.buf, (cast(^^TypeInfo)v.data)^); } else { - fmt_pointer(fi, ^rawptr(v.data)^, verb); + fmt_pointer(fi, (cast(^rawptr)v.data)^, verb); } case Atomic: @@ -780,25 +780,25 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) { for i in 0..info.count { if i > 0 do write_string(fi.buf, ", "); - data := ^u8(v.data) + i*info.elem_size; + data := cast(^u8)v.data + i*info.elem_size; fmt_arg(fi, any{rawptr(data), info.elem}, verb); } case DynamicArray: write_byte(fi.buf, '['); defer write_byte(fi.buf, ']'); - array := ^raw.DynamicArray(v.data); + array := cast(^raw.DynamicArray)v.data; for i in 0..array.len { if i > 0 do write_string(fi.buf, ", "); - data := ^u8(array.data) + i*info.elem_size; + data := cast(^u8)array.data + i*info.elem_size; fmt_arg(fi, any{rawptr(data), info.elem}, verb); } case Slice: write_byte(fi.buf, '['); defer write_byte(fi.buf, ']'); - slice := ^[]u8(v.data); + slice := cast(^[]u8)v.data; for _, i in slice { if i > 0 do write_string(fi.buf, ", "); @@ -813,7 +813,7 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) { for i in 0..info.count { if i > 0 do write_string(fi.buf, ", "); - data := ^u8(v.data) + i*info.elem_size; + data := cast(^u8)v.data + i*info.elem_size; fmt_value(fi, any{rawptr(data), info.elem}, verb); } @@ -826,7 +826,7 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) { write_string(fi.buf, "map["); defer write_byte(fi.buf, ']'); - entries := &(^raw.DynamicMap(v.data).entries); + entries := &((cast(^raw.DynamicMap)v.data).entries); gs := type_info_base(info.generated_struct).variant.(Struct); ed := type_info_base(gs.types[1]).variant.(DynamicArray); entry_type := ed.elem.variant.(Struct); @@ -835,8 +835,8 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) { for i in 0..entries.len { if i > 0 do write_string(fi.buf, ", "); - data := ^u8(entries.data) + i*entry_size; - header := ^__MapEntryHeader(data); + data := cast(^u8)entries.data + i*entry_size; + header := cast(^__MapEntryHeader)data; if types.is_string(info.key) { write_string(fi.buf, header.key.str); @@ -866,7 +866,7 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) { if t := info.types[i]; types.is_any(t) { write_string(fi.buf, "any{}"); } else { - data := ^u8(v.data) + info.offsets[i]; + data := cast(^u8)v.data + info.offsets[i]; fmt_arg(fi, any{rawptr(data), t}, 'v'); } } @@ -883,7 +883,7 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) { case Procedure: write_type(fi.buf, v.type_info); write_string(fi.buf, " @ "); - fmt_pointer(fi, ^rawptr(v.data)^, 'p'); + fmt_pointer(fi, (cast(^rawptr)v.data)^, 'p'); } } diff --git a/core/hash.odin b/core/hash.odin index 5747776a5..ad6a9ae52 100644 --- a/core/hash.odin +++ b/core/hash.odin @@ -57,7 +57,7 @@ murmur32 :: proc(data: []u8) -> u32 { p1 := p + 4*nblocks; for ; p < p1; p += 4 { - k1 := ^u32(p)^; + k1 := (cast(^u32)p)^; k1 *= c1_32; k1 = (k1 << 15) | (k1 >> 17); @@ -104,7 +104,7 @@ murmur64 :: proc(data: []u8) -> u64 { r :: 47; h: u64 = SEED ~ (u64(len(data)) * m); - data64 := mem.slice_ptr(^u64(&data[0]), len(data)/size_of(u64)); + data64 := mem.slice_ptr(cast(^u64)&data[0], len(data)/size_of(u64)); for _, i in data64 { k := data64[i]; @@ -140,7 +140,7 @@ murmur64 :: proc(data: []u8) -> u64 { h1 := u32(SEED) ~ u32(len(data)); h2 := u32(SEED) >> 32; - data32 := mem.slice_ptr(^u32(&data[0]), len(data)/size_of(u32)); + data32 := mem.slice_ptr(cast(^u32)&data[0], len(data)/size_of(u32)); len := len(data); i := 0; diff --git a/core/mem.odin b/core/mem.odin index 6c0d95e98..c52786f59 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -29,19 +29,19 @@ compare :: proc(a, b: []u8) -> int #cc_contextless { slice_ptr :: proc(ptr: ^$T, len: int) -> []T #cc_contextless { assert(len >= 0); slice := raw.Slice{data = ptr, len = len, cap = len}; - return ^[]T(&slice)^; + return (cast(^[]T)&slice)^; } slice_ptr :: proc(ptr: ^$T, len, cap: int) -> []T #cc_contextless { assert(0 <= len && len <= cap); slice := raw.Slice{data = ptr, len = len, cap = cap}; - return ^[]T(&slice)^; + return (cast(^[]T)&slice)^; } slice_to_bytes :: proc(slice: []$T) -> []u8 #cc_contextless { - s := ^raw.Slice(&slice); + s := cast(^raw.Slice)&slice; s.len *= size_of(T); s.cap *= size_of(T); - return ^[]u8(s)^; + return (cast(^[]u8)s)^; } @@ -73,7 +73,7 @@ AllocationHeader :: struct { allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) { header.size = size; - ptr := ^int(header+1); + ptr := cast(^int)(header+1); for i := 0; rawptr(ptr) < data; i++ { (ptr+i)^ = -1; @@ -81,9 +81,9 @@ allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: in } allocation_header :: proc(data: rawptr) -> ^AllocationHeader { if data == nil do return nil; - p := ^int(data); + p := cast(^int)data; for (p-1)^ == -1 do p = (p-1); - return ^AllocationHeader(p-1); + return cast(^AllocationHeader)(p-1); } @@ -141,7 +141,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode, size, alignment: int, old_memory: rawptr, old_size: int, flags: u64) -> rawptr { using Allocator.Mode; - arena := ^Arena(allocator_data); + arena := cast(^Arena)allocator_data; match mode { case Alloc: diff --git a/core/opengl.odin b/core/opengl.odin index 6ad1d5700..9ec29704f 100644 --- a/core/opengl.odin +++ b/core/opengl.odin @@ -120,7 +120,7 @@ get_proc_address :: proc(name: string) -> rawptr { init :: proc() { set_proc_address :: proc(p: rawptr, name: string) #inline { - x := ^rawptr(p); + x := cast(^rawptr)p; x^ = get_proc_address(name); } diff --git a/core/os.odin b/core/os.odin index f7cec9586..586212d62 100644 --- a/core/os.odin +++ b/core/os.odin @@ -5,7 +5,7 @@ import_load ( ) write_string :: proc(fd: Handle, str: string) -> (int, Errno) { - return write(fd, []u8(str)); + return write(fd, cast([]u8)str); } read_entire_file :: proc(name: string) -> ([]u8, bool) { diff --git a/core/os_windows.odin b/core/os_windows.odin index ba607cfa7..e0db968ca 100644 --- a/core/os_windows.odin +++ b/core/os_windows.odin @@ -96,7 +96,7 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn } buf: [300]u8; - copy(buf[..], []u8(path)); + copy(buf[..], cast([]u8)path); handle := Handle(win32.create_file_a(&buf[0], access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil)); if handle != INVALID_HANDLE do return handle, ERROR_NONE; @@ -217,7 +217,7 @@ last_write_time_by_name :: proc(name: string) -> FileTime { assert(len(buf) > len(name)); - copy(buf[..], []u8(name)); + copy(buf[..], cast([]u8)name); if win32.get_file_attributes_ex_a(&buf[0], win32.GetFileExInfoStandard, &data) != 0 { last_write_time = data.last_write_time; diff --git a/core/strconv.odin b/core/strconv.odin index 58924100e..545a50376 100644 --- a/core/strconv.odin +++ b/core/strconv.odin @@ -191,7 +191,7 @@ parse_f64 :: proc(s: string) -> f64 { append_bool :: proc(buf: []u8, b: bool) -> string { s := b ? "true" : "false"; - append(&buf, ...[]u8(s)); + append(&buf, ...cast([]u8)s); return string(buf); } @@ -257,7 +257,7 @@ generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8 } else { s = "+Inf"; } - append(&buf, ...[]u8(s)); + append(&buf, ...cast([]u8)s); return buf; case 0: // denormalized diff --git a/core/strings.odin b/core/strings.odin index 1ca1c1497..3bb086326 100644 --- a/core/strings.odin +++ b/core/strings.odin @@ -2,14 +2,14 @@ import "mem.odin"; new_string :: proc(s: string) -> string { c := make([]u8, len(s)+1); - copy(c, []u8(s)); + copy(c, cast([]u8)s); c[len(s)] = 0; return string(c[..len(s)]); } new_c_string :: proc(s: string) -> ^u8 { c := make([]u8, len(s)+1); - copy(c, []u8(s)); + copy(c, cast([]u8)s); c[len(s)] = 0; return &c[0]; } diff --git a/core/utf8.odin b/core/utf8.odin index 50d3c4cdb..2973acbe9 100644 --- a/core/utf8.odin +++ b/core/utf8.odin @@ -92,7 +92,7 @@ encode_rune :: proc(r: rune) -> ([4]u8, int) { return buf, 4; } -decode_rune :: proc(s: string) -> (rune, int) #inline { return decode_rune([]u8(s)); } +decode_rune :: proc(s: string) -> (rune, int) #inline { return decode_rune(cast([]u8)s); } decode_rune :: proc(s: []u8) -> (rune, int) { n := len(s); if n < 1 { @@ -132,7 +132,7 @@ decode_rune :: proc(s: []u8) -> (rune, int) { -decode_last_rune :: proc(s: string) -> (rune, int) #inline { return decode_last_rune([]u8(s)); } +decode_last_rune :: proc(s: string) -> (rune, int) #inline { return decode_last_rune(cast([]u8)s); } decode_last_rune :: proc(s: []u8) -> (rune, int) { r: rune; size: int; @@ -217,7 +217,7 @@ valid_string :: proc(s: string) -> bool { rune_start :: proc(b: u8) -> bool #inline { return b&0xc0 != 0x80; } -rune_count :: proc(s: string) -> int #inline { return rune_count([]u8(s)); } +rune_count :: proc(s: string) -> int #inline { return rune_count(cast([]u8)s); } rune_count :: proc(s: []u8) -> int { count := 0; n := len(s); diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 52f785ef6..96827590d 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -365,7 +365,7 @@ void init_entity_foreign_library(Checker *c, Entity *e) { String name = ident->Ident.token.string; Entity *found = scope_lookup_entity(c->context.scope, name); if (found == nullptr) { - if (name == "_") { + if (is_blank_ident(name)) { error(ident, "`_` cannot be used as a value type"); } else { error(ident, "Undeclared name: %.*s", LIT(name)); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index c19fc9afb..a5557ee86 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -823,7 +823,7 @@ void check_record_field_decl(Checker *c, AstNode *decl, Array<Entity *> *fields, Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, cast(i32)fields->count); e->identifier = name; - if (name_token.string == "_") { + if (is_blank_ident(name_token)) { array_add(fields, e); } else if (name_token.string == "__tag") { error(name, "`__tag` is a reserved identifier for fields"); @@ -1223,7 +1223,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod // NOTE(bill): Skip blank identifiers - if (name == "_") { + if (is_blank_ident(name)) { continue; } else if (name == "count") { error(field, "`count` is a reserved identifier for enumerations"); @@ -1331,7 +1331,7 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As e->flags |= EntityFlag_BitFieldValue; HashKey key = hash_string(name); - if (name != "_" && + if (!is_blank_ident(name) && map_get(&entity_map, key) != nullptr) { error(ident, "`%.*s` is already declared in this bit field", LIT(name)); } else { @@ -1879,12 +1879,12 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) { for (isize i = 0; i < variable_index; i++) { String x = variables[i]->token.string; - if (x.len == 0 || x == "_") { + if (x.len == 0 || is_blank_ident(x)) { continue; } for (isize j = i+1; j < variable_index; j++) { String y = variables[j]->token.string; - if (y.len == 0 || y == "_") { + if (y.len == 0 || is_blank_ident(y)) { continue; } if (x == y) { @@ -2162,7 +2162,7 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type * Entity *e = scope_lookup_entity(c->context.scope, name); if (e == nullptr) { - if (name == "_") { + if (is_blank_ident(name)) { error(n, "`_` cannot be used as a value type"); } else { error(n, "Undeclared name: %.*s", LIT(name)); @@ -2603,7 +2603,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) Type *elem = check_type(c, at->elem, nullptr); i64 count = check_array_or_map_count(c, at->count, false); if (count < 0) { - error(at->count, ".. can only be used in conjuction with compound literals"); + error(at->count, "... can only be used in conjuction with compound literals"); count = 0; } #if 0 @@ -5735,7 +5735,7 @@ isize lookup_procedure_parameter(TypeProc *pt, String parameter_name) { for (isize i = 0; i < param_count; i++) { Entity *e = pt->params->Tuple.variables[i]; String name = e->token.string; - if (name == "_") { + if (is_blank_ident(name)) { continue; } if (name == parameter_name) { @@ -5749,7 +5749,7 @@ isize lookup_procedure_result(TypeProc *pt, String result_name) { for (isize i = 0; i < result_count; i++) { Entity *e = pt->results->Tuple.variables[i]; String name = e->token.string; - if (name == "_") { + if (is_blank_ident(name)) { continue; } if (name == result_name) { @@ -5818,7 +5818,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { for (isize i = 0; i < param_count_to_check; i++) { if (!visited[i]) { Entity *e = pt->params->Tuple.variables[i]; - if (e->token.string == "_") { + if (is_blank_ident(e->token)) { continue; } if (e->kind == Entity_Variable) { @@ -6664,7 +6664,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t bool all_fields_are_blank = true; for (isize i = 0; i < t->Record.field_count; i++) { Entity *field = t->Record.fields_in_src_order[i]; - if (field->token.string != "_") { + if (!is_blank_ident(field->token)) { all_fields_are_blank = false; break; } @@ -6682,7 +6682,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t } Entity *field = t->Record.fields_in_src_order[index]; - if (!all_fields_are_blank && field->token.string == "_") { + if (!all_fields_are_blank && is_blank_ident(field->token)) { // NOTE(bill): Ignore blank identifiers continue; } @@ -7599,9 +7599,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) { if (field->names.count == 0) { continue; } - AstNode *name = field->names[0]; - ast_node(n, Ident, name); - if (n->token.string != "_") { + if (!is_blank_ident(field->names[0])) { has_name = true; break; } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 4d07ce1cf..6bf873bd3 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -186,8 +186,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) { AstNode *node = unparen_expr(lhs_node); // NOTE(bill): Ignore assignments to `_` - if (node->kind == AstNode_Ident && - node->Ident.token.string == "_") { + if (is_blank_ident(node)) { add_entity_definition(&c->info, node, nullptr); check_assignment(c, rhs, nullptr, str_lit("assignment to `_` identifier")); if (rhs->mode == Addressing_Invalid) { @@ -429,7 +428,7 @@ void check_label(Checker *c, AstNode *label) { return; } String name = l->name->Ident.token.string; - if (name == "_") { + if (is_blank_ident(name)) { error(l->name, "A label's name cannot be a blank identifier"); return; } @@ -884,7 +883,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { for (isize i = 0; i < result_count; i++) { if (!visited[i]) { Entity *e = pt->results->Tuple.variables[i]; - if (e->token.string == "_") { + if (is_blank_ident(e->token)) { continue; } GB_ASSERT(e->kind == Entity_Variable); @@ -1133,7 +1132,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { String str = token.string; Entity *found = nullptr; - if (str != "_") { + if (!is_blank_ident(str)) { found = current_scope_lookup_entity(c->context.scope, str); } if (found == nullptr) { @@ -1686,7 +1685,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { String str = token.string; Entity *found = nullptr; // NOTE(bill): Ignore assignments to `_` - if (str != "_") { + if (!is_blank_ident(str)) { found = current_scope_lookup_entity(c->context.scope, str); } if (found == nullptr) { diff --git a/src/checker.cpp b/src/checker.cpp index e2133144f..d7882414a 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -979,7 +979,7 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) { GB_ASSERT(identifier != nullptr); if (identifier->kind == AstNode_Ident) { - if (identifier->Ident.token.string == "_") { + if (is_blank_ident(identifier)) { return; } HashKey key = hash_node(identifier); @@ -994,7 +994,7 @@ bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) { return false; } String name = entity->token.string; - if (name != "_") { + if (!is_blank_ident(name)) { Entity *ie = scope_insert_entity(scope, entity); if (ie) { TokenPos pos = ie->token.pos; @@ -2202,7 +2202,7 @@ void check_import_entities(Checker *c, Map<Scope *> *file_scopes) { } } else { String import_name = path_to_entity_name(id->import_name.string, id->fullpath); - if (import_name == "_") { + if (is_blank_ident(import_name)) { error(token, "File name, %.*s, cannot be as an import name as it is not a valid identifier", LIT(id->import_name.string)); } else { GB_ASSERT(id->import_name.pos.line != 0); @@ -2254,7 +2254,7 @@ void check_import_entities(Checker *c, Map<Scope *> *file_scopes) { String library_name = path_to_entity_name(fl->library_name.string, file_str); - if (library_name == "_") { + if (is_blank_ident(library_name)) { error(spec, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string)); } else { GB_ASSERT(fl->library_name.pos.line != 0); diff --git a/src/ir.cpp b/src/ir.cpp index b11255cf1..8746b676b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -653,13 +653,6 @@ Type *ir_type(irValue *value) { } -bool ir_is_blank_ident(AstNode *node) { - if (node->kind == AstNode_Ident) { - ast_node(i, Ident, node); - return is_blank_ident(i->token.string); - } - return false; -} irInstr *ir_get_last_instr(irBlock *block) { @@ -5001,7 +4994,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { case_end; case_ast_node(i, Ident, expr); - if (ir_is_blank_ident(expr)) { + if (is_blank_ident(expr)) { irAddr val = {}; return val; } @@ -5614,6 +5607,15 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { return ir_addr(v); case_end; + + case_ast_node(tc, TypeCast, expr); + Type *type = type_of_expr(proc->module->info, expr); + irValue *x = ir_build_expr(proc, tc->expr); + irValue *e = ir_emit_conv(proc, x, type); + irValue *v = ir_add_local_generated(proc, type); + ir_emit_store(proc, v, e); + return ir_addr(v); + case_end; } TokenPos token_pos = ast_node_token(expr).pos; @@ -6143,7 +6145,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { if (vd->values.count == 0) { // declared and zero-initialized for_array(i, vd->names) { AstNode *name = vd->names[i]; - if (!ir_is_blank_ident(name)) { + if (!is_blank_ident(name)) { ir_add_local_for_identifier(proc, name, true); } } @@ -6156,7 +6158,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { for_array(i, vd->names) { AstNode *name = vd->names[i]; irAddr lval = ir_addr(nullptr); - if (!ir_is_blank_ident(name)) { + if (!is_blank_ident(name)) { ir_add_local_for_identifier(proc, name, false); lval = ir_build_addr(proc, name); } @@ -6200,7 +6202,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { for_array(i, as->lhs) { AstNode *lhs = as->lhs[i]; irAddr lval = {}; - if (!ir_is_blank_ident(lhs)) { + if (!is_blank_ident(lhs)) { lval = ir_build_addr(proc, lhs); } array_add(&lvals, lval); @@ -6498,10 +6500,10 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { Type *val_type = nullptr; Type *idx_type = nullptr; - if (rs->value != nullptr && !ir_is_blank_ident(rs->value)) { + if (rs->value != nullptr && !is_blank_ident(rs->value)) { val_type = type_of_expr(proc->module->info, rs->value); } - if (rs->index != nullptr && !ir_is_blank_ident(rs->index)) { + if (rs->index != nullptr && !is_blank_ident(rs->index)) { idx_type = type_of_expr(proc->module->info, rs->index); } @@ -7073,8 +7075,7 @@ void ir_begin_procedure_body(irProcedure *proc) { } Type *abi_type = proc->type->Proc.abi_compat_params[i]; - if (e->token.string != "" && - e->token.string != "_") { + if (e->token.string != "" && !is_blank_ident(e->token)) { irValue *param = ir_add_param(proc, e, name, abi_type); array_add(&proc->params, param); } diff --git a/src/ir_print.cpp b/src/ir_print.cpp index bad0e6eca..7bd79fe2e 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1580,8 +1580,7 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { ir_fprintf(f, " noalias"); } if (proc->body != nullptr) { - if (e->token.string != "" && - e->token.string != "_") { + if (e->token.string != "" && !is_blank_ident(e->token)) { ir_fprintf(f, " "); ir_print_encoded_local(f, e->token.string); } else { diff --git a/src/parser.cpp b/src/parser.cpp index 6836e901f..a2d8ab1f9 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -35,6 +35,7 @@ struct AstFile { isize expr_level; bool allow_range; // NOTE(bill): Ranges are only allowed in certain cases bool in_foreign_block; + bool allow_type; Array<AstNode *> decls; bool is_global_scope; @@ -712,6 +713,10 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) { n->TypeAssertion.expr = clone_ast_node(a, n->TypeAssertion.expr); n->TypeAssertion.type = clone_ast_node(a, n->TypeAssertion.type); break; + case AstNode_TypeCast: + n->TypeCast.type = clone_ast_node(a, n->TypeCast.type); + n->TypeCast.expr = clone_ast_node(a, n->TypeCast.expr); + break; case AstNode_BadStmt: break; case AstNode_EmptyStmt: break; @@ -1623,39 +1628,39 @@ CommentGroup consume_comment_group(AstFile *f, isize n, isize *end_line_) { return comments; } +void comsume_comment_groups(AstFile *f, Token prev) { + if (f->curr_token.kind != Token_Comment) return; + CommentGroup comment = {}; + isize end_line = 0; -bool next_token(AstFile *f) { - gb_zero_item(&f->lead_comment); - gb_zero_item(&f->line_comment); - Token prev = f->prev_token = f->curr_token; - - bool ok = next_token0(f); - if (!ok) { - return false; - } - if (f->curr_token.kind == Token_Comment) { - CommentGroup comment = {}; - isize end_line = 0; - - if (f->curr_token.pos.line == prev.pos.line) { - comment = consume_comment_group(f, 0, &end_line); - if (f->curr_token.pos.line != end_line) { - f->line_comment = comment; - } + if (f->curr_token.pos.line == prev.pos.line) { + comment = consume_comment_group(f, 0, &end_line); + if (f->curr_token.pos.line != end_line) { + f->line_comment = comment; } + } - end_line = -1; - while (f->curr_token.kind == Token_Comment) { - comment = consume_comment_group(f, 1, &end_line); - } + end_line = -1; + while (f->curr_token.kind == Token_Comment) { + comment = consume_comment_group(f, 1, &end_line); + } - if (end_line+1 == f->curr_token.pos.line) { - f->lead_comment = comment; - } + if (end_line+1 == f->curr_token.pos.line) { + f->lead_comment = comment; } + GB_ASSERT(f->curr_token.kind != Token_Comment); +} - return true; + +Token advance_token(AstFile *f) { + gb_zero_item(&f->lead_comment); + gb_zero_item(&f->line_comment); + Token prev = f->prev_token = f->curr_token; + + bool ok = next_token0(f); + if (ok) comsume_comment_groups(f, prev); + return prev; } TokenKind look_ahead_token_kind(AstFile *f, isize amount) { @@ -1685,7 +1690,7 @@ Token expect_token(AstFile *f, TokenKind kind) { } } - next_token(f); + advance_token(f); return prev; } @@ -1698,7 +1703,7 @@ Token expect_token_after(AstFile *f, TokenKind kind, char *msg) { msg, LIT(p)); } - next_token(f); + advance_token(f); return prev; } @@ -1712,7 +1717,7 @@ Token expect_operator(AstFile *f) { syntax_error(f->curr_token, "Expected an non-range operator, got `%.*s`", LIT(token_strings[prev.kind])); } - next_token(f); + advance_token(f); return prev; } @@ -1722,14 +1727,14 @@ Token expect_keyword(AstFile *f) { syntax_error(f->curr_token, "Expected a keyword, got `%.*s`", LIT(token_strings[prev.kind])); } - next_token(f); + advance_token(f); return prev; } bool allow_token(AstFile *f, TokenKind kind) { Token prev = f->curr_token; if (prev.kind == kind) { - next_token(f); + advance_token(f); return true; } return false; @@ -1742,6 +1747,20 @@ bool is_blank_ident(String str) { } return false; } +bool is_blank_ident(Token token) { + if (token.kind == Token_Ident) { + return is_blank_ident(token.string); + } + return false; +} +bool is_blank_ident(AstNode *node) { + if (node->kind == AstNode_Ident) { + ast_node(i, Ident, node); + return is_blank_ident(i->token.string); + } + return false; +} + // NOTE(bill): Go to next statement to prevent numerous error messages popping up @@ -1791,7 +1810,7 @@ void fix_advance_to_next_stmt(AstFile *f) { // NOTE(bill): Reaching here means there is a parsing bug } break; } - next_token(f); + advance_token(f); } #endif } @@ -1801,7 +1820,7 @@ Token expect_closing(AstFile *f, TokenKind kind, String context) { f->curr_token.kind == Token_Semicolon && f->curr_token.string == "\n") { error(f->curr_token, "Missing `,` before newline in %.*s", LIT(context)); - next_token(f); + advance_token(f); } return expect_token(f, kind); } @@ -1923,7 +1942,7 @@ AstNode * parse_body(AstFile *f); AstNode *parse_ident(AstFile *f) { Token token = f->curr_token; if (token.kind == Token_Ident) { - next_token(f); + advance_token(f); } else { token.string = str_lit("_"); expect_token(f, Token_Ident); @@ -2079,7 +2098,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven syntax_error(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*link_name)); } - next_token(f); + advance_token(f); } else { expect_token(f, Token_String); } @@ -2157,11 +2176,12 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven } -Array<AstNode *> parse_lhs_expr_list(AstFile *f); -Array<AstNode *> parse_rhs_expr_list(AstFile *f); -AstNode * parse_simple_stmt (AstFile *f, StmtAllowFlag flags); -AstNode * parse_type (AstFile *f); -AstNode * parse_call_expr (AstFile *f, AstNode *operand); +Array<AstNode *> parse_lhs_expr_list (AstFile *f); +Array<AstNode *> parse_rhs_expr_list (AstFile *f); +AstNode * parse_simple_stmt (AstFile *f, StmtAllowFlag flags); +AstNode * parse_type (AstFile *f); +AstNode * parse_call_expr (AstFile *f, AstNode *operand); +AstNode * parse_record_field_list(AstFile *f, isize *name_count_); AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) { if (statement == nullptr) { @@ -2195,6 +2215,7 @@ AstNode *convert_stmt_to_body(AstFile *f, AstNode *stmt) { + AstNode *parse_operand(AstFile *f, bool lhs) { AstNode *operand = nullptr; // Operand switch (f->curr_token.kind) { @@ -2211,21 +2232,16 @@ AstNode *parse_operand(AstFile *f, bool lhs) { case Token_Float: case Token_Imag: case Token_Rune: - operand = ast_basic_lit(f, f->curr_token); - next_token(f); - return operand; + return ast_basic_lit(f, advance_token(f)); case Token_size_of: case Token_align_of: - case Token_offset_of: { - operand = ast_implicit(f, f->curr_token); next_token(f); - return parse_call_expr(f, operand); - } + case Token_offset_of: + return parse_call_expr(f, ast_implicit(f, advance_token(f))); case Token_String: { - Token token = f->curr_token; - next_token(f); + Token token = advance_token(f); if (f->curr_token.kind == Token_String) { // NOTE(bill): Allow neighbouring string literals to be merge together to // become one big string @@ -2240,7 +2256,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) { isize old_count = data.count; array_resize(&data, data.count + s.len); gb_memmove(data.data+old_count, s.text, s.len); - next_token(f); + advance_token(f); } token.string = make_string(data.data, data.count); @@ -2332,7 +2348,242 @@ AstNode *parse_operand(AstFile *f, bool lhs) { return type; } + + // Check for Types + case Token_Dollar: { + Token token = expect_token(f, Token_Dollar); + AstNode *type = parse_ident(f); + return ast_poly_type(f, token, type); + } break; + + case Token_type_of: { + AstNode *i = ast_implicit(f, expect_token(f, Token_type_of)); + AstNode *type = parse_call_expr(f, i); + while (f->curr_token.kind == Token_Period) { + Token token = advance_token(f); + AstNode *sel = parse_ident(f); + type = ast_selector_expr(f, token, type, sel); + } + return type; + } break; + + case Token_Pointer: { + Token token = expect_token(f, Token_Pointer); + AstNode *elem = parse_type(f); + return ast_pointer_type(f, token, elem); + } break; + + case Token_atomic: { + Token token = expect_token(f, Token_atomic); + AstNode *elem = parse_type(f); + return ast_atomic_type(f, token, elem); + } break; + + case Token_OpenBracket: { + Token token = expect_token(f, Token_OpenBracket); + AstNode *count_expr = nullptr; + bool is_vector = false; + + if (f->curr_token.kind == Token_Ellipsis) { + count_expr = ast_unary_expr(f, expect_token(f, Token_Ellipsis), nullptr); + } else if (allow_token(f, Token_vector)) { + if (f->curr_token.kind != Token_CloseBracket) { + f->expr_level++; + count_expr = parse_expr(f, false); + f->expr_level--; + } else { + syntax_error(f->curr_token, "Vector type missing count"); + } + is_vector = true; + } else if (allow_token(f, Token_dynamic)) { + expect_token(f, Token_CloseBracket); + return ast_dynamic_array_type(f, token, parse_type(f)); + } else if (f->curr_token.kind != Token_CloseBracket) { + f->expr_level++; + count_expr = parse_expr(f, false); + f->expr_level--; + } + expect_token(f, Token_CloseBracket); + if (is_vector) { + return ast_vector_type(f, token, count_expr, parse_type(f)); + } + return ast_array_type(f, token, count_expr, parse_type(f)); + } break; + + case Token_map: { + Token token = expect_token(f, Token_map); + AstNode *count = nullptr; + AstNode *key = nullptr; + AstNode *value = nullptr; + + Token open = expect_token_after(f, Token_OpenBracket, "map"); + key = parse_expr(f, true); + if (allow_token(f, Token_Comma)) { + count = key; + key = parse_type(f); + } + Token close = expect_token(f, Token_CloseBracket); + value = parse_type(f); + + return ast_map_type(f, token, count, key, value); + } break; + + case Token_struct: { + Token token = expect_token(f, Token_struct); + bool is_packed = false; + bool is_ordered = false; + AstNode *align = nullptr; + + isize prev_level = f->expr_level; + f->expr_level = -1; + + while (allow_token(f, Token_Hash)) { + Token tag = expect_token_after(f, Token_Ident, "#"); + if (tag.string == "packed") { + if (is_packed) { + syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); + } + is_packed = true; + } else if (tag.string == "ordered") { + if (is_ordered) { + syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); + } + is_ordered = true; + } else if (tag.string == "align") { + if (align) { + syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); + } + align = parse_expr(f, true); + } else { + syntax_error(tag, "Invalid struct tag `#%.*s`", LIT(tag.string)); + } + } + + f->expr_level = prev_level; + + if (is_packed && is_ordered) { + syntax_error(token, "`#ordered` is not needed with `#packed` which implies ordering"); + } + + Token open = expect_token_after(f, Token_OpenBrace, "struct"); + + isize name_count = 0; + AstNode *fields = parse_record_field_list(f, &name_count); + Token close = expect_token(f, Token_CloseBrace); + + Array<AstNode *> decls = {}; + if (fields != nullptr) { + GB_ASSERT(fields->kind == AstNode_FieldList); + decls = fields->FieldList.list; + } + + return ast_struct_type(f, token, decls, name_count, is_packed, is_ordered, align); + } break; + + case Token_union: { + Token token = expect_token(f, Token_union); + Token open = expect_token_after(f, Token_OpenBrace, "union"); + Array<AstNode *> variants = make_ast_node_array(f); + isize total_decl_name_count = 0; + + CommentGroup docs = f->lead_comment; + Token start_token = f->curr_token; + + + while (f->curr_token.kind != Token_CloseBrace && + f->curr_token.kind != Token_EOF) { + AstNode *type = parse_type(f); + if (type->kind != AstNode_BadExpr) { + array_add(&variants, type); + } + if (!allow_token(f, Token_Comma)) { + break; + } + } + + Token close = expect_token(f, Token_CloseBrace); + + return ast_union_type(f, token, variants); + } break; + + case Token_raw_union: { + Token token = expect_token(f, Token_raw_union); + Token open = expect_token_after(f, Token_OpenBrace, "raw_union"); + + isize decl_count = 0; + AstNode *fields = parse_record_field_list(f, &decl_count); + Token close = expect_token(f, Token_CloseBrace); + + Array<AstNode *> decls = {}; + if (fields != nullptr) { + GB_ASSERT(fields->kind == AstNode_FieldList); + decls = fields->FieldList.list; + } + + return ast_raw_union_type(f, token, decls, decl_count); + } break; + + case Token_enum: { + Token token = expect_token(f, Token_enum); + AstNode *base_type = nullptr; + if (f->curr_token.kind != Token_OpenBrace) { + base_type = parse_type(f); + } + Token open = expect_token(f, Token_OpenBrace); + + Array<AstNode *> values = parse_element_list(f); + Token close = expect_token(f, Token_CloseBrace); + + return ast_enum_type(f, token, base_type, values); + } break; + + case Token_bit_field: { + Token token = expect_token(f, Token_bit_field); + Array<AstNode *> fields = make_ast_node_array(f); + AstNode *align = nullptr; + Token open, close; + + isize prev_level = f->expr_level; + f->expr_level = -1; + + while (allow_token(f, Token_Hash)) { + Token tag = expect_token_after(f, Token_Ident, "#"); + if (tag.string == "align") { + if (align) { + syntax_error(tag, "Duplicate bit_field tag `#%.*s`", LIT(tag.string)); + } + align = parse_expr(f, true); + } else { + syntax_error(tag, "Invalid bit_field tag `#%.*s`", LIT(tag.string)); + } + } + + f->expr_level = prev_level; + + open = expect_token_after(f, Token_OpenBrace, "bit_field"); + + while (f->curr_token.kind != Token_EOF && + f->curr_token.kind != Token_CloseBrace) { + AstNode *name = parse_ident(f); + Token colon = expect_token(f, Token_Colon); + AstNode *value = parse_expr(f, true); + + AstNode *field = ast_field_value(f, name, value, colon); + array_add(&fields, field); + + if (f->curr_token.kind != Token_Comma) { + break; + } + advance_token(f); + } + + close = expect_token(f, Token_CloseBrace); + + return ast_bit_field_type(f, token, fields, align); + } break; + default: { + #if 0 AstNode *type = parse_type_or_ident(f); if (type != nullptr) { // TODO(bill): Is this correct??? @@ -2341,6 +2592,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) { GB_ASSERT_MSG(type->kind != AstNode_Ident, "Type cannot be identifier %.*s(%td:%td)", LIT(pos.file), pos.line, pos.column); return type; } + #endif break; } } @@ -2385,7 +2637,7 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) { if (f->curr_token.kind == Token_Ellipsis) { prefix_ellipsis = true; ellipsis = f->curr_token; - next_token(f); + advance_token(f); } AstNode *arg = parse_expr(f, false); @@ -2397,7 +2649,7 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) { } if (f->curr_token.kind == Token_Ellipsis) { ellipsis = f->curr_token; - next_token(f); + advance_token(f); } AstNode *value = parse_value(f); @@ -2450,6 +2702,7 @@ AstNode *parse_macro_call_expr(AstFile *f, AstNode *operand) { AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) { if (operand == nullptr) { + if (f->allow_type) return nullptr; Token begin = f->curr_token; syntax_error(begin, "Expected an operand"); fix_advance_to_next_stmt(f); @@ -2467,8 +2720,7 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) { break; case Token_Period: { - Token token = f->curr_token; - next_token(f); + Token token = advance_token(f); switch (f->curr_token.kind) { case Token_Ident: operand = ast_selector_expr(f, token, operand, parse_ident(f)); @@ -2485,7 +2737,7 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) { default: syntax_error(f->curr_token, "Expected a selector"); - next_token(f); + advance_token(f); operand = ast_bad_expr(f, ast_node_token(operand), f->curr_token); // operand = ast_selector_expr(f, f->curr_token, operand, nullptr); break; @@ -2516,8 +2768,7 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) { while ((f->curr_token.kind == Token_Ellipsis || f->curr_token.kind == Token_HalfClosed) && ellipsis_count < gb_count_of(ellipses)) { - ellipses[ellipsis_count++] = f->curr_token; - next_token(f); + ellipses[ellipsis_count++] = advance_token(f); if (f->curr_token.kind != Token_Ellipsis && f->curr_token.kind != Token_HalfClosed && f->curr_token.kind != Token_CloseBracket && @@ -2583,8 +2834,7 @@ AstNode *parse_unary_expr(AstFile *f, bool lhs) { case Token_Not: case Token_Xor: case Token_And: { - Token op = f->curr_token; - next_token(f); + Token op = advance_token(f); return ast_unary_expr(f, op, parse_unary_expr(f, lhs)); } break; case Token_cast: { @@ -2703,7 +2953,7 @@ Array<AstNode *> parse_expr_list(AstFile *f, bool lhs) { f->curr_token.kind == Token_EOF) { break; } - next_token(f); + advance_token(f); } return list; @@ -2726,7 +2976,7 @@ Array<AstNode *> parse_ident_list(AstFile *f) { f->curr_token.kind == Token_EOF) { break; } - next_token(f); + advance_token(f); } while (true); return list; @@ -2744,9 +2994,8 @@ AstNode *parse_type_attempt(AstFile *f) { AstNode *parse_type(AstFile *f) { AstNode *type = parse_type_attempt(f); if (type == nullptr) { - Token token = f->curr_token; + Token token = advance_token(f); syntax_error(token, "Expected a type"); - next_token(f); return ast_bad_expr(f, token, f->curr_token); } return type; @@ -2798,20 +3047,18 @@ PARSE_SPEC_FUNC(parse_import_spec) { switch (f->curr_token.kind) { case Token_Period: - import_name = f->curr_token; + import_name = advance_token(f); import_name.kind = Token_Ident; - next_token(f); break; case Token_Ident: - import_name = f->curr_token; - next_token(f); + import_name = advance_token(f); break; default: import_name.pos = f->curr_token.pos; break; } - if (import_name.string == "_") { + if (is_blank_ident(import_name)) { syntax_error(import_name, "Illegal import name: `_`"); } @@ -2856,15 +3103,13 @@ PARSE_SPEC_FUNC(parse_foreign_library_spec) { switch (f->curr_token.kind) { case Token_Ident: - lib_name = f->curr_token; - next_token(f); + lib_name = advance_token(f); break; default: lib_name.pos = f->curr_token.pos; break; } - - if (lib_name.string == "_") { + if (is_blank_ident(lib_name)) { syntax_error(lib_name, "Illegal foreign_library name: `_`"); } Token file_path = expect_token(f, Token_String); @@ -2887,15 +3132,14 @@ PARSE_SPEC_FUNC(parse_foreign_library_spec) { switch (f->curr_token.kind) { case Token_Ident: - lib_name = f->curr_token; - next_token(f); + lib_name = advance_token(f); break; default: lib_name.pos = f->curr_token.pos; break; } - if (lib_name.string == "_") { + if (is_blank_ident(lib_name)) { syntax_error(lib_name, "Illegal foreign_library name: `_`"); } Token file_path = expect_token(f, Token_String); @@ -2986,9 +3230,7 @@ AstNode *parse_decl(AstFile *f) { } } - Token token = f->curr_token; - next_token(f); - return parse_gen_decl(f, token, func); + return parse_gen_decl(f, advance_token(f), func); } AstNode *parse_value_decl(AstFile *f, Array<AstNode *> names, CommentGroup docs) { @@ -3002,7 +3244,7 @@ AstNode *parse_value_decl(AstFile *f, Array<AstNode *> names, CommentGroup docs) if (f->curr_token.kind == Token_Eq || f->curr_token.kind == Token_Colon) { - Token sep = f->curr_token; next_token(f); + Token sep = advance_token(f); is_mutable = sep.kind != Token_Colon; values = parse_rhs_expr_list(f); if (values.count > names.count) { @@ -3073,7 +3315,7 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) { syntax_error(f->curr_token, "You cannot use a simple statement in the file scope"); return ast_bad_stmt(f, f->curr_token, f->curr_token); } - next_token(f); + advance_token(f); Array<AstNode *> rhs = parse_rhs_expr_list(f); if (rhs.count == 0) { syntax_error(token, "No right-hand side in assignment statement."); @@ -3103,7 +3345,7 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) { switch (next) { case Token_for: case Token_match: { - next_token(f); + advance_token(f); AstNode *name = lhs[0]; AstNode *label = ast_label_decl(f, ast_node_token(name), name); AstNode *stmt = parse_stmt(f); @@ -3135,7 +3377,7 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) { switch (token.kind) { case Token_Inc: case Token_Dec: - next_token(f); + advance_token(f); return ast_inc_dec_stmt(f, token, lhs[0]); } @@ -3212,8 +3454,7 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) { AstNode *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_type_token) { if (allow_ellipsis && f->curr_token.kind == Token_Ellipsis) { - Token tok = f->curr_token; - next_token(f); + Token tok = advance_token(f); AstNode *type = parse_type_or_ident(f); if (type == nullptr) { error(tok, "variadic field missing type after `...`"); @@ -3254,7 +3495,7 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) { return FieldPrefix_Using; case Token_Hash: { - next_token(f); + advance_token(f); switch (f->curr_token.kind) { case Token_Ident: if (f->curr_token.string == "no_alias") { @@ -3282,9 +3523,9 @@ u32 parse_field_prefixes(AstFile *f) { break; } switch (kind) { - case FieldPrefix_Using: using_count += 1; next_token(f); break; - case FieldPrefix_NoAlias: no_alias_count += 1; next_token(f); break; - case FieldPrefix_CVarArg: c_vararg_count += 1; next_token(f); break; + case FieldPrefix_Using: using_count += 1; advance_token(f); break; + case FieldPrefix_NoAlias: no_alias_count += 1; advance_token(f); break; + case FieldPrefix_CVarArg: c_vararg_count += 1; advance_token(f); break; } } if (using_count > 1) syntax_error(f->curr_token, "Multiple `using` in this field list"); @@ -3358,8 +3599,8 @@ bool parse_expect_field_separator(AstFile *f, AstNode *param) { return true; } if (token.kind == Token_Semicolon) { - next_token(f); error(f->curr_token, "Expected a comma, got a semicolon"); + advance_token(f); return true; } return false; @@ -3372,8 +3613,8 @@ bool parse_expect_struct_separator(AstFile *f, AstNode *param) { } if (token.kind == Token_Colon) { - next_token(f); error(f->curr_token, "Expected a semicolon, got a comma"); + advance_token(f); return true; } @@ -3453,7 +3694,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok if (f->curr_token.kind != Token_Comma) { break; } - next_token(f); + advance_token(f); } if (f->curr_token.kind == Token_Colon) { @@ -3555,6 +3796,14 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok } AstNode *parse_type_or_ident(AstFile *f) { +#if 1 + bool prev_allow_type = f->allow_type; + f->allow_type = true; + AstNode *operand = parse_operand(f, true); + AstNode *type = parse_atom_expr(f, operand, true); + f->allow_type = prev_allow_type; + return type; +#else switch (f->curr_token.kind) { case Token_Dollar: { Token token = expect_token(f, Token_Dollar); @@ -3566,8 +3815,7 @@ AstNode *parse_type_or_ident(AstFile *f) { AstNode *i = ast_implicit(f, expect_token(f, Token_type_of)); AstNode *type = parse_call_expr(f, i); while (f->curr_token.kind == Token_Period) { - Token token = f->curr_token; - next_token(f); + Token token = advance_token(f); AstNode *sel = parse_ident(f); type = ast_selector_expr(f, token, type, sel); } @@ -3577,8 +3825,7 @@ AstNode *parse_type_or_ident(AstFile *f) { case Token_Ident: { AstNode *e = parse_ident(f); while (f->curr_token.kind == Token_Period) { - Token token = f->curr_token; - next_token(f); + Token token = advance_token(f); AstNode *sel = parse_ident(f); e = ast_selector_expr(f, token, e, sel); } @@ -3616,8 +3863,7 @@ AstNode *parse_type_or_ident(AstFile *f) { if (f->curr_token.kind == Token_Ellipsis) { count_expr = ast_unary_expr(f, expect_token(f, Token_Ellipsis), nullptr); - } else if (f->curr_token.kind == Token_vector) { - next_token(f); + } else if (allow_token(f, Token_vector)) { if (f->curr_token.kind != Token_CloseBracket) { f->expr_level++; count_expr = parse_expr(f, false); @@ -3626,8 +3872,7 @@ AstNode *parse_type_or_ident(AstFile *f) { syntax_error(f->curr_token, "Vector type missing count"); } is_vector = true; - } else if (f->curr_token.kind == Token_dynamic) { - next_token(f); + } else if (allow_token(f, Token_dynamic)) { expect_token(f, Token_CloseBracket); return ast_dynamic_array_type(f, token, parse_type(f)); } else if (f->curr_token.kind != Token_CloseBracket) { @@ -3806,7 +4051,7 @@ AstNode *parse_type_or_ident(AstFile *f) { if (f->curr_token.kind != Token_Comma) { break; } - next_token(f); + advance_token(f); } close = expect_token(f, Token_CloseBrace); @@ -3815,7 +4060,7 @@ AstNode *parse_type_or_ident(AstFile *f) { } break; case Token_proc: { - Token token = f->curr_token; next_token(f); + Token token = advance_token(f); AstNode *pt = parse_proc_type(f, token, nullptr); if (pt->ProcType.tags != 0) { syntax_error(token, "A procedure type cannot have tags"); @@ -3832,6 +4077,7 @@ AstNode *parse_type_or_ident(AstFile *f) { } return nullptr; +#endif } @@ -3984,7 +4230,7 @@ AstNode *parse_return_stmt(AstFile *f) { f->curr_token.kind == Token_EOF) { break; } - next_token(f); + advance_token(f); } AstNode *end = nullptr; @@ -4061,8 +4307,7 @@ AstNode *parse_for_stmt(AstFile *f) { } } - if (!is_range && f->curr_token.kind == Token_Semicolon) { - next_token(f); + if (!is_range && allow_token(f, Token_Semicolon)) { init = cond; cond = nullptr; if (f->curr_token.kind != Token_Semicolon) { @@ -4291,8 +4536,8 @@ AstNode *parse_stmt(AstFile *f) { case Token_break: case Token_continue: case Token_fallthrough: { + Token token = advance_token(f); AstNode *label = nullptr; - next_token(f); if (token.kind != Token_fallthrough && f->curr_token.kind == Token_Ident) { label = parse_ident(f); @@ -4333,7 +4578,7 @@ AstNode *parse_stmt(AstFile *f) { } break; case Token_push_allocator: { - next_token(f); + advance_token(f); AstNode *body = nullptr; isize prev_level = f->expr_level; f->expr_level = -1; @@ -4350,7 +4595,7 @@ AstNode *parse_stmt(AstFile *f) { } break; case Token_push_context: { - next_token(f); + advance_token(f); AstNode *body = nullptr; isize prev_level = f->expr_level; f->expr_level = -1; @@ -4432,7 +4677,7 @@ AstNode *parse_stmt(AstFile *f) { case Token_Semicolon: s = ast_empty_stmt(f, token); - next_token(f); + advance_token(f); return s; } @@ -4694,9 +4939,7 @@ void parse_file(Parser *p, AstFile *f) { base_dir.len--; } - while (f->curr_token.kind == Token_Comment) { - next_token(f); - } + comsume_comment_groups(f, f->prev_token); f->decls = parse_stmt_list(f); parse_setup_file_decls(p, f, base_dir, f->decls); diff --git a/src/types.cpp b/src/types.cpp index 1604ec3f2..d25f3fba9 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1476,7 +1476,7 @@ Entity *current_scope_lookup_entity(Scope *s, String name); Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel) { GB_ASSERT(type_ != nullptr); - if (field_name == "_") { + if (is_blank_ident(field_name)) { return empty_selection; } |