Browse Source

Change push allocator system; update core libraries

gingerBill 7 years ago
parent
commit
eb4b3f5976
12 changed files with 162 additions and 177 deletions
  1. 96 54
      core/bits.odin
  2. 9 10
      core/math.odin
  3. 8 1
      core/mem.odin
  4. 1 1
      core/thread.odin
  5. 1 1
      core/utf8.odin
  6. 3 3
      examples/demo.odin
  7. 16 8
      src/check_expr.cpp
  8. 8 12
      src/check_stmt.cpp
  9. 0 26
      src/ir.cpp
  10. 20 56
      src/parser.cpp
  11. 0 3
      src/ssa.cpp
  12. 0 2
      src/tokenizer.cpp

+ 96 - 54
core/bits.odin

@@ -22,17 +22,73 @@ I32_MAX  ::  -I32_MIN - 1;
 I64_MAX  ::  -I64_MIN - 1;
 I128_MAX :: -I128_MIN - 1;
 
+foreign __llvm_core {
+	@(link_name="llvm.ctpop.i8")        __llvm_ctpop :: proc(u8)   ->   u8 ---;
+	@(link_name="llvm.ctpop.i8")        __llvm_ctpop :: proc(i8)   ->   i8 ---;
+	@(link_name="llvm.ctpop.i16")       __llvm_ctpop :: proc(u16)  ->  u16 ---;
+	@(link_name="llvm.ctpop.i16")       __llvm_ctpop :: proc(i16)  ->  i16 ---;
+	@(link_name="llvm.ctpop.i32")       __llvm_ctpop :: proc(u32)  ->  u32 ---;
+	@(link_name="llvm.ctpop.i32")       __llvm_ctpop :: proc(i32)  ->  i32 ---;
+	@(link_name="llvm.ctpop.i64")       __llvm_ctpop :: proc(u64)  ->  u64 ---;
+	@(link_name="llvm.ctpop.i64")       __llvm_ctpop :: proc(i64)  ->  i64 ---;
+	@(link_name="llvm.ctpop.i128")      __llvm_ctpop :: proc(u128) -> u128 ---;
+	@(link_name="llvm.ctpop.i128")      __llvm_ctpop :: proc(i128) -> i128 ---;
+
+	@(link_name="llvm.ctlz.i8")         __llvm_ctlz :: proc(u8,   bool) ->   u8 ---;
+	@(link_name="llvm.ctlz.i8")         __llvm_ctlz :: proc(i8,   bool) ->   i8 ---;
+	@(link_name="llvm.ctlz.i16")        __llvm_ctlz :: proc(u16,  bool) ->  u16 ---;
+	@(link_name="llvm.ctlz.i16")        __llvm_ctlz :: proc(i16,  bool) ->  i16 ---;
+	@(link_name="llvm.ctlz.i32")        __llvm_ctlz :: proc(u32,  bool) ->  u32 ---;
+	@(link_name="llvm.ctlz.i32")        __llvm_ctlz :: proc(i32,  bool) ->  i32 ---;
+	@(link_name="llvm.ctlz.i64")        __llvm_ctlz :: proc(u64,  bool) ->  u64 ---;
+	@(link_name="llvm.ctlz.i64")        __llvm_ctlz :: proc(i64,  bool) ->  i64 ---;
+	@(link_name="llvm.ctlz.i128")       __llvm_ctlz :: proc(u128, bool) -> u128 ---;
+	@(link_name="llvm.ctlz.i128")       __llvm_ctlz :: proc(i128, bool) -> i128 ---;
+
+	@(link_name="llvm.cttz.i8")         __llvm_cttz :: proc(u8,   bool) ->   u8 ---;
+	@(link_name="llvm.cttz.i8")         __llvm_cttz :: proc(i8,   bool) ->   i8 ---;
+	@(link_name="llvm.cttz.i16")        __llvm_cttz :: proc(u16,  bool) ->  u16 ---;
+	@(link_name="llvm.cttz.i16")        __llvm_cttz :: proc(i16,  bool) ->  i16 ---;
+	@(link_name="llvm.cttz.i32")        __llvm_cttz :: proc(u32,  bool) ->  u32 ---;
+	@(link_name="llvm.cttz.i32")        __llvm_cttz :: proc(i32,  bool) ->  i32 ---;
+	@(link_name="llvm.cttz.i64")        __llvm_cttz :: proc(u64,  bool) ->  u64 ---;
+	@(link_name="llvm.cttz.i64")        __llvm_cttz :: proc(i64,  bool) ->  i64 ---;
+	@(link_name="llvm.cttz.i128")       __llvm_cttz :: proc(u128, bool) -> u128 ---;
+	@(link_name="llvm.cttz.i128")       __llvm_cttz :: proc(i128, bool) -> i128 ---;
+
+	@(link_name="llvm.bitreverse.i8")   __llvm_bitreverse :: proc(u8)   ->   u8 ---;
+	@(link_name="llvm.bitreverse.i8")   __llvm_bitreverse :: proc(i8)   ->   i8 ---;
+	@(link_name="llvm.bitreverse.i16")  __llvm_bitreverse :: proc(u16)  ->  u16 ---;
+	@(link_name="llvm.bitreverse.i16")  __llvm_bitreverse :: proc(i16)  ->  i16 ---;
+	@(link_name="llvm.bitreverse.i32")  __llvm_bitreverse :: proc(u32)  ->  u32 ---;
+	@(link_name="llvm.bitreverse.i32")  __llvm_bitreverse :: proc(i32)  ->  i32 ---;
+	@(link_name="llvm.bitreverse.i64")  __llvm_bitreverse :: proc(u64)  ->  u64 ---;
+	@(link_name="llvm.bitreverse.i64")  __llvm_bitreverse :: proc(i64)  ->  i64 ---;
+	@(link_name="llvm.bitreverse.i128") __llvm_bitreverse :: proc(u128) -> u128 ---;
+	@(link_name="llvm.bitreverse.i128") __llvm_bitreverse :: proc(i128) -> i128 ---;
+
+	@(link_name="llvm.bswap.i16")  byte_swap :: proc(u16)  ->  u16 ---;
+	@(link_name="llvm.bswap.i16")  byte_swap :: proc(i16)  ->  i16 ---;
+	@(link_name="llvm.bswap.i32")  byte_swap :: proc(u32)  ->  u32 ---;
+	@(link_name="llvm.bswap.i32")  byte_swap :: proc(i32)  ->  i32 ---;
+	@(link_name="llvm.bswap.i64")  byte_swap :: proc(u64)  ->  u64 ---;
+	@(link_name="llvm.bswap.i64")  byte_swap :: proc(i64)  ->  i64 ---;
+	@(link_name="llvm.bswap.i128") byte_swap :: proc(u128) -> u128 ---;
+	@(link_name="llvm.bswap.i128") byte_swap :: proc(i128) -> i128 ---;
+}
+byte_swap :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(byte_swap(u32(i))); } else { return uint(byte_swap(u64(i))); } }
+byte_swap :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(byte_swap(i32(i))); } else { return  int(byte_swap(i64(i))); } }
 
-count_ones :: proc(i:   u8) ->   u8 { foreign __llvm_core @(link_name="llvm.ctpop.i8")   __llvm_ctpop :: proc(u8)   ->   u8 ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:   i8) ->   i8 { foreign __llvm_core @(link_name="llvm.ctpop.i8")   __llvm_ctpop :: proc(i8)   ->   i8 ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  u16) ->  u16 { foreign __llvm_core @(link_name="llvm.ctpop.i16")  __llvm_ctpop :: proc(u16)  ->  u16 ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  i16) ->  i16 { foreign __llvm_core @(link_name="llvm.ctpop.i16")  __llvm_ctpop :: proc(i16)  ->  i16 ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  u32) ->  u32 { foreign __llvm_core @(link_name="llvm.ctpop.i32")  __llvm_ctpop :: proc(u32)  ->  u32 ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  i32) ->  i32 { foreign __llvm_core @(link_name="llvm.ctpop.i32")  __llvm_ctpop :: proc(i32)  ->  i32 ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  u64) ->  u64 { foreign __llvm_core @(link_name="llvm.ctpop.i64")  __llvm_ctpop :: proc(u64)  ->  u64 ---; return __llvm_ctpop(i); }
-count_ones :: proc(i:  i64) ->  i64 { foreign __llvm_core @(link_name="llvm.ctpop.i64")  __llvm_ctpop :: proc(i64)  ->  i64 ---; return __llvm_ctpop(i); }
-count_ones :: proc(i: u128) -> u128 { foreign __llvm_core @(link_name="llvm.ctpop.i128") __llvm_ctpop :: proc(u128) -> u128 ---; return __llvm_ctpop(i); }
-count_ones :: proc(i: i128) -> i128 { foreign __llvm_core @(link_name="llvm.ctpop.i128") __llvm_ctpop :: proc(i128) -> i128 ---; return __llvm_ctpop(i); }
+count_ones :: proc(i:   u8) ->   u8 { return __llvm_ctpop(i); }
+count_ones :: proc(i:   i8) ->   i8 { return __llvm_ctpop(i); }
+count_ones :: proc(i:  u16) ->  u16 { return __llvm_ctpop(i); }
+count_ones :: proc(i:  i16) ->  i16 { return __llvm_ctpop(i); }
+count_ones :: proc(i:  u32) ->  u32 { return __llvm_ctpop(i); }
+count_ones :: proc(i:  i32) ->  i32 { return __llvm_ctpop(i); }
+count_ones :: proc(i:  u64) ->  u64 { return __llvm_ctpop(i); }
+count_ones :: proc(i:  i64) ->  i64 { return __llvm_ctpop(i); }
+count_ones :: proc(i: u128) -> u128 { return __llvm_ctpop(i); }
+count_ones :: proc(i: i128) -> i128 { return __llvm_ctpop(i); }
 count_ones :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(count_ones(u32(i))); } else { return uint(count_ones(u64(i))); } }
 count_ones :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return int(count_ones(i32(i)));  } else { return int(count_ones(i64(i))); } }
 
@@ -77,60 +133,46 @@ rotate_right :: proc(i: i128, s: uint) -> i128 { return (i >> s)|(i << (8*size_o
 rotate_right :: proc(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(rotate_right(u32(i), s)); } else { return uint(rotate_right(u64(i), s)); } }
 rotate_right :: proc(i:  int, s: uint) ->  int { when size_of(int)  == size_of(i32) { return  int(rotate_right(i32(i), s)); } else { return  int(rotate_right(i64(i), s)); } }
 
-
-leading_zeros :: proc(i:   u8) ->   u8 { foreign __llvm_core @(link_name="llvm.ctlz.i8")   __llvm_ctlz :: proc(u8,   bool) ->   u8 ---;  return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:   i8) ->   i8 { foreign __llvm_core @(link_name="llvm.ctlz.i8")   __llvm_ctlz :: proc(i8,   bool) ->   i8 ---;  return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  u16) ->  u16 { foreign __llvm_core @(link_name="llvm.ctlz.i16")  __llvm_ctlz :: proc(u16,  bool) ->  u16 ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  i16) ->  i16 { foreign __llvm_core @(link_name="llvm.ctlz.i16")  __llvm_ctlz :: proc(i16,  bool) ->  i16 ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  u32) ->  u32 { foreign __llvm_core @(link_name="llvm.ctlz.i32")  __llvm_ctlz :: proc(u32,  bool) ->  u32 ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  i32) ->  i32 { foreign __llvm_core @(link_name="llvm.ctlz.i32")  __llvm_ctlz :: proc(i32,  bool) ->  i32 ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  u64) ->  u64 { foreign __llvm_core @(link_name="llvm.ctlz.i64")  __llvm_ctlz :: proc(u64,  bool) ->  u64 ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  i64) ->  i64 { foreign __llvm_core @(link_name="llvm.ctlz.i64")  __llvm_ctlz :: proc(i64,  bool) ->  i64 ---; return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i: u128) -> u128 { foreign __llvm_core @(link_name="llvm.ctlz.i128") __llvm_ctlz :: proc(u128, bool) -> u128 ---;return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i: i128) -> i128 { foreign __llvm_core @(link_name="llvm.ctlz.i128") __llvm_ctlz :: proc(i128, bool) -> i128 ---;return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:   u8) ->   u8 { return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:   i8) ->   i8 { return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  u16) ->  u16 { return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  i16) ->  i16 { return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  u32) ->  u32 { return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  i32) ->  i32 { return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  u64) ->  u64 { return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i:  i64) ->  i64 { return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i: u128) -> u128 { return __llvm_ctlz(i, false); }
+leading_zeros :: proc(i: i128) -> i128 { return __llvm_ctlz(i, false); }
 leading_zeros :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(leading_zeros(u32(i))); } else { return uint(leading_zeros(u64(i))); } }
 leading_zeros :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(leading_zeros(i32(i))); } else { return  int(leading_zeros(i64(i))); } }
 
-trailing_zeros :: proc(i:   u8) ->   u8 { foreign __llvm_core @(link_name="llvm.cttz.i8")   __llvm_cttz :: proc(u8,   bool) ->   u8 ---;  return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:   i8) ->   i8 { foreign __llvm_core @(link_name="llvm.cttz.i8")   __llvm_cttz :: proc(i8,   bool) ->   i8 ---;  return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  u16) ->  u16 { foreign __llvm_core @(link_name="llvm.cttz.i16")  __llvm_cttz :: proc(u16,  bool) ->  u16 ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  i16) ->  i16 { foreign __llvm_core @(link_name="llvm.cttz.i16")  __llvm_cttz :: proc(i16,  bool) ->  i16 ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  u32) ->  u32 { foreign __llvm_core @(link_name="llvm.cttz.i32")  __llvm_cttz :: proc(u32,  bool) ->  u32 ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  i32) ->  i32 { foreign __llvm_core @(link_name="llvm.cttz.i32")  __llvm_cttz :: proc(i32,  bool) ->  i32 ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  u64) ->  u64 { foreign __llvm_core @(link_name="llvm.cttz.i64")  __llvm_cttz :: proc(u64,  bool) ->  u64 ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  i64) ->  i64 { foreign __llvm_core @(link_name="llvm.cttz.i64")  __llvm_cttz :: proc(i64,  bool) ->  i64 ---; return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i: u128) -> u128 { foreign __llvm_core @(link_name="llvm.cttz.i128") __llvm_cttz :: proc(u128, bool) -> u128 ---;return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i: i128) -> i128 { foreign __llvm_core @(link_name="llvm.cttz.i128") __llvm_cttz :: proc(i128, bool) -> i128 ---;return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:   u8) ->   u8 { return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:   i8) ->   i8 { return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  u16) ->  u16 { return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  i16) ->  i16 { return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  u32) ->  u32 { return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  i32) ->  i32 { return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  u64) ->  u64 { return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i:  i64) ->  i64 { return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i: u128) -> u128 { return __llvm_cttz(i, false); }
+trailing_zeros :: proc(i: i128) -> i128 { return __llvm_cttz(i, false); }
 trailing_zeros :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(trailing_zeros(u32(i))); } else { return uint(trailing_zeros(u64(i))); } }
 trailing_zeros :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(trailing_zeros(i32(i))); } else { return  int(trailing_zeros(i64(i))); } }
 
 
-reverse_bits :: proc(i:   u8) ->   u8 { foreign __llvm_core @(link_name="llvm.bitreverse.i8")   __llvm_bitreverse :: proc(u8)   ->   u8 ---;  return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:   i8) ->   i8 { foreign __llvm_core @(link_name="llvm.bitreverse.i8")   __llvm_bitreverse :: proc(i8)   ->   i8 ---;  return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  u16) ->  u16 { foreign __llvm_core @(link_name="llvm.bitreverse.i16")  __llvm_bitreverse :: proc(u16)  ->  u16 ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  i16) ->  i16 { foreign __llvm_core @(link_name="llvm.bitreverse.i16")  __llvm_bitreverse :: proc(i16)  ->  i16 ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  u32) ->  u32 { foreign __llvm_core @(link_name="llvm.bitreverse.i32")  __llvm_bitreverse :: proc(u32)  ->  u32 ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  i32) ->  i32 { foreign __llvm_core @(link_name="llvm.bitreverse.i32")  __llvm_bitreverse :: proc(i32)  ->  i32 ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  u64) ->  u64 { foreign __llvm_core @(link_name="llvm.bitreverse.i64")  __llvm_bitreverse :: proc(u64)  ->  u64 ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  i64) ->  i64 { foreign __llvm_core @(link_name="llvm.bitreverse.i64")  __llvm_bitreverse :: proc(i64)  ->  i64 ---; return __llvm_bitreverse(i); }
-reverse_bits :: proc(i: u128) -> u128 { foreign __llvm_core @(link_name="llvm.bitreverse.i128") __llvm_bitreverse :: proc(u128) -> u128 ---;return __llvm_bitreverse(i); }
-reverse_bits :: proc(i: i128) -> i128 { foreign __llvm_core @(link_name="llvm.bitreverse.i128") __llvm_bitreverse :: proc(i128) -> i128 ---;return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:   u8) ->   u8 { return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:   i8) ->   i8 { return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  u16) ->  u16 { return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  i16) ->  i16 { return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  u32) ->  u32 { return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  i32) ->  i32 { return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  u64) ->  u64 { return __llvm_bitreverse(i); }
+reverse_bits :: proc(i:  i64) ->  i64 { return __llvm_bitreverse(i); }
+reverse_bits :: proc(i: u128) -> u128 { return __llvm_bitreverse(i); }
+reverse_bits :: proc(i: i128) -> i128 { return __llvm_bitreverse(i); }
 reverse_bits :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(reverse_bits(u32(i))); } else { return uint(reverse_bits(u64(i))); } }
 reverse_bits :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(reverse_bits(i32(i))); } else { return  int(reverse_bits(i64(i))); } }
 
-foreign __llvm_core {
-	@(link_name="llvm.bswap.i16")  byte_swap :: proc(u16)  ->  u16 ---;
-	@(link_name="llvm.bswap.i16")  byte_swap :: proc(i16)  ->  i16 ---;
-	@(link_name="llvm.bswap.i32")  byte_swap :: proc(u32)  ->  u32 ---;
-	@(link_name="llvm.bswap.i32")  byte_swap :: proc(i32)  ->  i32 ---;
-	@(link_name="llvm.bswap.i64")  byte_swap :: proc(u64)  ->  u64 ---;
-	@(link_name="llvm.bswap.i64")  byte_swap :: proc(i64)  ->  i64 ---;
-	@(link_name="llvm.bswap.i128") byte_swap :: proc(u128) -> u128 ---;
-	@(link_name="llvm.bswap.i128") byte_swap :: proc(i128) -> i128 ---;
-}
-byte_swap :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(byte_swap(u32(i))); } else { return uint(byte_swap(u64(i))); } }
-byte_swap :: proc(i:  int) ->  int { when size_of(int)  == size_of(i32) { return  int(byte_swap(i32(i))); } else { return  int(byte_swap(i64(i))); } }
-
 from_be :: proc(i:   u8) ->   u8 { return i; }
 from_be :: proc(i:   i8) ->   i8 { return i; }
 from_be :: proc(i:  u16) ->  u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }

+ 9 - 10
core/math.odin

@@ -64,8 +64,8 @@ unlerp :: proc(a, b, x: f32) -> (t: f32) do return (x-a)/(b-a);
 unlerp :: proc(a, b, x: f64) -> (t: f64) do return (x-a)/(b-a);
 
 
-sign :: proc(x: f32) -> f32 { if x >= 0 do return +1; return -1; }
-sign :: proc(x: f64) -> f64 { if x >= 0 do return +1; return -1; }
+sign :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
+sign :: proc(x: f64) -> f64 { return x >= 0 ? +1 : -1; }
 
 
 
@@ -85,14 +85,14 @@ copy_sign :: proc(x, y: f64) -> f64 {
 	return transmute(f64)ix;
 }
 
-round :: proc(x: f32) -> f32 { if x >= 0 do return floor(x + 0.5); return ceil(x - 0.5); }
-round :: proc(x: f64) -> f64 { if x >= 0 do return floor(x + 0.5); return ceil(x - 0.5); }
+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 { if x >= 0 do return f32(i64(x)); return f32(i64(x-0.5)); } // TODO: Get accurate versions
-floor :: proc(x: f64) -> f64 { if x >= 0 do return f64(i64(x)); return f64(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 { if x <  0 do return f32(i64(x)); return f32(i64(x+1));  }// TODO: Get accurate versions
-ceil :: proc(x: f64) -> f64 { if x <  0 do return f64(i64(x)); return f64(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 do return x - round(x/y) * y;
 remainder :: proc(x, y: f64) -> f64 do return x - round(x/y) * y;
@@ -141,8 +141,7 @@ norm :: proc(v: $T/[$N]$E) -> T do return v / mag(v);
 
 norm0 :: proc(v: $T/[$N]$E) -> T {
 	m := mag(v);
-	if m == 0 do return 0;
-	return v/m;
+	return m == 0 ? 0 : v/m;
 }
 
 

+ 8 - 1
core/mem.odin

@@ -115,9 +115,16 @@ init_arena_from_context :: proc(using a: ^Arena, size: int) {
 	temp_count = 0;
 }
 
+
+context_from_allocator :: proc(a: Allocator) -> Context {
+	c := context;
+	c.allocator = a;
+	return c;
+}
+
 destroy_arena :: proc(using a: ^Arena) {
 	if backing.procedure != nil {
-		push_allocator backing {
+		context <- context_from_allocator(backing) {
 			free(memory);
 			memory = nil;
 		}

+ 1 - 1
core/thread.odin

@@ -32,7 +32,7 @@ create :: proc(procedure: Thread_Proc) -> ^Thread {
 		}
 
 		exit := 0;
-		push_context c {
+		context <- c {
 			exit = t.procedure(t);
 		}
 

+ 1 - 1
core/utf8.odin

@@ -61,7 +61,7 @@ accept_sizes := [256]u8{
 encode_rune :: proc(r: rune) -> ([4]u8, int) {
 	buf: [4]u8;
 	i := u32(r);
-	mask: u8 : 0x3f;
+	mask :: u8(0x3f);
 	if i <= 1<<7-1 {
 		buf[0] = u8(r);
 		return buf, 1;

+ 3 - 3
examples/demo.odin

@@ -385,7 +385,7 @@ parametric_polymorphism :: proc() {
 			c := context;
 			if table.allocator.procedure != nil do c.allocator = table.allocator;
 
-			push_context c {
+			context <- c {
 				table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN));
 			}
 		}
@@ -394,7 +394,7 @@ parametric_polymorphism :: proc() {
 			c := context;
 			if table.allocator.procedure != nil do c.allocator = table.allocator;
 
-			push_context c {
+			context <- c {
 				old_slots := table.slots;
 
 				cap := max(2*cap(table.slots), TABLE_SIZE_MIN);
@@ -559,7 +559,7 @@ threading_example :: proc() {
 }
 
 main :: proc() {
-	when true {
+	when false {
 		fmt.println("\n# general_stuff");              general_stuff();
 		fmt.println("\n# default_struct_values");      default_struct_values();
 		fmt.println("\n# union_type");                 union_type();

+ 16 - 8
src/check_expr.cpp

@@ -5179,7 +5179,6 @@ bool ternary_compare_types(Type *x, Type *y) {
 	return are_types_identical(x, y);
 }
 
-
 ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *type_hint) {
 	ExprKind kind = Expr_Stmt;
 
@@ -5550,16 +5549,17 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 						}
 					}
 
-					isize field_index = 0;
+					bool seen_field_value = false;
+
 					for_array(index, cl->elems) {
-						Entity *field = t->Struct.fields_in_src_order[field_index++];
-						if (!all_fields_are_blank && is_blank_ident(field->token)) {
-							// NOTE(bill): Ignore blank identifiers
-							continue;
-						}
+						Entity *field = nullptr;
 						AstNode *elem = cl->elems[index];
 						if (elem->kind == AstNode_FieldValue) {
-							error(elem, "Mixture of `field = value` and value elements in a literal is not allowed");
+							seen_field_value = true;
+							// error(elem, "Mixture of `field = value` and value elements in a literal is not allowed");
+							// continue;
+						} else if (seen_field_value) {
+							error(elem, "Value elements cannot be used after a `field = value`");
 							continue;
 						}
 						if (index >= field_count) {
@@ -5567,6 +5567,14 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 							break;
 						}
 
+						if (field == nullptr) {
+							field = t->Struct.fields_in_src_order[index];
+						}
+						if (!all_fields_are_blank && is_blank_ident(field->token)) {
+							// NOTE(bill): Ignore blank identifiers
+							continue;
+						}
+
 						check_expr_with_type_hint(c, o, elem, field->type);
 
 						if (!check_is_field_exported(c, field)) {

+ 8 - 12
src/check_stmt.cpp

@@ -170,9 +170,6 @@ bool check_is_terminating(AstNode *node) {
 		return has_default;
 	case_end;
 
-	case_ast_node(pa, PushAllocator, node);
-		return check_is_terminating(pa->body);
-	case_end;
 	case_ast_node(pc, PushContext, node);
 		return check_is_terminating(pc->body);
 	case_end;
@@ -697,7 +694,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			array_init(&rhs_operands, c->tmp_allocator, 2 * lhs_count);
 
 			for_array(i, as->lhs) {
-				check_expr(c, &lhs_operands[i], as->lhs[i]);
+				if (is_blank_ident(as->lhs[i])) {
+					Operand *o = &lhs_operands[i];
+					o->expr = as->lhs[i];
+					o->mode = Addressing_Value;
+				} else {
+					check_expr(c, &lhs_operands[i], as->lhs[i]);
+				}
 			}
 
 			check_unpack_arguments(c, nullptr, lhs_operands.count, &rhs_operands, as->rhs, true);
@@ -1648,18 +1651,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 	case_end;
 
 
-	case_ast_node(pa, PushAllocator, node);
-		Operand op = {};
-		check_expr(c, &op, pa->expr);
-		check_assignment(c, &op, t_allocator, str_lit("argument to push_allocator"));
-		check_stmt(c, pa->body, mod_flags);
-	case_end;
-
 
 	case_ast_node(pa, PushContext, node);
 		Operand op = {};
 		check_expr(c, &op, pa->expr);
-		check_assignment(c, &op, t_context, str_lit("argument to push_context"));
+		check_assignment(c, &op, t_context, str_lit("argument to context <-"));
 		check_stmt(c, pa->body, mod_flags);
 	case_end;
 

+ 0 - 26
src/ir.cpp

@@ -7251,32 +7251,6 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 	case_end;
 
 
-
-	case_ast_node(pa, PushAllocator, node);
-		ir_emit_comment(proc, str_lit("push_allocator"));
-		irValue *new_allocator = ir_build_expr(proc, pa->expr);
-
-		ir_open_scope(proc);
-
-		irValue *prev = ir_find_or_generate_context_ptr(proc);
-		irValue *next = ir_add_local_generated(proc, t_context);
-		ir_emit_store(proc, next, ir_emit_load(proc, prev));
-
-		Selection sel = lookup_field(proc->module->allocator, t_context, str_lit("allocator"), false);
-		irValue *gep = ir_emit_deep_field_gep(proc, next, sel);
-		ir_emit_store(proc, gep, new_allocator);
-
-		array_add(&proc->context_stack, next);
-		defer (array_pop(&proc->context_stack));
-
-		// TODO(bill): is this too leaky?
-
-		ir_build_stmt(proc, pa->body);
-
-		ir_close_scope(proc, irDeferExit_Default, nullptr);
-	case_end;
-
-
 	case_ast_node(pc, PushContext, node);
 		ir_emit_comment(proc, str_lit("push_context"));
 		irValue *new_context = ir_build_expr(proc, pc->expr);

+ 20 - 56
src/parser.cpp

@@ -313,12 +313,7 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
 		AstNode *clobber_list; \
 		isize output_count, input_count, clobber_count; \
 	}) \
-	AST_NODE_KIND(PushAllocator, "push_allocator statement", struct { \
-		Token token;   \
-		AstNode *expr; \
-		AstNode *body; \
-	}) \
-	AST_NODE_KIND(PushContext, "push_context statement", struct { \
+	AST_NODE_KIND(PushContext, "context <- statement", struct { \
 		Token token;   \
 		AstNode *expr; \
 		AstNode *body; \
@@ -596,7 +591,6 @@ Token ast_node_token(AstNode *node) {
 	case AstNode_BranchStmt:    return node->BranchStmt.token;
 	case AstNode_UsingStmt:     return node->UsingStmt.token;
 	case AstNode_AsmStmt:       return node->AsmStmt.token;
-	case AstNode_PushAllocator: return node->PushAllocator.token;
 	case AstNode_PushContext:   return node->PushContext.token;
 
 	case AstNode_BadDecl:            return node->BadDecl.begin;
@@ -829,10 +823,6 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
 		n->AsmStmt.input_list   = clone_ast_node(a, n->AsmStmt.input_list);
 		n->AsmStmt.clobber_list = clone_ast_node(a, n->AsmStmt.clobber_list);
 		break;
-	case AstNode_PushAllocator:
-		n->PushAllocator.expr = clone_ast_node(a, n->PushAllocator.expr);
-		n->PushAllocator.body = clone_ast_node(a, n->PushAllocator.body);
-		break;
 	case AstNode_PushContext:
 		n->PushContext.expr = clone_ast_node(a, n->PushContext.expr);
 		n->PushContext.body = clone_ast_node(a, n->PushContext.body);
@@ -1365,14 +1355,6 @@ AstNode *ast_asm_stmt(AstFile *f, Token token, bool is_volatile, Token open, Tok
 	return result;
 }
 
-AstNode *ast_push_allocator(AstFile *f, Token token, AstNode *expr, AstNode *body) {
-	AstNode *result = make_ast_node(f, AstNode_PushAllocator);
-	result->PushAllocator.token = token;
-	result->PushAllocator.expr = expr;
-	result->PushAllocator.body = body;
-	return result;
-}
-
 AstNode *ast_push_context(AstFile *f, Token token, AstNode *expr, AstNode *body) {
 	AstNode *result = make_ast_node(f, AstNode_PushContext);
 	result->PushContext.token = token;
@@ -1832,9 +1814,6 @@ void fix_advance_to_next_stmt(AstFile *f) {
 		case Token_continue:
 		case Token_fallthrough:
 
-		case Token_push_allocator:
-		case Token_push_context:
-
 		case Token_Hash:
 		{
 			if (t.pos == f->fix_prev_pos &&
@@ -4454,6 +4433,25 @@ AstNode *parse_stmt(AstFile *f) {
 	switch (token.kind) {
 	// Operands
 	case Token_context:
+		if (look_ahead_token_kind(f, 1) == Token_ArrowLeft) {
+			advance_token(f);
+			Token arrow = expect_token(f, Token_ArrowLeft);
+			AstNode *body = nullptr;
+			isize prev_level = f->expr_level;
+			f->expr_level = -1;
+			AstNode *expr = parse_expr(f, false);
+			f->expr_level = prev_level;
+
+			if (allow_token(f, Token_do)) {
+				body = convert_stmt_to_body(f, parse_stmt(f));
+			} else {
+				body = parse_block_stmt(f, false);
+			}
+
+			return ast_push_context(f, token, expr, body);
+		}
+		/*fallthrough*/
+
 	case Token_Ident:
 	case Token_Integer:
 	case Token_Float:
@@ -4539,40 +4537,6 @@ AstNode *parse_stmt(AstFile *f) {
 		return ast_bad_stmt(f, token, f->curr_token);
 	} break;
 
-	case Token_push_allocator: {
-		advance_token(f);
-		AstNode *body = nullptr;
-		isize prev_level = f->expr_level;
-		f->expr_level = -1;
-		AstNode *expr = parse_expr(f, false);
-		f->expr_level = prev_level;
-
-		if (allow_token(f, Token_do)) {
-			body = convert_stmt_to_body(f, parse_stmt(f));
-		} else {
-			body = parse_block_stmt(f, false);
-		}
-
-		return ast_push_allocator(f, token, expr, body);
-	} break;
-
-	case Token_push_context: {
-		advance_token(f);
-		AstNode *body = nullptr;
-		isize prev_level = f->expr_level;
-		f->expr_level = -1;
-		AstNode *expr = parse_expr(f, false);
-		f->expr_level = prev_level;
-
-		if (allow_token(f, Token_do)) {
-			body = convert_stmt_to_body(f, parse_stmt(f));
-		} else {
-			body = parse_block_stmt(f, false);
-		}
-
-		return ast_push_context(f, token, expr, body);
-	} break;
-
 	case Token_At: {
 		advance_token(f);
 

+ 0 - 3
src/ssa.cpp

@@ -2176,9 +2176,6 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
 		ssa_emit_jump(p, b);
 	case_end;
 
-	case_ast_node(pa, PushAllocator, node);
-		GB_PANIC("TODO: PushAllocator");
-	case_end;
 	case_ast_node(pc, PushContext, node);
 		GB_PANIC("TODO: PushContext");
 	case_end;

+ 0 - 2
src/tokenizer.cpp

@@ -117,8 +117,6 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 	TOKEN_KIND(Token_inline,                 "inline"),                 \
 	TOKEN_KIND(Token_no_inline,              "no_inline"),              \
 	TOKEN_KIND(Token_context,                "context"),                \
-	TOKEN_KIND(Token_push_context,           "push_context"),           \
-	TOKEN_KIND(Token_push_allocator,         "push_allocator"),         \
 	TOKEN_KIND(Token_size_of,                "size_of"),                \
 	TOKEN_KIND(Token_align_of,               "align_of"),               \
 	TOKEN_KIND(Token_offset_of,              "offset_of"),              \