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