From 05f23c25078dc0d1661fe61a20d45e60ca9d83e8 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Mon, 12 Feb 2024 00:18:55 -0500 Subject: [PATCH] Initial working version of generic cord func --- .gitignore | 1 + Makefile | 5 ++- metamethods/cord.c | 100 +++++++++++++++++++++++++++++++++++++++++++++ nextlang.c | 2 +- nextlang.h | 2 + 5 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 metamethods/cord.c diff --git a/.gitignore b/.gitignore index 0c13ec3..53d5ccb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.o +*.so nextlang tags diff --git a/Makefile b/Makefile index 4b183a6..1460ad5 100644 --- a/Makefile +++ b/Makefile @@ -26,10 +26,13 @@ LDLIBS=-lgc -lgccjit -lcord -lm -lunistring BUILTIN_OBJS=builtins/array.o builtins/bool.o builtins/builtins.o builtins/char.o builtins/floats.o builtins/functions.o builtins/integers.o \ builtins/memory.o builtins/string.o builtins/table.o builtins/types.o -all: nextlang +all: nextlang libnext.so nextlang: nextlang.c parse.o files.o util.o ast.o compile.o types.o SipHash/halfsiphash.o $(BUILTIN_OBJS) +libnext.so: metamethods/cord.o util.o SipHash/halfsiphash.o + $(CC) $^ $(CFLAGS) $(EXTRA) $(CWARN) $(G) $(O) $(OSFLAGS) $(LDLIBS) -Wl,-soname,libnext.so -shared -o $@ + SipHash/halfsiphash.c: git submodule update --init --recursive diff --git a/metamethods/cord.c b/metamethods/cord.c new file mode 100644 index 0000000..4243ffb --- /dev/null +++ b/metamethods/cord.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include + +#include "../util.h" + +typedef CORD (*custom_cord_func)(void *x, void *userdata); + +typedef struct { + void *data; + int64_t length:42; + uint8_t free:4; + bool copy_on_write:1, atomic:1; + int16_t stride:16; +} generic_array_t; + +static CORD vas_cord(void *x, const char **fmt, va_list args) +{ + char c = **fmt; + ++(*fmt); + switch (c) { + case '@': case '?': { + if (!x) + return CORD_asprintf("%c%r", vas_cord(NULL, fmt, args)); + void *ptr = *(void**)x; + return CORD_cat(ptr ? (c == '@' ? "@" : "?") : "!", vas_cord(ptr, fmt, args)); + } + case 'B': { + if (!x) return "Bool"; + return *(bool*)x ? "yes" : "no"; + } + case 'I': { + size_t bits = va_arg(args, size_t); + switch (bits) { + case 64: + return x ? CORD_asprintf("%ld", *(int64_t*)x) : "Int64"; + case 32: + return x ? CORD_asprintf("%d", *(int32_t*)x) : "Int32"; + case 16: + return x ? CORD_asprintf("%d", *(int16_t*)x) : "Int16"; + case 8: + return x ? CORD_asprintf("%d", *(int8_t*)x) : "Int8"; + default: errx(1, "Unsupported Int precision: %ld", bits); + } + } + case 'N': { + size_t bits = va_arg(args, size_t); + switch (bits) { + case 64: + return x ? CORD_asprintf("%g", *(double*)x) : "Num64"; + case 32: + return x ? CORD_asprintf("%g", *(double*)x) : "Num32"; + default: errx(1, "Unsupported Num precision: %ld", bits); + } + } + case 'S': { + return x ? *(CORD*)x : "Str"; + } + case '[': { + if (!x) { + CORD cord = CORD_asprintf("[%r]", vas_cord(NULL, fmt, args)); + if (**fmt == ']') + ++(*fmt); + return cord; + } + CORD cord = "["; + generic_array_t *arr = x; + for (int64_t i = 0; i < arr->length; i++) { + const char *item_fmt = *fmt; + va_list args_copy; + va_copy(args_copy, args); + if (i > 0) cord = CORD_cat(cord, ", "); + CORD item_cord = vas_cord(arr->data + i*arr->stride, &item_fmt, args_copy); + cord = CORD_cat(cord, item_cord); + va_end(args_copy); + } + (void)vas_cord(NULL, fmt, args); + if (**fmt == ']') ++(*fmt); + return CORD_cat(cord, "]"); + } + case '_': { + custom_cord_func fn = va_arg(args, custom_cord_func); + void *arg = va_arg(args, void*); + return fn(x, arg); + } + default: errx(1, "Unsupported format specifier: '%c'", c); + } + errx(1, "Unreachable"); +} + +public CORD as_cord(void *x, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + CORD ret = vas_cord(x, &fmt, args); + va_end(args); + return ret; +} diff --git a/nextlang.c b/nextlang.c index aa1c1e9..92ec411 100644 --- a/nextlang.c +++ b/nextlang.c @@ -116,7 +116,7 @@ int main(int argc, char *argv[]) if (!cflags) cflags = "-std=c11"; - const char *ldlibs = "-lgc -lcord -lm"; + const char *ldlibs = "-lgc -lcord -lm -L. -lnext"; if (getenv("LDLIBS")) ldlibs = heap_strf("%s %s", ldlibs, getenv("LDLIBS")); diff --git a/nextlang.h b/nextlang.h index 4f4a3b2..39cc2c4 100644 --- a/nextlang.h +++ b/nextlang.h @@ -30,6 +30,8 @@ #define __Array(t) array_t +CORD as_cord(void *x, const char *fmt, ...); + #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", \