978888f32a13c9a81c33da616ec6fb1ce85a04ff
[sdk] / compiler / libec / src / pass3.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.h"
5
6 extern External curExternal;
7 ///////////////// INSTANCE DECLARATION PASS ///////////////////////
8
9 // Returns true if we should add a * to the declarator
10 static int ReplaceClassSpec(OldList specs, Specifier spec, bool param)
11 {
12    if(spec.type == templateTypeSpecifier)
13    {
14       TemplateParameter parameter = spec.templateParameter;
15
16       if(!param && parameter.dataTypeString)
17       {
18          OldList * newSpecs = MkList();
19          Declarator decl = SpecDeclFromString(parameter.dataTypeString, newSpecs, null);
20          if(newSpecs->first)
21          {
22             Specifier newSpec = CopySpecifier(newSpecs->first);
23             *spec = *newSpec;
24             delete newSpec;
25          }
26          FreeList(newSpecs, FreeSpecifier);
27
28          if(decl)
29          {
30             bool isPointer = decl.type == pointerDeclarator;
31             if(decl)
32                FreeDeclarator(decl);
33             if(isPointer)
34                return 1;
35          }
36       }
37       else if(!param && parameter.dataType)
38       {
39          OldList * newSpecs = parameter.dataType.specifiers;
40          Declarator decl = parameter.dataType.decl;
41          if(newSpecs->first)
42          {
43             Specifier newSpec = CopySpecifier(newSpecs->first);
44             *spec = *newSpec;
45             delete newSpec;
46          }
47
48          if(decl)
49          {
50             bool isPointer = decl.type == pointerDeclarator;
51             if(isPointer)
52                return 1;
53          }
54       }
55       else
56       {
57          spec.type = nameSpecifier;
58          spec.name = CopyString("uint64");
59          spec.symbol = FindClass("uint64");
60       }
61    }
62
63    if(spec.type == nameSpecifier || spec.type == subClassSpecifier)
64    {
65       // TODO: Apply more care because nameSpecifier / subClassSpecifier use different parts of the union!
66       Symbol classSym = spec.symbol;
67       if(spec.type == subClassSpecifier)
68       {
69          classSym = FindClass("ecere::com::Class");
70       }
71
72       if(classSym)
73       {
74          Class _class = classSym.registered;
75
76          FreeSpecifierContents(spec);
77
78          spec.type = nameSpecifier;
79          if(_class && _class.type == structClass)
80          {
81             //Externalexternal;
82             char name[1024];
83             name[0] = 0;
84             FullClassNameCat(name, _class.fullName, false);
85             FreeSpecifierContents(spec);
86             spec.type = structSpecifier;
87             spec.baseSpecs = null;
88             spec.id = MkIdentifier(name);
89             spec.list = null;
90             spec.definitions = null;
91             spec.ctx = null;
92             spec.addNameSpace = false;
93          }
94          else if(_class && _class.type == noHeadClass)
95          {
96             char name[1024] = "";
97             FullClassNameCat(name, _class.fullName, false);
98             spec.type = structSpecifier;
99             spec.baseSpecs = null;
100             spec.id = MkIdentifier(name);
101             spec.list = null;
102             spec.definitions = null;
103             spec.ctx = null;
104             spec.addNameSpace = false;
105          }
106          else if(_class)
107          {
108             if((_class.type != systemClass ||
109                !strcmp(_class.fullName, "enum") ||
110                (_class.dataTypeString && !strcmp(_class.dataTypeString, "char *")) ||
111                //strcmp(_class.fullName, "bool") &&
112                !strcmp(_class.fullName, "uint64") ||
113                !strcmp(_class.fullName, "uint32") ||
114                !strcmp(_class.fullName, "uint16") ||
115                !strcmp(_class.fullName, "uintptr") ||
116                !strcmp(_class.fullName, "intptr") ||
117                !strcmp(_class.fullName, "uintsize") ||
118                !strcmp(_class.fullName, "intsize") ||
119                !strcmp(_class.fullName, "uint") ||
120                !strcmp(_class.fullName, "byte")))
121             {
122                if(_class.dataTypeString)
123                {
124                   if(!strcmp(_class.dataTypeString, "uint64") ||
125                      !strcmp(_class.dataTypeString, "uint32") ||
126                      !strcmp(_class.dataTypeString, "uint16") ||
127                      !strcmp(_class.dataTypeString, "uintptr") ||
128                      !strcmp(_class.dataTypeString, "intptr") ||
129                      !strcmp(_class.dataTypeString, "uintsize") ||
130                      !strcmp(_class.dataTypeString, "intsize") ||
131                      !strcmp(_class.dataTypeString, "uint") ||
132                      !strcmp(_class.dataTypeString, "byte"))
133                   {
134                      if(!_class.dataType)
135                         _class.dataType = ProcessTypeString(_class.dataTypeString, false);
136                      if(_class.dataType && _class.dataType.kind == classType)
137                         classSym = _class.dataType._class;
138                      else
139                         classSym = FindClass(_class.dataTypeString);
140                      _class = classSym ? classSym.registered : null;
141                   }
142
143                   spec.name = CopyString(!strcmp(_class.dataTypeString, "char *") ? "char" : _class.dataTypeString);
144                   spec.symbol = null;
145                }
146                else
147                {
148                   spec.name = CopyString(null);
149                   spec.symbol = null;
150                }
151             }
152             else if(!_class.base)
153             {
154                spec.type = baseSpecifier;
155                spec.specifier = VOID;
156                return 1;
157             }
158          }
159          else
160          {
161             spec.type = structSpecifier;
162             spec.id = MkIdentifier("__ecereNameSpace__ecere__com__Instance");
163             spec.list = null;
164             spec.baseSpecs = null;
165             spec.definitions = null;
166             spec.ctx = null;
167             spec.addNameSpace = false;
168          }
169
170          if(_class && _class.dataTypeString && !strcmp(_class.dataTypeString, "char *"))
171             return 1; //false;
172          if(!_class || _class.type == normalClass || _class.type == noHeadClass)
173             return 1;
174          else if(param && _class.type == structClass)
175             return 2;
176       }
177    }
178    else if(spec.type == baseSpecifier)
179    {
180       if(spec.specifier == ANY_OBJECT || spec.specifier == CLASS)
181       {
182          spec.specifier = CONST;
183          specs.Add(MkSpecifier(VOID));
184          return 1;
185       }
186    }
187    return 0;
188 }
189
190 static void ReplaceByInstancePtr(Specifier spec, Declarator * declPtr, int type)
191 {
192    Declarator decl = *declPtr;
193    if(decl && decl.type == pointerDeclarator)
194    {
195       // Pointers to simple classes shouldn't be added pointers
196       if(type == 2);
197       else
198       // Add pointer
199          decl.pointer.pointer = MkPointer(null, decl.pointer.pointer);
200    }
201    else
202    {
203       Declarator newDecl { };
204       if(decl)
205       {
206          *newDecl = *decl;
207          decl.declarator = newDecl;
208       }
209       else
210          decl = newDecl;
211       decl.type = pointerDeclarator;
212       decl.pointer.pointer = MkPointer(null, null);
213       *declPtr = decl;
214    }
215 }
216
217 static void InstDeclPassSpecifier(Specifier spec, bool byRefTypedObject)
218 {
219    switch(spec.type)
220    {
221       case baseSpecifier:
222          if(spec.specifier == TYPED_OBJECT)
223          {
224             spec.type = extendedSpecifier;
225             spec.extDecl = MkExtDeclString(CopyString(byRefTypedObject ?
226                "struct __ecereNameSpace__ecere__com__Class * class, void *" :
227                "struct __ecereNameSpace__ecere__com__Class * class, const void *"));
228             DeclareStruct(curExternal, "ecere::com::Class", false, true);
229          }
230          break;
231       case nameSpecifier:
232          break;
233       case enumSpecifier:
234       {
235          Enumerator e;
236          if(spec.list)
237          {
238             for(e = spec.list->first; e; e = e.next)
239             {
240
241             }
242          }
243          break;
244       }
245       case structSpecifier:
246       case unionSpecifier:
247       {
248          if(spec.definitions)
249          {
250             ClassDef def;
251             for(def = spec.definitions->first; def; def = def.next)
252                if(def.decl)
253                   InstDeclPassDeclaration(def.decl);
254          }
255          if(spec.id)
256             InstDeclPassIdentifier(spec.id);
257          break;
258       }
259       case extendedSpecifier:
260          if(spec.extDecl && spec.extDecl.type == extDeclString && spec.extDecl.s)
261          {
262             if(!strcmp(spec.extDecl.s, "dllexport"))
263             {
264                Specifier prevSpec;
265                delete spec.extDecl.s;
266                for(prevSpec = spec.prev; prevSpec; prevSpec = prevSpec.prev)
267                   if(prevSpec.type == baseSpecifier && prevSpec.specifier == EXTERN)
268                      break;
269                if(prevSpec)
270                {
271                   if(targetPlatform == win32)
272                      spec.extDecl.s = CopyString("__declspec(dllexport)");
273                   else
274                      spec.extDecl.s = CopyString("__attribute__ ((visibility(\"default\")))");
275                }
276                else
277                {
278                   if(targetPlatform == win32)
279                      spec.extDecl.s = CopyString("extern __declspec(dllexport)");
280                   else
281                      spec.extDecl.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
282                }
283             }
284             else if(!strcmp(spec.extDecl.s, "stdcall") || !strcmp(spec.extDecl.s, "_stdcall") ||
285                !strcmp(spec.extDecl.s, "__stdcall") || !strcmp(spec.extDecl.s, "__stdcall__"))
286             {
287                delete spec.extDecl.s;
288                spec.extDecl.s = CopyString("ecere_stdcall");
289             }
290          }
291          break;
292    }
293 }
294
295 static void InstDeclPassDeclarator(Declarator decl)
296 {
297    switch(decl.type)
298    {
299       case structDeclarator:
300          if(decl.declarator)
301             InstDeclPassDeclarator(decl.declarator);
302          break;
303       case identifierDeclarator:
304       {
305          if(decl.identifier)
306             InstDeclPassIdentifier(decl.identifier);
307          break;
308       }
309       case bracketsDeclarator:
310          if(decl.declarator)
311             InstDeclPassDeclarator(decl.declarator);
312          break;
313       case arrayDeclarator:
314          if(decl.declarator)
315             InstDeclPassDeclarator(decl.declarator);
316          break;
317       case functionDeclarator:
318       {
319          if(decl.declarator)
320             InstDeclPassDeclarator(decl.declarator);
321          if(decl.function.parameters)
322          {
323             TypeName type;
324             if(decl.declarator)
325                InstDeclPassDeclarator(decl.declarator);
326             for(type = decl.function.parameters->first; type; type = type.next)
327             {
328                bool typedObject = false;
329                Specifier spec = null;
330                if(type.qualifiers)
331                {
332                   spec = (Specifier)type.qualifiers->first;
333                   if(spec && spec.type == nameSpecifier && !strcmp(spec.name, "class"))
334                      typedObject = true;
335                }
336
337                InstDeclPassTypeName(type, true);
338                if(typedObject)
339                {
340                   TypeName _class
341                   {
342                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
343                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
344                   };
345                   DeclareStruct(curExternal, "ecere::com::Class", false, true);
346                   decl.function.parameters->Insert(spec.prev, _class);
347                }
348             }
349          }
350          break;
351       }
352       case pointerDeclarator:
353       case extendedDeclarator:
354       case extendedDeclaratorEnd:
355          if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended)
356          {
357             if(decl.extended.extended.type == extDeclString && decl.extended.extended.s && !strcmp(decl.extended.extended.s, "dllexport"))
358             {
359                delete decl.extended.extended.s;
360                if(targetPlatform == win32)
361                   decl.extended.extended.s = CopyString("extern __declspec(dllexport)");
362                else
363                   decl.extended.extended.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
364             }
365             else if(decl.extended.extended.type == extDeclString && decl.extended.extended.s &&
366                (!strcmp(decl.extended.extended.s, "stdcall") || !strcmp(decl.extended.extended.s, "_stdcall") ||
367                !strcmp(decl.extended.extended.s, "__stdcall") || !strcmp(decl.extended.extended.s, "__stdcall__")))
368             {
369                delete decl.extended.extended.s;
370                decl.extended.extended.s = CopyString("ecere_stdcall");
371             }
372          }
373          if(decl.declarator)
374             InstDeclPassDeclarator(decl.declarator);
375          break;
376    }
377 }
378
379 /*static */void InstDeclPassTypeName(TypeName type, bool param)
380 {
381    if(type.qualifiers)
382    {
383       Specifier spec;
384       for(spec = type.qualifiers->first; spec; spec = spec.next)
385       {
386          int result;
387          if((result = ReplaceClassSpec(type.qualifiers, spec, param)))
388             ReplaceByInstancePtr(spec, &type.declarator, result);
389          else
390          {
391             Symbol classSym = (spec.type == nameSpecifier) ? spec.symbol /*FindClass(spec.name)*/ : null;
392             if(type.classObjectType && (!classSym || (classSym && classSym.registered &&
393                (classSym.registered.type == enumClass || classSym.registered.type == bitClass || classSym.registered.type == unitClass))))
394                ReplaceByInstancePtr(spec, &type.declarator, 2);
395          }
396          InstDeclPassSpecifier(spec, type.declarator && type.declarator.type == pointerDeclarator);
397       }
398    }
399    if(type.declarator)
400       InstDeclPassDeclarator(type.declarator);
401 }
402
403 static void InstDeclPassIdentifier(Identifier id)
404 {
405    if(strchr(id.string, ':'))
406    {
407       char newID[1024];
408       int c;
409       char ch;
410       int len;
411       strcpy(newID, "__ecereNameSpace__");
412       len = strlen(newID);
413
414       for(c = 0; (ch = id.string[c]); c++)
415       {
416          if(ch == ':') ch = '_';
417
418          newID[len++] = ch;
419       }
420       newID[len] = 0;
421       delete id.string;
422       id.string = CopyString(newID);
423    }
424 }
425
426 /*static */bool IsVoidPtrCast(TypeName typeName)
427 {
428    bool result = false;
429    Declarator d = typeName.declarator;
430    if(d && d.type == pointerDeclarator && d.pointer.pointer && !d.pointer.pointer.pointer)
431    {
432       if(typeName.qualifiers)
433       {
434          Specifier s;
435          for(s = typeName.qualifiers->first; s; s = s.next)
436          {
437             if(s.type == baseSpecifier && s.specifier == VOID)
438                result = true;
439          }
440       }
441    }
442    return result;
443 }
444
445 static void AddPointerCast(Expression e)
446 {
447    Type src = e.expType;
448
449    if(src && (src.kind == templateType || src.kind == classType))
450    {
451       if(e.type != castExp || !IsVoidPtrCast(e.cast.typeName))
452       {
453          if(src) src.refCount++;
454          if(src.kind == templateType && src.templateParameter && src.templateParameter.type == type)
455          {
456             Type newType = null;
457             if(src.templateParameter.dataTypeString)
458                newType = ProcessTypeString(src.templateParameter.dataTypeString, false);
459             else if(src.templateParameter.dataType)
460                newType = ProcessType(src.templateParameter.dataType.specifiers, src.templateParameter.dataType.decl);
461             if(newType)
462             {
463                FreeType(src);
464                src = newType;
465             }
466          }
467          if(src && src.kind == classType && src._class)
468          {
469             Class sc = src._class.registered;
470             if(src.thisClassFrom && src.thisClassFrom.base)
471                sc = src.thisClassFrom;
472
473             if(sc && (sc.type == structClass || sc.type == noHeadClass))
474             {
475                Type dest = e.destType;
476
477                if(dest && (dest.kind == templateType || dest.kind == classType))
478                {
479                   if(dest) dest.refCount++;
480
481                   if(dest.kind == templateType && dest.templateParameter && dest.templateParameter.type == type)
482                   {
483                      Type newType = null;
484                      if(dest.templateParameter.dataTypeString)
485                         newType = ProcessTypeString(dest.templateParameter.dataTypeString, false);
486                      else if(dest.templateParameter.dataType)
487                         newType = ProcessType(dest.templateParameter.dataType.specifiers, dest.templateParameter.dataType.decl);
488                      if(newType)
489                      {
490                         FreeType(dest);
491                         dest = newType;
492                      }
493                   }
494                   if(!dest.passAsTemplate && dest.kind == classType && dest._class && dest._class.registered)
495                   {
496                      Class dc = dest._class.registered;
497
498                      if(sc.templateClass) sc = sc.templateClass;
499                      if(dc.templateClass) dc = dc.templateClass;
500                      if(dc.base && sc != dc)
501                      {
502                         e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
503                         e.type = castExp;
504                         e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
505                      }
506                   }
507                   FreeType(dest);
508                }
509             }
510          }
511          FreeType(src);
512       }
513    }
514    else if(src && src.kind == intPtrType && e.destType && e.destType.classObjectType)
515    {
516       Expression nbExp = GetNonBracketsExp(e);
517       if(nbExp.type != castExp || !IsVoidPtrCast(nbExp.cast.typeName))
518       {
519          e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
520          e.type = castExp;
521          e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
522       }
523    }
524 }
525
526 static void InstDeclPassExpression(Expression exp)
527 {
528    switch(exp.type)
529    {
530       case identifierExp:
531       {
532          if(exp.identifier)
533             InstDeclPassIdentifier(exp.identifier);
534          break;
535       }
536       case constantExp:
537          break;
538       case stringExp:
539          break;
540       case opExp:
541          if(exp.op.exp1)
542             InstDeclPassExpression(exp.op.exp1);
543          if(exp.op.exp2)
544          {
545             InstDeclPassExpression(exp.op.exp2);
546             if(exp.op.op != '=' && exp.op.exp1 && exp.op.exp1.expType && exp.op.exp1.expType.kind == pointerType && exp.op.exp1.expType.type && exp.op.exp1.expType.type.kind == templateType &&
547                exp.op.exp2.expType && exp.op.exp2.expType.kind == pointerType && exp.op.exp2.expType.type && exp.op.exp2.expType.type.kind == templateType)
548             {
549                Expression e = exp.op.exp2;
550                e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
551                e.type = castExp;
552                e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
553
554                e = exp.op.exp1;
555                e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
556                e.type = castExp;
557                e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
558             }
559             else if(exp.op.exp1 && (exp.op.op == '=' || exp.op.op == EQ_OP || exp.op.op == NE_OP))
560                AddPointerCast(exp.op.exp2);
561          }
562          break;
563       case extensionExpressionExp:
564       case bracketsExp:
565       {
566          Expression e;
567          for(e = exp.list->first; e; e = e.next)
568             InstDeclPassExpression(e);
569          break;
570       }
571       case indexExp:
572       {
573          Expression e;
574          InstDeclPassExpression(exp.index.exp);
575          for(e = exp.index.index->first; e; e = e.next)
576             InstDeclPassExpression(e);
577          break;
578       }
579       case callExp:
580       {
581          Expression e;
582          InstDeclPassExpression(exp.call.exp);
583          if(exp.call.arguments)
584          {
585             for(e = exp.call.arguments->first; e; e = e.next)
586             {
587                bool addCast = false;
588                InstDeclPassExpression(e);
589                AddPointerCast(e);
590
591                if(e.expType && e.expType.kind == pointerType && e.expType.type && (e.expType.type.kind == classType || (e.expType.type.kind == pointerType && e.expType.type.type && e.expType.type.type.kind != voidType)) &&
592                   e.destType && e.destType.kind == pointerType && e.destType.type && e.destType.type.kind == pointerType && e.destType.type.type && e.destType.type.type.kind == voidType)
593                   addCast = true;
594                // Fix for adding a cast to Unserialize with a struct passed as a parameter:
595                else if(e.expType && e.expType.kind == classType && e.expType._class && e.expType._class.registered && e.expType._class.registered.type == structClass && e.byReference &&
596                   e.destType && e.destType.kind == classType && e.destType.classObjectType && e.destType.byReference)
597                   addCast = true;
598
599                if(addCast && (e.type != castExp || !IsVoidPtrCast(e.cast.typeName)))
600                {
601                   e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
602                   e.type = castExp;
603                   e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
604                }
605             }
606          }
607          break;
608       }
609       case memberExp:
610       {
611          if(exp.member.exp)
612             InstDeclPassExpression(exp.member.exp);
613          break;
614       }
615       case pointerExp:
616       {
617          if(exp.member.exp)
618             InstDeclPassExpression(exp.member.exp);
619          break;
620       }
621       case typeSizeExp:
622          InstDeclPassTypeName(exp.typeName, false);
623          break;
624       case castExp:
625       {
626          Type type = exp.expType;
627          // Remove casts to simple structs... (Watch out for pointers later...)
628          if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass && !exp.needCast)
629          {
630             if(exp.destType && exp.destType.classObjectType == typedObject && exp.destType.byReference)
631             {
632                // For Unserialize with a StaticString
633                FreeTypeName(exp.cast.typeName);
634                exp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, MkPointer(null, null)), null));
635             }
636             else
637             {
638                Expression castExp = exp.cast.exp;
639                Expression prev = exp.prev, next = exp.next;
640                exp.cast.exp = null;
641                FreeExpContents(exp);
642                FreeType(exp.expType);
643                FreeType(exp.destType);
644                *exp = *castExp;
645                delete castExp;
646                exp.prev = prev;
647                exp.next = next;
648                InstDeclPassExpression(exp);
649             }
650          }
651          else
652          {
653             if(exp.expType && exp.expType.kind == pointerType)
654             {
655                if(exp.cast.exp && exp.cast.exp.expType && exp.cast.exp.expType.kind == templateType && !exp.cast.exp.expType.isPointerType)
656                   exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), exp.cast.exp);
657             }
658
659             InstDeclPassTypeName(exp.cast.typeName, exp.usage.usageArg /*false*/);
660             if(exp.cast.exp)
661             {
662                if(exp.expType && exp.expType.kind == templateType && exp.destType &&
663                   (exp.destType.passAsTemplate || (!exp.destType.templateParameter || (!exp.destType.templateParameter.dataType && !exp.destType.templateParameter.dataTypeString))) &&
664                   exp.cast.exp.expType && !exp.cast.exp.expType.passAsTemplate && exp.cast.exp.expType.isPointerType)
665                   exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), exp.cast.exp);
666                InstDeclPassExpression(exp.cast.exp);
667             }
668          }
669          break;
670       }
671       case conditionExp:
672       {
673          Expression e;
674          InstDeclPassExpression(exp.cond.cond);
675          for(e = exp.cond.exp->first; e; e = e.next)
676             InstDeclPassExpression(e);
677          InstDeclPassExpression(exp.cond.elseExp);
678          break;
679       }
680       case extensionCompoundExp:
681       {
682          InstDeclPassStatement(exp.compound);
683          break;
684       }
685       case vaArgExp:
686       {
687          InstDeclPassExpression(exp.vaArg.exp);
688          break;
689       }
690       case extensionInitializerExp:
691       {
692          InstDeclPassTypeName(exp.initializer.typeName, false);
693          InstDeclPassInitializer(exp.initializer.initializer);
694          break;
695       }
696    }
697 }
698
699 static void InstDeclPassInitializer(Initializer init)
700 {
701    switch(init.type)
702    {
703       case expInitializer:
704          if(init.exp)
705          {
706             InstDeclPassExpression(init.exp);
707             AddPointerCast(init.exp);
708          }
709          break;
710       case listInitializer:
711       {
712          Initializer i;
713          for(i = init.list->first; i; i = i.next)
714             InstDeclPassInitializer(i);
715          break;
716       }
717    }
718 }
719
720 static void InstDeclPassDeclaration(Declaration decl)
721 {
722    switch(decl.type)
723    {
724       case initDeclaration:
725       {
726          if(decl.specifiers)
727          {
728             Specifier spec;
729             for(spec = decl.specifiers->first; spec; spec = spec.next)
730             {
731                int type;
732                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
733                {
734                   InitDeclarator d;
735                   if(decl.declarators)
736                   {
737                      for(d = decl.declarators->first; d; d = d.next)
738                         ReplaceByInstancePtr(spec, &d.declarator, type);
739                   }
740                }
741                InstDeclPassSpecifier(spec, false);
742             }
743          }
744          if(decl.declarators)
745          {
746             InitDeclarator d;
747             for(d = decl.declarators->first; d; d = d.next)
748             {
749                InstDeclPassDeclarator(d.declarator);
750                if(d.initializer)
751                   InstDeclPassInitializer(d.initializer);
752             }
753          }
754          break;
755       }
756       case structDeclaration:
757       {
758          if(decl.specifiers)
759          {
760             Specifier spec;
761             for(spec = decl.specifiers->first; spec; spec = spec.next)
762             {
763                int type;
764                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
765                {
766                   if(decl.declarators)
767                   {
768                      Declarator d;
769                      for(d = decl.declarators->first; d; d = d.next)
770                         ReplaceByInstancePtr(spec, &d, type);
771                   }
772                }
773                InstDeclPassSpecifier(spec, false);
774             }
775          }
776
777          if(decl.declarators)
778          {
779             Declarator d;
780             for(d = decl.declarators->first; d; d = d.next)
781                InstDeclPassDeclarator(d);
782          }
783          break;
784       }
785       // This should be removed by now?
786       case instDeclaration:
787          // InstDeclPassInstantiation(decl.inst);
788          break;
789    }
790 }
791
792 static void InstDeclPassStatement(Statement stmt)
793 {
794    switch(stmt.type)
795    {
796       case badDeclarationStmt:
797          if(stmt.decl)
798             InstDeclPassDeclaration(stmt.decl);
799          break;
800       case labeledStmt:
801          InstDeclPassStatement(stmt.labeled.stmt);
802          break;
803       case caseStmt:
804          // This expression should be constant...
805          if(stmt.caseStmt.exp)
806             InstDeclPassExpression(stmt.caseStmt.exp);
807          if(stmt.caseStmt.stmt)
808             InstDeclPassStatement(stmt.caseStmt.stmt);
809          break;
810       case compoundStmt:
811       {
812          Declaration decl;
813          Statement s;
814          Context prevContext = curContext;
815
816          if(!stmt.compound.isSwitch)
817             curContext = stmt.compound.context;
818
819          if(stmt.compound.declarations)
820          {
821             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
822                InstDeclPassDeclaration(decl);
823          }
824          if(stmt.compound.statements)
825          {
826             for(s = stmt.compound.statements->first; s; s = s.next)
827                InstDeclPassStatement(s);
828          }
829          curContext = prevContext;
830          break;
831       }
832       case expressionStmt:
833       {
834          if(stmt.expressions)
835          {
836             Expression exp;
837             for(exp = stmt.expressions->first; exp; exp = exp.next)
838                InstDeclPassExpression(exp);
839          }
840          break;
841       }
842       case ifStmt:
843       {
844          if(stmt.ifStmt.exp)
845          {
846             Expression exp;
847             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
848                InstDeclPassExpression(exp);
849          }
850          if(stmt.ifStmt.stmt)
851             InstDeclPassStatement(stmt.ifStmt.stmt);
852          if(stmt.ifStmt.elseStmt)
853             InstDeclPassStatement(stmt.ifStmt.elseStmt);
854          break;
855       }
856       case switchStmt:
857       {
858          Expression exp;
859          if(stmt.switchStmt.exp)
860          {
861             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
862                InstDeclPassExpression(exp);
863          }
864          InstDeclPassStatement(stmt.switchStmt.stmt);
865          break;
866       }
867       case whileStmt:
868       {
869          Expression exp;
870          if(stmt.whileStmt.exp)
871          {
872             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
873                InstDeclPassExpression(exp);
874          }
875          InstDeclPassStatement(stmt.whileStmt.stmt);
876          break;
877       }
878       case doWhileStmt:
879       {
880          if(stmt.doWhile.exp)
881          {
882             Expression exp;
883             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
884                InstDeclPassExpression(exp);
885          }
886          if(stmt.doWhile.stmt)
887             InstDeclPassStatement(stmt.doWhile.stmt);
888          break;
889       }
890       case forStmt:
891       {
892          Expression exp;
893          if(stmt.forStmt.init)
894             InstDeclPassStatement(stmt.forStmt.init);
895          if(stmt.forStmt.check)
896             InstDeclPassStatement(stmt.forStmt.check);
897          if(stmt.forStmt.increment)
898          {
899             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
900                InstDeclPassExpression(exp);
901          }
902          if(stmt.forStmt.stmt)
903             InstDeclPassStatement(stmt.forStmt.stmt);
904          break;
905       }
906       case gotoStmt:
907          break;
908       case continueStmt:
909          break;
910       case breakStmt:
911          break;
912       case returnStmt:
913       {
914          Expression exp;
915          if(stmt.expressions)
916          {
917             for(exp = stmt.expressions->first; exp; exp = exp.next)
918                InstDeclPassExpression(exp);
919             AddPointerCast(stmt.expressions->last);
920          }
921          break;
922       }
923       case asmStmt:
924       {
925          AsmField field;
926          if(stmt.asmStmt.inputFields)
927          {
928             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
929                if(field.expression)
930                   InstDeclPassExpression(field.expression);
931          }
932          if(stmt.asmStmt.outputFields)
933          {
934             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
935                if(field.expression)
936                   InstDeclPassExpression(field.expression);
937          }
938          if(stmt.asmStmt.clobberedFields)
939          {
940             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
941                if(field.expression)
942                   InstDeclPassExpression(field.expression);
943          }
944          break;
945       }
946    }
947 }
948
949 void TopoSort(OldList * input)
950 {
951    OldList L { };
952    OldList S { };
953    OldList B { };
954    External n, next;
955    //External x;
956
957    for(n = input->first; n; n = next)
958    {
959       next = n.next;
960       if(n.type == declarationExternal && !n.declaration)
961       {
962          input->Remove(n);
963          if(n.symbol && n.symbol.structExternal == n)
964             n.symbol.structExternal = null;
965          FreeExternal(n);
966       }
967       else if(!n.incoming.count)
968       {
969          input->Remove(n);
970          S.Add(n);
971       }
972       else if(!n.nonBreakableIncoming)
973       {
974          input->Remove(n);
975          B.Add(n);
976       }
977    }
978 /*
979          for(x = input->first; x; x = x.next)
980          {
981             int count = 0;
982             for(e : x.incoming; !e.breakable)
983                count++;
984             if(count != x.nonBreakableIncoming)
985                printf("Bug in input");
986
987             if(!x.incoming.count)
988                printf("This node should be in S!\n");
989             for(e : x.incoming)
990             {
991                External y, from = e.from;
992                for(y = input->first; y; y = y.next)
993                   if(y == from)
994                      break;
995                if(!y)
996                {
997                   for(y = B.first; y; y = y.next)
998                      if(y == from)
999                         break;
1000                }
1001
1002                if(!y)
1003                {
1004                   for(y = S.first; y; y = y.next)
1005                      if(y == from)
1006                         break;
1007                }
1008                if(!y)
1009                {
1010                   printf("This node is nowhere!\n");
1011                }
1012             }
1013          }*/
1014
1015    while(true)
1016    {
1017       TopoEdge e, ne;
1018       if((n = S.first))
1019       {
1020          /*
1021          for(x = input->first; x; x = x.next)
1022          {
1023             int count = 0;
1024             for(e : x.incoming; !e.breakable)
1025                count++;
1026             if(count != x.nonBreakableIncoming)
1027                printf("Bug in input");
1028             if(!x.incoming.count)
1029                printf("This node should be in S!\n");
1030             for(e : x.incoming)
1031             {
1032                External y, from = e.from;
1033                for(y = input->first; y; y = y.next)
1034                   if(y == from)
1035                      break;
1036                if(!y)
1037                {
1038                   for(y = B.first; y; y = y.next)
1039                      if(y == from)
1040                         break;
1041                }
1042
1043                if(!y)
1044                {
1045                   for(y = S.first; y; y = y.next)
1046                      if(y == from)
1047                         break;
1048                }
1049                if(!y)
1050                {
1051                   printf("This node is nowhere!\n");
1052                }
1053             }
1054          }*/
1055
1056          //DebugPrint("*** Free Node: [", n.id, "]\n\t", n.output);
1057          S.Remove((IteratorPointer)n);
1058
1059          /*
1060          if(n && n.symbol && n.symbol.string && !strcmp(n.symbol.string, "ecere::com::Instance"))
1061             printf("Adding Instance\n");
1062          */
1063
1064          L.Add(n);
1065          for(e = n.outgoing.first; e; e = ne)
1066          {
1067             External m = e.to;
1068             OldList * list;
1069
1070             //DebugPrint(" This Free Node has an edge to [", m.id, "] ", m.output);
1071             if(m.nonBreakableIncoming)
1072             {
1073                //DebugPrint("... which we think is in input");
1074                list = input;
1075             }
1076             else
1077             {
1078                //DebugPrint("... which we think is in B");
1079                list = &B;
1080             }
1081
1082             if(!list->count)
1083                PrintLn("!!! Something's wrong !!!");
1084             ne = e.out.next;
1085
1086             if(!e.breakable)
1087             {
1088 #ifdef _DEBUG
1089                if(!m.nonBreakableIncoming)
1090                   printf("Bug");
1091 #endif
1092                m.nonBreakableIncoming--;
1093                //DebugPrint("Reducing non breakable incoming, now ", m.nonBreakableIncoming);
1094             }
1095
1096             n.outgoing.Remove((IteratorPointer)e);
1097             m.incoming.Remove((IteratorPointer)e);
1098             delete e;
1099
1100             if(!m.incoming.count)
1101             {
1102                //DebugPrint("Last edge to this node taken out, moving to S...");
1103                list->Remove(m);
1104                S.Add(m);
1105             }
1106             else if(!m.nonBreakableIncoming)
1107             {
1108                //DebugPrint("Last non-breakable edge to this node taken out, moving to B...");
1109                list->Remove(m);
1110                B.Add(m);
1111             }
1112          }
1113       }
1114       else if((n = B.first))
1115       {
1116          //DebugPrint("Breaking some of the ", n.incoming.count, " incoming edges to [", n.id, "] ", n.output);
1117          B.Remove((IteratorPointer)n);
1118
1119          // Break the edges of this node
1120          for(e = n.incoming.first; e; e = ne)
1121          {
1122             TopoEdge e2, n2;
1123             External m = e.from;
1124             External f;
1125 /*
1126          for(x = input->first; x; x = x.next)
1127          {
1128             int count = 0;
1129             for(e : x.incoming; !e.breakable)
1130                count++;
1131             if(count != x.nonBreakableIncoming)
1132                printf("Bug in input");
1133             if(!x.incoming.count)
1134                printf("This node should be in S!\n");
1135             for(e : x.incoming)
1136             {
1137                External y, from = e.from;
1138                for(y = input->first; y; y = y.next)
1139                   if(y == from)
1140                      break;
1141                if(!y)
1142                {
1143                   for(y = B.first; y; y = y.next)
1144                      if(y == from)
1145                         break;
1146                }
1147
1148                if(!y)
1149                {
1150                   for(y = S.first; y; y = y.next)
1151                      if(y == from)
1152                         break;
1153                }
1154                if(!y && from != n)
1155                {
1156                   printf("This node is nowhere!\n");
1157                }
1158             }
1159          }*/
1160
1161             f = m.ForwardDeclare();
1162             ne = e.in.next;
1163 /*
1164          for(x = input->first; x; x = x.next)
1165          {
1166             int count = 0;
1167             for(e : x.incoming; !e.breakable)
1168                count++;
1169             if(count != x.nonBreakableIncoming)
1170                printf("Bug in input");
1171             if(!x.incoming.count)
1172                printf("This node should be in S!\n");
1173             for(e : x.incoming)
1174             {
1175                External y, from = e.from;
1176                for(y = input->first; y; y = y.next)
1177                   if(y == from)
1178                      break;
1179                if(!y)
1180                {
1181                   for(y = B.first; y; y = y.next)
1182                      if(y == from)
1183                         break;
1184                }
1185
1186                if(!y)
1187                {
1188                   for(y = S.first; y; y = y.next)
1189                      if(y == from)
1190                         break;
1191                }
1192                if(!y && from != n && from != f)
1193                {
1194                   printf("This node is nowhere!\n");
1195                }
1196             }
1197          }
1198 */
1199             // Recheck input for edges created by forward declaration
1200             {
1201                External c, next;
1202                for(c = input->first; c; c = next)
1203                {
1204                   next = c.next;
1205                   if(!c.incoming.count)
1206                   {
1207                      input->Remove(c);
1208                      S.Add(c);
1209                   }
1210                   else if(!c.nonBreakableIncoming)
1211                   {
1212                      input->Remove(c);
1213                      B.Add(c);
1214                   }
1215                }
1216             }
1217
1218             //DebugPrint("Breaking edge from ", e.from.id, " to ", e.to.id);
1219             //DebugPrint("Creating a forward decl node [", f.id, "] for [", m.id, "]");
1220
1221             for(e2 = m.outgoing.first; e2; e2 = n2)
1222             {
1223                n2 = e2.out.next;
1224                if(e2.breakable)
1225                {
1226                   External to = e2.to;
1227
1228                   if(e2 == e)
1229                      ;//DebugPrint("Breaking this particular connection");
1230                   else
1231                      ;//DebugPrint("Also redirecting connection from ", m.id, " to ", to.id, " to come from ", f.id, " instead.");
1232                   e2.breakable = false;
1233                   e2.from = f;
1234                   m.outgoing.Remove((IteratorPointer)e2);
1235                   f.outgoing.Add(e2);
1236                   to.nonBreakableIncoming++;
1237                   if(e2 != e && to.nonBreakableIncoming == 1)
1238                   {
1239                      // If this node was previously in B, move it to input
1240                      B.Remove(to);
1241                      input->Add(to);
1242                   }
1243
1244                   //DebugPrint("Node ", e2.to.id, " now has ", e2.to.nonBreakableIncoming, " non-breakable incoming edges.");
1245                }
1246             }
1247 /*
1248          for(x = input->first; x; x = x.next)
1249          {
1250             int count = 0;
1251             for(e : x.incoming; !e.breakable)
1252                count++;
1253             if(count != x.nonBreakableIncoming)
1254                printf("Bug in input");
1255             if(!x.incoming.count)
1256                printf("This node should be in S!\n");
1257             for(e : x.incoming)
1258             {
1259                External y, from = e.from;
1260                for(y = input->first; y; y = y.next)
1261                   if(y == from)
1262                      break;
1263                if(!y)
1264                {
1265                   for(y = B.first; y; y = y.next)
1266                      if(y == from)
1267                         break;
1268                }
1269
1270                if(!y)
1271                {
1272                   for(y = S.first; y; y = y.next)
1273                      if(y == from)
1274                         break;
1275                }
1276                if(!y && from != n && from != f)
1277                {
1278                   printf("This node is nowhere!\n");
1279                }
1280             }
1281          }*/
1282             if(!f.incoming.count)
1283                S.Add(f);
1284             else if(!f.nonBreakableIncoming)
1285                B.Add(f);
1286             else
1287                input->Add(f);
1288 /*
1289          for(x = input->first; x; x = x.next)
1290          {
1291             int count = 0;
1292             for(e : x.incoming; !e.breakable)
1293                count++;
1294             if(count != x.nonBreakableIncoming)
1295                printf("Bug in input");
1296             if(!x.incoming.count)
1297                printf("This node should be in S!\n");
1298             for(e : x.incoming)
1299             {
1300                External y, from = e.from;
1301                for(y = input->first; y; y = y.next)
1302                   if(y == from)
1303                      break;
1304                if(!y)
1305                {
1306                   for(y = B.first; y; y = y.next)
1307                      if(y == from)
1308                         break;
1309                }
1310
1311                if(!y)
1312                {
1313                   for(y = S.first; y; y = y.next)
1314                      if(y == from)
1315                         break;
1316                }
1317
1318                if(!y)
1319                {
1320                   for(y = L.first; y; y = y.next)
1321                      if(y == from)
1322                      {
1323                         PrintLn("This node is already in L!");
1324                         break;
1325                      }
1326                }
1327
1328                if(!y && from != n)
1329                {
1330                   ConsoleFile file { };
1331                   printf("This node is nowhere!\n");
1332                   OutputExternal(from, file);
1333                   delete file;
1334                }
1335             }
1336          }
1337 */
1338             // Avoid needless edge breaking by processing a node as soon as one shows up in S
1339             if(S.first)
1340                break;
1341          }
1342
1343          // Put n back in input because it now has unbreakable edges
1344          input->Add(n);
1345       }
1346       else
1347       {
1348          if(input->count)
1349          {
1350 #ifdef _DEBUG
1351             ConsoleFile f { };
1352             External e = input->first;
1353 #endif
1354             Compiler_Error("declarations cycles found\n");
1355 #ifdef _DEBUG
1356             //OutputTree(input, f);
1357 /*
1358          for(x = input->first; x; x = x.next)
1359          {
1360             int count = 0;
1361             for(e : x.incoming; !e.breakable)
1362                count++;
1363             if(count != x.nonBreakableIncoming)
1364                printf("Bug in input");
1365             if(!x.incoming.count)
1366                printf("This node should be in S!\n");
1367
1368             for(e : x.incoming)
1369             {
1370                External y, from = e.from;
1371                for(y = input->first; y; y = y.next)
1372                   if(y == from)
1373                      break;
1374                if(!y)
1375                {
1376                   for(y = B.first; y; y = y.next)
1377                      if(y == from)
1378                         break;
1379                }
1380
1381                if(!y)
1382                {
1383                   for(y = S.first; y; y = y.next)
1384                      if(y == from)
1385                         break;
1386                }
1387                if(!y)
1388                {
1389                   printf("This node is nowhere!\n");
1390                }
1391             }
1392          }
1393 */
1394             SetOutputLineNumbers(false);
1395             OutputExternal(e, f);
1396
1397             PrintLn("\nDepends on:\n");
1398             { TopoEdge i; for(i = e.incoming.last; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
1399
1400             OutputExternal(e, f);
1401
1402             PrintLn("\nWhile that depends on:\n");
1403             { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
1404
1405             OutputExternal(e, f);
1406
1407             PrintLn("\nWhile that depends on:\n");
1408             { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
1409
1410             OutputExternal(e, f);
1411
1412             PrintLn("\nWhile that depends on:\n");
1413             { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
1414
1415             OutputExternal(e, f);
1416             delete f;
1417
1418             system("pause");
1419
1420             while((e = input->first))
1421             {
1422                input->Remove(e);
1423                L.Add(e);
1424             }
1425             *input = L;
1426 #endif
1427          }
1428          else
1429             *input = L;
1430          break;
1431       }
1432    }
1433
1434    for(n = input->first; n; n = next)
1435    {
1436       next = n.next;
1437       if(n.type == declarationExternal && (!n.declaration || ((!n.declaration.specifiers || !n.declaration.specifiers->count) && (!n.declaration.declarators || !n.declaration.declarators->count))))
1438       {
1439          input->Remove(n);
1440          if(n.symbol && n.symbol.structExternal == n)
1441             n.symbol.structExternal = null;
1442          FreeExternal(n);
1443       }
1444    }
1445 }
1446
1447 public void ProcessInstanceDeclarations()
1448 {
1449    External external;
1450    curContext = globalContext;
1451    for(external = ast->first; external; external = external.next)
1452    {
1453       curExternal = external;
1454       if(external.type == functionExternal)
1455       {
1456          FunctionDefinition func = external.function;
1457          if(func.specifiers)
1458          {
1459             Specifier spec;
1460             for(spec = func.specifiers->first; spec; spec = spec.next)
1461             {
1462                int type;
1463                if((type = ReplaceClassSpec(func.specifiers, spec, false)))
1464                   ReplaceByInstancePtr(spec, &func.declarator, type);
1465                InstDeclPassSpecifier(spec, false);
1466             }
1467          }
1468          InstDeclPassDeclarator(func.declarator);
1469          if(func.body)
1470             InstDeclPassStatement(func.body);
1471       }
1472       else if(external.type == declarationExternal)
1473       {
1474          if(external.declaration)
1475             InstDeclPassDeclaration(external.declaration);
1476       }
1477    }
1478
1479    // Perform topological sort
1480    TopoSort(ast);
1481 }