#ifndef OO_H #define OO_H #include "registry.qh" #ifdef MENUQC #define NULL (null_entity) #else #define NULL (world) #endif .string classname; /** Location entity was spawned from in source */ .string sourceLocFile; .int sourceLocLine; entity _spawn(); entity __spawn(string _classname, string _sourceFile, int _sourceLine) { entity this = _spawn(); this.classname = _classname; this.sourceLocFile = _sourceFile; this.sourceLocLine = _sourceLine; return this; } #define entityclass(...) OVERLOAD(entityclass, __VA_ARGS__) #define entityclass_1(name) entityclass_2(name, Object) #ifndef QCC_SUPPORT_ENTITYCLASS #define entityclass_2(name, base) typedef entity name #define class(name) #define new(class) __spawn(#class, __FILE__, __LINE__) #else #define entityclass_2(name, base) entityclass name : base {} #define class(name) [[class(name)]] #define new(class) ((class) __spawn(#class, __FILE__, __LINE__)) #endif // Classes have a `spawn##cname(entity)` constructor // The parameter is used across [[accumulate]] functions // Macro to hide this implementation detail #define NEW(cname) (spawn##cname(new(cname))) .string vtblname; .entity vtblbase; #define VTBL(cname, base) \ entity cname##_vtbl; \ STATIC_INIT(cname##_vtbl) { \ entity e = NEW(cname); \ e.vtblname = #cname; \ e.classname = "vtbl"; \ /* Top level objects refer to themselves */ \ e.vtblbase = base ? base : e; \ cname##_vtbl = e; \ } #define INIT_STATIC(cname) [[accumulate]] entity spawn##cname(entity this) #define INIT(cname) [[accumulate]] void spawn##cname##_init(entity this) #define CLASS(cname, base) \ entityclass(cname, base); \ class(cname) .bool instanceOf##cname; \ INIT(cname) { } \ INIT_STATIC(cname); \ VTBL(cname, base##_vtbl) \ INIT_STATIC(cname) { \ if (cname##_vtbl) { \ copyentity(cname##_vtbl, this); \ spawn##cname##_init(this); \ return this; \ } \ spawn##base(this); \ this.instanceOf##cname = true; \ } #define METHOD(cname, name, prototype) \ class(cname) .prototype name; \ prototype cname##_##name; \ INIT_STATIC(cname) { this.name = cname##_##name; } #define ATTRIB(cname, name, type, val) \ class(cname) .type name; \ INIT(cname) { this.name = val; } #define ATTRIBARRAY(cname, name, type, cnt) \ class(cname) .type name[cnt]; #define ENDCLASS(cname) \ [[last]] INIT_STATIC(cname) { return this; } #define SUPER(cname) (cname##_vtbl.vtblbase) #define spawnNULL(e) #define NULL_vtbl NULL CLASS(Object, NULL) ENDCLASS(Object) #endif