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