1 // Preprocessor directives can be added at the beginning (Can't store them in AST)
3 /****************************************************************************
4 ===========================================================================
6 ===========================================================================
7 ****************************************************************************/
8 #if !defined(__EC_HPP__)
13 // Syntactic Sugar (NOT GENERATED)
14 #define INSTANCEL(x, c) (*(void **)((char *)(x) + (c)->offset))
15 #define _INSTANCE(x, c) INSTANCEL((x) ? (x) : 0, c)
17 #define INSTANCE(x, c) ({c * _i = (c *)_INSTANCE(x, x->_class); _i ? *_i : c(x); })
20 #define newi(c) Instance_newEx(c, true)
22 #define _REGISTER_CLASS(n, ns, bs, a) \
23 (Class *)eC_registerClass(normalClass, ns, bs, sizeof(Instance *), 0, \
24 (eC_bool (*)(void *)) n::constructor, (void(*)(void *)) n::destructor, (a).impl, privateAccess, publicAccess)
26 // For defining _class and registereing together (single translation unit)
27 #define REGISTER_CLASS_DEF(n, b, a) TCPPClass<n> n::_class(_REGISTER_CLASS(n, #n, b::_class.impl->name, a));
29 // For defining _class and registering separately (multiple translation units)
30 #define CLASS_DEF(n) TCPPClass<n> n::_class;
31 #define REGISTER_CLASS(n, b, a) n::_class.setup(_REGISTER_CLASS(n, #n, b::_class.impl->name, a));
33 // For C++ classes proxying eC classes:
34 #define REGISTER_CPP_CLASS(n, a) n::_class.setup(_REGISTER_CLASS(n, "CPP" #n, #n, a));
36 #define _CONSTRUCT(c, b) \
37 INSTANCE_VIRTUAL_METHODS(c) \
38 static TCPPClass<c> _class; \
39 static eC_bool constructor(eC_Instance i, eC_bool alloc) { return (alloc && !_INSTANCE(i, _class.impl)) ? new c(i, _class) != null : true; } \
40 static void destructor(eC_Instance i) { c * inst = (c *)_INSTANCE(i, _class.impl); if(_class.destructor) ((void (*)(c & self))_class.destructor)(*inst); delete inst; } \
41 explicit inline c(eC_Instance _impl, CPPClass & cl = _class) : b(_impl, cl)
43 #define CONSTRUCT(c, b) \
44 c() : c(Instance_newEx(_class.impl, false), _class) { } \
48 ((TCPPClass<c> &)_class).destructor
51 static void class_registration(CPPClass & _class)
53 #define APP_CONSTRUCT(c, b) \
54 inline c() : c(eC_init_CALL) { } \
57 #if !defined(__WIN32__) || defined(__CONSOLE_APP__)
58 #define APP_SET_ARGS(a) eC_setArgs(a.impl, argc, argv);
60 #define APP_SET_ARGS(a)
63 #define MAIN_DEFINITION \
64 extern "C" MAIN_DECLARATION \
68 unloadTranslatedStrings(MODULE_NAME); \
69 return app.exitCode; \
72 #define SELF(c, n) c * self = ((c *)(((char *)this) + 0x10 - (char *)&((c *)0x10)->n))
76 #define VIRTUAL_METHOD(n, c, b, r, p0, ep, p, d) \
77 struct c ## _ ## n ## _Functor \
80 typedef r (* FunctionType)(p0 p); \
81 inline FunctionType operator= (FunctionType func) \
84 if(self->vTbl == c::_class.vTbl) \
86 uint size = c :: _class.impl->vTblSize; \
87 self->vTbl = (void (**)())newt(FunctionType, size); \
88 memcpy(self->vTbl, c::_class.vTbl, sizeof(FunctionType) * size); \
90 ((FunctionType *)self->vTbl)[b ## _ ## n ## _vTblID] = func; \
93 inline r operator()(ep p) \
100 inline static void register_ ## n(CPPClass & cl, c ## _ ## n ## _Functor::FunctionType func) \
102 ((c ## _ ## n ## _Functor::FunctionType *)cl.vTbl)[b ## _ ## n ## _vTblID] = func; \
105 #define _REGISTER_METHOD(cp1, cp2, ns, n, bc, c, r, p, ocl, oi, code, ea, rv) \
106 addMethod(_class.impl, ns, (void *) +[]p \
108 Class * cl = (ocl) ? (Class *)(ocl)->_class : null; \
110 c * i = (oi) ? (c *)_INSTANCE(oi, cl) : null; \
111 int vid = bc ## _ ## n ## _vTblID; \
112 bc ## _ ## n ## _Functor::FunctionType fn; \
113 if(i && i->vTbl && i->vTbl[vid]) \
115 fn = (bc ## _ ## n ## _Functor::FunctionType) i->vTbl[vid]; \
121 auto method = ((r (*) p)(class_ ## c->_vTbl)[bc ## _ ## n ## _vTblID]); \
122 if(method) return method ea; \
127 #define REGISTER_METHOD(ns, n, bc, c, r, p, ocl, oi, code, ea, rv) \
128 _REGISTER_METHOD(,, ns, n, bc, c, r, p, ocl, oi, code, ea, rv)
130 #define REGISTER_TYPED_METHOD(ns, n, bc, c, r, p, ocl, oi, code, ea, rv) \
132 CPPClass * cppcl = _class ? (CPPClass *)_class->bindingsClass : null;, \
133 else if(cppcl && cppcl->vTbl && cppcl->vTbl[vid]) \
135 fn = (bc ## _ ## n ## _Functor::FunctionType) cppcl->vTbl[vid]; \
138 ns, n, bc, c, r, p, ocl, oi, code, ea, rv)
140 #define property(n, sg) struct n ## Prop { n ## Prop() { }; int _[0]; sg } n;
142 #define _set(t, n, c, d) \
143 inline t operator= (t v) \
150 #define set(t, n, c, d) \
152 inline n ## Prop & operator= (n ## Prop & prop) \
160 #define get(t, n, c, d) inline operator t () const { SELF(c, n); d; }
162 extern "C" eC_Module ecere_init(eC_Module fromModule);
164 class Class : public eC_Class { };
169 typedef void (* Function)(void);
172 inline CPPClass() { };
173 inline CPPClass(const CPPClass & c) = delete;
174 inline CPPClass(const CPPClass && c)
182 class TCPPClass : public CPPClass
186 TCPPClass(Class * _impl)
190 void (*destructor)(T &);
191 void setup(Class * _impl)
196 _impl->bindingsClass = this;
197 if(vTbl) eC_delete(vTbl);
198 vTbl = newt(Function, impl->vTblSize);
199 memset(vTbl, 0, sizeof(Function) * impl->vTblSize);
200 T::class_registration(*this);
210 // GENERATED: (Instance, Module and Application might require some custom tweaks...)
212 #define Instance_onDisplay_vTblID onDisplay_vTblID
213 #define Instance_onCompare_vTblID onCompare_vTblID
214 #define Instance_onCopy_vTblID onCopy_vTblID
215 #define Instance_onFree_vTblID onFree_vTblID
216 #define Instance_onGetString_vTblID onGetString_vTblID
217 #define Instance_onGetDataFromString_vTblID onGetDataFromString_vTblID
218 #define Instance_onEdit_vTblID onEdit_vTblID
219 #define Instance_onSerialize_vTblID onSerialize_vTblID
220 #define Instance_onUnserialize_vTblID onUnserialize_vTblID
221 #define Instance_onSaveEdit_vTblID onSaveEdit_vTblID
223 // Normal Class Definitions
225 #define Instance_class_registration(d) \
226 REGISTER_TYPED_METHOD("OnCompare", onCompare, Instance, d, int, (Class * _class, eC_Instance o, eC_Instance o2), \
227 o, o, return fn(*i, *(Instance *)INSTANCEL(o2, o2->_class)), (_class, o, o2), 1); \
228 REGISTER_TYPED_METHOD("OnDisplay", onDisplay, Instance, d, void, (Class * _class, eC_Instance o, eC_Instance /*eC_Surface */ s, int x, int y, int w, void * f, Alignment a, DataDisplayFlags df), \
229 o, o, Surface surface(s); fn(*i, surface, x, y, w, f, a, df), (_class, o, s, x, y, w, f, a, df), ); \
230 REGISTER_TYPED_METHOD("OnCopy", onCopy, Instance, d, void, (Class * _class, eC_Instance * dest, eC_Instance src), \
231 src, dest ? *dest : null, fn(*i, *(Instance *)INSTANCEL(src, src->_class) ), (_class, dest, src), ); \
232 REGISTER_TYPED_METHOD("OnFree", onFree, Instance, d, void, (Class * _class, eC_Instance o), \
233 o, o, fn(*i), (_class, o), ); \
234 REGISTER_TYPED_METHOD("OnGetString", onGetString, Instance, d, constString, (Class * _class, eC_Instance o, String tempString, void * fieldData, eC_bool * needClass), \
235 o, o, bool nc; constString r = fn(*i, tempString, fieldData, needClass ? &nc : null); if(needClass) *needClass = nc; return r;, (_class, o, tempString, fieldData, needClass), (constString)null); \
236 REGISTER_TYPED_METHOD("OnGetDataFromString", onGetDataFromString, Instance, d, bool, (Class * _class, eC_Instance * o, constString string), \
237 o ? *o : null, o ? *o : null, return fn(*i, string); , (_class, o, string), false); \
238 REGISTER_TYPED_METHOD("OnSerialize", onSerialize, Instance, d, void, (Class * _class, eC_Instance o, eC_Instance /*eC_IOChannel*/ c), \
239 o, o, IOChannel * ref = (IOChannel *)_INSTANCE(c, c->_class); if(ref) fn(*i, *ref); else { IOChannel channel(c); fn(*i, channel); }, (_class, o, c), ); \
240 REGISTER_TYPED_METHOD("OnUnserialize", onUnserialize, Instance, d, void, (Class * _class, eC_Instance * o, eC_Instance /*eC_IOChannel*/ c), \
241 o ? *o : null, o, IOChannel * ref = (IOChannel *)_INSTANCE(c, c->_class); if(ref) fn(*i, *ref); else { IOChannel channel(c); fn(*i, channel); }, (_class, o, c), ); \
242 REGISTER_TYPED_METHOD("OnSaveEdit", onSaveEdit, Instance, d, bool, (Class * _class, eC_Instance * o, eC_Instance /*eC_Window*/ w, void * object), \
243 o ? *o : null, o, Window * ref = (Window *)_INSTANCE(w, w->_class); if(ref) return fn(*i, *ref, object); else { Window window(w); return fn(*i, window, object); }, (_class, o, w, object), false); \
244 REGISTER_TYPED_METHOD("OnEdit", onEdit, Instance, d, eC_Window, (Class * _class, eC_Instance o, eC_Instance /*eC_DataBox */db, void * obsolete, int x, int y, int w, int h, void * userData), \
246 Window /*DataBox*/ * ref = (Window /*DataBox*/ *)_INSTANCE(db, db->_class); \
248 if(ref) ret = &fn(*i, *ref, obsolete, x, y, w, h, userData); \
249 else { Window /*DataBox */dataBox(db); \
250 ret = &fn(*i, dataBox, obsolete, x, y, w, h, userData); } \
251 return ret ? ret->impl : null;, \
252 (_class, o, db, obsolete, x, y, w, h, userData), (eC_Window)null);
254 #define INSTANCE_VIRTUAL_METHODS(c) \
255 VIRTUAL_METHOD(onCompare, c, Instance, \
256 int, c & _ARG, , c & b, \
257 return Instance_onCompare(_class.impl, self ? self->impl : (eC_Instance)null, &b ? b.impl : (eC_Instance)null)); \
258 VIRTUAL_METHOD(onCopy, c, Instance, \
259 void, c & _ARG, , c & src, \
260 return Instance_onCopy(_class.impl, self->impl, &src ? src.impl : (eC_Instance)null)); \
261 VIRTUAL_METHOD(onDisplay, c, Instance, \
262 void, c & _ARG, , Surface & surface _ARG int x _ARG int y _ARG int w _ARG void * fieldData _ARG Alignment alignment _ARG DataDisplayFlags flags, \
263 Instance_onDisplay(_class.impl, self ? self->impl : (eC_Instance)null, &surface ? ((Instance *)&surface)->impl : (eC_Instance)null, x, y, w, fieldData, alignment, flags)); \
264 VIRTUAL_METHOD(onFree, c, Instance, \
266 return Instance_onFree(_class.impl, self->impl)); \
267 VIRTUAL_METHOD(onGetString, c, Instance, \
268 constString, c & _ARG, , String tempString _ARG void * fieldData _ARG bool * needClass, \
269 return Instance_onGetString(_class.impl, self ? self->impl : (eC_Instance)null, tempString, fieldData, needClass)); \
270 VIRTUAL_METHOD(onGetDataFromString, c, Instance, \
271 bool, c & _ARG, , constString string, \
272 return Instance_onGetDataFromString(_class.impl, self->impl, string)); \
273 VIRTUAL_METHOD(onSerialize, c, Instance, \
274 void, c & _ARG, , IOChannel & channel, \
275 return Instance_onSerialize(_class.impl, self ? self->impl : (eC_Instance)null, &channel ? ((Instance *)&channel)->impl : (eC_Instance)null)); \
276 VIRTUAL_METHOD(onUnserialize, c, Instance, \
277 void, c & _ARG, , IOChannel & channel, \
278 return Instance_onUnserialize(_class.impl, self->impl, &channel ? ((Instance *)&channel)->impl : (eC_Instance)null)); \
279 VIRTUAL_METHOD(onSaveEdit, c, Instance, \
280 bool, c & _ARG, , Window & window _ARG void * object, \
281 return Instance_onSaveEdit(_class.impl, self->impl, &window ? ((Instance *)&window)->impl : (eC_Instance)null, object)); \
282 VIRTUAL_METHOD(onEdit, c, Instance, \
283 Window &, c & _ARG, , Window /*DataBox*/ & dataBox _ARG void * obsolete _ARG int x _ARG int y _ARG int w _ARG int h _ARG void * userData, \
284 eC_Window window = Instance_onEdit(_class.impl, self->impl, &dataBox ? ((Instance *)&dataBox)->impl : (eC_Instance)null, obsolete, x, y, w, h, userData); \
285 return *(Window *)_INSTANCE(window, window->_class); );
292 typedef eC_Window eC_DataBox;
294 typedef uint32 Alignment;
295 typedef uint32 DataDisplayFlags;
300 static TCPPClass<Instance> _class;
304 void * operator new (uintsize count) { return eC_new(count); }
305 void * operator new [](uintsize count) { return eC_new(count); }
306 void operator delete (void * ptr) { eC_delete(ptr); }
307 void operator delete [](void * ptr) { eC_delete(ptr); }
309 static eC_bool constructor(eC_Instance i, bool alloc)
311 if(alloc &&!_INSTANCE(i, _class.impl))
312 return new Instance(i, _class) != null;
315 static void destructor(eC_Instance i) { Instance * inst = (Instance *)_INSTANCE(i, _class.impl); delete inst; }
316 static void class_registration(CPPClass & _class);
318 INSTANCE_VIRTUAL_METHODS(Instance);
320 inline explicit Instance(eC_Instance _impl, CPPClass & cl = _class)
327 if(c && !_INSTANCE(impl, c))
328 _INSTANCE(impl, c) = this;
339 if(impl && impl->_class)
341 if(impl->_class->bindingsClass)
343 Instance ** i = (Instance **)&INSTANCEL(impl, impl->_class);
348 CPPClass * cl = (CPPClass *)impl->_class->bindingsClass;
349 if(cl && vTbl != cl->vTbl)
353 Instance_decref(impl);
356 inline Instance(const Instance & i) = delete;
357 inline Instance(const Instance && i)
364 class Module : public Instance
367 static TCPPClass<Module> _class;
368 inline explicit Module(eC_Instance _impl, CPPClass & c = _class) : Instance(_impl, c) { }
371 void eC_cpp_init(Module & module);
372 void ecere_cpp_init(Module & module);
374 #define Application_class_registration(d) \
375 REGISTER_METHOD("Main", main, Application, d, void, (eC_Instance o), o, o, return fn(*i), (o), );
377 class Application : public Module
380 APP_CONSTRUCT(Application, Module)
383 _INSTANCE(impl, impl->_class) = this;
387 // TODO: Omit this if we're linking against eC rt only
389 ecere_cpp_init(*this);
392 loadTranslatedStrings(null, MODULE_NAME);
396 static void class_registration(CPPClass & _class) { Application_class_registration(Application); }
398 property(exitCode, get(int, exitCode, Application, return self ? _IPTR(self->impl, class_Application, class_members_Application)->exitCode : 0) );
400 VIRTUAL_METHOD(main, Application, Application, void, Application &, , ,
401 return Application_main(self->impl));
404 class Container : public Instance
407 CONSTRUCT(Container, Instance) { }
409 inline IteratorPointer getFirst(void) { return Container_getFirst(impl); }
410 inline IteratorPointer getLast(void) { return Container_getLast(impl); }
411 inline IteratorPointer getPrev(IteratorPointer * pointer) { return Container_getPrev(impl, pointer); }
412 inline IteratorPointer getNext(IteratorPointer * pointer) { return Container_getNext(impl, pointer); }
413 inline Container_D getData(IteratorPointer * pointer) { return (return Container_getData(impl, pointer); }
414 inline bool setData(IteratorPointer * pointer, Container_D data) { return Container_setData(impl, pointer, data); }
415 inline IteratorPointer getAtPosition(const Container_I pos, bool create, bool * justAdded) { return Container_getAtPosition(impl, pos, create, justAdded); }
416 inline IteratorPointer insert(IteratorPointer * after, Container_T value) { return Container_insert(impl, after, value); }
417 inline IteratorPointer add(Container_T value) { return Container_add(impl, value) }
418 inline void remove(IteratorPointer * it) { Container_remove(impl, it); }
419 inline void move(IteratorPointer * it, IteratorPointer * after) { Container_move(impl, it, after); }
420 inline void removeAll() { Container_removeAll(impl); }
421 inline void copy(Container <T> source) { Container_copy(impl, source); } // Container <T> source
422 inline IteratorPointer find(const Container_D value) { return Container_find(impl, value); }
423 inline void freeIterator(IteratorPointer * it) { Container_freeIterator(impl, it); }
424 inline int getCount() { return Container_getCount(impl); }
425 inline void free() { Container_free(impl); }
426 inline void deleteItem(IteratorPointer * i) { Container_deleteItem(impl, i); }
427 inline void takeOut(const Container_D d) { Container_takeOut(impl, d); }
431 // Non-Events like methods
432 // 1. The methods will call the eC methods through the C bindings
433 // 2. This shound end up calling static class virtual table if overriden
434 // 3. Registering a method (e.g. onRedraw) needs to call addMethod to update the virtual table, with C callback
436 class Array : public Container
439 CONSTRUCT(Array, Container) { }
442 class CustomAVLTree : public Container
445 CONSTRUCT(CustomAVLTree, Container) { }
448 class AVLTree : public CustomAVLTree
451 CONSTRUCT(AVLTree, CustomAVLTree) { }
454 class Map : public CustomAVLTree
457 CONSTRUCT(Map, CustomAVLTree) { }
460 class LinkList : public Container
463 CONSTRUCT(LinkList, Container) { }
466 class List : public LinkList
469 CONSTRUCT(List, LinkList) { }
472 class IOChannel : public Instance
475 CONSTRUCT(IOChannel, Instance) { }
478 class SerialBuffer : public IOChannel
481 CONSTRUCT(SerialBuffer, IOChannel) { }
484 class OldArray : public Instance
487 CONSTRUCT(OldArray, Instance) { }
490 // How to handle inheritance from classes not loaded yet?
492 class ClassDesignerBase : public Window
495 CONSTRUCT(ClassDesignerBase, Window) { }
497 class DesignerBase : public Window
500 CONSTRUCT(DesignerBase, Window) { }