-#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; \
-}
+void RegisterClasses() { }
+ACCUMULATE_FUNCTION(__static_init, RegisterClasses)
+
+#define VTBL(cname, base) \
+ INIT_STATIC(cname); \
+ entity cname##_vtbl; \
+ void cname##_vtbl_init() { \
+ cname e = new(vtbl); \
+ spawn##cname##_static(e); \
+ e.vtblname = #cname; \
+ /* Top level objects refer to themselves */ \
+ e.vtblbase = base##_vtbl ? base##_vtbl : e; \
+ cname##_vtbl = e; \
+ } \
+ ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init)
+
+#define INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this)
+#define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this)
+
+#define CLASS(cname, base) \
+ entityclass(cname, base); \
+ class(cname) .bool instanceOf##cname; \
+ VTBL(cname, base) \
+ INIT_STATIC(cname) { \
+ if (cname##_vtbl) { \
+ copyentity(cname##_vtbl, this); \
+ return; \
+ } \
+ spawn##base##_static(this); \
+ this.instanceOf##cname = true; \
+ } \
+ INIT(cname) { \
+ /* Only statically initialize the current class, it contains everything it inherits */ \
+ if (cname##_vtbl.vtblname == this.classname) { \
+ spawn##cname##_static(this); \
+ this.classname = #cname; \
+ this.vtblname = string_null; \
+ this.vtblbase = cname##_vtbl; \
+ } \
+ spawn##base##_1(this); \
+ }
+
+#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(cname) { return this; }