bindings: Initial commit of C & C++ bindings prototype
[sdk] / bindings / cpp / eC.hpp
1 // Preprocessor directives can be added at the beginning (Can't store them in AST)
2
3 /****************************************************************************
4 ===========================================================================
5    Core eC Library
6 ===========================================================================
7 ****************************************************************************/
8 #if !defined(__EC_HPP__)
9 #define __EC_HPP__
10
11 #include "eC.h"
12
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)
16
17 #define INSTANCE(x, c) ({c * _i = (c *)_INSTANCE(x, x->_class); _i ? *_i : c { x }; })
18
19 #define newt(t, c) eC_new(class_ ## t->structSize * c)
20
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); } \
24
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))
28
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));
31
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);
35
36 // For C++ classes proxying eC classes:
37 #define REGISTER_CPP_CLASS(n, a)       n::_class.impl = _REGISTER_CLASS(n, "CPP" #n, #n, a);
38
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)
44
45 #define CONSTRUCT(c, b) \
46    c() : c(Instance_new(_class.impl), _class.impl) { } \
47    _CONSTRUCT(c, b)
48
49 #define APP_CONSTRUCT(c, b) \
50    inline c() : c(eC_init_CALL) { } \
51    _CONSTRUCT(c, b)
52
53 #if !defined(__WIN32__) || defined(__CONSOLE_APP__)
54    #define APP_SET_ARGS(a) eC_setArgs(app, argc, argv)
55 #else
56    #define APP_SET_ARGS(a)
57 #endif
58
59 #define MAIN_DEFINITION \
60    MAIN_DECLARATION \
61    { \
62       APP_SET_ARGS(app); \
63       app.main(); \
64       unloadTranslatedStrings(MODULE_NAME); \
65       return app.exitCode; \
66    }
67
68 #define SELF(c, n)  c * self = ((c *)(((char *)this) - (char *)&((c *)0)->n))
69
70 #define VIRTUAL_METHOD(n, c, b, r, p, sp, d) \
71    struct c ## _ ## n ## _Functor \
72    { \
73       int _[0]; \
74       typedef r (* FunctionType)p; \
75       FunctionType operator= (FunctionType func) \
76       { \
77          SELF(c, n); \
78          if(self->vTbl == c::_class.impl->data) \
79          { \
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); \
83          } \
84          ((FunctionType *)self->vTbl)[b ## _ ## n ## _vTblID] = func; \
85          return func; \
86       } \
87       r operator()sp \
88       { \
89          SELF(c, n); \
90          d; \
91       } \
92    } n; \
93    static void register_ ## n(Class * cl, c ## _ ## n ## _Functor::FunctionType func) \
94    { \
95       ((c ## _ ## n ## _Functor::FunctionType *)cl->data)[b ## _ ## n ## _vTblID] = func; \
96    }
97
98 #define REGISTER_METHOD(ns, n, bc, c, r, p, o, a, ea, rv) \
99    addMethod(_class, ns, (void *) +[]p \
100    { \
101       Class * cl = (Class *)o->_class; \
102       c * i = (c *)_INSTANCE(o, cl); \
103       if(i) \
104       { \
105          int vid = bc ## _ ## n ## _vTblID; \
106          if(i->vTbl && i->vTbl[vid]) \
107          { \
108             return ((bc ## _ ## n ## _Functor::FunctionType)i->vTbl[vid]) a; \
109          } \
110          else \
111          { \
112             auto method = ((r (*) p)(class_ ## c->_vTbl)[bc ## _ ## n ## _vTblID]); \
113             if(method) return method ea; \
114          } \
115       } \
116       return rv; \
117    })
118
119 #define property(n, sg) struct n ## Prop { n ## Prop() { }; int _[0]; sg } n;
120
121 #define _set(t, n, d) \
122    inline t operator= (t v) \
123    { \
124       PSELF; \
125       d; \
126       return v; \
127    } \
128
129 #define set(t, n, d) \
130    _set(t, n, d) \
131    inline n ## Prop & operator= (n ## Prop & prop) \
132    { \
133       PSELF; \
134       t v = prop; \
135       d; \
136       return prop; \
137    }
138
139 #define get(t, n, d) inline operator t () const { PSELF; d; }
140
141 extern "C" eC_Module ecere_init(eC_Module fromModule);
142
143 class Class : public eC_Class { };
144
145 template <class T>
146 class CPPClass
147 {
148 public:
149    Class * impl;
150    void (*destructor)(T &);
151
152    CPPClass() { };
153    CPPClass(Class * _impl) : impl(_impl) { }
154    ~CPPClass()
155    {
156       if(impl)
157          delete [] (void (**)(void))impl->data;
158    }
159 };
160
161 // GENERATED: (Instance, Module and Application might require some custom tweaks...)
162
163 // Normal Class Definitions
164 class Instance
165 {
166 public:
167    static CPPClass<Instance> _class;
168    eC_Instance impl;
169    void (**vTbl)(void);
170
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; }
173
174    inline explicit Instance(eC_Instance _impl, Class * c = _class.impl)
175    {
176       impl = _impl;
177       vTbl = c ? (void (**)(void))c->data : null;
178       if(impl)
179       {
180          if(c && !_INSTANCE(impl, c))
181             _INSTANCE(impl, c) = this;
182          impl->_refCount++;
183       }
184    }
185
186    inline Instance()
187    {
188       impl = null;
189       vTbl = null;
190    }
191
192    inline ~Instance()
193    {
194       if(impl && impl->_class)
195       {
196          Instance ** i = (Instance **)&INSTANCEL(impl, impl->_class);
197          if(i && *i == this)
198             *i = null;
199          if(vTbl && vTbl != impl->_class->data)
200             delete [] vTbl;
201          Instance_decref(impl);
202       }
203    }
204
205    inline Instance(const Instance & i)
206    {
207       impl = i.impl;
208       vTbl = null;
209       if(impl)
210       {
211          impl->_refCount++;
212          if(i.vTbl)
213             vTbl = i.vTbl;
214       }
215    }
216
217    static Class * class_registration(Class * _class) { return _class; }
218 };
219
220 class Module : public Instance
221 {
222 public:
223    static CPPClass<Module> _class;
224    inline explicit Module(eC_Instance _impl, Class * c = _class.impl) : Instance(_impl, c) { }
225 };
226
227 void eC_cpp_init(Module & module);
228 void ecere_cpp_init(Module & module);
229
230 #define Application_class_registration(c, d) \
231    REGISTER_METHOD("Main", main, Application, d, void, (eC_Instance o), o, (*i), (o), );
232
233 class Application : public Module
234 {
235 public:
236    APP_CONSTRUCT(Application, Module)
237    {
238       eC_cpp_init(*this);
239       _INSTANCE(impl, impl->_class) = this;
240       vTbl = (void (**)(void))_class.impl->data;
241
242       // TODO: Omit this if we're linking against eC rt only
243       ecere_init(impl);
244       ecere_cpp_init(*this);
245 #ifdef MODULE_NAME
246       loadTranslatedStrings(null, MODULE_NAME);
247 #endif
248    }
249
250    static Class * class_registration(Class * _class) { Application_class_registration(_class, Application); class_vtbl_setup(_class); return _class; }
251
252    #undef   PSELF
253    #define  PSELF SELF(Application, exitCode)
254    property(exitCode, get(int, exitCode, return self ? _IPTR(self->impl, class_Application, class_members_Application)->exitCode : 0) );
255
256    VIRTUAL_METHOD(main, Application, Application, void, (Application &), (),
257       return Application_main(self->impl));
258 };
259
260 class Container : public Instance
261 {
262 public:
263    CONSTRUCT(Container, Instance) { }
264 /*
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); }
284 */
285 };
286
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
291
292 class Array : Container
293 {
294 public:
295    CONSTRUCT(Array, Container) { }
296 };
297
298 class CustomAVLTree : Container
299 {
300 public:
301    CONSTRUCT(CustomAVLTree, Container) { }
302 };
303
304 class AVLTree : CustomAVLTree
305 {
306 public:
307    CONSTRUCT(AVLTree, CustomAVLTree) { }
308 };
309
310 class Map : CustomAVLTree
311 {
312 public:
313    CONSTRUCT(Map, CustomAVLTree) { }
314 };
315
316 class LinkList : Container
317 {
318 public:
319    CONSTRUCT(LinkList, Container) { }
320 };
321
322 class List : LinkList
323 {
324 public:
325    CONSTRUCT(List, LinkList) { }
326 };
327
328 class IOChannel : Instance
329 {
330 public:
331    CONSTRUCT(IOChannel, Instance) { }
332 };
333
334 class SerialBuffer : IOChannel
335 {
336 public:
337    CONSTRUCT(SerialBuffer, IOChannel) { }
338 };
339
340 class OldArray : Instance
341 {
342 public:
343    CONSTRUCT(OldArray, Instance) { }
344 };
345
346 // How to handle inheritance from classes not loaded yet?
347 /*
348 class ClassDesignerBase : Window
349 {
350 public:
351    CONSTRUCT(ClassDesignerBase, Window) { }
352 };
353 class DesignerBase : Window
354 {
355 public:
356    CONSTRUCT(DesignerBase, Window) { }
357 };
358 */
359
360 #endif