]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/oo.qh
Implement CONSTRUCTOR
[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
26
27 #define entityclass(...) OVERLOAD(entityclass, __VA_ARGS__)
28 #define entityclass_1(name) entityclass_2(name, Object)
29 #ifndef QCC_SUPPORT_ENTITYCLASS
30     #define entityclass_2(name, base) typedef entity name
31     #define class(name)
32     #define new(class) __spawn(#class, __FILE__, __LINE__)
33 #else
34     #define entityclass_2(name, base) entityclass name : base {}
35     #define class(name) [[class(name)]]
36     #define new(class) ((class) __spawn(#class, __FILE__, __LINE__))
37 #endif
38
39 // Classes have a `spawn##cname(entity)` constructor
40 // The parameter is used across [[accumulate]] functions
41
42 // Macro to hide this implementation detail
43 #define NEW(cname, ...) \
44     OVERLOAD(spawn##cname, new(cname), ##__VA_ARGS__)
45
46 #define CONSTRUCTOR(cname, ...) \
47     cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__)
48
49 .string vtblname;
50 .entity vtblbase;
51
52 void RegisterClasses() { }
53 ACCUMULATE_FUNCTION(__static_init, RegisterClasses)
54
55 #define VTBL(cname, base) \
56     INIT_STATIC(cname); \
57     entity cname##_vtbl; \
58     void cname##_vtbl_init() { \
59         cname e = new(vtbl); \
60         spawn##cname##_static(e); \
61         e.vtblname = #cname; \
62         /* Top level objects refer to themselves */ \
63         e.vtblbase = base##_vtbl ? base##_vtbl : e; \
64         cname##_vtbl = e; \
65     } \
66     ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init)
67
68 #define INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this)
69 #define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this)
70
71 #define CLASS(cname, base)                  \
72     entityclass(cname, base);               \
73     class(cname) .bool instanceOf##cname;   \
74     VTBL(cname, base)                       \
75     INIT_STATIC(cname) {                    \
76         if (cname##_vtbl) {                 \
77             copyentity(cname##_vtbl, this); \
78             return;                         \
79         }                                   \
80         spawn##base##_static(this);         \
81         this.instanceOf##cname = true;      \
82     }                                       \
83     INIT(cname) {                           \
84         /* Only statically initialize the current class, it contains everything it inherits */ \
85         if (cname##_vtbl.vtblname == this.classname) { \
86             spawn##cname##_static(this);    \
87             this.classname = #cname;        \
88             this.vtblname = string_null;    \
89             this.vtblbase = cname##_vtbl;   \
90         }                                   \
91         spawn##base##_1(this);              \
92     }
93
94 #define METHOD(cname, name, prototype)      \
95     class(cname) .prototype name;           \
96     prototype cname##_##name;               \
97     INIT_STATIC(cname) { this.name = cname##_##name; }
98
99 #define ATTRIB(cname, name, type, val)      \
100     class(cname) .type name;                \
101     INIT(cname) { this.name = val; }
102
103 #define ATTRIBARRAY(cname, name, type, cnt) \
104     class(cname) .type name[cnt];
105
106 #define ENDCLASS(cname) \
107     [[last]] INIT(cname) { return this; }
108
109 #define SUPER(cname) (cname##_vtbl.vtblbase)
110
111 #define spawn_static(this)
112 #define spawn_1(this)
113 #define _vtbl NULL
114 CLASS(Object, ); ENDCLASS(Object)
115 #undef spawn_static
116 #undef spawn_1
117 #undef _vtbl
118
119 #endif