undar-lang/test/plex.c

697 lines
12 KiB
C

#define __UNDAR_ARENA_SIZE__ 64000
#if defined(__has_include)
#if __has_include(<stdint.h>)
#define HAVE_STDINT 1
#endif
#if __has_include(<stdbool.h>)
#define HAVE_STDBOOL 1
#endif
#if __has_include(<stddef.h>)
#define HAVE_STDDEF 1
#endif
#endif
#ifdef HAVE_STDINT
#include <stdint.h>
typedef uint8_t u8;
typedef int8_t i8;
typedef uint16_t u16;
typedef int16_t i16;
typedef uint32_t u32;
typedef int32_t i32;
typedef int32_t r32;
typedef float f32;
#else
typedef unsigned char u8;
typedef signed char i8;
typedef unsigned short u16;
typedef signed short i16;
typedef unsigned int u32;
typedef signed int i32;
typedef signed int r32;
typedef float f32;
#endif
#ifdef HAVE_STDBOOL
#include <stdbool.h>
#else
#define true 1
#define false 0
typedef u8 bool;
#endif
#ifdef HAVE_STDDEF
#include <stddef.h>
#define nil NULL
#else
#define nil ((void *)0)
#endif
#define I8_MIN -128
#define I8_MAX 127
#define U8_MAX 255
#define I16_MIN -32768
#define I16_MAX 32767
#define U16_MAX 65535
#define I32_MIN -2147483648
#define I32_MAX 2147483647
#define U32_MAX 4294967295
#define FIXED_CONST 65536.0f
#define AS_INT(v) ((i32)(v))
#define AS_NAT(v) ((u32)(v))
#define AS_REAL(v) ((r32)(v))
#define FLOAT_TO_REAL(v) (((r32)(v)) * FIXED_CONST)
#define REAL_TO_FLOAT(v) (((f32)(v)) / FIXED_CONST)
#define USED(x) ((void)(x))
#define MAX_LEN_REAL32 12
#define MAX_LEN_INT32 11
const char radix_set[11] = "0123456789";
typedef struct arena_s Arena;
struct arena_s {
u8 *tape;
u32 count;
u32 capacity;
};
typedef bool (*compare_fn)(void *data, void *target);
typedef bool (*list_iter_fn)(void *data);
static inline void
mcpy(void *to, void *from, u32 length)
{
u8 *src, *dest;
if(to == nil || from == nil) return;
src = (u8 *)from;
dest = (u8 *)to;
while(length-- > 0) *(dest++) = *(src++);
return;
}
static inline i32
scpy(char *to, const char *from, u32 length)
{
u32 i;
if(to == nil || from == nil) return -1;
if(length == 0) return 0;
for(i = 0; i < length && from[i] != '\0'; i++) to[i] = from[i];
to[i] = '\0';
return 0;
}
static inline bool
seq(const char *s1, const char *s2)
{
if(s1 == nil && s2 == nil) return true;
if(s1 == nil || s2 == nil) return false;
while(*s1 && *s2) {
if(*s1 != *s2) return false;
s1++;
s2++;
}
return (*s1 == '\0' && *s2 == '\0');
}
static inline bool
sleq(const char *s1, const char *s2, u32 length)
{
u32 i;
if(s1 == nil && s2 == nil) return true;
if(s1 == nil || s2 == nil) return false;
i = 0;
while(i < length && *s1 && *s2) {
if(*s1 != *s2) return false;
s1++;
s2++;
i++;
}
if(i == length) return true;
return (*s1 == '\0' && *s2 == '\0');
}
static inline u32
slen(const char *str)
{
u32 i;
if(str == nil) return 0;
for(i = 0; str[i] != '\0'; i++);
return i;
}
static inline u32
snlen(const char *str, u32 max_len)
{
u32 i;
if(str == nil) return 0;
for(i = 0; i < max_len && str[i] != '\0'; i++);
return i;
}
u8 tape[__UNDAR_ARENA_SIZE__];
Arena arena = {tape, 0, __UNDAR_ARENA_SIZE__};
static inline void *
aalloc(u32 size)
{
u32 pos;
if(arena.count + size > arena.capacity) return nil;
pos = arena.count;
arena.count += size;
return (void *)&arena.tape[pos];
}
static inline void *
aend()
{
i32 pos = arena.count;
return (void *)&arena.tape[pos];
}
static inline void *
areturn(u32 checkpoint, const void *src, u32 size)
{
void *dest;
if(src == nil) return nil;
u32 current = arena.count;
dest = (void *)&arena.tape[checkpoint];
if(src == dest) return dest;
mcpy(dest, (void *)src, size);
arena.count = checkpoint + size;
// zero out the end of the memory copy (for strings mostly)
arena.tape[arena.count] = 0;
return dest;
}
#define ARENA_RETURN(ckpt, src_ptr, type) \
return (type *)areturn((ckpt), (src_ptr), sizeof(type))
#define ARENA_RETURN_ARRAY(ckpt, src_ptr, type, count) \
return (type *)areturn((ckpt), (src_ptr), sizeof(type) * (count))
#define ARENA_RETURN_STR(ckpt, src_ptr) \
return (char *)areturn((ckpt), (src_ptr), slen(src_ptr))
#define ARENA_RETURN_STRBUF(ckpt, sbuf) \
char *to_return = StrBuf_toS(sbuf); \
return (char *)areturn((ckpt), (to_return), slen(to_return))
static inline r32
int_to_real(i32 i)
{
return i << 16;
}
static inline i32
real_to_int(r32 f)
{
return f >> 16;
}
static inline r32
float_to_real(f32 f)
{
return FLOAT_TO_REAL(f);
}
static inline f32
real_to_float(r32 r)
{
return REAL_TO_FLOAT(r);
}
static inline r32
real_add(r32 a, r32 b)
{
return a + b;
}
static inline r32
real_sub(r32 a, r32 b)
{
return a - b;
}
static inline r32
real_mul(r32 a, r32 b)
{
r32 src1_whole = (r32)a >> 16;
r32 src2_whole = (r32)b >> 16;
r32 src1_decimal = (r32)a & 16;
r32 src2_decimal = (r32)b & 16;
r32 result = 0;
result += (src1_whole * src2_whole) << 16;
result += (src1_whole * src2_decimal);
result += (src1_decimal * src2_whole);
result += ((src1_decimal * src2_decimal) >> 16) & 16;
return result;
}
static inline r32
real_div(r32 a, r32 b)
{
r32 result;
r32 src1_val = (r32)a;
r32 src2_val = (r32)b;
u32 src2_reciprocal = 1;
src2_reciprocal <<= 31;
src2_reciprocal = (u32)(src2_reciprocal / src2_val);
result = src1_val * src2_reciprocal;
result <<= 1;
return result;
}
static inline r32
real_eq(r32 a, r32 b)
{
return a == b;
}
static inline r32
real_ne(r32 a, r32 b)
{
return a != b;
}
static inline r32
real_lt(r32 a, r32 b)
{
return a < b;
}
static inline r32
real_le(r32 a, r32 b)
{
return a <= b;
}
static inline r32
real_gt(r32 a, r32 b)
{
return a > b;
}
static inline r32
real_ge(r32 a, r32 b)
{
return a >= b;
}
static inline r32
real_neg(r32 f)
{
return -f;
}
static inline r32
real_abs(r32 f)
{
return (f < 0) ? -f : f;
}
static inline char *
ascpy(const char *start, u32 length)
{
char *str;
if(!start) return nil;
str = (char *)aalloc(length + 1);
if(!str) return nil;
scpy(str, start, length);
return str;
}
static inline void *
amcpy(void *from, u32 length)
{
void *ptr;
if(!from) return nil;
ptr = aalloc(length);
if(!ptr) return nil;
mcpy(ptr, from, length);
return ptr;
}
static inline char*
int_to_string(i32 v)
{
char buffer[MAX_LEN_INT32] = {0};
i32 n;
u32 i = MAX_LEN_INT32;
bool neg;
n = v;
neg = n < 0;
if(neg) n = -n;
do {
buffer[--i] = radix_set[n % 10];
n /= 10;
} while(n > 0);
if(neg) buffer[--i] = '-';
/* Ensure at least one digit is written for 0 */
if(v == 0) buffer[--i] = '0';
return ascpy(buffer + i, MAX_LEN_INT32 - i);
}
static inline char*
nat_to_string(u32 v)
{
char buffer[MAX_LEN_INT32] = {0};
u32 n;
u32 i = MAX_LEN_INT32;
n = v;
do {
buffer[--i] = radix_set[n % 10];
n /= 10;
} while(n > 0);
/* Ensure at least one digit is written for 0 */
if(v == 0) buffer[--i] = '0';
return ascpy(buffer + i, MAX_LEN_INT32 - i);
}
static inline char*
real_to_string(r32 q)
{
char buffer[MAX_LEN_REAL32] = {0};
bool neg;
i32 int_part;
u32 frac_part;
u32 i = MAX_LEN_REAL32;
if(q < 0) q = -q;
int_part = q >> 16;
frac_part = q & 0xFFFF;
do {
buffer[--i] = radix_set[frac_part % 10];
frac_part /= 10;
} while(frac_part > 0);
buffer[--i] = '.';
neg = int_part < 0;
if(neg) int_part = -int_part;
do {
buffer[--i] = radix_set[int_part % 10];
int_part /= 10;
} while(int_part > 0);
if(neg) buffer[--i] = '-';
return ascpy(buffer + i, MAX_LEN_REAL32 - i);
}
typedef struct node_s Node;
struct node_s {
u32 size;
struct node_s *next;
};
typedef struct list_s List;
struct list_s {
Node *head;
Node *tail;
u32 count;
};
typedef bool (*compare_fn)(void *data, void *target);
typedef bool (*list_iter_fn)(void *data);
List *
List_init(Arena *arena)
{
List *l = (List*)aalloc(sizeof(List));
if (!l) return nil;
l->head = nil;
l->tail = nil;
l->count = 0;
return l;
}
void *
node_value(Node *n)
{
return (void *)((u8 *)n + sizeof(Node));
}
void *
List_push(List *list, void *data, u32 data_size)
{
void *dest;
void *ptr = aalloc(sizeof(Node) + data_size);
Node *node = (Node *)ptr;
if (!node) return nil;
node->size = data_size;
node->next = nil;
if (!list->head) {
list->head = list->tail = node;
} else {
list->tail->next = node;
list->tail = node;
}
list->count++;
dest = node_value(node);
if (data && data_size > 0) {
mcpy(dest, data, data_size);
}
return dest;
}
void
List_map(List *list, list_iter_fn func)
{
Node *curr;
if (!list || !func) return;
curr = list->head;
while (curr) {
if (!func(node_value(curr))) break;
curr = curr->next;
}
}
void *
List_get(List *list, u32 index)
{
u32 i;
Node *curr;
if (!list || index >= list->count) return nil;
curr = list->head;
for (i = 0; i < index; i++) {
curr = curr->next;
}
return node_value(curr);
}
void
List_set(List *list, u32 index, void *data, u32 size)
{
void *target = List_get(list, index);
if (!target) return;
mcpy(target, data, size);
}
void *
List_find(List *list, compare_fn compare, void *target)
{
Node *curr;
void *data;
if (!list || !compare) return nil;
curr = list->head;
while (curr) {
data = node_value(curr);
if (compare(data, target)) {
return data;
}
curr = curr->next;
}
return nil;
}
typedef struct strbuf_s StrBuf;
struct strbuf_s {
Node *head;
Node *tail;
u32 count;
};
StrBuf *
StrBuf_init()
{
StrBuf *l = (StrBuf*)aalloc(sizeof(StrBuf));
if (!l) return nil;
l->head = nil;
l->tail = nil;
l->count = 0;
return l;
}
void *
StrBuf_append(StrBuf *buf, char *str)
{
u32 length = slen(str);
void *dest;
void *ptr = aalloc(sizeof(Node) + length);
Node *node = (Node *)ptr;
if (!node) return nil;
node->next = nil;
node->size = length;
if (!buf->head) {
buf->head = buf->tail = node;
} else {
buf->tail->next = node;
buf->tail = node;
}
buf->count++;
dest = node_value(node);
if (str && length > 0) {
mcpy(dest, str, length);
}
return dest;
}
char *
StrBuf_toS(StrBuf *buf)
{
Node *curr;
char *tmp_str;
char *str = (char *)aend();
if (!buf || !str) return nil;
curr = buf->head;
while (curr) {
tmp_str = node_value(curr);
amcpy(tmp_str, curr->size);
curr = curr->next;
}
return str;
}
#include <stdio.h>
typedef struct Point Point;
struct Point {
u32 x;
u32 y;
};
Point *
Point_init(u32 x, u32 y)
{
Point *this = (Point *)aalloc(sizeof(Point));
this->x = x;
this->y = y;
return this;
}
char*
Point_toS(Point *this)
{
u32 __UNDAR_FN_CHECKPOINT_REF__ = arena.count;
StrBuf *buf = StrBuf_init();
StrBuf_append(buf, "[x:");
StrBuf_append(buf,nat_to_string(this->x));
StrBuf_append(buf, ", y:");
StrBuf_append(buf,nat_to_string(this->y));
StrBuf_append(buf, "]");
ARENA_RETURN_STRBUF(__UNDAR_FN_CHECKPOINT_REF__, buf);
}
typedef struct Rect Rect;
struct Rect {
Point top_left;
Point bottom_right;
u32 width;
u32 height;
};
Rect *
Rect_init(Point *tl, Point *br, u32 width, u32 height)
{
Rect *this = (Rect *)aalloc(sizeof(Rect));
mcpy(&this->top_left, tl, sizeof(Point));
mcpy(&this->bottom_right, br, sizeof(Point));
this->width = width;
this->height = height;
return this;
}
char*
Rect_toS(Rect *this)
{
u32 __UNDAR_FN_CHECKPOINT_REF__ = arena.count;
StrBuf *buf = StrBuf_init();
StrBuf_append(buf, "[top_left: ");
StrBuf_append(buf,Point_toS(&this->top_left));
StrBuf_append(buf,", bottom_right: ");
StrBuf_append(buf,Point_toS(&this->bottom_right));
StrBuf_append(buf, ", width:");
StrBuf_append(buf,nat_to_string(this->width));
StrBuf_append(buf, ", height:");
StrBuf_append(buf,nat_to_string(this->height));
StrBuf_append(buf, "]");
ARENA_RETURN_STRBUF(__UNDAR_FN_CHECKPOINT_REF__, buf);
}
Rect *
create_geometry()
{
u32 __UNDAR_FN_CHECKPOINT_REF__ = arena.count;
Point *tl = Point_init(10, 20);
Point *br = Point_init(100, 200);
Rect *final_rect = Rect_init(tl, br, 90, 180);
ARENA_RETURN(__UNDAR_FN_CHECKPOINT_REF__, final_rect, Rect);
}
int main() {
Rect *r = create_geometry();
printf("%s\n", Rect_toS(r));
return 0;
}