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