compiler/libec: Proper __attribute__ support and other fixes to compile for Android
[sdk] / compiler / libec / src / firstPass.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.h"
5
6 static void AddDefinitions(Class regClass, DataMember member, OldList definitions)
7 {
8    if(definitions != null)
9    {
10       ClassDef def;
11       for(def = definitions.first; def; def = def.next)
12       {
13          if(def.type == declarationClassDef)
14          {
15             Declaration decl = def.decl;
16             DataMember dataMember;
17             Type dataType;
18
19             if(decl.type == structDeclaration)
20             {
21                Declarator d;
22                // Add data members to the class
23                if(decl.declarators)
24                {
25                   for(d = decl.declarators->first; d; d = d.next)
26                   {
27                      Identifier declId = GetDeclId(d);
28                      if(declId)
29                      {
30                         if(regClass && regClass.type == bitClass)
31                         {
32                            Expression sizeExp = d.structDecl.exp, posExp = d.structDecl.posExp;
33                            int bitSize = 0, bitPos = -1;
34                            char dataTypeString[1024] = "";
35                         
36                            if(sizeExp)
37                            {
38                               // Should this be processed/computed later?
39                               ProcessExpressionType(sizeExp);
40                               ComputeExpression(sizeExp);
41
42                               if(sizeExp.isConstant)
43                                  bitSize = strtol(sizeExp.constant, null, 0);
44                               FreeExpression(sizeExp);
45                            }
46
47                            if(posExp)
48                            {
49                               // Should this be processed/computed later?
50                               ProcessExpressionType(posExp);
51                               ComputeExpression(posExp);
52
53                               if(posExp.isConstant)
54                                  bitPos = strtol(posExp.constant, null, 0);
55                               FreeExpression(posExp);
56                            }
57
58                            d.structDecl.posExp = null;
59                            d.structDecl.exp = null;
60
61                            dataType = ProcessType(decl.specifiers, d);
62                            PrintType(dataType, dataTypeString, false, true);
63
64                            //if(!eClass_FindDataMember(regClass, declId.string))
65                            {
66                               BitMember member = eClass_AddBitMember(regClass, declId.string, dataTypeString, 0, 0, def.memberAccess);
67                               if(member)
68                               {
69                                  member.size = bitSize;
70                                  member.pos = bitPos;
71                               }
72                               dataMember = (DataMember)member;
73                            }
74
75                            if(dataMember)
76                               dataMember.dataType = dataType;
77                            else
78                            {
79                               Compiler_Error($"Member with same name already exists %s in class %s\n", declId.string, regClass.name);
80                               FreeType(dataType);
81                            }
82                         }
83                         else
84                         {
85                            //if(isMember || !eClass_FindDataMember(regClass, declId.string))
86                            {
87                               //char * dataTypeString = StringFromSpecDecl(decl.specifiers, d);
88                               char typeString[1024] = "";
89                               dataType = ProcessType(decl.specifiers, d);
90                               PrintType(dataType, typeString, false, true);
91
92                               if(member)
93                               {
94                                  dataMember = eMember_AddDataMember(member, declId.string, 
95                                     typeString, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
96                                  if(!dataMember)
97                                     Compiler_Error($"Member with same name already exists %s in member %s\n", declId.string, member.name);
98                               }
99                               else
100                               {
101                                  dataMember = eClass_AddDataMember(regClass, declId.string, 
102                                     typeString, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
103                                  if(!dataMember)
104                                     Compiler_Error($"Member with same name already exists %s in class %s\n", declId.string, regClass.name);
105                               }
106
107                               //delete dataTypeString;
108                               if(dataMember)
109                                  dataMember.dataType = dataType;
110                               else
111                                  FreeType(dataType);
112                            }
113                         }
114                      }
115                   }
116                }
117                else if(decl.specifiers)
118                {
119                   Specifier spec;
120                   // Unnamed struct/union
121                   for(spec = decl.specifiers->first; spec; spec = spec.next)
122                   {
123                      if(spec.type == structSpecifier || spec.type == unionSpecifier)
124                      {
125                         if(spec.definitions && !spec.id)
126                         {
127                            DataMember dataMember = eMember_New((spec.type == unionSpecifier) ? unionMember : structMember, def.memberAccess);
128                            
129                            AddDefinitions(null, dataMember, spec.definitions);
130
131                            if(member)
132                            {
133                               eMember_AddMember(member, dataMember);
134                            }
135                            else
136                            {
137                               eClass_AddMember(regClass, dataMember);
138                            }
139                         }
140                         else if(spec.definitions && spec.id)
141                         {
142                            //if(isMember || !eClass_FindDataMember(regClass, spec.id.string))
143                            {
144                               Identifier id = spec.id;
145                               char typeString[1024] = "";
146
147                               spec.id = null;
148                               decl.declarators = MkListOne(MkDeclaratorIdentifier(id));
149
150                               dataType = ProcessType(decl.specifiers, null);
151                               PrintType(dataType, typeString, false, true);
152
153                               if(member)
154                               {
155                                  dataMember = eMember_AddDataMember(member, id.string, 
156                                     typeString, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
157                                  if(!dataMember)
158                                     Compiler_Error($"Member with same name already exists %s in member %s\n", id.string, member.name);
159                               }
160                               else
161                               {
162                                  dataMember = eClass_AddDataMember(regClass, id.string, 
163                                     typeString, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
164                                  if(!dataMember)
165                                     Compiler_Error($"Member with same name already exists %s in class %s\n", id.string, regClass.name);
166
167                               }
168
169                               // delete dataTypeString;
170                               if(dataMember)
171                                  dataMember.dataType = dataType;
172                               else
173                                  FreeType(dataType);
174                            }
175                         }
176                      }
177                   }
178                }
179             }
180             else if(decl.type == instDeclaration)
181             {
182                Instantiation inst = decl.inst;
183                Expression exp = inst.exp;
184                if(exp)
185                {
186                   // Add data member to the class
187                   char * string = exp.identifier.string;
188                   //if(isMember || !eClass_FindDataMember(regClass, string))
189                   {
190                      Type dataType
191                      {
192                         kind = classType;
193                         _class = inst._class.symbol; // FindClass(inst._class.name);
194                         refCount = 1;
195                      };
196                      if(member)
197                      {
198                         dataMember = eMember_AddDataMember(member, string, inst._class.name, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
199                         if(!dataMember)
200                            Compiler_Error($"Member with same name already exists %s in member %s\n", string, member.name);
201
202                      }
203                      else
204                      {
205                         dataMember = eClass_AddDataMember(regClass, string, inst._class.name, 0, 0 /*ComputeTypeSize(dataType)*/, def.memberAccess);
206                         if(!dataMember)
207                            Compiler_Error($"Member with same name already exists %s in class %s\n", string, regClass.name);
208                      }
209                      if(dataMember)
210                         dataMember.dataType = dataType;
211                      else
212                         FreeType(dataType);
213                   }
214                }
215             }
216          }
217          // TODO: Decide whether property ID should go after member ID, if so this should move back to ProcessClass
218          else if(def.type == propertyClassDef && def.propertyDef)
219          {
220             PropertyDef propertyDef = def.propertyDef;
221             Property prop;
222
223             // Register the property in the list
224             // MOVED THIS UP HERE BEFORE NEXT BLOCK BECAUSE WE NULL OUT SPECIFIERS/DECLARATORS... OK?
225             
226             char * dataTypeString = StringFromSpecDecl(propertyDef.specifiers, propertyDef.declarator);
227             prop = eClass_AddProperty(regClass, propertyDef.conversion ? null : propertyDef.id.string,
228                dataTypeString,
229                inCompiler ? propertyDef.setStmt : null, inCompiler ? propertyDef.getStmt : null, def.memberAccess);
230             delete dataTypeString;
231             if(prop)
232             {
233                if(inCompiler) prop.IsSet = (void *)propertyDef.issetStmt;
234
235                prop.compiled = false;
236                
237                // prop.symbol = propertyDef.symbol;
238                prop.symbol = Symbol
239                {
240                   string = CopyString(propertyDef.symbol.string);
241                   id = propertyDef.symbol.id;
242                   type = propertyDef.symbol.type;
243                };
244
245                /*if(propertyDef.category) 
246                {
247                   char temp[1024];
248                   ReadString(temp, propertyDef.category);
249                   prop.category = CopyString(temp);  // LEAK: To free in parsed classes...
250                }*/
251                // TODO: Support property category in parsing mode
252                ((Symbol)prop.symbol).propCategory = propertyDef.category;
253                propertyDef.category = null;
254
255                if(propertyDef.isWatchable)
256                   eProperty_Watchable(prop);
257             }
258             else
259                // TODO: What happens here?
260                printf("");
261
262
263             // Testing this... wasn't found anywhere, seems to be useful
264             // (Determining if it's a conversion property in ProcessClassFunction)
265             propertyDef.symbol._property = prop;
266
267             if(propertyDef.symbol.type)
268                propertyDef.symbol.type.refCount++;
269          }
270          else if(def.type == classPropertyClassDef && def.propertyDef)
271          {
272             PropertyDef propertyDef = def.propertyDef;
273             ClassProperty prop;
274
275             // Register the property in the list
276             // MOVED THIS UP HERE BEFORE NEXT BLOCK BECAUSE WE NULL OUT SPECIFIERS/DECLARATORS... OK?
277             
278             char * dataTypeString = StringFromSpecDecl(propertyDef.specifiers, propertyDef.declarator);
279             prop = eClass_AddClassProperty(regClass, propertyDef.id.string, dataTypeString,
280                inCompiler ? propertyDef.setStmt : null, inCompiler ? propertyDef.getStmt : null);
281
282             delete dataTypeString;
283          }
284       }
285    }
286 }
287
288 static void ProcessClass(ClassType classType, OldList definitions, Symbol symbol, OldList baseSpecs, OldList enumValues, Location loc, OldList defs, void * after, OldList initDeclarators, AccessMode declMode)
289 {
290    Class regClass;
291    ClassDef def;
292    bool redefinition = false;
293
294    regClass = eSystem_FindClass(privateModule /*__thisModule*/, symbol.string);
295    if(regClass && !regClass.internalDecl)
296    {
297       if(symbol.parent || (Symbol)globalContext.classes.root == symbol)
298       {
299          globalContext.classes.Remove((BTNode)symbol);
300          excludedSymbols->Add(symbol);
301       }
302       redefinition = true;
303       if(inCompiler)
304       {
305          yylloc = loc;
306          Compiler_Error($"redefinition of class %s\n", symbol.string /*_class._class.name*/);
307          return;
308       }
309    }
310    else
311    {
312       char baseName[1024] = "";
313       bool unitType = false;
314       bool wouldBeEnum = false;
315       AccessMode inheritanceAccess = publicAccess;
316
317       if(baseSpecs != null)
318       {
319          Type baseType = ProcessType(baseSpecs, null);
320          PrintType(baseType, baseName, false, true);
321          if(baseType.kind == TypeKind::classType)
322          {
323             if(baseType._class.registered && classType == normalClass)
324             {
325                if(baseType._class.registered.type == unitClass)
326                   classType = unitClass;
327                else if(baseType._class.registered.type == bitClass)
328                   classType = bitClass;
329                else if(baseType._class.registered.type == noHeadClass)
330                   classType = noHeadClass;
331                else if(baseType._class.registered.type == enumClass)
332                {
333                   wouldBeEnum = true;
334                   //classType = enumClass;
335                }
336             }
337          }
338          else if(baseType.kind == structType || baseType.kind == unionType) 
339          {
340             classType = noHeadClass;
341             baseName[0] = '\0';
342          }
343          else 
344             unitType = true;
345          FreeType(baseType);
346
347          if(((Specifier)baseSpecs.first).type == baseSpecifier && ((Specifier)baseSpecs.first).specifier == PRIVATE)
348             inheritanceAccess = privateAccess;
349       }
350
351       // If there's any struct declaration in a unit data type, it means this is a bit class
352       if(classType == normalClass)
353       {
354          if(unitType) classType = unitClass;
355          if(definitions != null)
356          {
357             for(def = definitions.first; def; def = def.next)
358             {
359                if(def.type == declarationClassDef)
360                {
361                   Declaration decl = def.decl;
362                   if(decl.type == structDeclaration)
363                   {
364                      if(unitType)
365                      {
366                         classType = bitClass;
367                         break;
368                      }
369                      if(decl.declarators)
370                      {
371                         Declarator d;
372
373                         for(d = decl.declarators->first; d; d = d.next)
374                         {
375                            if(d.structDecl.exp)
376                            {
377                               classType = bitClass;
378                               break;
379                            }
380                         }
381                         if(d) break;
382                      }
383                   }
384                }
385             }
386          }
387       }
388       if(classType == normalClass && wouldBeEnum) classType = enumClass;
389
390       regClass = symbol.registered = eSystem_RegisterClass((classType == unionClass) ? structClass : classType,
391          symbol.string, baseName[0] ? baseName : null, 0, 0, null, null, privateModule, buildingECERECOMModule ? baseSystemAccess : declMode /*publicAccess*/, inheritanceAccess);
392
393       // HI DANGER: TESTING THIS
394       if(regClass)
395          regClass.symbol = symbol;
396    }
397
398    // First check if there's any declaration or instantiations, we'll need a struct
399    if(!redefinition)
400    {
401       if(classType == unionClass)
402       {
403          DataMember unionMember = eMember_New(DataMemberType::unionMember, publicAccess);
404          AddDefinitions(regClass, unionMember, definitions);
405          eClass_AddMember(regClass, unionMember);
406       }
407       else
408          AddDefinitions(regClass, null, definitions);
409    }
410
411    // Do the functions
412    if(definitions != null)
413    {
414       for(def = definitions.first; def; def = def.next)
415       {
416          if(def.type == functionClassDef && def.function.declarator)
417          {
418             ClassFunction func = def.function;
419
420             func._class = regClass;
421             // Add ecereMethod_[class]_ to the declarator
422             if(!redefinition && !func.dontMangle)
423             {
424                Declarator funcDecl = GetFuncDecl(func.declarator);
425                Identifier id = GetDeclId(funcDecl);
426                Method method;               
427                         
428                if(func.isVirtual)
429                {
430                   char * typeString = StringFromSpecDecl(func.specifiers, func.declarator);
431                   method = eClass_AddVirtualMethod(regClass, id.string, typeString, inCompiler ? func.declarator.symbol : null, def.memberAccess);
432                   delete typeString;
433                }
434                else
435                {
436                   char * typeString = StringFromSpecDecl(func.specifiers, func.declarator);
437                   method = eClass_AddMethod(regClass, id.string, typeString, 
438                      inCompiler ? func.declarator.symbol : null, def.memberAccess);
439                   if(!method)
440                      Compiler_Error($"Redefinition of method %s in class %s\n", id.string, regClass.name);
441                   delete typeString;
442                }
443                if(method && (method.type != virtualMethod || method._class == regClass))
444                {
445                   //method.symbol = func.declarator.symbol;
446
447                   // Make a copy here...
448                   method.symbol = Symbol
449                   {
450                      string = CopyString(func.declarator.symbol.string);
451                      id = func.declarator.symbol.id;
452                      type = func.declarator.symbol.type;
453                      method = method;
454                   };
455                   if(func.declarator.symbol.type)
456                      func.declarator.symbol.type.refCount++;
457
458                   func.declarator.symbol.method = method;
459                }
460                else
461                {
462                   /*
463                   method.symbol = Symbol
464                   {
465                      string = CopyString(func.declarator.symbol.string);
466                      id = func.declarator.symbol.id;
467                      type = func.declarator.symbol.type;
468                      method = method;
469                   };
470                   if(func.declarator.symbol.type)
471                      func.declarator.symbol.type.refCount++;
472                   */
473                   func.declarator.symbol.method = method;
474                }
475             }
476          }
477       }
478    }
479    if(regClass && symbol.templateParams)
480    {
481       TemplateParameter param;
482       // Add template parameters here
483       for(param = symbol.templateParams->first; param; param = param.next)
484       {
485          ClassTemplateArgument defaultArg { };
486          if(param.defaultArgument)
487          {
488             switch(param.type)
489             {
490                case type:
491                   defaultArg.dataTypeString = 
492                      StringFromSpecDecl(param.defaultArgument.templateDatatype.specifiers, param.defaultArgument.templateDatatype.decl);
493                   break;
494                case identifier:
495                {
496                   char memberString[1024];
497                   memberString[0] = '\0';
498
499                   if(param.defaultArgument.identifier._class)
500                   {
501                      if(param.defaultArgument.identifier._class.type == templateTypeSpecifier)
502                      {
503                         if(param.defaultArgument.identifier._class.templateParameter)
504                            strcpy(memberString, param.defaultArgument.identifier._class.templateParameter.identifier.string);
505                      }
506                      else
507                      {
508                         if(param.defaultArgument.identifier._class.name)
509                            strcpy(memberString, param.defaultArgument.identifier._class.name);
510                      }
511                   }
512                   
513                   if(memberString[0])
514                   {
515                      strcat(memberString, "::");
516                   }
517                   strcat(memberString, param.defaultArgument.identifier.string);
518                   defaultArg.memberString = CopyString(memberString);
519                   break;
520                }
521                case expression:
522                {
523                   Operand op;
524                   param.defaultArgument.expression.destType = ProcessType(param.dataType.specifiers, param.dataType.decl);
525                   ProcessExpressionType(param.defaultArgument.expression);
526                   ComputeExpression(param.defaultArgument.expression);
527                   op = GetOperand(param.defaultArgument.expression);
528                   defaultArg.expression.ui64 = op.ui64;
529                   break;
530                }
531             }
532          }
533          if(param.type == identifier)
534          {
535             eClass_AddTemplateParameter(regClass, param.identifier.string, identifier, (void *)param.memberType, defaultArg);
536          }
537          else
538          {
539             char * typeString = param.dataType ? StringFromSpecDecl(param.dataType.specifiers, param.dataType.decl) : null;
540             eClass_AddTemplateParameter(regClass, param.identifier.string, param.type, typeString, defaultArg);
541             delete typeString;
542          }
543          if(param.type == type || param.type == identifier)
544             delete defaultArg.dataTypeString;
545
546       }
547       eClass_DoneAddingTemplateParameters(regClass);
548    }
549 }
550
551 extern External curExternal;
552
553 public void PrePreProcessClassDefinitions()
554 {
555    External external, next;
556
557    curExternal = null;
558
559    if(ast)
560    {
561       for(external = ast->first; external; external = next)
562       {
563          next = external.next;
564          curExternal = external;
565          if(external.type == classExternal)
566          {
567             ClassDefinition _class = external._class;
568             if(_class.definitions && (!_class.symbol.registered || !inCompiler))
569             {
570                ProcessClass(normalClass, _class.definitions, _class.symbol, _class.baseSpecs, null, _class.loc, ast, external.prev, null, _class.declMode);
571                _class.symbol.isStatic = _class.declMode == staticAccess;
572             }
573          }
574          else if(external.type == declarationExternal)
575          {
576             Declaration declaration = external.declaration;
577             if(declaration.type == initDeclaration)
578             {
579                if(declaration.specifiers)
580                {
581                   Specifier specifier;
582                   for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
583                   {
584                      if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string && 
585                         (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
586                      {
587                         Symbol type = FindType(globalContext, specifier.id.string);
588                         Symbol symbol = FindClass(specifier.id.string);
589                         if(type)
590                         {
591                            declaration.declMode = defaultAccess;
592                            if(symbol)
593                            {
594                               globalContext.classes.Remove((BTNode)symbol);
595                               excludedSymbols->Add(symbol);
596                            }
597                         }
598                         else if(symbol && !symbol.registered)
599                         {
600                            ClassType classType;
601
602                            if(specifier.type == enumSpecifier)
603                               classType = enumClass;
604                            else if(specifier.type == unionSpecifier)
605                               classType = unionClass;
606                            else
607                               classType = structClass;
608                            ProcessClass(classType, specifier.definitions, symbol, specifier.baseSpecs, specifier.list, specifier.loc, ast, external.prev, declaration.declarators, declaration.declMode);
609                            symbol.isStatic = declaration.declMode == staticAccess;
610                         }
611                      }
612                   }
613                }
614             }
615          }
616          else if(external.type == importExternal)
617          {
618             //ImportModule(external._import);
619          }
620       }
621
622
623       // Update templated classes
624       {
625          for(external = ast->first; external; external = external.next)
626          {
627             if(external.type == classExternal)
628             {
629                ClassDefinition _class = external._class;
630                if(_class.symbol)
631                {
632                   OldLink link;
633                   for(link = _class.symbol.templatedClasses.first; link; link = link.next)
634                   {
635                      Symbol symbol = link.data;
636                      symbol.registered = eSystem_FindClass(privateModule, symbol.string);
637                   }
638                }
639             }
640             else if(external.type == declarationExternal)
641             {
642                Declaration declaration = external.declaration;
643                if(declaration.type == initDeclaration)
644                {
645                   if(declaration.specifiers)
646                   {
647                      Specifier specifier;
648                      for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
649                      {
650                         if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string && 
651                            (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
652                         {
653                            Symbol type = FindType(globalContext, specifier.id.string);
654                            Symbol symbol = FindClass(specifier.id.string);
655                            if(type)
656                            {
657                            }
658                            else if(symbol)
659                            {
660                               OldLink link;
661                               for(link = symbol.templatedClasses.first; link; link = link.next)
662                               {
663                                  Symbol tplSymbol = link.data;
664                                  tplSymbol.registered = eSystem_FindClass(privateModule, tplSymbol.string);
665                                  tplSymbol.module = symbol.module ? symbol.module : mainModule;
666                               }
667                            }
668                         }
669                      }
670                   }
671                }
672             }
673          } 
674       }
675    }
676 }