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 }; })
19 #define newt(t, c) eC_new(class_ ## t->structSize * c)
21 #define class_vtbl_setup(c) \
22 { typedef void (* Function)(void *); delete [] (Function *)_class->data; _class->data = new Function [_class->vTblSize]; \
23 memset(_class->data, 0, sizeof(Function) * _class->vTblSize); } \
25 #define _REGISTER_CLASS(n, ns, bs, a) \
26 n::class_registration((Class *)eC_registerClass(normalClass, ns, bs, sizeof(Instance *), 0, \
27 (eC_bool (*)(void *)) n::constructor, (void(*)(void *)) n::destructor, (a).impl, privateAccess, publicAccess))
29 // For defining _class and registereing together (single translation unit)
30 #define REGISTER_CLASS_DEF(n, b, a) CPPClass<n> n::_class(_REGISTER_CLASS(n, #n, b::_class.impl->name, a));
32 // For defining _class and registering separately (multiple translation units)
33 #define CLASS_DEF(n) CPPClass<n> n::_class;
34 #define REGISTER_CLASS(n, b, a) n::_class.impl = _REGISTER_CLASS(n, #n, b::_class.impl->name, a);
36 // For C++ classes proxying eC classes:
37 #define REGISTER_CPP_CLASS(n, a) n::_class.impl = _REGISTER_CLASS(n, "CPP" #n, #n, a);
39 #define _CONSTRUCT(c, b) \
40 static CPPClass<c> _class; \
41 static eC_bool constructor(eC_Instance i) { if(!Class_isDerived(i->_class, _class.impl)) return new c(i) != null; return true;} \
42 static void destructor(eC_Instance i) { c * inst = (c *)_INSTANCE(i, _class.impl); if(_class.destructor) ((void (*)(c & self))_class.destructor)(*inst); delete inst; } \
43 explicit inline c(eC_Instance _impl, Class * cl = _class.impl) : b(_impl, cl)
45 #define CONSTRUCT(c, b) \
46 c() : c(Instance_new(_class.impl), _class.impl) { } \
49 #define APP_CONSTRUCT(c, b) \
50 inline c() : c(eC_init_CALL) { } \
53 #if !defined(__WIN32__) || defined(__CONSOLE_APP__)
54 #define APP_SET_ARGS(a) eC_setArgs(app, argc, argv)
56 #define APP_SET_ARGS(a)
59 #define MAIN_DEFINITION \
64 unloadTranslatedStrings(MODULE_NAME); \
65 return app.exitCode; \
68 #define SELF(c, n) c * self = ((c *)(((char *)this) - (char *)&((c *)0)->n))
70 #define VIRTUAL_METHOD(n, c, b, r, p, sp, d) \
71 struct c ## _ ## n ## _Functor \
74 typedef r (* FunctionType)p; \
75 FunctionType operator= (FunctionType func) \
78 if(self->vTbl == c::_class.impl->data) \
80 uint size = c :: _class.impl->vTblSize; \
81 self->vTbl = (void (**)())new FunctionType[size]; \
82 memcpy(self->vTbl, c::_class.impl->data, sizeof(FunctionType) * size); \
84 ((FunctionType *)self->vTbl)[b ## _ ## n ## _vTblID] = func; \
93 static void register_ ## n(Class * cl, c ## _ ## n ## _Functor::FunctionType func) \
95 ((c ## _ ## n ## _Functor::FunctionType *)cl->data)[b ## _ ## n ## _vTblID] = func; \
98 #define REGISTER_METHOD(ns, n, bc, c, r, p, o, a, ea, rv) \
99 addMethod(_class, ns, (void *) +[]p \
101 Class * cl = (Class *)o->_class; \
102 c * i = (c *)_INSTANCE(o, cl); \
105 int vid = bc ## _ ## n ## _vTblID; \
106 if(i->vTbl && i->vTbl[vid]) \
108 return ((bc ## _ ## n ## _Functor::FunctionType)i->vTbl[vid]) a; \
112 auto method = ((r (*) p)(class_ ## c->_vTbl)[bc ## _ ## n ## _vTblID]); \
113 if(method) return method ea; \
119 #define property(n, sg) struct n ## Prop { n ## Prop() { }; int _[0]; sg } n;
121 #define _set(t, n, d) \
122 inline t operator= (t v) \
129 #define set(t, n, d) \
131 inline n ## Prop & operator= (n ## Prop & prop) \
139 #define get(t, n, d) inline operator t () const { PSELF; d; }
141 extern "C" eC_Module ecere_init(eC_Module fromModule);
143 class Class : public eC_Class { };
150 void (*destructor)(T &);
153 CPPClass(Class * _impl) : impl(_impl) { }
157 delete [] (void (**)(void))impl->data;
161 // GENERATED: (Instance, Module and Application might require some custom tweaks...)
163 // Normal Class Definitions
167 static CPPClass<Instance> _class;
171 static eC_bool constructor(eC_Instance i) { if(!Class_isDerived(i->_class, _class.impl)) return new Instance(i) != null; return true; }
172 static void destructor(eC_Instance i) { Instance * inst = (Instance *)_INSTANCE(i, _class.impl); delete inst; }
174 inline explicit Instance(eC_Instance _impl, Class * c = _class.impl)
177 vTbl = c ? (void (**)(void))c->data : null;
180 if(c && !_INSTANCE(impl, c))
181 _INSTANCE(impl, c) = this;
194 if(impl && impl->_class)
196 Instance ** i = (Instance **)&INSTANCEL(impl, impl->_class);
199 if(vTbl && vTbl != impl->_class->data)
201 Instance_decref(impl);
205 inline Instance(const Instance & i)
217 static Class * class_registration(Class * _class) { return _class; }
220 class Module : public Instance
223 static CPPClass<Module> _class;
224 inline explicit Module(eC_Instance _impl, Class * c = _class.impl) : Instance(_impl, c) { }
227 void eC_cpp_init(Module & module);
228 void ecere_cpp_init(Module & module);
230 #define Application_class_registration(c, d) \
231 REGISTER_METHOD("Main", main, Application, d, void, (eC_Instance o), o, (*i), (o), );
233 class Application : public Module
236 APP_CONSTRUCT(Application, Module)
239 _INSTANCE(impl, impl->_class) = this;
240 vTbl = (void (**)(void))_class.impl->data;
242 // TODO: Omit this if we're linking against eC rt only
244 ecere_cpp_init(*this);
246 loadTranslatedStrings(null, MODULE_NAME);
250 static Class * class_registration(Class * _class) { Application_class_registration(_class, Application); class_vtbl_setup(_class); return _class; }
253 #define PSELF SELF(Application, exitCode)
254 property(exitCode, get(int, exitCode, return self ? _IPTR(self->impl, class_Application, class_members_Application)->exitCode : 0) );
256 VIRTUAL_METHOD(main, Application, Application, void, (Application &), (),
257 return Application_main(self->impl));
260 class Container : public Instance
263 CONSTRUCT(Container, Instance) { }
265 inline IteratorPointer getFirst(void) { return Container_getFirst(impl); }
266 inline IteratorPointer getLast(void) { return Container_getLast(impl); }
267 inline IteratorPointer getPrev(IteratorPointer * pointer) { return Container_getPrev(impl, pointer); }
268 inline IteratorPointer getNext(IteratorPointer * pointer) { return Container_getNext(impl, pointer); }
269 inline Container_D getData(IteratorPointer * pointer) { return (return Container_getData(impl, pointer); }
270 inline bool setData(IteratorPointer * pointer, Container_D data) { return Container_setData(impl, pointer, data); }
271 inline IteratorPointer getAtPosition(const Container_I pos, bool create, bool * justAdded) { return Container_getAtPosition(impl, pos, create, justAdded); }
272 inline IteratorPointer insert(IteratorPointer * after, Container_T value) { return Container_insert(impl, after, value); }
273 inline IteratorPointer add(Container_T value) { return Container_add(impl, value) }
274 inline void remove(IteratorPointer * it) { Container_remove(impl, it); }
275 inline void move(IteratorPointer * it, IteratorPointer * after) { Container_move(impl, it, after); }
276 inline void removeAll() { Container_removeAll(impl); }
277 inline void copy(Container <T> source) { Container_copy(impl, source); } // Container <T> source
278 inline IteratorPointer find(const Container_D value) { return Container_find(impl, value); }
279 inline void freeIterator(IteratorPointer * it) { Container_freeIterator(impl, it); }
280 inline int getCount() { return Container_getCount(impl); }
281 inline void free() { Container_free(impl); }
282 inline void deleteItem(IteratorPointer * i) { Container_deleteItem(impl, i); }
283 inline void takeOut(const Container_D d) { Container_takeOut(impl, d); }
287 // Non-Events like methods
288 // 1. The methods will call the eC methods through the C bindings
289 // 2. This shound end up calling static class virtual table if overriden
290 // 3. Registering a method (e.g. onRedraw) needs to call addMethod to update the virtual table, with C callback
292 class Array : Container
295 CONSTRUCT(Array, Container) { }
298 class CustomAVLTree : Container
301 CONSTRUCT(CustomAVLTree, Container) { }
304 class AVLTree : CustomAVLTree
307 CONSTRUCT(AVLTree, CustomAVLTree) { }
310 class Map : CustomAVLTree
313 CONSTRUCT(Map, CustomAVLTree) { }
316 class LinkList : Container
319 CONSTRUCT(LinkList, Container) { }
322 class List : LinkList
325 CONSTRUCT(List, LinkList) { }
328 class IOChannel : Instance
331 CONSTRUCT(IOChannel, Instance) { }
334 class SerialBuffer : IOChannel
337 CONSTRUCT(SerialBuffer, IOChannel) { }
340 class OldArray : Instance
343 CONSTRUCT(OldArray, Instance) { }
346 // How to handle inheritance from classes not loaded yet?
348 class ClassDesignerBase : Window
351 CONSTRUCT(ClassDesignerBase, Window) { }
353 class DesignerBase : Window
356 CONSTRUCT(DesignerBase, Window) { }