Bläddra i källkod

Syntax change: cast(T)x => T(x); union_cast(T)x => x.(T); transmute(T)x => transmute(T, x); `y:=^x` => `y:=&x;`
Sorry for all the code breaking in this commit :(

Ginger Bill 8 år sedan
förälder
incheckning
784f3ecf7e
22 ändrade filer med 651 tillägg och 731 borttagningar
  1. 32 32
      core/_preload.odin
  2. 14 14
      core/decimal.odin
  3. 106 111
      core/fmt.odin
  4. 32 32
      core/hash.odin
  5. 10 10
      core/math.odin
  6. 11 11
      core/mem.odin
  7. 58 55
      core/opengl.odin
  8. 7 7
      core/os_linux.odin
  9. 48 48
      core/os_windows.odin
  10. 1 1
      core/raw.odin
  11. 43 46
      core/strconv.odin
  12. 3 3
      core/strings.odin
  13. 10 10
      core/sys/windows.odin
  14. 22 24
      core/types.odin
  15. 4 4
      core/utf16.odin
  16. 24 24
      core/utf8.odin
  17. 129 116
      src/check_expr.c
  18. 4 1
      src/checker.c
  19. 22 59
      src/ir.c
  20. 52 45
      src/parser.c
  21. 0 61
      src/ssa.c
  22. 19 17
      src/tokenizer.c

+ 32 - 32
core/_preload.odin

@@ -166,7 +166,7 @@ DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
 
 
 __check_context :: proc() {
-	c := ^__context;
+	c := &__context;
 
 	if c.allocator.procedure == nil {
 		c.allocator = default_allocator();
@@ -287,14 +287,14 @@ __string_eq :: proc(a, b: string) -> bool {
 	if len(a) == 0 {
 		return true;
 	}
-	if ^a[0] == ^b[0] {
+	if &a[0] == &b[0] {
 		return true;
 	}
 	return __string_cmp(a, b) == 0;
 }
 
 __string_cmp :: proc(a, b: string) -> int {
-	return __mem_compare(^a[0], ^b[0], min(len(a), len(b)));
+	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); }
@@ -360,9 +360,9 @@ __substring_expr_error :: proc(file: string, line, column: int, low, high: int)
 	            file, line, column, low, high);
 	__debug_trap();
 }
-__union_cast_check :: proc(ok: bool, file: string, line, column: int, from, to: ^Type_Info) {
+__type_assertion_check :: proc(ok: bool, file: string, line, column: int, from, to: ^Type_Info) {
 	if !ok {
-		fmt.fprintf(os.stderr, "%s(%d:%d) Invalid `union_cast` from %T to %T\n",
+		fmt.fprintf(os.stderr, "%s(%d:%d) Invalid type_assertion from %T to %T\n",
 		            file, line, column, from, to);
 		__debug_trap();
 	}
@@ -375,7 +375,7 @@ __string_decode_rune :: proc(s: string) -> (rune, int) #inline {
 
 __mem_set :: proc(data: rawptr, value: i32, len: int) -> rawptr {
 	llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memset.p0i8.i64";
-	llvm_memset_64bit(data, cast(byte)value, len, 1, false);
+	llvm_memset_64bit(data, byte(value), len, 1, false);
 	return data;
 }
 __mem_zero :: proc(data: rawptr, len: int) -> rawptr {
@@ -429,7 +429,7 @@ __abs_quaternion256 :: proc(x: quaternion256) -> f64 #inline {
 
 
 __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int) {
-	array := cast(^raw.Dynamic_Array)array_;
+	array := ^raw.Dynamic_Array(array_);
 	__check_context();
 	array.allocator = context.allocator;
 	assert(array.allocator.procedure != nil);
@@ -441,7 +441,7 @@ __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, ca
 }
 
 __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int) -> bool {
-	array := cast(^raw.Dynamic_Array)array_;
+	array := ^raw.Dynamic_Array(array_);
 
 	if cap <= array.cap {
 		return true;
@@ -468,7 +468,7 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap:
 }
 
 __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int) -> bool {
-	array := cast(^raw.Dynamic_Array)array_;
+	array := ^raw.Dynamic_Array(array_);
 
 	ok := __dynamic_array_reserve(array_, elem_size, elem_align, len);
 	if ok {
@@ -480,7 +480,7 @@ __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len:
 
 __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
                                items: rawptr, item_count: int) -> int {
-	array := cast(^raw.Dynamic_Array)array_;
+	array := ^raw.Dynamic_Array(array_);
 
 	if item_count <= 0 || items == nil {
 		return array.len;
@@ -496,7 +496,7 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
 		// TODO(bill): Better error handling for failed reservation
 		return array.len;
 	}
-	data := cast(^byte)array.data;
+	data := ^byte(array.data);
 	assert(data != nil);
 	__mem_copy(data + (elem_size*array.len), items, elem_size * item_count);
 	array.len += item_count;
@@ -504,7 +504,7 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
 }
 
 __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int) -> int {
-	array := cast(^raw.Dynamic_Array)array_;
+	array := ^raw.Dynamic_Array(array_);
 
 	ok := true;
 	if array.cap <= array.len+1 {
@@ -515,7 +515,7 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in
 		// TODO(bill): Better error handling for failed reservation
 		return array.len;
 	}
-	data := cast(^byte)array.data;
+	data := ^byte(array.data);
 	assert(data != nil);
 	__mem_zero(data + (elem_size*array.len), elem_size);
 	array.len++;
@@ -524,7 +524,7 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in
 
 __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int,
                        items: rawptr, item_count: int) -> int {
-	slice := cast(^raw.Slice)slice_;
+	slice := ^raw.Slice(slice_);
 
 	if item_count <= 0 || items == nil {
 		return slice.len;
@@ -532,7 +532,7 @@ __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int,
 
 	item_count = min(slice.cap-slice.len, item_count);
 	if item_count > 0 {
-		data := cast(^byte)slice.data;
+		data := ^byte(slice.data);
 		assert(data != nil);
 		__mem_copy(data + (elem_size*slice.len), items, elem_size * item_count);
 		slice.len += item_count;
@@ -547,14 +547,14 @@ __default_hash :: proc(data: []byte) -> u64 {
 	fnv64a :: proc(data: []byte) -> u64 {
 		h: u64 = 0xcbf29ce484222325;
 		for b in data {
-			h = (h ~ cast(u64)b) * 0x100000001b3;
+			h = (h ~ u64(b)) * 0x100000001b3;
 		}
 		return h;
 	}
 	return fnv64a(data);
 }
 __default_hash_string :: proc(s: string) -> u64 {
-	return __default_hash(cast([]byte)s);
+	return __default_hash([]byte(s));
 }
 
 __INITIAL_MAP_CAP :: 16;
@@ -588,20 +588,20 @@ __Map_Header :: struct #ordered {
 }
 
 __dynamic_map_reserve :: proc(using header: __Map_Header, cap: int)  {
-	__dynamic_array_reserve(^m.hashes, size_of(int), align_of(int), cap);
-	__dynamic_array_reserve(^m.entries, entry_size, entry_align,    cap);
+	__dynamic_array_reserve(&m.hashes, size_of(int), align_of(int), cap);
+	__dynamic_array_reserve(&m.entries, entry_size, entry_align,    cap);
 }
 
 __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) {
 	new_header: __Map_Header = header;
 	nm: raw.Dynamic_Map;
-	new_header.m = ^nm;
+	new_header.m = &nm;
 
-	header_hashes := cast(^raw.Dynamic_Array)^header.m.hashes;
-	nm_hashes := cast(^raw.Dynamic_Array)^nm.hashes;
+	header_hashes := ^raw.Dynamic_Array(&header.m.hashes);
+	nm_hashes := ^raw.Dynamic_Array(&nm.hashes);
 
 	__dynamic_array_resize(nm_hashes, size_of(int), align_of(int), new_count);
-	__dynamic_array_reserve(^nm.entries, entry_size, entry_align, m.entries.len);
+	__dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len);
 	for i in 0..<new_count {
 		nm.hashes[i] = -1;
 	}
@@ -612,7 +612,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) {
 		}
 
 		entry_header := __dynamic_map_get_entry(header, i);
-		data := cast(^byte)entry_header;
+		data := ^byte(entry_header);
 
 		fr := __dynamic_map_find(new_header, entry_header.key);
 		j := __dynamic_map_add_entry(new_header, entry_header.key);
@@ -625,7 +625,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) {
 
 		e := __dynamic_map_get_entry(new_header, j);
 		e.next = fr.entry_index;
-		ndata := cast(^byte)e;
+		ndata := ^byte(e);
 		__mem_copy(ndata+value_offset, data+value_offset, value_size);
 
 		if __dynamic_map_full(new_header) {
@@ -640,7 +640,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) {
 __dynamic_map_get :: proc(h: __Map_Header, key: __Map_Key) -> rawptr {
 	index := __dynamic_map_find(h, key).entry_index;
 	if index >= 0 {
-		data := cast(^byte)__dynamic_map_get_entry(h, index);
+		data := ^byte(__dynamic_map_get_entry(h, index));
 		val := data + h.value_offset;
 		return val;
 	}
@@ -672,7 +672,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(^byte)e + value_offset;
+		val := ^byte(e) + value_offset;
 		__mem_copy(val, value, value_size);
 	}
 
@@ -688,7 +688,7 @@ __dynamic_map_grow :: proc(using h: __Map_Header) {
 }
 
 __dynamic_map_full :: proc(using h: __Map_Header) -> bool {
-	return cast(int)(0.75 * cast(f64)len(m.hashes)) <= m.entries.cap;
+	return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
 }
 
 
@@ -705,7 +705,7 @@ __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 len(m.hashes) > 0 {
-		fr.hash_index = cast(int)(key.hash % cast(u64)len(m.hashes));
+		fr.hash_index = int(key.hash % 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);
@@ -721,7 +721,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.len;
-	c := __dynamic_array_append_nothing(^m.entries, entry_size, entry_align);
+	c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align);
 	if c != prev {
 		end := __dynamic_map_get_entry(h, c-1);
 		end.key = key;
@@ -739,8 +739,8 @@ __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 {
-	data := cast(^byte)m.entries.data + index*entry_size;
-	return cast(^__Map_Entry_Header)data;
+	data := ^byte(m.entries.data) + index*entry_size;
+	return ^__Map_Entry_Header(data);
 }
 
 __dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) {

+ 14 - 14
core/decimal.odin

@@ -26,7 +26,7 @@ decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string {
 
 	if a.count == 0 {
 		buf[0] = '0';
-		return cast(string)buf[0..<1];
+		return string(buf[0..<1]);
 	}
 
 	w := 0;
@@ -44,7 +44,7 @@ decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string {
 		w += digit_zero(buf[w ..< w+a.decimal_point-a.count]);
 	}
 
-	return cast(string)buf[0..<w];
+	return string(buf[0..<w]);
 }
 
 // trim trailing zeros
@@ -64,7 +64,7 @@ assign :: proc(a: ^Decimal, i: u64) {
 	for i > 0 {
 		j := i/10;
 		i -= 10*j;
-		buf[n] = cast(byte)('0'+i);
+		buf[n] = byte('0'+i);
 		n++;
 		i = j;
 	}
@@ -99,7 +99,7 @@ shift_right :: proc(a: ^Decimal, k: uint) {
 			}
 			break;
 		}
-		c := cast(uint)a.digits[r];
+		c := uint(a.digits[r]);
 		n = n*10 + c - '0';
 	}
 	a.decimal_point -= r-1;
@@ -107,10 +107,10 @@ shift_right :: proc(a: ^Decimal, k: uint) {
 	mask: uint = (1<<k) - 1;
 
 	for ; r < a.count; r++ {
-		c := cast(uint)a.digits[r];
+		c := uint(a.digits[r]);
 		dig := n>>k;
 		n &= mask;
-		a.digits[w] = cast(byte)('0' + dig);
+		a.digits[w] = byte('0' + dig);
 		w++;
 		n = n*10 + c - '0';
 	}
@@ -119,7 +119,7 @@ shift_right :: proc(a: ^Decimal, k: uint) {
 		dig := n>>k;
 		n &= mask;
 		if w < len(a.digits) {
-			a.digits[w] = cast(byte)('0' + dig);
+			a.digits[w] = byte('0' + dig);
 			w++;
 		} else if dig > 0 {
 			a.trunc = true;
@@ -133,19 +133,19 @@ shift_right :: proc(a: ^Decimal, k: uint) {
 }
 
 shift_left :: proc(a: ^Decimal, k: uint) {
-	delta := cast(int)(k/4);
+	delta := int(k/4);
 
 	r := a.count;       // read index
 	w := a.count+delta; // write index
 
 	n: uint;
 	for r--; r >= 0; r-- {
-		n += (cast(uint)a.digits[r] - '0') << k;
+		n += (uint(a.digits[r]) - '0') << k;
 		quo := n/10;
 		rem := n - 10*quo;
 		w--;
 		if w < len(a.digits) {
-			a.digits[w] = cast(byte)('0' + rem);
+			a.digits[w] = byte('0' + rem);
 		} else if rem != 0 {
 			a.trunc = true;
 		}
@@ -157,7 +157,7 @@ shift_left :: proc(a: ^Decimal, k: uint) {
 		rem := n - 10*quo;
 		w--;
 		if 0 <= w && w < len(a.digits) {
-			a.digits[w] = cast(byte)('0' + rem);
+			a.digits[w] = byte('0' + rem);
 		} else if rem != 0 {
 			a.trunc = true;
 		}
@@ -179,7 +179,7 @@ shift :: proc(a: ^Decimal, k: int) {
 			shift_left(a, max_shift);
 			k -= max_shift;
 		}
-		shift_left(a, cast(uint)k);
+		shift_left(a, uint(k));
 
 
 	case k < 0:
@@ -187,7 +187,7 @@ shift :: proc(a: ^Decimal, k: int) {
 			shift_right(a, max_shift);
 			k += max_shift;
 		}
-		shift_right(a, cast(uint)-k);
+		shift_right(a, uint(-k));
 	}
 }
 
@@ -245,7 +245,7 @@ rounded_integer :: proc(a: ^Decimal) -> u64 {
 	n: u64 = 0;
 	m := min(a.decimal_point, a.count);
 	for i = 0; i < m; i++ {
-		n = n*10 + cast(u64)(a.digits[i]-'0');
+		n = n*10 + u64(a.digits[i]-'0');
 	}
 	for ; i < a.decimal_point; i++ {
 		n *= 10;

+ 106 - 111
core/fmt.odin

@@ -37,12 +37,12 @@ string_buffer_data :: proc(buf: String_Buffer) -> []byte {
 	return buf.sa[..];
 }
 to_string :: proc(buf: String_Buffer) -> string {
-	return cast(string)string_buffer_data(buf);
+	return string(string_buffer_data(buf));
 }
 
 
 write_string :: proc(buf: ^String_Buffer, s: string) {
-	write_bytes(buf, cast([]byte)s);
+	write_bytes(buf, []byte(s));
 }
 write_bytes :: proc(buf: ^String_Buffer, b: []byte) {
 	if buf.is_dynamic {
@@ -60,7 +60,7 @@ write_byte :: proc(buf: ^String_Buffer, b: byte) {
 }
 write_rune :: proc(buf: ^String_Buffer, r: rune) {
 	if r < utf8.RUNE_SELF {
-		write_byte(buf, cast(byte)r);
+		write_byte(buf, byte(r));
 		return;
 	}
 
@@ -92,7 +92,7 @@ Fmt_Info :: struct {
 fprint :: proc(fd: os.Handle, args: ..any) -> int {
 	data: [_BUFFER_SIZE]byte;
 	buf := make_string_buffer_from_slice(data[0..<0]);
-	sbprint(^buf, ..args);
+	sbprint(&buf, ..args);
 	res := string_buffer_data(buf);
 	os.write(fd, res);
 	return len(res);
@@ -101,7 +101,7 @@ fprint :: proc(fd: os.Handle, args: ..any) -> int {
 fprintln :: proc(fd: os.Handle, args: ..any) -> int {
 	data: [_BUFFER_SIZE]byte;
 	buf := make_string_buffer_from_slice(data[0..<0]);
-	sbprintln(^buf, ..args);
+	sbprintln(&buf, ..args);
 	res := string_buffer_data(buf);
 	os.write(fd, res);
 	return len(res);
@@ -109,7 +109,7 @@ fprintln :: proc(fd: os.Handle, args: ..any) -> int {
 fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
 	data: [_BUFFER_SIZE]byte;
 	buf := make_string_buffer_from_slice(data[0..<0]);
-	sbprintf(^buf, fmt, ..args);
+	sbprintf(&buf, fmt, ..args);
 	res := string_buffer_data(buf);
 	os.write(fd, res);
 	return len(res);
@@ -131,17 +131,17 @@ printf :: proc(fmt: string, args: ..any) -> int {
 // They must be freed accordingly
 aprint :: proc(args: ..any) -> string {
 	buf := make_string_dynamic_buffer();
-	sbprint(^buf, ..args);
+	sbprint(&buf, ..args);
 	return to_string(buf);
 }
 aprintln :: proc(args: ..any) -> string {
 	buf := make_string_dynamic_buffer();
-	sbprintln(^buf, ..args);
+	sbprintln(&buf, ..args);
 	return to_string(buf);
 }
 aprintf :: proc(fmt: string, args: ..any) -> string {
 	buf := make_string_dynamic_buffer();
-	sbprintf(^buf, fmt, ..args);
+	sbprintf(&buf, fmt, ..args);
 	return to_string(buf);
 }
 
@@ -153,15 +153,15 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
 // They must be freed accordingly
 bprint :: proc(buf: []byte, args: ..any) -> int {
 	sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
-	return sbprint(^sb, ..args);
+	return sbprint(&sb, ..args);
 }
 bprintln :: proc(buf: []byte, args: ..any) -> int {
 	sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
-	return sbprintln(^sb, ..args);
+	return sbprintln(&sb, ..args);
 }
 bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> int {
 	sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
-	return sbprintf(^sb, fmt, ..args);
+	return sbprintf(&sb, fmt, ..args);
 }
 
 
@@ -172,7 +172,7 @@ bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> int {
 fprint_type :: proc(fd: os.Handle, info: ^Type_Info) {
 	data: [_BUFFER_SIZE]byte;
 	buf := make_string_buffer_from_slice(data[0..<0]);
-	write_type(^buf, info);
+	write_type(&buf, info);
 	os.write(fd, string_buffer_data(buf));
 }
 
@@ -192,7 +192,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 		default:
 			write_string(buf, info.signed ? "i" : "u");
 			fi := Fmt_Info{buf = buf};
-			fmt_int(^fi, cast(u64)(8*info.size), false, 64, 'd');
+			fmt_int(&fi, u64(8*info.size), false, 64, 'd');
 		}
 
 	case Float:
@@ -228,7 +228,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 		if info.params == nil {
 			write_string(buf, "()");
 		} else {
-			t := union_cast(^Tuple)info.params;
+			t := info.params.(^Tuple);
 			write_string(buf, "(");
 			for type, i in t.types {
 				if i > 0 { write_string(buf, ", "); }
@@ -259,7 +259,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 	case Array:
 		write_string(buf, "[");
 		fi := Fmt_Info{buf = buf};
-		fmt_int(^fi, cast(u64)info.count, false, 64, 'd');
+		fmt_int(&fi, u64(info.count), false, 64, 'd');
 		write_string(buf, "]");
 		write_type(buf, info.elem);
 	case Dynamic_Array:
@@ -271,7 +271,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 	case Vector:
 		write_string(buf, "[vector ");
 		fi := Fmt_Info{buf = buf};
-		fmt_int(^fi, cast(u64)info.count, false, 64, 'd');
+		fmt_int(&fi, u64(info.count), false, 64, 'd');
 		write_string(buf, "]");
 		write_type(buf, info.elem);
 
@@ -288,7 +288,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 		if info.custom_align {
 			write_string(buf, "#align ");
 			fi := Fmt_Info{buf = buf};
-			fmt_int(^fi, cast(u64)info.align, false, 64, 'd');
+			fmt_int(&fi, u64(info.align), false, 64, 'd');
 			write_byte(buf, ' ');
 		}
 		write_byte(buf, '{');
@@ -324,7 +324,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 			defer write_byte(buf, '}');
 
 			variant_type := type_info_base(info.variant_types[i]);
-			variant := union_cast(^Struct)variant_type;
+			variant := variant_type.(^Struct);
 
 			vc := len(variant.names)-len(cf.names);
 			for j in 0..vc {
@@ -376,26 +376,21 @@ _parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: boo
 	ok := true;
 
 	i := 0;
-	for o in offset..len(s) {
-		c := cast(rune)s[offset+i];
+	for i < len(s[offset..]) {
+		c := rune(s[offset+i]);
 		if !is_digit(c) {
 			break;
 		}
 		i++;
 
 		result *= 10;
-		result += cast(int)(c - '0');
+		result += int(c)-'0';
 	}
 
 	return result, offset+i, i != 0;
 }
 
-_arg_number :: proc(fi: ^Fmt_Info,
-                    arg_index: int,
-                    format: string,
-                    offset: int,
-                    arg_count: int,
-                    ) -> (index: int, offset: int, ok: bool) {
+_arg_number :: proc(fi: ^Fmt_Info, arg_index: int, format: string, offset, arg_count: int) -> (index, offset: int, ok: bool) {
 	parse_arg_number :: proc(format: string) -> (int, int, bool) {
 		if len(format) < 3 {
 			return 0, 1, false;
@@ -436,14 +431,14 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
 		arg.type_info = type_info_base(arg.type_info);
 		match i in arg {
 		case int:  num = i;
-		case i8:   num = cast(int)i;
-		case i16:  num = cast(int)i;
-		case i32:  num = cast(int)i;
-		case i64:  num = cast(int)i;
-		case u8:   num = cast(int)i;
-		case u16:  num = cast(int)i;
-		case u32:  num = cast(int)i;
-		case u64:  num = cast(int)i;
+		case i8:   num = int(i);
+		case i16:  num = int(i);
+		case i32:  num = int(i);
+		case i64:  num = int(i);
+		case u8:   num = int(i);
+		case u16:  num = int(i);
+		case u32:  num = int(i);
+		case u64:  num = int(i);
 		default:
 			ok = false;
 		}
@@ -500,25 +495,25 @@ is_integer_negative :: proc(u: u64, is_signed: bool, bit_size: int) -> (unsigned
 	if is_signed {
 		match bit_size {
 		case 8:
-			i := cast(i8)u;
+			i := i8(u);
 			neg = i < 0;
 			if neg { i = -i; }
-			u = cast(u64)i;
+			u = u64(i);
 		case 16:
-			i := cast(i16)u;
+			i := i16(u);
 			neg = i < 0;
 			if neg { i = -i; }
-			u = cast(u64)i;
+			u = u64(i);
 		case 32:
-			i := cast(i32)u;
+			i := i32(u);
 			neg = i < 0;
 			if neg { i = -i; }
-			u = cast(u64)i;
+			u = u64(i);
 		case 64:
-			i := cast(i64)u;
+			i := i64(u);
 			neg = i < 0;
 			if neg { i = -i; }
-			u = cast(u64)i;
+			u = u64(i);
 		default:
 			panic("is_integer_negative: Unknown integer size");
 		}
@@ -592,9 +587,9 @@ fmt_int :: proc(fi: ^Fmt_Info, u: u64, is_signed: bool, bit_size: int, verb: run
 	case 'x': _write_int(fi, u, 16, is_signed, bit_size, __DIGITS_LOWER);
 	case 'X': _write_int(fi, u, 16, is_signed, bit_size, __DIGITS_UPPER);
 	case 'c', 'r':
-		fmt_rune(fi, cast(rune)u);
+		fmt_rune(fi, rune(u));
 	case 'U':
-		r := cast(rune)u;
+		r := rune(u);
 		if r < 0 || r > utf8.MAX_RUNE {
 			fmt_bad_verb(fi, verb);
 		} else {
@@ -634,7 +629,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[0..<len(str)];
+		str = string(buf[0..<len(str)]);
 		if str[1] == '+' || str[1] == '-' {
 			str = str[1..];
 		} else {
@@ -645,7 +640,7 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) {
 			str[0] = ' ';
 		}
 
-		if str[1] == 'N' && str[1] == 'I' {
+		if len(str) > 1 && str[1] == 'N' && str[1] == 'I' {
 			write_string(fi.buf, str);
 			return;
 		}
@@ -681,7 +676,7 @@ fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) {
 			if i > 0 && space {
 				write_byte(fi.buf, ' ');
 			}
-			_write_int(fi, cast(u64)s[i], 16, false, 8, verb == 'x' ? __DIGITS_LOWER : __DIGITS_UPPER);
+			_write_int(fi, u64(s[i]), 16, false, 8, verb == 'x' ? __DIGITS_LOWER : __DIGITS_UPPER);
 		}
 
 	default:
@@ -697,7 +692,7 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
 		fmt_bad_verb(fi, verb);
 		return;
 	}
-	u := cast(u64)cast(uint)p;
+	u := u64(uint(p));
 	if !fi.hash || verb == 'v' {
 		write_string(fi.buf, "0x");
 	}
@@ -725,18 +720,18 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			ok := false;
 			a := any{v.data, type_info_base(e.base)};
 			match v in a {
-			case i8:   i = cast(i64)v;
-			case i16:  i = cast(i64)v;
-			case i32:  i = cast(i64)v;
-			case i64:  i = cast(i64)v;
-			case int:  i = cast(i64)v;
-			case u8:   i = cast(i64)v;
-			case u16:  i = cast(i64)v;
-			case u32:  i = cast(i64)v;
-			case u64:  i = cast(i64)v;
-			case uint: i = cast(i64)v;
-			case f32:  f = cast(f64)v; i = transmute(i64)f;
-			case f64:  f = cast(f64)v; i = transmute(i64)f;
+			case i8:   i = i64(v);
+			case i16:  i = i64(v);
+			case i32:  i = i64(v);
+			case i64:  i = i64(v);
+			case int:  i = i64(v);
+			case u8:   i = i64(v);
+			case u16:  i = i64(v);
+			case u32:  i = i64(v);
+			case u64:  i = i64(v);
+			case uint: i = i64(v);
+			case f32:  f = f64(v); i = transmute(i64, f);
+			case f64:  f = f64(v); i = transmute(i64, f);
 			}
 
 			if types.is_string(e.base) {
@@ -794,8 +789,8 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 				}
 				write_string(fi.buf, b.names[i]);
 				write_string(fi.buf, " = ");
-				data := cast(^byte)v.data + b.offsets[i];
-				fmt_arg(fi, any{cast(rawptr)data, b.types[i]}, 'v');
+				data := ^byte(v.data) + b.offsets[i];
+				fmt_arg(fi, any{rawptr(data), b.types[i]}, 'v');
 			}
 			write_byte(fi.buf, '}');
 
@@ -812,9 +807,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 
 	case Pointer:
 		if v.type_info == type_info(^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 Atomic:
@@ -832,8 +827,8 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			if i > 0 {
 				write_string(fi.buf, ", ");
 			}
-			data := cast(^byte)v.data + i*info.elem_size;
-			fmt_arg(fi, any{cast(rawptr)data, info.elem}, 'v');
+			data := ^byte(v.data) + i*info.elem_size;
+			fmt_arg(fi, any{rawptr(data), info.elem}, 'v');
 		}
 
 	case Dynamic_Array:
@@ -844,13 +839,13 @@ 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;
+		array := (^raw.Dynamic_Array)(v.data);
 		for i in 0..<array.len {
 			if i > 0 {
 				write_string(fi.buf, ", ");
 			}
-			data := cast(^byte)array.data + i*info.elem_size;
-			fmt_arg(fi, any{cast(rawptr)data, info.elem}, 'v');
+			data := ^byte(array.data) + i*info.elem_size;
+			fmt_arg(fi, any{rawptr(data), info.elem}, 'v');
 		}
 
 	case Map:
@@ -861,30 +856,30 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 
 		write_string(fi.buf, "map[");
 		defer write_byte(fi.buf, ']');
-		entries := ^(cast(^raw.Dynamic_Map)v.data).entries;
-		gs := union_cast(^Struct)type_info_base(info.generated_struct);
-		ed := union_cast(^Dynamic_Array)type_info_base(gs.types[1]);
+		entries := &(^raw.Dynamic_Map(v.data).entries);
+		gs := type_info_base(info.generated_struct).(^Struct);
+		ed := type_info_base(gs.types[1]).(^Dynamic_Array);
 
-		entry_type := union_cast(^Struct)ed.elem;
+		entry_type := ed.elem.(^Struct);
 		entry_size := ed.elem_size;
 		for i in 0..<entries.len {
 			if i > 0 {
 				write_string(fi.buf, ", ");
 			}
-			data := cast(^byte)entries.data + i*entry_size;
+			data := ^byte(entries.data) + i*entry_size;
 
-			header := cast(^__Map_Entry_Header)data;
+			header := ^__Map_Entry_Header(data);
 			if types.is_string(info.key) {
 				write_string(fi.buf, header.key.str);
 			} else {
 				fi := Fmt_Info{buf = fi.buf};
-				fmt_arg(^fi, any{cast(rawptr)^header.key.hash, info.key}, 'v');
+				fmt_arg(&fi, any{rawptr(&header.key.hash), info.key}, 'v');
 			}
 
 			write_string(fi.buf, "=");
 
 			value := data + entry_type.offsets[2];
-			fmt_arg(fi, any{cast(rawptr)value, info.value}, 'v');
+			fmt_arg(fi, any{rawptr(value), info.value}, 'v');
 		}
 
 	case Slice:
@@ -895,13 +890,13 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 
 		write_byte(fi.buf, '[');
 		defer write_byte(fi.buf, ']');
-		slice := cast(^[]byte)v.data;
+		slice := (^[]byte)(v.data);
 		for _, i in slice {
 			if i > 0 {
 				write_string(fi.buf, ", ");
 			}
-			data := ^slice[0] + i*info.elem_size;
-			fmt_arg(fi, any{cast(rawptr)data, info.elem}, 'v');
+			data := &slice[0] + i*info.elem_size;
+			fmt_arg(fi, any{rawptr(data), info.elem}, 'v');
 		}
 
 	case Vector:
@@ -913,8 +908,8 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 				write_string(fi.buf, ", ");
 			}
 
-			data := cast(^byte)v.data + i*info.elem_size;
-			fmt_value(fi, any{cast(rawptr)data, info.elem}, 'v');
+			data := ^byte(v.data) + i*info.elem_size;
+			fmt_value(fi, any{rawptr(data), info.elem}, 'v');
 		}
 
 	case Struct:
@@ -927,8 +922,8 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			}
 			write_string(fi.buf, info.names[i]);
 			write_string(fi.buf, " = ");
-			data := cast(^byte)v.data + info.offsets[i];
-			fmt_value(fi, any{cast(rawptr)data, info.types[i]}, 'v');
+			data := ^byte(v.data) + info.offsets[i];
+			fmt_value(fi, any{rawptr(data), info.types[i]}, 'v');
 		}
 
 	case Union:
@@ -943,8 +938,8 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			}
 			write_string(fi.buf, cf.names[i]);
 			write_string(fi.buf, " = ");
-			data := cast(^byte)v.data + cf.offsets[i];
-			fmt_value(fi, any{cast(rawptr)data, cf.types[i]}, 'v');
+			data := ^byte(v.data) + cf.offsets[i];
+			fmt_value(fi, any{rawptr(data), cf.types[i]}, 'v');
 		}
 
 	case Raw_Union:
@@ -956,7 +951,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 	case 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');
 	}
 }
 
@@ -1027,23 +1022,23 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
 	match a in base_arg {
 	case any:           fmt_arg(fi, a, verb);
 	case bool:          fmt_bool(fi, a, verb);
-	case f32:           fmt_float(fi, cast(f64)a, 32, verb);
+	case f32:           fmt_float(fi, f64(a), 32, verb);
 	case f64:           fmt_float(fi, a, 64, verb);
-	case complex64:     fmt_complex(fi, cast(complex128)a, 64, verb);
+	case complex64:     fmt_complex(fi, complex128(a), 64, verb);
 	case complex128:    fmt_complex(fi, a, 128, verb);
-	case quaternion128: fmt_quaternion(fi, cast(quaternion256)a, 128, verb);
+	case quaternion128: fmt_quaternion(fi, quaternion256(a), 128, verb);
 	case quaternion256: fmt_quaternion(fi, a, 256, verb);
 
-	case int:     fmt_int(fi, cast(u64)a, true,  8*size_of(int), verb);
-	case i8:      fmt_int(fi, cast(u64)a, true,  8, verb);
-	case i16:     fmt_int(fi, cast(u64)a, true,  16, verb);
-	case i32:     fmt_int(fi, cast(u64)a, true,  32, verb);
-	case i64:     fmt_int(fi, cast(u64)a, true,  64, verb);
-	case uint:    fmt_int(fi, cast(u64)a, false, 8*size_of(uint), verb);
-	case u8:      fmt_int(fi, cast(u64)a, false, 8, verb);
-	case u16:     fmt_int(fi, cast(u64)a, false, 16, verb);
-	case u32:     fmt_int(fi, cast(u64)a, false, 32, verb);
-	case u64:     fmt_int(fi, cast(u64)a, false, 64, verb);
+	case int:     fmt_int(fi, u64(a), true,  8*size_of(int), verb);
+	case i8:      fmt_int(fi, u64(a), true,  8, verb);
+	case i16:     fmt_int(fi, u64(a), true,  16, verb);
+	case i32:     fmt_int(fi, u64(a), true,  32, verb);
+	case i64:     fmt_int(fi, u64(a), true,  64, verb);
+	case uint:    fmt_int(fi, u64(a), false, 8*size_of(uint), verb);
+	case u8:      fmt_int(fi, u64(a), false, 8, verb);
+	case u16:     fmt_int(fi, u64(a), false, 16, verb);
+	case u32:     fmt_int(fi, u64(a), false, 32, verb);
+	case u64:     fmt_int(fi, u64(a), false, 64, verb);
 	case string:  fmt_string(fi, a, verb);
 	default:      fmt_value(fi, arg, verb);
 	}
@@ -1062,7 +1057,7 @@ sbprint :: proc(buf: ^String_Buffer, args: ..any) -> int {
 		if i > 0 && !is_string && !prev_string {
 			write_byte(buf, ' ');
 		}
-		fmt_value(^fi, args[i], 'v');
+		fmt_value(&fi, args[i], 'v');
 		prev_string = is_string;
 	}
 	return len(string_buffer_data(buf));
@@ -1076,7 +1071,7 @@ sbprintln :: proc(buf: ^String_Buffer, args: ..any) -> int {
 		if i > 0 {
 			write_byte(buf, ' ');
 		}
-		fmt_value(^fi, args[i], 'v');
+		fmt_value(&fi, args[i], 'v');
 	}
 	write_byte(buf, '\n');
 	return len(string_buffer_data(buf));
@@ -1123,7 +1118,7 @@ sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> int {
 			}
 		}
 
-		arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, len(args));
+		arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
 
 		// Width
 		if i < end && fmt[i] == '*' {
@@ -1153,7 +1148,7 @@ sbprintf :: proc(b: ^String_Buffer, 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, len(args));
+				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 {
@@ -1167,14 +1162,14 @@ sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> int {
 			} else {
 				fi.prec, i, fi.prec_set = _parse_int(fmt, i);
 				if !fi.prec_set {
-					fi.prec_set = true;
-					fi.prec = 0;
+					// fi.prec_set = true;
+					// fi.prec = 0;
 				}
 			}
 		}
 
 		if !was_prev_index {
-			arg_index, i, was_prev_index = _arg_number(^fi, arg_index, fmt, i, len(args));
+			arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
 		}
 
 		if i >= end {
@@ -1192,7 +1187,7 @@ sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> int {
 		} else if arg_index >= len(args) {
 			write_string(b, "%!(MISSING ARGUMENT)");
 		} else {
-			fmt_arg(^fi, args[arg_index], verb);
+			fmt_arg(&fi, args[arg_index], verb);
 			arg_index++;
 		}
 	}
@@ -1206,7 +1201,7 @@ sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> int {
 			if arg == nil {
 				write_string(b, "<nil>");
 			} else {
-				fmt_arg(^fi, args[index], 'v');
+				fmt_arg(&fi, args[index], 'v');
 			}
 		}
 		write_string(b, ")");

+ 32 - 32
core/hash.odin

@@ -1,14 +1,14 @@
 crc32 :: proc(data: []byte) -> u32 {
-	result := ~cast(u32)0;
+	result := ~u32(0);
 	for b in data {
-		result = result>>8 ~ _crc32_table[(result ~ cast(u32)b) & 0xff];
+		result = result>>8 ~ _crc32_table[(result ~ u32(b)) & 0xff];
 	}
 	return ~result;
 }
 crc64 :: proc(data: []byte) -> u64 {
-	result := ~cast(u64)0;
+	result := ~u64(0);
 	for b in data {
-		result = result>>8 ~ _crc64_table[(result ~ cast(u64)b) & 0xff];
+		result = result>>8 ~ _crc64_table[(result ~ u64(b)) & 0xff];
 	}
 	return ~result;
 }
@@ -16,7 +16,7 @@ crc64 :: proc(data: []byte) -> u64 {
 fnv32 :: proc(data: []byte) -> u32 {
 	h: u32 = 0x811c9dc5;
 	for b in data {
-		h = (h * 0x01000193) ~ cast(u32)b;
+		h = (h * 0x01000193) ~ u32(b);
 	}
 	return h;
 }
@@ -24,7 +24,7 @@ fnv32 :: proc(data: []byte) -> u32 {
 fnv64 :: proc(data: []byte) -> u64 {
 	h: u64 = 0xcbf29ce484222325;
 	for b in data {
-		h = (h * 0x100000001b3) ~ cast(u64)b;
+		h = (h * 0x100000001b3) ~ u64(b);
 	}
 	return h;
 }
@@ -32,7 +32,7 @@ fnv64 :: proc(data: []byte) -> u64 {
 fnv32a :: proc(data: []byte) -> u32 {
 	h: u32 = 0x811c9dc5;
 	for b in data {
-		h = (h ~ cast(u32)b) * 0x01000193;
+		h = (h ~ u32(b)) * 0x01000193;
 	}
 	return h;
 }
@@ -40,7 +40,7 @@ fnv32a :: proc(data: []byte) -> u32 {
 fnv64a :: proc(data: []byte) -> u64 {
 	h: u64 = 0xcbf29ce484222325;
 	for b in data {
-		h = (h ~ cast(u64)b) * 0x100000001b3;
+		h = (h ~ u64(b)) * 0x100000001b3;
 	}
 	return h;
 }
@@ -51,11 +51,11 @@ murmur32 :: proc(data: []byte) -> u32 {
 
 	h1: u32 = 0;
 	nblocks := len(data)/4;
-	p := ^data[0];
+	p := &data[0];
 	p1 := p + 4*nblocks;
 
 	for ; p < p1; p += 4 {
-		k1 := (cast(^u32)p)^;
+		k1 := ^u32(p)^;
 
 		k1 *= c1_32;
 		k1 = (k1 << 15) | (k1 >> 17);
@@ -71,20 +71,20 @@ murmur32 :: proc(data: []byte) -> u32 {
 	k1: u32;
 	match len(tail)&3 {
 	case 3:
-		k1 ~= cast(u32)tail[2] << 16;
+		k1 ~= u32(tail[2]) << 16;
 		fallthrough;
 	case 2:
-		k1 ~= cast(u32)tail[2] << 8;
+		k1 ~= u32(tail[2]) << 8;
 		fallthrough;
 	case 1:
-		k1 ~= cast(u32)tail[0];
+		k1 ~= u32(tail[0]);
 		k1 *= c1_32;
 		k1 = (k1 << 15) | (k1 >> 17) ;
 		k1 *= c2_32;
 		h1 ~= k1;
 	}
 
-	h1 ~= cast(u32)len(data);
+	h1 ~= u32(len(data));
 
 	h1 ~= h1 >> 16;
 	h1 *= 0x85ebca6b;
@@ -98,12 +98,12 @@ murmur32 :: proc(data: []byte) -> u32 {
 murmur64 :: proc(data: []byte) -> u64 {
 	SEED :: 0x9747b28c;
 
-	when false && size_of(int) == 8 {
+	when size_of(int) == 8 {
 		m :: 0xc6a4a7935bd1e995;
 		r :: 47;
 
-		h: u64 = SEED ~ (cast(u64)data.count * m);
-		data64 := slice_ptr(cast(^u64)^data[0], data.count/size_of(u64));
+		h: u64 = SEED ~ (u64(len(data)) * m);
+		data64 := slice_ptr(^u64(&data[0]), len(data)/size_of(u64));
 
 		for _, i in data64 {
 			k := data64[i];
@@ -116,15 +116,15 @@ murmur64 :: proc(data: []byte) -> u64 {
 			h *= m;
 		}
 
-		match data.count&7 {
-		case 7: h ~= cast(u64)data[6] << 48; fallthrough;
-		case 6: h ~= cast(u64)data[5] << 40; fallthrough;
-		case 5: h ~= cast(u64)data[4] << 32; fallthrough;
-		case 4: h ~= cast(u64)data[3] << 24; fallthrough;
-		case 3: h ~= cast(u64)data[2] << 16; fallthrough;
-		case 2: h ~= cast(u64)data[1] << 8;  fallthrough;
+		match len(data)&7 {
+		case 7: h ~= u64(data[6]) << 48; fallthrough;
+		case 6: h ~= u64(data[5]) << 40; fallthrough;
+		case 5: h ~= u64(data[4]) << 32; fallthrough;
+		case 4: h ~= u64(data[3]) << 24; fallthrough;
+		case 3: h ~= u64(data[2]) << 16; fallthrough;
+		case 2: h ~= u64(data[1]) << 8;  fallthrough;
 		case 1:
-			h ~= cast(u64)data[0];
+			h ~= u64(data[0]);
 			h *= m;
 		}
 
@@ -137,10 +137,10 @@ murmur64 :: proc(data: []byte) -> u64 {
 		m :: 0x5bd1e995;
 		r :: 24;
 
-		h1: u32 = cast(u32)SEED ~ cast(u32)len(data);
-		h2: u32 = SEED >> 32;
+		h1 := u32(SEED) ~ u32(len(data));
+		h2 := u32(SEED) >> 32;
 
-		data32 := slice_ptr(cast(^u32)^data[0], len(data)/size_of(u32));
+		data32 := slice_ptr(cast(^u32)&data[0], len(data)/size_of(u32));
 		len := len(data);
 
 		i := 0;
@@ -175,16 +175,16 @@ murmur64 :: proc(data: []byte) -> u64 {
 		}
 
 		// TODO(bill): Fix this
-		#no_bounds_check data8 := slice_to_bytes(data32[i..])[..<3];
+		#no_bounds_check data8 := slice_to_bytes(data32[i..])[0..<3];
 		match len {
 		case 3:
-			h2 ~= cast(u32)data8[2] << 16;
+			h2 ~= u32(data8[2]) << 16;
 			fallthrough;
 		case 2:
-			h2 ~= cast(u32)data8[1] << 8;
+			h2 ~= u32(data8[1]) << 8;
 			fallthrough;
 		case 1:
-			h2 ~= cast(u32)data8[0];
+			h2 ~= u32(data8[0]);
 			h2 *= m;
 		}
 

+ 10 - 10
core/math.odin

@@ -55,29 +55,29 @@ fmuladd :: proc(a, b, c: f64) -> f64 #foreign __llvm_core "llvm.fmuladd.f64";
 
 
 copy_sign :: proc(x, y: f32) -> f32 {
-	ix := transmute(u32)x;
-	iy := transmute(u32)y;
+	ix := transmute(u32, x);
+	iy := transmute(u32, y);
 	ix &= 0x7fff_ffff;
 	ix |= iy & 0x8000_0000;
-	return transmute(f32)ix;
+	return transmute(f32, ix);
 }
 
 copy_sign :: proc(x, y: f64) -> f64 {
-	ix := transmute(u64)x;
-	iy := transmute(u64)y;
+	ix := transmute(u64, x);
+	iy := transmute(u64, y);
 	ix &= 0x7fff_ffff_ffff_ff;
 	ix |= iy & 0x8000_0000_0000_0000;
-	return transmute(f64)ix;
+	return transmute(f64, ix);
 }
 
 round     :: proc(x: f32) -> f32 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
 round     :: proc(x: f64) -> f64 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
 
-floor     :: proc(x: f32) -> f32 { return x >= 0 ? cast(f32)cast(i64)x : cast(f32)cast(i64)(x-0.5); } // TODO: Get accurate versions
-floor     :: proc(x: f64) -> f64 { return x >= 0 ? cast(f64)cast(i64)x : cast(f64)cast(i64)(x-0.5); } // TODO: Get accurate versions
+floor     :: proc(x: f32) -> f32 { return x >= 0 ? f32(i64(x)) : f32(i64(x-0.5)); } // TODO: Get accurate versions
+floor     :: proc(x: f64) -> f64 { return x >= 0 ? f64(i64(x)) : f64(i64(x-0.5)); } // TODO: Get accurate versions
 
-ceil      :: proc(x: f32) -> f32 { return x <  0 ? cast(f32)cast(i64)x : cast(f32)cast(i64)(x+1); } // TODO: Get accurate versions
-ceil      :: proc(x: f64) -> f64 { return x <  0 ? cast(f64)cast(i64)x : cast(f64)cast(i64)(x+1); } // TODO: Get accurate versions
+ceil      :: proc(x: f32) -> f32 { return x <  0 ? f32(i64(x)) : f32(i64(x+1)); } // TODO: Get accurate versions
+ceil      :: proc(x: f64) -> f64 { return x <  0 ? f64(i64(x)) : f64(i64(x+1)); } // TODO: Get accurate versions
 
 remainder :: proc(x, y: f32) -> f32 { return x - round(x/y) * y; }
 remainder :: proc(x, y: f64) -> f64 { return x - round(x/y) * y; }

+ 11 - 11
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[0], ^b[0], min(len(a), len(b)));
+	return __mem_compare(&a[0], &b[0], min(len(a), len(b)));
 }
 
 
@@ -39,13 +39,13 @@ is_power_of_two :: proc(x: int) -> bool {
 align_forward :: proc(ptr: rawptr, align: int) -> rawptr {
 	assert(is_power_of_two(align));
 
-	a := cast(uint)align;
-	p := cast(uint)ptr;
+	a := uint(align);
+	p := uint(ptr);
 	modulo := p & (a-1);
 	if modulo != 0 {
 		p += a - modulo;
 	}
-	return cast(rawptr)p;
+	return rawptr(p);
 }
 
 
@@ -56,9 +56,9 @@ Allocation_Header :: struct {
 
 allocation_header_fill :: proc(header: ^Allocation_Header, data: rawptr, size: int) {
 	header.size = size;
-	ptr := cast(^int)(header+1);
+	ptr := ^int(header+1);
 
-	for i := 0; cast(rawptr)ptr < data; i++ {
+	for i := 0; rawptr(ptr) < data; i++ {
 		(ptr+i)^ = -1;
 	}
 }
@@ -66,11 +66,11 @@ allocation_header :: proc(data: rawptr) -> ^Allocation_Header {
 	if data == nil {
 		return nil;
 	}
-	p := cast(^int)data;
+	p := ^int(data);
 	for (p-1)^ == -1 {
 		p = (p-1);
 	}
-	return cast(^Allocation_Header)p-1;
+	return ^Allocation_Header(p-1);
 }
 
 
@@ -127,7 +127,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
                           size, alignment: int,
                           old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
 	using Allocator_Mode;
-	arena := cast(^Arena)allocator_data;
+	arena := ^Arena(allocator_data);
 
 	match mode {
 	case ALLOC:
@@ -138,7 +138,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 			return nil;
 		}
 
-		#no_bounds_check end := ^arena.memory[arena.offset];
+		#no_bounds_check end := &arena.memory[arena.offset];
 
 		ptr := align_forward(end, alignment);
 		arena.offset += total_size;
@@ -221,7 +221,7 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int {
 		return WORD_SIZE;
 	case Vector:
 		size := size_of_type_info(info.elem);
-		count := cast(int)max(prev_pow2(cast(i64)info.count), 1);
+		count := int(max(prev_pow2(i64(info.count)), 1));
 		total := size * count;
 		return clamp(total, 1, MAX_ALIGN);
 	case Tuple:

+ 58 - 55
core/opengl.odin

@@ -31,7 +31,7 @@ TexImage2D    :: proc(target, level, internal_format,
                       format, type: i32, pixels: rawptr)        #foreign lib "glTexImage2D";
 
 
-_string_data :: proc(s: string) -> ^u8 #inline { return ^s[0]; }
+_string_data :: proc(s: string) -> ^u8 #inline { return &s[0]; }
 
 _libgl := win32.LoadLibraryA(_string_data("opengl32.dll\x00"));
 
@@ -40,10 +40,10 @@ GetProcAddress :: proc(name: string) -> proc() #cc_c {
 		name = name[0..<len(name)-1];
 	}
 	// NOTE(bill): null terminated
-	assert((^name[0] + len(name))^ == 0);
-	res := wgl.GetProcAddress(^name[0]);
+	assert((&name[0] + len(name))^ == 0);
+	res := wgl.GetProcAddress(&name[0]);
 	if res == nil {
-		res = win32.GetProcAddress(_libgl, ^name[0]);
+		res = win32.GetProcAddress(_libgl, &name[0]);
 	}
 	return res;
 }
@@ -108,56 +108,59 @@ UniformMatrix4fv:         proc(loc: i32, count: u32, transpose: i32, value: ^f32
 GetUniformLocation:       proc(program: u32, name: ^byte) -> i32 #cc_c;
 
 init :: proc() {
-	set_proc_address :: proc(p: rawptr, name: string) #inline { (cast(^(proc() #cc_c))p)^ = GetProcAddress(name); }
-
-	set_proc_address(^GenBuffers,              "glGenBuffers\x00");
-	set_proc_address(^GenVertexArrays,         "glGenVertexArrays\x00");
-	set_proc_address(^GenSamplers,             "glGenSamplers\x00");
-	set_proc_address(^DeleteBuffers,           "glDeleteBuffers\x00");
-	set_proc_address(^BindBuffer,              "glBindBuffer\x00");
-	set_proc_address(^BindSampler,             "glBindSampler\x00");
-	set_proc_address(^BindVertexArray,         "glBindVertexArray\x00");
-	set_proc_address(^BufferData,              "glBufferData\x00");
-	set_proc_address(^BufferSubData,           "glBufferSubData\x00");
-
-	set_proc_address(^DrawArrays,              "glDrawArrays\x00");
-	set_proc_address(^DrawElements,            "glDrawElements\x00");
-
-	set_proc_address(^MapBuffer,               "glMapBuffer\x00");
-	set_proc_address(^UnmapBuffer,             "glUnmapBuffer\x00");
-
-	set_proc_address(^VertexAttribPointer,     "glVertexAttribPointer\x00");
-	set_proc_address(^EnableVertexAttribArray, "glEnableVertexAttribArray\x00");
-
-	set_proc_address(^CreateShader,            "glCreateShader\x00");
-	set_proc_address(^ShaderSource,            "glShaderSource\x00");
-	set_proc_address(^CompileShader,           "glCompileShader\x00");
-	set_proc_address(^CreateProgram,           "glCreateProgram\x00");
-	set_proc_address(^AttachShader,            "glAttachShader\x00");
-	set_proc_address(^DetachShader,            "glDetachShader\x00");
-	set_proc_address(^DeleteShader,            "glDeleteShader\x00");
-	set_proc_address(^LinkProgram,             "glLinkProgram\x00");
-	set_proc_address(^UseProgram,              "glUseProgram\x00");
-	set_proc_address(^DeleteProgram,           "glDeleteProgram\x00");
-
-	set_proc_address(^GetShaderiv,             "glGetShaderiv\x00");
-	set_proc_address(^GetProgramiv,            "glGetProgramiv\x00");
-	set_proc_address(^GetShaderInfoLog,        "glGetShaderInfoLog\x00");
-	set_proc_address(^GetProgramInfoLog,       "glGetProgramInfoLog\x00");
-
-	set_proc_address(^ActiveTexture,           "glActiveTexture\x00");
-	set_proc_address(^GenerateMipmap,          "glGenerateMipmap\x00");
-
-	set_proc_address(^Uniform1i,               "glUniform1i\x00");
-	set_proc_address(^UniformMatrix4fv,        "glUniformMatrix4fv\x00");
-
-	set_proc_address(^GetUniformLocation,      "glGetUniformLocation\x00");
-
-	set_proc_address(^SamplerParameteri,       "glSamplerParameteri\x00");
-	set_proc_address(^SamplerParameterf,       "glSamplerParameterf\x00");
-	set_proc_address(^SamplerParameteriv,      "glSamplerParameteriv\x00");
-	set_proc_address(^SamplerParameterfv,      "glSamplerParameterfv\x00");
-	set_proc_address(^SamplerParameterIiv,     "glSamplerParameterIiv\x00");
-	set_proc_address(^SamplerParameterIuiv,    "glSamplerParameterIuiv\x00");
+	set_proc_address :: proc(p: rawptr, name: string) #inline {
+		x := ^(proc() #cc_c)(p);
+		x^ = GetProcAddress(name);
+	}
+
+	set_proc_address(&GenBuffers,              "glGenBuffers\x00");
+	set_proc_address(&GenVertexArrays,         "glGenVertexArrays\x00");
+	set_proc_address(&GenSamplers,             "glGenSamplers\x00");
+	set_proc_address(&DeleteBuffers,           "glDeleteBuffers\x00");
+	set_proc_address(&BindBuffer,              "glBindBuffer\x00");
+	set_proc_address(&BindSampler,             "glBindSampler\x00");
+	set_proc_address(&BindVertexArray,         "glBindVertexArray\x00");
+	set_proc_address(&BufferData,              "glBufferData\x00");
+	set_proc_address(&BufferSubData,           "glBufferSubData\x00");
+
+	set_proc_address(&DrawArrays,              "glDrawArrays\x00");
+	set_proc_address(&DrawElements,            "glDrawElements\x00");
+
+	set_proc_address(&MapBuffer,               "glMapBuffer\x00");
+	set_proc_address(&UnmapBuffer,             "glUnmapBuffer\x00");
+
+	set_proc_address(&VertexAttribPointer,     "glVertexAttribPointer\x00");
+	set_proc_address(&EnableVertexAttribArray, "glEnableVertexAttribArray\x00");
+
+	set_proc_address(&CreateShader,            "glCreateShader\x00");
+	set_proc_address(&ShaderSource,            "glShaderSource\x00");
+	set_proc_address(&CompileShader,           "glCompileShader\x00");
+	set_proc_address(&CreateProgram,           "glCreateProgram\x00");
+	set_proc_address(&AttachShader,            "glAttachShader\x00");
+	set_proc_address(&DetachShader,            "glDetachShader\x00");
+	set_proc_address(&DeleteShader,            "glDeleteShader\x00");
+	set_proc_address(&LinkProgram,             "glLinkProgram\x00");
+	set_proc_address(&UseProgram,              "glUseProgram\x00");
+	set_proc_address(&DeleteProgram,           "glDeleteProgram\x00");
+
+	set_proc_address(&GetShaderiv,             "glGetShaderiv\x00");
+	set_proc_address(&GetProgramiv,            "glGetProgramiv\x00");
+	set_proc_address(&GetShaderInfoLog,        "glGetShaderInfoLog\x00");
+	set_proc_address(&GetProgramInfoLog,       "glGetProgramInfoLog\x00");
+
+	set_proc_address(&ActiveTexture,           "glActiveTexture\x00");
+	set_proc_address(&GenerateMipmap,          "glGenerateMipmap\x00");
+
+	set_proc_address(&Uniform1i,               "glUniform1i\x00");
+	set_proc_address(&UniformMatrix4fv,        "glUniformMatrix4fv\x00");
+
+	set_proc_address(&GetUniformLocation,      "glGetUniformLocation\x00");
+
+	set_proc_address(&SamplerParameteri,       "glSamplerParameteri\x00");
+	set_proc_address(&SamplerParameterf,       "glSamplerParameterf\x00");
+	set_proc_address(&SamplerParameteriv,      "glSamplerParameteriv\x00");
+	set_proc_address(&SamplerParameterfv,      "glSamplerParameterfv\x00");
+	set_proc_address(&SamplerParameterIiv,     "glSamplerParameterIiv\x00");
+	set_proc_address(&SamplerParameterIuiv,    "glSamplerParameterIuiv\x00");
 }
 

+ 7 - 7
core/os_linux.odin

@@ -58,7 +58,7 @@ Stat :: struct #ordered {
 	size:          i64, // Size of the file, in bytes
 	block_size:    i64, // Optimal bllocksize for I/O
 	blocks:        i64, // Number of 512-byte blocks allocated
-	
+
 	last_access:   _File_Time, // Time of last access
 	modified:      _File_Time, // Time of last modification
 	status_change: _File_Time, // Time of last status change
@@ -146,7 +146,7 @@ _unix_dlerror :: proc() -> ^u8
 
 // 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);
 	handle := _unix_open(cstr, mode);
 	free(cstr);
@@ -175,15 +175,15 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 }
 
 seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
-	res := _unix_seek(fd, offset, cast(i32)whence);
+	res := _unix_seek(fd, offset, i32(whence));
 	return res, 0;
 }
 
 
 // NOTE(bill): Uses startup to initialize it
-stdin:  Handle = 0; 
-stdout: Handle = 1; 
-stderr: Handle = 2; 
+stdin:  Handle = 0;
+stdout: Handle = 1;
+stderr: Handle = 2;
 
 /* TODO(zangent): Implement these!
 last_write_time :: proc(fd: Handle) -> File_Time {}
@@ -195,7 +195,7 @@ stat :: proc(path: string) -> (Stat, int) #inline {
 	cstr := strings.new_c_string(path);
 	defer free(cstr);
 	ret_int := _unix_stat(cstr, ^s);
-	return s, cast(int)ret_int;
+	return s, int(ret_int);
 }
 
 access :: proc(path: string, mask: int) -> bool #inline {

+ 48 - 48
core/os_windows.odin

@@ -73,11 +73,11 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
 		access |=  win32.FILE_APPEND_DATA;
 	}
 
-	share_mode := cast(u32)(win32.FILE_SHARE_READ|win32.FILE_SHARE_WRITE);
+	share_mode := u32(win32.FILE_SHARE_READ|win32.FILE_SHARE_WRITE);
 	sa: ^win32.Security_Attributes = nil;
 	sa_inherit := win32.Security_Attributes{length = size_of(win32.Security_Attributes), inherit_handle = 1};
 	if mode&O_CLOEXEC == 0 {
-		sa = ^sa_inherit;
+		sa = &sa_inherit;
 	}
 
 	create_mode: u32;
@@ -95,34 +95,34 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
 	}
 
 	buf: [300]byte;
-	copy(buf[..], cast([]byte)path);
+	copy(buf[..], []byte(path));
 
-	handle := cast(Handle)win32.CreateFileA(^buf[0], access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil);
+	handle := Handle(win32.CreateFileA(&buf[0], access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil));
 	if handle != INVALID_HANDLE {
 		return handle, ERROR_NONE;
 	}
 	err := win32.GetLastError();
-	return INVALID_HANDLE, cast(Errno)err;
+	return INVALID_HANDLE, Errno(err);
 }
 
 close :: proc(fd: Handle) {
-	win32.CloseHandle(cast(win32.Handle)fd);
+	win32.CloseHandle(win32.Handle(fd));
 }
 
 write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
-	return write(fd, cast([]byte)str);
+	return write(fd, []byte(str));
 }
 write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 	if len(data) == 0 {
 		return 0, ERROR_NONE;
 	}
 	bytes_written: i32;
-	e := win32.WriteFile(cast(win32.Handle)fd, ^data[0], cast(i32)len(data), ^bytes_written, nil);
+	e := win32.WriteFile(win32.Handle(fd), &data[0], i32(len(data)), &bytes_written, nil);
 	if e == win32.FALSE {
 		err := win32.GetLastError();
-		return 0, cast(Errno)err;
+		return 0, Errno(err);
 	}
-	return cast(int)bytes_written, ERROR_NONE;
+	return int(bytes_written), ERROR_NONE;
 }
 
 read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
@@ -130,12 +130,12 @@ read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 		return 0, ERROR_NONE;
 	}
 	bytes_read: i32;
-	e := win32.ReadFile(cast(win32.Handle)fd, ^data[0], cast(u32)len(data), ^bytes_read, nil);
+	e := win32.ReadFile(win32.Handle(fd), &data[0], u32(len(data)), &bytes_read, nil);
 	if e == win32.FALSE {
 		err := win32.GetLastError();
-		return 0, cast(Errno)err;
+		return 0, Errno(err);
 	}
-	return cast(int)bytes_read, ERROR_NONE;
+	return int(bytes_read), ERROR_NONE;
 }
 
 seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
@@ -145,18 +145,18 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
 	case 1: w = win32.FILE_CURRENT;
 	case 2: w = win32.FILE_END;
 	}
-	hi := cast(i32)(offset>>32);
-	lo := cast(i32)(offset);
-	ft := win32.GetFileType(cast(win32.Handle)fd);
+	hi := i32(offset>>32);
+	lo := i32(offset);
+	ft := win32.GetFileType(win32.Handle(fd));
 	if ft == win32.FILE_TYPE_PIPE {
 		return 0, ERROR_FILE_IS_PIPE;
 	}
-	dw_ptr := win32.SetFilePointer(cast(win32.Handle)fd, lo, ^hi, w);
+	dw_ptr := win32.SetFilePointer(win32.Handle(fd), lo, &hi, w);
 	if dw_ptr == win32.INVALID_SET_FILE_POINTER {
 		err := win32.GetLastError();
-		return 0, cast(Errno)err;
+		return 0, Errno(err);
 	}
-	return cast(i64)hi<<32 + cast(i64)dw_ptr, ERROR_NONE;
+	return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE;
 }
 
 
@@ -167,9 +167,9 @@ stderr := get_std_handle(win32.STD_ERROR_HANDLE);
 
 
 get_std_handle :: proc(h: int) -> Handle {
-	fd := win32.GetStdHandle(cast(i32)h);
+	fd := win32.GetStdHandle(i32(h));
 	win32.SetHandleInformation(fd, win32.HANDLE_FLAG_INHERIT, 0);
-	return cast(Handle)fd;
+	return Handle(fd);
 }
 
 
@@ -179,9 +179,9 @@ get_std_handle :: proc(h: int) -> Handle {
 
 last_write_time :: proc(fd: Handle) -> File_Time {
 	file_info: win32.By_Handle_File_Information;
-	win32.GetFileInformationByHandle(cast(win32.Handle)fd, ^file_info);
-	lo := cast(File_Time)file_info.last_write_time.lo;
-	hi := cast(File_Time)file_info.last_write_time.hi;
+	win32.GetFileInformationByHandle(win32.Handle(fd), &file_info);
+	lo := File_Time(file_info.last_write_time.lo);
+	hi := File_Time(file_info.last_write_time.hi);
 	return lo | hi << 32;
 }
 
@@ -192,21 +192,21 @@ last_write_time_by_name :: proc(name: string) -> File_Time {
 
 	assert(len(buf) > len(name));
 
-	copy(buf[..], cast([]byte)name);
+	copy(buf[..], []byte(name));
 
-	if win32.GetFileAttributesExA(^buf[0], win32.GetFileExInfoStandard, ^data) != 0 {
+	if win32.GetFileAttributesExA(&buf[0], win32.GetFileExInfoStandard, &data) != 0 {
 		last_write_time = data.last_write_time;
 	}
 
-	l := cast(File_Time)last_write_time.lo;
-	h := cast(File_Time)last_write_time.hi;
+	l := File_Time(last_write_time.lo);
+	h := File_Time(last_write_time.hi);
 	return l | h << 32;
 }
 
 
 read_entire_file :: proc(name: string) -> ([]byte, bool) {
 	buf: [300]byte;
-	copy(buf[..], cast([]byte)name);
+	copy(buf[..], []byte(name));
 
 	fd, err := open(name, O_RDONLY, 0);
 	if err != ERROR_NONE {
@@ -215,7 +215,7 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) {
 	defer close(fd);
 
 	length: i64;
-	if ok := win32.GetFileSizeEx(cast(win32.Handle)fd, ^length) != 0; !ok {
+	if ok := win32.GetFileSizeEx(win32.Handle(fd), &length) != 0; !ok {
 		return nil, false;
 	}
 
@@ -236,18 +236,18 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) {
 		to_read: u32;
 		MAX :: 1<<32-1;
 		if remaining <= MAX {
-			to_read = cast(u32)remaining;
+			to_read = u32(remaining);
 		} else {
 			to_read = MAX;
 		}
 
-		win32.ReadFile(cast(win32.Handle)fd, ^data[total_read], to_read, ^single_read_length, nil);
+		win32.ReadFile(win32.Handle(fd), &data[total_read], to_read, &single_read_length, nil);
 		if single_read_length <= 0 {
 			free(data);
 			return nil, false;
 		}
 
-		total_read += cast(i64)single_read_length;
+		total_read += i64(single_read_length);
 	}
 
 	return data, true;
@@ -277,13 +277,13 @@ heap_free :: proc(ptr: rawptr) {
 
 
 exit :: proc(code: int) {
-	win32.ExitProcess(cast(u32)code);
+	win32.ExitProcess(u32(code));
 }
 
 
 
 current_thread_id :: proc() -> int {
-	return cast(int)win32.GetCurrentThreadId();
+	return int(win32.GetCurrentThreadId());
 }
 
 
@@ -306,24 +306,24 @@ _alloc_command_line_arguments :: proc() -> []string {
 				if i+1 > len {
 					return "";
 				}
-				buf[i] = cast(byte)str[j]; i++;
+				buf[i] = byte(str[j]); i++;
 				j++;
 			case str[j] < 0x800:
 				if i+2 > len {
 					return "";
 				}
-				buf[i] = cast(byte)(0xc0 + (str[j]>>6));   i++;
-				buf[i] = cast(byte)(0x80 + (str[j]&0x3f)); i++;
+				buf[i] = byte(0xc0 + (str[j]>>6));   i++;
+				buf[i] = byte(0x80 + (str[j]&0x3f)); i++;
 				j++;
 			case 0xd800 <= str[j] && str[j] < 0xdc00:
 				if i+4 > len {
 					return "";
 				}
-				c := cast(rune)((str[j] - 0xd800) << 10) + cast(rune)((str[j+1]) - 0xdc00) + 0x10000;
-				buf[i] = cast(byte)(0xf0 +  (c >> 18));         i++;
-				buf[i] = cast(byte)(0x80 + ((c >> 12) & 0x3f)); i++;
-				buf[i] = cast(byte)(0x80 + ((c >>  6) & 0x3f)); i++;
-				buf[i] = cast(byte)(0x80 + ((c      ) & 0x3f)); i++;
+				c := rune((str[j] - 0xd800) << 10) + rune((str[j+1]) - 0xdc00) + 0x10000;
+				buf[i] = byte(0xf0 +  (c >> 18));         i++;
+				buf[i] = byte(0x80 + ((c >> 12) & 0x3f)); i++;
+				buf[i] = byte(0x80 + ((c >>  6) & 0x3f)); i++;
+				buf[i] = byte(0x80 + ((c      ) & 0x3f)); i++;
 				j += 2;
 			case 0xdc00 <= str[j] && str[j] < 0xe000:
 				return "";
@@ -331,18 +331,18 @@ _alloc_command_line_arguments :: proc() -> []string {
 				if i+3 > len {
 					return "";
 				}
-				buf[i] = 0xe0 + cast(byte) (str[j] >> 12);         i++;
-				buf[i] = 0x80 + cast(byte)((str[j] >>  6) & 0x3f); i++;
-				buf[i] = 0x80 + cast(byte)((str[j]      ) & 0x3f); i++;
+				buf[i] = 0xe0 + byte (str[j] >> 12);         i++;
+				buf[i] = 0x80 + byte((str[j] >>  6) & 0x3f); i++;
+				buf[i] = 0x80 + byte((str[j]      ) & 0x3f); i++;
 				j++;
 			}
 		}
 
-		return cast(string)buf[0..<i];
+		return string(buf[0..<i]);
 	}
 
 	arg_count: i32;
-	arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), ^arg_count);
+	arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), &arg_count);
 	arg_list := make([]string, arg_count);
 	for _, i in arg_list {
 		arg_list[i] = alloc_ucs2_to_utf8((arg_list_ptr+i)^);

+ 1 - 1
core/raw.odin

@@ -1,6 +1,6 @@
 Any :: struct #ordered {
-	type_info: ^Type_Info,
 	data:      rawptr,
+	type_info: ^Type_Info,
 }
 
 String :: struct #ordered {

+ 43 - 46
core/strconv.odin

@@ -19,15 +19,12 @@ parse_bool :: proc(s: string) -> (result: bool, ok: bool) {
 }
 
 _digit_value :: proc(r: rune) -> (int) {
-	ri := cast(int)r;
+	ri := int(r);
 	v: int = 16;
 	match r {
-	case '0'..'9':
-		v = ri - '0';
-	case 'a'..'z':
-		v = ri - 'a' + 10;
-	case 'A'..'Z':
-		v = ri - 'A' + 10;
+	case '0'..'9': v = ri-'0';
+	case 'a'..'z': v = ri-'a'+10;
+	case 'A'..'Z': v = ri-'A'+10;
 	}
 	return v;
 }
@@ -39,8 +36,8 @@ parse_i64 :: proc(s: string, base: int) -> i64 {
 		if v >= base {
 			break;
 		}
-		result *= cast(i64)base;
-		result += cast(i64)v;
+		result *= i64(base);
+		result += i64(v);
 	}
 	return result;
 }
@@ -51,35 +48,35 @@ parse_u64 :: proc(s: string, base: int) -> u64 {
 		if v >= base {
 			break;
 		}
-		result *= cast(u64)base;
-		result += cast(u64)v;
+		result *= u64(base);
+		result += u64(v);
 	}
 	return result;
 }
 parse_int :: proc(s: string, base: int) -> int {
-	return cast(int)parse_i64(s, base);
+	return int(parse_i64(s, base));
 }
 parse_uint :: proc(s: string, base: int) -> uint {
-	return cast(uint)parse_u64(s, base);
+	return uint(parse_u64(s, base));
 }
 
 
 append_bool :: proc(buf: []byte, b: bool) -> string {
 	s := b ? "true" : "false";
-	append(buf, ..cast([]byte)s);
-	return cast(string)buf;
+	append(buf, ..[]byte(s));
+	return string(buf);
 }
 
 append_uint :: proc(buf: []byte, u: u64, base: int) -> string {
 	return append_bits(buf, u, base, false, 8*size_of(uint), digits, 0);
 }
 append_int :: proc(buf: []byte, i: i64, base: int) -> string {
-	return append_bits(buf, cast(u64)i, base, true, 8*size_of(int), digits, 0);
+	return append_bits(buf, u64(i), base, true, 8*size_of(int), digits, 0);
 }
-itoa :: proc(buf: []byte, i: int) -> string { return append_int(buf, cast(i64)i, 10); }
+itoa :: proc(buf: []byte, i: int) -> string { return append_int(buf, i64(i), 10); }
 
 append_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string {
-	return cast(string)generic_ftoa(buf, f, fmt, prec, bit_size);
+	return string(generic_ftoa(buf, f, fmt, prec, bit_size));
 }
 
 
@@ -107,18 +104,18 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [
 	flt: ^Float_Info;
 	match bit_size {
 	case 32:
-		bits = cast(u64)transmute(u32)cast(f32)val;
-		flt = ^f32_info;
+		bits = u64(transmute(u32, f32(val)));
+		flt = &f32_info;
 	case 64:
-		bits = transmute(u64)val;
-		flt = ^f64_info;
+		bits = transmute(u64, val);
+		flt = &f64_info;
 	default:
 		panic("strconv: invalid bit_size");
 	}
 
 	neg := bits>>(flt.expbits+flt.mantbits) != 0;
-	exp := cast(int)(bits>>flt.mantbits) & (1<<flt.expbits - 1);
-	mant := bits & (cast(u64)1 << flt.mantbits - 1);
+	exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1);
+	mant := bits & (u64(1) << flt.mantbits - 1);
 
 	match exp {
 	case 1<<flt.expbits - 1:
@@ -130,22 +127,22 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [
 		} else {
 			s = "+Inf";
 		}
-		append(buf, ..cast([]byte)s);
+		append(buf, ..[]byte(s));
 		return buf;
 
 	case 0: // denormalized
 		exp++;
 
 	default:
-		mant |= cast(u64)1 << flt.mantbits;
+		mant |= u64(1) << flt.mantbits;
 	}
 
 	exp += flt.bias;
 
 	d_: Decimal;
-	d := ^d_;
+	d := &d_;
 	assign(d, mant);
-	shift(d, exp - cast(int)flt.mantbits);
+	shift(d, exp - int(flt.mantbits));
 	digs: Decimal_Slice;
 	shortest := prec < 0;
 	if shortest {
@@ -194,7 +191,7 @@ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slic
 		// fractional part
 		if prec > 0 {
 			append(buf, '.');
-			for i in 0..<prec {
+			for i in 0..prec {
 				c: byte = '0';
 				if j := digs.decimal_point + i; 0 <= j && j < digs.count {
 					c = digs.digits[j];
@@ -234,14 +231,14 @@ round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) {
 		332*(dp-nd) >= 100*(exp-mantbits)
 	 */
 	minexp := flt.bias+1;
-	if exp > minexp && 332*(d.decimal_point-d.count) >= 100*(exp - cast(int)flt.mantbits) {
+	if exp > minexp && 332*(d.decimal_point-d.count) >= 100*(exp - int(flt.mantbits)) {
 		// Number is already its shortest
 		return;
 	}
 
-	upper_: Decimal; upper: = ^upper_;
+	upper_: Decimal; upper: = &upper_;
 	assign(upper, 2*mant - 1);
-	shift(upper, exp - cast(int)flt.mantbits - 1);
+	shift(upper, exp - int(flt.mantbits) - 1);
 
 	mantlo: u64;
 	explo:  int;
@@ -252,9 +249,9 @@ round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) {
 		mantlo = 2*mant - 1;
 		explo = exp-1;
 	}
-	lower_: Decimal; lower: = ^lower_;
+	lower_: Decimal; lower: = &lower_;
 	assign(lower, 2*mantlo + 1);
-	shift(lower, explo - cast(int)flt.mantbits - 1);
+	shift(lower, explo - int(flt.mantbits) - 1);
 
 	inclusive := mant%2 == 0;
 
@@ -297,25 +294,25 @@ is_integer_negative :: proc(u: u64, is_signed: bool, bit_size: int) -> (unsigned
 	if is_signed {
 		match bit_size {
 		case 8:
-			i := cast(i8)u;
+			i := i8(u);
 			neg = i < 0;
 			if neg { i = -i; }
-			u = cast(u64)i;
+			u = u64(i);
 		case 16:
-			i := cast(i16)u;
+			i := i16(u);
 			neg = i < 0;
 			if neg { i = -i; }
-			u = cast(u64)i;
+			u = u64(i);
 		case 32:
-			i := cast(i32)u;
+			i := i32(u);
 			neg = i < 0;
 			if neg { i = -i; }
-			u = cast(u64)i;
+			u = u64(i);
 		case 64:
-			i := cast(i64)u;
+			i := i64(u);
 			neg = i < 0;
 			if neg { i = -i; }
-			u = cast(u64)i;
+			u = u64(i);
 		default:
 			panic("is_integer_negative: Unknown integer size");
 		}
@@ -342,15 +339,15 @@ append_bits :: proc(buf: []byte, u: u64, base: int, is_signed: bool, bit_size: i
 	neg: bool;
 	u, neg = is_integer_negative(u, is_signed, bit_size);
 
-	for b := cast(u64)base; u >= b; {
+	for b := u64(base); u >= b; {
 		i--;
 		q := u / b;
-		a[i] = digits[cast(uint)(u-q*b)];
+		a[i] = digits[uint(u-q*b)];
 		u = q;
 	}
 
 	i--;
-	a[i] = digits[cast(uint)u];
+	a[i] = digits[uint(u)];
 
 	if flags&Int_Flag.PREFIX != 0 {
 		ok := true;
@@ -378,6 +375,6 @@ append_bits :: proc(buf: []byte, u: u64, base: int, is_signed: bool, bit_size: i
 
 
 	append(buf, ..a[i..]);
-	return cast(string)buf;
+	return string(buf);
 }
 

+ 3 - 3
core/strings.odin

@@ -1,8 +1,8 @@
 new_c_string :: proc(s: string) -> ^byte {
 	c := make([]byte, len(s)+1);
-	copy(c, cast([]byte)s);
+	copy(c, []byte(s));
 	c[len(s)] = 0;
-	return ^c[0];
+	return &c[0];
 }
 
 to_odin_string :: proc(c: ^byte) -> string {
@@ -10,5 +10,5 @@ to_odin_string :: proc(c: ^byte) -> string {
 	for (c+len)^ != 0 {
 		len++;
 	}
-	return cast(string)slice_ptr(c, len);
+	return string(slice_ptr(c, len));
 }

+ 10 - 10
core/sys/windows.odin

@@ -21,7 +21,7 @@ Bool      :: i32;
 Wnd_Proc  :: #type proc(Hwnd, u32, Wparam, Lparam) -> Lresult #cc_c;
 
 
-INVALID_HANDLE :: cast(Handle)~cast(int)0;
+INVALID_HANDLE :: Handle(~int(0));
 
 FALSE: Bool : 0;
 TRUE:  Bool : 1;
@@ -56,7 +56,7 @@ WM_CHAR              :: 0x0102;
 
 PM_REMOVE :: 1;
 
-COLOR_BACKGROUND :: cast(Hbrush)(cast(int)1);
+COLOR_BACKGROUND :: Hbrush(int(1));
 BLACK_BRUSH :: 4;
 
 SM_CXSCREEN :: 0;
@@ -178,7 +178,7 @@ DescribePixelFormat :: proc(dc: Hdc, pixel_format: i32, bytes : u32, pfd: ^PIXEL
 
 GetQueryPerformanceFrequency :: proc() -> i64 {
 	r: i64;
-	QueryPerformanceFrequency(^r);
+	QueryPerformanceFrequency(&r);
 	return r;
 }
 
@@ -260,7 +260,7 @@ FILE_TYPE_DISK :: 0x0001;
 FILE_TYPE_CHAR :: 0x0002;
 FILE_TYPE_PIPE :: 0x0003;
 
-INVALID_SET_FILE_POINTER :: ~cast(u32)0;
+INVALID_SET_FILE_POINTER :: ~u32(0);
 
 
 
@@ -313,7 +313,7 @@ Hmonitor :: Handle;
 
 GWL_STYLE     :: -16;
 
-Hwnd_TOP :: cast(Hwnd)cast(uint)0;
+Hwnd_TOP :: Hwnd(uint(0));
 
 MONITOR_DEFAULTTONULL    :: 0x00000000;
 MONITOR_DEFAULTTOPRIMARY :: 0x00000001;
@@ -356,10 +356,10 @@ SetWindowLongPtrA :: proc(wnd: Hwnd, index: i32, new: i64) -> i64 #foreign user3
 
 GetWindowText :: proc(wnd: Hwnd, str: ^byte, maxCount: i32) -> i32 #foreign user32;
 
-HIWORD :: proc(wParam: Wparam) -> u16 { return cast(u16)((cast(u32)wParam >> 16) & 0xffff); }
-HIWORD :: proc(lParam: Lparam) -> u16 { return cast(u16)((cast(u32)lParam >> 16) & 0xffff); }
-LOWORD :: proc(wParam: Wparam) -> u16 { return cast(u16)wParam; }
-LOWORD :: proc(lParam: Lparam) -> u16 { return cast(u16)lParam; }
+HIWORD :: proc(wParam: Wparam) -> u16 { return u16((u32(wParam) >> 16) & 0xffff); }
+HIWORD :: proc(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff); }
+LOWORD :: proc(wParam: Wparam) -> u16 { return u16(wParam); }
+LOWORD :: proc(lParam: Lparam) -> u16 { return u16(lParam); }
 
 
 
@@ -477,7 +477,7 @@ Proc  :: #type proc() #cc_c;
 GetKeyState      :: proc(v_key: i32) -> i16 #foreign user32;
 GetAsyncKeyState :: proc(v_key: i32) -> i16 #foreign user32;
 
-is_key_down :: proc(key: Key_Code) -> bool #inline { return GetAsyncKeyState(cast(i32)key) < 0; }
+is_key_down :: proc(key: Key_Code) -> bool #inline { return GetAsyncKeyState(i32(key)) < 0; }
 
 Key_Code :: enum i32 {
 	LBUTTON    = 0x01,

+ 22 - 24
core/types.odin

@@ -1,100 +1,98 @@
 is_signed :: proc(info: ^Type_Info) -> bool {
-	info = type_info_base(info);
-	if i, ok := union_cast(^Type_Info.Integer)info; ok {
-		return i.signed;
-	}
-	if _, ok := union_cast(^Type_Info.Float)info; ok {
-		return true;
+	if info == nil { return false; }
+	match i in type_info_base(info) {
+	case Type_Info.Integer: return i.signed;
+	case Type_Info.Float:   return true;
 	}
 	return false;
 }
 is_integer :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Integer)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Integer);
 	return ok;
 }
 is_float :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Float)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Float);
 	return ok;
 }
 is_complex :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Complex)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Complex);
 	return ok;
 }
 is_any :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Any)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Any);
 	return ok;
 }
 is_string :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.String)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.String);
 	return ok;
 }
 is_boolean :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Boolean)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Boolean);
 	return ok;
 }
 is_pointer :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Pointer)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Pointer);
 	return ok;
 }
 is_procedure :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Procedure)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Procedure);
 	return ok;
 }
 is_array :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Array)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Array);
 	return ok;
 }
 is_dynamic_array :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Dynamic_Array)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Dynamic_Array);
 	return ok;
 }
 is_dynamic_map :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Map)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Map);
 	return ok;
 }
 is_slice :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Slice)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Slice);
 	return ok;
 }
 is_vector :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Vector)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Vector);
 	return ok;
 }
 is_tuple :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Tuple)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Tuple);
 	return ok;
 }
 is_struct :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Struct)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Struct);
 	return ok;
 }
 is_union :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Union)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Union);
 	return ok;
 }
 is_raw_union :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Raw_Union)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Raw_Union);
 	return ok;
 }
 is_enum :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
-	_, ok := union_cast(^Type_Info.Enum)type_info_base(info);
+	_, ok := type_info_base(info).(^Type_Info.Enum);
 	return ok;
 }

+ 4 - 4
core/utf16.odin

@@ -41,17 +41,17 @@ encode :: proc(d: []u16, s: []rune) {
 	for r in s {
 		match r {
 		case 0..<_surr1, _surr3..<_surr_self:
-			d[n] = cast(u16)r;
+			d[n] = u16(r);
 			n++;
 
 		case _surr_self..MAX_RUNE:
 			r1, r2 := encode_surrogate_pair(r);
-			d[n]    = cast(u16)r1;
-			d[n+1]  = cast(u16)r2;
+			d[n]    = u16(r1);
+			d[n+1]  = u16(r2);
 			n += 2;
 
 		default:
-			d[n] = cast(u16)REPLACEMENT_CHAR;
+			d[n] = u16(REPLACEMENT_CHAR);
 			n++;
 		}
 	}

+ 24 - 24
core/utf8.odin

@@ -1,7 +1,7 @@
 RUNE_ERROR :: '\ufffd';
 RUNE_SELF  :: 0x80;
 RUNE_BOM   :: 0xfeff;
-RUNE_EOF   :: ~cast(rune)0;
+RUNE_EOF   :: ~rune(0);
 MAX_RUNE   :: '\U0010ffff';
 UTF_MAX    :: 4;
 
@@ -60,15 +60,15 @@ immutable accept_sizes := [256]byte{
 
 encode_rune :: proc(r: rune) -> ([4]byte, int) {
 	buf: [4]byte;
-	i := cast(u32)r;
+	i := u32(r);
 	mask: byte : 0x3f;
 	if i <= 1<<7-1 {
-		buf[0] = cast(byte)r;
+		buf[0] = byte(r);
 		return buf, 1;
 	}
 	if i <= 1<<11-1 {
-		buf[0] = 0xc0 | cast(byte)(r>>6);
-		buf[1] = 0x80 | cast(byte)r & mask;
+		buf[0] = 0xc0 | byte(r>>6);
+		buf[1] = 0x80 | byte(r) & mask;
 		return buf, 2;
 	}
 
@@ -79,20 +79,20 @@ encode_rune :: proc(r: rune) -> ([4]byte, int) {
 	}
 
 	if i <= 1<<16-1 {
-		buf[0] = 0xe0 | cast(byte)(r>>12);
-		buf[1] = 0x80 | cast(byte)(r>>6) & mask;
-		buf[2] = 0x80 | cast(byte)r    & mask;
+		buf[0] = 0xe0 | byte(r>>12);
+		buf[1] = 0x80 | byte(r>>6) & mask;
+		buf[2] = 0x80 | byte(r)    & mask;
 		return buf, 3;
 	}
 
-	buf[0] = 0xf0 | cast(byte)(r>>18);
-	buf[1] = 0x80 | cast(byte)(r>>12) & mask;
-	buf[2] = 0x80 | cast(byte)(r>>6)  & mask;
-	buf[3] = 0x80 | cast(byte)r       & mask;
+	buf[0] = 0xf0 | byte(r>>18);
+	buf[1] = 0x80 | byte(r>>12) & mask;
+	buf[2] = 0x80 | byte(r>>6)  & mask;
+	buf[3] = 0x80 | byte(r)       & mask;
 	return buf, 4;
 }
 
-decode_rune :: proc(s: string) -> (rune, int) #inline { return decode_rune(cast([]byte)s); }
+decode_rune :: proc(s: string) -> (rune, int) #inline { return decode_rune([]byte(s)); }
 decode_rune :: proc(s: []byte) -> (rune, int) {
 	n := len(s);
 	if n < 1 {
@@ -101,12 +101,12 @@ decode_rune :: proc(s: []byte) -> (rune, int) {
 	s0 := s[0];
 	x := accept_sizes[s0];
 	if x >= 0xF0 {
-		mask := cast(rune)(x) << 31 >> 31; // NOTE(bill): Create 0x0000 or 0xffff.
-		return cast(rune)(s[0])&~mask | RUNE_ERROR&mask, 1;
+		mask := rune(x) << 31 >> 31; // NOTE(bill): Create 0x0000 or 0xffff.
+		return rune(s[0])&~mask | RUNE_ERROR&mask, 1;
 	}
 	sz := x & 7;
 	accept := accept_ranges[x>>4];
-	if n < cast(int)sz {
+	if n < int(sz) {
 		return RUNE_ERROR, 1;
 	}
 	b1 := s[1];
@@ -114,25 +114,25 @@ decode_rune :: proc(s: []byte) -> (rune, int) {
 		return RUNE_ERROR, 1;
 	}
 	if sz == 2 {
-		return cast(rune)(s0&MASK2)<<6 | cast(rune)(b1&MASKX), 2;
+		return rune(s0&MASK2)<<6 | rune(b1&MASKX), 2;
 	}
 	b2 := s[2];
 	if b2 < LOCB || HICB < b2 {
 		return RUNE_ERROR, 1;
 	}
 	if sz == 3 {
-		return cast(rune)(s0&MASK3)<<12 | cast(rune)(b1&MASKX)<<6 | cast(rune)(b2&MASKX), 3;
+		return rune(s0&MASK3)<<12 | rune(b1&MASKX)<<6 | rune(b2&MASKX), 3;
 	}
 	b3 := s[3];
 	if b3 < LOCB || HICB < b3 {
 		return RUNE_ERROR, 1;
 	}
-	return cast(rune)(s0&MASK4)<<18 | cast(rune)(b1&MASKX)<<12 | cast(rune)(b2&MASKX)<<6 | cast(rune)(b3&MASKX), 4;
+	return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4;
 }
 
 
 
-decode_last_rune :: proc(s: string) -> (rune, int) #inline { return decode_last_rune(cast([]byte)s); }
+decode_last_rune :: proc(s: string) -> (rune, int) #inline { return decode_last_rune([]byte(s)); }
 decode_last_rune :: proc(s: []byte) -> (rune, int) {
 	r: rune;
 	size: int;
@@ -143,7 +143,7 @@ decode_last_rune :: proc(s: []byte) -> (rune, int) {
 		return RUNE_ERROR, 0;
 	}
 	start = end-1;
-	r = cast(rune)s[start];
+	r = rune(s[start]);
 	if r < RUNE_SELF {
 		return r, 1;
 	}
@@ -194,7 +194,7 @@ valid_string :: proc(s: string) -> bool {
 		if x == 0xf1 {
 			return false;
 		}
-		size := cast(int)(x & 7);
+		size := int(x & 7);
 		if i+size > n {
 			return false;
 		}
@@ -217,7 +217,7 @@ valid_string :: proc(s: string) -> bool {
 
 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: string) -> int #inline { return rune_count([]byte(s)); }
 rune_count :: proc(s: []byte) -> int {
 	count := 0;
 	n := len(s);
@@ -234,7 +234,7 @@ rune_count :: proc(s: []byte) -> int {
 			i++;
 			continue;
 		}
-		size := cast(int)(x & 7);
+		size := int(x & 7);
 		if i+size > n {
 			i++;
 			continue;

+ 129 - 116
src/check_expr.c

@@ -1839,6 +1839,12 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
 			return false;
 		}
 		if (out_value) *out_value = v;
+
+
+		if (is_type_untyped(type)) {
+			return true;
+		}
+
 		i64 i = v.value_integer;
 		u64 u = *cast(u64 *)&i;
 		i64 s = 8*type_size_of(c->allocator, type);
@@ -2005,7 +2011,7 @@ bool check_is_vector_elem(Checker *c, AstNode *expr) {
 
 void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
 	switch (op.kind) {
-	case Token_Pointer: { // Pointer address
+	case Token_And: { // Pointer address
 		if (o->mode == Addressing_Type) {
 			o->type = make_type_pointer(c->allocator, o->type);
 			return;
@@ -3217,6 +3223,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 	case BuiltinProc_align_of:
 	case BuiltinProc_offset_of:
 	case BuiltinProc_type_info:
+	case BuiltinProc_transmute:
 		// NOTE(bill): The first arg may be a Type, this will be checked case by case
 		break;
 	default:
@@ -4463,6 +4470,56 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 			}
 		}
 	} break;
+
+	case BuiltinProc_transmute: {
+		Operand op = {0};
+		check_expr_or_type(c, &op, ce->args.e[0]);
+		Type *t = op.type;
+		if ((op.mode != Addressing_Type && t == NULL) || t == t_invalid) {
+			error_node(ce->args.e[0], "Expected a type for `transmute`");
+			return false;
+		}
+		AstNode *expr = ce->args.e[1];
+		Operand *o = operand;
+		check_expr(c, o, expr);
+		if (o->mode == Addressing_Invalid) {
+			return false;
+		}
+
+		if (o->mode == Addressing_Constant) {
+			gbString expr_str = expr_to_string(o->expr);
+			error_node(o->expr, "Cannot transmute a constant expression: `%s`", expr_str);
+			gb_string_free(expr_str);
+			o->mode = Addressing_Invalid;
+			o->expr = expr;
+			return false;
+		}
+
+		if (is_type_untyped(o->type)) {
+			gbString expr_str = expr_to_string(o->expr);
+			error_node(o->expr, "Cannot transmute untyped expression: `%s`", expr_str);
+			gb_string_free(expr_str);
+			o->mode = Addressing_Invalid;
+			o->expr = expr;
+			return false;
+		}
+
+		i64 srcz = type_size_of(c->allocator, o->type);
+		i64 dstz = type_size_of(c->allocator, t);
+		if (srcz != dstz) {
+			gbString expr_str = expr_to_string(o->expr);
+			gbString type_str = type_to_string(t);
+			error_node(o->expr, "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, srcz, dstz);
+			gb_string_free(type_str);
+			gb_string_free(expr_str);
+			o->mode = Addressing_Invalid;
+			o->expr = expr;
+			return false;
+		}
+
+		o->mode = Addressing_Value;
+		o->type = t;
+	} break;
 	}
 
 	return true;
@@ -4766,13 +4823,14 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
 	}
 
 	if (operand->mode == Addressing_Type) {
+	#if 0
 		gbString str = type_to_string(operand->type);
 		error_node(call, "Expected a procedure, got a type `%s`", str);
 		gb_string_free(str);
 		operand->mode = Addressing_Invalid;
 		operand->expr = call;
 		return Expr_Stmt;
-	#if 0
+	#else
 		Type *t = operand->type;
 		gbString str = type_to_string(t);
 		operand->mode = Addressing_Invalid;
@@ -5480,129 +5538,85 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 		o->expr = node;
 	case_end;
 
-	case_ast_node(ce, CastExpr, node);
-		Type *t = check_type(c, ce->type);
-		check_expr(c, o, ce->expr);
+	case_ast_node(ta, TypeAssertion, node);
+		check_expr(c, o, ta->expr);
 		if (o->mode == Addressing_Invalid) {
 			o->expr = node;
 			return kind;
 		}
-		switch (ce->token.kind) {
-		case Token_cast:
-			check_cast(c, o, t);
-			break;
-		case Token_transmute: {
-			if (o->mode == Addressing_Constant) {
-				gbString expr_str = expr_to_string(o->expr);
-				error_node(o->expr, "Cannot transmute a constant expression: `%s`", expr_str);
-				gb_string_free(expr_str);
-				o->mode = Addressing_Invalid;
-				o->expr = node;
-				return kind;
-			}
-
-			if (is_type_untyped(o->type)) {
-				gbString expr_str = expr_to_string(o->expr);
-				error_node(o->expr, "Cannot transmute untyped expression: `%s`", expr_str);
-				gb_string_free(expr_str);
-				o->mode = Addressing_Invalid;
-				o->expr = node;
-				return kind;
-			}
-
-			i64 srcz = type_size_of(c->allocator, o->type);
-			i64 dstz = type_size_of(c->allocator, t);
-			if (srcz != dstz) {
-				gbString expr_str = expr_to_string(o->expr);
-				gbString type_str = type_to_string(t);
-				error_node(o->expr, "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, srcz, dstz);
-				gb_string_free(type_str);
-				gb_string_free(expr_str);
-				o->mode = Addressing_Invalid;
-				o->expr = node;
-				return kind;
-			}
+		Type *t = check_type(c, ta->type);
 
-			o->type = t;
-		} break;
-
-		case Token_union_cast: {
-			if (o->mode == Addressing_Constant) {
-				gbString expr_str = expr_to_string(o->expr);
-				error_node(o->expr, "Cannot `union_cast` a constant expression: `%s`", expr_str);
-				gb_string_free(expr_str);
-				o->mode = Addressing_Invalid;
-				o->expr = node;
-				return kind;
-			}
+		if (o->mode == Addressing_Constant) {
+			gbString expr_str = expr_to_string(o->expr);
+			error_node(o->expr, "A type assertion cannot be applied to a constant expression: `%s`", expr_str);
+			gb_string_free(expr_str);
+			o->mode = Addressing_Invalid;
+			o->expr = node;
+			return kind;
+		}
 
-			if (is_type_untyped(o->type)) {
-				gbString expr_str = expr_to_string(o->expr);
-				error_node(o->expr, "Cannot `union_cast` an untyped expression: `%s`", expr_str);
-				gb_string_free(expr_str);
-				o->mode = Addressing_Invalid;
-				o->expr = node;
-				return kind;
-			}
+		if (is_type_untyped(o->type)) {
+			gbString expr_str = expr_to_string(o->expr);
+			error_node(o->expr, "A type assertion cannot be applied to an untyped expression: `%s`", expr_str);
+			gb_string_free(expr_str);
+			o->mode = Addressing_Invalid;
+			o->expr = node;
+			return kind;
+		}
 
-			bool src_is_ptr = is_type_pointer(o->type);
-			bool dst_is_ptr = is_type_pointer(t);
-			Type *src = type_deref(o->type);
-			Type *dst = type_deref(t);
-			Type *bsrc = base_type(src);
-			Type *bdst = base_type(dst);
 
-			if (src_is_ptr != dst_is_ptr) {
-				gbString src_type_str = type_to_string(o->type);
-				gbString dst_type_str = type_to_string(t);
-				error_node(o->expr, "Invalid `union_cast` types: `%s` and `%s`", src_type_str, dst_type_str);
-				gb_string_free(dst_type_str);
-				gb_string_free(src_type_str);
-				o->mode = Addressing_Invalid;
-				o->expr = node;
-				return kind;
-			}
+		bool src_is_ptr = is_type_pointer(o->type);
+		bool dst_is_ptr = is_type_pointer(t);
+		Type *src = type_deref(o->type);
+		Type *dst = type_deref(t);
+		Type *bsrc = base_type(src);
+		Type *bdst = base_type(dst);
 
-			if (!is_type_union(src)) {
-				error_node(o->expr, "`union_cast` can only operate on unions");
-				o->mode = Addressing_Invalid;
-				o->expr = node;
-				return kind;
-			}
+		if (src_is_ptr != dst_is_ptr) {
+			gbString src_type_str = type_to_string(o->type);
+			gbString dst_type_str = type_to_string(t);
+			error_node(o->expr, "Invalid type assertion types: `%s` and `%s`", src_type_str, dst_type_str);
+			gb_string_free(dst_type_str);
+			gb_string_free(src_type_str);
+			o->mode = Addressing_Invalid;
+			o->expr = node;
+			return kind;
+		}
 
-			bool ok = false;
-			for (isize i = 1; i < bsrc->Record.variant_count; i++) {
-				Entity *f = bsrc->Record.variants[i];
-				if (are_types_identical(f->type, dst)) {
-					ok = true;
-					break;
-				}
-			}
+		if (!is_type_union(src)) {
+			error_node(o->expr, "Type assertions can only operate on unions");
+			o->mode = Addressing_Invalid;
+			o->expr = node;
+			return kind;
+		}
 
-			if (!ok) {
-				gbString expr_str = expr_to_string(o->expr);
-				gbString dst_type_str = type_to_string(t);
-				error_node(o->expr, "Cannot `union_cast` `%s` to `%s`", expr_str, dst_type_str);
-				gb_string_free(dst_type_str);
-				gb_string_free(expr_str);
-				o->mode = Addressing_Invalid;
-				o->expr = node;
-				return kind;
+		bool ok = false;
+		for (isize i = 1; i < bsrc->Record.variant_count; i++) {
+			Entity *f = bsrc->Record.variants[i];
+			if (are_types_identical(f->type, dst)) {
+				ok = true;
+				break;
 			}
+		}
 
-			add_type_info_type(c, o->type);
-			add_type_info_type(c, t);
+		if (!ok) {
+			gbString expr_str = expr_to_string(o->expr);
+			gbString dst_type_str = type_to_string(t);
+			error_node(o->expr, "Cannot type assert `%s` to `%s`", expr_str, dst_type_str);
+			gb_string_free(dst_type_str);
+			gb_string_free(expr_str);
+			o->mode = Addressing_Invalid;
+			o->expr = node;
+			return kind;
+		}
 
-			o->type = t;
-			o->mode = Addressing_OptionalOk;
-		} break;
+		add_type_info_type(c, o->type);
+		add_type_info_type(c, t);
 
-		default:
-			GB_PANIC("Unknown cast expression");
-		}
+		o->type = t;
+		o->mode = Addressing_OptionalOk;
 	case_end;
 
-
 	case_ast_node(ue, UnaryExpr, node);
 		check_expr_base(c, o, ue->expr, type_hint);
 		if (o->mode == Addressing_Invalid) {
@@ -6022,14 +6036,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = write_expr_to_string(str, ue->expr);
 	case_end;
 
-	case_ast_node(ce, CastExpr, node);
-		str = string_append_token(str, ce->token);
-		str = gb_string_appendc(str, "(");
-		str = write_expr_to_string(str, ce->type);
-		str = gb_string_appendc(str, ")");
-		str = write_expr_to_string(str, ce->expr);
-	case_end;
-
 	case_ast_node(de, DerefExpr, node);
 		str = write_expr_to_string(str, de->expr);
 		str = gb_string_appendc(str, "^");
@@ -6055,6 +6061,13 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = write_expr_to_string(str, se->selector);
 	case_end;
 
+	case_ast_node(ta, TypeAssertion, node);
+		str = write_expr_to_string(str, ta->expr);
+		str = gb_string_appendc(str, ".(");
+		str = write_expr_to_string(str, ta->type);
+		str = gb_string_appendc(str, ")");
+	case_end;
+
 	case_ast_node(ie, IndexExpr, node);
 		str = write_expr_to_string(str, ie->expr);
 		str = gb_string_appendc(str, "[");

+ 4 - 1
src/checker.c

@@ -52,7 +52,6 @@ typedef enum BuiltinProcId {
 	BuiltinProc_panic,
 
 	BuiltinProc_copy,
-	// BuiltinProc_append,
 
 	BuiltinProc_swizzle,
 
@@ -72,6 +71,8 @@ typedef enum BuiltinProcId {
 	BuiltinProc_abs,
 	BuiltinProc_clamp,
 
+	BuiltinProc_transmute,
+
 	BuiltinProc_Count,
 } BuiltinProcId;
 gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
@@ -123,6 +124,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
 	{STR_LIT("max"),              2, false, Expr_Expr},
 	{STR_LIT("abs"),              1, false, Expr_Expr},
 	{STR_LIT("clamp"),            3, false, Expr_Expr},
+
+	{STR_LIT("transmute"),        2, false, Expr_Expr},
 };
 
 

+ 22 - 59
src/ir.c

@@ -3105,7 +3105,7 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token
 
 		args[4] = ir_type_info(proc, src_type);
 		args[5] = ir_type_info(proc, dst_type);
-		ir_emit_global_call(proc, "__union_cast_check", args, 6);
+		ir_emit_global_call(proc, "__type_assertion_check", args, 6);
 
 		return ir_emit_load(proc, ir_emit_struct_ep(proc, v, 0));
 	}
@@ -3606,36 +3606,21 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 	case_end;
 #endif
 
-	case_ast_node(ce, CastExpr, expr);
+	case_ast_node(ta, TypeAssertion, expr);
 		Type *type = tv->type;
-		irValue *e = ir_build_expr(proc, ce->expr);
-		switch (ce->token.kind) {
-		case Token_cast:
-			ir_emit_comment(proc, str_lit("cast - cast"));
-			return ir_emit_conv(proc, e, type);
-
-		case Token_transmute:
-			ir_emit_comment(proc, str_lit("cast - transmute"));
-			return ir_emit_transmute(proc, e, type);
-
-	#if 0
-		case Token_down_cast:
-			ir_emit_comment(proc, str_lit("cast - down_cast"));
-			return ir_emit_down_cast(proc, e, type);
-	#endif
-
-		case Token_union_cast:
+		irValue *e = ir_build_expr(proc, ta->expr);
+		Type *t = type_deref(ir_type(e));
+		if (is_type_union(t)) {
 			ir_emit_comment(proc, str_lit("cast - union_cast"));
 			return ir_emit_union_cast(proc, e, type, ast_node_token(expr).pos);
-
-		default:
-			GB_PANIC("Unknown cast expression");
+		} else {
+			GB_PANIC("TODO(bill): type assertion %s", type_to_string(ir_type(e)));
 		}
 	case_end;
 
 	case_ast_node(ue, UnaryExpr, expr);
 		switch (ue->op.kind) {
-		case Token_Pointer:
+		case Token_And:
 			return ir_emit_ptr_offset(proc, ir_build_addr(proc, ue->expr).addr, v_zero); // Make a copy of the pointer
 		default:
 			return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv->type);
@@ -3734,6 +3719,11 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 					return ir_type_info(proc, t);
 				} break;
 
+				case BuiltinProc_transmute: {
+					irValue *x = ir_build_expr(proc, ce->args.e[1]);
+					return ir_emit_transmute(proc, x, tv->type);
+				}
+
 				case BuiltinProc_len: {
 					irValue *v = ir_build_expr(proc, ce->args.e[0]);
 					Type *t = base_type(ir_type(v));
@@ -4736,50 +4726,23 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 		}
 	case_end;
 
-	case_ast_node(ce, CastExpr, expr);
-		switch (ce->token.kind) {
-		case Token_cast: {
-			ir_emit_comment(proc, str_lit("Cast - cast"));
-			// NOTE(bill): Needed for dereference of pointer conversion
-			Type *type = type_of_expr(proc->module->info, expr);
-			irValue *v = ir_add_local_generated(proc, type);
-			ir_emit_store(proc, v, ir_emit_conv(proc, ir_build_expr(proc, ce->expr), type));
-			return ir_addr(v);
-		}
-		case Token_transmute: {
-			ir_emit_comment(proc, str_lit("Cast - transmute"));
-			// NOTE(bill): Needed for dereference of pointer conversion
-			Type *type = type_of_expr(proc->module->info, expr);
-			irValue *v = ir_add_local_generated(proc, type);
-			ir_emit_store(proc, v, ir_emit_transmute(proc, ir_build_expr(proc, ce->expr), type));
-			return ir_addr(v);
-		}
-	#if 0
-		case Token_down_cast: {
-			ir_emit_comment(proc, str_lit("Cast - down_cast"));
-			// NOTE(bill): Needed for dereference of pointer conversion
+	case_ast_node(ta, TypeAssertion, expr);
+		irValue *e = ir_build_expr(proc, ta->expr);
+		Type *t = type_deref(ir_type(e));
+		if (is_type_union(t)) {
 			Type *type = type_of_expr(proc->module->info, expr);
 			irValue *v = ir_add_local_generated(proc, type);
-			ir_emit_store(proc, v, ir_emit_down_cast(proc, ir_build_expr(proc, ce->expr), type));
-			return ir_addr(v);
-		}
-	#endif
-		case Token_union_cast: {
-			ir_emit_comment(proc, str_lit("Cast - union_cast"));
-			// NOTE(bill): Needed for dereference of pointer conversion
-			Type *type = type_of_expr(proc->module->info, expr);
-			irValue *v = ir_add_local_generated(proc, type);
-			ir_emit_store(proc, v, ir_emit_union_cast(proc, ir_build_expr(proc, ce->expr), type, ast_node_token(expr).pos));
+			ir_emit_comment(proc, str_lit("cast - union_cast"));
+			ir_emit_store(proc, v, ir_emit_union_cast(proc, ir_build_expr(proc, ta->expr), type, ast_node_token(expr).pos));
 			return ir_addr(v);
-		}
-		default:
-			GB_PANIC("Unknown cast expression");
+		} else {
+			GB_PANIC("TODO(bill): type assertion %s", type_to_string(ir_type(e)));
 		}
 	case_end;
 
 	case_ast_node(ue, UnaryExpr, expr);
 		switch (ue->op.kind) {
-		case Token_Pointer: {
+		case Token_And: {
 			return ir_build_addr(proc, ue->expr);
 		}
 		default:

+ 52 - 45
src/parser.c

@@ -182,9 +182,9 @@ AST_NODE_KIND(_ExprBegin,  "",  i32) \
 		Token        open; \
 		Token        close; \
 	}) \
-	AST_NODE_KIND(CastExpr,     "cast expression",     struct { Token token; AstNode *type, *expr; Token open, close; }) \
-	AST_NODE_KIND(FieldValue,   "field value",         struct { Token eq; AstNode *field, *value; }) \
-	AST_NODE_KIND(TernaryExpr,  "ternary expression",  struct { AstNode *cond, *x, *y; }) \
+	AST_NODE_KIND(FieldValue,    "field value",         struct { Token eq; AstNode *field, *value; }) \
+	AST_NODE_KIND(TernaryExpr,   "ternary expression",  struct { AstNode *cond, *x, *y; }) \
+	AST_NODE_KIND(TypeAssertion, "type assertion",      struct { AstNode *expr; Token dot; AstNode *type; }) \
 AST_NODE_KIND(_ExprEnd,       "", i32) \
 AST_NODE_KIND(_StmtBegin,     "", i32) \
 	AST_NODE_KIND(BadStmt,    "bad statement",                 struct { Token begin, end; }) \
@@ -485,13 +485,13 @@ Token ast_node_token(AstNode *node) {
 			return ast_node_token(node->SelectorExpr.selector);
 		}
 		return node->SelectorExpr.token;
-	case AstNode_IndexExpr:    return node->IndexExpr.open;
-	case AstNode_SliceExpr:    return node->SliceExpr.open;
-	case AstNode_Ellipsis:     return node->Ellipsis.token;
-	case AstNode_CastExpr:     return node->CastExpr.token;
-	case AstNode_FieldValue:   return node->FieldValue.eq;
-	case AstNode_DerefExpr:    return node->DerefExpr.op;
-	case AstNode_TernaryExpr:  return ast_node_token(node->TernaryExpr.cond);
+	case AstNode_IndexExpr:     return node->IndexExpr.open;
+	case AstNode_SliceExpr:     return node->SliceExpr.open;
+	case AstNode_Ellipsis:      return node->Ellipsis.token;
+	case AstNode_FieldValue:    return node->FieldValue.eq;
+	case AstNode_DerefExpr:     return node->DerefExpr.op;
+	case AstNode_TernaryExpr:   return ast_node_token(node->TernaryExpr.cond);
+	case AstNode_TypeAssertion: return ast_node_token(node->TypeAssertion.expr);
 
 	case AstNode_BadStmt:       return node->BadStmt.begin;
 	case AstNode_EmptyStmt:     return node->EmptyStmt.token;
@@ -773,16 +773,6 @@ AstNode *ast_field_value(AstFile *f, AstNode *field, AstNode *value, Token eq) {
 	return result;
 }
 
-AstNode *ast_cast_expr(AstFile *f, Token token, AstNode *type, AstNode *expr, Token open, Token close) {
-	AstNode *result = make_ast_node(f, AstNode_CastExpr);
-	result->CastExpr.token = token;
-	result->CastExpr.type = type;
-	result->CastExpr.expr = expr;
-	result->CastExpr.open = open;
-	result->CastExpr.close = close;
-	return result;
-}
-
 AstNode *ast_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token open, Token close) {
 	AstNode *result = make_ast_node(f, AstNode_CompoundLit);
 	result->CompoundLit.type = type;
@@ -806,6 +796,14 @@ AstNode *ast_ternary_expr(AstFile *f, AstNode *cond, AstNode *x, AstNode *y) {
 	result->TernaryExpr.y = y;
 	return result;
 }
+AstNode *ast_type_assertion(AstFile *f, AstNode *expr, Token dot, AstNode *type) {
+	AstNode *result = make_ast_node(f, AstNode_TypeAssertion);
+	result->TypeAssertion.expr = expr;
+	result->TypeAssertion.dot  = dot;
+	result->TypeAssertion.type = type;
+	return result;
+}
+
 
 
 
@@ -1977,6 +1975,13 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
 			// case Token_Integer:
 				// operand = ast_selector_expr(f, token, operand, parse_expr(f, lhs));
 				// break;
+			case Token_OpenParen: {
+				Token open = expect_token(f, Token_OpenParen);
+				AstNode *type = parse_type(f);
+				Token close = expect_token(f, Token_CloseParen);
+				operand = ast_type_assertion(f, operand, token, type);
+			} break;
+
 			default:
 				syntax_error(f->curr_token, "Expected a selector");
 				next_token(f);
@@ -2073,32 +2078,33 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
 AstNode *parse_unary_expr(AstFile *f, bool lhs) {
 	switch (f->curr_token.kind) {
 
-	case Token_cast:
-	case Token_transmute:
-	case Token_union_cast:
-	{
-		Token token = f->curr_token; next_token(f);
-		Token open = expect_token(f, Token_OpenParen);
-		AstNode *type = parse_type(f);
-		Token close = expect_token(f, Token_CloseParen);
-		AstNode *expr = parse_unary_expr(f, lhs);
-		return ast_cast_expr(f, token, type, expr, open, close);
-	} break;
+	// case Token_cast:
+	// case Token_transmute:
+	// case Token_union_cast:
+	// {
+		// Token token = f->curr_token; next_token(f);
+		// Token open = expect_token(f, Token_OpenParen);
+		// AstNode *type = parse_type(f);
+		// Token close = expect_token(f, Token_CloseParen);
+		// AstNode *expr = parse_unary_expr(f, lhs);
+		// return ast_cast_expr(f, token, type, expr, open, close);
+	// } break;
+
+	// case Token_Pointer: {
+	// 	Token op = f->curr_token;
+	// 	next_token(f);
+	// 	AstNode *expr = parse_unary_expr(f, lhs);
+	// 	if (is_ast_node_type(expr)) {
+	// 		return ast_pointer_type(f, op, expr);
+	// 	}
+	// 	return ast_unary_expr(f, op, expr);
+	// } break;
 
-	case Token_Pointer: {
-		Token op = f->curr_token;
-		next_token(f);
-		AstNode *expr = parse_unary_expr(f, lhs);
-		if (is_ast_node_type(expr)) {
-			return ast_pointer_type(f, op, expr);
-		}
-		return ast_unary_expr(f, op, expr);
-	} break;
-	// case Token_Maybe:
 	case Token_Add:
 	case Token_Sub:
 	case Token_Not:
-	case Token_Xor: {
+	case Token_Xor:
+	case Token_And: {
 		Token op = f->curr_token;
 		next_token(f);
 		return ast_unary_expr(f, op, parse_unary_expr(f, lhs));
@@ -2663,10 +2669,11 @@ AstNode *parse_type_or_ident(AstFile *f) {
 			AstNode *sel = parse_ident(f);
 			e = ast_selector_expr(f, token, e, sel);
 		}
-		if (f->curr_token.kind == Token_OpenParen) {
+		// TODO(bill): Merge type_or_ident into the general parsing for expressions
+		// if (f->curr_token.kind == Token_OpenParen) {
 			// HACK NOTE(bill): For type_of_val(expr) et al.
-			e = parse_call_expr(f, e);
-		}
+			// e = parse_call_expr(f, e);
+		// }
 		return e;
 	}
 

+ 0 - 61
src/ssa.c

@@ -1111,40 +1111,6 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) {
 		}
 	case_end;
 
-
-	case_ast_node(ce, CastExpr, expr);
-		switch (ce->token.kind) {
-		case Token_cast: {
-			ssa_emit_comment(p, str_lit("Cast - cast"));
-			// NOTE(bill): Needed for dereference of pointer conversion
-			Type *type = type_of_expr(p->module->info, expr);
-			ssaAddr addr = ssa_add_local_generated(p, type);
-			ssa_addr_store(p, addr, ssa_emit_conv(p, ssa_build_expr(p, ce->expr), type));
-			return addr;
-		}
-		#if 0
-		case Token_transmute: {
-			ssa_emit_comment(p, str_lit("Cast - transmute"));
-			// NOTE(bill): Needed for dereference of pointer conversion
-			Type *type = type_of_expr(p->module->info, expr);
-			ssaValue *v = ssa_add_local_generated(p, type);
-			ssa_emit_store(p, v, ssa_emit_transmute(p, ssa_build_expr(p, ce->expr), type));
-			return ssa_addr(v);
-		}
-		case Token_union_cast: {
-			ssa_emit_comment(p, str_lit("Cast - union_cast"));
-			// NOTE(bill): Needed for dereference of pointer conversion
-			Type *type = type_of_expr(p->module->info, expr);
-			ssaValue *v = ssa_add_local_generated(p, type);
-			ssa_emit_store(p, v, ssa_emit_union_cast(p, ssa_build_expr(p, ce->expr), type, ast_node_token(expr).pos));
-			return ssa_addr(v);
-		}
-		#endif
-		default:
-			GB_PANIC("Unknown cast expression");
-		}
-	case_end;
-
 	case_ast_node(ue, UnaryExpr, expr);
 		switch (ue->op.kind) {
 		case Token_Pointer: {
@@ -1841,33 +1807,6 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
 	case_end;
 
 
-	case_ast_node(ce, CastExpr, expr);
-		Type *type = tv->type;
-		ssaValue *e = ssa_build_expr(p, ce->expr);
-		switch (ce->token.kind) {
-		case Token_cast:
-			ssa_emit_comment(p, str_lit("cast - cast"));
-			return ssa_emit_conv(p, e, type);
-
-		// case Token_transmute:
-			// ssa_emit_comment(p, str_lit("cast - transmute"));
-			// return ssa_emit_transmute(p, e, type);
-
-	#if 0
-		case Token_down_cast:
-			ssa_emit_comment(p, str_lit("cast - down_cast"));
-			return ssa_emit_down_cast(p, e, type);
-	#endif
-
-		// case Token_union_cast:
-			// ssa_emit_comment(p, str_lit("cast - union_cast"));
-			// return ssa_emit_union_cast(p, e, type, ast_node_token(expr).pos);
-
-		default:
-			GB_PANIC("Unhandled cast expression %.*s", LIT(token_strings[ce->token.kind]));
-		}
-	case_end;
-
 	case_ast_node(pl, ProcLit, expr);
 		GB_PANIC("TODO(bill): ssa_build_expr ProcLit");
 	#if 0

+ 19 - 17
src/tokenizer.c

@@ -76,6 +76,7 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
 	TOKEN_KIND(Token_Comma,         ","),   \
 	TOKEN_KIND(Token_Ellipsis,      ".."),  \
 	TOKEN_KIND(Token_HalfClosed,    "..<"), \
+	TOKEN_KIND(Token_BackSlash,     "\\"),  \
 TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
 \
 TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
@@ -106,9 +107,9 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 	TOKEN_KIND(Token_using,          "using"),               \
 	TOKEN_KIND(Token_no_alias,       "no_alias"),            \
 	TOKEN_KIND(Token_immutable,      "immutable"),           \
-	TOKEN_KIND(Token_cast,           "cast"),                \
-	TOKEN_KIND(Token_transmute,      "transmute"),           \
-	TOKEN_KIND(Token_union_cast,     "union_cast"),          \
+	/* TOKEN_KIND(Token_cast,           "cast"), */                \
+	/* TOKEN_KIND(Token_transmute,      "transmute"), */           \
+	/* TOKEN_KIND(Token_union_cast,     "union_cast"), */          \
 	TOKEN_KIND(Token_context,        "context"),             \
 	TOKEN_KIND(Token_push_context,   "push_context"),        \
 	TOKEN_KIND(Token_push_allocator, "push_allocator"),      \
@@ -878,20 +879,21 @@ Token tokenizer_get_token(Tokenizer *t) {
 			}
 			break;
 
-		case '#': token.kind = Token_Hash;         break;
-		case '@': token.kind = Token_At;           break;
-		case '$': token.kind = Token_Dollar;       break;
-		case '?': token.kind = Token_Question;     break;
-		case '^': token.kind = Token_Pointer;      break;
-		case ';': token.kind = Token_Semicolon;    break;
-		case ',': token.kind = Token_Comma;        break;
-		case ':': token.kind = Token_Colon;        break;
-		case '(': token.kind = Token_OpenParen;    break;
-		case ')': token.kind = Token_CloseParen;   break;
-		case '[': token.kind = Token_OpenBracket;  break;
-		case ']': token.kind = Token_CloseBracket; break;
-		case '{': token.kind = Token_OpenBrace;    break;
-		case '}': token.kind = Token_CloseBrace;   break;
+		case '#':  token.kind = Token_Hash;         break;
+		case '@':  token.kind = Token_At;           break;
+		case '$':  token.kind = Token_Dollar;       break;
+		case '?':  token.kind = Token_Question;     break;
+		case '^':  token.kind = Token_Pointer;      break;
+		case ';':  token.kind = Token_Semicolon;    break;
+		case ',':  token.kind = Token_Comma;        break;
+		case ':':  token.kind = Token_Colon;        break;
+		case '(':  token.kind = Token_OpenParen;    break;
+		case ')':  token.kind = Token_CloseParen;   break;
+		case '[':  token.kind = Token_OpenBracket;  break;
+		case ']':  token.kind = Token_CloseBracket; break;
+		case '{':  token.kind = Token_OpenBrace;    break;
+		case '}':  token.kind = Token_CloseBrace;   break;
+		case '\\': token.kind = Token_BackSlash;    break;
 
 		case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq);                                        break;
 		case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq);                                        break;