]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/oo.qh
Cleanup OO macros
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / oo.qh
1 #ifndef OO_H
2 #define OO_H
3
4 #include "registry.qh"
5
6 #ifdef MENUQC
7     #define NULL (null_entity)
8 #else
9     #define NULL (world)
10 #endif
11
12 .string classname;
13 /** Location entity was spawned from in source */
14 .string sourceLocFile;
15 .int sourceLocLine;
16 entity _spawn();
17 entity __spawn(string _classname, string _sourceFile, int _sourceLine) {
18     entity this = _spawn();
19     this.classname = _classname;
20     this.sourceLocFile = _sourceFile;
21     this.sourceLocLine = _sourceLine;
22     return this;
23 }
24
25 #define entityclass(...) OVERLOAD(entityclass, __VA_ARGS__)
26 #define entityclass_1(name) entityclass_2(name, Object)
27 #ifndef QCC_SUPPORT_ENTITYCLASS
28     #define entityclass_2(name, base) typedef entity name
29     #define class(name)
30     #define new(class) __spawn(#class, __FILE__, __LINE__)
31 #else
32     #define entityclass_2(name, base) entityclass name : base {}
33     #define class(name) [[class(name)]]
34     #define new(class) ((class) __spawn(#class, __FILE__, __LINE__))
35 #endif
36
37 // Classes have a `spawn##cname(entity)` constructor
38 // The parameter is used across [[accumulate]] functions
39
40 // Macro to hide this implementation detail
41 #define NEW(cname) (spawn##cname(new(cname)))
42
43 .string vtblname;
44 .entity vtblbase;
45
46 #define VTBL(cname, base) \
47     entity cname##_vtbl; \
48     STATIC_INIT(cname##_vtbl) { \
49         entity e = NEW(cname); \
50         e.vtblname = #cname; \
51         e.classname = "vtbl"; \
52         /* Top level objects refer to themselves */ \
53         e.vtblbase = base ? base : e; \
54         cname##_vtbl = e; \
55     }
56
57 #define INIT_STATIC(cname) [[accumulate]] entity spawn##cname(entity this)
58 #define INIT(cname) [[accumulate]] void spawn##cname##_init(entity this)
59
60 #define CLASS(cname, base)                  \
61     entityclass(cname, base);               \
62     class(cname) .bool instanceOf##cname;   \
63     INIT(cname) { }                         \
64     INIT_STATIC(cname);                     \
65     VTBL(cname, base##_vtbl)                \
66     INIT_STATIC(cname) {                    \
67         if (cname##_vtbl) {                 \
68             copyentity(cname##_vtbl, this); \
69             spawn##cname##_init(this);      \
70             return this;                    \
71         }                                   \
72         spawn##base(this);                  \
73         this.instanceOf##cname = true;      \
74     }
75
76 #define METHOD(cname, name, prototype)      \
77     class(cname) .prototype name;           \
78     prototype cname##_##name;               \
79     INIT_STATIC(cname) { this.name = cname##_##name; }
80
81 #define ATTRIB(cname, name, type, val)      \
82     class(cname) .type name;                \
83     INIT(cname) { this.name = val; }
84
85 #define ATTRIBARRAY(cname, name, type, cnt) \
86     class(cname) .type name[cnt];
87
88 #define ENDCLASS(cname) \
89     [[last]] INIT_STATIC(cname) { return this; }
90
91 #define SUPER(cname) (cname##_vtbl.vtblbase)
92
93 #define spawnNULL(e)
94 #define NULL_vtbl NULL
95
96 CLASS(Object, NULL)
97 ENDCLASS(Object)
98
99 #endif