compiler/libec: (#501, #503) Fixed various memory leaks
[sdk] / compiler / libec / src / pass1.ec
1 import "ecdefs"
2
3 // UNTIL IMPLEMENTED IN GRAMMAR
4 #define ACCESS_CLASSDATA(_class, baseClass) \
5    (_class ? ((void *)(((char *)_class.data) + baseClass.offsetClass)) : null)
6
7 #define YYLTYPE Location
8 #include "grammar.h"
9
10 static Statement registerModuleBody;
11 static External registerModuleExternal;
12 static Statement unregisterModuleBody;
13 static External unregisterModuleExternal;
14
15 extern int propWatcherID;
16
17 bool buildingECERECOM = false;
18 public void SetBuildingEcereCom(bool b) { buildingECERECOM = b; } public bool GetBuildingEcereCom() { return buildingECERECOM; }
19 bool buildingECERECOMModule = false;
20 public void SetBuildingEcereComModule(bool b) { buildingECERECOMModule = b; } public bool GetBuildingEcereComModule() { return buildingECERECOMModule; }
21
22 // This will also be called by the instance processer to make the instance methods... (pass 1.5)
23 External ProcessClassFunction(Class owningClass, ClassFunction func, OldList defs, External after, bool makeStatic)
24 {
25    Identifier id = GetDeclId(func.declarator);
26    Type type = null;
27    Symbol symbol;
28    External external = null;
29
30    if(defs && func.declarator)
31    {
32       FunctionDefinition function = null;
33       Symbol propSymbol;
34       int symid = func.declarator.symbol.id;
35       int symidCode = func.declarator.symbol.idCode;
36
37       if(inCompiler)
38       {
39          if(!func.specifiers)
40             func.specifiers = MkList();
41          // Add static to the specifiers
42          if(makeStatic)
43             func.specifiers->Insert(null, MkSpecifier(STATIC));
44       }
45
46       propSymbol = func.declarator.symbol;
47
48       ReplaceThisClassSpecifiers(func.specifiers, owningClass);
49
50       if(propSymbol.externalGet == (External)func)
51          func.declarator.symbol = null;
52       else if(propSymbol.externalSet == (External)func)
53       {
54          func.declarator.symbol = null;
55          symid++;
56       }
57       else if(propSymbol.externalIsSet == (External)func)
58       {
59          func.declarator.symbol = null;
60          symid += 2; // TOFIX: What should we do with this? Where are 2 IDs allocated for properties? In MkProperty...
61       }
62
63       //if(inCompiler)
64       {
65          /*FunctionDefinition*/ function = _MkFunction(func.specifiers, func.declarator, null, false);
66          function.propSet = func.propSet;
67          function.type = func.type;
68          if(func.type) func.type.refCount++;
69          ProcessFunctionBody(function, func.body);
70          external = MkExternalFunction(function);
71
72          external.symbol = func.declarator.symbol;
73          external.function._class = func._class;
74       }
75
76       symbol = func.declarator.symbol;
77       //symbol.id = func.id; //symid;
78       symbol.id = symid;
79       symbol.idCode = symidCode;
80
81       if(!func.dontMangle)
82       {
83          // Normal method
84          Method method = func.declarator.symbol.method;
85          func.declarator.symbol.methodExternal = external;
86
87          // DANGER: Added this one...
88
89          if(method && method.symbol)
90             //((Symbol)method.symbol).methodExternal = external;
91             ((Symbol)method.symbol).methodCodeExternal = external;
92
93          if(method && method.type == virtualMethod)
94          {
95             Type methodDataType;
96             ProcessMethodType(method);
97
98             methodDataType = method.dataType;
99
100             // Do type checking here of type against method.dataType
101             // ThisClass must be the owning class for types not specified, static for static, or inherit from method's ThisClass is specified
102             // If not specified, defaults to ThisClass if ThisClass specified in method, otherwise overiding class or static
103
104             type = symbol.type;
105
106             if(!type.staticMethod && !type.thisClass && !type.thisClassTemplate)
107             {
108                if(method.dataType.thisClassTemplate)
109                {
110                   if(owningClass.templateArgs)
111                   {
112                      ClassTemplateArgument * arg = FindTemplateArg(owningClass, method.dataType.thisClassTemplate);
113                      type.byReference = method.dataType.byReference;
114
115                      methodDataType = ProcessTypeString(method.dataTypeString, false);
116                      type.thisClass = methodDataType.thisClass = arg ? FindClass(arg->dataTypeString) : null;
117                   }
118                }
119                else if(method.dataType.staticMethod)
120                   type.staticMethod = true;
121                else if(method.dataType.thisClass)
122                {
123                   type.thisClass = method.dataType.thisClass;
124                   type.byReference = method.dataType.byReference;
125                }
126                else
127                {
128                   if(!owningClass.symbol)
129                      owningClass.symbol = FindClass(owningClass.fullName);
130
131                   type.thisClass = owningClass.symbol;
132                   // WORKING ON THIS TO SUPPORT : pass.NotifyClicked(this, pass, 0, 0, key.modifiers);
133                   type.extraParam = true;
134                }
135             }
136
137             yylloc = func.loc;
138             if(!MatchTypes(type, methodDataType, null, owningClass, method._class /*owningClass*/, true, true, true, false))
139             {
140 #ifdef _DEBUG
141                // MatchTypes(type, methodDataType, null, owningClass, owningClass, true, true, true, false);
142 #endif
143                Compiler_Error($"Incompatible virtual function %s\n", method.name);
144             }
145             else
146             {
147                // Mark typed_object/any_object parameters as such according to method type
148                Type typeParam;
149                Declarator funcDecl = GetFuncDecl(func.declarator);
150                if(funcDecl.function.parameters && funcDecl.function.parameters->first)
151                {
152                   TypeName param = funcDecl.function.parameters->first;
153
154                   for(typeParam = methodDataType.params.first; typeParam && param; typeParam = typeParam.next)
155                   {
156                      if(typeParam.classObjectType)
157                      {
158                         param.classObjectType = typeParam.classObjectType;
159                         if(param.declarator && param.declarator.symbol)
160                            param.declarator.symbol.type.classObjectType = typeParam.classObjectType;
161                      }
162                      param = param ? param.next : null;
163                   }
164                }
165             }
166             if(methodDataType != method.dataType)
167                FreeType(methodDataType);
168          }
169          else
170          {
171             type = symbol.type;
172             if(!type.staticMethod && !type.thisClass)
173             {
174                if(owningClass && !owningClass.symbol)
175                   owningClass.symbol = FindClass(owningClass.fullName);
176
177                type.thisClass = owningClass ? FindClass(owningClass.fullName) : null;
178             }
179          }
180       }
181       else
182       {
183          // TESTING THIS HERE: (Implementing Class Properties)
184          if(symbol.type && !symbol.type.staticMethod && !symbol.type.thisClass)
185          {
186             if(!owningClass.symbol)
187                owningClass.symbol = FindClass(owningClass.fullName);
188             symbol.type.thisClass = owningClass.symbol;
189          }
190
191          // Those type of classes don't need a this parameter for Set methods, null thisClass before changing the externals
192          if(propSymbol.externalSet == (External)func && propSymbol._property && propSymbol._property.conversion)
193          {
194             if(symbol.type.thisClass && symbol.type.classObjectType != classPointer)
195             {
196                // TODO: Perhaps improve this so as to support both "this =" and "return " syntax for all types of classes
197                if(owningClass.type != structClass)
198                   //function.propertyNoThis = true;
199                   symbol.type.thisClass = null;
200             }
201          }
202
203          // Property
204          if(propSymbol.externalGet == (External)func)
205          {
206             propSymbol.externalGet = external;
207          }
208          else if(propSymbol.externalSet == (External)func)
209          {
210             propSymbol.externalSet = external;
211          }
212          else if(propSymbol.externalIsSet == (External)func)
213          {
214             propSymbol.externalIsSet = external;
215          }
216          else
217          {
218             // Constructor destructor
219             //symbol.type = Type { };
220          }
221       }
222       if(inCompiler)
223       {
224          if(func.body)
225          {
226             func.declarator = null;
227             func.specifiers = null;
228             func.body = null;
229
230             defs.Insert(after, external);
231          }
232          else
233          {
234             Method method = func.declarator.symbol.method;
235             if(method && method.symbol)
236                ((Symbol)method.symbol).methodCodeExternal = null;
237             if(func.declarator.symbol && func.declarator.symbol.methodExternal == external)
238                func.declarator.symbol.methodExternal = null;
239
240             //external.function = null;
241             func.declarator = null;
242             func.specifiers = null;
243
244             FreeExternal(external); // Free external here?
245          }
246       }
247       else
248       {
249          globalContext /*curContext*/.symbols.Remove((BTNode)symbol);
250          excludedSymbols->Add(symbol);
251
252          // Testing this...
253          defs.Insert(after, external);
254
255          external.function.declarator = CopyDeclarator(external.function.declarator);
256          external.function.specifiers = CopyList(external.function.specifiers, CopySpecifier);
257          external.function.body = null;
258       }
259    }
260    return external;
261 }
262
263 void CreateRegisterModuleBody()
264 {
265    if(!registerModuleBody && inCompiler)
266    {
267       char registerName[1024], moduleName[MAX_FILENAME];
268       OldList * specifiers;
269       Declarator declarator;
270       TypeName moduleParam;
271
272       registerModuleBody = MkCompoundStmt(MkList(), MkList());
273       registerModuleBody.compound.context = Context { parent = globalContext };
274
275       #if 0
276       ListAdd(registerModuleBody.compound.declarations,
277          MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null) /*MkSpecifierName("ecere::com::Class")*/ /*MkStructOrUnion(SpecifierStruct, MkIdentifier("Class"), null)*/),
278                        MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class"))), null))));
279       #endif
280       ListAdd(registerModuleBody.compound.declarations,
281          MkDeclaration(MkListOne(MkSpecifierName("ecere::com::Class")),
282                        MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("class")), null))));
283
284       specifiers = MkList();
285       ListAdd(specifiers, MkSpecifier(VOID));
286
287       moduleParam = MkTypeName(MkListOne(/*MkSpecifier(VOID)*/MkSpecifierName("Module")),
288          //MkDeclaratorPointer(MkPointer(null, null),
289          MkDeclaratorIdentifier(MkIdentifier("module")));
290
291       GetLastDirectory(outputFile, moduleName);
292       //strcpy(moduleName, argv[2]);
293       StripExtension(moduleName);
294       FixModuleName(moduleName);
295       sprintf(registerName, "__ecereRegisterModule_%s", moduleName);
296
297       declarator = MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(registerName)),
298          MkListOne(moduleParam));
299
300       {
301          FunctionDefinition function = _MkFunction(specifiers, declarator, null, false);
302          ProcessFunctionBody(function, registerModuleBody);
303          function.declMode = defaultAccess;
304          if(!ast) ast = MkList();
305          ListAdd(ast, (registerModuleExternal = MkExternalFunction(function)));
306       }
307    }
308
309    // Unregister Module
310    if(!unregisterModuleBody && inCompiler)
311    {
312       char registerName[1024], moduleName[MAX_FILENAME];
313       OldList * specifiers;
314       Declarator declarator;
315       TypeName moduleParam;
316
317       unregisterModuleBody = MkCompoundStmt(MkList(), MkList());
318       unregisterModuleBody.compound.context = Context { parent = globalContext };
319
320       specifiers = MkList();
321       ListAdd(specifiers, MkSpecifier(VOID));
322
323       moduleParam = MkTypeName(MkListOne(/*MkSpecifier(VOID)*/ MkSpecifierName("Module")),
324          //MkDeclaratorPointer(MkPointer(null, null),
325          MkDeclaratorIdentifier(MkIdentifier("module")));
326
327       GetLastDirectory(outputFile, moduleName);
328       StripExtension(moduleName);
329       FixModuleName(moduleName);
330       //strcpy(moduleName, argv[2]);
331       sprintf(registerName, "__ecereUnregisterModule_%s", moduleName);
332
333       declarator = MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(registerName)),
334          MkListOne(moduleParam));
335
336       {
337          FunctionDefinition function = _MkFunction(specifiers, declarator, null, false);
338          ProcessFunctionBody(function, unregisterModuleBody);
339          function.declMode = defaultAccess;
340          if(!ast) ast = MkList();
341          ListAdd(ast, (unregisterModuleExternal = MkExternalFunction(function)));
342       }
343    }
344 }
345
346 void RegisterMembersAndProperties(Class regClass, bool isMember, char * className, Statement statement)
347 {
348    DataMember dataMember = isMember ? (DataMember)regClass : null;
349    DataMember member;
350    Property prop;
351    Expression exp;
352    Statement stmt;
353    char dataMemberSize[16];
354
355    uint lastOffset = 0;
356    int privateID = 0;
357    bool privateMembers = false;
358
359    sprintf(dataMemberSize, "%d", (int)sizeof(DataMember));
360    if(!isMember)
361    {
362       for(prop = regClass.conversions.first; prop; prop = prop.next)
363       {
364          OldList * args = MkList();
365          char name[1024];
366
367          // Class class
368          ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
369          // char * name
370          ListAdd(args, MkExpConstant("0"));
371
372          // char * type
373          {
374             char * string = QMkString(prop.dataTypeString);
375             ListAdd(args, MkExpString(string));
376             delete string;
377          }
378          // void * Set
379          if(prop.Set)
380          {
381             strcpy(name, "__ecereProp_");
382             FullClassNameCat(name, regClass.fullName, false);
383             strcat(name, "_Set_");
384             // strcat(name, prop.name);
385             FullClassNameCat(name, prop.name, true);
386             MangleClassName(name);
387             ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
388          }
389          else
390             ListAdd(args, MkExpConstant("0"));
391          // void * Get
392          if(prop.Get)
393          {
394             strcpy(name, "__ecereProp_");
395             FullClassNameCat(name, regClass.fullName, false);
396             strcat(name, "_Get_");
397             // strcat(name, prop.name);
398             FullClassNameCat(name, prop.name, true);
399             MangleClassName(name);
400
401             ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
402          }
403          else
404             ListAdd(args, MkExpConstant("0"));
405
406
407          // Declaration Mode
408          switch(prop.memberAccess)
409          {
410             case staticAccess:
411                ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
412                break;
413             case privateAccess:
414                ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
415                break;
416             case publicAccess:
417             default:
418                ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
419                break;
420          }
421
422          strcpy(name, "__ecereProp_");
423          FullClassNameCat(name, regClass.fullName, false);
424          strcat(name, "_");
425          FullClassNameCat(name, prop.name, true);
426          // strcat(name, prop.name);
427          MangleClassName(name);
428
429          stmt = MkExpressionStmt(MkListOne(
430             MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=',
431             MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddProperty")), args))));
432          ListAdd(registerModuleBody.compound.statements, stmt);
433       }
434    }
435
436    for(member = isMember ? dataMember.members.first : regClass.membersAndProperties.first; member; member = member.next)
437    {
438       if(member.isProperty)
439       {
440          prop = (Property) member;
441          {
442             OldList * args = MkList();
443             char name[1024], nameM[1024];
444             char * string = QMkString(prop.name);
445
446             // Class class
447             ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
448
449             // char * name
450             ListAdd(args, MkExpString(string));
451             delete string;
452
453             // char * type
454             {
455                char * string = QMkString(prop.dataTypeString);
456                ListAdd(args, MkExpString(string));
457                delete string;
458             }
459             // void * Set
460             if(prop.Set)
461             {
462                strcpy(name, "__ecereProp_");
463                FullClassNameCat(name, regClass.fullName, false);
464                strcat(name, "_Set_");
465                FullClassNameCat(name, prop.name, true);
466                // strcat(name, prop.name);
467                MangleClassName(name);
468                ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
469             }
470             else
471                ListAdd(args, MkExpConstant("0"));
472             // void * Get
473             if(prop.Get)
474             {
475                strcpy(name, "__ecereProp_");
476                FullClassNameCat(name, regClass.fullName, false);
477                strcat(name, "_Get_");
478                FullClassNameCat(name, prop.name, true);
479                // strcat(name, prop.name);
480                MangleClassName(name);
481                ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
482             }
483             else
484                ListAdd(args, MkExpConstant("0"));
485
486             // Declaration Mode
487             switch(prop.memberAccess)
488             {
489                case staticAccess:
490                   ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
491                   break;
492                case privateAccess:
493                   ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
494                   break;
495                case publicAccess:
496                default:
497                   ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
498                   break;
499             }
500
501             strcpy(name, "__ecereProp_");
502             FullClassNameCat(name, regClass.fullName, false);
503             strcat(name, "_");
504             FullClassNameCat(name, prop.name, true);
505             // strcat(name, prop.name);
506             MangleClassName(name);
507
508             strcpy(nameM, "__ecerePropM_");
509             FullClassNameCat(nameM, regClass.fullName, false);
510             strcat(nameM, "_");
511             FullClassNameCat(nameM, prop.name, true);
512             // strcat(nameM, prop.name);
513             MangleClassName(nameM);
514
515             if(prop.dataTypeString)
516             {
517                stmt = MkExpressionStmt(MkListOne(
518                   MkExpOp(MkExpIdentifier(MkIdentifier(nameM)), '=',
519                   MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddProperty")), args))));
520             }
521             else
522             {
523                stmt = MkExpressionStmt(MkListOne(MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddProperty")), args)));
524             }
525             ListAdd(registerModuleBody.compound.statements, stmt);
526
527             if(prop.IsSet)
528             {
529                char name[1024];
530                strcpy(name, "__ecereProp_");
531                FullClassNameCat(name, regClass.fullName, true);
532                strcat(name, "_IsSet_");
533                FullClassNameCat(name, prop.name, false);
534                // strcat(name, prop.name);
535                MangleClassName(name);
536
537                stmt = MkExpressionStmt(MkListOne(
538                   MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier(nameM)), MkIdentifier("IsSet")), '=',
539                   MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null)), MkExpIdentifier(MkIdentifier(name))))));
540                ListAdd(registerModuleBody.compound.statements, stmt);
541             }
542             if(prop.symbol && ((Symbol)prop.symbol).propCategory)
543             {
544                stmt = MkExpressionStmt(MkListOne(
545                   MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier(nameM)), MkIdentifier("category")), '=',
546                   CopyExpression(((Symbol)prop.symbol).propCategory))));
547                ListAdd(registerModuleBody.compound.statements, stmt);
548             }
549
550             if(prop.dataTypeString)
551             {
552                OldList * list = MkList();
553                ListAdd(list, MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', MkExpIdentifier(MkIdentifier(nameM))));
554                ListAdd(list, MkExpOp(MkExpIdentifier(MkIdentifier(nameM)), '=', MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null)), MkExpConstant("0"))));
555                // stmt = MkIfStmt(MkListOne(MkExpOp(null, '!', MkExpIdentifier(MkIdentifier(name)))), MkExpressionStmt(list), null);
556                stmt = MkIfStmt(MkListOne(MkExpOp(
557                      MkExpMember(MkExpIdentifier(MkIdentifier("module")), MkIdentifier("application")), EQ_OP,
558                      MkExpMember(MkExpIdentifier(MkIdentifier("__thisModule")), MkIdentifier("application")))), MkExpressionStmt(list), null);
559
560                ListAdd(registerModuleBody.compound.statements, stmt);
561
562                // Unregister 2nd property
563                stmt = MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(nameM)), '=',
564                   MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null)), MkExpConstant("0")))));
565                ListAdd(unregisterModuleBody.compound.statements, stmt);
566             }
567          }
568       }
569       else if(member.type == normalMember && !isMember && regClass.type == bitClass)
570       {
571          BitMember bitMember = (BitMember) member;
572          OldList * args = MkList();
573
574          // Class class
575          ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
576
577          // char * name
578          {
579             char * string = QMkString(bitMember.name);
580             ListAdd(args, MkExpString(string));
581             delete string;
582          }
583          // char * type
584          {
585             char * string = QMkString(bitMember.dataTypeString);
586             ListAdd(args, MkExpString(string));
587             delete string;
588          }
589          // int bitSize
590          {
591             char string[256];
592             sprintf(string, "%d", bitMember.size);
593             ListAdd(args, (exp = MkExpConstant(string)));
594          }
595          // int bitPos
596          {
597             char string[256];
598             sprintf(string, "%d", bitMember.pos);
599             ListAdd(args, (exp = MkExpConstant(string)));
600          }
601
602          // Declaration Mode
603          switch(member.memberAccess)
604          {
605             case staticAccess:
606                ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
607                break;
608             case privateAccess:
609                ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
610                break;
611             case publicAccess:
612             default:
613                ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
614                break;
615          }
616
617          stmt = MkExpressionStmt(MkListOne(
618             MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddBitMember")), args)));
619
620          ListAdd(statement.compound.statements, stmt);
621       }
622       else if(member.memberAccess == publicAccess || (member.type == normalMember && !member.dataTypeString))
623       {
624          OldList * args;
625          // ADD PRIVATE DATA PADDING HERE...
626          if(privateMembers)
627          {
628             uint offset = member.offset - lastOffset;
629
630             args = MkList();
631
632             // Class class
633             ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
634
635             // char * name
636             {
637                char string[200];
638                sprintf(string, "\"__ecerePrivateData%d\"", privateID++);
639                ListAdd(args, MkExpString(string));
640             }
641             // char * type
642             {
643                char string[200];
644                sprintf(string, "\"byte[%d]\"", offset);
645                ListAdd(args, MkExpString(string));
646             }
647             // int size
648             {
649                char string[256];
650                sprintf(string, "%d", offset);
651                ListAdd(args, (exp = MkExpConstant(string)));
652             }
653
654             // int alignment
655             ListAdd(args, (exp = MkExpConstant("1")));
656
657             // Declaration Mode
658             ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
659
660             stmt = MkExpressionStmt(MkListOne(
661                MkExpCall(MkExpIdentifier(MkIdentifier(isMember ? "eMember_AddDataMember" : "eClass_AddDataMember")), args)));
662
663             ListAdd(statement.compound.statements, stmt);
664             privateMembers = false;
665          }
666
667          if(member.type == normalMember)
668          {
669             if(!member.dataType)
670                member.dataType = ProcessTypeString(member.dataTypeString, false);
671
672             ComputeTypeSize(member.dataType);
673
674             args = MkList();
675
676             // Class class
677             ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
678
679             // char * name
680             {
681                char * string = QMkString(member.name);
682                ListAdd(args, MkExpString(string));
683                delete string;
684             }
685             // char * type
686             {
687                char * string = QMkString(member.dataTypeString);
688                ListAdd(args, MkExpString(string));
689                delete string;
690             }
691             // int size
692             {
693                char string[256];
694                sprintf(string, "%d", member.dataType.size);
695                ListAdd(args, (exp = MkExpConstant(string)));
696             }
697
698             // int alignment
699             {
700                char string[256];
701                sprintf(string, "%d", member.dataType.alignment);
702                ListAdd(args, (exp = MkExpConstant(string)));
703             }
704
705             // Declaration Mode
706             switch(member.memberAccess)
707             {
708                case staticAccess:
709                   ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
710                   break;
711                case privateAccess:
712                   ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
713                   break;
714                case publicAccess:
715                default:
716                   ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
717                   break;
718             }
719
720             stmt = MkExpressionStmt(MkListOne(
721                MkExpCall(MkExpIdentifier(MkIdentifier(isMember ? "eMember_AddDataMember" : "eClass_AddDataMember")), args)));
722
723             ListAdd(statement.compound.statements, stmt);
724
725             lastOffset = member.offset + member.dataType.size;
726          }
727          else
728          {
729             static int memberCount = 0;
730
731             Context context;
732             Statement compound;
733             char memberName[256];
734             sprintf(memberName, "dataMember%d", memberCount);
735             memberCount++;
736
737             curContext = statement.compound.context;
738             context = PushContext();
739
740             args = MkListOne(MkExpIdentifier(MkIdentifier((member.type == unionMember) ? "unionMember" : "structMember")));
741
742             // Declaration Mode
743             switch(member.memberAccess)
744             {
745                case staticAccess:
746                   ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
747                   break;
748                case privateAccess:
749                   ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
750                   break;
751                case publicAccess:
752                default:
753                   ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
754                   break;
755             }
756
757             compound = MkCompoundStmt(MkListOne(MkDeclaration(MkListOne(MkSpecifierName("DataMember")),
758                MkListOne(MkInitDeclarator(/*MkDeclaratorPointer(MkPointer(null, null), */MkDeclaratorIdentifier(MkIdentifier(memberName))/*)*/,
759                   MkInitializerAssignment(MkExpCall(MkExpIdentifier(MkIdentifier("eMember_New")), args)))))), MkList());
760             compound.compound.context = context;
761
762             args = MkList();
763
764             // Class class / DataMember member
765             ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
766
767             // DataMember dataMember
768             ListAdd(args, MkExpIdentifier(MkIdentifier(memberName)));
769
770             RegisterMembersAndProperties((Class)member, true, memberName, compound);
771
772             if(isMember)
773                stmt = MkExpressionStmt(MkListOne(
774                   MkExpCall(MkExpIdentifier(MkIdentifier("eMember_AddMember")), args)));
775             else
776                stmt = MkExpressionStmt(MkListOne(
777                   MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddMember")), args)));
778
779             ListAdd(compound.compound.statements, stmt);
780
781             PopContext(context);
782
783             ListAdd(statement.compound.statements, compound);
784
785             memberCount--;
786
787             lastOffset = member.offset + member.memberOffset;
788          }
789       }
790       else
791          privateMembers = true;
792    }
793
794    if(!isMember)
795    {
796       ClassProperty classProperty;
797
798       // Watchable properties
799       for(prop = regClass.membersAndProperties.first; prop; prop = prop.next)
800       {
801          if(prop.isProperty && prop.isWatchable)
802          {
803             OldList * args;
804             char name[1024], nameM[1024];
805
806             strcpy(name, "__ecereProp_");
807             FullClassNameCat(name, regClass.fullName, true);
808             strcat(name, "_");
809             FullClassNameCat(name, prop.name, false);
810             // strcat(name, prop.name);
811             MangleClassName(name);
812
813             strcpy(nameM, "__ecerePropM_");
814             FullClassNameCat(nameM, regClass.fullName, true);
815             strcat(nameM, "_");
816             FullClassNameCat(nameM, prop.name, false);
817             // strcat(nameM, prop.name);
818             MangleClassName(nameM);
819
820             args = MkListOne(MkExpCondition(MkExpIdentifier(MkIdentifier(nameM)), MkListOne(MkExpIdentifier(MkIdentifier(nameM))), MkExpIdentifier(MkIdentifier(name))));
821             stmt = MkExpressionStmt(MkListOne(
822                MkExpCall(MkExpIdentifier(MkIdentifier("eProperty_Watchable")), args)));
823             ListAdd(registerModuleBody.compound.statements, stmt);
824          }
825       }
826
827       // Add Class Properties
828       for(classProperty = (ClassProperty)regClass.classProperties.first; classProperty; classProperty = (ClassProperty)((BTNode)classProperty).next)
829       {
830          OldList * args = MkList();
831          char name[1024];
832          char * string = QMkString(classProperty.name);
833
834          // Class * class
835          ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
836
837          // char * name
838          ListAdd(args, MkExpString(string));
839          delete string;
840
841          // char * type
842          {
843             char * string = QMkString(classProperty.dataTypeString);
844             ListAdd(args, MkExpString(string));
845             delete string;
846          }
847          // void * Set
848          if(classProperty.Set)
849          {
850             strcpy(name, "__ecereClassProp_");
851             FullClassNameCat(name, regClass.fullName, true);
852             strcat(name, "_Set_");
853             strcat(name, classProperty.name);
854             MangleClassName(name);
855             ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
856          }
857          else
858             ListAdd(args, MkExpConstant("0"));
859          // void * Get
860          if(classProperty.Get)
861          {
862             strcpy(name, "__ecereClassProp_");
863             FullClassNameCat(name, regClass.fullName, true);
864             strcat(name, "_Get_");
865             strcat(name, classProperty.name);
866             MangleClassName(name);
867
868             ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
869          }
870          else
871             ListAdd(args, MkExpConstant("0"));
872
873          stmt = MkExpressionStmt(MkListOne(MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddClassProperty")), args)));
874          ListAdd(registerModuleBody.compound.statements, stmt);
875       }
876    }
877 }
878
879 extern External curExternal;
880
881 void GetNameSpaceString(NameSpace ns, char * string)
882 {
883    if(ns.parent)
884       GetNameSpaceString(ns.parent, string);
885    if(ns.name)
886    {
887       strcat(string, ns.name);
888       strcat(string, "::");
889    }
890 }
891
892 // *******************************************************************
893 static void ProcessClass(ClassType classType, OldList definitions, Symbol symbol, OldList baseSpecs, OldList enumValues, OldList defs, External external, AccessMode declMode)
894 {
895    ClassDef def;
896    Class regClass = symbol.registered;
897
898    if(regClass)
899    {
900       classType = regClass.type;
901       if(classType == enumClass && enumValues && (inCompiler || !buildingECERECOMModule))
902       {
903          Enumerator e;
904          for(e = enumValues.first; e; e = e.next)
905          {
906             if(e.exp)
907             {
908                Type destType
909                {
910                   kind = intType;
911                   refCount = 1;
912                };
913                e.exp.destType = destType;
914
915                // Set parsingType to avoid producing errors
916                parsingType = true;
917                ProcessExpressionType(e.exp);
918                parsingType = false;
919
920                if(!e.exp.expType)
921                {
922                   destType.kind = TypeKind::classType;
923                   destType._class = symbol;
924                   ProcessExpressionType(e.exp);
925                }
926                if(e.exp.type == identifierExp && e.exp.expType && e.exp.identifier && e.exp.identifier.string && e.exp.expType.kind == enumType)
927                {
928                   // Resolve enums here
929                   NamedLink l;
930                   char * string = e.exp.identifier.string;
931                   for(l = e.exp.expType.members.first; l; l = l.next)
932                   {
933                      if(!strcmp(l.name, string))
934                      {
935                         if(l.data)
936                         {
937                            FreeExpContents(e.exp);
938                            e.exp.type = constantExp;
939                            e.exp.constant = PrintUInt((uint)l.data);
940                            FreeType(e.exp.expType);
941                            e.exp.expType = ProcessTypeString("uint", false);
942                         }
943                         break;
944                      }
945                   }
946                }
947                else
948                   ComputeExpression(e.exp);
949                if(e.exp.isConstant && /*e.exp.expType.kind == intType*/ e.exp.type == constantExp)
950                {
951                   Operand op = GetOperand(e.exp);
952                   int value;
953                   // TODO: 64 BIT ENUM SUPPORT...
954                   switch(op.kind)
955                   {
956                      case charType: value = op.c; break;
957                      case shortType: value = op.s; break;
958                      default: value = op.i;
959                   }
960
961                   // value = op.i; //strtol(e.exp.string, null, 0);
962                   eEnum_AddFixedValue(regClass, e.id.string, value);
963                }
964                else
965                   // Sort of an error
966                   eEnum_AddValue(regClass, e.id.string);
967             }
968             else
969                eEnum_AddValue(regClass, e.id.string);
970          }
971          // Fix up derivatives enums largest
972          {
973             EnumClassData baseData = regClass.data;
974             OldLink deriv;
975             for(deriv = regClass.derivatives.first; deriv; deriv = deriv.next)
976             {
977                Class c = deriv.data;
978                if(c && c.type == enumClass)
979                {
980                   EnumClassData data = c.data;
981                   data.largest = baseData.largest;
982                }
983             }
984          }
985       }
986
987       // Process all functions
988       if(definitions != null)
989       {
990          if(inCompiler)
991          {
992             for(def = definitions.first; def; def = def.next)
993             {
994                if(def.type == propertyWatchClassDef && def.propertyWatch)
995                {
996                   PropertyWatch propWatch = def.propertyWatch;
997                   ClassFunction func;
998                   char watcherName[1024];
999                   Identifier propID;
1000                   Statement stmt = MkExpressionStmt(MkList());
1001                   Declarator decl;
1002
1003                   sprintf(watcherName,"__ecerePropertySelfWatcher_%d", propWatcherID++);
1004                   for(propID = propWatch.properties->first; propID; propID = propID.next)
1005                   {
1006                      strcat(watcherName, "_");
1007                      strcat(watcherName, propID.string);
1008                   }
1009
1010                   // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
1011                   decl = MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)), MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null)));
1012                   func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, decl, null);
1013                   ProcessClassFunctionBody(func, propWatch.compound);
1014
1015                   // TESTING WITH SAME SYMBOL ID AS CLASS
1016                   decl.symbol = Symbol
1017                   {
1018                      id = symbol.id;
1019                      idCode = symbol.idCode;
1020                   };
1021                   excludedSymbols->Add(decl.symbol);
1022
1023                   func.id = symbol.id;
1024                   func.idCode = symbol.idCode;
1025                   func.dontMangle = true;
1026
1027                   // Create a declaration above for constructor to see
1028                   {
1029                      External externalDecl = MkExternalDeclaration(null);
1030                      Declaration decl;
1031                      OldList * specifiers = MkList();
1032                      ListAdd(specifiers, MkSpecifier(STATIC));
1033                      ListAdd(specifiers, MkSpecifier(VOID));
1034
1035                      ast->Insert(curExternal.prev, externalDecl);
1036
1037                      decl = MkDeclaration(specifiers,
1038                         MkListOne(MkInitDeclarator(MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)),
1039                            MkListOne(MkTypeName(MkListOne(MkSpecifierName(regClass.fullName)), null))), null)));
1040                      externalDecl.declaration = decl;
1041                      if(decl.symbol && !decl.symbol.methodExternal)
1042                      {
1043                         decl.symbol.methodExternal = externalDecl;
1044
1045                         // PATCHED THIS, 2 SYMBOLS WERE THERE.. THIS ONE HAD AN ID TOO BIG
1046                         decl.symbol.id = symbol.id;
1047                         decl.symbol.idCode = symbol.idCode;
1048                      }
1049                   }
1050
1051                   propWatch.compound = null;
1052                   definitions.Insert(null, MkClassDefFunction(func));
1053
1054                   for(propID = propWatch.properties->first; propID; propID = propID.next)
1055                   {
1056                      Property prop = eClass_FindProperty(regClass, propID.string, privateModule);
1057                      if(prop)
1058                      {
1059                         // eProperty_SelfWatch(_class, name, callback);
1060                         OldList * args = MkList();
1061                         ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1062                         {
1063                            char * s = QMkString(propID.string);
1064                            ListAdd(args, MkExpString(s));
1065                            delete s;
1066                         }
1067                         ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
1068
1069                         ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("eProperty_SelfWatch")), args));
1070                      }
1071                      else
1072                         Compiler_Error($"Property %s not found in class %s\n", propID.string, regClass.fullName);
1073                   }
1074                   FreePropertyWatch(def.propertyWatch);
1075                   def.propertyWatch = (PropertyWatch)stmt; // Store this here to use it after CreateRegisterModuleBody is done
1076
1077                   // ListAdd(statements, stmt);
1078                }
1079             }
1080          }
1081
1082          for(def = definitions.first; def; def = def.next)
1083          {
1084             if(def.type == functionClassDef)
1085             {
1086                ProcessClassFunction(regClass, def.function, defs, external.prev, declMode == staticAccess);
1087             }
1088          }
1089       }
1090
1091       // Make the RegisterClass section
1092
1093       if(inCompiler && symbol.id != MAXINT && regClass)
1094       {
1095          Statement stmt;
1096          OldList * args = MkList();
1097          Method method;
1098          Expression exp;
1099          char * registerFunction = null;
1100          AccessMode inheritanceAccess = publicAccess;
1101
1102          CreateRegisterModuleBody();
1103
1104          curExternal = registerModuleExternal;
1105
1106           // Class Type
1107          switch(regClass.type)
1108          {
1109             case structClass: ListAdd(args, MkExpIdentifier(MkIdentifier("structClass"))); break;
1110             case bitClass:    ListAdd(args, MkExpIdentifier(MkIdentifier("bitClass"))); break;
1111             case enumClass:   ListAdd(args, MkExpIdentifier(MkIdentifier("enumClass"))); break;
1112             case noHeadClass: ListAdd(args, MkExpIdentifier(MkIdentifier("noHeadClass"))); break;
1113             case unitClass:   ListAdd(args, MkExpIdentifier(MkIdentifier("unitClass"))); break;
1114             case normalClass: ListAdd(args, MkExpIdentifier(MkIdentifier("normalClass"))); break;
1115          }
1116
1117          {
1118             char nameSpace[1024] = "";
1119             char className[1024] = "";
1120             char * string;
1121             GetNameSpaceString(regClass.nameSpace, nameSpace);
1122
1123             if(declMode == staticAccess)
1124             {
1125                GetLastDirectory(sourceFile, className);
1126                ChangeCh(className, '.', '_');
1127                strcat(className, "}");
1128             }
1129             strcat(className, nameSpace);
1130             strcat(className, regClass.name);
1131             string = QMkString(className);
1132             ListAdd(args, MkExpString(string));
1133             delete string;
1134          }
1135
1136          /*
1137          {
1138             char * string = QMkString(regClass.base.name);
1139             ListAdd(args, regClass.base ? MkExpString(string) :
1140                MkExpConstant("0"));
1141             delete string;
1142          }
1143          */
1144
1145          if(baseSpecs != null)
1146          {
1147             Type baseType = ProcessType(baseSpecs, null);
1148             if(baseType.kind != structType && baseType.kind != unionType)
1149             {
1150                char baseName[1024] = "";
1151                char * string;
1152                if(baseType.kind == TypeKind::classType && baseType._class && baseType._class.isStatic)
1153                {
1154                   // TODO: Handle static classes and complex declarators...
1155                   GetLastDirectory(sourceFile, baseName);
1156                   ChangeCh(baseName, '.', '_');
1157                   strcat(baseName, "}");
1158                   strcat(baseName, baseType._class.string);
1159                }
1160                else
1161                   PrintType(baseType, baseName, false, true);
1162
1163                string = QMkString(baseName);
1164                ListAdd(args, MkExpString(string));
1165                delete string;
1166             }
1167             else
1168                ListAdd(args, MkExpConstant("0"));
1169             FreeType(baseType);
1170             if(((Specifier)baseSpecs.first).type == baseSpecifier && ((Specifier)baseSpecs.first).specifier == PRIVATE)
1171                inheritanceAccess = privateAccess;
1172          }
1173          else
1174             ListAdd(args, MkExpConstant("0"));
1175
1176          //ListAdd(args, class.declaredStruct ? MkExpTypeSize(MkTypeName(MkListOne(
1177             //MkSpecifierName(class.structName)), null)) : MkExpConstant("0"));
1178
1179          if(regClass.type == structClass || regClass.type == normalClass || regClass.type == noHeadClass)
1180          {
1181             // Check if we have a data member in this class
1182             DataMember member = null;
1183             {
1184                Class base;
1185                for(base = regClass.base; base && base.type != systemClass; base = base.next)
1186                {
1187                   for(member = base.membersAndProperties.first; member; member = member.next)
1188                      if(!member.isProperty)
1189                         break;
1190                   if(member)
1191                      break;
1192                }
1193             }
1194
1195             if(regClass.type == structClass && symbol.declaredStruct && member)
1196             {
1197                char baseStructName[1024];
1198                baseStructName[0] = 0;
1199                // TESTING THIS HERE
1200                // FullClassNameCat(baseStructName, regClass.base.fullName, false);
1201                strcpy(baseStructName, (regClass.base.templateClass ? regClass.base.templateClass : regClass.base).fullName);
1202
1203                ListAdd(args, MkExpOp(
1204                   MkExpTypeSize(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(symbol.structName), null)), null)), '-',
1205                   MkExpTypeSize(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(baseStructName), null)), null))));
1206             }
1207             else
1208                ListAdd(args, symbol.declaredStruct ? MkExpTypeSize(MkTypeName(MkListOne(
1209                   MkStructOrUnion(structSpecifier, MkIdentifier(symbol.structName), null)), null)) : MkExpConstant("0"));
1210          }
1211          else
1212          {
1213             ListAdd(args, MkExpConstant("0"));
1214          }
1215
1216          //if(regClass.type == normalClass)
1217          {
1218             char classDataStructName[1024];
1219             strcpy(classDataStructName, "__ecereClassData_");
1220             FullClassNameCat(classDataStructName, symbol.string, false);
1221
1222             ListAdd(args, symbol.classData ? MkExpTypeSize(MkTypeName(MkListOne(
1223                MkStructOrUnion(structSpecifier, MkIdentifier(classDataStructName), null)), null)) : MkExpConstant("0"));
1224          }
1225          /*else
1226             // TODO: Support Class Data for all other types of classes
1227             ListAdd(args, MkExpConstant("0"));
1228             */
1229
1230          if(regClass.type == normalClass || regClass.type == noHeadClass)
1231          {
1232             // Constructor
1233             ListAdd(args, symbol.needConstructor ?
1234                MkExpIdentifier(MkIdentifier(symbol.constructorName)) :
1235                MkExpConstant("0"));
1236             // Destructor
1237             ListAdd(args, symbol.needDestructor ?
1238                MkExpIdentifier(MkIdentifier(symbol.destructorName)) :
1239                MkExpConstant("0"));
1240          }
1241          else
1242          {
1243             // TODO: Support Constructors / Destructors for structs
1244
1245             // Constructor
1246             ListAdd(args, MkExpConstant("0"));
1247             // Destructor
1248             ListAdd(args, MkExpConstant("0"));
1249          }
1250
1251          // Module
1252          ListAdd(args, MkExpIdentifier(MkIdentifier("module")));
1253
1254          // Declaration Mode
1255          switch(declMode)
1256          {
1257             case staticAccess:
1258                ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
1259                break;
1260             case privateAccess:
1261                ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1262                break;
1263             case publicAccess:
1264             default:
1265                ListAdd(args, MkExpIdentifier(MkIdentifier(buildingECERECOMModule ? "baseSystemAccess" : "publicAccess")));
1266                break;
1267          }
1268
1269          // Declaration Mode
1270          switch(inheritanceAccess)
1271          {
1272             case privateAccess:
1273                ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1274                break;
1275             case publicAccess:
1276             default:
1277                ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
1278                break;
1279          }
1280
1281          registerFunction = "eSystem_RegisterClass";
1282
1283          stmt = MkExpressionStmt(MkListOne(
1284             MkExpOp(MkExpIdentifier(MkIdentifier("class")), '=',
1285             MkExpCall((exp = MkExpIdentifier(MkIdentifier(registerFunction))), args))));
1286
1287          ListAdd(registerModuleBody.compound.statements, stmt);
1288
1289          /*
1290          stmt = MkIfStmt(MkListOne(MkExpOp(null, '!', MkExpIdentifier(MkIdentifier(symbol.className)))),
1291                MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(symbol.className)), '=',
1292             MkExpIdentifier(MkIdentifier("class"))))), null);
1293          */
1294
1295          stmt = MkIfStmt(MkListOne(
1296                   MkExpOp(MkExpOp(
1297                      MkExpMember(MkExpIdentifier(MkIdentifier("module")), MkIdentifier("application")), EQ_OP,
1298                      MkExpMember(MkExpIdentifier(MkIdentifier("__thisModule")), MkIdentifier("application"))), AND_OP, MkExpIdentifier(MkIdentifier("class")))),
1299                MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(symbol.className)), '=',
1300             MkExpIdentifier(MkIdentifier("class"))))), null);
1301          /*
1302          stmt = MkIfStmt(MkListOne(
1303                   MkExpOp(MkExpOp(null, '!', MkExpIdentifier(MkIdentifier(symbol.className))), AND_OP, MkExpIdentifier(MkIdentifier("class")))),
1304                MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(symbol.className)), '=',
1305             MkExpIdentifier(MkIdentifier("class"))))), null);
1306          */
1307
1308          ListAdd(registerModuleBody.compound.statements, stmt);
1309
1310          if(external && external.type == classExternal && external._class.deleteWatchable)
1311          {
1312             args = MkListOne(MkExpIdentifier(MkIdentifier("class")));
1313             stmt = MkExpressionStmt(MkListOne(
1314                MkExpCall(MkExpIdentifier(MkIdentifier("eClass_DestructionWatchable")), args)));
1315             ListAdd(registerModuleBody.compound.statements, stmt);
1316          }
1317
1318          // Add Virtual Methods
1319          if(regClass.base)
1320          {
1321             Class base = regClass.base;
1322             int c;
1323             for(c = 0; c<base.vTblSize; c++)
1324             {
1325                Symbol method = (Symbol)regClass._vTbl[c];
1326                if((void *) method != DummyMethod && base._vTbl[c] != (void *)method && method.methodExternal) // TOLOOKAT: Module check here?
1327                {
1328                   External external = method.methodExternal;
1329                   OldList * args = MkList();
1330                   Identifier id = external.function ? GetDeclId(external.function.declarator) : null;
1331
1332                   // Class class
1333                   ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1334                   // char * name
1335                   {
1336                      //char * string = QMkString(method.string);
1337
1338                      char * string = QMkString(method.method.name);
1339                      ListAdd(args, MkExpString(string));
1340                      delete string;
1341                   }
1342                   // char * type
1343                   ListAdd(args, MkExpConstant("0"));
1344                   // void * function
1345                   ListAdd(args, (exp = MkExpIdentifier(MkIdentifier(
1346                      id.string))));
1347
1348                   // Declaration Mode
1349                   ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
1350
1351                   exp.expType = Type { refCount = 1 };
1352                   stmt = MkExpressionStmt(MkListOne(
1353                      MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddMethod")), args)));
1354                   ListAdd(registerModuleBody.compound.statements, stmt);
1355                }
1356             }
1357          }
1358
1359          // Add Virtual Methods in order
1360          {
1361             int c;
1362             for(c = regClass.base ? regClass.base.vTblSize : 0; c < regClass.vTblSize; c++)
1363             {
1364                for(method = (Method)regClass.methods.first; method; method = (Method)((BTNode)method).next)
1365                {
1366                   if(method.type == virtualMethod && method._class == regClass && method.vid == c)
1367                   {
1368                      char name[1024];
1369                      Expression exp;
1370
1371                      //External external = method->symbol ? ((Symbol)method.symbol).methodExternal : null;
1372                      External external = method.symbol ? ((Symbol)method.symbol).methodCodeExternal : null;
1373                      OldList * args = MkList();
1374                      Identifier id = (external && external.function) ? GetDeclId(external.function.declarator) : null;
1375
1376                      // Class * class
1377                      ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1378                      // char * name
1379                      {
1380                         char * string = QMkString(method.name);
1381                         ListAdd(args, MkExpString(string));
1382                         delete string;
1383                      }
1384                      // char * type
1385                      {
1386                         char * string = QMkString(method.dataTypeString);
1387                         ListAdd(args, MkExpString(string));
1388                         delete string;
1389                      }
1390                      // void * function
1391                      if(id && external.function.body)
1392                      {
1393                         ListAdd(args, (exp = MkExpIdentifier(MkIdentifier(id.string))));
1394                         exp.expType = Type { refCount = 1 };
1395                      }
1396                      else
1397                      {
1398                         ListAdd(args, (exp = MkExpConstant("0")));
1399                      }
1400
1401                      // Declaration Mode
1402                      switch(method.memberAccess)
1403                      {
1404                         case staticAccess:
1405                            ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
1406                            break;
1407                         case privateAccess:
1408                            ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1409                            break;
1410                         case publicAccess:
1411                         default:
1412                            ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
1413                            break;
1414                      }
1415
1416                      //sprintf(name, "__ecereVMethodID_%s_%s", method._class.fullName, method.name);
1417                      strcpy(name, "__ecereVMethodID_");
1418                      FullClassNameCat(name, method._class.fullName, false);
1419                      strcat(name, "_");
1420                      strcat(name, method.name);
1421
1422                      exp = /*MkExpPointer(*/MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddVirtualMethod")), args)/*, MkIdentifier("vid"))*/;
1423                      /*
1424                      exp->expType = eSystem_New(sizeof(Type));
1425                      exp->expType->refCount++;
1426                      exp->expType->isSigned = true;
1427                      exp->expType->kind = TypeInt;
1428                      */
1429
1430                      stmt = MkExpressionStmt(MkListOne(/*
1431                         MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', */exp/*)*/));
1432
1433                      DeclareMethod(method, name);
1434
1435                      ListAdd(registerModuleBody.compound.statements, stmt);
1436                   }
1437                }
1438             }
1439          }
1440
1441
1442          // Add Public Methods (all for now)
1443          for(method = (Method)regClass.methods.first; method; method = (Method)((BTNode)method).next)
1444          {
1445             if(method.type == virtualMethod && method._class == regClass);
1446             else if(method.memberAccess == publicAccess || !method.dataTypeString)
1447             {
1448                //External external = method.symbol ? ((Symbol )method.symbol).methodExternal : null;
1449                External external = method.symbol ? ((Symbol )method.symbol).methodCodeExternal : null;
1450                OldList * args = MkList();
1451                Identifier id = (external && external.function) ? GetDeclId(external.function.declarator) : null;
1452
1453                // Class class
1454                ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1455                // char * name
1456                {
1457                   char * string = QMkString(method.name);
1458                   ListAdd(args, MkExpString(string));
1459                   delete string;
1460                }
1461                // char * type
1462                {
1463                   char * string = QMkString(method.dataTypeString);
1464                   ListAdd(args, MkExpString(string));
1465                   delete string;
1466                }
1467                // void * function
1468                if(id && external.function.body)
1469                {
1470                   ListAdd(args, (exp = MkExpIdentifier(MkIdentifier(
1471                      id.string))));
1472                   exp.expType = Type { refCount = 1 };
1473                }
1474                else
1475                {
1476                   ListAdd(args, (exp = MkExpConstant("0")));
1477                }
1478
1479                // Declaration Mode
1480                switch(method.memberAccess)
1481                {
1482                   case staticAccess:
1483                      ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
1484                      break;
1485                   case privateAccess:
1486                      ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1487                      break;
1488                   case publicAccess:
1489                   default:
1490                      ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
1491                      break;
1492                }
1493
1494                stmt = MkExpressionStmt(MkListOne(
1495                   MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddMethod")), args)));
1496                ListAdd(registerModuleBody.compound.statements, stmt);
1497             }
1498          }
1499
1500          RegisterMembersAndProperties(regClass, false, "class", registerModuleBody);
1501
1502          // Add Enumeration Values
1503          if(classType == enumClass)
1504          {
1505             NamedLink value;
1506             Class enumClass = eSystem_FindClass(privateModule, "enum");
1507             EnumClassData e = ACCESS_CLASSDATA(regClass, enumClass);
1508
1509             for(value = e.values.first; value; value = value.next)
1510             {
1511                OldList * args = MkList();
1512
1513                // Class class
1514                ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1515                // char * name
1516                {
1517                   char * string = QMkString(value.name);
1518                   ListAdd(args, MkExpString(string));
1519                   delete string;
1520                }
1521                // uint value
1522                {
1523                   char temp[1024];
1524                   // TODO: Support 64 bit enums
1525                   sprintf(temp, "%d", (int)value.data);
1526                   ListAdd(args, MkExpConstant(temp));
1527                }
1528
1529                stmt = MkExpressionStmt(MkListOne(
1530                   MkExpCall(MkExpIdentifier(MkIdentifier("eEnum_AddFixedValue")), args)));
1531                ListAdd(registerModuleBody.compound.statements, stmt);
1532             }
1533          }
1534
1535          // Add Template Parameters
1536          if(symbol.templateParams)
1537          {
1538             TemplateParameter param;
1539             for(param = symbol.templateParams->first; param; param = param.next)
1540             {
1541                OldList * args = MkList();
1542
1543                // Class
1544                ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1545
1546                // Name
1547                {
1548                   char * string = QMkString(param.identifier.string);
1549                   ListAdd(args, MkExpString(string));
1550                   delete string;
1551                }
1552
1553                // Type
1554                ListAdd(args, MkExpIdentifier(MkIdentifier((param.type == type) ? "type" : ((param.type == identifier) ? "identifier" : "expression"))));
1555
1556                // Parameter
1557                switch(param.type)
1558                {
1559                   case type:
1560                   case expression:
1561                   {
1562                      char * typeString = param.dataType ? StringFromSpecDecl(param.dataType.specifiers, param.dataType.decl) : null;
1563                      char * string = QMkString(typeString);
1564                      ListAdd(args, MkExpString(string));
1565                      delete typeString;
1566                      delete string;
1567                      break;
1568                   }
1569                   case identifier:
1570                   {
1571                      char memberTypeString[132] = "TemplateMemberType::";
1572                      bool needClass = true;
1573
1574                      param.memberType.OnGetString(memberTypeString + strlen(memberTypeString), null, &needClass);
1575                      ListAdd(args,
1576                         MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)),
1577                            MkExpIdentifier(MkIdentifier(memberTypeString))));
1578                      break;
1579                   }
1580                }
1581
1582                // Default Argument
1583                if(param.defaultArgument)
1584                {
1585                   OldList * members = MkList();
1586                   switch(param.type)
1587                   {
1588                      case type:
1589                      {
1590                         char * typeString = param.defaultArgument.templateDatatype ?
1591                            StringFromSpecDecl(param.defaultArgument.templateDatatype.specifiers, param.defaultArgument.templateDatatype.decl) : null;
1592                         char * string = QMkString(typeString);
1593
1594                         members->Add(MkMemberInit(MkListOne(MkIdentifier("dataTypeString")), MkInitializerAssignment(MkExpString(string))));
1595
1596                         delete typeString;
1597                         delete string;
1598                         break;
1599                      }
1600                      case identifier:
1601                      {
1602                         char memberString[1024];
1603                         char * string;
1604                         memberString[0] = '\0';
1605
1606                         if(param.defaultArgument.identifier._class)
1607                         {
1608                            if(param.defaultArgument.identifier._class.type == templateTypeSpecifier)
1609                               strcpy(memberString, param.defaultArgument.identifier._class.templateParameter.identifier.string);
1610                            else if(param.defaultArgument.identifier._class.name)
1611                               strcpy(memberString, param.defaultArgument.identifier._class.name);
1612                         }
1613                         if(memberString[0])
1614                            strcat(memberString, "::");
1615
1616                         strcat(memberString, param.defaultArgument.identifier.string);
1617
1618                         string = QMkString(memberString);
1619
1620                         // TOFIX: UNIONS ARE BROKEN FOR ASSIGNMENTS, USING dataTypeString INSTEAD
1621                         // members->Add(MkMemberInit(MkListOne(MkIdentifier("memberString")), MkInitializerAssignment(MkExpString(string))));
1622                         members->Add(MkMemberInit(MkListOne(MkIdentifier("dataTypeString")), MkInitializerAssignment(MkExpString(string))));
1623
1624                         delete string;
1625                         break;
1626                      }
1627                      case expression:
1628                      {
1629                         Operand op { };
1630                         OldList * ids = MkList();
1631                         char * ui64String;
1632                         char * string = null;
1633
1634                         //ProcessExpressionType(param.defaultArgument.expression);
1635                         //ComputeExpression(param.defaultArgument.expression);
1636
1637                         op = GetOperand(param.defaultArgument.expression);
1638                         ui64String = PrintUInt64(op.ui64);
1639                         ids->Add(MkIdentifier("expression"));
1640                         ids->Add(MkIdentifier("ui64"));
1641
1642                         //string = QMkString(ui64String);
1643                         members->Add(MkMemberInit(ids, MkInitializerAssignment(MkExpConstant(ui64String))));
1644
1645                         delete string;
1646                         delete ui64String;
1647                         break;
1648                      }
1649                   }
1650                   ListAdd(args, MkExpInstance(MkInstantiation(MkSpecifierName("ClassTemplateArgument"), null,
1651                      MkListOne(MkMembersInitList(members)))));
1652                }
1653                else
1654                   ListAdd(args, MkExpIdentifier(MkIdentifier("null")));
1655
1656                stmt = MkExpressionStmt(MkListOne(
1657                   MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddTemplateParameter")), args)));
1658                ListAdd(registerModuleBody.compound.statements, stmt);
1659             }
1660             stmt = MkExpressionStmt(MkListOne(
1661                MkExpCall(MkExpIdentifier(MkIdentifier("eClass_DoneAddingTemplateParameters")),
1662                   MkListOne(MkExpIdentifier(MkIdentifier("class"))))));
1663             ListAdd(registerModuleBody.compound.statements, stmt);
1664          }
1665
1666          if(definitions != null)
1667          {
1668             for(def = definitions.first; def; def = def.next)
1669             {
1670                if(def.type == propertyWatchClassDef && def.propertyWatch)
1671                {
1672                   ListAdd(registerModuleBody.compound.statements, (Statement)def.propertyWatch);
1673                   def.propertyWatch = null;
1674                }
1675                else if(def.type == classDesignerClassDef)
1676                {
1677                   /*
1678                   char className[1024];
1679                   sprintf(className, "__ecereClass_%s", def.designer);
1680                   MangleClassName(className);
1681
1682                   DeclareClass(FindClass(def.designer), className);
1683                   */
1684
1685                   {
1686                      char * s = QMkString(def.designer);
1687                      stmt = MkIfStmt(MkListOne(MkExpIdentifier(MkIdentifier("class"))), MkExpressionStmt(MkListOne(
1688                         MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("designerClass")), '=',
1689                            MkExpString(s)))), null);
1690                      delete s;
1691                   }
1692                   ListAdd(registerModuleBody.compound.statements, stmt);
1693                }
1694                else if(def.type == classNoExpansionClassDef)
1695                {
1696                   stmt = MkIfStmt(MkListOne(MkExpIdentifier(MkIdentifier("class"))), MkExpressionStmt(MkListOne(
1697                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("noExpansion")), '=',
1698                         MkExpConstant("1")))), null);
1699                   ListAdd(registerModuleBody.compound.statements, stmt);
1700                }
1701                else if(def.type == classFixedClassDef)
1702                {
1703                   stmt = MkIfStmt(MkListOne(MkExpIdentifier(MkIdentifier("class"))), MkExpressionStmt(MkListOne(
1704                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("fixed")), '=',
1705                         MkExpConstant("1")))), null);
1706                   ListAdd(registerModuleBody.compound.statements, stmt);
1707                   if(regClass)
1708                      regClass.fixed = true;
1709                }
1710                else if(def.type == designerDefaultPropertyClassDef)
1711                {
1712                   char * s = QMkString(def.defaultProperty.string);
1713                   stmt = MkIfStmt(MkListOne(MkExpIdentifier(MkIdentifier("class"))), MkExpressionStmt(MkListOne(
1714                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("defaultProperty")), '=',
1715                         MkExpString(s)))), null);
1716                   ListAdd(registerModuleBody.compound.statements, stmt);
1717                   delete s;
1718                }
1719                else if(def.type == classPropertyValueClassDef)
1720                {
1721                   classPropValues.Add(ClassPropertyValue { regClass = regClass, id = def.id, exp = def.initializer.exp });
1722                   def.id = null;
1723                   def.initializer.exp = null;
1724                }
1725             }
1726          }
1727       }
1728    }
1729 }
1730
1731 class ClassPropertyValue
1732 {
1733    Class regClass;
1734    Identifier id;
1735    Expression exp;
1736
1737    ~ClassPropertyValue()
1738    {
1739       FreeIdentifier(id);
1740    }
1741 };
1742
1743 static List<ClassPropertyValue> classPropValues { };
1744
1745 public void ProcessClassDefinitions()
1746 {
1747    External external, next;
1748
1749    CreateRegisterModuleBody();
1750    if(ast)
1751    {
1752       // (Need to do those things after in case something is not yet defined)
1753       for(external = ast->first; external; external = next)
1754       {
1755          next = external.next;
1756          curExternal = external;
1757          if(external.type == classExternal)
1758          {
1759             ClassDefinition _class = external._class;
1760             if(_class.definitions)
1761             {
1762                ProcessClass(normalClass, _class.definitions, _class.symbol, _class.baseSpecs, null, ast, external, _class.declMode);
1763             }
1764             if(inCompiler)
1765             {
1766                ast->Remove(external);
1767                FreeExternal(external);
1768             }
1769          }
1770          else if(external.type == functionExternal)
1771          {
1772             bool setStaticMethod = false;
1773             // Mark
1774             if(external.symbol && !external.symbol.type.thisClass && !external.symbol.type.staticMethod)
1775             {
1776                // TOCHECK: Where do we actually need this to be set?
1777                external.symbol.type.staticMethod = true;
1778                setStaticMethod = true;
1779             }
1780
1781             if(inCompiler)
1782             {
1783                FunctionDefinition function = external.function;
1784                Statement stmt;
1785                OldList * args;
1786
1787                if(!strcmp(function.declarator.symbol.string, "__on_register_module"))
1788                {
1789                   ListAdd(registerModuleBody.compound.statements, function.body);
1790                   function.body.compound.context.parent = registerModuleBody.compound.context;
1791                   ast->Remove(external);
1792                   function.body = null;
1793                   FreeExternal(external);
1794                   continue;
1795                }
1796
1797                if(function.declMode != privateAccess && function.declMode != publicAccess) continue;
1798
1799                args = MkList();
1800
1801                CreateRegisterModuleBody();
1802
1803                // Identifier
1804                {
1805                   char * string = QMkString(function.declarator.symbol.string);
1806                   ListAdd(args, MkExpString(string));
1807                   delete string;
1808                }
1809
1810                // Type
1811                {
1812                   char * string;
1813                   char type[1024] = "";
1814                   // We don't want functions to be marked as static methods
1815                   if(setStaticMethod)
1816                      function.declarator.symbol.type.staticMethod = false;
1817                   PrintType(function.declarator.symbol.type, type, true, true);
1818                   if(setStaticMethod)
1819                      function.declarator.symbol.type.staticMethod = true;
1820                   string = QMkString(type);
1821                   ListAdd(args, MkExpString(string));
1822                   delete string;
1823                }
1824
1825                // Function
1826                {
1827                   ListAdd(args, MkExpIdentifier(MkIdentifier(function.declarator.symbol.string)));
1828                }
1829
1830                // Module
1831                ListAdd(args, MkExpIdentifier(MkIdentifier("module")));
1832
1833                // Declaration Mode
1834                switch(function.declMode)
1835                {
1836                   case staticAccess:
1837                      ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
1838                      break;
1839                   case privateAccess:
1840                      ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1841                      break;
1842                   case publicAccess:
1843                   default:
1844                      ListAdd(args, MkExpIdentifier(MkIdentifier(buildingECERECOMModule ? "baseSystemAccess" : "publicAccess")));
1845                      break;
1846                }
1847
1848                stmt = MkExpressionStmt(MkListOne(
1849                   MkExpCall((MkExpIdentifier(MkIdentifier("eSystem_RegisterFunction"))), args)));
1850
1851                ListAdd(registerModuleBody.compound.statements, stmt);
1852             }
1853          }
1854          else if(external.type == declarationExternal)
1855          {
1856             Declaration declaration = external.declaration;
1857
1858             if(external.symbol)
1859             {
1860                if(external.symbol.type && external.symbol.type.kind == functionType && !external.symbol.type.thisClass)
1861                   external.symbol.type.staticMethod = true;
1862             }
1863
1864             if(external.symbol && declaration.type == initDeclaration)
1865             {
1866                if(declaration.specifiers)
1867                {
1868                   Specifier specifier;
1869                   bool removeExternal = false;
1870
1871                   for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
1872                   {
1873                      if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string &&
1874                         (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
1875                      {
1876                         Symbol symbol = FindClass(specifier.id.string);
1877                         if(symbol)
1878                         {
1879                            ClassType classType;
1880                            if(specifier.type == enumSpecifier)
1881                               classType = enumClass;
1882                            else
1883                               classType = structClass;
1884
1885                            removeExternal = true;
1886                            // Transfer Context over to Symbol
1887                            symbol.ctx = specifier.ctx;
1888                            specifier.ctx = null;
1889
1890                            ProcessClass(classType, specifier.definitions, symbol, specifier.baseSpecs, specifier.list,ast, external, declaration.declMode);
1891                         }
1892                      }
1893                   }
1894                   if(inCompiler && removeExternal)
1895                   {
1896                      ast->Remove(external);
1897                      FreeExternal(external);
1898                   }
1899                }
1900             }
1901             else if(declaration.type == defineDeclaration)
1902             {
1903                if(inCompiler && declaration.declMode != staticAccess)
1904                {
1905                   Statement stmt;
1906                   OldList * args = MkList();
1907
1908                   CreateRegisterModuleBody();
1909
1910                   // Identifier
1911                   {
1912                      char * string = QMkString(declaration.id.string);
1913                      ListAdd(args, MkExpString(string));
1914                      delete string;
1915                   }
1916
1917                   // Expression
1918                   {
1919                      char * string;
1920                      char type[1024] = "";
1921                      PrintExpression(declaration.exp, type);
1922                      string = QMkString(type);
1923                      ListAdd(args, MkExpString(string));
1924                      delete string;
1925                   }
1926
1927                   // Module
1928                   ListAdd(args, MkExpIdentifier(MkIdentifier("module")));
1929
1930                   // Declaration Mode
1931                   switch(declaration.declMode)
1932                   {
1933                      case staticAccess:
1934                         ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
1935                         break;
1936                      case privateAccess:
1937                         ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1938                         break;
1939                      case publicAccess:
1940                      default:
1941                         ListAdd(args, MkExpIdentifier(MkIdentifier(buildingECERECOMModule ? "baseSystemAccess" : "publicAccess")));
1942                         break;
1943                   }
1944
1945                   stmt = MkExpressionStmt(MkListOne(
1946                      MkExpCall((MkExpIdentifier(MkIdentifier("eSystem_RegisterDefine"))), args)));
1947
1948                   ListAdd(registerModuleBody.compound.statements, stmt);
1949                }
1950             }
1951          }
1952       }
1953
1954       // Set the class properties at the very end
1955       for(v : classPropValues)
1956       {
1957          OldList * findClassArgs = MkList();
1958          OldList * args = MkList();
1959          Statement compoundStmt;
1960          String s;
1961
1962          ListAdd(findClassArgs, MkExpIdentifier(MkIdentifier("module")));
1963          s = QMkString(v.regClass.name);
1964          ListAdd(findClassArgs, MkExpString(s));
1965          delete s;
1966
1967          ListAdd(args, MkExpIdentifier(MkIdentifier("_class")));
1968          s = QMkString(v.id.string);
1969          ListAdd(args, MkExpString(s));
1970          delete s;
1971          ListAdd(args, MkExpCast(MkTypeName(MkListOne(MkSpecifier(INT64)), null), v.exp));
1972          compoundStmt = MkCompoundStmt(MkListOne(MkDeclaration(MkListOne(MkSpecifierName("ecere::com::Class")),
1973                        MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("_class")),
1974                         MkInitializerAssignment(MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eSystem_FindClass")), findClassArgs)))))),
1975             MkListOne(MkExpressionStmt(MkListOne(
1976                MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eClass_SetProperty")), args)))));
1977          compoundStmt.compound.context = Context { parent = registerModuleBody.compound.context };
1978          ListAdd(registerModuleBody.compound.statements, compoundStmt);
1979       }
1980
1981       classPropValues.Free();
1982    }
1983 }