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