2024-02-04 15:04:41 -08:00
# pragma once
2024-02-11 20:09:00 -08:00
# include <err.h>
2024-02-04 15:04:41 -08:00
# include <gc.h>
# include <gc/cord.h>
# include <stdbool.h>
# include <stdint.h>
# include <stdio.h>
2024-02-04 18:13:50 -08:00
# include <stdlib.h>
2024-02-04 15:04:41 -08:00
# include <string.h>
2024-02-11 11:02:00 -08:00
# include <unistd.h>
2024-02-04 15:04:41 -08:00
2024-02-04 18:13:50 -08:00
# include "builtins/datatypes.h"
2024-02-04 15:04:41 -08:00
# define Int64_t int64_t
# define Int32_t int32_t
# define Int16_t int16_t
# define Int8_t int8_t
# define Num64_t double
# define Num32_t float
# define String_t CORD
# define Bool_t bool
# define Void_t void
2024-02-04 20:29:57 -08:00
# define __Array(t) array_t
2024-02-04 15:04:41 -08:00
2024-02-11 21:18:55 -08:00
CORD as_cord ( void * x , const char * fmt , . . . ) ;
2024-02-04 15:04:41 -08:00
# define CORD_asprintf(...) ({ CORD __c; CORD_sprintf(&__c, __VA_ARGS__); __c; })
# define __declare(var, val) __typeof(val) var = val
# define __cord(x) _Generic(x, bool: x ? "yes" : "no", \
2024-02-10 12:33:35 -08:00
int8_t : CORD_asprintf ( " %d " , x ) , \
int16_t : CORD_asprintf ( " %d " , x ) , \
2024-02-04 18:13:50 -08:00
int32_t : CORD_asprintf ( " %d " , x ) , int64_t : CORD_asprintf ( " %ld " , x ) , \
2024-02-04 15:04:41 -08:00
double : CORD_asprintf ( " %g " , x ) , float : CORD_asprintf ( " %g " , x ) , \
CORD : x , \
2024-02-11 21:38:29 -08:00
char * : ( CORD ) ( { const char * __str = x ; __str & & __str [ 0 ] ? __str : CORD_EMPTY ; } ) , \
2024-02-11 22:36:46 -08:00
array_t : as_cord ( & ( x ) , " [ ] " ) , \
2024-02-04 15:04:41 -08:00
default : " ??? " )
# define __heap(x) (__typeof(x)*)memcpy(GC_MALLOC(sizeof(x)), (__typeof(x)[1]){x}, sizeof(x))
2024-02-11 21:38:29 -08:00
# define __stack(x) &(x)
2024-02-04 20:29:57 -08:00
# define __length(x) _Generic(x, default: (x).length)
2024-02-04 18:13:50 -08:00
// Convert negative indices to back-indexed without branching: index0 = index + (index < 0)*(len+1)) - 1
# define __index(x, i) _Generic(x, array_t: ({ __typeof(x) __obj; int64_t __offset = i; __offset += (__offset < 0) * (__obj.length + 1) - 1; assert(__offset >= 0 && offset < __obj.length); __obj.data + __obj.stride * __offset;}))
# define __safe_index(x, i) _Generic(x, array_t: ({ __typeof(x) __obj; int64_t __offset = i - 1; __obj.data + __obj.stride * __offset;}))
# define __array(x, ...) ({ __typeof(x) __items[] = {x, __VA_ARGS__}; \
2024-02-04 20:29:57 -08:00
( __Array ( __typeof ( x ) ) ) { . length = sizeof ( __items ) / sizeof ( __items [ 0 ] ) , \
2024-02-04 18:13:50 -08:00
. stride = ( int64_t ) & __items [ 1 ] - ( int64_t ) & __items [ 0 ] , \
. data = memcpy ( GC_MALLOC ( sizeof ( __items ) ) , __items , sizeof ( __items ) ) , \
. copy_on_write = 1 } ; } )
2024-02-11 20:09:00 -08:00
# define not(x) _Generic(x, bool: (bool)!(x), default: ~(x))
# define and(x, y) _Generic(x, bool: (bool)((x) && (y)), default: ((x) & (y)))
# define or(x, y) _Generic(x, bool: (bool)((x) || (y)), default: ((x) | (y)))
# define xor(x, y) _Generic(x, bool: (bool)((x) ^ (y)), default: ((x) ^ (y)))
2024-02-04 18:13:50 -08:00
# define mod(x, n) ((x) % (n))
# define mod1(x, n) (((x) % (n)) + (__typeof(x))1)
2024-02-10 14:36:04 -08:00
# define __cmp(x, y) (_Generic(x, CORD: CORD_cmp(x, y), char*: strcmp(x, y), const char*: strcmp(x, y), default: (x > 0) - (y > 0)))
2024-02-11 21:38:29 -08:00
# define __lt(x, y) (bool)(_Generic(x, int8_t: x < y, int16_t: x < y, int32_t: x < y, int64_t: x < y, float: x < y, double: x < y, bool: x < y, \
2024-02-10 14:36:04 -08:00
default : __cmp ( x , y ) < 0 ) )
2024-02-11 21:38:29 -08:00
# define __le(x, y) (bool)(_Generic(x, int8_t: x <= y, int16_t: x <= y, int32_t: x <= y, int64_t: x <= y, float: x <= y, double: x <= y, bool: x <= y, \
2024-02-10 14:36:04 -08:00
default : __cmp ( x , y ) < = 0 ) )
2024-02-11 21:38:29 -08:00
# define __ge(x, y) (bool)(_Generic(x, int8_t: x >= y, int16_t: x >= y, int32_t: x >= y, int64_t: x >= y, float: x >= y, double: x >= y, bool: x >= y, \
2024-02-10 14:36:04 -08:00
default : __cmp ( x , y ) > = 0 ) )
2024-02-11 21:38:29 -08:00
# define __gt(x, y) (bool)(_Generic(x, int8_t: x > y, int16_t: x > y, int32_t: x > y, int64_t: x > y, float: x > y, double: x > y, bool: x > y, \
2024-02-10 14:36:04 -08:00
default : __cmp ( x , y ) > 0 ) )
2024-02-11 21:38:29 -08:00
# define __eq(x, y) (bool)(_Generic(x, int8_t: x == y, int16_t: x == y, int32_t: x == y, int64_t: x == y, float: x == y, double: x == y, bool: x == y, \
2024-02-10 14:36:04 -08:00
default : __cmp ( x , y ) = = 0 ) )
2024-02-11 21:38:29 -08:00
# define __ne(x, y) (bool)(_Generic(x, int8_t: x != y, int16_t: x != y, int32_t: x != y, int64_t: x != y, float: x != y, double: x != y, bool: x != y, \
2024-02-10 14:36:04 -08:00
default : __cmp ( x , y ) ! = 0 ) )
# define min(x, y) ({ __declare(__min_lhs, x); __declare(__min_rhs, y); __le(__min_lhs, __min_rhs) ? __min_lhs : __min_rhs; })
# define max(x, y) ({ __declare(__min_lhs, x); __declare(__min_rhs, y); __ge(__min_lhs, __min_rhs) ? __min_lhs : __min_rhs; })
2024-02-04 15:04:41 -08:00
2024-02-10 14:36:04 -08:00
# define say(str) puts(CORD_to_const_char_star(__cord(str)))
2024-02-11 20:09:00 -08:00
# define __test(src, expr, expected) do { \
CORD __result = __cord ( expr ) ; \
2024-02-11 23:10:10 -08:00
say ( CORD_catn ( 5 , USE_COLOR ? " \x1b [33;1m>> \x1b [0m " : " >> " , src , USE_COLOR ? " \n \x1b [0;2m= \x1b [0;35m " : " \n = " , __result , " \x1b [m " ) ) ; \
2024-02-11 20:09:00 -08:00
if ( expected & & CORD_cmp ( __result , expected ) ) { \
errx ( 1 , " I expected: \n %s but got: \n %s " , CORD_to_const_char_star ( expected ) , CORD_to_const_char_star ( __result ) ) ; \
} \
} while ( 0 )
2024-02-10 12:23:06 -08:00
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0