diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-04-02 18:16:45 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-04-02 18:16:45 +0100 |
| commit | 8ce58573dfa2c140dcafd633e51c56d555f7ebc1 (patch) | |
| tree | 0bbcfca14f77f8cbcbb6385e72148d3fbb1caedb | |
| parent | 2c8b99337bb33d0f713026c5c38e05428cc52143 (diff) | |
len, cap, make; remove .count, .capacity, new_slice
| -rw-r--r-- | code/demo.odin | 18 | ||||
| -rw-r--r-- | core/_preload.odin | 117 | ||||
| -rw-r--r-- | core/decimal.odin | 12 | ||||
| -rw-r--r-- | core/fmt.odin | 74 | ||||
| -rw-r--r-- | core/hash.odin | 14 | ||||
| -rw-r--r-- | core/mem.odin | 12 | ||||
| -rw-r--r-- | core/opengl.odin | 6 | ||||
| -rw-r--r-- | core/os_windows.odin | 17 | ||||
| -rw-r--r-- | core/strconv.odin | 33 | ||||
| -rw-r--r-- | core/strings.odin | 15 | ||||
| -rw-r--r-- | core/utf8.odin | 8 | ||||
| -rw-r--r-- | src/check_expr.c | 133 | ||||
| -rw-r--r-- | src/checker.c | 12 | ||||
| -rw-r--r-- | src/ir.c | 221 | ||||
| -rw-r--r-- | src/tokenizer.c | 10 | ||||
| -rw-r--r-- | src/types.c | 21 |
16 files changed, 538 insertions, 185 deletions
diff --git a/code/demo.odin b/code/demo.odin index 197aa83fe..ba157a977 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,10 +1,18 @@ +#import "atomic.odin"; +#import "decimal.odin"; #import "fmt.odin"; -#import "os.odin"; +#import "hash.odin"; #import "math.odin"; +#import "mem.odin"; +#import "opengl.odin"; +#import "os.odin"; +#import "strconv.odin"; +#import "strings.odin"; +#import "sync.odin"; +#import "types.odin"; +#import "utf8.odin"; +#import "utf16.odin"; main :: proc() { - x := 1+2i+3j+4k; - y := conj(x); - z := x/y; - fmt.println(z, abs(z)); + } diff --git a/core/_preload.odin b/core/_preload.odin index f06d9bafb..0b5efc0d5 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -277,17 +277,17 @@ default_allocator :: proc() -> Allocator { __string_eq :: proc(a, b: string) -> bool { - if a.count != b.count { + if len(a) != len(b) { return false; } - if a.data == b.data { + if ^a[0] == ^b[0] { return true; } return __string_cmp(a, b) == 0; } __string_cmp :: proc(a, b: string) -> int { - return __mem_compare(a.data, b.data, min(a.count, b.count)); + return __mem_compare(^a[0], ^b[0], min(len(a), len(b))); } __string_ne :: proc(a, b: string) -> bool #inline { return !__string_eq(a, b); } @@ -426,19 +426,19 @@ Raw_Any :: struct #ordered { Raw_String :: struct #ordered { data: ^byte, - count: int, + len: int, }; Raw_Slice :: struct #ordered { - data: rawptr, - count: int, - capacity: int, + data: rawptr, + len: int, + cap: int, }; Raw_Dynamic_Array :: struct #ordered { data: rawptr, - count: int, - capacity: int, + len: int, + cap: int, allocator: Allocator, }; @@ -448,11 +448,22 @@ Raw_Dynamic_Map :: struct #ordered { }; +__dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int) { + array := cast(^Raw_Dynamic_Array)array_; + __check_context(); + array.allocator = context.allocator; + assert(array.allocator.procedure != nil); + + if cap > 0 { + __dynamic_array_reserve(array_, elem_size, elem_align, cap); + array.len = len; + } +} -__dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, capacity: int) -> bool { +__dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int) -> bool { array := cast(^Raw_Dynamic_Array)array_; - if capacity <= array.capacity { + if cap <= array.cap { return true; } @@ -462,8 +473,8 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, capa } assert(array.allocator.procedure != nil); - old_size := array.capacity * elem_size; - new_size := capacity * elem_size; + old_size := array.cap * elem_size; + new_size := cap * elem_size; allocator := array.allocator; new_data := allocator.procedure(allocator.data, Allocator_Mode.RESIZE, new_size, elem_align, array.data, old_size, 0); @@ -472,7 +483,7 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, capa } array.data = new_data; - array.capacity = capacity; + array.cap = cap; return true; } @@ -482,43 +493,43 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int, array := cast(^Raw_Dynamic_Array)array_; if item_count <= 0 || items == nil { - return array.count; + return array.len; } ok := true; - if array.capacity <= array.count+item_count { - capacity := 2 * array.capacity + max(8, item_count); - ok = __dynamic_array_reserve(array, elem_size, elem_align, capacity); + if array.cap <= array.len+item_count { + cap := 2 * array.cap + max(8, item_count); + ok = __dynamic_array_reserve(array, elem_size, elem_align, cap); } if !ok { // TODO(bill): Better error handling for failed reservation - return array.count; + return array.len; } data := cast(^byte)array.data; assert(data != nil); - __mem_copy(data + (elem_size*array.count), items, elem_size * item_count); - array.count += item_count; - return array.count; + __mem_copy(data + (elem_size*array.len), items, elem_size * item_count); + array.len += item_count; + return array.len; } __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int) -> int { array := cast(^Raw_Dynamic_Array)array_; ok := true; - if array.capacity <= array.count+1 { - capacity := 2 * array.capacity + max(8, 1); - ok = __dynamic_array_reserve(array, elem_size, elem_align, capacity); + if array.cap <= array.len+1 { + cap := 2 * array.cap + max(8, 1); + ok = __dynamic_array_reserve(array, elem_size, elem_align, cap); } if !ok { // TODO(bill): Better error handling for failed reservation - return array.count; + return array.len; } data := cast(^byte)array.data; assert(data != nil); - __mem_zero(data + (elem_size*array.count), elem_size); - array.count++; - return array.count; + __mem_zero(data + (elem_size*array.len), elem_size); + array.len++; + return array.len; } __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int, @@ -526,17 +537,17 @@ __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int, slice := cast(^Raw_Slice)slice_; if item_count <= 0 || items == nil { - return slice.count; + return slice.len; } - item_count = min(slice.capacity-slice.count, item_count); + item_count = min(slice.cap-slice.len, item_count); if item_count > 0 { data := cast(^byte)slice.data; assert(data != nil); - __mem_copy(data + (elem_size*slice.count), items, elem_size * item_count); - slice.count += item_count; + __mem_copy(data + (elem_size*slice.len), items, elem_size * item_count); + slice.len += item_count; } - return slice.count; + return slice.len; } @@ -583,9 +594,9 @@ __Map_Header :: struct #ordered { value_offset: int, } -__dynamic_map_reserve :: proc(using header: __Map_Header, capacity: int) -> bool { - h := __dynamic_array_reserve(^m.hashes, size_of(int), align_of(int), capacity); - e := __dynamic_array_reserve(^m.entries, entry_size, entry_align, capacity); +__dynamic_map_reserve :: proc(using header: __Map_Header, cap: int) -> bool { + h := __dynamic_array_reserve(^m.hashes, size_of(int), align_of(int), cap); + e := __dynamic_array_reserve(^m.entries, entry_size, entry_align, cap); return h && e; } @@ -594,18 +605,22 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) { nm: Raw_Dynamic_Map; new_header.m = ^nm; + header_hashes := cast(^Raw_Dynamic_Array)^header.m.hashes; + nm_hashes := cast(^Raw_Dynamic_Array)^nm.hashes; + + reserve(nm.hashes, new_count); - nm.hashes.count = nm.hashes.capacity; - __dynamic_array_reserve(^nm.entries, entry_size, entry_align, m.entries.count); + nm_hashes.len = nm_hashes.cap; + __dynamic_array_reserve(^nm.entries, entry_size, entry_align, m.entries.len); for _, i in nm.hashes { nm.hashes[i] = -1; } - for i := 0; i < nm.entries.count; i++ { + for i := 0; i < nm.entries.len; i++ { entry_header := __dynamic_map_get_entry(new_header, i); data := cast(^byte)entry_header; - if nm.hashes.count == 0 { + if len(nm.hashes) == 0 { __dynamic_map_grow(new_header); } @@ -626,7 +641,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) { __dynamic_map_grow(new_header); } } - free_ptr_with_allocator(header.m.hashes.allocator, header.m.hashes.data); + free_ptr_with_allocator(header_hashes.allocator, header_hashes.data); free_ptr_with_allocator(header.m.entries.allocator, header.m.entries.data); header.m^ = nm; } @@ -644,7 +659,7 @@ __dynamic_map_get :: proc(h: __Map_Header, key: __Map_Key) -> rawptr { __dynamic_map_set :: proc(using h: __Map_Header, key: __Map_Key, value: rawptr) { index: int; - if m.hashes.count == 0 { + if len(m.hashes) == 0 { __dynamic_map_grow(h); } fr := __dynamic_map_find(h, key); @@ -672,12 +687,12 @@ __dynamic_map_set :: proc(using h: __Map_Header, key: __Map_Key, value: rawptr) __dynamic_map_grow :: proc(using h: __Map_Header) { - new_count := 2*m.entries.count + 8; + new_count := 2*m.entries.len + 8; __dynamic_map_rehash(h, new_count); } __dynamic_map_full :: proc(using h: __Map_Header) -> bool { - return cast(int)(0.75 * cast(f64)m.hashes.count) <= m.entries.count; + return cast(int)(0.75 * cast(f64)len(m.hashes)) <= m.entries.len; } @@ -693,8 +708,8 @@ __dynamic_map_hash_equal :: proc(h: __Map_Header, a, b: __Map_Key) -> bool { __dynamic_map_find :: proc(using h: __Map_Header, key: __Map_Key) -> __Map_Find_Result { fr := __Map_Find_Result{-1, -1, -1}; - if m.hashes.count > 0 { - fr.hash_index = cast(int)(key.hash % cast(u64)m.hashes.count); + if len(m.hashes) > 0 { + fr.hash_index = cast(int)(key.hash % cast(u64)len(m.hashes)); fr.entry_index = m.hashes[fr.hash_index]; for fr.entry_index >= 0 { entry := __dynamic_map_get_entry(h, fr.entry_index); @@ -709,7 +724,7 @@ __dynamic_map_find :: proc(using h: __Map_Header, key: __Map_Key) -> __Map_Find_ } __dynamic_map_add_entry :: proc(using h: __Map_Header, key: __Map_Key) -> int { - prev := m.entries.count; + prev := m.entries.len; c := __dynamic_array_append_nothing(^m.entries, entry_size, entry_align); if c != prev { end := __dynamic_map_get_entry(h, c-1); @@ -739,10 +754,10 @@ __dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) { __dynamic_map_get_entry(h, fr.entry_prev).next = __dynamic_map_get_entry(h, fr.entry_index).next; } - if fr.entry_index == m.entries.count-1 { - m.entries.count--; + if fr.entry_index == m.entries.len-1 { + m.entries.len--; } - __mem_copy(__dynamic_map_get_entry(h, fr.entry_index), __dynamic_map_get_entry(h, m.entries.count-1), entry_size); + __mem_copy(__dynamic_map_get_entry(h, fr.entry_index), __dynamic_map_get_entry(h, m.entries.len-1), entry_size); last := __dynamic_map_find(h, __dynamic_map_get_entry(h, fr.entry_index).key); if last.entry_prev >= 0 { __dynamic_map_get_entry(h, last.entry_prev).next = fr.entry_index; diff --git a/core/decimal.odin b/core/decimal.odin index 07031104b..6d9593895 100644 --- a/core/decimal.odin +++ b/core/decimal.odin @@ -14,14 +14,14 @@ decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string { for _, i in buf { buf[i] = '0'; } - return buf.count; + return len(buf); } n := 10 + a.count + abs(a.decimal_point); // TODO(bill): make this work with a buffer that's not big enough - assert(buf.count >= n); + assert(len(buf) >= n); buf = buf[..n]; if a.count == 0 { @@ -118,7 +118,7 @@ shift_right :: proc(a: ^Decimal, k: uint) { for n > 0 { dig := n>>k; n &= mask; - if w < a.digits.count { + if w < len(a.digits) { a.digits[w] = cast(byte)('0' + dig); w++; } else if dig > 0 { @@ -144,7 +144,7 @@ shift_left :: proc(a: ^Decimal, k: uint) { quo := n/10; rem := n - 10*quo; w--; - if w < a.digits.count { + if w < len(a.digits) { a.digits[w] = cast(byte)('0' + rem); } else if rem != 0 { a.trunc = true; @@ -156,7 +156,7 @@ shift_left :: proc(a: ^Decimal, k: uint) { quo := n/10; rem := n - 10*quo; w--; - if w < a.digits.count { + if w < len(a.digits) { a.digits[w] = cast(byte)('0' + rem); } else if rem != 0 { a.trunc = true; @@ -165,7 +165,7 @@ shift_left :: proc(a: ^Decimal, k: uint) { } a.count += delta; - a.count = min(a.count, a.digits.count); + a.count = min(a.count, len(a.digits)); a.decimal_point += delta; trim(a); } diff --git a/core/fmt.odin b/core/fmt.odin index 480155c08..a39e5db2e 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -48,23 +48,23 @@ fprint :: proc(fd: os.Handle, args: ..any) -> int { data: [_BUFFER_SIZE]byte; buf := data[..0]; bprint(^buf, ..args); - os.write(fd, buf[..buf.count]); - return buf.count; + os.write(fd, buf[..len(buf)]); + return len(buf); } fprintln :: proc(fd: os.Handle, args: ..any) -> int { data: [_BUFFER_SIZE]byte; buf := data[..0]; bprintln(^buf, ..args); - os.write(fd, buf[..buf.count]); - return buf.count; + os.write(fd, buf[..len(buf)]); + return len(buf); } fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int { data: [_BUFFER_SIZE]byte; buf := data[..0]; bprintf(^buf, fmt, ..args); - os.write(fd, buf[..buf.count]); - return buf.count; + os.write(fd, buf[..len(buf)]); + return len(buf); } @@ -83,7 +83,7 @@ fprint_type :: proc(fd: os.Handle, info: ^Type_Info) { data: [_BUFFER_SIZE]byte; buf := data[..0]; write_type(^buf, info); - os.write(fd, buf[..buf.count]); + os.write(fd, buf[..len(buf)]); } write_type :: proc(buf: ^[]byte, ti: ^Type_Info) { @@ -147,14 +147,14 @@ write_type :: proc(buf: ^[]byte, ti: ^Type_Info) { write_type(buf, info.results); } case Tuple: - count := info.names.count; + count := len(info.names); if count != 1 { write_string(buf, "("); } for name, i in info.names { if i > 0 { write_string(buf, ", "); } type := info.types[i]; - if name.count > 0 { + if len(name) > 0 { write_string(buf, name); write_string(buf, ": "); } @@ -233,12 +233,12 @@ write_type :: proc(buf: ^[]byte, ti: ^Type_Info) { variant_type := type_info_base(info.variant_types[i]); variant := union_cast(^Struct)variant_type; - vc := variant.names.count-cf.names.count; + vc := len(variant.names)-len(cf.names); for j in 0..vc { if j > 0 { write_string(buf, ", "); } - index := j + cf.names.count; + index := j + len(cf.names); write_string(buf, variant.names[index]); write_string(buf, ": "); write_type(buf, variant.types[index]); @@ -279,14 +279,14 @@ bprint :: proc(buf: ^[]byte, args: ..any) -> int { prev_string := false; for arg, i in args { - is_string := arg.data != nil && types.is_string(arg.type_info); + is_string := arg != nil && types.is_string(arg.type_info); if i > 0 && !is_string && !prev_string { write_byte(buf, ' '); } fmt_value(^fi, args[i], 'v'); prev_string = is_string; } - return buf.count; + return len(buf); } bprintln :: proc(buf: ^[]byte, args: ..any) -> int { @@ -300,7 +300,7 @@ bprintln :: proc(buf: ^[]byte, args: ..any) -> int { fmt_value(^fi, args[i], 'v'); } write_byte(buf, '\n'); - return buf.count; + return len(buf); } sprint :: proc(buf: []byte, args: ..any) -> string { @@ -328,7 +328,7 @@ parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: bool ok := true; i := 0; - for o in offset..s.count { + for o in offset..len(s) { c := cast(rune)s[offset+i]; if !is_digit(c) { break; @@ -349,11 +349,11 @@ _arg_number :: proc(fi: ^Fmt_Info, arg_count: int, ) -> (index: int, offset: int, ok: bool) { parse_arg_number :: proc(format: string) -> (int, int, bool) { - if format.count < 3 { + if len(format) < 3 { return 0, 1, false; } - for i in 1..format.count { + for i in 1..len(format) { if format[i] == ']' { width, new_index, ok := parse_int(format, 1); if !ok || new_index != i { @@ -367,7 +367,7 @@ _arg_number :: proc(fi: ^Fmt_Info, } - if format.count <= offset || format[offset] != '[' { + if len(format) <= offset || format[offset] != '[' { return arg_index, offset, false; } fi.reordered = true; @@ -383,7 +383,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) { num := 0; new_arg_index := arg_index; ok := true; - if arg_index < args.count { + if arg_index < len(args) { arg := args[arg_index]; arg.type_info = type_info_base(arg.type_info); match i in arg { @@ -439,7 +439,7 @@ fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) { pad_byte = '0'; } - count := min(width, fi.buf.capacity-fi.buf.count); + count := min(width, cap(fi.buf)-len(fi.buf)); for _ in 0..count { append(fi.buf, pad_byte); } @@ -585,7 +585,7 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) { } buf: [128]byte; str := strconv.append_float(buf[1..1], v, 'f', prec, bit_size); - str = cast(string)buf[..str.count+1]; + str = cast(string)buf[..len(str)+1]; if str[1] == '+' || str[1] == '-' { str = str[1..]; } else { @@ -602,9 +602,9 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) { } if fi.plus || str[0] != '+' { - if fi.zero && fi.width_set && fi.width > str.count { + if fi.zero && fi.width_set && fi.width > len(str) { write_byte(fi.buf, str[0]); - fmt_write_padding(fi, fi.width - str.count); + fmt_write_padding(fi, fi.width - len(str)); write_string(fi.buf, str[1..]); } else { _pad(fi, str); @@ -685,7 +685,7 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) { break; } } - } else if e.values.count == 0 { + } else if len(e.values) == 0 { write_string(fi.buf, ""); ok = true; } else { @@ -780,7 +780,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { write_byte(fi.buf, '['); defer write_byte(fi.buf, ']'); array := cast(^Raw_Dynamic_Array)v.data; - for i in 0..array.count { + for i in 0..array.len { if i > 0 { write_string(fi.buf, ", "); } @@ -802,7 +802,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { entry_type := union_cast(^Struct)ed.elem; entry_size := ed.elem_size; - for i in 0..entries.count { + for i in 0..entries.len { if i > 0 { write_string(fi.buf, ", "); } @@ -831,11 +831,11 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { write_byte(fi.buf, '['); defer write_byte(fi.buf, ']'); slice := cast(^[]byte)v.data; - for i in 0..slice.count { + for i in 0..len(slice) { if i > 0 { write_string(fi.buf, ", "); } - data := slice.data + i*info.elem_size; + data := ^slice[0] + i*info.elem_size; fmt_arg(fi, any{info.elem, cast(rawptr)data}, 'v'); } @@ -941,7 +941,7 @@ fmt_quaternion :: proc(fi: ^Fmt_Info, c: quaternion256, bits: int, verb: rune) { } fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { - if arg.data == nil || arg.type_info == nil { + if arg == nil { write_string(fi.buf, "<nil>"); return; } @@ -987,7 +987,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { bprintf :: proc(b: ^[]byte, fmt: string, args: ..any) -> int { fi := Fmt_Info{}; - end := fmt.count; + end := len(fmt); arg_index := 0; was_prev_index := false; for i := 0; i < end; { @@ -1026,7 +1026,7 @@ bprintf :: proc(b: ^[]byte, fmt: string, args: ..any) -> int { } } - arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, args.count); + arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, len(args)); // Width if i < end && fmt[i] == '*' { @@ -1056,7 +1056,7 @@ bprintf :: proc(b: ^[]byte, fmt: string, args: ..any) -> int { fi.good_arg_index = false; } if i < end && fmt[i] == '*' { - arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, args.count); + arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, len(args)); i++; fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index); if fi.prec < 0 { @@ -1077,7 +1077,7 @@ bprintf :: proc(b: ^[]byte, fmt: string, args: ..any) -> int { } if !was_prev_index { - arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, args.count); + arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, len(args)); } if i >= end { @@ -1092,7 +1092,7 @@ bprintf :: proc(b: ^[]byte, fmt: string, args: ..any) -> int { write_byte(b, '%'); } else if !fi.good_arg_index { write_string(b, "%!(BAD ARGUMENT NUMBER)"); - } else if arg_index >= args.count { + } else if arg_index >= len(args) { write_string(b, "%!(MISSING ARGUMENT)"); } else { fmt_arg(^fi, args[arg_index], verb); @@ -1100,13 +1100,13 @@ bprintf :: proc(b: ^[]byte, fmt: string, args: ..any) -> int { } } - if !fi.reordered && arg_index < args.count { + if !fi.reordered && arg_index < len(args) { write_string(b, "%!(EXTRA "); for arg, index in args[arg_index..] { if index > 0 { write_string(b, ", "); } - if arg.data == nil || arg.type_info == nil { + if arg == nil { write_string(b, "<nil>"); } else { fmt_arg(^fi, args[index], 'v'); @@ -1115,5 +1115,5 @@ bprintf :: proc(b: ^[]byte, fmt: string, args: ..any) -> int { write_string(b, ")"); } - return b.count; + return len(b); } diff --git a/core/hash.odin b/core/hash.odin index 6d61594d2..b4bd5ca83 100644 --- a/core/hash.odin +++ b/core/hash.odin @@ -50,8 +50,8 @@ murmur32 :: proc(data: []byte) -> u32 { c2_32: u32 : 0x1b873593; h1: u32 = 0; - nblocks := data.count/4; - p := data.data; + nblocks := len(data)/4; + p := ^data[0]; p1 := p + 4*nblocks; for ; p < p1; p += 4 { @@ -69,7 +69,7 @@ murmur32 :: proc(data: []byte) -> u32 { tail := data[nblocks*4 ..]; k1: u32; - match tail.count&3 { + match len(tail)&3 { case 3: k1 ~= cast(u32)tail[2] << 16; fallthrough; @@ -84,7 +84,7 @@ murmur32 :: proc(data: []byte) -> u32 { h1 ~= k1; } - h1 ~= cast(u32)data.count; + h1 ~= cast(u32)len(data); h1 ~= h1 >> 16; h1 *= 0x85ebca6b; @@ -137,11 +137,11 @@ murmur64 :: proc(data: []byte) -> u64 { m :: 0x5bd1e995; r :: 24; - h1: u32 = cast(u32)SEED ~ cast(u32)data.count; + h1: u32 = cast(u32)SEED ~ cast(u32)len(data); h2: u32 = SEED >> 32; - data32 := slice_ptr(cast(^u32)^data[0], data.count/size_of(u32)); - len := data.count; + data32 := slice_ptr(cast(^u32)^data[0], len(data)/size_of(u32)); + len := len(data); i := 0; for len >= 8 { diff --git a/core/mem.odin b/core/mem.odin index 1560ca410..f3396b7ac 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -19,7 +19,7 @@ copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr { return __mem_copy_non_overlapping(dst, src, len); } compare :: proc(a, b: []byte) -> int { - return __mem_compare(a.data, b.data, min(a.count, b.count)); + return __mem_compare(^a[0], ^b[0], min(len(a), len(b))); } @@ -102,7 +102,7 @@ init_arena_from_memory :: proc(using a: ^Arena, data: []byte) { init_arena_from_context :: proc(using a: ^Arena, size: int) { backing = context.allocator; - memory = new_slice(byte, size); + memory = make([]byte, size); temp_count = 0; } @@ -133,7 +133,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, case ALLOC: total_size := size + alignment; - if arena.offset + total_size > arena.memory.count { + if arena.offset + total_size > len(arena.memory) { fmt.fprintln(os.stderr, "Arena out of memory"); return nil; } @@ -161,15 +161,15 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, begin_arena_temp_memory :: proc(a: ^Arena) -> Arena_Temp_Memory { tmp: Arena_Temp_Memory; tmp.arena = a; - tmp.original_count = a.memory.count; + tmp.original_count = len(a.memory); a.temp_count++; return tmp; } end_arena_temp_memory :: proc(using tmp: Arena_Temp_Memory) { - assert(arena.memory.count >= original_count); + assert(len(arena.memory) >= original_count); assert(arena.temp_count > 0); - arena.memory.count = original_count; + arena.memory = arena.memory[..original_count]; arena.temp_count--; } diff --git a/core/opengl.odin b/core/opengl.odin index 4e3ab9c39..88ea8c4b4 100644 --- a/core/opengl.odin +++ b/core/opengl.odin @@ -35,10 +35,10 @@ string_data :: proc(s: string) -> ^u8 #inline { return ^s[0]; } _libgl := win32.LoadLibraryA(string_data("opengl32.dll\x00")); GetProcAddress :: proc(name: string) -> proc() #cc_c { - assert(name[name.count-1] == 0); - res := wgl.GetProcAddress(name.data); + assert(name[len(name)-1] == 0); + res := wgl.GetProcAddress(^name[0]); if res == nil { - res = win32.GetProcAddress(_libgl, name.data); + res = win32.GetProcAddress(_libgl, ^name[0]); } return res; } diff --git a/core/os_windows.odin b/core/os_windows.odin index b834a2726..157bb7b55 100644 --- a/core/os_windows.odin +++ b/core/os_windows.odin @@ -53,7 +53,7 @@ args := _alloc_command_line_arguments(); open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) { - if path.count == 0 { + if len(path) == 0 { return INVALID_HANDLE, ERROR_FILE_NOT_FOUND; } @@ -110,7 +110,7 @@ close :: proc(fd: Handle) { write :: proc(fd: Handle, data: []byte) -> (int, Errno) { bytes_written: i32; - e := win32.WriteFile(cast(win32.Handle)fd, data.data, cast(i32)data.count, ^bytes_written, nil); + e := win32.WriteFile(cast(win32.Handle)fd, ^data[0], cast(i32)len(data), ^bytes_written, nil); if e == win32.FALSE { err := win32.GetLastError(); return 0, cast(Errno)err; @@ -120,7 +120,7 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) { read :: proc(fd: Handle, data: []byte) -> (int, Errno) { bytes_read: i32; - e := win32.ReadFile(cast(win32.Handle)fd, data.data, cast(u32)data.count, ^bytes_read, nil); + e := win32.ReadFile(cast(win32.Handle)fd, ^data[0], cast(u32)len(data), ^bytes_read, nil); if e == win32.FALSE { err := win32.GetLastError(); return 0, cast(Errno)err; @@ -180,7 +180,7 @@ last_write_time_by_name :: proc(name: string) -> File_Time { data: win32.File_Attribute_Data; buf: [1024]byte; - assert(buf.count > name.count); + assert(len(buf) > len(name)); copy(buf[..], cast([]byte)name); @@ -213,8 +213,8 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) { return nil, false; } - data := new_slice(u8, length); - if data.data == nil { + data := make([]byte, length); + if ^data[0] == nil { return nil, false; } @@ -286,10 +286,9 @@ _alloc_command_line_arguments :: proc() -> []string { wstr_len++; } len := 2*wstr_len-1; - buf := new_slice(byte, len+1); + buf := make([]byte, len+1); str := slice_ptr(wstr, wstr_len+1); - i, j := 0, 0; for str[j] != 0 { match { @@ -334,7 +333,7 @@ _alloc_command_line_arguments :: proc() -> []string { arg_count: i32; arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), ^arg_count); - arg_list := new_slice(string, arg_count); + arg_list := make([]string, arg_count); for _, i in arg_list { arg_list[i] = alloc_ucs2_to_utf8((arg_list_ptr+i)^); } diff --git a/core/strconv.odin b/core/strconv.odin index 998129829..e083bfd82 100644 --- a/core/strconv.odin +++ b/core/strconv.odin @@ -131,50 +131,33 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slice, prec: int, fmt: byte) -> []byte { match fmt { case 'f', 'F': - add_bytes :: proc(dst: ^[]byte, w: ^int, bytes: ..byte) { - for b in bytes { - if dst.capacity <= w^ { - break; - } - dst.count++; - dst[w^] = b; - w^++; - } - } - - dst := buf[..]; - w := 0; - if neg { - add_bytes(^dst, ^w, '-'); - } else { - add_bytes(^dst, ^w, '+'); - } + append(buf, neg ? '-' : '+'); // integer, padded with zeros when needed if digs.decimal_point > 0 { m := min(digs.count, digs.decimal_point); - add_bytes(^dst, ^w, ..digs.digits[..m]); + append(buf, ..digs.digits[..m]); for ; m < digs.decimal_point; m++ { - add_bytes(^dst, ^w, '0'); + append(buf, '0'); } } else { - add_bytes(^dst, ^w, '0'); + append(buf, '0'); } // fractional part if prec > 0 { - add_bytes(^dst, ^w, '.'); + append(buf, '.'); for i in 0..prec { c: byte = '0'; if j := digs.decimal_point + i; 0 <= j && j < digs.count { c = digs.digits[j]; } - add_bytes(^dst, ^w, c); + append(buf, c); } } - return buf[..w]; + return buf; case 'e', 'E': panic("strconv: e/E float printing is not yet supported"); @@ -308,7 +291,7 @@ append_bits :: proc(buf: []byte, u: u64, base: int, is_signed: bool, bit_size: i } a: [65]byte; - i := a.count; + i := len(a); neg: bool; u, neg = is_integer_negative(u, is_signed, bit_size); diff --git a/core/strings.odin b/core/strings.odin index 7b2f09230..846c7398c 100644 --- a/core/strings.odin +++ b/core/strings.odin @@ -1,15 +1,14 @@ new_c_string :: proc(s: string) -> ^byte { - c := new_slice(byte, s.count+1); + c := make([]byte, len(s)+1); copy(c, cast([]byte)s); - c[s.count] = 0; - return c.data; + c[len(s)] = 0; + return ^c[0]; } to_odin_string :: proc(c: ^byte) -> string { - s: string; - s.data = c; - for (c+s.count)^ != 0 { - s.count++; + len := 0; + for (c+len)^ != 0 { + len++; } - return s; + return cast(string)slice_ptr(c, len); } diff --git a/core/utf8.odin b/core/utf8.odin index a90e4e45b..b933448b9 100644 --- a/core/utf8.odin +++ b/core/utf8.odin @@ -94,7 +94,7 @@ encode_rune :: proc(r: rune) -> ([4]byte, int) { decode_rune :: proc(s: string) -> (rune, int) #inline { return decode_rune(cast([]byte)s); } decode_rune :: proc(s: []byte) -> (rune, int) { - n := s.count; + n := len(s); if n < 1 { return RUNE_ERROR, 0; } @@ -138,7 +138,7 @@ decode_last_rune :: proc(s: []byte) -> (rune, int) { size: int; start, end, limit: int; - end = s.count; + end = len(s); if end == 0 { return RUNE_ERROR, 0; } @@ -183,7 +183,7 @@ valid_rune :: proc(r: rune) -> bool { } valid_string :: proc(s: string) -> bool { - n := s.count; + n := len(s); for i := 0; i < n; { si := s[i]; if si < RUNE_SELF { // ascii @@ -220,7 +220,7 @@ rune_start :: proc(b: byte) -> bool #inline { return b&0xc0 != 0x80; } rune_count :: proc(s: string) -> int #inline { return rune_count(cast([]byte)s); } rune_count :: proc(s: []byte) -> int { count := 0; - n := s.count; + n := len(s); for i := 0; i < n; { defer count++; diff --git a/src/check_expr.c b/src/check_expr.c index 55dcdb941..477520aa7 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -249,8 +249,12 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n operand->mode = Addressing_Invalid; return; } - target_type = default_type(operand->type); - GB_ASSERT(is_type_typed(target_type)); + if (is_type_any(type)) { + target_type = t_any; + } else { + target_type = default_type(operand->type); + } + GB_ASSERT_MSG(is_type_typed(target_type), "%s", type_to_string(type)); add_type_info_type(c, type); add_type_info_type(c, target_type); } @@ -1963,7 +1967,9 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) { switch (op) { case Token_CmpEq: case Token_NotEq: - defined = is_type_comparable(x->type); + defined = is_type_comparable(x->type) || + (is_operand_nil(*x) && type_has_nil(y->type)) || + (is_operand_nil(*y) && type_has_nil(x->type)); break; case Token_Lt: case Token_Gt: @@ -1973,6 +1979,7 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) { } break; } + #if 0 // CLEANUP(bill) NOTE(bill): there is an auto assignment to `any` which needs to be checked if (is_type_any(x->type) && !is_type_any(y->type)) { err_type = x->type; @@ -1981,8 +1988,14 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) { err_type = y->type; defined = false; } + #endif if (!defined) { + if (x->type == err_type && is_operand_nil(*x)) { + err_type = y->type; + } + gb_printf_err("%d %d\n", is_operand_nil(*x), type_has_nil(y->type)); + gb_printf_err("%d %d\n", is_operand_nil(*y), type_has_nil(x->type)); gbString type_string = type_to_string(err_type); err_str = gb_string_make(c->tmp_allocator, gb_bprintf("operator `%.*s` not defined for type `%s`", LIT(token_strings[op]), type_string)); @@ -2659,7 +2672,9 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level break; case Basic_UntypedNil: - if (!type_has_nil(target_type)) { + if (is_type_any(target_type)) { + target_type = t_untyped_nil; + } else if (!type_has_nil(target_type)) { operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); return; @@ -3070,11 +3085,11 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } } - Operand prev_operand = *operand; switch (id) { case BuiltinProc_new: - case BuiltinProc_new_slice: + // case BuiltinProc_new_slice: + case BuiltinProc_make: case BuiltinProc_size_of: case BuiltinProc_align_of: case BuiltinProc_offset_of: @@ -3090,6 +3105,53 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id GB_PANIC("Implement builtin procedure: %.*s", LIT(builtin_procs[id].name)); break; + case BuiltinProc_len: + case BuiltinProc_cap: { + // len :: proc(Type) -> int + // cap :: proc(Type) -> int + Type *op_type = type_deref(operand->type); + Type *type = t_int; + AddressingMode mode = Addressing_Invalid; + ExactValue value = {0}; + if (is_type_string(op_type) && id == BuiltinProc_len) { + if (operand->mode == Addressing_Constant) { + mode = Addressing_Constant; + String str = operand->value.value_string; + value = exact_value_integer(str.len); + type = t_untyped_integer; + } else { + mode = Addressing_Value; + } + } else if (is_type_array(op_type)) { + Type *at = core_type(op_type); + mode = Addressing_Constant; + value = exact_value_integer(at->Array.count); + type = t_untyped_integer; + } else if (is_type_vector(op_type) && id == BuiltinProc_len) { + Type *at = core_type(op_type); + mode = Addressing_Constant; + value = exact_value_integer(at->Vector.count); + type = t_untyped_integer; + } else if (is_type_slice(op_type)) { + mode = Addressing_Value; + } else if (is_type_dynamic_array(op_type)) { + mode = Addressing_Value; + } else if (is_type_map(op_type)) { + mode = Addressing_Value; + } + + if (mode == Addressing_Invalid) { + String name = builtin_procs[id].name; + gbString t = type_to_string(operand->type); + error_node(call, "`%.*s` is not supported for `%s`", LIT(name), t); + return false; + } + + operand->mode = mode; + operand->value = value; + operand->type = type; + } break; + case BuiltinProc_new: { // new :: proc(Type) -> ^Type Operand op = {0}; @@ -3102,6 +3164,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id operand->mode = Addressing_Value; operand->type = make_type_pointer(c->allocator, type); } break; + #if 0 case BuiltinProc_new_slice: { // new_slice :: proc(Type, len: int) -> []Type // new_slice :: proc(Type, len, cap: int) -> []Type @@ -3139,6 +3202,62 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id operand->mode = Addressing_Value; operand->type = make_type_slice(c->allocator, type); } break; + #endif + case BuiltinProc_make: { + // make :: proc(Type, len: int) -> []Type + // make :: proc(Type, len, cap: int) -> []Type + Operand op = {0}; + check_expr_or_type(c, &op, ce->args.e[0]); + Type *type = op.type; + if ((op.mode != Addressing_Type && type == NULL) || type == t_invalid) { + error_node(ce->args.e[0], "Expected a type for `make`"); + return false; + } + + isize min_args = 0; + isize max_args = 1; + if (is_type_slice(type)) { + min_args = 2; + max_args = 3; + } else if (is_type_dynamic_map(type)) { + min_args = 1; + max_args = 2; + } else if (is_type_dynamic_array(type)) { + min_args = 1; + max_args = 3; + } else { + gbString str = type_to_string(type); + error_node(call, "Cannot `make` %s; type must be a slice, map, or dynamic array", str); + gb_string_free(str); + return false; + } + + isize arg_count = ce->args.count; + if (arg_count < min_args || max_args < arg_count) { + error_node(ce->args.e[0], "`make` expects %td or %d argument, found %td", min_args, max_args, arg_count); + return false; + } + + // If any are constant + i64 sizes[4] = {0}; + isize size_count = 0; + for (isize i = 1; i < arg_count; i++) { + i64 val = 0; + bool ok = check_index_value(c, ce->args.e[i], -1, &val); + if (ok && val >= 0) { + GB_ASSERT(size_count < gb_count_of(sizes)); + sizes[size_count++] = val; + } + } + + if (size_count == 2 && sizes[0] > sizes[1]) { + error_node(ce->args.e[1], "`make` count and capacity are swapped"); + // No need quit + } + + operand->mode = Addressing_Value; + operand->type = type; + } break; case BuiltinProc_free: { // free :: proc(^Type) @@ -3216,6 +3335,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id case BuiltinProc_append: { // append :: proc([dynamic]Type, item: ..Type) // append :: proc([]Type, item: ..Type) + Operand prev_operand = *operand; + Type *type = operand->type; bool is_pointer = is_type_pointer(type); type = base_type(type_deref(type)); diff --git a/src/checker.c b/src/checker.c index c594bbe8a..30b1857b5 100644 --- a/src/checker.c +++ b/src/checker.c @@ -23,9 +23,13 @@ typedef struct BuiltinProc { typedef enum BuiltinProcId { BuiltinProc_Invalid, + BuiltinProc_len, + BuiltinProc_cap, + BuiltinProc_new, - BuiltinProc_new_slice, BuiltinProc_free, + // BuiltinProc_new_slice, + BuiltinProc_make, BuiltinProc_reserve, BuiltinProc_clear, @@ -75,9 +79,13 @@ typedef enum BuiltinProcId { gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = { {STR_LIT(""), 0, false, Expr_Stmt}, + {STR_LIT("len"), 1, false, Expr_Expr}, + {STR_LIT("cap"), 1, false, Expr_Expr}, + {STR_LIT("new"), 1, false, Expr_Expr}, - {STR_LIT("new_slice"), 2, true, Expr_Expr}, {STR_LIT("free"), 1, false, Expr_Stmt}, + // {STR_LIT("new_slice"), 2, true, Expr_Expr}, + {STR_LIT("make"), 1, true, Expr_Expr}, {STR_LIT("reserve"), 2, false, Expr_Stmt}, {STR_LIT("clear"), 1, false, Expr_Stmt}, @@ -1470,6 +1470,7 @@ irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val, Type *map_type) GB_ASSERT_MSG(is_type_pointer(ir_type(map_val)), "%s", type_to_string(ir_type(map_val))); gbAllocator a = proc->module->allocator; irValue *h = ir_add_local_generated(proc, t_map_header); + map_type = base_type(map_type); Type *key_type = map_type->Map.key; Type *val_type = map_type->Map.value; @@ -1962,12 +1963,74 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue * return ir_emit(proc, ir_instr_binary_op(proc, op, left, right, type)); } +irValue *ir_emit_comp_against_nil(irProcedure *proc, TokenKind op_kind, irValue *x) { + Type *t = ir_type(x); + if (is_type_any(t)) { + irValue *ti = ir_emit_struct_ev(proc, x, 0); + irValue *data = ir_emit_struct_ev(proc, x, 1); + if (op_kind == Token_CmpEq) { + irValue *a = ir_emit_comp(proc, Token_CmpEq, ti, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_CmpEq, data, v_raw_nil); + return ir_emit_arith(proc, Token_Or, a, b, t_bool); + } else if (op_kind == Token_NotEq) { + irValue *a = ir_emit_comp(proc, Token_NotEq, ti, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_NotEq, data, v_raw_nil); + return ir_emit_arith(proc, Token_And, a, b, t_bool); + } + } else if (is_type_slice(t)) { + irValue *data = ir_emit_struct_ev(proc, x, 0); + irValue *cap = ir_emit_struct_ev(proc, x, 2); + if (op_kind == Token_CmpEq) { + irValue *a = ir_emit_comp(proc, Token_CmpEq, data, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_CmpEq, cap, v_zero); + return ir_emit_arith(proc, Token_Or, a, b, t_bool); + } else if (op_kind == Token_NotEq) { + irValue *a = ir_emit_comp(proc, Token_NotEq, data, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_NotEq, cap, v_zero); + return ir_emit_arith(proc, Token_And, a, b, t_bool); + } + } else if (is_type_dynamic_array(t)) { + irValue *data = ir_emit_struct_ev(proc, x, 0); + irValue *cap = ir_emit_struct_ev(proc, x, 2); + if (op_kind == Token_CmpEq) { + irValue *a = ir_emit_comp(proc, Token_CmpEq, data, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_CmpEq, cap, v_zero); + return ir_emit_arith(proc, Token_Or, a, b, t_bool); + } else if (op_kind == Token_NotEq) { + irValue *a = ir_emit_comp(proc, Token_NotEq, data, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_NotEq, cap, v_zero); + return ir_emit_arith(proc, Token_And, a, b, t_bool); + } + } else if (is_type_map(t)) { + irValue *hashes = ir_emit_struct_ev(proc, x, 0); + irValue *entries = ir_emit_struct_ev(proc, x, 1); + irValue *a = ir_emit_comp_against_nil(proc, op_kind, hashes); + irValue *b = ir_emit_comp_against_nil(proc, op_kind, entries); + if (op_kind == Token_CmpEq) { + return ir_emit_arith(proc, Token_Or, a, b, t_bool); + } else if (op_kind == Token_NotEq) { + return ir_emit_arith(proc, Token_And, a, b, t_bool); + } + } + return NULL; +} + irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irValue *right) { Type *a = base_type(ir_type(left)); Type *b = base_type(ir_type(right)); GB_ASSERT(gb_is_between(op_kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1)); + irValue *nil_check = NULL; + if (left->kind == irValue_Nil) { + nil_check = ir_emit_comp_against_nil(proc, op_kind, right); + } else if (right->kind == irValue_Nil) { + nil_check = ir_emit_comp_against_nil(proc, op_kind, left); + } + if (nil_check != NULL) { + return nil_check; + } + if (are_types_identical(a, b)) { // NOTE(bill): No need for a conversion } else if (left->kind == irValue_Constant || left->kind == irValue_Nil) { @@ -3222,6 +3285,20 @@ void ir_build_defer_stmt(irProcedure *proc, irDefer d) { } +irValue *ir_emit_clamp(irProcedure *proc, Type *t, irValue *x, irValue *min, irValue *max) { + irValue *cond = NULL; + ir_emit_comment(proc, str_lit("clamp")); + x = ir_emit_conv(proc, x, t); + min = ir_emit_conv(proc, min, t); + max = ir_emit_conv(proc, max, t); + + cond = ir_emit_comp(proc, Token_Gt, min, x); + x = ir_emit_select(proc, cond, min, x); + cond = ir_emit_comp(proc, Token_Lt, max, x); + x = ir_emit_select(proc, cond, max, x); + return x; +} + irValue *ir_find_global_variable(irProcedure *proc, String name) { irValue **value = map_ir_value_get(&proc->module->members, hash_string(name)); @@ -3505,6 +3582,59 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { return ir_type_info(proc, t); } break; + case BuiltinProc_len: { + irValue *v = ir_build_expr(proc, ce->args.e[0]); + Type *t = base_type(ir_type(v)); + if (is_type_pointer(t)) { + // IMPORTANT TODO(bill): Should there be a nil pointer check? + v = ir_emit_load(proc, v); + t = type_deref(t); + } + if (is_type_string(t)) { + return ir_string_len(proc, v); + } else if (is_type_array(t)) { + GB_PANIC("Array lengths are constant"); + } else if (is_type_vector(t)) { + GB_PANIC("Vector lengths are constant"); + } else if (is_type_slice(t)) { + return ir_slice_count(proc, v); + } else if (is_type_dynamic_array(t)) { + return ir_dynamic_array_count(proc, v); + } else if (is_type_map(t)) { + irValue *entries = ir_emit_struct_ev(proc, v, 1); + return ir_dynamic_array_count(proc, entries); + } + + GB_PANIC("Unreachable"); + } break; + + case BuiltinProc_cap: { + irValue *v = ir_build_expr(proc, ce->args.e[0]); + Type *t = base_type(ir_type(v)); + if (is_type_pointer(t)) { + // IMPORTANT TODO(bill): Should there be a nil pointer check? + v = ir_emit_load(proc, v); + t = type_deref(t); + } + if (is_type_string(t)) { + GB_PANIC("Unreachable"); + } else if (is_type_array(t)) { + GB_PANIC("Array lengths are constant"); + } else if (is_type_vector(t)) { + GB_PANIC("Unreachable"); + } else if (is_type_slice(t)) { + return ir_slice_capacity(proc, v); + } else if (is_type_dynamic_array(t)) { + return ir_dynamic_array_capacity(proc, v); + } else if (is_type_map(t)) { + irValue *entries = ir_emit_struct_ev(proc, v, 1); + return ir_dynamic_array_capacity(proc, entries); + } + + GB_PANIC("Unreachable"); + + } break; + case BuiltinProc_new: { ir_emit_comment(proc, str_lit("new")); // new :: proc(Type) -> ^Type @@ -3524,6 +3654,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { return v; } break; + #if 0 case BuiltinProc_new_slice: { ir_emit_comment(proc, str_lit("new_slice")); // new_slice :: proc(Type, len: int) -> []Type @@ -3562,6 +3693,83 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { ir_fill_slice(proc, slice, ptr, count, capacity); return ir_emit_load(proc, slice); } break; + #endif + case BuiltinProc_make: { + ir_emit_comment(proc, str_lit("make")); + gbAllocator a = proc->module->allocator; + Type *type = type_of_expr(proc->module->info, ce->args.e[0]); + + if (is_type_slice(type)) { + Type *elem_type = core_type(type)->Slice.elem; + Type *elem_ptr_type = make_type_pointer(a, elem_type); + + irValue *elem_size = ir_const_int(a, type_size_of(a, elem_type)); + irValue *elem_align = ir_const_int(a, type_align_of(a, elem_type)); + + irValue *count = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t_int); + irValue *capacity = count; + + if (ce->args.count == 3) { + capacity = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[2]), t_int); + } + + ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, count, capacity, false); + + irValue *slice_size = ir_emit_arith(proc, Token_Mul, elem_size, capacity, t_int); + + irValue **args = gb_alloc_array(a, irValue *, 2); + args[0] = slice_size; + args[1] = elem_align; + irValue *call = ir_emit_global_call(proc, "alloc_align", args, 2); + + irValue *ptr = ir_emit_conv(proc, call, elem_ptr_type); + irValue *slice = ir_add_local_generated(proc, type); + + ir_fill_slice(proc, slice, ptr, count, capacity); + return ir_emit_load(proc, slice); + } else if (is_type_dynamic_map(type)) { + irValue *int_16 = ir_const_int(a, 16); + irValue *cap = v_zero; + if (ce->args.count == 2) { + cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t_int); + } + + irValue *cond = ir_emit_comp(proc, Token_Gt, cap, v_zero); + cap = ir_emit_select(proc, cond, cap, int_16); + + irValue *map = ir_add_local_generated(proc, type); + irValue *header = ir_gen_map_header(proc, map, base_type(type)); + irValue **args = gb_alloc_array(a, irValue *, 2); + args[0] = header; + args[1] = cap; + ir_emit_global_call(proc, "__dynamic_map_reserve", args, 2); + + return ir_emit_load(proc, map); + } else if (is_type_dynamic_array(type)) { + Type *elem_type = base_type(type)->DynamicArray.elem; + irValue *len = v_zero; + irValue *cap = ir_const_int(a, 8); + if (ce->args.count > 1) { + len = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t_int); + } + if (ce->args.count > 2) { + cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[2]), t_int); + } + + ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[0]), v_zero, len, cap, false); + + irValue *array = ir_add_local_generated(proc, type); + irValue **args = gb_alloc_array(a, irValue *, 5); + args[0] = array; + args[1] = ir_const_int(a, type_size_of(a, elem_type)); + args[2] = ir_const_int(a, type_align_of(a, elem_type));; + args[3] = len; + args[4] = cap; + ir_emit_global_call(proc, "__dynamic_array_make", args, 5); + + return ir_emit_load(proc, array); + } + } break; case BuiltinProc_free: { ir_emit_comment(proc, str_lit("free")); @@ -4112,15 +4320,10 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { case BuiltinProc_clamp: { ir_emit_comment(proc, str_lit("clamp")); Type *t = type_of_expr(proc->module->info, expr); - irValue *x = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[0]), t); - irValue *min = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t); - irValue *max = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[2]), t); - irValue *cond; - cond = ir_emit_comp(proc, Token_Gt, min, x); - x = ir_emit_select(proc, cond, min, x); - cond = ir_emit_comp(proc, Token_Lt, max, x); - x = ir_emit_select(proc, cond, max, x); - return x; + return ir_emit_clamp(proc, t, + ir_build_expr(proc, ce->args.e[0]), + ir_build_expr(proc, ce->args.e[1]), + ir_build_expr(proc, ce->args.e[2])); } break; } } diff --git a/src/tokenizer.c b/src/tokenizer.c index 398f39f98..2ef1a7add 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -619,20 +619,22 @@ bool scan_escape(Tokenizer *t, Rune quote) { advance_to_next_rune(t); len = 8; base = 16; max = GB_RUNE_MAX; } else { - if (t->curr_rune < 0) + if (t->curr_rune < 0) { tokenizer_err(t, "Escape sequence was not terminated"); - else + } else { tokenizer_err(t, "Unknown escape sequence"); + } return false; } while (len --> 0) { u32 d = cast(u32)digit_value(t->curr_rune); if (d >= base) { - if (t->curr_rune < 0) + if (t->curr_rune < 0) { tokenizer_err(t, "Escape sequence was not terminated"); - else + } else { tokenizer_err(t, "Illegal character %d in escape sequence", t->curr_rune); + } return false; } diff --git a/src/types.c b/src/types.c index 9735e6e38..c99aeeb18 100644 --- a/src/types.c +++ b/src/types.c @@ -834,9 +834,10 @@ bool type_has_nil(Type *t) { return false; } break; case Type_Slice: - case Type_DynamicArray: case Type_Proc: case Type_Pointer: + case Type_DynamicArray: + case Type_Map: return true; } return false; @@ -1232,6 +1233,9 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n if (type->kind == Type_Basic) { switch (type->Basic.kind) { case Basic_any: { + #if 1 + // IMPORTANT TODO(bill): Should these members be available to should I only allow them with + // `Raw_Any` type? String type_info_str = str_lit("type_info"); String data_str = str_lit("data"); if (entity__any_type_info == NULL) { @@ -1250,8 +1254,10 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = entity__any_data; return sel; } + #endif } break; case Basic_string: { + #if 0 String data_str = str_lit("data"); String count_str = str_lit("count"); if (entity__string_data == NULL) { @@ -1271,11 +1277,13 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = entity__string_count; return sel; } + #endif } break; } return sel; } else if (type->kind == Type_Array) { + #if 0 String count_str = str_lit("count"); // NOTE(bill): Underlying memory address cannot be changed if (str_eq(field_name, count_str)) { @@ -1283,7 +1291,9 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, exact_value_integer(type->Array.count)); return sel; } + #endif } else if (type->kind == Type_Vector) { + #if 0 String count_str = str_lit("count"); // NOTE(bill): Vectors are not addressable if (str_eq(field_name, count_str)) { @@ -1291,7 +1301,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, exact_value_integer(type->Vector.count)); return sel; } - + #endif if (type->Vector.count <= 4 && !is_type_boolean(type->Vector.elem)) { // HACK(bill): Memory leak switch (type->Vector.count) { @@ -1315,6 +1325,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n } } else if (type->kind == Type_Slice) { + #if 0 String data_str = str_lit("data"); String count_str = str_lit("count"); String capacity_str = str_lit("capacity"); @@ -1341,8 +1352,9 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = entity__slice_capacity; return sel; } - + #endif } else if (type->kind == Type_DynamicArray) { + #if 0 String data_str = str_lit("data"); String count_str = str_lit("count"); String capacity_str = str_lit("capacity"); @@ -1375,7 +1387,9 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = entity__dynamic_array_allocator; return sel; } + #endif } else if (type->kind == Type_Map) { + #if 0 String count_str = str_lit("count"); String capacity_str = str_lit("capacity"); String allocator_str = str_lit("allocator"); @@ -1405,6 +1419,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = entity__dynamic_map_allocator; return sel; } + #endif } if (is_type) { |