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