Initial git commit -- Transition from CodeGuard repository
[sdk] / compiler / libec / src / firstPass.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.eh"
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
252                if(propertyDef.isWatchable)
253                   eProperty_Watchable(prop);
254             }
255             else
256                // TODO: What happens here?
257                printf("");
258
259
260             // Testing this... wasn't found anywhere, seems to be useful
261             // (Determining if it's a conversion property in ProcessClassFunction)
262             propertyDef.symbol._property = prop;
263
264             if(propertyDef.symbol.type)
265                propertyDef.symbol.type.refCount++;
266          }
267          else if(def.type == classPropertyClassDef && def.propertyDef)
268          {
269             PropertyDef propertyDef = def.propertyDef;
270             ClassProperty prop;
271
272             // Register the property in the list
273             // MOVED THIS UP HERE BEFORE NEXT BLOCK BECAUSE WE NULL OUT SPECIFIERS/DECLARATORS... OK?
274             
275             char * dataTypeString = StringFromSpecDecl(propertyDef.specifiers, propertyDef.declarator);
276             prop = eClass_AddClassProperty(regClass, propertyDef.id.string, dataTypeString,
277                inCompiler ? propertyDef.setStmt : null, inCompiler ? propertyDef.getStmt : null);
278
279             delete dataTypeString;
280
281             // Testing this... wasn't found anywhere, seems to be useful 
282             // (Determining if it's a conversion property in ProcessClassFunction)
283             // propertyDef.symbol.property = prop;
284
285             if(propertyDef.symbol.type)
286                propertyDef.symbol.type.refCount++;
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.structDecl.exp)
380                            {
381                               classType = bitClass;
382                               break;
383                            }
384                         }
385                         if(d) break;
386                      }
387                   }
388                }
389             }
390          }
391       }
392       if(classType == normalClass && wouldBeEnum) classType = enumClass;
393
394       regClass = symbol.registered = eSystem_RegisterClass((classType == unionClass) ? structClass : classType,
395          symbol.string, baseName[0] ? baseName : null, 0, 0, null, null, privateModule, buildingECERECOMModule ? baseSystemAccess : declMode /*publicAccess*/, inheritanceAccess);
396
397       // HI DANGER: TESTING THIS
398       if(regClass)
399          regClass.symbol = symbol;
400    }
401
402    // First check if there's any declaration or instantiations, we'll need a struct
403    if(!redefinition)
404    {
405       if(classType == unionClass)
406       {
407          DataMember unionMember = eMember_New(DataMemberType::unionMember, publicAccess);
408          AddDefinitions(regClass, unionMember, definitions);
409          eClass_AddMember(regClass, unionMember);
410       }
411       else
412          AddDefinitions(regClass, null, definitions);
413    }
414
415    // Do the functions
416    if(definitions != null)
417    {
418       for(def = definitions.first; def; def = def.next)
419       {
420          if(def.type == functionClassDef && def.function.declarator)
421          {
422             ClassFunction func = def.function;
423
424             func._class = regClass;
425             // Add ecereMethod_[class]_ to the declarator
426             if(!redefinition && !func.dontMangle)
427             {
428                Declarator funcDecl = GetFuncDecl(func.declarator);
429                Identifier id = GetDeclId(funcDecl);
430                Method method;               
431                         
432                if(func.isVirtual)
433                {
434                   char * typeString = StringFromSpecDecl(func.specifiers, func.declarator);
435                   method = eClass_AddVirtualMethod(regClass, id.string, typeString, inCompiler ? func.declarator.symbol : null, def.memberAccess);
436                   delete typeString;
437                }
438                else
439                {
440                   char * typeString = StringFromSpecDecl(func.specifiers, func.declarator);
441                   method = eClass_AddMethod(regClass, id.string, typeString, 
442                      inCompiler ? func.declarator.symbol : null, def.memberAccess);
443                   if(!method)
444                      Compiler_Error("Redefinition of method %s in class %s\n", id.string, regClass.name);
445                   delete typeString;
446                }
447                if(method && (method.type != virtualMethod || method._class == regClass))
448                {
449                   //method.symbol = func.declarator.symbol;
450
451                   // Make a copy here...
452                   method.symbol = Symbol
453                   {
454                      string = CopyString(func.declarator.symbol.string);
455                      id = func.declarator.symbol.id;
456                      type = func.declarator.symbol.type;
457                      method = method;
458                   };
459                   if(func.declarator.symbol.type)
460                      func.declarator.symbol.type.refCount++;
461
462                   func.declarator.symbol.method = method;
463                }
464                else
465                {
466                   /*
467                   method.symbol = Symbol
468                   {
469                      string = CopyString(func.declarator.symbol.string);
470                      id = func.declarator.symbol.id;
471                      type = func.declarator.symbol.type;
472                      method = method;
473                   };
474                   if(func.declarator.symbol.type)
475                      func.declarator.symbol.type.refCount++;
476                   */
477                   func.declarator.symbol.method = method;
478                }
479             }
480          }
481       }
482    }
483    if(regClass && symbol.templateParams)
484    {
485       TemplateParameter param;
486       // Add template parameters here
487       for(param = symbol.templateParams->first; param; param = param.next)
488       {
489          ClassTemplateArgument defaultArg { };
490          if(param.defaultArgument)
491          {
492             switch(param.type)
493             {
494                case type:
495                   defaultArg.dataTypeString = 
496                      StringFromSpecDecl(param.defaultArgument.templateDatatype.specifiers, param.defaultArgument.templateDatatype.decl);
497                   break;
498                case identifier:
499                {
500                   char memberString[1024];
501                   memberString[0] = '\0';
502
503                   if(param.defaultArgument.identifier._class && param.defaultArgument.identifier._class.name)
504                   {
505                      if(param.defaultArgument.identifier._class.type == templateTypeSpecifier)
506                         strcpy(memberString, param.defaultArgument.identifier._class.templateParameter.identifier.string);
507                      else
508                         strcpy(memberString, param.defaultArgument.identifier._class.name);
509                   }
510                   
511                   if(memberString[0])
512                   {
513                      strcat(memberString, "::");
514                   }
515                   strcat(memberString, param.defaultArgument.identifier.string);
516                   defaultArg.memberString = CopyString(memberString);
517                   break;
518                }
519                case expression:
520                {
521                   Operand op;
522                   param.defaultArgument.expression.destType = ProcessType(param.dataType.specifiers, param.dataType.decl);
523                   ProcessExpressionType(param.defaultArgument.expression);
524                   ComputeExpression(param.defaultArgument.expression);
525                   op = GetOperand(param.defaultArgument.expression);
526                   defaultArg.expression.ui64 = op.ui64;
527                   break;
528                }
529             }
530          }
531          if(param.type == identifier)
532          {
533             eClass_AddTemplateParameter(regClass, param.identifier.string, identifier, (void *)param.memberType, defaultArg);
534          }
535          else
536          {
537             char * typeString = param.dataType ? StringFromSpecDecl(param.dataType.specifiers, param.dataType.decl) : null;
538             eClass_AddTemplateParameter(regClass, param.identifier.string, param.type, typeString, defaultArg);
539             delete typeString;
540          }
541          if(param.type == type || param.type == identifier)
542             delete defaultArg.dataTypeString;
543
544       }
545       eClass_DoneAddingTemplateParameters(regClass);
546    }
547 }
548
549 extern External curExternal;
550
551 public void PrePreProcessClassDefinitions()
552 {
553    External external, next;
554
555    curExternal = null;
556
557    if(ast)
558    {
559       for(external = ast->first; external; external = next)
560       {
561          next = external.next;
562          curExternal = external;
563          if(external.type == classExternal)
564          {
565             ClassDefinition _class = external._class;
566             if(_class.definitions && !_class.symbol.registered)
567             {
568                ProcessClass(normalClass, _class.definitions, _class.symbol, _class.baseSpecs, null, _class.loc, ast, external.prev, null, _class.declMode);
569                _class.symbol.isStatic = _class.declMode == staticAccess;
570             }
571          }
572          else if(external.type == declarationExternal)
573          {
574             Declaration declaration = external.declaration;
575             if(declaration.type == initDeclaration)
576             {
577                if(declaration.specifiers)
578                {
579                   Specifier specifier;
580                   for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
581                   {
582                      if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string && 
583                         (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
584                      {
585                         Symbol type = FindType(globalContext, specifier.id.string);
586                         Symbol symbol = FindClass(specifier.id.string);
587                         if(type)
588                         {
589                            declaration.declMode = defaultAccess;
590                            if(symbol)
591                            {
592                               globalContext.classes.Remove((BTNode)symbol);
593                               excludedSymbols->Add(symbol);
594                            }
595                         }
596                         else if(symbol && !symbol.registered)
597                         {
598                            ClassType classType;
599
600                            if(specifier.type == enumSpecifier)
601                               classType = enumClass;
602                            else if(specifier.type == unionSpecifier)
603                               classType = unionClass;
604                            else
605                               classType = structClass;
606                            ProcessClass(classType, specifier.definitions, symbol, specifier.baseSpecs, specifier.list, specifier.loc, ast, external.prev, declaration.declarators, declaration.declMode);
607                            symbol.isStatic = declaration.declMode == staticAccess;
608                         }
609                      }
610                   }
611                }
612             }
613          }
614          else if(external.type == importExternal)
615          {
616             //ImportModule(external._import);
617          }
618       }
619
620
621       // Update templated classes
622       {
623          for(external = ast->first; external; external = external.next)
624          {
625             if(external.type == classExternal)
626             {
627                ClassDefinition _class = external._class;
628                if(_class.symbol)
629                {
630                   OldLink link;
631                   for(link = _class.symbol.templatedClasses.first; link; link = link.next)
632                   {
633                      Symbol symbol = link.data;
634                      symbol.registered = eSystem_FindClass(privateModule, symbol.string);
635                   }
636                }
637             }
638             else if(external.type == declarationExternal)
639             {
640                Declaration declaration = external.declaration;
641                if(declaration.type == initDeclaration)
642                {
643                   if(declaration.specifiers)
644                   {
645                      Specifier specifier;
646                      for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
647                      {
648                         if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string && 
649                            (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
650                         {
651                            Symbol type = FindType(globalContext, specifier.id.string);
652                            Symbol symbol = FindClass(specifier.id.string);
653                            if(type)
654                            {
655                            }
656                            else if(symbol)
657                            {
658                               OldLink link;
659                               for(link = symbol.templatedClasses.first; link; link = link.next)
660                               {
661                                  Symbol tplSymbol = link.data;
662                                  tplSymbol.registered = eSystem_FindClass(privateModule, tplSymbol.string);
663                                  tplSymbol.module = symbol.module ? symbol.module : mainModule;
664                               }
665                            }
666                         }
667                      }
668                   }
669                }
670             }
671          } 
672       }
673    }
674 }