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