fn undefined(): @undefined fn offset-ptr(x Ptr a, count I64): @offset-ptr(x, count * @cast(@size-of(@undefined as a))) # Alignment is already included in size, (as padding) so move should be okay? fn offset-ptr'(x Ptr a, count Size): x offset-ptr(@cast(count)) TypeSize a size Size fn get-typesize () -> TypeSize a return TypeSize { size: @size-of(@undefined as a) } fn size-of (x a): @size-of(x) fn ptr-size-of (x Ptr a): (get-typesize() as TypeSize a).size # wrapper for intrinsic. fn cast (x): @cast(x) # safe cast for pointers fn cast-ptr (p Ptr a) -> Ptr b: @cast(p) # set a pointer if you're in a lambda :) fn set-ptr(x Ptr a, e a) x <&= e # special function to prevent the situation where we want &@undefined, but write @undefined fn uninit-buf() -> Array n a: @undefined use Cnile fn zeroed() -> a x = @undefined Cnile.memset(cast-ptr(&x), 0, size-of(x)) return x # make sure the second value's size is GREATER fn cast-on-zeroed(x a) -> b y =& zeroed() yp = y cast() yp <&= x return y& # TODO: maybe make a module "Ptr"? # Also, this is only used for C shit... because in the final std, the Ptr type should not be nullable, so this should not be here. # For undefined stuff we should have 0xabcdef and stuff. fn null-ptr() -> Ptr a: zeroed() fn null-c-ptr() -> Ptr a: zeroed() fn is-ptr-null(p Ptr a): @memeq(p, null-ptr()) fn ptr-to-int(p Ptr a) -> Size: @cast(p) fn ptr-eq(l Ptr a, r Ptr a): @memeq(l, r) fn from-nullable-c-str (s ConstStr) if s cast() ptr-eq (null-ptr() as Ptr Unit) return None else return Just(s) fn size-i64(x Size) -> I64: @cast(x) fn i32-u8(x I32) -> U8: @cast(x) fn i32-i8(x I32) -> I8: @cast(x) fn i32-u32(x I32) -> U32: @cast(x) fn i32-i64(x I32) -> I64: @i32-i64(x) fn i32-u64(x I32) -> U64: @cast(@i32-i64(x)) fn i32-size(x I32) -> Size: @cast(@i32-i64(x)) fn i64-i8(x I64) -> I8: @cast(x) fn i64-u8(x I64) -> U8: @cast(x) fn i64-i32(x I64) -> I32: @cast(x) fn i64-u32(x I64) -> U32: @cast(x) fn i64-size(x I64) -> Size: @cast(x) fn size-u64(x Size) -> U64: @cast(x) fn size-i32(x Size) -> I32: @cast(x) fn size-u32(x Size) -> U32: @cast(x) fn size-u16(x Size) -> U16: @cast(x) fn size-u8(x Size) -> U8: @cast(x) fn size-i8(x Size) -> I8: @cast(x) fn u16-u32(x U16) -> U32: cast-on-zeroed(x) fn u16-i32(x U16) -> I32: cast-on-zeroed(x) fn u32-size(x U32) -> Size: cast-on-zeroed(x) fn u32-u64(x U32) -> U64: cast-on-zeroed(x) fn u32-i64(x U32) -> I64: cast-on-zeroed(x) fn u32-u8(x U32) -> U8: cast(x) fn u32-i32(x U32) -> I32: cast(x) fn u8-size(x U8) -> Size: cast-on-zeroed(x) fn u8-i64(x U8) -> I64: cast-on-zeroed(x) fn u8-i32(x U8) -> I32: cast-on-zeroed(x) fn u8-u32(x U8) -> U32: cast-on-zeroed(x) fn u64-size(x U64) -> Size: @cast(x) fn u64-u32(x U64) -> U32: @cast(x) fn u64-i32(x U64) -> I32: @cast(x) fn u64-i64(x U64) -> I64: @cast(x) fn size-f64(x Size) -> F64: @size-f64(x) fn size-f32(x Size) -> F32: @size-f32(x) # not sure if it should be here? fn int-f64 (x) if x >= 0 return size-f64(into-uint(x)) else return size-f64(into-uint(-x)) fn int-f32 (x) if x >= 0 return size-f32(into-uint(x)) else return size-f32(into-uint(-x)) # used for pointer tagging. # rewrite this function to be clearer? fn get-ms-byte-of-pointer (ptr Ptr a) -> U8 return ((@cast(ptr) as Size) / 0x100000000000000) size-u8() fn set-ms-byte-of-pointer (ptr Ptr a, b U8) -> Ptr a # RETURNS INVALID PTR BTW s = @cast(ptr) as Size exp = 0x100000000000000 # 2^8^7 return @cast(s - ptr get-ms-byte-of-pointer() u8-size() + exp * u8-size(b))