Browse Source

New slice memory layout (ptr+len); `byte`

gingerBill 7 years ago
parent
commit
74fa7ca25d
21 changed files with 425 additions and 506 deletions
  1. 32 47
      core/_preload.odin
  2. 9 9
      core/decimal.odin
  3. 70 94
      core/fmt.odin
  4. 9 9
      core/hash.odin
  5. 25 22
      core/mem.odin
  6. 6 6
      core/os.odin
  7. 41 43
      core/os_essence.odin
  8. 16 15
      core/os_linux.odin
  9. 17 17
      core/os_windows.odin
  10. 17 18
      core/os_x.odin
  11. 0 1
      core/raw.odin
  12. 52 35
      core/strconv.odin
  13. 2 2
      core/sys/wgl.odin
  14. 20 20
      core/sys/windows.odin
  15. 16 9
      examples/demo.odin
  16. 5 30
      src/check_expr.cpp
  17. 5 10
      src/checker.cpp
  18. 65 83
      src/ir.cpp
  19. 1 1
      src/ir_print.cpp
  20. 14 33
      src/parser.cpp
  21. 3 2
      src/types.cpp

+ 32 - 47
core/_preload.odin

@@ -74,8 +74,8 @@ Type_Info_Tuple :: struct #ordered { // Only really used for procedures
 Type_Info_Struct :: struct #ordered {
 	types:        []^Type_Info,
 	names:        []string,
-	offsets:      []int,  // offsets may not be used in tuples
-	usings:       []bool, // usings may not be used in tuples
+	offsets:      []uintptr, // offsets may not be used in tuples
+	usings:       []bool,    // usings may not be used in tuples
 	is_packed:    bool,
 	is_ordered:   bool,
 	is_raw_union: bool,
@@ -83,7 +83,7 @@ Type_Info_Struct :: struct #ordered {
 };
 Type_Info_Union :: struct #ordered {
 	variants:   []^Type_Info,
-	tag_offset: int,
+	tag_offset: uintptr,
 	tag_type:   ^Type_Info,
 };
 Type_Info_Enum :: struct #ordered {
@@ -136,7 +136,7 @@ Type_Info :: struct #ordered {
 __type_table: []Type_Info;
 
 __argc__: i32;
-__argv__: ^^u8;
+__argv__: ^^byte;
 
 // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
 
@@ -149,7 +149,7 @@ Source_Code_Location :: struct #ordered {
 
 
 
-Allocator_Mode :: enum u8 {
+Allocator_Mode :: enum byte {
 	Alloc,
 	Free,
 	FreeAll,
@@ -327,23 +327,6 @@ copy :: proc "contextless" (dst, src: $T/[]$E) -> int {
 }
 
 
-append :: proc "contextless" (array: ^$T/[]$E, args: ...E) -> int {
-	if array == nil do return 0;
-
-	arg_len := len(args);
-	if arg_len <= 0 do return len(array);
-
-	arg_len = min(cap(array)-len(array), arg_len);
-	if arg_len > 0 {
-		s := cast(^raw.Slice)array;
-		data := cast(^E)s.data;
-		assert(data != nil);
-		__mem_copy(data + s.len, &args[0], size_of(E)*arg_len);
-		s.len += arg_len;
-	}
-	return len(array);
-}
-
 append :: proc(array: ^$T/[dynamic]$E, args: ...E, loc := #caller_location) -> int {
 	if array == nil do return 0;
 
@@ -366,12 +349,6 @@ append :: proc(array: ^$T/[dynamic]$E, args: ...E, loc := #caller_location) -> i
 	return len(array);
 }
 
-append_string :: proc(array: ^$T/[]u8, args: ...string) -> int {
-	for arg in args {
-		append(array, ...cast(T)arg);
-	}
-	return len(array);
-}
 append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ...string, loc := #caller_location) -> int {
 	for arg in args {
 		append(array = array, args = cast([]E)arg, loc = loc);
@@ -691,16 +668,24 @@ __bounds_check_error :: proc "contextless" (file: string, line, column: int, ind
 	__debug_trap();
 }
 
-__slice_expr_error :: proc "contextless" (file: string, line, column: int, low, high, max: int) {
+__slice_expr_error :: proc "contextless" (file: string, line, column: int, low, high: int) {
+	if 0 <= low && low <= high do return;
+	fmt.fprintf(os.stderr, "%s(%d:%d) Invalid slice indices: %d..%d\n",
+	            file, line, column, low, high);
+	__debug_trap();
+}
+
+__dynamic_array_expr_error :: proc "contextless" (file: string, line, column: int, low, high, max: int) {
 	if 0 <= low && low <= high && high <= max do return;
-	fmt.fprintf(os.stderr, "%s(%d:%d) Invalid slice indices: [%d..%d..%d]\n",
+	fmt.fprintf(os.stderr, "%s(%d:%d) Invalid slice indices: %d..%d..%d\n",
 	            file, line, column, low, high, max);
 	__debug_trap();
 }
 
+
 __substring_expr_error :: proc "contextless" (file: string, line, column: int, low, high: int) {
 	if 0 <= low && low <= high do return;
-	fmt.fprintf(os.stderr, "%s(%d:%d) Invalid substring indices: [%d..%d]\n",
+	fmt.fprintf(os.stderr, "%s(%d:%d) Invalid substring indices: %d..%d\n",
 	            file, line, column, low, high);
 	__debug_trap();
 }
@@ -718,8 +703,8 @@ __string_decode_rune :: inline proc "contextless" (s: string) -> (rune, int) {
 __bounds_check_error_loc :: inline proc "contextless" (using loc := #caller_location, index, count: int) {
 	__bounds_check_error(file_path, int(line), int(column), index, count);
 }
-__slice_expr_error_loc :: inline proc "contextless" (using loc := #caller_location, low, high, max: int) {
-	__slice_expr_error(file_path, int(line), int(column), low, high, max);
+__slice_expr_error_loc :: inline proc "contextless" (using loc := #caller_location, low, high: int) {
+	__slice_expr_error(file_path, int(line), int(column), low, high);
 }
 __substring_expr_error_loc :: inline proc "contextless" (using loc := #caller_location, low, high: int) {
 	__substring_expr_error(file_path, int(line), int(column), low, high);
@@ -730,13 +715,13 @@ __mem_set :: proc "contextless" (data: rawptr, value: i32, len: int) -> rawptr {
 	foreign __llvm_core {
 		when size_of(rawptr) == 8 {
 			@(link_name="llvm.memset.p0i8.i64")
-			llvm_memset :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) ---;
+			llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---;
 		} else {
 			@(link_name="llvm.memset.p0i8.i32")
-			llvm_memset :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) ---;
+			llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---;
 		}
 	}
-	llvm_memset(data, u8(value), len, 1, false);
+	llvm_memset(data, byte(value), len, 1, false);
 	return data;
 }
 __mem_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
@@ -773,7 +758,7 @@ __mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) ->
 	return dst;
 }
 
-__mem_compare :: proc "contextless" (a, b: ^u8, n: int) -> int {
+__mem_compare :: proc "contextless" (a, b: ^byte, n: int) -> int {
 	for i in 0..n do switch {
 	case (a+i)^ < (b+i)^: return -1;
 	case (a+i)^ > (b+i)^: return +1;
@@ -867,7 +852,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 := cast(^u8)array.data;
+	data := cast(^byte)array.data;
 	assert(data != nil);
 	__mem_copy(data + (elem_size*array.len), items, elem_size * item_count);
 	array.len += item_count;
@@ -885,7 +870,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 := cast(^u8)array.data;
+	data := cast(^byte)array.data;
 	assert(data != nil);
 	__mem_zero(data + (elem_size*array.len), elem_size);
 	array.len += 1;
@@ -894,8 +879,8 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in
 
 // Map stuff
 
-__default_hash :: proc(data: []u8) -> u128 {
-	fnv128a :: proc(data: []u8) -> u128 {
+__default_hash :: proc(data: []byte) -> u128 {
+	fnv128a :: proc(data: []byte) -> u128 {
 		h: u128 = 0x6c62272e07bb014262b821756295c58d;
 		for b in data {
 			h = (h ~ u128(b)) * 0x1000000000000000000013b;
@@ -904,7 +889,7 @@ __default_hash :: proc(data: []u8) -> u128 {
 	}
 	return fnv128a(data);
 }
-__default_hash_string :: proc(s: string) -> u128 do return __default_hash(cast([]u8)s);
+__default_hash_string :: proc(s: string) -> u128 do return __default_hash(cast([]byte)s);
 
 __dynamic_map_reserve :: proc(using header: __Map_Header, cap: int, loc := #caller_location)  {
 	__dynamic_array_reserve(&m.hashes, size_of(int), align_of(int), cap, loc);
@@ -927,7 +912,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int, loc :=
 		if len(nm.hashes) == 0 do __dynamic_map_grow(new_header, loc);
 
 		entry_header := __dynamic_map_get_entry(header, i);
-		data := cast(^u8)entry_header;
+		data := cast(^byte)entry_header;
 
 		fr := __dynamic_map_find(new_header, entry_header.key);
 		j := __dynamic_map_add_entry(new_header, entry_header.key, loc);
@@ -940,7 +925,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int, loc :=
 
 		e := __dynamic_map_get_entry(new_header, j);
 		e.next = fr.entry_index;
-		ndata := cast(^u8)e;
+		ndata := cast(^byte)e;
 		__mem_copy(ndata+value_offset, data+value_offset, value_size);
 
 		if __dynamic_map_full(new_header) do __dynamic_map_grow(new_header, loc);
@@ -953,7 +938,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int, loc :=
 __dynamic_map_get :: proc(h: __Map_Header, key: __Map_Key) -> rawptr {
 	index := __dynamic_map_find(h, key).entry_index;
 	if index >= 0 {
-		data := cast(^u8)__dynamic_map_get_entry(h, index);
+		data := cast(^byte)__dynamic_map_get_entry(h, index);
 		return data + h.value_offset;
 	}
 	return nil;
@@ -983,7 +968,7 @@ __dynamic_map_set :: proc(using h: __Map_Header, key: __Map_Key, value: rawptr,
 	{
 		e := __dynamic_map_get_entry(h, index);
 		e.key = key;
-		val := cast(^u8)e + value_offset;
+		val := cast(^byte)e + value_offset;
 		__mem_copy(val, value, value_size);
 	}
 
@@ -1045,7 +1030,7 @@ __dynamic_map_delete :: proc(using h: __Map_Header, key: __Map_Key) {
 }
 
 __dynamic_map_get_entry :: proc(using h: __Map_Header, index: int) -> ^__Map_Entry_Header {
-	return cast(^__Map_Entry_Header)(cast(^u8)m.entries.data + index*entry_size);
+	return cast(^__Map_Entry_Header)(cast(^byte)m.entries.data + index*entry_size);
 }
 
 __dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) {

+ 9 - 9
core/decimal.odin

@@ -2,14 +2,14 @@
 // NOTE: This is only for floating point printing and nothing else
 
 Decimal :: struct {
-	digits:        [384]u8, // big-endian digits
+	digits:        [384]byte, // big-endian digits
 	count:         int,
 	decimal_point: int,
 	neg, trunc:    bool,
 }
 
-decimal_to_string :: proc(buf: []u8, a: ^Decimal) -> string {
-	digit_zero :: proc(buf: []u8) -> int {
+decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string {
+	digit_zero :: proc(buf: []byte) -> int {
 		for _, i in buf do buf[i] = '0';
 		return len(buf);
 	}
@@ -56,12 +56,12 @@ trim :: proc(a: ^Decimal) {
 
 
 assign :: proc(a: ^Decimal, i: u64) {
-	buf: [64]u8;
+	buf: [64]byte;
 	n := 0;
 	for i > 0 {
 		j := i/10;
 		i -= 10*j;
-		buf[n] = u8('0'+i);
+		buf[n] = byte('0'+i);
 		n += 1;
 		i = j;
 	}
@@ -106,7 +106,7 @@ shift_right :: proc(a: ^Decimal, k: uint) {
 		c := uint(a.digits[r]);
 		dig := n>>k;
 		n &= mask;
-		a.digits[w] = u8('0' + dig);
+		a.digits[w] = byte('0' + dig);
 		w += 1;
 		n = n*10 + c - '0';
 	}
@@ -115,7 +115,7 @@ shift_right :: proc(a: ^Decimal, k: uint) {
 		dig := n>>k;
 		n &= mask;
 		if w < len(a.digits) {
-			a.digits[w] = u8('0' + dig);
+			a.digits[w] = byte('0' + dig);
 			w += 1;
 		} else if dig > 0 {
 			a.trunc = true;
@@ -141,7 +141,7 @@ shift_left :: proc(a: ^Decimal, k: uint) {
 		rem := n - 10*quo;
 		w -= 1;
 		if w < len(a.digits) {
-			a.digits[w] = u8('0' + rem);
+			a.digits[w] = byte('0' + rem);
 		} else if rem != 0 {
 			a.trunc = true;
 		}
@@ -153,7 +153,7 @@ shift_left :: proc(a: ^Decimal, k: uint) {
 		rem := n - 10*quo;
 		w -= 1;
 		if 0 <= w && w < len(a.digits) {
-			a.digits[w] = u8('0' + rem);
+			a.digits[w] = byte('0' + rem);
 		} else if rem != 0 {
 			a.trunc = true;
 		}

+ 70 - 94
core/fmt.odin

@@ -8,10 +8,7 @@ import "core:raw.odin"
 
 _BUFFER_SIZE :: 1<<12;
 
-String_Buffer :: union {
-	[]u8,
-	[dynamic]u8,
-}
+String_Buffer :: [dynamic]byte;
 
 Fmt_Info :: struct {
 	minus:     bool,
@@ -33,45 +30,34 @@ Fmt_Info :: struct {
 	arg: any, // Temporary
 }
 
+string_buffer_from_slice :: proc(backing: []byte) -> String_Buffer {
+	s := transmute(raw.Slice)backing;
+	d: raw.Dynamic_Array;
+	d.data = s.data;
+	d.len = 0;
+	d.cap = s.len;
+	d.allocator = nil_allocator();
+	return transmute(String_Buffer)d;
+}
 
 
-string_buffer_data :: proc(buf: ^String_Buffer) -> []u8 {
-	switch b in buf {
-	case []u8:        return b[..];
-	case [dynamic]u8: return b[..];
-	}
-	return nil;
-}
-string_buffer_data :: proc(buf: String_Buffer) -> []u8 {
-	switch b in buf {
-	case []u8:        return b[..];
-	case [dynamic]u8: return b[..];
-	}
-	return nil;
-}
 to_string :: proc(buf: String_Buffer) -> string {
-	return string(string_buffer_data(buf));
+	return string(buf[..]);
 }
 
 
 write_string :: proc(buf: ^String_Buffer, s: string) {
-	write_bytes(buf, cast([]u8)s);
+	append_string(buf, s);
 }
-write_bytes :: proc(buf: ^String_Buffer, data: []u8) {
-	switch b in buf {
-	case []u8:        append(b, ...data);
-	case [dynamic]u8: append(b, ...data);
-	}
+write_bytes :: proc(buf: ^String_Buffer, data: []byte) {
+	append(buf, ...data);
 }
-write_byte :: proc(buf: ^String_Buffer, data: u8) {
-	switch b in buf {
-	case []u8:        append(b, data);
-	case [dynamic]u8: append(b, data);
-	}
+write_byte :: proc(buf: ^String_Buffer, data: byte) {
+	append(buf, data);
 }
 write_rune :: proc(buf: ^String_Buffer, r: rune) {
 	if r < utf8.RUNE_SELF {
-		write_byte(buf, u8(r));
+		write_byte(buf, byte(r));
 		return;
 	}
 
@@ -80,41 +66,36 @@ write_rune :: proc(buf: ^String_Buffer, r: rune) {
 }
 
 write_int :: proc(buf: ^String_Buffer, i: i128, base: int) {
-	b: [129]u8;
-	s := strconv.append_bits(b[..0], u128(i), base, true, 128, strconv.digits, 0);
+	b: [129]byte;
+	s := strconv.append_bits(b[..], u128(i), base, true, 128, strconv.digits, 0);
 	write_string(buf, s);
 }
 write_int :: proc(buf: ^String_Buffer, i: i64, base: int) {
-	b: [129]u8;
-	s := strconv.append_bits(b[..0], u128(i), base, true, 64, strconv.digits, 0);
+	b: [129]byte;
+	s := strconv.append_bits(b[..], u128(i), base, true, 64, strconv.digits, 0);
 	write_string(buf, s);
 }
 
-
-
 fprint :: proc(fd: os.Handle, args: ...any) -> int {
-	data: [_BUFFER_SIZE]u8;
-	buf := String_Buffer(data[..0]);
-	sbprint(&buf, ...args);
-	res := string_buffer_data(buf);
-	os.write(fd, res);
+	data: [_BUFFER_SIZE]byte;
+	buf := string_buffer_from_slice(data[..]);
+	res := sbprint(&buf, ...args);
+	os.write_string(fd, res);
 	return len(res);
 }
 
 fprintln :: proc(fd: os.Handle, args: ...any) -> int {
-	data: [_BUFFER_SIZE]u8;
-	buf := String_Buffer(data[..0]);
-	sbprintln(&buf, ...args);
-	res := string_buffer_data(buf);
-	os.write(fd, res);
+	data: [_BUFFER_SIZE]byte;
+	buf := string_buffer_from_slice(data[..]);
+	res := sbprintln(&buf, ...args);
+	os.write_string(fd, res);
 	return len(res);
 }
 fprintf :: proc(fd: os.Handle, fmt: string, args: ...any) -> int {
-	data: [_BUFFER_SIZE]u8;
-	buf := String_Buffer(data[..0]);
-	sbprintf(&buf, fmt, ...args);
-	res := string_buffer_data(buf);
-	os.write(fd, res);
+	data: [_BUFFER_SIZE]byte;
+	buf := string_buffer_from_slice(data[..]);
+	res := sbprintf(&buf, fmt, ...args);
+	os.write_string(fd, res);
 	return len(res);
 }
 
@@ -131,33 +112,33 @@ printf_err  :: proc(fmt: string, args: ...any) -> int { return fprintf(os.stderr
 // aprint* procedures return a string that was allocated with the current context
 // They must be freed accordingly
 aprint :: proc(args: ...any) -> string {
-	buf := String_Buffer(make([dynamic]u8));
+	buf := String_Buffer(make([dynamic]byte));
 	sbprint(&buf, ...args);
 	return to_string(buf);
 }
 aprintln :: proc(args: ...any) -> string {
-	buf := String_Buffer(make([dynamic]u8));
+	buf := String_Buffer(make([dynamic]byte));
 	sbprintln(&buf, ...args);
 	return to_string(buf);
 }
 aprintf :: proc(fmt: string, args: ...any) -> string {
-	buf := String_Buffer(make([dynamic]u8));
+	buf := String_Buffer(make([dynamic]byte));
 	sbprintf(&buf, fmt, ...args);
 	return to_string(buf);
 }
 
 
 // bprint* procedures return a string using a buffer from an array
-bprint :: proc(buf: []u8, args: ...any) -> string {
-	sb := String_Buffer(buf[..0..len(buf)]);
+bprint :: proc(buf: []byte, args: ...any) -> string {
+	sb := string_buffer_from_slice(buf[0..len(buf)]);
 	return sbprint(&sb, ...args);
 }
-bprintln :: proc(buf: []u8, args: ...any) -> string {
-	sb := String_Buffer(buf[..0..len(buf)]);
+bprintln :: proc(buf: []byte, args: ...any) -> string {
+	sb := string_buffer_from_slice(buf[0..len(buf)]);
 	return sbprintln(&sb, ...args);
 }
-bprintf :: proc(buf: []u8, fmt: string, args: ...any) -> string {
-	sb := String_Buffer(buf[..0..len(buf)]);
+bprintf :: proc(buf: []byte, fmt: string, args: ...any) -> string {
+	sb := string_buffer_from_slice(buf[0..len(buf)]);
 	return sbprintf(&sb, fmt, ...args);
 }
 
@@ -167,10 +148,10 @@ bprintf :: proc(buf: []u8, fmt: string, args: ...any) -> string {
 
 
 fprint_type :: proc(fd: os.Handle, info: ^Type_Info) {
-	data: [_BUFFER_SIZE]u8;
-	buf := String_Buffer(data[..0]);
+	data: [_BUFFER_SIZE]byte;
+	buf := string_buffer_from_slice(data[..]);
 	write_type(&buf, info);
-	os.write(fd, string_buffer_data(buf));
+	os.write(fd, buf[..]);
 }
 
 write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
@@ -438,7 +419,7 @@ fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) {
 fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) {
 	if width <= 0 do return;
 
-	pad_byte: u8 = '0';
+	pad_byte: byte = '0';
 	if fi.space do pad_byte = ' ';
 
 	for _ in 0..width {
@@ -483,17 +464,17 @@ _fmt_int :: proc(fi: ^Fmt_Info, u: u128, base: int, is_signed: bool, bit_size: i
 		panic("_fmt_int: unknown base, whoops");
 	}
 
-	buf: [256]u8;
+	buf: [256]byte;
 	start := 0;
 
 	flags: strconv.Int_Flag;
 	if fi.hash && !fi.zero do flags |= strconv.Int_Flag.Prefix;
 	if fi.plus             do flags |= strconv.Int_Flag.Plus;
 	if fi.space            do flags |= strconv.Int_Flag.Space;
-	s := strconv.append_bits(buf[start..start], u128(u), base, is_signed, bit_size, digits, flags);
+	s := strconv.append_bits(buf[start..], u128(u), base, is_signed, bit_size, digits, flags);
 
 	if fi.hash && fi.zero {
-		c: u8;
+		c: byte;
 		switch base {
 		case 2:  c = 'b';
 		case 8:  c = 'o';
@@ -576,9 +557,9 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) {
 	case 'f', 'F', 'v':
 		prec: int = 3;
 		if fi.prec_set do prec = fi.prec;
-		buf: [386]u8;
+		buf: [386]byte;
 
-		str := strconv.append_float(buf[1..1], v, 'f', prec, bit_size);
+		str := strconv.append_float(buf[1..], v, 'f', prec, bit_size);
 		str = string(buf[...len(str)]);
 		if str[1] == '+' || str[1] == '-' {
 			str = str[1..];
@@ -752,7 +733,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 				write_string(fi.buf, info.name);
 				write_string(fi.buf, "{}");
 				return;
-			}
+			};
 			write_string(fi.buf, info.name);
 			write_byte(fi.buf, '{');
 
@@ -774,7 +755,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 				if t := b.types[i]; types.is_any(t) {
 					write_string(fi.buf, "any{}");
 				} else {
-					data := cast(^u8)v.data + b.offsets[i];
+					data := uintptr(v.data) + b.offsets[i];
 					fmt_arg(fi, any{rawptr(data), t}, 'v');
 				}
 
@@ -797,9 +778,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 
 	case Type_Info_Pointer:
 		if v.type_info == type_info_of(^Type_Info) {
-			write_type(fi.buf, (cast(^^Type_Info)v.data)^);
+			write_type(fi.buf, (^^Type_Info)(v.data)^);
 		} else {
-			fmt_pointer(fi, (cast(^rawptr)v.data)^, verb);
+			fmt_pointer(fi, (^rawptr)(v.data)^, verb);
 		}
 
 	case Type_Info_Array:
@@ -808,7 +789,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 		for i in 0..info.count {
 			if i > 0 do write_string(fi.buf, ", ");
 
-			data := cast(^u8)v.data + i*info.elem_size;
+			data := uintptr(v.data) + uintptr(i*info.elem_size);
 			fmt_arg(fi, any{rawptr(data), info.elem}, verb);
 		}
 
@@ -819,18 +800,18 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 		for i in 0..array.len {
 			if i > 0 do write_string(fi.buf, ", ");
 
-			data := cast(^u8)array.data + i*info.elem_size;
+			data := uintptr(array.data) + uintptr(i*info.elem_size);
 			fmt_arg(fi, any{rawptr(data), info.elem}, verb);
 		}
 
 	case Type_Info_Slice:
 		write_byte(fi.buf, '[');
 		defer write_byte(fi.buf, ']');
-		slice := cast(^[]u8)v.data;
-		for _, i in slice {
+		slice := cast(^raw.Slice)v.data;
+		for i in 0..slice.len {
 			if i > 0 do write_string(fi.buf, ", ");
 
-			data := &slice[0] + i*info.elem_size;
+			data := uintptr(slice.data) + uintptr(i*info.elem_size);
 			fmt_arg(fi, any{rawptr(data), info.elem}, verb);
 		}
 
@@ -841,7 +822,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 		for i in 0..info.count {
 			if i > 0 do write_string(fi.buf, ", ");
 
-			data := cast(^u8)v.data + i*info.elem_size;
+			data := uintptr(v.data) + uintptr(i*info.elem_size);
 			fmt_value(fi, any{rawptr(data), info.elem}, verb);
 		}
 
@@ -863,7 +844,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 		for i in 0..entries.len {
 			if i > 0 do write_string(fi.buf, ", ");
 
-			data := cast(^u8)entries.data + i*entry_size;
+			data := uintptr(entries.data) + uintptr(i*entry_size);
 			header := cast(^__Map_Entry_Header)data;
 
 			if types.is_string(info.key) {
@@ -912,16 +893,15 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			if t := info.types[i]; types.is_any(t) {
 				write_string(fi.buf, "any{}");
 			} else {
-				data := cast(^u8)v.data + info.offsets[i];
+				data := uintptr(v.data) + info.offsets[i];
 				fmt_arg(fi, any{rawptr(data), t}, 'v');
 			}
 			if hash do write_string(fi.buf, ",\n");
 		}
 
 	case Type_Info_Union:
-		data := cast(^u8)v.data;
-		tag_ptr := rawptr(data + info.tag_offset);
-		tag_any := any{tag_ptr, info.tag_type};
+		tag_ptr := uintptr(v.data) + info.tag_offset;
+		tag_any := any{rawptr(tag_ptr), info.tag_type};
 
 		tag: i64 = -1;
 		switch i in tag_any {
@@ -938,11 +918,11 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 		case: panic("Invalid union tag type");
 		}
 
-		if data == nil || tag <= 0 {
+		if v.data == nil || tag == 0 {
 			write_string(fi.buf, "nil");
 		} else {
 			ti := info.variants[tag-1];
-			fmt_arg(fi, any{data, ti}, verb);
+			fmt_arg(fi, any{v.data, ti}, verb);
 		}
 
 	case Type_Info_Enum:
@@ -951,7 +931,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 	case Type_Info_Procedure:
 		write_type(fi.buf, v.type_info);
 		write_string(fi.buf, " @ ");
-		fmt_pointer(fi, (cast(^rawptr)v.data)^, 'p');
+		fmt_pointer(fi, (^rawptr)(v.data)^, 'p');
 	}
 }
 
@@ -972,14 +952,10 @@ fmt_complex :: proc(fi: ^Fmt_Info, c: complex128, bits: int, verb: rune) {
 	}
 }
 
-_u128_to_lo_hi :: proc(a: u128) -> (lo, hi: u64) { return u64(a), u64(a>>64); }
-_i128_to_lo_hi :: proc(a: u128) -> (lo: u64 hi: i64) { return u64(a), i64(a>>64); }
+_u128_to_lo_hi :: proc(a: u128) -> (lo, hi: u64)     do return u64(a), u64(a>>64);
+_i128_to_lo_hi :: proc(a: u128) -> (lo: u64 hi: i64) do return u64(a), i64(a>>64);
 
 
-do_foo :: proc(fi: ^Fmt_Info, f: f64) {
-	fmt_string(fi, "Hellope$%!", 'v');
-}
-
 fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
 	if arg == nil {
 		write_string(fi.buf, "<nil>");

+ 9 - 9
core/hash.odin

@@ -1,6 +1,6 @@
 import "core:mem.odin"
 
-adler32 :: proc(data: []u8) -> u32 {
+adler32 :: proc(data: []byte) -> u32 {
 	ADLER_CONST :: 65521;
 	a, b: u32 = 1, 0;
 	for x in data {
@@ -10,14 +10,14 @@ adler32 :: proc(data: []u8) -> u32 {
 	return (b << 16) | a;
 }
 
-crc32 :: proc(data: []u8) -> u32 {
+crc32 :: proc(data: []byte) -> u32 {
 	result := ~u32(0);
 	for b in data {
 		result = result>>8 ~ _crc32_table[(result ~ u32(b)) & 0xff];
 	}
 	return ~result;
 }
-crc64 :: proc(data: []u8) -> u64 {
+crc64 :: proc(data: []byte) -> u64 {
 	result := ~u64(0);
 	for b in data {
 		result = result>>8 ~ _crc64_table[(result ~ u64(b)) & 0xff];
@@ -25,7 +25,7 @@ crc64 :: proc(data: []u8) -> u64 {
 	return ~result;
 }
 
-fnv32 :: proc(data: []u8) -> u32 {
+fnv32 :: proc(data: []byte) -> u32 {
 	h: u32 = 0x811c9dc5;
 	for b in data {
 		h = (h * 0x01000193) ~ u32(b);
@@ -33,7 +33,7 @@ fnv32 :: proc(data: []u8) -> u32 {
 	return h;
 }
 
-fnv64 :: proc(data: []u8) -> u64 {
+fnv64 :: proc(data: []byte) -> u64 {
 	h: u64 = 0xcbf29ce484222325;
 	for b in data {
 		h = (h * 0x100000001b3) ~ u64(b);
@@ -41,7 +41,7 @@ fnv64 :: proc(data: []u8) -> u64 {
 	return h;
 }
 
-fnv32a :: proc(data: []u8) -> u32 {
+fnv32a :: proc(data: []byte) -> u32 {
 	h: u32 = 0x811c9dc5;
 	for b in data {
 		h = (h ~ u32(b)) * 0x01000193;
@@ -49,7 +49,7 @@ fnv32a :: proc(data: []u8) -> u32 {
 	return h;
 }
 
-fnv64a :: proc(data: []u8) -> u64 {
+fnv64a :: proc(data: []byte) -> u64 {
 	h: u64 = 0xcbf29ce484222325;
 	for b in data {
 		h = (h ~ u64(b)) * 0x100000001b3;
@@ -57,7 +57,7 @@ fnv64a :: proc(data: []u8) -> u64 {
 	return h;
 }
 
-murmur32 :: proc(data: []u8) -> u32 {
+murmur32 :: proc(data: []byte) -> u32 {
 	c1_32: u32 : 0xcc9e2d51;
 	c2_32: u32 : 0x1b873593;
 
@@ -106,7 +106,7 @@ murmur32 :: proc(data: []u8) -> u32 {
 	return h1;
 }
 
-murmur64 :: proc(data: []u8) -> u64 {
+murmur64 :: proc(data: []byte) -> u64 {
 	SEED :: 0x9747b28c;
 
 	when size_of(int) == 8 {

+ 25 - 22
core/mem.odin

@@ -18,37 +18,27 @@ copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
 copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
 	return __mem_copy_non_overlapping(dst, src, len);
 }
-compare :: proc "contextless" (a, b: []u8) -> int {
+compare :: proc "contextless" (a, b: []byte) -> int {
 	return __mem_compare(&a[0], &b[0], min(len(a), len(b)));
 }
 
 
 slice_ptr :: proc "contextless" (ptr: ^$T, len: int) -> []T {
 	assert(len >= 0);
-	slice := raw.Slice{data = ptr, len = len, cap = len};
-	return transmute([]T)slice;
-}
-slice_ptr :: proc "contextless" (ptr: ^$T, len, cap: int) -> []T {
-	assert(0 <= len && len <= cap);
-	slice := raw.Slice{data = ptr, len = len, cap = cap};
+	slice := raw.Slice{data = ptr, len = len};
 	return transmute([]T)slice;
 }
 
-slice_to_bytes :: proc "contextless" (slice: $E/[]$T) -> []u8 {
+slice_to_bytes :: proc "contextless" (slice: $E/[]$T) -> []byte {
 	s := transmute(raw.Slice)slice;
 	s.len *= size_of(T);
 	s.cap *= size_of(T);
-	return transmute([]u8)s;
+	return transmute([]byte)s;
 }
 
-ptr_to_bytes :: proc "contextless" (ptr: ^$T, len := 1) -> []u8 {
+ptr_to_bytes :: proc "contextless" (ptr: ^$T, len := 1) -> []byte {
     assert(len >= 0);
-    return transmute([]u8)raw.Slice{ptr, len*size_of(T), len*size_of(T)};
-}
-
-ptr_to_bytes :: proc "contextless" (ptr: ^$T, len, cap: int) -> []u8 {
-    assert(0 <= len && len <= cap);
-    return transmute([]u8)raw.Slice{ptr, len*size_of(T), cap*size_of(T)};
+    return transmute([]byte)raw.Slice{ptr, len*size_of(T), len*size_of(T)};
 }
 
 
@@ -93,6 +83,17 @@ allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
 }
 
 
+Fixed_Byte_Buffer :: [dynamic]byte;
+
+make_fixed_byte_buffer :: proc(backing: []byte) -> Fixed_Byte_Buffer {
+	s := transmute(raw.Slice)backing;
+	d: raw.Dynamic_Array;
+	d.data = s.data;
+	d.len = 0;
+	d.cap = s.len;
+	d.allocator = nil_allocator();
+	return transmute(Fixed_Byte_Buffer)d;
+}
 
 
 
@@ -100,7 +101,7 @@ allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
 
 Arena :: struct {
 	backing:    Allocator,
-	memory:     []u8,
+	memory:     Fixed_Byte_Buffer,
 	temp_count: int,
 }
 
@@ -113,15 +114,15 @@ ArenaTempMemory :: struct {
 
 
 
-init_arena_from_memory :: proc(using a: ^Arena, data: []u8) {
+init_arena_from_memory :: proc(using a: ^Arena, data: []byte) {
 	backing    = Allocator{};
-	memory     = data[..0];
+	memory     = make_fixed_byte_buffer(data);
 	temp_count = 0;
 }
 
 init_arena_from_context :: proc(using a: ^Arena, size: int) {
 	backing = context.allocator;
-	memory = make([]u8, 0, size);
+	memory = make_fixed_byte_buffer(make([]byte, size));
 	temp_count = 0;
 }
 
@@ -135,7 +136,9 @@ context_from_allocator :: proc(a: Allocator) -> Context {
 destroy_arena :: proc(using a: ^Arena) {
 	if backing.procedure != nil {
 		context <- context_from_allocator(backing) {
-			free(memory);
+			if memory != nil {
+				free(&memory[0]);
+			}
 			memory = nil;
 		}
 	}
@@ -194,7 +197,7 @@ begin_arena_temp_memory :: proc(a: ^Arena) -> ArenaTempMemory {
 end_arena_temp_memory :: proc(using tmp: ArenaTempMemory) {
 	assert(len(arena.memory) >= original_count);
 	assert(arena.temp_count > 0);
-	arena.memory = arena.memory[..original_count];
+	(^raw.Dynamic_Array)(&arena.memory).len = original_count;
 	arena.temp_count -= 1;
 }
 

+ 6 - 6
core/os.odin

@@ -6,10 +6,10 @@ when ODIN_OS == "essence" do export "core:os_essence.odin";
 import "mem.odin";
 
 write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
-	return write(fd, cast([]u8)str);
+	return write(fd, cast([]byte)str);
 }
 
-read_entire_file :: proc(name: string) -> (data: []u8, success: bool) {
+read_entire_file :: proc(name: string) -> (data: []byte, success: bool) {
 	fd, err := open(name, O_RDONLY, 0);
 	if err != 0 {
 		return nil, false;
@@ -25,7 +25,7 @@ read_entire_file :: proc(name: string) -> (data: []u8, success: bool) {
 		return nil, true;
 	}
 
-	data := make([]u8, int(length));
+	data := make([]byte, int(length));
 	if data == nil {
 		return nil, false;
 	}
@@ -38,7 +38,7 @@ read_entire_file :: proc(name: string) -> (data: []u8, success: bool) {
 	return data[0..bytes_read], true;
 }
 
-write_entire_file :: proc(name: string, data: []u8, truncate := true) -> (success: bool) {
+write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (success: bool) {
 	flags: int = O_WRONLY|O_CREATE;
 	if truncate {
 		flags |= O_TRUNC;
@@ -54,9 +54,9 @@ write_entire_file :: proc(name: string, data: []u8, truncate := true) -> (succes
 }
 
 write :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
-	return write(fd, mem.slice_ptr(cast(^u8)data, len));
+	return write(fd, mem.slice_ptr(cast(^byte)data, len));
 }
 
 read :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
-	return read(fd, mem.slice_ptr(cast(^u8)data, len));
+	return read(fd, mem.slice_ptr(cast(^byte)data, len));
 }

+ 41 - 43
core/os_essence.odin

@@ -14,35 +14,35 @@ OS_Node_Type :: enum i32 {
 }
 
 OS_Node_Information :: struct #ordered {
-	handle: Handle,
-	id: [16]u8,
-	ntype: OS_Node_Type,
-	size: i64,
+	handle:   Handle,
+	id:       [16]byte,
+	ntype:    OS_Node_Type,
+	size:     i64,
 	position: i64,
 }
 
 foreign api {
-	@(link_name="OSHelloWorld")		os_hello_world :: proc() ---;
-	@(link_name="OSPrintDirect")		os_print_direct :: proc(string: ^u8, length: int) ---;
-	@(link_name="OSHeapAllocate")		os_heap_allocate :: proc(bytes: int, zero: bool) -> rawptr ---;
-	@(link_name="OSHeapFree")		os_heap_free :: proc(address: rawptr) ---;
-	@(link_name="OSOpenNode")		os_open_node :: proc(path: ^u8, path_length: int, flags: u64, information: ^OS_Node_Information) -> Errno ---;
-	@(link_name="OSResizeFile")		os_resize_file :: proc(handle: Handle, new_size: u64) -> Errno ---;
-	@(link_name="OSCloseHandle")		os_close_handle :: proc(handle: Handle) ---;
-	@(link_name="OSWriteFileSync")		os_write_file_sync :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---;
-	@(link_name="OSReadFileSync")		os_read_file_sync :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---;
-	@(link_name="OSInitialiseAPI")		os_initialise_api :: proc() -> int ---;
-	@(link_name="OSTerminateProcess")	os_terminate_process :: proc(handle: Handle) ---;
-	@(link_name="realloc")			os_heap_reallocate :: proc(address: rawptr, size: int) -> rawptr ---;
+	@(link_name="OSHelloWorld")       os_hello_world       :: proc() ---;
+	@(link_name="OSPrintDirect")      os_print_direct      :: proc(string: ^byte, length: int) ---;
+	@(link_name="OSHeapAllocate")     os_heap_allocate     :: proc(bytes: int, zero: bool) -> rawptr ---;
+	@(link_name="OSHeapFree")         os_heap_free         :: proc(address: rawptr) ---;
+	@(link_name="OSOpenNode")         os_open_node         :: proc(path: ^byte, path_length: int, flags: u64, information: ^OS_Node_Information) -> Errno ---;
+	@(link_name="OSResizeFile")       os_resize_file       :: proc(handle: Handle, new_size: u64) -> Errno ---;
+	@(link_name="OSCloseHandle")      os_close_handle      :: proc(handle: Handle) ---;
+	@(link_name="OSWriteFileSync")    os_write_file_sync   :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---;
+	@(link_name="OSReadFileSync")     os_read_file_sync    :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---;
+	@(link_name="OSInitialiseAPI")    os_initialise_api    :: proc() -> int ---;
+	@(link_name="OSTerminateProcess") os_terminate_process :: proc(handle: Handle) ---;
+	@(link_name="realloc")            os_heap_reallocate   :: proc(address: rawptr, size: int) -> rawptr ---;
 }
 
-stdin  := cast(Handle) -1; // Not implemented
-stdout := cast(Handle) 0;
-stderr := cast(Handle) 0;
+stdin  := Handle(-1); // Not implemented
+stdout := Handle(0);
+stderr := Handle(0);
 
 current_thread_id :: proc() -> int {
 	// Not implemented
-	return int(-1);
+	return -1;
 }
 
 heap_alloc :: proc(size: int) -> rawptr {
@@ -59,55 +59,53 @@ heap_resize :: proc(address: rawptr, new_size: int) -> rawptr {
 
 open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errno) {
 	information := new(OS_Node_Information);
-	error := os_open_node(&path[0], len(path), cast(u64) mode, information);
-	if (error < -1) { return 0,1; }
+	error := os_open_node(&path[0], len(path), u64(mode), information);
+	if error < -1 do return 0, 1;
 	information.position = 0;
-	if (mode&O_TRUNC==O_TRUNC) {
+	if mode&O_TRUNC==O_TRUNC {
 		error := os_resize_file(information.handle, 0);
-		if (error < -1) { return 0,1; }
+		if error < -1 do return 0, 1;
 	}
-	return cast(Handle) cast(uintptr) information,0;
+	return Handle(uintptr(information)), 0;
 }
 
 close :: proc(fd: Handle) {
-	information := cast(^OS_Node_Information) cast(uintptr) fd;
+	information := (^OS_Node_Information)(uintptr(fd));
 	os_close_handle(information.handle);
 	free(information);
 }
 
 file_size :: proc(fd: Handle) -> (i64, Errno) {
 	// Not (properly) implemented
-	information := cast(^OS_Node_Information) cast(uintptr) fd;
+	information := cast(^OS_Node_Information)uintptr(fd);
 	return information.size,0;
 }
 
-write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
-	if (fd == 0) {
+write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
+	if fd == 0 {
 		os_print_direct(&data[0], len(data));
 		return len(data), 0;
-	} else if (fd == 1) {
+	} else if fd == 1 {
 		assert(false);
 		return 0, 1;
-	} else {
-		information := cast(^OS_Node_Information) cast(uintptr) fd;
-		count := os_write_file_sync(information.handle, information.position, cast(i64) len(data), cast(rawptr) &data[0]);
-		if (count < 0) { return 0, 1; }
-		information.position += count;
-		return cast(int) count, 0;
 	}
+	information := (^OS_Node_Information)(uintptr(fd));
+	count := os_write_file_sync(information.handle, information.position, i64(len(data)), &data[0]);
+	if count < 0 do  return 0, 1;
+	information.position += count;
+	return int(count), 0;
 }
 
-read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
+read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 	if (fd == 0 || fd == 1) {
 		assert(false);
 		return 0, 1;
-	} else {
-		information := cast(^OS_Node_Information) cast(uintptr) fd;
-		count := os_read_file_sync(information.handle, information.position, cast(i64) len(data), cast(rawptr) &data[0]);
-		if (count < 0) { return 0, 1; }
-		information.position += count;
-		return cast(int) count, 0;
 	}
+	information := (^OS_Node_Information)(uintptr(fd));
+	count := os_read_file_sync(information.handle, information.position, i64(len(data)), &data[0]);
+	if count < 0 do return 0, 1;
+	information.position += count;
+	return int(count), 0;
 }
 
 os_terminate_this_process :: proc() {

+ 16 - 15
core/os_linux.odin

@@ -122,28 +122,28 @@ W_OK :: 2; // Test for write permission
 R_OK :: 4; // Test for read permission
 
 foreign libc {
-	@(link_name="open")    _unix_open    :: proc(path: ^u8, mode: int) -> Handle ---;
+	@(link_name="open")    _unix_open    :: proc(path: ^byte, mode: int) -> Handle ---;
 	@(link_name="close")   _unix_close   :: proc(fd: Handle) -> i32 ---;
 	@(link_name="read")    _unix_read    :: proc(fd: Handle, buf: rawptr, size: int) -> int ---;
 	@(link_name="write")   _unix_write   :: proc(fd: Handle, buf: rawptr, size: int) -> int ---;
 	@(link_name="lseek64") _unix_seek    :: proc(fd: Handle, offset: i64, whence: i32) -> i64 ---;
 	@(link_name="gettid")  _unix_gettid  :: proc() -> u64 ---;
-	@(link_name="stat")    _unix_stat    :: proc(path: ^u8, stat: ^Stat) -> i32 ---;
-	@(link_name="access")  _unix_access  :: proc(path: ^u8, mask: int) -> i32 ---;
+	@(link_name="stat")    _unix_stat    :: proc(path: ^byte, stat: ^Stat) -> i32 ---;
+	@(link_name="access")  _unix_access  :: proc(path: ^byte, mask: int) -> i32 ---;
 
 	@(link_name="malloc")  _unix_malloc  :: proc(size: int) -> rawptr ---;
 	@(link_name="calloc")  _unix_calloc  :: proc(num, size: int) -> rawptr ---;
 	@(link_name="free")    _unix_free    :: proc(ptr: rawptr) ---;
 	@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr ---;
-	@(link_name="getenv")  _unix_getenv  :: proc(^u8) -> ^u8 ---;
+	@(link_name="getenv")  _unix_getenv  :: proc(^byte) -> ^byte ---;
 
 	@(link_name="exit")    _unix_exit    :: proc(status: int) ---;
 }
 foreign dl {
-	@(link_name="dlopen")  _unix_dlopen  :: proc(filename: ^u8, flags: int) -> rawptr ---;
-	@(link_name="dlsym")   _unix_dlsym   :: proc(handle: rawptr, symbol: ^u8) -> rawptr ---;
+	@(link_name="dlopen")  _unix_dlopen  :: proc(filename: ^byte, flags: int) -> rawptr ---;
+	@(link_name="dlsym")   _unix_dlsym   :: proc(handle: rawptr, symbol: ^byte) -> rawptr ---;
 	@(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> int ---;
-	@(link_name="dlerror") _unix_dlerror :: proc() -> ^u8 ---;
+	@(link_name="dlerror") _unix_dlerror :: proc() -> ^byte ---;
 }
 
 // TODO(zangent): Change this to just `open` when Bill fixes overloading.
@@ -166,12 +166,12 @@ close :: proc(fd: Handle) {
 	_unix_close(fd);
 }
 
-read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
+read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 	sz := _unix_read(fd, &data[0], len(data));
 	return sz, 0;
 }
 
-write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
+write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 	sz := _unix_write(fd, &data[0], len(data));
 	return sz, 0;
 }
@@ -201,9 +201,10 @@ last_write_time_by_name :: proc(name: string) -> File_Time {}
 */
 
 stat :: inline proc(path: string) -> (Stat, int) {
-	s: Stat;
 	cstr := strings.new_c_string(path);
 	defer free(cstr);
+
+	s: Stat;
 	ret_int := _unix_stat(cstr, &s);
 	return s, int(ret_int);
 }
@@ -229,9 +230,9 @@ heap_free :: proc(ptr: rawptr) {
 
 getenv :: proc(name: string) -> (string, bool) {
 	path_str := strings.new_c_string(name);
-	cstr: ^u8 = _unix_getenv(path_str);
-	free(path_str);
-	if(cstr == nil) {
+	defer free(path_str);
+	cstr := _unix_getenv(path_str);
+	if cstr == nil {
 		return "", false;
 	}
 	return strings.to_odin_string(cstr), true;
@@ -248,15 +249,15 @@ current_thread_id :: proc() -> int {
 
 dlopen :: inline proc(filename: string, flags: int) -> rawptr {
 	cstr := strings.new_c_string(filename);
+	defer free(cstr);
 	handle := _unix_dlopen(cstr, flags);
-	free(cstr);
 	return handle;
 }
 dlsym :: inline proc(handle: rawptr, symbol: string) -> rawptr {
 	assert(handle != nil);
 	cstr := strings.new_c_string(symbol);
+	defer free(cstr);
 	proc_handle := _unix_dlsym(handle, cstr);
-	free(cstr);
 	return proc_handle;
 }
 dlclose :: inline proc(handle: rawptr) -> bool {

+ 17 - 17
core/os_windows.odin

@@ -95,8 +95,8 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn
 		create_mode = win32.OPEN_EXISTING;
 	}
 
-	buf: [300]u8;
-	copy(buf[..], cast([]u8)path);
+	buf: [300]byte;
+	copy(buf[..], cast([]byte)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;
@@ -110,7 +110,7 @@ close :: proc(fd: Handle) {
 }
 
 
-write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
+write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 	if len(data) == 0 do return 0, ERROR_NONE;
 
 	single_write_length: i32;
@@ -132,7 +132,7 @@ write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
 	return int(total_write), ERROR_NONE;
 }
 
-read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
+read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 	if len(data) == 0 do return 0, ERROR_NONE;
 
 	single_read_length: i32;
@@ -213,11 +213,11 @@ last_write_time :: proc(fd: Handle) -> File_Time {
 last_write_time_by_name :: proc(name: string) -> File_Time {
 	last_write_time: win32.Filetime;
 	data: win32.File_Attribute_Data;
-	buf: [1024]u8;
+	buf: [1024]byte;
 
 	assert(len(buf) > len(name));
 
-	copy(buf[..], cast([]u8)name);
+	copy(buf[..], cast([]byte)name);
 
 	if win32.get_file_attributes_ex_a(&buf[0], win32.GetFileExInfoStandard, &data) != 0 {
 		last_write_time = data.last_write_time;
@@ -267,7 +267,7 @@ _alloc_command_line_arguments :: proc() -> []string {
 		for (wstr+wstr_len)^ != 0 do wstr_len += 1;
 
 		len := 2*wstr_len-1;
-		buf := make([]u8, len+1);
+		buf := make([]byte, len+1);
 		str := mem.slice_ptr(wstr, wstr_len+1);
 
 		i, j := 0, 0;
@@ -275,28 +275,28 @@ _alloc_command_line_arguments :: proc() -> []string {
 			switch {
 			case str[j] < 0x80:
 				if i+1 > len do return "";
-				buf[i] = u8(str[j]); i += 1;
+				buf[i] = byte(str[j]); i += 1;
 				j += 1;
 			case str[j] < 0x800:
 				if i+2 > len do return "";
-				buf[i] = u8(0xc0 + (str[j]>>6));   i += 1;
-				buf[i] = u8(0x80 + (str[j]&0x3f)); i += 1;
+				buf[i] = byte(0xc0 + (str[j]>>6));   i += 1;
+				buf[i] = byte(0x80 + (str[j]&0x3f)); i += 1;
 				j += 1;
 			case 0xd800 <= str[j] && str[j] < 0xdc00:
 				if i+4 > len do return "";
 			c := rune((str[j] - 0xd800) << 10) + rune((str[j+1]) - 0xdc00) + 0x10000;
-				buf[i] = u8(0xf0 +  (c >> 18));         i += 1;
-				buf[i] = u8(0x80 + ((c >> 12) & 0x3f)); i += 1;
-				buf[i] = u8(0x80 + ((c >>  6) & 0x3f)); i += 1;
-				buf[i] = u8(0x80 + ((c      ) & 0x3f)); i += 1;
+				buf[i] = byte(0xf0 +  (c >> 18));         i += 1;
+				buf[i] = byte(0x80 + ((c >> 12) & 0x3f)); i += 1;
+				buf[i] = byte(0x80 + ((c >>  6) & 0x3f)); i += 1;
+				buf[i] = byte(0x80 + ((c      ) & 0x3f)); i += 1;
 				j += 2;
 			case 0xdc00 <= str[j] && str[j] < 0xe000:
 				return "";
 			case:
 				if i+3 > len do return "";
-				buf[i] = 0xe0 + u8 (str[j] >> 12);         i += 1;
-				buf[i] = 0x80 + u8((str[j] >>  6) & 0x3f); i += 1;
-				buf[i] = 0x80 + u8((str[j]      ) & 0x3f); i += 1;
+				buf[i] = 0xe0 + byte (str[j] >> 12);         i += 1;
+				buf[i] = 0x80 + byte((str[j] >>  6) & 0x3f); i += 1;
+				buf[i] = 0x80 + byte((str[j]      ) & 0x3f); i += 1;
 				j += 1;
 			}
 		}

+ 17 - 18
core/os_x.odin

@@ -122,38 +122,37 @@ X_OK :: 1; // Test for execute permission
 F_OK :: 0; // Test for file existance
 
 foreign libc {
-	@(link_name="open")    _unix_open    :: proc(path: ^u8, mode: int) -> Handle ---;
+	@(link_name="open")    _unix_open    :: proc(path: ^byte, mode: int) -> Handle ---;
 	@(link_name="close")   _unix_close   :: proc(handle: Handle) ---;
 	@(link_name="read")    _unix_read    :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---;
 	@(link_name="write")   _unix_write   :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---;
 	@(link_name="lseek")   _unix_lseek   :: proc(fs: Handle, offset: int, whence: int) -> int ---;
 	@(link_name="gettid")  _unix_gettid  :: proc() -> u64 ---;
-	@(link_name="stat")    _unix_stat    :: proc(path: ^u8, stat: ^Stat) -> int ---;
-	@(link_name="access")  _unix_access  :: proc(path: ^u8, mask: int) -> int ---;
+	@(link_name="stat")    _unix_stat    :: proc(path: ^byte, stat: ^Stat) -> int ---;
+	@(link_name="access")  _unix_access  :: proc(path: ^byte, mask: int) -> int ---;
 
 	@(link_name="malloc")  _unix_malloc  :: proc(size: int) -> rawptr ---;
 	@(link_name="calloc")  _unix_calloc  :: proc(num, size: int) -> rawptr ---;
 	@(link_name="free")    _unix_free    :: proc(ptr: rawptr) ---;
 	@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr ---;
-	@(link_name="getenv")  _unix_getenv  :: proc(^u8) -> ^u8 ---;
+	@(link_name="getenv")  _unix_getenv  :: proc(^byte) -> ^byte ---;
 
 	@(link_name="exit")    _unix_exit    :: proc(status: int) ---;
 }
 
 foreign dl {
-	@(link_name="dlopen")  _unix_dlopen  :: proc(filename: ^u8, flags: int) -> rawptr ---;
-	@(link_name="dlsym")   _unix_dlsym   :: proc(handle: rawptr, symbol: ^u8) -> rawptr ---;
+	@(link_name="dlopen")  _unix_dlopen  :: proc(filename: ^byte, flags: int) -> rawptr ---;
+	@(link_name="dlsym")   _unix_dlsym   :: proc(handle: rawptr, symbol: ^byte) -> rawptr ---;
 	@(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> int ---;
-	@(link_name="dlerror") _unix_dlerror :: proc() -> ^u8 ---;
+	@(link_name="dlerror") _unix_dlerror :: proc() -> ^byte ---;
 }
 
 // TODO(zangent): Change this to just `open` when Bill fixes overloading.
 open_simple :: proc(path: string, mode: int) -> (Handle, Errno) {
-
 	cstr := strings.new_c_string(path);
+	defer free(cstr);
 	handle := _unix_open(cstr, mode);
-	free(cstr);
-	if(handle == -1) {
+	if handle == -1 {
 		return 0, 1;
 	}
 	return handle, 0;
@@ -182,7 +181,7 @@ read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
 	assert(fd != -1);
 
 	bytes_read := _unix_read(fd, &data[0], len(data));
-	if(bytes_read == -1) {
+	if bytes_read == -1 {
 		return 0, 1;
 	}
 	return bytes_read, 0;
@@ -192,7 +191,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
 	assert(fd != -1);
 
 	final_offset := i64(_unix_lseek(fd, int(offset), whence));
-	if(final_offset == -1) {
+	if final_offset == -1 {
 		return 0, 1;
 	}
 	return final_offset, 0;
@@ -244,9 +243,9 @@ heap_free :: inline proc(ptr: rawptr) {
 
 getenv :: proc(name: string) -> (string, bool) {
 	path_str := strings.new_c_string(name);
-	cstr: ^u8 = _unix_getenv(path_str);
-	free(path_str);
-	if(cstr == nil) {
+	defer free(path_str);
+	cstr := _unix_getenv(path_str);
+	if cstr == nil {
 		return "", false;
 	}
 	return strings.to_odin_string(cstr), true;
@@ -258,21 +257,21 @@ exit :: inline proc(code: int) {
 
 
 current_thread_id :: proc() -> int {
-	// return cast(int) _unix_gettid();
+	// return int(_unix_gettid());
 	return 0;
 }
 
 dlopen :: inline proc(filename: string, flags: int) -> rawptr {
 	cstr := strings.new_c_string(filename);
+	defer free(cstr);
 	handle := _unix_dlopen(cstr, flags);
-	free(cstr);
 	return handle;
 }
 dlsym :: inline proc(handle: rawptr, symbol: string) -> rawptr {
 	assert(handle != nil);
 	cstr := strings.new_c_string(symbol);
+	defer free(cstr);
 	proc_handle := _unix_dlsym(handle, cstr);
-	free(cstr);
 	return proc_handle;
 }
 dlclose :: inline proc(handle: rawptr) -> bool {

+ 0 - 1
core/raw.odin

@@ -11,7 +11,6 @@ String :: struct #ordered {
 Slice :: struct #ordered {
 	data: rawptr,
 	len:  int,
-	cap:  int,
 }
 
 Dynamic_Array :: struct #ordered {

+ 52 - 35
core/strconv.odin

@@ -185,21 +185,22 @@ parse_f64 :: proc(s: string) -> f64 {
 }
 
 
-append_bool :: proc(buf: []u8, b: bool) -> string {
-	if b do append_string(&buf, "true");
-	else do append_string(&buf, "false");
-	return string(buf);
+append_bool :: proc(buf: []byte, b: bool) -> string {
+	n := 0;
+	if b do n = copy(buf, cast([]byte)"true");
+	else do n = copy(buf, cast([]byte)"false");
+	return string(buf[..n]);
 }
 
-append_uint :: proc(buf: []u8, u: u64, base: int) -> string {
+append_uint :: proc(buf: []byte, u: u64, base: int) -> string {
 	return append_bits(buf, u128(u), base, false, 8*size_of(uint), digits, 0);
 }
-append_int :: proc(buf: []u8, i: i64, base: int) -> string {
+append_int :: proc(buf: []byte, i: i64, base: int) -> string {
 	return append_bits(buf, u128(i), base, true, 8*size_of(int), digits, 0);
 }
-itoa :: proc(buf: []u8, i: int) -> string do return append_int(buf, i64(i), 10);
+itoa :: proc(buf: []byte, i: int) -> string do return append_int(buf, i64(i), 10);
 
-append_float :: proc(buf: []u8, f: f64, fmt: u8, prec, bit_size: int) -> string {
+append_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string {
 	return string(generic_ftoa(buf, f, fmt, prec, bit_size));
 }
 
@@ -207,7 +208,7 @@ append_float :: proc(buf: []u8, f: f64, fmt: u8, prec, bit_size: int) -> string
 
 
 DecimalSlice :: struct {
-	digits:        []u8,
+	digits:        []byte,
 	count:         int,
 	decimal_point: int,
 	neg:           bool,
@@ -225,7 +226,7 @@ _f32_info := FloatInfo{23, 8,  -127};
 _f64_info := FloatInfo{52, 11, -1023};
 
 
-generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8 {
+generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> []byte {
 	bits: u64;
 	flt: ^FloatInfo;
 	switch bit_size {
@@ -253,8 +254,8 @@ generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8
 		} else {
 			s = "+Inf";
 		}
-		append(&buf, ...cast([]u8)s);
-		return buf;
+		n := copy(buf, cast([]byte)s);
+		return buf[..n];
 
 	case 0: // denormalized
 		exp += 1;
@@ -297,48 +298,62 @@ generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8
 
 
 
-format_digits :: proc(buf: []u8, shortest: bool, neg: bool, digs: DecimalSlice, prec: int, fmt: u8) -> []u8 {
+format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: DecimalSlice, prec: int, fmt: byte) -> []byte {
+	Buffer :: struct {
+		b: []byte,
+		n: int,
+	}
+
+	to_bytes :: proc(b: Buffer) -> []byte do return b.b[..b.n];
+	add_bytes :: proc(buf: ^Buffer, bytes: ...byte) {
+		buf.n += copy(buf.b[buf.n..], bytes);
+	}
+
+	b := Buffer{b = buf};
+
 	switch fmt {
 	case 'f', 'F':
-		append(&buf, neg ? '-' : '+');
+		add_bytes(&b, neg ? '-' : '+');
 
 		// integer, padded with zeros when needed
 		if digs.decimal_point > 0 {
 			m := min(digs.count, digs.decimal_point);
-			append(&buf, ...digs.digits[0..m]);
+			add_bytes(&b, ...digs.digits[0..m]);
 			for ; m < digs.decimal_point; m += 1 {
-				append(&buf, '0');
+				add_bytes(&b, '0');
 			}
 		} else {
-			append(&buf, '0');
+			add_bytes(&b, '0');
 		}
 
 
 		// fractional part
 		if prec > 0 {
-			append(&buf, '.');
+			add_bytes(&b, '.');
 			for i in 0..prec {
-				c: u8 = '0';
+				c: byte = '0';
 				if j := digs.decimal_point + i; 0 <= j && j < digs.count {
 					c = digs.digits[j];
 				}
-				append(&buf, c);
+				add_bytes(&b, c);
 			}
 		}
-		return buf;
+		return to_bytes(b);
 
 	case 'e', 'E':
 		panic("strconv: e/E float printing is not yet supported");
-		return buf; // TODO
+		return to_bytes(b); // TODO
 
 	case 'g', 'G':
 		panic("strconv: g/G float printing is not yet supported");
-		return buf; // TODO
+		return to_bytes(b); // TODO
+
+	case:
+		add_bytes(&b, '%', fmt);
+		return to_bytes(b);
 	}
 
-	c := [2]u8{'%', fmt};
-	append(&buf, ...c[..]);
-	return buf;
+
 }
 
 round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^FloatInfo) {
@@ -379,12 +394,12 @@ round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^FloatInfo) {
 	inclusive := mant%2 == 0;
 
 	for i in 0..d.count {
-		l: u8 = '0'; // lower digit
+		l: byte = '0'; // lower digit
 		if i < lower.count {
 			l = lower.digits[i];
 		}
 		m := d.digits[i];   // middle digit
-		u: u8 = '0'; // upper digit
+		u: byte = '0'; // upper digit
 		if i < upper.count {
 			u = upper.digits[i];
 		}
@@ -443,13 +458,13 @@ is_integer_negative :: proc(u: u128, is_signed: bool, bit_size: int) -> (unsigne
 	return u, neg;
 }
 
-append_bits :: proc(buf: []u8, u: u128, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flag) -> string {
+append_bits :: proc(buf: []byte, u: u128, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flag) -> string {
 	if base < 2 || base > MAX_BASE {
 		panic("strconv: illegal base passed to append_bits");
 	}
 
 	neg: bool;
-	a: [129]u8;
+	a: [129]byte;
 	i := len(a);
 	u, neg = is_integer_negative(u, is_signed, bit_size);
 	b := u128(base);
@@ -474,15 +489,17 @@ append_bits :: proc(buf: []u8, u: u128, base: int, is_signed: bool, bit_size: in
 		}
 	}
 
-	if neg {
+	switch {
+	case neg:
 		i-=1; a[i] = '-';
-	} else if flags&Int_Flag.Plus != 0 {
+	case flags&Int_Flag.Plus != 0:
 		i-=1; a[i] = '+';
-	} else if flags&Int_Flag.Space != 0 {
+	case flags&Int_Flag.Space != 0:
 		i-=1; a[i] = ' ';
 	}
 
-	append(&buf, ...a[i..]);
-	return string(buf);
+	out := a[i..];
+	copy(buf, out);
+	return string(buf[0..len(out)]);
 }
 

+ 2 - 2
core/sys/wgl.odin

@@ -55,7 +55,7 @@ Glyph_Metrics_Float :: struct {
 Create_Context_Attribs_ARB_Type :: #type proc "c" (hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc;
 Choose_Pixel_Format_ARB_Type    :: #type proc "c" (hdc: Hdc, attrib_i_list: ^i32, attrib_f_list: ^f32, max_formats: u32, formats: ^i32, num_formats : ^u32) -> Bool;
 Swap_Interval_EXT_Type          :: #type proc "c" (interval: i32) -> bool;
-Get_Extensions_String_ARB_Type  :: #type proc "c" (Hdc) -> ^u8;
+Get_Extensions_String_ARB_Type  :: #type proc "c" (Hdc) -> ^byte;
 
 // Procedures
 	create_context_attribs_arb: Create_Context_Attribs_ARB_Type;
@@ -72,7 +72,7 @@ foreign opengl32 {
 	make_current :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool ---;
 
 	@(link_name="wglGetProcAddress")
-	get_proc_address :: proc(c_str: ^u8) -> rawptr ---;
+	get_proc_address :: proc(c_str: ^byte) -> rawptr ---;
 
 	@(link_name="wglDeleteContext")
 	delete_context :: proc(hglrc: Hglrc) -> Bool ---;

+ 20 - 20
core/sys/windows.odin

@@ -42,7 +42,7 @@ Wnd_Class_Ex_A :: struct #ordered {
 	icon:                  Hicon,
 	cursor:                Hcursor,
 	background:            Hbrush,
-	menu_name, class_name: ^u8,
+	menu_name, class_name: ^byte,
 	sm:                    Hicon,
 }
 
@@ -116,8 +116,8 @@ Find_Data :: struct #ordered{
     file_size_low:       u32,
     reserved0:           u32,
     reserved1:           u32,
-    file_name:           [MAX_PATH]u8,
-    alternate_file_name: [14]u8,
+    file_name:           [MAX_PATH]byte,
+    alternate_file_name: [14]byte,
 }
 
 Security_Attributes :: struct #ordered {
@@ -152,7 +152,7 @@ Pixel_Format_Descriptor :: struct #ordered {
 	stencil_bits,
 	aux_buffers,
 	layer_type,
-	reserved: u8,
+	reserved: byte,
 
 	layer_mask,
 	visible_mask,
@@ -201,7 +201,7 @@ Raw_Input_Header :: struct #ordered {
 Raw_HID :: struct #ordered {
 	size_hid: u32,
 	count:    u32,
-	raw_data: [1]u8,
+	raw_data: [1]byte,
 }
 
 Raw_Keyboard :: struct #ordered {
@@ -435,14 +435,14 @@ GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1;
 foreign kernel32 {
 	@(link_name="GetLastError")              get_last_error              :: proc() -> i32 ---;
 	@(link_name="ExitProcess")               exit_process                :: proc(exit_code: u32) ---;
-	@(link_name="GetModuleHandleA")          get_module_handle_a         :: proc(module_name: ^u8) -> Hinstance ---;
+	@(link_name="GetModuleHandleA")          get_module_handle_a         :: proc(module_name: ^byte) -> Hinstance ---;
 	@(link_name="GetModuleHandleW")          get_module_handle_w         :: proc(module_name: ^u16) -> Hinstance ---;
 	@(link_name="Sleep")                     sleep                       :: proc(ms: i32) -> i32 ---;
 	@(link_name="QueryPerformanceFrequency") query_performance_frequency :: proc(result: ^i64) -> i32 ---;
 	@(link_name="QueryPerformanceCounter")   query_performance_counter   :: proc(result: ^i64) -> i32 ---;
-	@(link_name="OutputDebugStringA")        output_debug_string_a       :: proc(c_str: ^u8) ---;
+	@(link_name="OutputDebugStringA")        output_debug_string_a       :: proc(c_str: ^byte) ---;
 
-	@(link_name="GetCommandLineA")    get_command_line_a    :: proc() -> ^u8 ---;
+	@(link_name="GetCommandLineA")    get_command_line_a    :: proc() -> ^byte ---;
 	@(link_name="GetCommandLineW")    get_command_line_w    :: proc() -> ^u16 ---;
 	@(link_name="GetSystemMetrics")   get_system_metrics    :: proc(index: i32) -> i32 ---;
 	@(link_name="GetCurrentThreadId") get_current_thread_id :: proc() -> u32 ---;
@@ -456,7 +456,7 @@ foreign kernel32 {
 	@(link_name="GetStdHandle") get_std_handle :: proc(h: i32) -> Handle ---;
 
 	@(link_name="CreateFileA")
-	create_file_a :: proc(filename: ^u8, desired_access, share_module: u32,
+	create_file_a :: proc(filename: ^byte, desired_access, share_module: u32,
 	                      security: rawptr,
 	                      creation, flags_and_attribs: u32, template_file: Handle) -> Handle ---;
 
@@ -464,8 +464,8 @@ foreign kernel32 {
 	@(link_name="WriteFile") write_file :: proc(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool ---;
 
 	@(link_name="GetFileSizeEx")              get_file_size_ex               :: proc(file_handle: Handle, file_size: ^i64) -> Bool ---;
-	@(link_name="GetFileAttributesA")         get_file_attributes_a          :: proc(filename: ^u8) -> u32 ---;
-	@(link_name="GetFileAttributesExA")       get_file_attributes_ex_a       :: proc(filename: ^u8, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool ---;
+	@(link_name="GetFileAttributesA")         get_file_attributes_a          :: proc(filename: ^byte) -> u32 ---;
+	@(link_name="GetFileAttributesExA")       get_file_attributes_ex_a       :: proc(filename: ^byte, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool ---;
 	@(link_name="GetFileInformationByHandle") get_file_information_by_handle :: proc(file_handle: Handle, file_info: ^By_Handle_File_Information) -> Bool ---;
 
 	@(link_name="GetFileType")    get_file_type    :: proc(file_handle: Handle) -> u32 ---;
@@ -473,7 +473,7 @@ foreign kernel32 {
 
 	@(link_name="SetHandleInformation") set_handle_information :: proc(obj: Handle, mask, flags: u32) -> Bool ---;
 
-	@(link_name="FindFirstFileA") find_first_file_a :: proc(file_name : ^u8, data : ^Find_Data) -> Handle ---;
+	@(link_name="FindFirstFileA") find_first_file_a :: proc(file_name : ^byte, data : ^Find_Data) -> Handle ---;
 	@(link_name="FindNextFileA")  find_next_file_a  :: proc(file : Handle, data : ^Find_Data) -> Bool ---;
 	@(link_name="FindClose")      find_close        :: proc(file : Handle) -> Bool ---;
 
@@ -484,7 +484,7 @@ foreign kernel32 {
 	@(link_name="GetProcessHeap") get_process_heap :: proc() -> Handle ---;
 
 
-	@(link_name="CreateSemaphoreA")    create_semaphore_a     :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^u8) -> Handle ---;
+	@(link_name="CreateSemaphoreA")    create_semaphore_a     :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^byte) -> Handle ---;
 	@(link_name="ReleaseSemaphore")    release_semaphore      :: proc(semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool ---;
 	@(link_name="WaitForSingleObject") wait_for_single_object :: proc(handle: Handle, milliseconds: u32) -> u32 ---;
 }
@@ -527,12 +527,12 @@ foreign kernel32 {
 	@(link_name="EnterCriticalSection")                  enter_critical_section                     :: proc(critical_section: ^Critical_Section) ---;
 	@(link_name="LeaveCriticalSection")                  leave_critical_section                     :: proc(critical_section: ^Critical_Section) ---;
 
-	@(link_name="CreateEventA") create_event_a :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: ^u8) -> Handle ---;
+	@(link_name="CreateEventA") create_event_a :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: ^byte) -> Handle ---;
 
-	@(link_name="LoadLibraryA")   load_library_a   :: proc(c_str: ^u8)  -> Hmodule ---;
+	@(link_name="LoadLibraryA")   load_library_a   :: proc(c_str: ^byte)  -> Hmodule ---;
 	@(link_name="LoadLibraryW")   load_library_a   :: proc(c_str: ^u16) -> Hmodule ---;
 	@(link_name="FreeLibrary")    free_library     :: proc(h: Hmodule) ---;
-	@(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: ^u8) -> rawptr ---;
+	@(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: ^byte) -> rawptr ---;
 
 }
 
@@ -545,13 +545,13 @@ foreign user32 {
 	@(link_name="ScreenToClient")   screen_to_client    :: proc(h: Hwnd, p: ^Point) -> Bool ---;
 	@(link_name="ClientToScreen")   client_to_screen    :: proc(h: Hwnd, p: ^Point) -> Bool ---;
 	@(link_name="PostQuitMessage")  post_quit_message   :: proc(exit_code: i32) ---;
-	@(link_name="SetWindowTextA")   set_window_text_a   :: proc(hwnd: Hwnd, c_string: ^u8) -> Bool ---;
+	@(link_name="SetWindowTextA")   set_window_text_a   :: proc(hwnd: Hwnd, c_string: ^byte) -> Bool ---;
 	@(link_name="RegisterClassExA") register_class_ex_a :: proc(wc: ^Wnd_Class_Ex_A) -> i16 ---;
 	@(link_name="RegisterClassExW") register_class_ex_w :: proc(wc: ^Wnd_Class_Ex_W) -> i16 ---;
 
 	@(link_name="CreateWindowExA")
 	create_window_ex_a :: proc(ex_style: u32,
-	                           class_name, title: ^u8,
+	                           class_name, title: ^byte,
 	                           style: u32,
 	                           x, y, w, h: i32,
 	                           parent: Hwnd, menu: Hmenu, instance: Hinstance,
@@ -601,7 +601,7 @@ foreign user32 {
 	@(link_name="GetWindowLongPtrW") get_window_long_ptr_w :: proc(wnd: Hwnd, index: i32) -> Long_Ptr ---;
 	@(link_name="SetWindowLongPtrW") set_window_long_ptr_w :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr ---;
 
-	@(link_name="GetWindowText") get_window_text :: proc(wnd: Hwnd, str: ^u8, maxCount: i32) -> i32 ---;
+	@(link_name="GetWindowText") get_window_text :: proc(wnd: Hwnd, str: ^byte, maxCount: i32) -> i32 ---;
 
 	@(link_name="GetClientRect") get_client_rect :: proc(hwnd: Hwnd, rect: ^Rect) -> Bool ---;
 
@@ -757,7 +757,7 @@ Bitmap_Info :: struct #ordered {
 }
 
 
-Rgb_Quad :: struct #ordered {blue, green, red, reserved: u8}
+Rgb_Quad :: struct #ordered {blue, green, red, reserved: byte}
 
 
 Key_Code :: enum i32 {

+ 16 - 9
examples/demo.odin

@@ -20,6 +20,7 @@ when ODIN_OS == "windows" {
 }
 
 general_stuff :: proc() {
+	fmt.println("# general_stuff");
 	{ // `do` for inline statmes rather than block
 		foo :: proc() do fmt.println("Foo!");
 		if   false do foo();
@@ -77,6 +78,7 @@ general_stuff :: proc() {
 }
 
 default_struct_values :: proc() {
+	fmt.println("# default_struct_values");
 	{
 		Vector3 :: struct {
 			x: f32,
@@ -138,6 +140,7 @@ default_struct_values :: proc() {
 
 
 union_type :: proc() {
+	fmt.println("\n# union_type");
 	{
 		val: union{int, bool};
 		val = 137;
@@ -310,6 +313,8 @@ union_type :: proc() {
 }
 
 parametric_polymorphism :: proc() {
+	fmt.println("# parametric_polymorphism");
+
 	print_value :: proc(value: $T) {
 		fmt.printf("print_value: %T %v\n", value, value);
 	}
@@ -510,12 +515,14 @@ prefix_table := [...]string{
 
 threading_example :: proc() {
 	when ODIN_OS == "windows" {
-		unordered_remove :: proc(array: ^[]$T, index: int, loc := #caller_location) {
+		fmt.println("# threading_example");
+
+		unordered_remove :: proc(array: ^[dynamic]$T, index: int, loc := #caller_location) {
 			__bounds_check_error_loc(loc, index, len(array));
 			array[index] = array[len(array)-1];
 			pop(array);
 		}
-		ordered_remove :: proc(array: ^[]$T, index: int, loc := #caller_location) {
+		ordered_remove :: proc(array: ^[dynamic]$T, index: int, loc := #caller_location) {
 			__bounds_check_error_loc(loc, index, len(array));
 			copy(array[index..], array[index+1..]);
 			pop(array);
@@ -530,7 +537,7 @@ threading_example :: proc() {
 			return 0;
 		}
 
-		threads := make([]^thread.Thread, 0, len(prefix_table));
+		threads := make([dynamic]^thread.Thread, 0, len(prefix_table));
 		defer free(threads);
 
 		for i in 0..len(prefix_table) {
@@ -559,12 +566,12 @@ threading_example :: proc() {
 }
 
 main :: proc() {
-	when false {
-		fmt.println("\n# general_stuff");              general_stuff();
-		fmt.println("\n# default_struct_values");      default_struct_values();
-		fmt.println("\n# union_type");                 union_type();
-		fmt.println("\n# parametric_polymorphism");    parametric_polymorphism();
-		fmt.println("\n# threading_example");          threading_example();
+	when true {
+		general_stuff();
+		default_struct_values();
+		union_type();
+		parametric_polymorphism();
+		threading_example();
 	}
 }
 

+ 5 - 30
src/check_expr.cpp

@@ -3077,7 +3077,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 		isize max_args = 1;
 		if (is_type_slice(type)) {
 			min_args = 2;
-			max_args = 3;
+			max_args = 2;
 		} else if (is_type_map(type)) {
 			min_args = 1;
 			max_args = 2;
@@ -6084,12 +6084,6 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 		switch (t->kind) {
 		case Type_Basic:
 			if (is_type_string(t)) {
-				if (se->index3) {
-					error(node, "3-index slice on a string in not needed");
-					o->mode = Addressing_Invalid;
-					o->expr = node;
-					return kind;
-				}
 				valid = true;
 				if (o->mode == Addressing_Constant) {
 					max_count = o->value.value_string.len;
@@ -6141,25 +6135,10 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 			// It is okay to continue as it will assume the 1st index is zero
 		}
 
-		if (se->index3 && (se->high == nullptr || se->max == nullptr)) {
-			error(se->close, "2nd and 3rd indices are required in a 3-index slice");
-			o->mode = Addressing_Invalid;
-			o->expr = node;
-			return kind;
-		}
+		TokenKind interval_kind = se->interval.kind;
 
-		if (se->index3 && se->interval0.kind != se->interval1.kind) {
-			error(se->close, "The interval separators for in a 3-index slice must be the same");
-			o->mode = Addressing_Invalid;
-			o->expr = node;
-			return kind;
-		}
-
-
-		TokenKind interval_kind = se->interval0.kind;
-
-		i64 indices[3] = {};
-		AstNode *nodes[3] = {se->low, se->high, se->max};
+		i64 indices[2] = {};
+		AstNode *nodes[2] = {se->low, se->high};
 		for (isize i = 0; i < gb_count_of(nodes); i++) {
 			i64 index = max_count;
 			if (nodes[i] != nullptr) {
@@ -6461,12 +6440,8 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = write_expr_to_string(str, se->expr);
 		str = gb_string_append_rune(str, '[');
 		str = write_expr_to_string(str, se->low);
-		str = gb_string_appendc(str, "..");
+		str = string_append_token(str, se->interval);
 		str = write_expr_to_string(str, se->high);
-		if (se->index3) {
-			str = gb_string_appendc(str, "..");
-			str = write_expr_to_string(str, se->max);
-		}
 		str = gb_string_append_rune(str, ']');
 	case_end;
 

+ 5 - 10
src/checker.cpp

@@ -852,6 +852,9 @@ void add_global_string_constant(gbAllocator a, String name, String value) {
 }
 
 
+void add_global_type_entity(gbAllocator a, String name, Type *type) {
+	add_global_entity(make_entity_type_name(a, nullptr, make_token_ident(name), type));
+}
 
 
 
@@ -863,17 +866,9 @@ void init_universal_scope(void) {
 
 // Types
 	for (isize i = 0; i < gb_count_of(basic_types); i++) {
-		add_global_entity(make_entity_type_name(a, nullptr, make_token_ident(basic_types[i].Basic.name), &basic_types[i]));
+		add_global_type_entity(a, basic_types[i].Basic.name, &basic_types[i]);
 	}
-#if 1
-	// for (isize i = 0; i < gb_count_of(basic_type_aliases); i++) {
-		// add_global_entity(make_entity_type_name(a, nullptr, make_token_ident(basic_type_aliases[i].Basic.name), &basic_type_aliases[i]));
-	// }
-#else
-	{
-		t_byte = add_global_type_alias(a, str_lit("byte"), &basic_types[Basic_u8]);
-	}
-#endif
+	add_global_type_entity(a, str_lit("byte"), &basic_types[Basic_u8]);
 
 // Constants
 	add_global_constant(a, str_lit("true"),  t_untyped_bool, exact_value_bool(true));

+ 65 - 83
src/ir.cpp

@@ -2674,7 +2674,6 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
 		switch (index) {
 		case 0: result_type = make_type_pointer(a, t->Slice.elem); break;
 		case 1: result_type = t_int; break;
-		case 2: result_type = t_int; break;
 		}
 		break;
 	case Type_DynamicArray:
@@ -2837,11 +2836,6 @@ irValue *ir_slice_count(irProcedure *proc, irValue *slice) {
 	GB_ASSERT(is_type_slice(ir_type(slice)));
 	return ir_emit_struct_ev(proc, slice, 1);
 }
-irValue *ir_slice_capacity(irProcedure *proc, irValue *slice) {
-	GB_ASSERT(is_type_slice(ir_type(slice)));
-	return ir_emit_struct_ev(proc, slice, 2);
-}
-
 irValue *ir_dynamic_array_elem(irProcedure *proc, irValue *da) {
 	GB_ASSERT(is_type_dynamic_array(ir_type(da)));
 	return ir_emit_struct_ev(proc, da, 0);
@@ -2873,14 +2867,13 @@ irValue *ir_string_len(irProcedure *proc, irValue *string) {
 }
 
 
-void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *len, irValue *cap) {
+void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *len) {
 	Type *t = ir_type(slice_ptr);
 	GB_ASSERT(is_type_pointer(t));
 	t = type_deref(t);
 	GB_ASSERT(is_type_slice(t));
 	ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 0), data);
 	ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 1), len);
-	ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 2), cap);
 }
 void ir_fill_string(irProcedure *proc, irValue *string_ptr, irValue *data, irValue *len) {
 	Type *t = ir_type(string_ptr);
@@ -2900,7 +2893,7 @@ irValue *ir_emit_string(irProcedure *proc, irValue *elem, irValue *len) {
 
 
 
-irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, irValue *low, irValue *high, irValue *max) {
+irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, irValue *low, irValue *high) {
 	// TODO(bill): array bounds checking for slice creation
 	// TODO(bill): check that low < high <= max
 	gbAllocator a = proc->module->allocator;
@@ -2916,16 +2909,8 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base,
 		case Type_Pointer: high = v_one;                     break;
 		}
 	}
-	if (max == nullptr) {
-		switch (bt->kind) {
-		case Type_Array:   high = ir_array_len(proc, base);      break;
-		case Type_Slice:   high = ir_slice_capacity(proc, base); break;
-		case Type_Pointer: high = v_one;                         break;
-		}
-	}
 
 	irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
-	irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int);
 
 	irValue *elem = nullptr;
 	switch (bt->kind) {
@@ -2937,7 +2922,7 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base,
 	elem = ir_emit_ptr_offset(proc, elem, low);
 
 	irValue *slice = ir_add_local_generated(proc, slice_type);
-	ir_fill_slice(proc, slice, elem, len, cap);
+	ir_fill_slice(proc, slice, elem, len);
 	return slice;
 }
 
@@ -3274,8 +3259,7 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
 		ir_emit_store(proc, elem_ptr, elem);
 
 		irValue *len  = ir_string_len(proc, value);
-		irValue *cap  = len;
-		irValue *slice = ir_add_local_slice(proc, t, elem_ptr, v_zero, len, cap);
+		irValue *slice = ir_add_local_slice(proc, t, elem_ptr, v_zero, len);
 		return ir_emit_load(proc, slice);
 	}
 
@@ -3648,7 +3632,7 @@ void ir_emit_bounds_check(irProcedure *proc, Token token, irValue *index, irValu
 	// ir_emit(proc, ir_instr_bounds_check(proc, token.pos, index, len));
 }
 
-void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *max, bool is_substring) {
+void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, bool is_substring) {
 	if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
 		return;
 	}
@@ -3660,22 +3644,38 @@ void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, ir
 	low  = ir_emit_conv(proc, low,  t_int);
 	high = ir_emit_conv(proc, high, t_int);
 
-	irValue **args = gb_alloc_array(a, irValue *, 6);
+	irValue **args = gb_alloc_array(a, irValue *, 5);
 	args[0] = file;
 	args[1] = line;
 	args[2] = column;
 	args[3] = low;
 	args[4] = high;
-	args[5] = max;
 
-	if (is_substring) {
-		ir_emit_global_call(proc, "__substring_expr_error", args, 5);
-	} else {
-		ir_emit_global_call(proc, "__slice_expr_error", args, 6);
+	char *func = is_substring ? "__substring_expr_error" : "__slice_expr_error";
+	ir_emit_global_call(proc, func, args, 5);
+}
+
+void ir_emit_dynamic_array_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *max) {
+	if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
+		return;
 	}
 
+	gbAllocator a = proc->module->allocator;
+	irValue *file = ir_find_or_add_entity_string(proc->module, token.pos.file);
+	irValue *line = ir_const_int(a, token.pos.line);
+	irValue *column = ir_const_int(a, token.pos.column);
+	low  = ir_emit_conv(proc, low,  t_int);
+	high = ir_emit_conv(proc, high, t_int);
+
+	irValue **args = gb_alloc_array(a, irValue *, 6);
+	args[0] = file;
+	args[1] = line;
+	args[2] = column;
+	args[3] = low;
+	args[4] = high;
+	args[5] = max;
 
-	// ir_emit(proc, ir_instr_slice_bounds_check(proc, token.pos, low, high, max, is_substring));
+	ir_emit_global_call(proc, "__dynamic_array_expr_error", args, 6);
 }
 
 
@@ -4139,7 +4139,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 		} else if (is_type_vector(t)) {
 			GB_PANIC("Unreachable");
 		} else if (is_type_slice(t)) {
-			return ir_slice_capacity(proc, v);
+			return ir_slice_count(proc, v);
 		} else if (is_type_dynamic_array(t)) {
 			return ir_dynamic_array_capacity(proc, v);
 		} else if (is_type_map(t)) {
@@ -4212,17 +4212,12 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 			irValue *elem_align = ir_const_int(a, eal);
 
 			irValue *len = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
-			irValue *cap = len;
 
-			if (ce->args.count == 3)  {
-				cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args[2]), t_int);
-			}
+			ir_emit_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, false);
 
-			ir_emit_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, cap, false);
-
-			irValue *slice_size = cap;
+			irValue *slice_size = len;
 			if (eal != 1) {
-				slice_size = ir_emit_arith(proc, Token_Mul, elem_size, cap, t_int);
+				slice_size = ir_emit_arith(proc, Token_Mul, elem_size, len, t_int);
 			}
 
 			TokenPos pos = ast_node_token(ce->args[0]).pos;
@@ -4240,7 +4235,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 			}
 
 			irValue *slice = ir_add_local_generated(proc, type);
-			ir_fill_slice(proc, slice, ptr, len, cap);
+			ir_fill_slice(proc, slice, ptr, len);
 			return ir_emit_load(proc, slice);
 		} else if (is_type_map(type)) {
 			irValue *int_16 = ir_const_int(a, 16);
@@ -4272,7 +4267,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 				cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args[2]), t_int);
 			}
 
-			ir_emit_slice_bounds_check(proc, ast_node_token(ce->args[0]), v_zero, len, cap, false);
+			ir_emit_dynamic_array_bounds_check(proc, ast_node_token(ce->args[0]), v_zero, len, cap);
 
 			irValue *array = ir_add_local_generated(proc, type);
 			irValue **args = gb_alloc_array(a, irValue *, 6);
@@ -5270,7 +5265,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 
 					irValue *base_elem = ir_emit_array_epi(proc, base_array, 0);
 					irValue *len = ir_const_int(allocator, slice_len);
-					ir_fill_slice(proc, slice, base_elem, len, len);
+					ir_fill_slice(proc, slice, base_elem, len);
 				}
 
 				arg_count = param_count;
@@ -5663,20 +5658,14 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 		gbAllocator a = proc->module->allocator;
 		irValue *low  = v_zero;
 		irValue *high = nullptr;
-		irValue *max = nullptr;
 
-		if (se->low  != nullptr)    low  = ir_build_expr(proc, se->low);
-		if (se->high != nullptr)    high = ir_build_expr(proc, se->high);
-		if (se->max  != nullptr)    max  = ir_build_expr(proc, se->max);
+		if (se->low  != nullptr) low  = ir_build_expr(proc, se->low);
+		if (se->high != nullptr) high = ir_build_expr(proc, se->high);
 
-		if (high != nullptr && se->interval0.kind == Token_Ellipsis) {
+		if (high != nullptr && se->interval.kind == Token_Ellipsis) {
 			high = ir_emit_arith(proc, Token_Add, high, v_one, t_int);
 		}
 
-		if (max != nullptr && se->interval1.kind == Token_Ellipsis) {
-			max = ir_emit_arith(proc, Token_Add, max, v_one, t_int);
-		}
-
 		irValue *addr = ir_build_addr_ptr(proc, se->expr);
 		irValue *base = ir_emit_load(proc, addr);
 		Type *type = base_type(ir_type(base));
@@ -5693,16 +5682,14 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			Type *slice_type = type;
 
 			if (high == nullptr) high = ir_slice_count(proc, base);
-			if (max == nullptr)  max =  ir_slice_capacity(proc, base);
 
-			ir_emit_slice_bounds_check(proc, se->open, low, high, max, false);
+			ir_emit_slice_bounds_check(proc, se->open, low, high, false);
 
 			irValue *elem  = ir_emit_ptr_offset(proc, ir_slice_elem(proc, base), low);
 			irValue *len   = ir_emit_arith(proc, Token_Sub, high, low, t_int);
-			irValue *cap   = ir_emit_arith(proc, Token_Sub, max, low, t_int);
 
 			irValue *slice = ir_add_local_generated(proc, slice_type);
-			ir_fill_slice(proc, slice, elem, len, cap);
+			ir_fill_slice(proc, slice, elem, len);
 			return ir_addr(slice);
 		}
 
@@ -5711,16 +5698,15 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			Type *slice_type = make_type_slice(a, elem_type);
 
 			if (high == nullptr) high = ir_dynamic_array_count(proc, base);
-			if (max == nullptr)  max  = ir_dynamic_array_capacity(proc, base);
+			irValue *cap = ir_dynamic_array_capacity(proc, base);
 
-			ir_emit_slice_bounds_check(proc, se->open, low, high, max, false);
+			ir_emit_dynamic_array_bounds_check(proc, se->open, low, high, cap);
 
 			irValue *elem  = ir_emit_ptr_offset(proc, ir_dynamic_array_elem(proc, base), low);
 			irValue *len   = ir_emit_arith(proc, Token_Sub, high, low, t_int);
-			irValue *cap   = ir_emit_arith(proc, Token_Sub, max, low, t_int);
 
 			irValue *slice = ir_add_local_generated(proc, slice_type);
-			ir_fill_slice(proc, slice, elem, len, cap);
+			ir_fill_slice(proc, slice, elem, len);
 			return ir_addr(slice);
 		}
 
@@ -5729,21 +5715,18 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			Type *slice_type = make_type_slice(a, type->Array.elem);
 
 			if (high == nullptr) high = ir_array_len(proc, base);
-			if (max == nullptr)  max  = ir_array_len(proc, base);
 
 			bool low_const  = type_and_value_of_expr(proc->module->info, se->low).mode  == Addressing_Constant;
 			bool high_const = type_and_value_of_expr(proc->module->info, se->high).mode == Addressing_Constant;
-			bool max_const  = type_and_value_of_expr(proc->module->info, se->max).mode  == Addressing_Constant;
 
-			if (!low_const || !high_const || !max_const) {
-				ir_emit_slice_bounds_check(proc, se->open, low, high, max, false);
+			if (!low_const || !high_const) {
+				ir_emit_slice_bounds_check(proc, se->open, low, high, false);
 			}
 			irValue *elem = ir_emit_ptr_offset(proc, ir_array_elem(proc, addr), low);
 			irValue *len  = ir_emit_arith(proc, Token_Sub, high, low, t_int);
-			irValue *cap  = ir_emit_arith(proc, Token_Sub, max, low, t_int);
 
 			irValue *slice = ir_add_local_generated(proc, slice_type);
-			ir_fill_slice(proc, slice, elem, len, cap);
+			ir_fill_slice(proc, slice, elem, len);
 			return ir_addr(slice);
 		}
 
@@ -5752,7 +5735,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			if (high == nullptr) high = ir_string_len(proc, base);
 			// if (max == nullptr)  max = ir_string_len(proc, base);
 
-			ir_emit_slice_bounds_check(proc, se->open, low, high, nullptr, true);
+			ir_emit_slice_bounds_check(proc, se->open, low, high, true);
 
 			irValue *elem = ir_emit_ptr_offset(proc, ir_string_elem(proc, base), low);
 			irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
@@ -5760,7 +5743,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			irValue *str = ir_add_local_generated(proc, t_string);
 			ir_fill_string(proc, str, elem, len);
 			return ir_addr(str);
-			break;
 		}
 		}
 
@@ -5984,7 +5966,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 				}
 
 				irValue *count = ir_const_int(proc->module->allocator, slice->ConstantSlice.count);
-				ir_fill_slice(proc, v, data, count, count);
+				ir_fill_slice(proc, v, data, count);
 			}
 			break;
 		}
@@ -7746,7 +7728,7 @@ void ir_init_module(irModule *m, Checker *c) {
 			{
 				String name = str_lit(IR_TYPE_INFO_OFFSETS_NAME);
 				Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name),
-				                                 make_type_array(m->allocator, t_int, count), false);
+				                                 make_type_array(m->allocator, t_uintptr, count), false);
 				irValue *g = ir_value_global(m->allocator, e, nullptr);
 				ir_module_add_value(m, e, g);
 				map_set(&m->members, hash_string(name), g);
@@ -7899,7 +7881,7 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 		irValue *len = ir_const_int(proc->module->allocator, type->Array.count);
 		ir_fill_slice(proc, global_type_table,
 		              ir_emit_array_epi(proc, ir_global_type_info_data, 0),
-		              len, len);
+		              len);
 	}
 
 
@@ -8098,8 +8080,8 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 			}
 
 			irValue *count = ir_const_int(a, t->Tuple.variables.count);
-			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types, count, count);
-			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count, count);
+			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types, count);
+			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count);
 			break;
 		}
 		case Type_Enum:
@@ -8138,11 +8120,11 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 
 					irValue *names = ir_emit_struct_ep(proc, tag, 1);
 					irValue *name_array_elem = ir_array_elem(proc, name_array);
-					ir_fill_slice(proc, names, name_array_elem, v_count, v_count);
+					ir_fill_slice(proc, names, name_array_elem, v_count);
 
 					irValue *values = ir_emit_struct_ep(proc, tag, 2);
 					irValue *value_array_elem = ir_array_elem(proc, value_array);
-					ir_fill_slice(proc, values, value_array_elem, v_count, v_count);
+					ir_fill_slice(proc, values, value_array_elem, v_count);
 				}
 			}
 			break;
@@ -8170,11 +8152,11 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 				}
 
 				irValue *count = ir_const_int(a, variant_count);
-				ir_fill_slice(proc, variant_types, memory_types, count, count);
+				ir_fill_slice(proc, variant_types, memory_types, count);
 
-				i64 tag_size  = union_tag_size(t);
+				i64 tag_size   = union_tag_size(t);
 				i64 tag_offset = align_formula(t->Union.variant_block_size, tag_size);
-				ir_emit_store(proc, tag_offset_ptr, ir_const_int(a, tag_offset));
+				ir_emit_store(proc, tag_offset_ptr, ir_const_uintptr(a, tag_offset));
 				ir_emit_store(proc, tag_type_ptr,   ir_type_info(proc, union_tag_type(t)));
 			}
 
@@ -8224,15 +8206,15 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 					irValue *name = ir_emit_ptr_offset(proc, memory_names,   index);
 					ir_emit_store(proc, name, ir_const_string(a, f->token.string));
 				}
-				ir_emit_store(proc, offset, ir_const_int(a, foffset));
+				ir_emit_store(proc, offset, ir_const_uintptr(a, foffset));
 				ir_emit_store(proc, is_using, ir_const_bool(a, (f->flags&EntityFlag_Using) != 0));
 			}
 
 			irValue *cv = ir_const_int(a, count);
-			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types,   cv, cv);
-			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names,   cv, cv);
-			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, cv, cv);
-			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 3), memory_usings,  cv, cv);
+			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types,   cv);
+			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names,   cv);
+			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, cv);
+			ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 3), memory_usings,  cv);
 			break;
 		}
 		case Type_Map: {
@@ -8281,15 +8263,15 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 
 				irValue *names = ir_emit_struct_ep(proc, tag, 0);
 				irValue *name_array_elem = ir_array_elem(proc, name_array);
-				ir_fill_slice(proc, names, name_array_elem, v_count, v_count);
+				ir_fill_slice(proc, names, name_array_elem, v_count);
 
 				irValue *bits = ir_emit_struct_ep(proc, tag, 1);
 				irValue *bit_array_elem = ir_array_elem(proc, bit_array);
-				ir_fill_slice(proc, bits, bit_array_elem, v_count, v_count);
+				ir_fill_slice(proc, bits, bit_array_elem, v_count);
 
 				irValue *offsets = ir_emit_struct_ep(proc, tag, 2);
 				irValue *offset_array_elem = ir_array_elem(proc, offset_array);
-				ir_fill_slice(proc, offsets, offset_array_elem, v_count, v_count);
+				ir_fill_slice(proc, offsets, offset_array_elem, v_count);
 			}
 			break;
 		}

+ 1 - 1
src/ir_print.cpp

@@ -323,7 +323,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
 	case Type_Slice:
 		ir_write_byte(f, '{');
 		ir_print_type(f, m, t->Slice.elem);
-		ir_fprintf(f, "*, i%lld, i%lld}", word_bits, word_bits);
+		ir_fprintf(f, "*, i%lld}", word_bits);
 		return;
 	case Type_DynamicArray:
 		ir_write_byte(f, '{');

+ 14 - 33
src/parser.cpp

@@ -192,10 +192,8 @@ AST_NODE_KIND(_ExprBegin,  "",  i32) \
 	AST_NODE_KIND(SliceExpr,    "slice expression", struct { \
 		AstNode *expr; \
 		Token open, close; \
-		Token interval0; \
-		Token interval1; \
-		bool index3; \
-		AstNode *low, *high, *max; \
+		Token interval; \
+		AstNode *low, *high; \
 	}) \
 	AST_NODE_KIND(CallExpr,     "call expression", struct { \
 		AstNode *    proc; \
@@ -714,7 +712,6 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
 		n->SliceExpr.expr = clone_ast_node(a, n->SliceExpr.expr);
 		n->SliceExpr.low  = clone_ast_node(a, n->SliceExpr.low);
 		n->SliceExpr.high = clone_ast_node(a, n->SliceExpr.high);
-		n->SliceExpr.max  = clone_ast_node(a, n->SliceExpr.max);
 		break;
 	case AstNode_CallExpr:
 		n->CallExpr.proc = clone_ast_node(a, n->CallExpr.proc);
@@ -1064,17 +1061,14 @@ AstNode *ast_index_expr(AstFile *f, AstNode *expr, AstNode *index, Token open, T
 }
 
 
-AstNode *ast_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, Token interval0, Token interval1, bool index3, AstNode *low, AstNode *high, AstNode *max) {
+AstNode *ast_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, Token interval, AstNode *low, AstNode *high) {
 	AstNode *result = make_ast_node(f, AstNode_SliceExpr);
 	result->SliceExpr.expr = expr;
 	result->SliceExpr.open = open;
 	result->SliceExpr.close = close;
-	result->SliceExpr.interval0 = interval0;
-	result->SliceExpr.interval1 = interval1;
-	result->SliceExpr.index3 = index3;
+	result->SliceExpr.interval = interval;
 	result->SliceExpr.low = low;
 	result->SliceExpr.high = high;
-	result->SliceExpr.max = max;
 	return result;
 }
 
@@ -2726,9 +2720,9 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) {
 			f->allow_range = false;
 
 			Token open = {}, close = {}, interval = {};
-			AstNode *indices[3] = {};
-			isize ellipsis_count = 0;
-			Token ellipses[2] = {};
+			AstNode *indices[2] = {};
+			Token ellipsis = {};
+			bool is_ellipsis = false;
 
 			f->expr_level++;
 			open = expect_token(f, Token_OpenBracket);
@@ -2739,15 +2733,15 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) {
 			}
 			bool is_index = true;
 
-			while ((f->curr_token.kind == Token_Ellipsis ||
-			        f->curr_token.kind == Token_HalfClosed)
-			        && ellipsis_count < gb_count_of(ellipses)) {
-				ellipses[ellipsis_count++] = advance_token(f);
+			if ((f->curr_token.kind == Token_Ellipsis ||
+			        f->curr_token.kind == Token_HalfClosed)) {
+				ellipsis = advance_token(f);
+				is_ellipsis = true;
 				if (f->curr_token.kind != Token_Ellipsis &&
 				    f->curr_token.kind != Token_HalfClosed &&
 				    f->curr_token.kind != Token_CloseBracket &&
 				    f->curr_token.kind != Token_EOF) {
-					indices[ellipsis_count] = parse_expr(f, false);
+					indices[1] = parse_expr(f, false);
 				}
 			}
 
@@ -2755,21 +2749,8 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) {
 			f->expr_level--;
 			close = expect_token(f, Token_CloseBracket);
 
-			if (ellipsis_count > 0) {
-				bool index3 = false;
-				if (ellipsis_count == 2) {
-					index3 = true;
-					// 2nd and 3rd index must be present
-					if (indices[1] == nullptr) {
-						syntax_error(ellipses[0], "2nd index required in 3-index slice expression");
-						indices[1] = ast_bad_expr(f, ellipses[0], ellipses[1]);
-					}
-					if (indices[2] == nullptr) {
-						syntax_error(ellipses[1], "3rd index required in 3-index slice expression");
-						indices[2] = ast_bad_expr(f, ellipses[1], close);
-					}
-				}
-				operand = ast_slice_expr(f, operand, open, close, ellipses[0], ellipses[1], index3, indices[0], indices[1], indices[2]);
+			if (is_ellipsis) {
+				operand = ast_slice_expr(f, operand, open, close, ellipsis, indices[0], indices[1]);
 			} else {
 				operand = ast_index_expr(f, operand, indices[0], open, close);
 			}

+ 3 - 2
src/types.cpp

@@ -327,6 +327,7 @@ gb_global Type *t_untyped_nil        = &basic_types[Basic_UntypedNil];
 gb_global Type *t_untyped_undef      = &basic_types[Basic_UntypedUndef];
 
 
+
 gb_global Type *t_u8_ptr       = nullptr;
 gb_global Type *t_int_ptr      = nullptr;
 gb_global Type *t_i64_ptr      = nullptr;
@@ -2127,8 +2128,8 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 	} break;
 
 
-	case Type_Slice: // ptr + count
-		return 3 * build_context.word_size;
+	case Type_Slice: // ptr + len
+		return 2 * build_context.word_size;
 
 	case Type_DynamicArray:
 		// data + len + cap + allocator(procedure+data)