huh/source/base.c
2026-02-20 00:23:09 -07:00

79 lines
2.7 KiB
C

typedef unsigned _BitInt(1) bool1;
typedef unsigned _BitInt(2) bool2;
typedef unsigned _BitInt(4) bool4;
typedef unsigned _BitInt(8) bool8;
typedef unsigned _BitInt(1) u1;
typedef unsigned _BitInt(2) u2;
typedef unsigned _BitInt(4) u4;
typedef unsigned _BitInt(8) u8;
typedef unsigned _BitInt(16) u16;
typedef unsigned _BitInt(32) u32;
typedef unsigned _BitInt(64) u64;
typedef unsigned _BitInt(128) u128;
typedef signed _BitInt(2) s2;
typedef signed _BitInt(4) s4;
typedef signed _BitInt(8) s8;
typedef signed _BitInt(16) s16;
typedef signed _BitInt(32) s32;
typedef signed _BitInt(64) s64;
typedef signed _BitInt(128) s128;
typedef float f32;
typedef double f64;
#if ARCH_32
typedef u32 uaddr;
typedef s32 saddr;
typedef u32 uword;
typedef s32 sword;
#else
typedef u64 uaddr;
typedef s64 saddr;
typedef u64 uword;
typedef s64 sword;
#endif
static_assert(sizeof(uaddr) == sizeof(void*), "uaddr was not equal to a pointer");
#define auto __auto_type
typedef struct { u8* data; uword count; } string;
#define string_from(P) (string){ .data = (P), .count = cast(uword, strlen((P))) }
#define string_from_const(S) (string){ .data = (S), .count = count_of((S)) }
#define string_with_count(P, C) (string){ .data = (P), .count = (C) }
#define usize_of(T) cast(uword, sizeof(T))
#define ssize_of(T) cast(sword, sizeof(T))
#define ualign_of(T) cast(uword, alignof(T))
#define salign_of(T) cast(sword, alignof(T))
#define count_of(P) (usize_of(P) / usize_of((P)[0]))
#define cast(to_type, expr) ((to_type)(expr))
// Thanks azmr
#define safecast(to_type, from_type, expr) _Generic(expr, from_type: cast(to_type, expr))
#define ptrcast(to_type, from_type, expr) _Generic(expr, from_type: cast(to_type, cast(uaddr, expr)))
#define bitcast(to_type, from_type, expr) (((union { from_type from; to_type to; }){_Generic(expr, from_type: expr)}).to)
#define procedure(ret_type, ...) typeof(ret_type(__VA_ARGS__))*
#define closure(ret_type, ...) typeof(ret_type(__VA_ARGS__))^
#include <Block.h>
#define capture __block // allows a variable to be mutably captured by a closure (will be moved to the heap if needed)
#define persist Block_copy // moves a closure to the heap (reference counted) so it can persist outside of its local stack frame
#define unpersist Block_release // frees a closure (or decrements its reference count)
typedef closure(void, void) __scope_exit;
static inline void __scope_exit_run(__scope_exit *blk) { (*blk)(); }
#define __concat__2(a, b) a##b
#define __concat(a, b) __concat__2(a, b)
#define scope_exit \
__attribute__((cleanup(__scope_exit_run), unused)) \
__scope_exit __concat(_defer_, __LINE__) = ^void(void)