tomo/nextlang.h

99 lines
5.0 KiB
C
Raw Normal View History

2024-02-04 15:04:41 -08:00
#pragma once
#include <err.h>
2024-02-04 15:04:41 -08:00
#include <gc.h>
#include <gc/cord.h>
2024-02-13 10:32:08 -08:00
#include <signal.h>
2024-02-04 15:04:41 -08:00
#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 Int_t int64_t
#define I64(x) ((int64_t)x)
#define I32(x) ((int32_t)x)
#define I16(x) ((int16_t)x)
#define I8(x) ((int8_t)x)
2024-02-04 15:04:41 -08:00
#define Num64_t double
#define Num32_t float
#define Num_t double
2024-02-04 15:04:41 -08:00
#define String_t CORD
2024-02-13 19:13:54 -08:00
#define Str_t CORD
2024-02-04 15:04:41 -08:00
#define Bool_t bool
2024-02-12 00:00:31 -08:00
#define yes (Bool_t)true
#define no (Bool_t)false
2024-02-04 15:04:41 -08:00
#define Void_t void
2024-02-14 10:28:28 -08:00
#define $Array(t) array_t
2024-02-04 15:04:41 -08:00
2024-02-12 00:00:31 -08:00
CORD as_cord(void *x, bool use_color, const char *fmt, ...);
2024-02-17 11:47:14 -08:00
#define StrF(...) ({ CORD $c; CORD_sprintf(&$c, __VA_ARGS__); $c; })
2024-02-14 10:28:28 -08:00
#define $var(var, val) __typeof(val) var = val
#define $cord(x) _Generic(x, bool: x ? "yes" : "no", \
2024-02-17 11:47:14 -08:00
int8_t: StrF("%d", x), \
int16_t: StrF("%d", x), \
int32_t: StrF("%d", x), int64_t: StrF("%ld", x), \
double: StrF("%g", x), float: StrF("%g", x), \
2024-02-04 15:04:41 -08:00
CORD: x, \
2024-02-14 10:28:28 -08:00
array_t: as_cord($stack(x), false, "[ ]"), \
2024-02-04 15:04:41 -08:00
default: "???")
2024-02-14 10:28:28 -08:00
#define $heap(x) (__typeof(x)*)memcpy(GC_MALLOC(sizeof(x)), (__typeof(x)[1]){x}, sizeof(x))
#define $stack(x) (__typeof(x)*)((__typeof(x)[1]){x})
#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
2024-02-14 10:28:28 -08:00
#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__}; \
($Array(__typeof(x))){.length=sizeof($items)/sizeof($items[0]), \
.stride=(int64_t)&$items[1] - (int64_t)&$items[0], \
.data=memcpy(GC_MALLOC(sizeof($items)), $items, sizeof($items)), \
2024-02-04 18:13:50 -08:00
.copy_on_write=1}; })
#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-14 10:28:28 -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)))
#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, \
default: $cmp(x, y) < 0))
#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, \
default: $cmp(x, y) <= 0))
#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, \
default: $cmp(x, y) >= 0))
#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, \
default: $cmp(x, y) > 0))
#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, \
default: $cmp(x, y) == 0))
#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, \
default: $cmp(x, y) != 0))
#define min(x, y) ({ $var($min_lhs, x); $var($min_rhs, y); $le($min_lhs, $min_rhs) ? $min_lhs : $min_rhs; })
#define max(x, y) ({ $var($min_lhs, x); $var($min_rhs, y); $ge($min_lhs, $min_rhs) ? $min_lhs : $min_rhs; })
2024-02-04 15:04:41 -08:00
2024-02-14 10:28:28 -08:00
#define say(str) puts(CORD_to_const_char_star($cord(str)))
#define $test(src, expr, expected) do { \
CORD $result = $cord(expr); \
CORD $output = CORD_catn(5, USE_COLOR ? "\x1b[33;1m>>\x1b[0m " : ">> ", src, USE_COLOR ? "\n\x1b[0;2m=\x1b[m " : "\n= ", $result, "\x1b[m"); \
puts(CORD_to_const_char_star($output)); \
if (expected && CORD_cmp($result, expected)) { \
fprintf(stderr, USE_COLOR ? "\x1b[31;1;7mTEST FAILURE!\x1b[27m\nI expected:\n\t\x1b[0;1m%s\x1b[1;31m\nbut got:\n\t%s\x1b[m\n" : "TEST FAILURE!\nI expected:\n\t%s\nbut got:\n\t%s\n", CORD_to_const_char_star(expected), CORD_to_const_char_star($result)); \
2024-02-13 10:32:08 -08:00
raise(SIGABRT); \
} \
} while (0)
2024-02-10 12:23:06 -08:00
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0