From: TimePath Date: Thu, 13 Aug 2015 08:13:53 +0000 (+1000) Subject: Cleanup OO macros X-Git-Tag: xonotic-v0.8.2~2073^3~4 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=08fe11af2394bba3cbeae74370269d6c63840969;p=xonotic%2Fxonotic-data.pk3dir.git Cleanup OO macros --- diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src index 94c92a54c..d161c6dfc 100644 --- a/qcsrc/client/progs.src +++ b/qcsrc/client/progs.src @@ -2,6 +2,7 @@ ../common/util-pre.qh ../dpdefs/csprogsdefs.qh +../common/util-post.qh announcer.qc bgmscript.qc diff --git a/qcsrc/common/oo.qh b/qcsrc/common/oo.qh index 63b17089e..b2b8b0ad2 100644 --- a/qcsrc/common/oo.qh +++ b/qcsrc/common/oo.qh @@ -1,71 +1,99 @@ #ifndef OO_H #define OO_H +#include "registry.qh" + #ifdef MENUQC - #define NULL (null_entity) + #define NULL (null_entity) #else - #define NULL (world) + #define NULL (world) #endif .string classname; -.string vtblname; -.entity vtblbase; -entity spawnVtbl(entity this, entity base) -{ - entity vtbl = spawn(); - copyentity(this, vtbl); - vtbl.vtblname = vtbl.classname; - vtbl.classname = "vtbl"; - vtbl.vtblbase = base ? base : vtbl; // Top level objects use vtbl as base - return vtbl; +/** 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; } -entity Object_vtbl; -entity spawnObject(entity this, entity) -{ - this = spawn(); - this.classname = "Object"; - if (!Object_vtbl) Object_vtbl = spawnVtbl(this, NULL); - 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, entity)` constructor -// The parameters are used as locals for [[accumulate]] +// 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(NULL, NULL)) +#define NEW(cname) (spawn##cname(new(cname))) -#define CLASS(cname, base) \ -entity spawn##cname(entity this, entity basevtbl) { \ - this = NEW(base); basevtbl = base##_vtbl; \ -} +.string vtblname; +.entity vtblbase; -#define METHOD(cname, name, prototype) \ -prototype cname##_##name; \ -.prototype name; \ -[[accumulate]] entity spawn##cname(entity this, entity basevtbl) { \ - this.name = cname##_##name; \ -} +#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 ATTRIB(cname, name, type, val) \ -.type name; \ -[[accumulate]] entity spawn##cname(entity this, entity basevtbl) { \ - this.name = val; \ -} +#define INIT_STATIC(cname) [[accumulate]] entity spawn##cname(entity this) +#define INIT(cname) [[accumulate]] void spawn##cname##_init(entity this) -#define ATTRIBARRAY(cname, name, type, cnt) \ -.type name[cnt]; - -#define ENDCLASS(cname) \ -.bool instanceOf##cname; \ -entity cname##_vtbl; \ -[[accumulate]] [[last]] entity spawn##cname(entity this, entity basevtbl) { \ - this.instanceOf##cname = true; \ - this.classname = #cname; \ - if (!cname##_vtbl) cname##_vtbl = spawnVtbl(this, basevtbl); \ - return 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 diff --git a/qcsrc/common/registry.qh b/qcsrc/common/registry.qh index 4c24b491d..0087c1bf7 100644 --- a/qcsrc/common/registry.qh +++ b/qcsrc/common/registry.qh @@ -1,6 +1,8 @@ #ifndef REGISTRY_H #define REGISTRY_H +#include "util.qh" + #define REGISTER_INIT(ns, id) [[accumulate]] void Register_##ns##_##id##_init(entity this) #define REGISTER(initfunc, ns, array, counter, id, class, fld) \ @@ -20,4 +22,9 @@ void __static_init() { } #define static_init() CALL_ACCUMULATED_FUNCTION(__static_init) #define REGISTER_REGISTRY(func) ACCUMULATE_FUNCTION(__static_init, func) +#define STATIC_INIT(func) \ + void _static_##func(); \ + ACCUMULATE_FUNCTION(__static_init, _static_##func) \ + void _static_##func() + #endif diff --git a/qcsrc/common/util-post.qh b/qcsrc/common/util-post.qh new file mode 100644 index 000000000..6d1ab21f9 --- /dev/null +++ b/qcsrc/common/util-post.qh @@ -0,0 +1,8 @@ +#ifndef UTIL_POST_H +#define UTIL_POST_H + +#define spawn() new(entity) + +#include "oo.qh" + +#endif diff --git a/qcsrc/common/util-pre.qh b/qcsrc/common/util-pre.qh index 9d60ae0a9..e68199855 100644 --- a/qcsrc/common/util-pre.qh +++ b/qcsrc/common/util-pre.qh @@ -37,16 +37,6 @@ const int false = 0; #endif -#ifndef QCC_SUPPORT_ENTITYCLASS - #define entityclass(name) typedef entity name - #define class(name) - #define new(class) spawn() -#else - #define entityclass(name) entityclass name {} - #define class(name) [[class(name)]] - #define new(class) ((class) spawn()) -#endif - // Transitional aliases [[deprecated("use true")]] [[alias("true")]] const bool TRUE; [[deprecated("use false")]] [[alias("false")]] const bool FALSE; diff --git a/qcsrc/dpdefs/csprogsdefs.qh b/qcsrc/dpdefs/csprogsdefs.qh index c4d8c54ce..b10ef09ba 100644 --- a/qcsrc/dpdefs/csprogsdefs.qh +++ b/qcsrc/dpdefs/csprogsdefs.qh @@ -8,6 +8,8 @@ #define TRUE _TRUE #define FALSE _FALSE +#define spawn _spawn + #include "upstream/csprogsdefs.qc" #undef true @@ -15,6 +17,8 @@ #undef TRUE #undef FALSE +#undef spawn + #pragma noref 0 #endif diff --git a/qcsrc/dpdefs/menudefs.qh b/qcsrc/dpdefs/menudefs.qh index dce99cde5..7d4dcc6af 100644 --- a/qcsrc/dpdefs/menudefs.qh +++ b/qcsrc/dpdefs/menudefs.qh @@ -8,6 +8,8 @@ #define TRUE _TRUE #define FALSE _FALSE +#define spawn _spawn + #include "upstream/menudefs.qc" #undef true @@ -15,6 +17,8 @@ #undef TRUE #undef FALSE +#undef spawn + int(string str, string sub, int startpos) _strstrofs = #221; #define strstrofs _strstrofs int(string str, int ofs) _str2chr = #222; diff --git a/qcsrc/dpdefs/progsdefs.qh b/qcsrc/dpdefs/progsdefs.qh index bffacafdd..c2440d3da 100644 --- a/qcsrc/dpdefs/progsdefs.qh +++ b/qcsrc/dpdefs/progsdefs.qh @@ -8,6 +8,8 @@ #define TRUE _TRUE #define FALSE _FALSE +#define spawn _spawn + #include "upstream/progsdefs.qc" #undef true @@ -15,6 +17,8 @@ #undef TRUE #undef FALSE +#undef spawn + #pragma noref 0 #endif diff --git a/qcsrc/menu/progs.src b/qcsrc/menu/progs.src index 2315616d1..a35fd484f 100644 --- a/qcsrc/menu/progs.src +++ b/qcsrc/menu/progs.src @@ -3,6 +3,7 @@ ../common/util-pre.qh ../dpdefs/menudefs.qh ../dpdefs/keycodes.qh +../common/util-post.qh oo/classes.qc diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index 2d110d2f9..388d1b675 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -5,6 +5,7 @@ sys-pre.qh ../dpdefs/progsdefs.qh ../dpdefs/dpextensions.qh sys-post.qh +../common/util-post.qh anticheat.qc antilag.qc