#include #include struct class_typeinfo { char *name; }; typedef struct class_typeinfo class_typeinfo; #define METHODS(methods...) methods #define MEMBERS(members...) members #define CLASS_VTBL(name) _##name##_vtable_ #define CLASS_MTHD(name, method) _##name##_##method##_ #define CLASS_DECL(name, methods, members) \ typedef struct name name; \ struct CLASS_VTBL(name) { \ void (*init)(name *); \ void (*destroy)(name *); \ class_typeinfo typeinfo; \ methods \ }; \ struct CLASS_VTBL(name) CLASS_VTBL(name); \ struct name { \ struct CLASS_VTBL(name) vtable; \ members \ }; #define ARGS(args...) args #define IMPLEMENT(class, method, return_t, args, body...) \ return_t CLASS_MTHD(class, method)(args) { \ body \ } #define CTOR(class, body...) \ void _##class##_init##_(class *self) { \ body \ } #define DTOR(class, body...) \ void _##class##_destroy##_(class *self) { \ body \ } #define NEW(class) \ class *tmpname = malloc(sizeof(class)); \ tmpname->vtable = CLASS_VTBL(class); \ tmpname->vtable.init(tmpname); #define METHODCALL(object, method, args...) \ object->vtable.method(object, ## args) CLASS_DECL(foo, METHODS( int (*inc)(foo *self); int (*dec)(foo *self); void (*set)(foo *self, int new_value); int (*get)(foo *self); ), MEMBERS( int local; ) ); CTOR(foo, self->local = 0; ); DTOR(foo, {}); IMPLEMENT(foo, inc, int, ARGS(foo *self), self->local += 1; return self->local; ); IMPLEMENT(foo, dec, int, ARGS(foo *self), self->local -= 1; return self->local; ); IMPLEMENT(foo, set, void, ARGS(foo *self, int new_value), self->local = new_value; ); IMPLEMENT(foo, get, int, ARGS(foo *self), return self->local; ); int main() { // until I figure out how to actually put these in the struct AOT. CLASS_VTBL(foo).init = _foo_init_; CLASS_VTBL(foo).destroy = _foo_destroy_; CLASS_VTBL(foo).inc = _foo_inc_; CLASS_VTBL(foo).dec = _foo_dec_; CLASS_VTBL(foo).set = _foo_set_; CLASS_VTBL(foo).get = _foo_get_; NEW(foo); foo *obj = tmpname; printf("obj->local starts at %i\n", obj->local); METHODCALL(obj, inc); METHODCALL(obj, inc); METHODCALL(obj, dec); printf("obj->inc() returns %i\n", METHODCALL(obj, inc)); METHODCALL(obj, set, 10); printf("obj->get() after setting to 10 is %i\n", METHODCALL(obj, get)); }