#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