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