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