Last active
November 8, 2024 16:14
-
-
Save agrif/6127126 to your computer and use it in GitHub Desktop.
a horrible, horrible, wonderful C Preprocessor hack library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __CO_BASIC_H_INCLUDED__ | |
#define __CO_BASIC_H_INCLUDED__ | |
/* useful stuff, usable without the rest of Cobalt */ | |
#include <string.h> | |
#define co_strcmp(a, b) strcmp(a, b) | |
#include <stdlib.h> | |
#define co_malloc(x) malloc(x) | |
#define co_free(x) free(x) | |
#define co_alloca(x) alloca(x) | |
#include <assert.h> | |
#define co_assert(test) assert(test) | |
#define co_runtime_assert(test) co_assert(test) | |
#define co_num_elements(array) (sizeof(array) / sizeof((array)[0])) | |
#endif /* __CO_BASIC_H_INCLUDED__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __CO_BOOTSTRAP_H_INCLUDED__ | |
#define __CO_BOOTSTRAP_H_INCLUDED__ | |
/* things that nice C environments provide, but not all */ | |
#ifndef bool | |
#define bool int | |
#endif | |
#ifndef false | |
#define false (0) | |
#endif | |
#ifndef true | |
#define true (!false) | |
#endif | |
#endif /* __CO_BOOTSTRAP_H_INCLUDED__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "co-iterate.h" | |
void* _co_iterate_initialize(void* obj, void* helper) | |
{ | |
co_runtime_assert(obj); | |
co_runtime_assert(helper); | |
const CoIterate* iface = co_implementation(obj, CoIterate); | |
co_runtime_assert(iface); | |
co_runtime_assert(iface->initialize); | |
iface->initialize(obj, helper); | |
return helper; | |
} | |
bool co_iterate_next(void* obj, void* helper, void** out) | |
{ | |
co_runtime_assert(obj); | |
co_runtime_assert(helper); | |
co_runtime_assert(out); | |
const CoIterate* iface = co_implementation(obj, CoIterate); | |
co_runtime_assert(iface); | |
co_runtime_assert(iface->next); | |
return iface->next(obj, helper, out); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __CO_ITERATE_H_INCLUDED__ | |
#define __CO_ITERATE_H_INCLUDED__ | |
#include "co-type.h" | |
#include "co-basic.h" | |
typedef struct | |
{ | |
size_t helper_size; | |
void (*initialize)(void*, void*); | |
bool (*next)(void*, void*, void**); | |
} CoIterate; | |
#define co_iterate_initialize(obj) \ | |
_co_iterate_initialize(obj, co_alloca(co_implementation(obj, CoIterate)->helper_size)) | |
void* _co_iterate_initialize(void* obj, void* helper); | |
bool co_iterate_next(void* obj, void* helper, void** out); | |
#define foreach(...) __foreach(__VA_ARGS__) | |
#define __foreach(x, haystack, astype) \ | |
for (astype* x, *__haystack = (astype*)haystack, *__iter = (astype*)co_iterate_initialize(__haystack); co_iterate_next((void*)__haystack, (void*)__iter, (void**)&x);) | |
#define in , | |
#define as , | |
#endif /* __CO_ITERATE_H_INCLUDED__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cobalt.h" | |
void* co_allocate_from_type(const CoType* type) | |
{ | |
co_runtime_assert(type); | |
const CoNew* inew = co_type_implementation(type, CoNew); | |
co_runtime_assert(inew); | |
void* data = co_malloc(inew->size + sizeof(CoTypeTag)) + sizeof(CoTypeTag); | |
co_runtime_assert(data); | |
CoTypeTag* tag = (data - sizeof(CoTypeTag)); | |
tag->type = type; | |
tag->on_heap = true; | |
return data; | |
} | |
void* co_new_from_type(const CoType* type) | |
{ | |
const CoNew* inew = co_type_implementation(type, CoNew); | |
co_runtime_assert(inew); | |
void* data = co_allocate_from_type(type); | |
if (inew->construct) | |
inew->construct(data); | |
return data; | |
} | |
#include <stdio.h> | |
void co_deallocate(void* obj) | |
{ | |
CoTypeTag* origaddr = obj - sizeof(CoTypeTag); | |
if (origaddr->on_heap) | |
co_free(origaddr); | |
} | |
void co_delete(void* obj) | |
{ | |
const CoNew* inew = co_implementation(obj, CoNew); | |
co_runtime_assert(inew); | |
if (inew->deconstruct) | |
inew->deconstruct(obj); | |
co_deallocate(obj); | |
} | |
void* co_construct(void* obj) | |
{ | |
const CoNew* inew = co_implementation(obj, CoNew); | |
co_runtime_assert(inew); | |
if (inew->construct) | |
inew->construct(obj); | |
return obj; | |
} | |
void co_deconstruct(void* obj) | |
{ | |
const CoNew* inew = co_implementation(obj, CoNew); | |
co_runtime_assert(inew); | |
if (inew->deconstruct) | |
inew->deconstruct(obj); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __CO_NEW_H_INCLUDED__ | |
#define __CO_NEW_H_INCLUDED__ | |
#include "co-type.h" | |
#include "co-basic.h" | |
typedef struct | |
{ | |
size_t size; | |
void (*construct)(void*); | |
void (*deconstruct)(void*); | |
} CoNew; | |
#define co_allocate(base) \ | |
(base*)co_allocate_from_type(((void)co_static_implementation(base, CoNew), co_static_type(base))) | |
#define co_new(base) \ | |
(base*)co_new_from_type(((void)co_static_implementation(base, CoNew), co_static_type(base))) | |
void* co_allocate_from_type(const CoType* type); | |
void* co_new_from_type(const CoType* type); | |
void co_deallocate(void* obj); | |
void co_delete(void* obj); | |
#define co_allocatea(base) \ | |
((base*)(memcpy(co_alloca(sizeof(CoTypeTag) + co_static_implementation(base, CoNew)->size), (CoTypeTag[]){{co_static_type(base), false}}, sizeof(CoTypeTag)) + sizeof(CoTypeTag))) | |
#define co_newa(base) \ | |
((base*)co_construct(co_allocatea(base))) | |
#define co_allocatea_with_value(base, ...) \ | |
((base*)memcpy(co_allocatea(base), (base[]){__VA_ARGS__}, sizeof(base))) | |
void* co_construct(void* obj); | |
void co_deconstruct(void* obj); | |
#endif /* __CO_NEW_H_INCLUDED__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "co-range.h" | |
static void co_range_construct(void* p) | |
{ | |
CoRange* self = p; | |
self->start = 0; | |
self->end = 0; | |
} | |
co_implementation_define(CoRange, CoNew) | |
{ | |
sizeof(CoRange), | |
co_range_construct, | |
NULL, | |
}; | |
static void co_range_initialize(void* p, void* h) | |
{ | |
CoRange* self = p; | |
int* helper = h; | |
*helper = self->start - 1; | |
} | |
static bool co_range_next(void* p, void* h, void** out) | |
{ | |
CoRange* self = p; | |
int* helper = h; | |
*helper += 1; | |
if (*helper >= self->end) | |
return false; | |
*out = helper; | |
return true; | |
} | |
co_implementation_define(CoRange, CoIterate) | |
{ | |
sizeof(int), | |
co_range_initialize, | |
co_range_next, | |
}; | |
co_type_define(CoRange) | |
{ | |
co_type_implements(CoRange, CoNew), | |
co_type_implements(CoRange, CoIterate), | |
co_type_end | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __CO_RANGE_H_INCLUDED__ | |
#define __CO_RANGE_H_INCULDED__ | |
#include "co-new.h" | |
#include "co-iterate.h" | |
typedef struct | |
{ | |
int start; | |
int end; | |
} CoRange; | |
co_type_export(CoRange); | |
co_implementation_export(CoRange, CoNew); | |
co_implementation_export(CoRange, CoIterate); | |
#define co_range(start, end) co_allocatea_with_value(CoRange, {(start), (end)}) | |
#endif /* __CO_RANGE_H_INCULDED__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __CO_TYPE_H_INCLUDED__ | |
#define __CO_TYPE_H_INCLUDED__ | |
#include "co-bootstrap.h" | |
typedef struct | |
{ | |
const char* name; | |
const void* value; | |
} CoInterfaceDef; | |
typedef struct | |
{ | |
CoInterfaceDef* defs; | |
} CoType; | |
typedef struct | |
{ | |
const CoType* type; | |
bool on_heap; | |
} CoTypeTag; | |
#define co_type_export(base) \ | |
extern const CoType base##_type | |
#define co_implementation_export(base, iface) \ | |
extern const iface base##_##iface##_implementation | |
#define co_static_implementation(base, iface) \ | |
(&base##_##iface##_implementation) | |
#define co_static_type(base) \ | |
(&base##_type) | |
#define co_type_define(base) \ | |
static CoInterfaceDef base##_interfaces[]; \ | |
const CoType base##_type = \ | |
{ \ | |
base##_interfaces, \ | |
}; \ | |
static CoInterfaceDef base##_interfaces[] = | |
#define co_type_implements(base, iface) \ | |
{#iface, co_static_implementation(base, iface)} | |
#define co_type_end \ | |
{NULL, NULL} | |
#define co_implementation_define(base, iface) \ | |
const iface base##_##iface##_implementation = | |
const CoType* co_type(void* obj); | |
#define co_type_implementation(type, iface) \ | |
((const iface*)co_type_implementation_with_name(type, #iface)) | |
#define co_implementation(obj, iface) \ | |
((const iface*)co_type_implementation_with_name(co_type(obj), #iface)) | |
const void* co_type_implementation_with_name(const CoType* type, const char* name); | |
#endif /* __CO_TYPE_H_INCLUDED__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cobalt.h" | |
const CoType* co_type(void* obj) | |
{ | |
co_runtime_assert(obj); | |
CoTypeTag* tag = (obj - sizeof(CoTypeTag)); | |
const CoType* type = tag->type; | |
co_runtime_assert(type); | |
co_runtime_assert(type->defs); | |
return type; | |
} | |
const void* co_type_implementation_with_name(const CoType* type, const char* name) | |
{ | |
co_runtime_assert(type); | |
co_runtime_assert(name); | |
size_t i; | |
for (i = 0; type->defs[i].name != NULL; i++) | |
{ | |
if (co_strcmp(type->defs[i].name, name) == 0) | |
{ | |
co_runtime_assert(type->defs[i].value); | |
return type->defs[i].value; | |
} | |
} | |
return NULL; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __COBALT_H_INCLUDED__ | |
#define __COBALT_H_INCLUDED__ | |
#include <stdlib.h> | |
#include "co-bootstrap.h" | |
#include "co-basic.h" | |
#include "co-type.h" | |
#include "co-new.h" | |
#include "co-iterate.h" | |
#include "co-range.h" | |
#endif /* __COBALT_H_INCLUDED__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
OBJECTS = cobalt.o co-new.o co-iterate.o co-range.o test.o | |
TARGET = test | |
CFLAGS = -Wall -Werror -std=gnu99 | |
.PHONY : all clean | |
all : ${TARGET} | |
clean : | |
rm -f ${TARGET} ${OBJECTS} | |
${TARGET} : ${OBJECTS} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cobalt.h" | |
#include <stdio.h> | |
int main(int argc, char** argv) | |
{ | |
foreach(x in co_range(0, 10) as int) | |
{ | |
printf("iterating %i\n", *x); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment