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