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