compiler/libec: Fixed improper usage of GCC compound statement expressions that would...
[sdk] / compiler / libec / src / pass15.ec
1 import "ecdefs"
2
3 #define uint _uint
4 #include <stdlib.h>  // For strtoll
5 #undef uint
6
7 // UNTIL IMPLEMENTED IN GRAMMAR
8 #define ACCESS_CLASSDATA(_class, baseClass) \
9    (_class ? ((void *)(((char *)_class.data) + baseClass.offsetClass)) : null)
10
11 #define YYLTYPE Location
12 #include "grammar.h"
13
14 extern OldList * ast;
15 extern int returnCode;
16 extern Expression parsedExpression;
17 extern bool yydebug;
18 public void SetYydebug(bool b) { yydebug = b; }
19 extern bool echoOn;
20
21 void resetScanner();
22
23 // TODO: Reset this to 0 on reinitialization
24 int propWatcherID;
25
26 int expression_yyparse();
27 static Statement curCompound;
28 External curExternal, afterExternal;
29 static Type curSwitchType;
30 static Class currentClass;
31 Class thisClass;
32 public void SetThisClass(Class c) { thisClass = c; } public Class GetThisClass() { return thisClass; }
33 static char * thisNameSpace;
34 /*static */Class containerClass;
35 bool thisClassParams = true;
36
37 #ifdef _DEBUG
38 Time findSymbolTotalTime;
39 #endif
40
41 // WARNING: PrintExpression CONCATENATES to string. Please initialize.
42 /*static */public void PrintExpression(Expression exp, char * string)
43 {
44    //if(inCompiler)
45    {
46       TempFile f { };
47       int count;
48
49       if(exp)
50          OutputExpression(exp, f);
51       f.Seek(0, start);
52       count = strlen(string);
53       count += f.Read(string + count, 1, 1023);
54       string[count] = '\0';
55       delete f;
56    }
57 }
58
59 int64 _strtoi64(char * string, char ** endString, int base)
60 {
61    int64 value = 0;
62    int sign = 1;
63    int c;
64    char ch;
65    for(c = 0; (ch = string[c]) && isspace(ch); c++);
66    if(ch =='+') c++;
67    else if(ch == '-') { sign = -1; c++; };
68    if(!base)
69    {
70       if(ch == 0 && string[c+1] == 'x')
71       {
72          base = 16;
73          c+=2;
74       }
75       else if(ch == '0')
76       {
77          base = 8;
78          c++;
79       }
80       else
81          base = 10;
82    }
83    for( ;(ch = string[c]); c++)
84    {
85       if(ch == '0')
86          ch = 0;
87       else if(ch >= '1' && ch <= '9')
88          ch -= '1';
89       else if(ch >= 'a' && ch <= 'z') 
90          ch -= 'a'; 
91       else if(ch >= 'A' && ch <= 'Z') 
92          ch -= 'A';
93       else
94       {
95          if(endString)
96             *endString = string + c;
97          // Invalid character
98          break;
99       }
100       if(ch < base)
101       {
102          value *= base;
103          value += ch;
104       }
105       else
106       {
107          if(endString)
108             *endString = string + c;
109          // Invalid character
110          break;
111       }
112    }
113    return sign*value;
114 }
115
116 uint64 _strtoui64(char * string, char ** endString, int base)
117 {
118    uint64 value = 0;
119    int sign = 1;
120    int c;
121    char ch;
122    for(c = 0; (ch = string[c]) && isspace(ch); c++);
123    if(ch =='+') c++;
124    else if(ch == '-') { sign = -1; c++; };
125    if(!base)
126    {
127       if(ch == 0 && string[c+1] == 'x')
128       {
129          base = 16;
130          c+=2;
131       }
132       else if(ch == '0')
133       {
134          base = 8;
135          c++;
136       }
137       else
138          base = 10;
139    }
140    for( ;(ch = string[c]); c++)
141    {
142       if(ch == '0')
143          ch = 0;
144       else if(ch >= '1' && ch <= '9')
145          ch -= '1';
146       else if(ch >= 'a' && ch <= 'z') 
147          ch -= 'a'; 
148       else if(ch >= 'A' && ch <= 'Z') 
149          ch -= 'A';
150       else
151       {
152          if(endString) *endString = string + c;
153          // Invalid character
154          break;
155       }
156       if(ch < base)
157       {
158          value *= base;
159          value += ch;
160       }
161       else
162       {
163          if(endString)
164             *endString = string + c;
165          // Invalid character
166          break;
167       }
168    }
169    return sign*value;
170 }
171
172 Type ProcessTemplateParameterType(TemplateParameter param)
173 {
174    if(param && param.type == TemplateParameterType::type && (param.dataType || param.dataTypeString))
175    {
176       // TOFIX: Will need to free this Type
177       if(!param.baseType)
178       {
179          if(param.dataTypeString)
180             param.baseType = ProcessTypeString(param.dataTypeString, false);
181          else
182             param.baseType = ProcessType(param.dataType.specifiers, param.dataType.decl);
183       }
184       return param.baseType;
185    }
186    return null;
187 }
188
189 bool NeedCast(Type type1, Type type2)
190 {
191    if(!type1 || !type2 || type1.keepCast || type2.keepCast) return true;
192
193    if(type1.kind == templateType && type2.kind == int64Type && type2.passAsTemplate == false)
194    {
195       return false;
196    }
197
198    if(type1.kind == type2.kind)
199    {
200       switch(type1.kind)
201       {
202          case charType:
203          case shortType:
204          case intType:
205          case int64Type:
206             if(type1.passAsTemplate && !type2.passAsTemplate)
207                return true;
208             return type1.isSigned != type2.isSigned;
209          case classType:
210             return type1._class != type2._class;
211          case pointerType:
212             return NeedCast(type1.type, type2.type);
213          default:
214             return true; //false; ????
215       }
216    }
217    return true;
218 }
219
220 static void ReplaceClassMembers(Expression exp, Class _class)
221 {
222    if(exp.type == identifierExp && exp.identifier)
223    {
224       Identifier id = exp.identifier;
225       Context ctx;
226       Symbol symbol = null;
227       if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
228       {
229          // First, check if the identifier is declared inside the function
230          for(ctx = curContext; ctx != topContext.parent && !symbol; ctx = ctx.parent)
231          {
232             symbol = (Symbol)ctx.symbols.FindString(id.string);
233             if(symbol) break;
234          }
235       }
236
237       // If it is not, check if it is a member of the _class
238       if(!symbol && ((!id._class || (id._class.name && !strcmp(id._class.name, "property"))) || (id.classSym && eClass_IsDerived(_class, id.classSym.registered))))
239       {
240          Property prop = eClass_FindProperty(_class, id.string, privateModule);
241          Method method = null;
242          DataMember member = null;
243          ClassProperty classProp;
244          if(!prop)
245          {
246             method = eClass_FindMethod(_class, id.string, privateModule);
247          }
248          if(!prop && !method)
249             member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
250          if(!prop && !method && !member)
251          {
252             classProp = eClass_FindClassProperty(_class, id.string);
253          }
254          if(prop || method || member || classProp)
255          {
256             // Replace by this.[member]
257             exp.type = memberExp;
258             exp.member.member = id;
259             exp.member.memberType = unresolvedMember;
260             exp.member.exp = QMkExpId("this");
261             //exp.member.exp.loc = exp.loc;
262             exp.addedThis = true;
263          }
264          else if(_class && _class.templateParams.first)
265          {
266             Class sClass;
267             for(sClass = _class; sClass; sClass = sClass.base)
268             {
269                if(sClass.templateParams.first)
270                {
271                   ClassTemplateParameter param;
272                   for(param = sClass.templateParams.first; param; param = param.next)
273                   {
274                      if(param.type == expression && !strcmp(param.name, id.string))
275                      {
276                         Expression argExp = GetTemplateArgExpByName(param.name, _class, TemplateParameterType::expression);
277
278                         if(argExp)
279                         {
280                            Declarator decl;
281                            OldList * specs = MkList();
282
283                            FreeIdentifier(exp.member.member);
284
285                            ProcessExpressionType(argExp);
286
287                            decl = SpecDeclFromString(param.dataTypeString, specs, null);
288
289                            exp.expType = ProcessType(specs, decl);
290
291                            // *[expType] *[argExp]
292                            exp.type = bracketsExp;
293                            exp.list = MkListOne(MkExpOp(null, '*',
294                               MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpOp(null, '&', argExp))));
295                         }
296                      }
297                   }
298                }
299             }
300          }
301       }
302    }
303 }
304
305 ////////////////////////////////////////////////////////////////////////
306 // PRINTING ////////////////////////////////////////////////////////////
307 ////////////////////////////////////////////////////////////////////////
308
309 public char * PrintInt(int64 result)
310 {
311    char temp[100];
312    if(result > MAXINT64)
313       sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
314    else
315       sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
316    return CopyString(temp);
317 }
318
319 public char * PrintUInt(uint64 result)
320 {
321    char temp[100];
322    if(result > MAXDWORD)
323       sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
324    else if(result > MAXINT)
325       sprintf(temp, FORMAT64HEX /*"0x%I64X"*/, result);
326    else
327       sprintf(temp, FORMAT64D /*"%I64d"*/, result);
328    return CopyString(temp);
329 }
330
331 public char * PrintInt64(int64 result)
332 {
333    char temp[100];
334    sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
335    return CopyString(temp);
336 }
337
338 public char * PrintUInt64(uint64 result)
339 {
340    char temp[100];
341    if(result > MAXINT64)
342       sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
343    else
344       sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
345    return CopyString(temp);
346 }
347
348 public char * PrintHexUInt(uint64 result)
349 {
350    char temp[100];
351    if(result > MAXDWORD)
352       sprintf(temp, FORMAT64HEXLL /*"0x%I64xLL"*/, result);
353    else
354       sprintf(temp, FORMAT64HEX /*"0x%I64x"*/, result);
355    return CopyString(temp);
356 }
357
358 public char * PrintHexUInt64(uint64 result)
359 {
360    char temp[100];
361    if(result > MAXDWORD)
362       sprintf(temp, FORMAT64HEXLL /*"0x%I64xLL"*/, result);
363    else
364       sprintf(temp, FORMAT64HEX /*"0x%I64x"*/, result);
365    return CopyString(temp);
366 }
367
368 public char * PrintShort(short result)
369 {
370    char temp[100];
371    sprintf(temp, "%d", (unsigned short)result);
372    return CopyString(temp);
373 }
374
375 public char * PrintUShort(unsigned short result)
376 {
377    char temp[100];
378    if(result > 32767)
379       sprintf(temp, "0x%X", (int)result);
380    else
381       sprintf(temp, "%d", result);
382    return CopyString(temp);
383 }
384
385 public char * PrintChar(char result)
386 {
387    char temp[100];
388    if(result > 0 && isprint(result))
389       sprintf(temp, "'%c'", result);
390    else if(result < 0)
391       sprintf(temp, "%d", result);
392    else
393       //sprintf(temp, "%#X", result);
394       sprintf(temp, "0x%X", (unsigned char)result);
395    return CopyString(temp);
396 }
397
398 public char * PrintUChar(unsigned char result)
399 {
400    char temp[100];
401    sprintf(temp, "0x%X", result);
402    return CopyString(temp);
403 }
404
405 public char * PrintFloat(float result)
406 {
407    char temp[350];
408    sprintf(temp, "%.16ff", result);
409    return CopyString(temp);
410 }
411
412 public char * PrintDouble(double result)
413 {
414    char temp[350];
415    sprintf(temp, "%.16f", result);
416    return CopyString(temp);
417 }
418
419 ////////////////////////////////////////////////////////////////////////
420 ////////////////////////////////////////////////////////////////////////
421
422 //public Operand GetOperand(Expression exp);
423
424 #define GETVALUE(name, t) \
425    public bool Get##name(Expression exp, t * value2) \
426    {                                                        \
427       Operand op2 = GetOperand(exp);                        \
428       if(op2.kind == intType && op2.type.isSigned) *value2 = (t) op2.i; \
429       else if(op2.kind == intType) *value2 = (t) op2.ui;                 \
430       if(op2.kind == int64Type && op2.type.isSigned) *value2 = (t) op2.i64; \
431       else if(op2.kind == int64Type) *value2 = (t) op2.ui64;                 \
432       else if(op2.kind == shortType && op2.type.isSigned) *value2 = (t) op2.s;   \
433       else if(op2.kind == shortType) *value2 = (t) op2.us;                        \
434       else if(op2.kind == charType && op2.type.isSigned) *value2 = (t) op2.c;    \
435       else if(op2.kind == charType) *value2 = (t) op2.uc;                         \
436       else if(op2.kind == floatType) *value2 = (t) op2.f;                         \
437       else if(op2.kind == doubleType) *value2 = (t) op2.d;                        \
438       else if(op2.kind == pointerType) *value2 = (t) op2.ui;                        \
439       else                                                                          \
440          return false;                                                              \
441       return true;                                                                  \
442    }
443
444 GETVALUE(Int, int);
445 GETVALUE(UInt, unsigned int);
446 GETVALUE(Int64, int64);
447 GETVALUE(UInt64, uint64);
448 GETVALUE(Short, short);
449 GETVALUE(UShort, unsigned short);
450 GETVALUE(Char, char);
451 GETVALUE(UChar, unsigned char);
452 GETVALUE(Float, float);
453 GETVALUE(Double, double);
454
455 void ComputeExpression(Expression exp);
456
457 void ComputeClassMembers(Class _class, bool isMember)
458 {
459    DataMember member = isMember ? (DataMember) _class : null;
460    Context context = isMember ? null : SetupTemplatesContext(_class);
461    if(member || ((_class.type == bitClass || _class.type == normalClass || _class.type == structClass || _class.type == noHeadClass) && 
462                  (_class.type == bitClass || _class.structSize == _class.offset) && _class.computeSize))
463    {
464       int c;
465       int unionMemberOffset = 0;
466       int bitFields = 0;
467
468       if(!member && _class.destructionWatchOffset)
469          _class.memberOffset += sizeof(OldList);
470
471       // To avoid reentrancy...
472       //_class.structSize = -1;
473
474       {
475          DataMember dataMember;
476          for(dataMember = member ? member.members.first : _class.membersAndProperties.first; dataMember; dataMember = dataMember.next)
477          {
478             if(!dataMember.isProperty)
479             {
480                if(dataMember.type == normalMember && dataMember.dataTypeString && !dataMember.dataType)
481                {
482                   /*if(dataMember.dataType)
483                      printf("");*/
484                   dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
485                   /*if(!dataMember.dataType)
486                      dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
487                      */
488                }
489             }
490          }
491       }
492
493       {
494          DataMember dataMember;
495          for(dataMember = member ? member.members.first : _class.membersAndProperties.first; dataMember; dataMember = dataMember.next)
496          {
497             if(!dataMember.isProperty && (dataMember.type != normalMember || dataMember.dataTypeString))
498             {
499                if(!isMember && _class.type == bitClass && dataMember.dataType)
500                {
501                   BitMember bitMember = (BitMember) dataMember;
502                   uint64 mask = 0;
503                   int d;
504
505                   ComputeTypeSize(dataMember.dataType);
506
507                   if(bitMember.pos == -1) bitMember.pos = _class.memberOffset;
508                   if(!bitMember.size) bitMember.size = dataMember.dataType.size * 8;
509
510                   _class.memberOffset = bitMember.pos + bitMember.size;
511                   for(d = 0; d<bitMember.size; d++)
512                   {
513                      if(d)
514                         mask <<= 1;
515                      mask |= 1;
516                   }
517                   bitMember.mask = mask << bitMember.pos;
518                }
519                else if(dataMember.type == normalMember && dataMember.dataType)
520                {
521                   int size;
522                   int alignment = 0;
523
524                   // Prevent infinite recursion
525                   if(dataMember.dataType.kind != classType || 
526                      ((!dataMember.dataType._class || !dataMember.dataType._class.registered || dataMember.dataType._class.registered != _class ||
527                      _class.type != structClass)))
528                      ComputeTypeSize(dataMember.dataType);
529
530                   if(dataMember.dataType.bitFieldCount)
531                   {
532                      bitFields += dataMember.dataType.bitFieldCount;
533                      size = 0;
534                   }
535                   else
536                   {
537                      if(bitFields)
538                      {
539                         int size = (bitFields + 7) / 8;
540
541                         if(isMember)
542                         {
543                            // TESTING THIS PADDING CODE
544                            if(alignment)
545                            {
546                               member.structAlignment = Max(member.structAlignment, alignment);
547
548                               if(member.memberOffset % alignment)
549                                  member.memberOffset += alignment - (member.memberOffset % alignment);
550                            }
551
552                            dataMember.offset = member.memberOffset;
553                            if(member.type == unionMember)
554                               unionMemberOffset = Max(unionMemberOffset, dataMember.dataType.size);
555                            else
556                            {
557                               member.memberOffset += size;
558                            }
559                         }
560                         else
561                         {
562                            // TESTING THIS PADDING CODE
563                            if(alignment)
564                            {
565                               _class.structAlignment = Max(_class.structAlignment, alignment);
566
567                               if(_class.memberOffset % alignment)
568                                  _class.memberOffset += alignment - (_class.memberOffset % alignment);
569                            }
570
571                            dataMember.offset = _class.memberOffset;
572                            _class.memberOffset += size;
573                         }
574                         bitFields = 0;
575                      }
576                      size = dataMember.dataType.size;
577                      alignment = dataMember.dataType.alignment;
578                   }
579
580 #ifdef _DEBUG
581                   if(!size)
582                   {
583                      // printf("");
584                   }
585 #endif
586                   if(isMember)
587                   {
588                      // TESTING THIS PADDING CODE
589                      if(alignment)
590                      {
591                         member.structAlignment = Max(member.structAlignment, alignment);
592
593                         if(member.memberOffset % alignment)
594                            member.memberOffset += alignment - (member.memberOffset % alignment);
595                      }
596
597                      dataMember.offset = member.memberOffset;
598                      if(member.type == unionMember)
599                         unionMemberOffset = Max(unionMemberOffset, dataMember.dataType.size);
600                      else
601                      {
602                         member.memberOffset += size;
603                      }
604                   }
605                   else
606                   {
607                      // TESTING THIS PADDING CODE
608                      if(alignment)
609                      {
610                         _class.structAlignment = Max(_class.structAlignment, alignment);
611
612                         if(_class.memberOffset % alignment)
613                            _class.memberOffset += alignment - (_class.memberOffset % alignment);
614                      }
615
616                      dataMember.offset = _class.memberOffset;
617                      _class.memberOffset += size;
618                   }
619                }
620                else
621                {
622                   ComputeClassMembers((Class)dataMember, true);
623
624                   if(isMember)
625                   {
626                      // THERE WASN'T A MAX HERE ? member.structAlignment = dataMember.structAlignment;
627                      member.structAlignment = Max(member.structAlignment, dataMember.structAlignment);
628                      dataMember.offset = member.memberOffset;
629                      if(member.type == unionMember)
630                         unionMemberOffset = Max(unionMemberOffset, dataMember.memberOffset);
631                      else
632                         member.memberOffset += dataMember.memberOffset;
633                   }
634                   else
635                   {
636                      _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
637                      dataMember.offset = _class.memberOffset;
638                      _class.memberOffset += dataMember.memberOffset;
639                   }
640                }
641             }
642          }
643          if(bitFields)
644          {
645             int alignment = 0;
646             int size = (bitFields + 7) / 8;
647
648             if(isMember)
649             {
650                // TESTING THIS PADDING CODE
651                if(alignment)
652                {
653                   member.structAlignment = Max(member.structAlignment, alignment);
654
655                   if(member.memberOffset % alignment)
656                      member.memberOffset += alignment - (member.memberOffset % alignment);
657                }
658
659                if(member.type == unionMember)
660                   unionMemberOffset = Max(unionMemberOffset, dataMember.dataType.size);
661                else
662                {
663                   member.memberOffset += size;
664                }
665             }
666             else
667             {
668                // TESTING THIS PADDING CODE
669                if(alignment)
670                {
671                   _class.structAlignment = Max(_class.structAlignment, alignment);
672
673                   if(_class.memberOffset % alignment)
674                      _class.memberOffset += alignment - (_class.memberOffset % alignment);
675                }
676                _class.memberOffset += size;
677             }
678             bitFields = 0;
679          }
680       }
681       if(member && member.type == unionMember)
682       {
683          member.memberOffset = unionMemberOffset;
684       }
685       
686       if(!isMember)
687       {
688          /*if(_class.type == structClass)
689             _class.size = _class.memberOffset;
690          else
691          */
692
693          if(_class.type != bitClass)
694          {
695             _class.structSize = (_class.base ? (_class.base.templateClass ? _class.base.templateClass.structSize : _class.base.structSize) : 0) + _class.memberOffset;
696             if(!member)
697             {
698                Property prop;
699                for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
700                {
701                   if(prop.isProperty && prop.isWatchable)
702                   {
703                      prop.watcherOffset = _class.structSize;
704                      _class.structSize += sizeof(OldList);
705                   }
706                }
707             }
708
709             // Fix Derivatives
710             {
711                OldLink derivative;
712                for(derivative = _class.derivatives.first; derivative; derivative = derivative.next)
713                {
714                   Class deriv = derivative.data;
715
716                   if(deriv.computeSize)
717                   {
718                      // TESTING THIS NEW CODE HERE... TRYING TO FIX ScrollBar MEMBERS DEBUGGING
719                      deriv.offset = /*_class.offset + */_class.structSize;
720                      deriv.memberOffset = 0;
721                      // ----------------------
722
723                      deriv.structSize = deriv.offset;
724
725                      ComputeClassMembers(deriv, false);
726                   }
727                }
728             }
729          }
730       }
731    }
732    if(context)
733       FinishTemplatesContext(context);
734 }
735
736 public void ComputeModuleClasses(Module module)
737 {
738    Class _class;
739    OldLink subModule;
740    
741    for(subModule = module.modules.first; subModule; subModule = subModule.next)
742       ComputeModuleClasses(subModule.data);
743    for(_class = module.classes.first; _class; _class = _class.next)
744       ComputeClassMembers(_class, false);
745 }
746
747
748 public int ComputeTypeSize(Type type)
749 {
750    uint size = type ? type.size : 0;
751    if(!size && type && !type.computing)
752    {
753       type.computing = true;
754       switch(type.kind)
755       {
756          case charType: type.alignment = size = sizeof(char); break;
757          case intType: type.alignment = size = sizeof(int); break;
758          case int64Type: type.alignment = size = sizeof(int64); break;
759          case longType: type.alignment = size = sizeof(long); break;
760          case shortType: type.alignment = size = sizeof(short); break;
761          case floatType: type.alignment = size = sizeof(float); break;
762          case doubleType: type.alignment = size = sizeof(double); break;
763          case classType:
764          {
765             Class _class = type._class ? type._class.registered : null;
766
767             if(_class && _class.type == structClass)
768             {
769                // Ensure all members are properly registered
770                ComputeClassMembers(_class, false);
771                type.alignment = _class.structAlignment;
772                size = _class.structSize;
773                if(type.alignment && size % type.alignment)
774                   size += type.alignment - (size % type.alignment);
775
776             }
777             else if(_class && (_class.type == unitClass || 
778                    _class.type == enumClass || 
779                    _class.type == bitClass))
780             {
781                if(!_class.dataType)
782                   _class.dataType = ProcessTypeString(_class.dataTypeString, false);
783                size = type.alignment = ComputeTypeSize(_class.dataType);
784             }
785             else
786                size = type.alignment = sizeof(Instance *);
787             break;
788          }
789          case pointerType: case subClassType: size = type.alignment = sizeof(void *); break;
790          case arrayType: 
791             if(type.arraySizeExp)
792             {
793                ProcessExpressionType(type.arraySizeExp);
794                ComputeExpression(type.arraySizeExp);
795                if(!type.arraySizeExp.isConstant || (type.arraySizeExp.expType.kind != intType && type.arraySizeExp.expType.kind != enumType && 
796                   (type.arraySizeExp.expType.kind != classType || !type.arraySizeExp.expType._class.registered || type.arraySizeExp.expType._class.registered.type != enumClass)))
797                {
798                   Location oldLoc = yylloc;
799                   // bool isConstant = type.arraySizeExp.isConstant;
800                   char expression[10240];
801                   expression[0] = '\0';
802                   type.arraySizeExp.expType = null;
803                   yylloc = type.arraySizeExp.loc;
804                   if(inCompiler)
805                      PrintExpression(type.arraySizeExp, expression);
806                   Compiler_Error($"Array size not constant int (%s)\n", expression);
807                   yylloc = oldLoc;
808                }
809                GetInt(type.arraySizeExp, &type.arraySize);
810 #ifdef _DEBUG
811                if(!type.arraySize)
812                {
813                   printf("");
814                }
815 #endif
816             }
817             else if(type.enumClass)
818             {
819                if(type.enumClass && type.enumClass.registered && type.enumClass.registered.type == enumClass)
820                {
821                   type.arraySize = eClass_GetProperty(type.enumClass.registered, "enumSize");
822                }
823                else
824                   type.arraySize = 0;
825             }
826             else
827             {
828                // Unimplemented auto size
829                type.arraySize = 0;
830             }
831
832             size = ComputeTypeSize(type.type) * type.arraySize;
833             type.alignment = type.type.alignment;
834             
835             break;
836          case structType:
837          {
838             Type member;
839             for(member = type.members.first; member; member = member.next)
840             {
841                uint addSize = ComputeTypeSize(member);
842
843                member.offset = size;
844                if(member.alignment && size % member.alignment)
845                   member.offset += member.alignment - (size % member.alignment);
846                size = member.offset;
847
848                type.alignment = Max(type.alignment, member.alignment);
849                size += addSize;
850             }
851             if(type.alignment && size % type.alignment)
852                size += type.alignment - (size % type.alignment);
853             break;
854          }
855          case unionType:
856          {
857             Type member;
858             for(member = type.members.first; member; member = member.next)
859             {
860                uint addSize = ComputeTypeSize(member);
861                
862                member.offset = size;
863                if(member.alignment && size % member.alignment)
864                   member.offset += member.alignment - (size % member.alignment);
865                size = member.offset;
866
867                type.alignment = Max(type.alignment, member.alignment);
868                size = Max(size, addSize);
869             }
870             if(type.alignment && size % type.alignment)
871                size += type.alignment - (size % type.alignment);
872             break;
873          }
874          case templateType:
875          {
876             TemplateParameter param = type.templateParameter;
877             Type baseType = ProcessTemplateParameterType(param);
878             if(baseType)
879                size = ComputeTypeSize(baseType);
880             else
881                size = sizeof(uint64);
882             break;
883          }
884          case enumType:
885          {
886             size = sizeof(enum { test });
887             break;
888          }
889          case thisClassType:
890          {
891             size = sizeof(void *);
892             break;
893          }
894       }
895       type.size = size;
896       type.computing = false;
897    }
898    return size;
899 }
900
901
902 /*static */int AddMembers(OldList * declarations, Class _class, bool isMember, uint * retSize, Class topClass)
903 {
904    // This function is in need of a major review when implementing private members etc.
905    DataMember topMember = isMember ? (DataMember) _class : null;
906    uint totalSize = 0;
907    uint maxSize = 0;
908    int alignment, size;
909    DataMember member;
910    Context context = isMember ? null : SetupTemplatesContext(_class);
911
912    if(!isMember && _class.base)
913    {
914       maxSize = _class.structSize;
915       //if(_class.base.type != systemClass) // Commented out with new Instance _class
916       {
917          // DANGER: Testing this noHeadClass here...
918          if(_class.type == structClass || _class.type == noHeadClass)
919             /*totalSize = */AddMembers(declarations, _class.base, false, &totalSize, topClass);
920          else
921             maxSize -= _class.base.templateClass ? _class.base.templateClass.structSize : _class.base.structSize;
922       }
923    }
924
925    for(member = isMember ? topMember.members.first : _class.membersAndProperties.first; member; member = member.next)
926    {
927       if(!member.isProperty)
928       {
929          switch(member.type)
930          {
931             case normalMember:
932             {
933                if(member.dataTypeString)
934                {
935                   OldList * specs = MkList(), * decls = MkList();
936                   Declarator decl;
937
938                   decl = SpecDeclFromString(member.dataTypeString, specs, 
939                      MkDeclaratorIdentifier(MkIdentifier(member.name)));
940                   ListAdd(decls, MkStructDeclarator(decl, null));
941                   ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, decls, null)));
942
943                   if(!member.dataType)
944                      member.dataType = ProcessType(specs, decl);
945
946                   ReplaceThisClassSpecifiers(specs, topClass /*member._class*/);
947
948                   {
949                      Type type = ProcessType(specs, decl);
950                      DeclareType(member.dataType, false, false);
951                      FreeType(type);
952                   }
953                   /*
954                   if(member.dataType && member.dataType.kind == classType && member.dataType._class &&
955                      member.dataType._class.registered && member.dataType._class.registered.type == structClass)
956                      DeclareStruct(member.dataType._class.string, false);
957                   */
958
959                   ComputeTypeSize(member.dataType);
960                   size = member.dataType.size;
961                   alignment = member.dataType.alignment;
962
963                   if(alignment)
964                   {
965                      if(totalSize % alignment)
966                         totalSize += alignment - (totalSize % alignment);
967                   }
968                   totalSize += size;
969                }
970                break;
971             }
972             case unionMember:
973             case structMember:
974             {
975                OldList * specs = MkList(), * list = MkList();
976                
977                size = 0;
978                AddMembers(list, (Class)member, true, &size, topClass);
979                ListAdd(specs, 
980                   MkStructOrUnion((member.type == unionMember)?unionSpecifier:structSpecifier, null, list));
981                ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, null, null)));
982                alignment = member.structAlignment;
983
984                if(alignment)
985                {
986                   if(totalSize % alignment)
987                      totalSize += alignment - (totalSize % alignment);
988                }
989                totalSize += size;
990                break;
991             }
992          }
993       }
994    }
995    if(retSize)
996    {
997       if(topMember && topMember.type == unionMember)
998          *retSize = Max(*retSize, totalSize);
999       else
1000          *retSize += totalSize;
1001    }
1002    else if(totalSize < maxSize && _class.type != systemClass)
1003    {
1004       char sizeString[50];
1005       sprintf(sizeString, "%d", maxSize - totalSize);
1006       ListAdd(declarations, 
1007          MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(CHAR)), 
1008          MkListOne(MkDeclaratorArray(MkDeclaratorIdentifier(MkIdentifier("__ecere_padding")), MkExpConstant(sizeString))), null)));
1009    }
1010    if(context)
1011       FinishTemplatesContext(context);
1012    return topMember ? topMember.memberID : _class.memberID;
1013 }
1014
1015 static int DeclareMembers(Class _class, bool isMember)
1016 {
1017    DataMember topMember = isMember ? (DataMember) _class : null;
1018    uint totalSize = 0;
1019    DataMember member;
1020    Context context = isMember ? null : SetupTemplatesContext(_class);
1021    
1022    if(!isMember && (_class.type == structClass || _class.type == noHeadClass) && _class.base.type != systemClass)
1023       DeclareMembers(_class.base, false);
1024
1025    for(member = isMember ? topMember.members.first : _class.membersAndProperties.first; member; member = member.next)
1026    {
1027       if(!member.isProperty)
1028       {
1029          switch(member.type)
1030          {
1031             case normalMember:
1032             {
1033                /*
1034                if(member.dataType && member.dataType.kind == classType && member.dataType._class &&
1035                   member.dataType._class.registered && member.dataType._class.registered.type == structClass)
1036                   DeclareStruct(member.dataType._class.string, false);
1037                   */
1038                if(!member.dataType && member.dataTypeString)
1039                   member.dataType = ProcessTypeString(member.dataTypeString, false);
1040                if(member.dataType)
1041                   DeclareType(member.dataType, false, false);
1042                break;
1043             }
1044             case unionMember:
1045             case structMember:
1046             {
1047                DeclareMembers((Class)member, true);
1048                break;
1049             }
1050          }
1051       }
1052    }
1053    if(context)
1054       FinishTemplatesContext(context);
1055
1056    return topMember ? topMember.memberID : _class.memberID;
1057 }
1058
1059 void DeclareStruct(char * name, bool skipNoHead)
1060 {
1061    External external = null;
1062    Symbol classSym = FindClass(name);
1063
1064    if(!inCompiler || !classSym) return null;
1065
1066    // We don't need any declaration for bit classes...
1067    if(classSym.registered && 
1068       (classSym.registered.type == bitClass || classSym.registered.type == unitClass || classSym.registered.type == enumClass))
1069       return null;
1070
1071    /*if(classSym.registered.templateClass)
1072       return DeclareStruct(classSym.registered.templateClass.fullName, skipNoHead);
1073    */
1074
1075    if(classSym.registered && classSym.imported && !classSym.declaredStructSym)
1076    {
1077       // Add typedef struct
1078       Declaration decl;
1079       OldList * specifiers, * declarators;
1080       OldList * declarations = null;
1081       char structName[1024];
1082       external = (classSym.registered && classSym.registered.type == structClass) ? 
1083          classSym.pointerExternal : classSym.structExternal;
1084
1085       // TEMPORARY HACK: Pass 3 will move up struct declarations without moving members
1086       // Moved this one up because DeclareClass done later will need it
1087
1088       classSym.declaring++;
1089
1090       if(strchr(classSym.string, '<'))
1091       {
1092          if(classSym.registered.templateClass)
1093          {
1094             DeclareStruct(classSym.registered.templateClass.fullName, skipNoHead);
1095             classSym.declaring--;
1096          }
1097          return null;
1098       }
1099       
1100       //if(!skipNoHead)
1101          DeclareMembers(classSym.registered, false);
1102
1103       structName[0] = 0;
1104       FullClassNameCat(structName, name, false);
1105
1106       /*if(!external)      
1107          external = MkExternalDeclaration(null);*/
1108
1109       if(!skipNoHead)
1110       {
1111          classSym.declaredStructSym = true;
1112
1113          declarations = MkList();
1114
1115          AddMembers(declarations, classSym.registered, false, null, classSym.registered);
1116
1117          //ListAdd(specifiers, MkSpecifier(TYPEDEF));
1118          //ListAdd(specifiers, MkStructOrUnion(structSpecifier, null, declarations));
1119
1120          if(!declarations->count)
1121          {
1122             FreeList(declarations, null);
1123             declarations = null;
1124          }
1125       }
1126       if(skipNoHead || declarations)
1127       {
1128          if(external && external.declaration)
1129          {
1130             ((Specifier)external.declaration.specifiers->first).definitions = declarations;
1131
1132             if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
1133             {
1134                // TODO: Fix this
1135                //ast->Move(classSym.structExternal ? classSym.structExternal : classSym.pointerExternal, curExternal.prev);
1136
1137                // DANGER
1138                if(classSym.structExternal)
1139                   ast->Move(classSym.structExternal, curExternal.prev);
1140                ast->Move(classSym.pointerExternal, curExternal.prev);
1141
1142                classSym.id = curExternal.symbol.idCode;
1143                classSym.idCode = curExternal.symbol.idCode;
1144                // external = classSym.pointerExternal;
1145                //external = classSym.structExternal ? classSym.structExternal : classSym.pointerExternal;
1146             }
1147          }
1148          else
1149          {
1150             if(!external)      
1151                external = MkExternalDeclaration(null);
1152
1153             specifiers = MkList();
1154             declarators = MkList();
1155             ListAdd(specifiers, MkStructOrUnion(structSpecifier, MkIdentifier(structName), declarations));
1156
1157             /*
1158             d = MkDeclaratorIdentifier(MkIdentifier(structName));
1159             ListAdd(declarators, MkInitDeclarator(d, null));
1160             */
1161             external.declaration = decl = MkDeclaration(specifiers, declarators);
1162             if(decl.symbol && !decl.symbol.pointerExternal)
1163                decl.symbol.pointerExternal = external;
1164
1165             // For simple classes, keep the declaration as the external to move around
1166             if(classSym.registered && classSym.registered.type == structClass)
1167             {
1168                char className[1024];
1169                strcpy(className, "__ecereClass_");
1170                FullClassNameCat(className, classSym.string, true);
1171                MangleClassName(className);
1172
1173                // Testing This
1174                DeclareClass(classSym, className);
1175
1176                external.symbol = classSym;
1177                classSym.pointerExternal = external;
1178                classSym.id = (curExternal && curExternal.symbol) ? curExternal.symbol.idCode : 0;
1179                classSym.idCode = (curExternal && curExternal.symbol) ? curExternal.symbol.idCode : 0;
1180             }
1181             else
1182             {
1183                char className[1024];
1184                strcpy(className, "__ecereClass_");
1185                FullClassNameCat(className, classSym.string, true);
1186                MangleClassName(className);
1187
1188                // TOFIX: TESTING THIS...
1189                classSym.structExternal = external;
1190                DeclareClass(classSym, className);
1191                external.symbol = classSym;
1192             }
1193
1194             //if(curExternal)
1195                ast->Insert(curExternal ? curExternal.prev : null, external);
1196          }
1197       }
1198
1199       classSym.declaring--;
1200    }
1201    else if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
1202    {
1203       // TEMPORARY HACK: Pass 3 will move up struct declarations without moving members
1204       // Moved this one up because DeclareClass done later will need it
1205
1206       // TESTING THIS:
1207       classSym.declaring++;
1208
1209       //if(!skipNoHead)
1210       {
1211          if(classSym.registered)
1212             DeclareMembers(classSym.registered, false);
1213       }
1214
1215       if(classSym.registered && (classSym.registered.type == structClass || classSym.registered.type == noHeadClass))
1216       {
1217          // TODO: Fix this
1218          //ast->Move(classSym.structExternal ? classSym.structExternal : classSym.pointerExternal, curExternal.prev);
1219
1220          // DANGER
1221          if(classSym.structExternal)
1222             ast->Move(classSym.structExternal, curExternal.prev);
1223          ast->Move(classSym.pointerExternal, curExternal.prev);
1224
1225          classSym.id = curExternal.symbol.idCode;
1226          classSym.idCode = curExternal.symbol.idCode;
1227          // external = classSym.pointerExternal;
1228          // external = classSym.structExternal ? classSym.structExternal : classSym.pointerExternal;
1229       }
1230
1231       classSym.declaring--;
1232    }
1233    //return external;
1234 }
1235
1236 void DeclareProperty(Property prop, char * setName, char * getName)
1237 {
1238    Symbol symbol = prop.symbol;
1239    char propName[1024];
1240
1241    strcpy(setName, "__ecereProp_");
1242    FullClassNameCat(setName, prop._class.fullName, false);
1243    strcat(setName, "_Set_");
1244    // strcat(setName, prop.name);
1245    FullClassNameCat(setName, prop.name, true);
1246
1247    strcpy(getName, "__ecereProp_");
1248    FullClassNameCat(getName, prop._class.fullName, false);
1249    strcat(getName, "_Get_");
1250    FullClassNameCat(getName, prop.name, true);
1251    // strcat(getName, prop.name);
1252
1253    strcpy(propName, "__ecereProp_");
1254    FullClassNameCat(propName, prop._class.fullName, false);
1255    strcat(propName, "_");
1256    FullClassNameCat(propName, prop.name, true);
1257    // strcat(propName, prop.name);
1258
1259    // To support "char *" property
1260    MangleClassName(getName);
1261    MangleClassName(setName);
1262    MangleClassName(propName);
1263
1264    if(prop._class.type == structClass)
1265       DeclareStruct(prop._class.fullName, false);
1266
1267    if(!symbol || curExternal.symbol.idCode < symbol.id)
1268    {
1269       bool imported = false;
1270       bool dllImport = false;
1271       if(!symbol || symbol._import)
1272       {
1273          if(!symbol)
1274          {
1275             Symbol classSym;
1276             if(!prop._class.symbol)
1277                prop._class.symbol = FindClass(prop._class.fullName);
1278             classSym = prop._class.symbol;
1279             if(classSym && !classSym._import)
1280             {
1281                ModuleImport module;
1282
1283                if(prop._class.module)
1284                   module = FindModule(prop._class.module);
1285                else
1286                   module = mainModule;
1287
1288                classSym._import = ClassImport
1289                {
1290                   name = CopyString(prop._class.fullName);
1291                   isRemote = prop._class.isRemote;
1292                };
1293                module.classes.Add(classSym._import);
1294             }
1295             symbol = prop.symbol = Symbol { };
1296             symbol._import = (ClassImport)PropertyImport
1297             {
1298                name = CopyString(prop.name);
1299                isVirtual = false; //prop.isVirtual;
1300                hasSet = prop.Set ? true : false;
1301                hasGet = prop.Get ? true : false;
1302             };
1303             if(classSym)
1304                classSym._import.properties.Add(symbol._import);
1305          }
1306          imported = true;
1307          if(prop._class.module != privateModule && prop._class.module.importType != staticImport)
1308             dllImport = true;
1309       }
1310
1311       if(!symbol.type)
1312       {
1313          Context context = SetupTemplatesContext(prop._class);
1314          symbol.type = ProcessTypeString(prop.dataTypeString, false);
1315          FinishTemplatesContext(context);
1316       }
1317
1318       // Get
1319       if(prop.Get)
1320       {
1321          if(!symbol.externalGet || symbol.externalGet.type == functionExternal)
1322          {
1323             Declaration decl;
1324             OldList * specifiers, * declarators;
1325             Declarator d;
1326             OldList * params;
1327             Specifier spec;
1328             External external;
1329             Declarator typeDecl;
1330             bool simple = false;
1331
1332             specifiers = MkList();
1333             declarators = MkList();
1334             params = MkList();
1335
1336             ListAdd(params, MkTypeName(MkListOne(MkSpecifierName /*MkClassName*/(prop._class.fullName)), 
1337                MkDeclaratorIdentifier(MkIdentifier("this"))));
1338
1339             d = MkDeclaratorIdentifier(MkIdentifier(getName));
1340             //if(imported)
1341             if(dllImport)
1342                d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
1343
1344             {
1345                Context context = SetupTemplatesContext(prop._class);
1346                typeDecl = SpecDeclFromString(prop.dataTypeString, specifiers, null);
1347                FinishTemplatesContext(context);
1348             }
1349
1350             // Make sure the simple _class's type is declared
1351             for(spec = specifiers->first; spec; spec = spec.next)
1352             {
1353                if(spec.type == nameSpecifier /*SpecifierClass*/)
1354                {
1355                   if((!typeDecl || typeDecl.type == identifierDeclarator))
1356                   {
1357                      Symbol classSym = spec.symbol; // FindClass(spec.name);
1358                      symbol._class = classSym.registered;
1359                      if(classSym.registered && classSym.registered.type == structClass)
1360                      {
1361                         DeclareStruct(spec.name, false);
1362                         simple = true;
1363                      }
1364                   }
1365                }
1366             }
1367
1368             if(!simple)
1369                d = PlugDeclarator(typeDecl, d);
1370             else
1371             {
1372                ListAdd(params, MkTypeName(specifiers, 
1373                   PlugDeclarator(typeDecl, MkDeclaratorIdentifier(MkIdentifier("value")))));
1374                specifiers = MkList();
1375             }
1376
1377             d = MkDeclaratorFunction(d, params);
1378  
1379             //if(imported)
1380             if(dllImport)
1381                specifiers->Insert(null, MkSpecifier(EXTERN));
1382             else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
1383                specifiers->Insert(null, MkSpecifier(STATIC));
1384             if(simple)
1385                ListAdd(specifiers, MkSpecifier(VOID));
1386
1387             ListAdd(declarators, MkInitDeclarator(d, null));
1388
1389             decl = MkDeclaration(specifiers, declarators);
1390
1391             external = MkExternalDeclaration(decl);
1392             ast->Insert(curExternal.prev, external);
1393             external.symbol = symbol;
1394             symbol.externalGet = external;
1395
1396             ReplaceThisClassSpecifiers(specifiers, prop._class);
1397
1398             if(typeDecl)
1399                FreeDeclarator(typeDecl);
1400          }
1401          else
1402          {
1403             // Move declaration higher...
1404             ast->Move(symbol.externalGet, curExternal.prev);
1405          }
1406       }
1407
1408       // Set
1409       if(prop.Set)
1410       {
1411          if(!symbol.externalSet || symbol.externalSet.type == functionExternal)
1412          {
1413             Declaration decl;
1414             OldList * specifiers, * declarators;
1415             Declarator d;
1416             OldList * params;
1417             Specifier spec;
1418             External external;
1419             Declarator typeDecl;
1420
1421             declarators = MkList();
1422             params = MkList();
1423
1424             // TESTING COMMENTING THIS FIRST LINE OUT, what was the problem? Trying to add noHeadClass here ...
1425             if(!prop.conversion || prop._class.type == structClass)
1426             {
1427                ListAdd(params, MkTypeName(MkListOne(MkSpecifierName/*MkClassName*/(prop._class.fullName)), 
1428                   MkDeclaratorIdentifier(MkIdentifier("this"))));
1429             }
1430
1431             specifiers = MkList();
1432
1433             {
1434                Context context = SetupTemplatesContext(prop._class);
1435                typeDecl = d = SpecDeclFromString(prop.dataTypeString, specifiers,
1436                   MkDeclaratorIdentifier(MkIdentifier("value")));
1437                FinishTemplatesContext(context);
1438             }
1439             ListAdd(params, MkTypeName(specifiers, d));
1440
1441             d = MkDeclaratorIdentifier(MkIdentifier(setName));
1442             //if(imported)
1443             if(dllImport)
1444                d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
1445             d = MkDeclaratorFunction(d, params);
1446
1447             // Make sure the simple _class's type is declared
1448             for(spec = specifiers->first; spec; spec = spec.next)
1449             {
1450                if(spec.type == nameSpecifier /*SpecifierClass*/)
1451                {
1452                   if((!typeDecl || typeDecl.type == identifierDeclarator))
1453                   {
1454                      Symbol classSym = spec.symbol; // FindClass(spec.name);
1455                      symbol._class = classSym.registered;
1456                      if(classSym.registered && classSym.registered.type == structClass)
1457                         DeclareStruct(spec.name, false);
1458                   }
1459                }
1460             }
1461
1462             ListAdd(declarators, MkInitDeclarator(d, null));
1463
1464             specifiers = MkList();
1465             //if(imported)
1466             if(dllImport)
1467                specifiers->Insert(null, MkSpecifier(EXTERN));
1468             else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
1469                specifiers->Insert(null, MkSpecifier(STATIC));
1470
1471             // TESTING COMMENTING THIS FIRST LINE OUT, what was the problem? Trying to add noHeadClass here ...
1472             if(!prop.conversion || prop._class.type == structClass)
1473                ListAdd(specifiers, MkSpecifier(VOID));
1474             else
1475                ListAdd(specifiers, MkSpecifierName/*MkClassName*/(prop._class.fullName));
1476
1477             decl = MkDeclaration(specifiers, declarators);
1478
1479             external = MkExternalDeclaration(decl);
1480             ast->Insert(curExternal.prev, external);
1481             external.symbol = symbol;
1482             symbol.externalSet = external;
1483
1484             ReplaceThisClassSpecifiers(specifiers, prop._class);
1485          }
1486          else
1487          {
1488             // Move declaration higher...
1489             ast->Move(symbol.externalSet, curExternal.prev);
1490          }
1491       }
1492
1493       // Property (for Watchers)
1494       if(!symbol.externalPtr)
1495       {
1496          Declaration decl;
1497          External external;
1498          OldList * specifiers = MkList();
1499
1500          if(imported)
1501             specifiers->Insert(null, MkSpecifier(EXTERN));
1502          else
1503             specifiers->Insert(null, MkSpecifier(STATIC));
1504
1505          ListAdd(specifiers, MkSpecifierName("Property"));
1506
1507          {
1508             OldList * list = MkList();
1509             ListAdd(list, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), 
1510                   MkDeclaratorIdentifier(MkIdentifier(propName))), null));
1511
1512             if(!imported)
1513             {
1514                strcpy(propName, "__ecerePropM_");
1515                FullClassNameCat(propName, prop._class.fullName, false);
1516                strcat(propName, "_");
1517                // strcat(propName, prop.name);
1518                FullClassNameCat(propName, prop.name, true);
1519
1520                MangleClassName(propName);
1521
1522                ListAdd(list, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), 
1523                      MkDeclaratorIdentifier(MkIdentifier(propName))), null));
1524             }
1525             decl = MkDeclaration(specifiers, list);
1526          }
1527
1528          external = MkExternalDeclaration(decl);
1529          ast->Insert(curExternal.prev, external);
1530          external.symbol = symbol;
1531          symbol.externalPtr = external;
1532       }
1533       else
1534       {
1535          // Move declaration higher...
1536          ast->Move(symbol.externalPtr, curExternal.prev);
1537       }
1538
1539       symbol.id = curExternal.symbol.idCode;
1540    }
1541 }
1542
1543 // ***************** EXPRESSION PROCESSING ***************************
1544 public Type Dereference(Type source)
1545 {
1546    Type type = null;
1547    if(source)
1548    {
1549       if(source.kind == pointerType || source.kind == arrayType)
1550       {
1551          type = source.type;
1552          source.type.refCount++;
1553       }
1554       else if(source.kind == classType && !strcmp(source._class.string, "String"))
1555       {
1556          type = Type
1557          {
1558             kind = charType;
1559             refCount = 1;
1560          };
1561       }
1562       // Support dereferencing of no head classes for now...
1563       else if(source.kind == classType && source._class && source._class.registered && source._class.registered.type == noHeadClass)
1564       {
1565          type = source;
1566          source.refCount++;
1567       }
1568       else
1569          Compiler_Error($"cannot dereference type\n");
1570    }
1571    return type;
1572 }
1573
1574 static Type Reference(Type source)
1575 {
1576    Type type = null;
1577    if(source)
1578    {
1579       type = Type
1580       {
1581          kind = pointerType;
1582          type = source;
1583          refCount = 1;
1584       };
1585       source.refCount++;
1586    }
1587    return type;
1588 }
1589
1590 void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
1591 {
1592    Identifier ident = member.identifiers ? member.identifiers->first : null;
1593    bool found = false;
1594    DataMember dataMember = null;
1595    Method method = null;
1596    bool freeType = false;
1597
1598    yylloc = member.loc;
1599
1600    if(!ident)
1601    {
1602       if(curMember)
1603       {
1604          eClass_FindNextMember(_class, curClass, curMember, subMemberStack, subMemberStackPos);
1605          if(*curMember)
1606          {
1607             found = true;
1608             dataMember = *curMember;
1609          }
1610       }
1611    }
1612    else
1613    {
1614       DataMember thisMember = (DataMember)eClass_FindProperty(_class, ident.string, privateModule);
1615       DataMember _subMemberStack[256];
1616       int _subMemberStackPos = 0;
1617
1618       // FILL MEMBER STACK
1619       if(!thisMember)
1620          thisMember = eClass_FindDataMember(_class, ident.string, privateModule, _subMemberStack, &_subMemberStackPos);
1621       if(thisMember)
1622       {
1623          dataMember = thisMember;
1624          if(curMember && thisMember.memberAccess == publicAccess)
1625          {
1626             *curMember = thisMember;
1627             *curClass = thisMember._class;
1628             memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
1629             *subMemberStackPos = _subMemberStackPos;
1630          }
1631          found = true;
1632       }
1633       else
1634       {
1635          // Setting a method
1636          method = eClass_FindMethod(_class, ident.string, privateModule);
1637          if(method && method.type == virtualMethod)
1638             found = true;
1639          else
1640             method = null;
1641       }
1642    }
1643
1644    if(found)
1645    {
1646       Type type = null;
1647       if(dataMember)
1648       {
1649          if(!dataMember.dataType && dataMember.dataTypeString)
1650          {
1651             //Context context = SetupTemplatesContext(dataMember._class);
1652             Context context = SetupTemplatesContext(_class);
1653             dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
1654             FinishTemplatesContext(context);
1655          }
1656          type = dataMember.dataType;
1657       }
1658       else if(method)
1659       {
1660          // This is for destination type...
1661          if(!method.dataType)
1662             ProcessMethodType(method);
1663          //DeclareMethod(method);
1664          // method.dataType = ((Symbol)method.symbol)->type;
1665          type = method.dataType;
1666       }
1667
1668       if(ident && ident.next)
1669       {
1670          for(ident = ident.next; ident && type; ident = ident.next)
1671          {
1672             if(type.kind == classType)
1673             {
1674                dataMember = (DataMember)eClass_FindProperty(type._class.registered, ident.string, privateModule);
1675                if(!dataMember)
1676                   dataMember = eClass_FindDataMember(type._class.registered, ident.string, privateModule, null, null);
1677                if(dataMember)
1678                   type = dataMember.dataType;
1679             }
1680             else if(type.kind == structType || type.kind == unionType)
1681             {
1682                Type memberType;
1683                for(memberType = type.members.first; memberType; memberType = memberType.next)
1684                {
1685                   if(!strcmp(memberType.name, ident.string))
1686                   {
1687                      type = memberType;
1688                      break;
1689                   }
1690                }
1691             }
1692          }
1693       }
1694
1695       // *** WORKING CODE: TESTING THIS HERE FOR TEMPLATES ***
1696       if(type && type.kind == templateType && type.templateParameter.type == TemplateParameterType::type && _class.templateArgs /* TODO: Watch out for these _class.templateClass*/)
1697       {
1698          int id = 0;
1699          ClassTemplateParameter curParam;
1700          Class sClass;
1701          for(sClass = _class; sClass; sClass = sClass.base)
1702          {
1703             id = 0;
1704             if(sClass.templateClass) sClass = sClass.templateClass;
1705             for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
1706             {
1707                if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
1708                {
1709                   for(sClass = sClass.base; sClass; sClass = sClass.base)
1710                   {
1711                      if(sClass.templateClass) sClass = sClass.templateClass;
1712                      id += sClass.templateParams.count;
1713                   }
1714                   break;
1715                }
1716                id++;
1717             }
1718             if(curParam) break;
1719          }
1720
1721          if(curParam)
1722          {
1723             ClassTemplateArgument arg = _class.templateArgs[id];
1724             if(arg.dataTypeString)
1725             {
1726                // FreeType(type);
1727                type = ProcessTypeString(arg.dataTypeString, false);
1728                freeType = true;
1729                if(type && _class.templateClass)
1730                   type.passAsTemplate = true;
1731                if(type)
1732                {
1733                   // type.refCount++;
1734                   /*if(!exp.destType)
1735                   {
1736                      exp.destType = ProcessTypeString(arg.dataTypeString, false);
1737                      exp.destType.refCount++;
1738                   }*/
1739                }
1740             }
1741          }
1742       }
1743       if(type && type.kind == classType && type._class && type._class.registered && strchr(type._class.registered.fullName, '<'))
1744       {
1745          Class expClass = type._class.registered;
1746          Class cClass = null;
1747          int c;
1748          int paramCount = 0;
1749          int lastParam = -1;
1750          
1751          char templateString[1024];
1752          ClassTemplateParameter param;
1753          sprintf(templateString, "%s<", expClass.templateClass.fullName);
1754          for(cClass = expClass; cClass; cClass = cClass.base)
1755          {
1756             int p = 0;
1757             if(cClass.templateClass) cClass = cClass.templateClass;
1758             for(param = cClass.templateParams.first; param; param = param.next)
1759             {
1760                int id = p;
1761                Class sClass;
1762                ClassTemplateArgument arg;
1763                for(sClass = cClass.base; sClass; sClass = sClass.base) 
1764                {
1765                   if(sClass.templateClass) sClass = sClass.templateClass;
1766                   id += sClass.templateParams.count;
1767                }
1768                arg = expClass.templateArgs[id];
1769
1770                for(sClass = _class /*expClass*/; sClass; sClass = sClass.base)
1771                {
1772                   ClassTemplateParameter cParam;
1773                   //int p = numParams - sClass.templateParams.count;
1774                   int p = 0;
1775                   Class nextClass;
1776                   if(sClass.templateClass) sClass = sClass.templateClass;
1777
1778                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) 
1779                   {
1780                      if(nextClass.templateClass) nextClass = nextClass.templateClass;
1781                      p += nextClass.templateParams.count;
1782                   }
1783                   
1784                   for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
1785                   {
1786                      if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
1787                      {
1788                         if(_class.templateArgs && arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
1789                         {
1790                            arg.dataTypeString = _class.templateArgs[p].dataTypeString;
1791                            arg.dataTypeClass = _class.templateArgs[p].dataTypeClass;
1792                            break;
1793                         }
1794                      }
1795                   }
1796                }
1797
1798                {
1799                   char argument[256];
1800                   argument[0] = '\0';
1801                   /*if(arg.name)
1802                   {
1803                      strcat(argument, arg.name.string);
1804                      strcat(argument, " = ");
1805                   }*/
1806                   switch(param.type)
1807                   {
1808                      case expression:
1809                      {
1810                         // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
1811                         char expString[1024];
1812                         OldList * specs = MkList();
1813                         Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
1814                         Expression exp;
1815                         char * string = PrintHexUInt64(arg.expression.ui64);
1816                         exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
1817
1818                         ProcessExpressionType(exp);
1819                         ComputeExpression(exp);
1820                         expString[0] = '\0';
1821                         PrintExpression(exp, expString);
1822                         strcat(argument, expString);
1823                         //delete exp;
1824                         FreeExpression(exp);
1825                         break;
1826                      }
1827                      case identifier:
1828                      {
1829                         strcat(argument, arg.member.name);
1830                         break;
1831                      }
1832                      case TemplateParameterType::type:
1833                      {
1834                         if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
1835                            strcat(argument, arg.dataTypeString);
1836                         break;
1837                      }
1838                   }
1839                   if(argument[0])
1840                   {
1841                      if(paramCount) strcat(templateString, ", ");
1842                      if(lastParam != p - 1)
1843                      {
1844                         strcat(templateString, param.name);
1845                         strcat(templateString, " = ");
1846                      }
1847                      strcat(templateString, argument);
1848                      paramCount++;
1849                      lastParam = p;
1850                   }
1851                   p++;
1852                }               
1853             }
1854          }
1855          {
1856             int len = strlen(templateString);
1857             if(templateString[len-1] == '<')
1858                len--;
1859             else
1860             {
1861                if(templateString[len-1] == '>')
1862                   templateString[len++] = ' ';
1863                templateString[len++] = '>';
1864             }
1865             templateString[len++] = '\0';
1866          }
1867          {
1868             Context context = SetupTemplatesContext(_class);
1869             if(freeType) FreeType(type);
1870             type = ProcessTypeString(templateString, false);
1871             freeType = true;
1872             FinishTemplatesContext(context);
1873          }
1874       }
1875
1876       if(method && member.initializer && member.initializer.type == expInitializer && member.initializer.exp)
1877       {
1878          ProcessExpressionType(member.initializer.exp);
1879          if(!member.initializer.exp.expType)
1880          {
1881             if(inCompiler)
1882             {
1883                char expString[10240];
1884                expString[0] = '\0';
1885                PrintExpression(member.initializer.exp, expString);
1886                ChangeCh(expString, '\n', ' ');
1887                Compiler_Error($"unresolved symbol used as an instance method %s\n", expString);
1888             }
1889          }
1890          //else if(!MatchTypes(member.exp.expType, type, null, _class, null, true, true, false, false))
1891          else if(!MatchTypes(member.initializer.exp.expType, type, null, null, _class, true, true, false, false))
1892          {
1893             Compiler_Error($"incompatible instance method %s\n", ident.string);
1894          }
1895       }
1896       else if(member.initializer)
1897       {
1898          /*
1899          FreeType(member.exp.destType);
1900          member.exp.destType = type;
1901          if(member.exp.destType)
1902             member.exp.destType.refCount++;
1903          ProcessExpressionType(member.exp);
1904          */
1905
1906          ProcessInitializer(member.initializer, type);
1907       }
1908       if(freeType) FreeType(type);
1909    }
1910    else
1911    {
1912       if(_class && _class.type == unitClass)
1913       {
1914          if(member.initializer)
1915          {
1916             /*
1917             FreeType(member.exp.destType);
1918             member.exp.destType = MkClassType(_class.fullName);
1919             ProcessExpressionType(member.initializer, type);
1920             */
1921             Type type = MkClassType(_class.fullName);
1922             ProcessInitializer(member.initializer, type);
1923             FreeType(type);
1924          }
1925       }
1926       else
1927       {
1928          if(member.initializer)
1929          {
1930             //ProcessExpressionType(member.exp);
1931             ProcessInitializer(member.initializer, null);
1932          }
1933          if(ident)
1934          {
1935             if(method)
1936             {
1937                Compiler_Error($"couldn't find virtual method %s in class %s\n", ident.string, _class.fullName);
1938             }
1939             else if(_class)
1940             {
1941                Compiler_Error($"couldn't find member %s in class %s\n", ident.string, _class.fullName);
1942                if(inCompiler)
1943                   eClass_AddDataMember(_class, ident.string, "int", 0, 0, publicAccess);
1944             }
1945          }
1946          else if(_class)
1947             Compiler_Error($"too many initializers for instantiation of class %s\n", _class.fullName);
1948       }
1949    }
1950 }
1951
1952 void ProcessInstantiationType(Instantiation inst)
1953 {
1954    yylloc = inst.loc;
1955    if(inst._class)
1956    {
1957       MembersInit members;
1958       Symbol classSym; // = inst._class.symbol; // FindClass(inst._class.name);
1959       Class _class;
1960       
1961       /*if(!inst._class.symbol)
1962          inst._class.symbol = FindClass(inst._class.name);*/
1963       classSym = inst._class.symbol;
1964       _class = classSym ? classSym.registered : null;
1965
1966       // DANGER: Patch for mutex not declaring its struct when not needed
1967       if(!_class || _class.type != noHeadClass)
1968          DeclareStruct(inst._class.name, false); //_class && _class.type == noHeadClass);
1969
1970       afterExternal = afterExternal ? afterExternal : curExternal;
1971
1972       if(inst.exp)
1973          ProcessExpressionType(inst.exp);
1974
1975       inst.isConstant = true;
1976       if(inst.members)
1977       {
1978          DataMember curMember = null;
1979          Class curClass = null;
1980          DataMember subMemberStack[256];
1981          int subMemberStackPos = 0;
1982
1983          for(members = inst.members->first; members; members = members.next)
1984          {
1985             switch(members.type)
1986             {
1987                case methodMembersInit:
1988                {
1989                   char name[1024];
1990                   static uint instMethodID = 0;
1991                   External external = curExternal;
1992                   Context context = curContext;
1993                   Declarator declarator = members.function.declarator;
1994                   Identifier nameID = GetDeclId(declarator);
1995                   char * unmangled = nameID ? nameID.string : null;
1996                   Expression exp;
1997                   External createdExternal = null;
1998
1999                   if(inCompiler)
2000                   {
2001                      char number[16];
2002                      //members.function.dontMangle = true;
2003                      strcpy(name, "__ecereInstMeth_");
2004                      FullClassNameCat(name, _class ? _class.fullName : "_UNKNOWNCLASS", false);
2005                      strcat(name, "_");
2006                      strcat(name, nameID.string);
2007                      strcat(name, "_");
2008                      sprintf(number, "_%08d", instMethodID++);
2009                      strcat(name, number);                     
2010                      nameID.string = CopyString(name);
2011                   }
2012
2013                   // Do modifications here...
2014                   if(declarator)
2015                   {
2016                      Symbol symbol = declarator.symbol;
2017                      Method method = eClass_FindMethod(_class, unmangled, privateModule);
2018                                     
2019                      if(method && method.type == virtualMethod)
2020                      {
2021                         symbol.method = method;
2022                         ProcessMethodType(method);
2023
2024                         if(!symbol.type.thisClass)
2025                         {
2026                            if(method.dataType.thisClass && currentClass && 
2027                               eClass_IsDerived(currentClass, method.dataType.thisClass.registered))
2028                            {
2029                               if(!currentClass.symbol)
2030                                  currentClass.symbol = FindClass(currentClass.fullName);
2031                               symbol.type.thisClass = currentClass.symbol;
2032                            }
2033                            else
2034                            {
2035                               if(!_class.symbol)
2036                                  _class.symbol = FindClass(_class.fullName);
2037                               symbol.type.thisClass = _class.symbol;
2038                            }
2039                         }
2040                         // TESTING THIS HERE:
2041                         DeclareType(symbol.type, true, true);
2042
2043                      }
2044                      else if(classSym)
2045                      {
2046                         Compiler_Error($"couldn't find virtual method %s in class %s\n",
2047                            unmangled, classSym.string);
2048                      }
2049                   }
2050
2051                   //declarator.symbol.id = declarator.symbol.idCode = curExternal.symbol.idCode;
2052                   createdExternal = ProcessClassFunction(classSym ? classSym.registered : null, members.function, ast, afterExternal, true);
2053
2054                   if(nameID)
2055                   {
2056                      FreeSpecifier(nameID._class);
2057                      nameID._class = null;
2058                   }
2059
2060                   if(inCompiler)
2061                   {
2062
2063                      Type type = declarator.symbol.type;
2064                      External oldExternal = curExternal;
2065
2066                      // *** Commented this out... Any negative impact? Yes: makes double prototypes declarations... Why was it commented out?
2067                      // *** It was commented out for problems such as
2068                      /*
2069                            class VirtualDesktop : Window
2070                            {
2071                               clientSize = Size { };
2072                               Timer timer
2073                               {
2074                                  bool DelayExpired()
2075                                  {
2076                                     clientSize.w;
2077                                     return true;
2078                                  }
2079                               };
2080                            }
2081                      */
2082                      // Commented Out: Good for bet.ec in Poker (Otherwise: obj\bet.c:187: error: `currentBet' undeclared (first use in this function))
2083
2084                      declarator.symbol.id = declarator.symbol.idCode = curExternal.symbol.idCode;
2085
2086                      /*
2087                      if(strcmp(declarator.symbol.string, name))
2088                      {
2089                         printf("TOCHECK: Look out for this\n");
2090                         delete declarator.symbol.string;
2091                         declarator.symbol.string = CopyString(name);
2092                      }
2093                      
2094                      if(!declarator.symbol.parent && globalContext.symbols.root != (BTNode)declarator.symbol)
2095                      {
2096                         printf("TOCHECK: Will this ever be in a list? Yes.\n");
2097                         excludedSymbols->Remove(declarator.symbol);
2098                         globalContext.symbols.Add((BTNode)declarator.symbol);
2099                         if(strstr(declarator.symbol.string), "::")
2100                            globalContext.hasNameSpace = true;
2101
2102                      }
2103                      */
2104                   
2105                      //curExternal = curExternal.prev;
2106                      //afterExternal = afterExternal->next;
2107
2108                      //ProcessFunction(afterExternal->function);
2109
2110                      //curExternal = afterExternal;
2111                      {
2112                         External externalDecl;
2113                         externalDecl = MkExternalDeclaration(null);
2114                         ast->Insert(oldExternal.prev, externalDecl);
2115
2116                         // Which function does this process?
2117                         if(createdExternal.function)
2118                         {
2119                            ProcessFunction(createdExternal.function);
2120
2121                            //curExternal = oldExternal;
2122
2123                            {
2124                               //Declaration decl = MkDeclaration(members.function.specifiers, MkListOne(MkInitDeclarator(CopyDeclarator(declarator), null)));
2125
2126                               Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier), 
2127                                  MkListOne(MkInitDeclarator(CopyDeclarator(declarator), null)));
2128                      
2129                               //externalDecl = MkExternalDeclaration(decl);
2130                         
2131                               //***** ast->Insert(external.prev, externalDecl);
2132                               //ast->Insert(curExternal.prev, externalDecl);
2133                               externalDecl.declaration = decl;
2134                               if(decl.symbol && !decl.symbol.pointerExternal)
2135                                  decl.symbol.pointerExternal = externalDecl;
2136
2137                               // Trying this out...
2138                               declarator.symbol.pointerExternal = externalDecl;
2139                            }
2140                         }
2141                      }
2142                   }
2143                   else if(declarator)
2144                   {
2145                      curExternal = declarator.symbol.pointerExternal;
2146                      ProcessFunction((FunctionDefinition)members.function);
2147                   }
2148                   curExternal = external;
2149                   curContext = context;
2150
2151                   if(inCompiler)
2152                   {
2153                      FreeClassFunction(members.function);
2154
2155                      // In this pass, turn this into a MemberInitData
2156                      exp = QMkExpId(name);
2157                      members.type = dataMembersInit;
2158                      members.dataMembers = MkListOne(MkMemberInit(MkListOne(MkIdentifier(unmangled)), MkInitializerAssignment(exp)));
2159
2160                      delete unmangled;
2161                   }
2162                   break;
2163                }
2164                case dataMembersInit:
2165                {
2166                   if(members.dataMembers && classSym)
2167                   {
2168                      MemberInit member;
2169                      Location oldyyloc = yylloc;
2170                      for(member = members.dataMembers->first; member; member = member.next)
2171                      {
2172                         ProcessMemberInitData(member, classSym.registered, &curClass, &curMember, subMemberStack, &subMemberStackPos);
2173                         if(member.initializer && !member.initializer.isConstant)
2174                            inst.isConstant = false;
2175                      }
2176                      yylloc = oldyyloc;
2177                   }
2178                   break;
2179                }
2180             }
2181          }
2182       }
2183    }
2184 }
2185
2186 static void DeclareType(Type type, bool declarePointers, bool declareParams)
2187 {
2188    // OPTIMIZATIONS: TESTING THIS...
2189    if(inCompiler)
2190    {
2191       if(type.kind == functionType)
2192       {
2193          Type param;
2194          if(declareParams)
2195          {
2196             for(param = type.params.first; param; param = param.next)
2197                DeclareType(param, declarePointers, true);
2198          }
2199          DeclareType(type.returnType, declarePointers, true);
2200       }
2201       else if(type.kind == pointerType && declarePointers)
2202          DeclareType(type.type, declarePointers, false);
2203       else if(type.kind == classType)
2204       {
2205          if(type._class.registered && (type._class.registered.type == structClass || type._class.registered.type == noHeadClass) && !type._class.declaring)
2206             DeclareStruct(type._class.registered.fullName, type._class.registered.type == noHeadClass);
2207       }
2208       else if(type.kind == structType || type.kind == unionType)
2209       {
2210          Type member;
2211          for(member = type.members.first; member; member = member.next)
2212             DeclareType(member, false, false);
2213       }
2214       else if(type.kind == arrayType)
2215          DeclareType(type.arrayType, declarePointers, false);
2216    }
2217 }
2218
2219 ClassTemplateArgument * FindTemplateArg(Class _class, TemplateParameter param)
2220 {
2221    ClassTemplateArgument * arg = null;
2222    int id = 0;
2223    ClassTemplateParameter curParam;
2224    Class sClass;
2225    for(sClass = _class; sClass; sClass = sClass.base)
2226    {
2227       id = 0;
2228       if(sClass.templateClass) sClass = sClass.templateClass;
2229       for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
2230       {
2231          if(curParam.type == TemplateParameterType::type && !strcmp(param.identifier.string, curParam.name))
2232          {
2233             for(sClass = sClass.base; sClass; sClass = sClass.base)
2234             {
2235                if(sClass.templateClass) sClass = sClass.templateClass;
2236                id += sClass.templateParams.count;
2237             }
2238             break;
2239          }
2240          id++;
2241       }
2242       if(curParam) break;
2243    }
2244    if(curParam)
2245    {
2246       arg = &_class.templateArgs[id];
2247       if(arg && param.type == type)
2248          arg->dataTypeClass = eSystem_FindClass(_class.module, arg->dataTypeString);
2249    }
2250    return arg;
2251 }
2252
2253 public Context SetupTemplatesContext(Class _class)
2254 {
2255    Context context = PushContext();
2256    context.templateTypesOnly = true;
2257    if(_class.symbol && ((Symbol)_class.symbol).templateParams)
2258    {
2259       TemplateParameter param = ((Symbol)_class.symbol).templateParams->first;
2260       for(; param; param = param.next)
2261       {
2262          if(param.type == type && param.identifier)
2263          {
2264             TemplatedType type { key = (uint)param.identifier.string, param = param };
2265             curContext.templateTypes.Add((BTNode)type);
2266          }
2267       }
2268    }
2269    else if(_class)
2270    {
2271       Class sClass;
2272       for(sClass = _class; sClass; sClass = sClass.base)
2273       {
2274          ClassTemplateParameter p;
2275          for(p = sClass.templateParams.first; p; p = p.next)
2276          {
2277             //OldList * specs = MkList();
2278             //Declarator decl = null;
2279             //decl = SpecDeclFromString(p.dataTypeString, specs, null);
2280             if(p.type == type)
2281             {
2282                TemplateParameter param = p.param;
2283                TemplatedType type;
2284                if(!param)
2285                {
2286                   // ADD DATA TYPE HERE...
2287                   p.param = param = TemplateParameter
2288                   {
2289                      identifier = MkIdentifier(p.name), type = p.type, 
2290                      dataTypeString = p.dataTypeString /*, dataType = { specs, decl }*/
2291                   };
2292                }
2293                type = TemplatedType { key = (uint)p.name, param = param };
2294                curContext.templateTypes.Add((BTNode)type);
2295             }
2296          }
2297       }
2298    }
2299    return context;
2300 }
2301
2302 public void FinishTemplatesContext(Context context)
2303 {
2304    PopContext(context);
2305    FreeContext(context);
2306    delete context;
2307 }
2308
2309 public void ProcessMethodType(Method method)
2310 {
2311    if(!method.dataType)
2312    {
2313       Context context = SetupTemplatesContext(method._class);
2314
2315       method.dataType = ProcessTypeString(method.dataTypeString, false);
2316
2317       FinishTemplatesContext(context);
2318
2319       if(method.type != virtualMethod && method.dataType)
2320       {
2321          if(!method.dataType.thisClass && !method.dataType.staticMethod)
2322          {
2323             if(!method._class.symbol)
2324                method._class.symbol = FindClass(method._class.fullName);
2325             method.dataType.thisClass = method._class.symbol;
2326          }
2327       }
2328
2329       // Why was this commented out? Working fine without now...
2330
2331       /*
2332       if(method.dataType.kind == functionType && !method.dataType.staticMethod && !method.dataType.thisClass)
2333          method.dataType.thisClass = method._class.symbol; // FindClass(method._class.fullName);
2334          */
2335    }
2336
2337    /*
2338    if(type)
2339    {
2340       char * par = strstr(type, "(");
2341       char * classOp = null;
2342       int classOpLen = 0;
2343       if(par)
2344       {
2345          int c;
2346          for(c = par-type-1; c >= 0; c++)
2347          {
2348             if(type[c] == ':' && type[c+1] == ':')
2349             {
2350                classOp = type + c - 1;
2351                for(c = c-1; c >=0 && !isspace(type[c]); c--)
2352                {
2353                   classOp--;
2354                   classOpLen++;
2355                }
2356                break;
2357             }
2358             else if(!isspace(type[c]))
2359                break;
2360          }
2361       }
2362       if(classOp)
2363       {
2364          char temp[1024];
2365          int typeLen = strlen(type);
2366          memcpy(temp, classOp, classOpLen);
2367          temp[classOpLen] = '\0';
2368          if(temp[0])
2369             _class = eSystem_FindClass(module, temp);
2370          else
2371             _class = null;
2372          method.dataTypeString = new char[typeLen - classOpLen + 1];
2373          memcpy(method.dataTypeString, type, classOp - type);
2374          memcpy(method.dataTypeString + (classOp - type), classOp + classOpLen, typeLen - (classOp - type + classOpLen));
2375       }
2376       else
2377          method.dataTypeString = type;
2378    }
2379    */
2380 }
2381
2382
2383 public void ProcessPropertyType(Property prop)
2384 {
2385    if(!prop.dataType)
2386    {
2387       Context context = SetupTemplatesContext(prop._class);
2388       prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2389       FinishTemplatesContext(context);
2390    }
2391 }
2392
2393 public void DeclareMethod(Method method, char * name)
2394 {
2395    Symbol symbol = method.symbol;
2396    if(!symbol || (!symbol.pointerExternal && method.type == virtualMethod) || symbol.id > (curExternal ? curExternal.symbol.idCode : -1))
2397    {
2398       bool imported = false;
2399       bool dllImport = false;
2400
2401       if(!method.dataType)
2402          method.dataType = ProcessTypeString(method.dataTypeString, false);
2403
2404       if(!symbol || symbol._import || method.type == virtualMethod)
2405       {
2406          if(!symbol || method.type == virtualMethod)
2407          {
2408             Symbol classSym;
2409             if(!method._class.symbol)
2410                method._class.symbol = FindClass(method._class.fullName);
2411             classSym = method._class.symbol;
2412             if(!classSym._import)
2413             {
2414                ModuleImport module;
2415                
2416                if(method._class.module && method._class.module.name)
2417                   module = FindModule(method._class.module);
2418                else
2419                   module = mainModule;
2420                classSym._import = ClassImport
2421                {
2422                   name = CopyString(method._class.fullName);
2423                   isRemote = method._class.isRemote;
2424                };
2425                module.classes.Add(classSym._import);
2426             }
2427             if(!symbol)
2428             {
2429                symbol = method.symbol = Symbol { };
2430             }
2431             if(!symbol._import)
2432             {
2433                symbol._import = (ClassImport)MethodImport
2434                {
2435                   name = CopyString(method.name);
2436                   isVirtual = method.type == virtualMethod;
2437                };
2438                classSym._import.methods.Add(symbol._import);
2439             }
2440             if(!symbol)
2441             {
2442                // Set the symbol type
2443                /*
2444                if(!type.thisClass)
2445                {
2446                   type.thisClass = method._class.symbol; // FindClass(method._class.fullName);
2447                }
2448                else if(type.thisClass == (void *)-1)
2449                {
2450                   type.thisClass = null;
2451                }
2452                */
2453                // symbol.type = ProcessTypeString(method.dataTypeString, false);
2454                symbol.type = method.dataType;
2455                if(symbol.type) symbol.type.refCount++;
2456             }
2457             /*
2458             if(!method.thisClass || strcmp(method.thisClass, "void"))
2459                symbol.type.params.Insert(null, 
2460                   MkClassType(method.thisClass ? method.thisClass : method._class.fullName));
2461             */
2462          }
2463          if(!method.dataType.dllExport)
2464          {
2465             imported = true;
2466             if(method._class.module != privateModule && method._class.module.importType != staticImport)
2467                dllImport = true;
2468          }
2469       }
2470
2471       /* MOVING THIS UP
2472       if(!method.dataType)
2473          method.dataType = ((Symbol)method.symbol).type;
2474          //ProcessMethodType(method);
2475       */
2476
2477       if(method.type != virtualMethod && method.dataType)
2478          DeclareType(method.dataType, true, true);
2479
2480       if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
2481       {
2482          // We need a declaration here :)
2483          Declaration decl;
2484          OldList * specifiers, * declarators;
2485          Declarator d;
2486          Declarator funcDecl;
2487          External external;
2488
2489          specifiers = MkList();
2490          declarators = MkList();
2491
2492          //if(imported)
2493          if(dllImport)
2494             ListAdd(specifiers, MkSpecifier(EXTERN));
2495          else if(method._class.symbol && ((Symbol)method._class.symbol).isStatic)
2496             ListAdd(specifiers, MkSpecifier(STATIC));
2497
2498          if(method.type == virtualMethod)
2499          {
2500             ListAdd(specifiers, MkSpecifier(INT));
2501             d = MkDeclaratorIdentifier(MkIdentifier(name));
2502          }
2503          else
2504          {
2505             d = MkDeclaratorIdentifier(MkIdentifier(name));
2506             //if(imported)
2507             if(dllImport)
2508                d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
2509             {
2510                Context context = SetupTemplatesContext(method._class);
2511                d = SpecDeclFromString(method.dataTypeString, specifiers, d);
2512                FinishTemplatesContext(context);
2513             }
2514             funcDecl = GetFuncDecl(d);
2515
2516             if(dllImport)
2517             {
2518                Specifier spec, next;
2519                for(spec = specifiers->first; spec; spec = next)
2520                {
2521                   next = spec.next;
2522                   if(spec.type == extendedSpecifier)
2523                   {
2524                      specifiers->Remove(spec);
2525                      FreeSpecifier(spec);
2526                   }
2527                }
2528             }
2529
2530             // Add this parameter if not a static method
2531             if(method.dataType && !method.dataType.staticMethod)
2532             {
2533                if(funcDecl && funcDecl.function.parameters && funcDecl.function.parameters->count)
2534                {
2535                   Class _class = method.dataType.thisClass ? method.dataType.thisClass.registered : method._class;
2536                   TypeName thisParam = MkTypeName(MkListOne(
2537                      MkSpecifierName/*MkClassName*/(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)), 
2538                      (_class && _class.type == systemClass) ? MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("this"))) : MkDeclaratorIdentifier(MkIdentifier("this")));
2539                   TypeName firstParam = ((TypeName)funcDecl.function.parameters->first);
2540                   Specifier firstSpec = firstParam.qualifiers ? firstParam.qualifiers->first : null;
2541
2542                   if(firstSpec && firstSpec.type == baseSpecifier && firstSpec.specifier == VOID && !firstParam.declarator)
2543                   {
2544                      TypeName param = funcDecl.function.parameters->first;
2545                      funcDecl.function.parameters->Remove(param);
2546                      FreeTypeName(param);
2547                   }
2548
2549                   if(!funcDecl.function.parameters)
2550                      funcDecl.function.parameters = MkList();
2551                   funcDecl.function.parameters->Insert(null, thisParam);
2552                }
2553             }
2554             // Make sure we don't have empty parameter declarations for static methods...
2555             /*
2556             else if(!funcDecl.function.parameters)
2557             {
2558                funcDecl.function.parameters = MkList();
2559                funcDecl.function.parameters->Insert(null, 
2560                   MkTypeName(MkListOne(MkSpecifier(VOID)),null));
2561             }*/
2562          }
2563          // TESTING THIS:
2564          ProcessDeclarator(d);
2565
2566          ListAdd(declarators, MkInitDeclarator(d, null));
2567
2568          decl = MkDeclaration(specifiers, declarators);
2569
2570          ReplaceThisClassSpecifiers(specifiers, method._class);
2571
2572          // Keep a different symbol for the function definition than the declaration...
2573          if(symbol.pointerExternal)
2574          {
2575             Symbol functionSymbol { };
2576
2577             // Copy symbol
2578             {
2579                *functionSymbol = *symbol;
2580                functionSymbol.string = CopyString(symbol.string);
2581                if(functionSymbol.type)
2582                   functionSymbol.type.refCount++;
2583             }
2584
2585             excludedSymbols->Add(functionSymbol);
2586             symbol.pointerExternal.symbol = functionSymbol;
2587          }
2588          external = MkExternalDeclaration(decl);
2589          if(curExternal)
2590             ast->Insert(curExternal ? curExternal.prev : null, external);
2591          external.symbol = symbol;
2592          symbol.pointerExternal = external;
2593       }
2594       else if(ast)
2595       {
2596          // Move declaration higher...
2597          ast->Move(symbol.pointerExternal, curExternal.prev);
2598       }
2599
2600       symbol.id = curExternal ? curExternal.symbol.idCode : MAXINT;
2601    }
2602 }
2603
2604 char * ReplaceThisClass(Class _class)
2605 {
2606    if(thisClassParams && _class.templateParams.count && !_class.templateClass)
2607    {
2608       bool first = true;
2609       int p = 0;
2610       ClassTemplateParameter param;
2611       int lastParam = -1;
2612       
2613       char className[1024];
2614       strcpy(className, _class.fullName);
2615       for(param = _class.templateParams.first; param; param = param.next)
2616       {
2617          // if((!param.defaultArg.dataTypeString && !param.defaultArg.expression.ui64))
2618          {
2619             if(first) strcat(className, "<");
2620             if(!first) strcat(className, ", ");
2621             if(lastParam + 1 != p)
2622             {
2623                strcat(className, param.name);
2624                strcat(className, " = ");
2625             }
2626             strcat(className, param.name);
2627             first = false;
2628             lastParam = p;
2629          }
2630          p++;
2631       }
2632       if(!first)
2633       {
2634          int len = strlen(className);
2635          if(className[len-1] == '>') className[len++] = ' ';
2636          className[len++] = '>';
2637          className[len++] = '\0';
2638       }
2639       return CopyString(className);
2640    }
2641    else
2642       return CopyString(_class.fullName);   
2643 }
2644
2645 Type ReplaceThisClassType(Class _class)
2646 {
2647    if(thisClassParams && _class.templateParams.count && !_class.templateClass)
2648    {
2649       bool first = true;
2650       int p = 0;
2651       ClassTemplateParameter param;
2652       int lastParam = -1;
2653       char className[1024];
2654       strcpy(className, _class.fullName);
2655       
2656       for(param = _class.templateParams.first; param; param = param.next)
2657       {
2658          // if((!param.defaultArg.dataTypeString && !param.defaultArg.expression.ui64))
2659          {
2660             if(first) strcat(className, "<");
2661             if(!first) strcat(className, ", ");
2662             if(lastParam + 1 != p)
2663             {
2664                strcat(className, param.name);
2665                strcat(className, " = ");
2666             }
2667             strcat(className, param.name);
2668             first = false;
2669             lastParam = p;
2670          }
2671          p++;
2672       }
2673       if(!first)
2674       {
2675          int len = strlen(className);
2676          if(className[len-1] == '>') className[len++] = ' ';
2677          className[len++] = '>';
2678          className[len++] = '\0';
2679       }
2680       return MkClassType(className);
2681       //return ProcessTypeString(className, false);
2682    }
2683    else
2684    {
2685       return MkClassType(_class.fullName);
2686       //return ProcessTypeString(_class.fullName, false);
2687    }
2688 }
2689
2690 void ReplaceThisClassSpecifiers(OldList specs, Class _class)
2691 {
2692    if(specs != null && _class)
2693    {
2694       Specifier spec;
2695       for(spec = specs.first; spec; spec = spec.next)
2696       {
2697          if(spec.type == baseSpecifier && spec.specifier == THISCLASS)
2698          {
2699             spec.type = nameSpecifier;
2700             spec.name = ReplaceThisClass(_class);
2701             spec.symbol = FindClass(spec.name); //_class.symbol;
2702          }
2703       }
2704    }
2705 }
2706
2707 // Returns imported or not
2708 bool DeclareFunction(GlobalFunction function, char * name)
2709 {
2710    Symbol symbol = function.symbol;
2711    if(curExternal && (!symbol || symbol.id > curExternal.symbol.idCode))
2712    {
2713       bool imported = false;
2714       bool dllImport = false;
2715
2716       if(!function.dataType)
2717       {
2718          function.dataType = ProcessTypeString(function.dataTypeString, false);
2719          if(!function.dataType.thisClass)
2720             function.dataType.staticMethod = true;
2721       }
2722
2723       if(inCompiler)
2724       {
2725          if(!symbol)
2726          {
2727             ModuleImport module = FindModule(function.module);
2728             // WARNING: This is not added anywhere...
2729             symbol = function.symbol = Symbol {  };
2730
2731             if(module.name)
2732             {
2733                if(!function.dataType.dllExport)
2734                {
2735                   symbol._import = (ClassImport)FunctionImport { name = CopyString(function.name) };
2736                   module.functions.Add(symbol._import);
2737                }
2738             }
2739             // Set the symbol type
2740             {
2741                symbol.type = ProcessTypeString(function.dataTypeString, false);
2742                if(!symbol.type.thisClass)
2743                   symbol.type.staticMethod = true;
2744             }
2745          }
2746          imported = symbol._import ? true : false;
2747          if(imported && function.module != privateModule && function.module.importType != staticImport)
2748             dllImport = true;
2749       }
2750
2751       DeclareType(function.dataType, true, true);
2752
2753       if(inCompiler)
2754       {
2755          if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
2756          {
2757             // We need a declaration here :)
2758             Declaration decl;
2759             OldList * specifiers, * declarators;
2760             Declarator d;
2761             Declarator funcDecl;
2762             External external;
2763
2764             specifiers = MkList();
2765             declarators = MkList();
2766
2767             //if(imported)
2768                ListAdd(specifiers, MkSpecifier(EXTERN));
2769             /*
2770             else
2771                ListAdd(specifiers, MkSpecifier(STATIC));
2772             */
2773
2774             d = MkDeclaratorIdentifier(MkIdentifier(imported ? name : function.name));
2775             //if(imported)
2776             if(dllImport)
2777                d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
2778
2779             d = SpecDeclFromString(function.dataTypeString, specifiers, d);
2780             // TAKE OUT THE DLL EXPORT IF STATICALLY IMPORTED:
2781             if(function.module.importType == staticImport)
2782             {
2783                Specifier spec;
2784                for(spec = specifiers->first; spec; spec = spec.next)
2785                   if(spec.type == extendedSpecifier && !strcmp(spec.name, "dllexport"))
2786                   {
2787                      specifiers->Remove(spec);
2788                      FreeSpecifier(spec);
2789                      break;
2790                   }
2791             }
2792
2793             funcDecl = GetFuncDecl(d);
2794
2795             // Make sure we don't have empty parameter declarations for static methods...
2796             if(funcDecl && !funcDecl.function.parameters)
2797             {
2798                funcDecl.function.parameters = MkList();
2799                funcDecl.function.parameters->Insert(null, 
2800                   MkTypeName(MkListOne(MkSpecifier(VOID)),null));
2801             }
2802
2803             ListAdd(declarators, MkInitDeclarator(d, null));
2804
2805             {
2806                Context oldCtx = curContext;
2807                curContext = globalContext;
2808                decl = MkDeclaration(specifiers, declarators);
2809                curContext = oldCtx;
2810             }
2811
2812             // Keep a different symbol for the function definition than the declaration...
2813             if(symbol.pointerExternal)
2814             {
2815                Symbol functionSymbol { };
2816                // Copy symbol
2817                {
2818                   *functionSymbol = *symbol;
2819                   functionSymbol.string = CopyString(symbol.string);
2820                   if(functionSymbol.type)
2821                      functionSymbol.type.refCount++;
2822                }
2823
2824                excludedSymbols->Add(functionSymbol);
2825
2826                symbol.pointerExternal.symbol = functionSymbol;
2827             }
2828             external = MkExternalDeclaration(decl);
2829             if(curExternal)
2830                ast->Insert(curExternal.prev, external);
2831             external.symbol = symbol;
2832             symbol.pointerExternal = external;
2833          }
2834          else
2835          {
2836             // Move declaration higher...
2837             ast->Move(symbol.pointerExternal, curExternal.prev);
2838          }
2839
2840          if(curExternal)
2841             symbol.id = curExternal.symbol.idCode;
2842       }
2843    }
2844    return (symbol && symbol._import && function.module != privateModule && function.module.importType != staticImport) ? true : false;
2845 }
2846
2847 void DeclareGlobalData(GlobalData data)
2848 {
2849    Symbol symbol = data.symbol;
2850    if(curExternal && (!symbol || symbol.id > curExternal.symbol.idCode))
2851    {
2852       if(inCompiler)
2853       {
2854          if(!symbol)
2855             symbol = data.symbol = Symbol { };
2856       }
2857       if(!data.dataType)
2858          data.dataType = ProcessTypeString(data.dataTypeString, false);
2859       DeclareType(data.dataType, true, true);
2860       if(inCompiler)
2861       {
2862          if(!symbol.pointerExternal)
2863          {
2864             // We need a declaration here :)
2865             Declaration decl;
2866             OldList * specifiers, * declarators;
2867             Declarator d;
2868             External external;
2869
2870             specifiers = MkList();
2871             declarators = MkList();
2872
2873             ListAdd(specifiers, MkSpecifier(EXTERN));
2874             d = MkDeclaratorIdentifier(MkIdentifier(data.fullName));
2875             d = SpecDeclFromString(data.dataTypeString, specifiers, d);
2876
2877             ListAdd(declarators, MkInitDeclarator(d, null));
2878
2879             decl = MkDeclaration(specifiers, declarators);
2880             external = MkExternalDeclaration(decl);
2881             if(curExternal)
2882                ast->Insert(curExternal.prev, external);
2883             external.symbol = symbol;
2884             symbol.pointerExternal = external;
2885          }
2886          else
2887          {
2888             // Move declaration higher...
2889             ast->Move(symbol.pointerExternal, curExternal.prev);
2890          }
2891
2892          if(curExternal)
2893             symbol.id = curExternal.symbol.idCode;
2894       }
2895    }
2896 }
2897
2898 class Conversion : struct
2899 {
2900    Conversion prev, next;
2901    Property convert;
2902    bool isGet;
2903    Type resultType;
2904 };
2905
2906 public bool MatchTypes(Type source, Type dest, OldList conversions, Class owningClassSource, Class owningClassDest, bool doConversion, bool enumBaseType, bool acceptReversedParams, bool isConversionExploration)
2907 {
2908    if(source && dest)
2909    {
2910       // Property convert;
2911
2912       if(source.kind == templateType && dest.kind != templateType)
2913       {
2914          Type type = ProcessTemplateParameterType(source.templateParameter);
2915          if(type) source = type;
2916       }
2917
2918       if(dest.kind == templateType && source.kind != templateType)
2919       {
2920          Type type = ProcessTemplateParameterType(dest.templateParameter);
2921          if(type) dest = type;
2922       }
2923
2924       if((dest.classObjectType == typedObject && source.classObjectType != anyObject) || (dest.classObjectType == anyObject && source.classObjectType != typedObject))
2925       {
2926          return true;
2927       }
2928       
2929       if(source.classObjectType == anyObject && dest.classObjectType != typedObject)
2930       {
2931          return true;
2932       }
2933       
2934       if((dest.kind == structType && source.kind == structType) ||
2935          (dest.kind == unionType && source.kind == unionType))
2936       {
2937          if((dest.enumName && source.enumName && !strcmp(dest.enumName, source.enumName)) ||
2938              (source.members.first && source.members.first == dest.members.first))
2939             return true;
2940       }
2941
2942       if(dest.kind == ellipsisType && source.kind != voidType)
2943          return true;
2944
2945       if(dest.kind == pointerType && dest.type.kind == voidType &&
2946          ((source.kind == classType && (!source._class || !source._class.registered || source._class.registered.type == structClass || source._class.registered.type == normalClass || source._class.registered.type == noHeadClass || source._class.registered.type == systemClass))
2947          || source.kind == subClassType || source.kind == pointerType || source.kind == arrayType || source.kind == functionType || source.kind == thisClassType)
2948
2949          /*source.kind != voidType && source.kind != structType && source.kind != unionType  */
2950       
2951          /*&& (source.kind != classType /*|| source._class.registered.type != structClass)*/)
2952          return true;
2953       if(!isConversionExploration && source.kind == pointerType && source.type.kind == voidType &&
2954          ((dest.kind == classType && (!dest._class || !dest._class.registered || dest._class.registered.type == structClass || dest._class.registered.type == normalClass || dest._class.registered.type == noHeadClass || dest._class.registered.type == systemClass))
2955          || dest.kind == subClassType || dest.kind == pointerType || dest.kind == arrayType || dest.kind == functionType || dest.kind == thisClassType)
2956
2957          /* dest.kind != voidType && dest.kind != structType && dest.kind != unionType  */
2958
2959          /*&& (dest.kind != classType || dest._class.registered.type != structClass)*/)
2960          return true;
2961
2962       if(((source.kind == classType && dest.kind == classType) || (source.kind == subClassType && dest.kind == subClassType)) && source._class)
2963       {
2964          if(source._class.registered && source._class.registered.type == unitClass)
2965          {
2966             if(conversions != null)
2967             {
2968                if(source._class.registered == dest._class.registered)
2969                   return true;
2970             }
2971             else
2972             {
2973                Class sourceBase, destBase;
2974                for(sourceBase = source._class.registered; sourceBase && sourceBase.base.type != systemClass; sourceBase = sourceBase.base);
2975                for(destBase = dest._class.registered; destBase && destBase.base.type != systemClass; destBase = destBase.base);
2976                if(sourceBase == destBase)
2977                   return true;
2978             }
2979          }
2980          // Don't match enum inheriting from other enum if resolving enumeration values
2981          // TESTING: !dest.classObjectType
2982          else if(source._class && dest._class && (dest.classObjectType == source.classObjectType || !dest.classObjectType) &&
2983             (enumBaseType || 
2984                (!source._class.registered || source._class.registered.type != enumClass) || 
2985                (!dest._class.registered || dest._class.registered.type != enumClass)) && eClass_IsDerived(source._class.registered, dest._class.registered))
2986             return true;
2987          else
2988          {
2989             // Added this so that DefinedColor = Color doesn't go through ColorRGB property
2990             if(enumBaseType && 
2991                dest._class && dest._class.registered && dest._class.registered.type == enumClass &&
2992                source._class && source._class.registered && source._class.registered.type != enumClass)
2993             {
2994                if(eClass_IsDerived(dest._class.registered, source._class.registered))
2995                {
2996                   return true;
2997                }
2998             }
2999          }
3000       }
3001
3002       // JUST ADDED THIS...
3003       if(source.kind == subClassType && dest.kind == classType && dest._class && !strcmp(dest._class.string, "ecere::com::Class"))
3004          return true;
3005
3006       if(doConversion)
3007       {
3008          // Just added this for Straight conversion of ColorAlpha => Color
3009          if(source.kind == classType)
3010          {
3011             Class _class;
3012             for(_class = source._class ? source._class.registered : null; _class; _class = _class.base)
3013             {
3014                Property convert;
3015                for(convert = _class.conversions.first; convert; convert = convert.next)
3016                {
3017                   if(convert.memberAccess == publicAccess || _class.module == privateModule)
3018                   {
3019                      Conversion after = (conversions != null) ? conversions.last : null;
3020
3021                      if(!convert.dataType)
3022                         convert.dataType = ProcessTypeString(convert.dataTypeString, false);
3023                      if(MatchTypes(convert.dataType, dest, conversions, null, null, false, true, false, true))
3024                      {
3025                         if(!conversions && !convert.Get)
3026                            return true;
3027                         else if(conversions != null)
3028                         {
3029                            if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class && 
3030                               convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base && 
3031                               (dest.kind != classType || dest._class.registered != _class.base))
3032                               return true;
3033                            else
3034                            {
3035                               Conversion conv { convert = convert, isGet = true };
3036                               // conversions.Add(conv);
3037                               conversions.Insert(after, conv);
3038                               return true;
3039                            }
3040                         }
3041                      }
3042                   }
3043                }
3044             }
3045          }
3046
3047          // MOVING THIS??
3048
3049          if(dest.kind == classType)
3050          {
3051             Class _class;
3052             for(_class = dest._class ? dest._class.registered : null; _class; _class = _class.base)
3053             {
3054                Property convert;
3055                for(convert = _class.conversions.first; convert; convert = convert.next)
3056                {
3057                   if(convert.memberAccess == publicAccess || _class.module == privateModule)
3058                   {
3059                      // Conversion after = (conversions != null) ? conversions.last : null;
3060
3061                      if(!convert.dataType)
3062                         convert.dataType = ProcessTypeString(convert.dataTypeString, false);
3063                      // Just added this equality check to prevent recursion.... Make it safer?
3064                      // Changed enumBaseType to false here to prevent all int-compatible enums to show up in AnchorValues
3065                      if(convert.dataType != dest && MatchTypes(source, convert.dataType, conversions, null, null, true, false /*true*/, false, true))
3066                      {
3067                         if(!conversions && !convert.Set)
3068                            return true;
3069                         else if(conversions != null)
3070                         {
3071                            if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class && 
3072                               convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base && 
3073                               (source.kind != classType || source._class.registered != _class.base))
3074                               return true;
3075                            else
3076                            {
3077                               // *** Testing this! ***
3078                               Conversion conv { convert = convert };
3079                               conversions.Add(conv);
3080                               //conversions.Insert(after, conv);
3081                               return true;
3082                            }
3083                         }
3084                      }
3085                   }
3086                }
3087             }
3088             /*if(dest._class.registered && !strcmp(dest._class.registered.name, "bool"))
3089             {
3090                if(source.kind != voidType && source.kind != structType && source.kind != unionType && 
3091                   (source.kind != classType || source._class.registered.type != structClass))
3092                   return true;
3093             }*/
3094
3095             // TESTING THIS... IS THIS OK??
3096             if(enumBaseType && dest._class && dest._class.registered && dest._class.registered.type == enumClass)
3097             {
3098                if(!dest._class.registered.dataType)
3099                   dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
3100                // Only support this for classes...
3101                if(dest._class.registered.dataType.kind == classType || source.truth || dest.truth/* ||
3102                   !strcmp(dest._class.registered.name, "bool") || (source.kind == classType && !strcmp(source._class.string, "bool"))*/)
3103                {
3104                   if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
3105                   {
3106                      return true;
3107                   }
3108                }
3109             }
3110          }
3111
3112          // Moved this lower
3113          if(source.kind == classType)
3114          {
3115             Class _class;
3116             for(_class = source._class ? source._class.registered : null; _class; _class = _class.base)
3117             {
3118                Property convert;
3119                for(convert = _class.conversions.first; convert; convert = convert.next)
3120                {
3121                   if(convert.memberAccess == publicAccess || _class.module == privateModule)
3122                   {
3123                      Conversion after = (conversions != null) ? conversions.last : null;
3124
3125                      if(!convert.dataType)
3126                         convert.dataType = ProcessTypeString(convert.dataTypeString, false);
3127                      if(convert.dataType != source && MatchTypes(convert.dataType, dest, conversions, null, null, true, true, false, true))
3128                      {
3129                         if(!conversions && !convert.Get)
3130                            return true;
3131                         else if(conversions != null)
3132                         {
3133                            if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class && 
3134                               convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base && 
3135                               (dest.kind != classType || dest._class.registered != _class.base))
3136                               return true;
3137                            else
3138                            {
3139                               Conversion conv { convert = convert, isGet = true };
3140
3141                               // conversions.Add(conv);
3142                               conversions.Insert(after, conv);
3143                               return true;
3144                            }
3145                         }
3146                      }
3147                   }
3148                }
3149             }
3150
3151             // TESTING THIS... IS THIS OK??
3152             if(enumBaseType && source._class && source._class.registered && source._class.registered.type == enumClass)
3153             {
3154                if(!source._class.registered.dataType)
3155                   source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3156                if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, true, false, false))
3157                {
3158                   return true;
3159                }
3160             }
3161          }
3162       }
3163
3164       if(source.kind == classType || source.kind == subClassType)
3165          ;
3166       else if(dest.kind == source.kind && 
3167          (dest.kind != structType && dest.kind != unionType &&
3168           dest.kind != functionType && dest.kind != arrayType && dest.kind != pointerType && dest.kind != methodType))
3169           return true;
3170       // RECENTLY ADDED THESE
3171       else if(dest.kind == doubleType && source.kind == floatType)
3172          return true;
3173       else if(dest.kind == shortType && source.kind == charType)
3174          return true;
3175       else if(dest.kind == intType && (source.kind == shortType || source.kind == charType))
3176          return true;
3177       else if(dest.kind == int64Type && (source.kind == shortType || source.kind == charType || source.kind == intType))
3178          return true;
3179       else if(source.kind == enumType &&
3180          (dest.kind == intType || dest.kind == shortType || dest.kind == charType || dest.kind == longType || dest.kind == int64Type))
3181           return true;
3182       else if(dest.kind == enumType &&
3183          (source.kind == intType || source.kind == shortType || source.kind == charType || source.kind == longType || dest.kind == int64Type))
3184           return true;
3185       else if((dest.kind == functionType || (dest.kind == pointerType && dest.type.kind == functionType) || dest.kind == methodType) && 
3186               ((source.kind == functionType || (source.kind == pointerType && source.type.kind == functionType) || source.kind == methodType)))
3187       {
3188          Type paramSource, paramDest;
3189
3190          if(dest.kind == methodType)     
3191             owningClassDest = dest.methodClass ? dest.methodClass : dest.method._class;
3192          if(source.kind == methodType)   
3193             owningClassSource = source.methodClass ? source.methodClass : source.method._class;
3194
3195          if(dest.kind == pointerType && dest.type.kind == functionType) dest = dest.type;
3196          if(source.kind == pointerType && source.type.kind == functionType) source = source.type;
3197          if(dest.kind == methodType) 
3198             dest = dest.method.dataType;
3199          if(source.kind == methodType) 
3200             source = source.method.dataType;
3201
3202          paramSource = source.params.first;
3203          if(paramSource && paramSource.kind == voidType) paramSource = null;
3204          paramDest = dest.params.first;
3205          if(paramDest && paramDest.kind == voidType) paramDest = null;
3206
3207      
3208          if((dest.staticMethod || (!dest.thisClass && !owningClassDest)) && 
3209             !(source.staticMethod || (!source.thisClass && !owningClassSource)))
3210          {
3211             // Source thisClass must be derived from destination thisClass
3212             if(!paramDest || (!(paramDest.kind == pointerType && paramDest.type && paramDest.type.kind == voidType) && (paramDest.kind != classType ||
3213                !eClass_IsDerived(source.thisClass ? source.thisClass.registered : owningClassSource,paramDest._class.registered))))
3214             {
3215                if(paramDest && paramDest.kind == classType)
3216                   Compiler_Error($"method class must be derived from %s\n", paramDest._class.string);
3217                else
3218                   Compiler_Error($"method class should not take an object\n");
3219                return false;
3220             }
3221             paramDest = paramDest.next;
3222          }
3223          else if(!dest.staticMethod && (dest.thisClass || owningClassDest))
3224          {
3225             if((source.staticMethod || (!source.thisClass && !owningClassSource)))
3226             {
3227                if(dest.thisClass)
3228                {
3229                   if(!paramSource || paramSource.kind != classType || !eClass_IsDerived(paramSource._class.registered,dest.thisClass.registered))
3230                   {
3231                      Compiler_Error($"method class must be derived from %s\n", dest.thisClass.string);
3232                      return false;
3233                   }
3234                }
3235                else
3236                {
3237                   // THIS WAS BACKWARDS:
3238                   // if(!paramSource || paramSource.kind != classType || (owningClassDest && !eClass_IsDerived(owningClassDest, paramSource._class.registered)))
3239                   if(!paramSource || paramSource.kind != classType || (owningClassDest && !eClass_IsDerived(paramSource._class.registered, owningClassDest)))
3240                   {
3241                      if(owningClassDest)
3242                        Compiler_Error($"%s expected to be derived from method class\n", owningClassDest.fullName);
3243                      else
3244                         Compiler_Error($"overriding class expected to be derived from method class\n");      
3245                      return false;
3246                   }
3247                }
3248                paramSource = paramSource.next;
3249             }
3250             else
3251             {
3252                if(dest.thisClass)
3253                {
3254                   // Source thisClass must be derived from destination thisClass
3255                   if(!eClass_IsDerived(source.thisClass ? source.thisClass.registered : owningClassSource, dest.thisClass.registered))
3256                   {
3257                      Compiler_Error($"method class must be derived from %s\n", dest.thisClass.string);
3258                      return false;
3259                   }
3260                }
3261                else
3262                {
3263                   // THIS WAS BACKWARDS TOO??
3264                   // if(source.thisClass && owningClassDest && !eClass_IsDerived(owningClassDest, source.thisClass.registered))
3265                   if(source.thisClass && source.thisClass.registered && owningClassDest && !eClass_IsDerived(source.thisClass.registered, owningClassDest))
3266                   {
3267                      //if(owningClass)
3268                         Compiler_Error($"%s expected to be derived from method class\n", /*owningClass.name*/ source.thisClass.registered.fullName);
3269                      //else
3270                         //Compiler_Error($"overriding class expected to be derived from method class\n");      
3271                      return false;
3272                   }
3273                }
3274             }
3275          }
3276
3277
3278          // Source return type must be derived from destination return type
3279          if(!MatchTypes(source.returnType, dest.returnType, null, null, null, true, true, false, false))
3280          {
3281             Compiler_Warning($"incompatible return type for function\n");
3282             return false;
3283          }
3284
3285          // Check parameters
3286       
3287          for(; paramDest; paramDest = paramDest.next)
3288          {
3289             if(!paramSource)
3290             {
3291                //Compiler_Warning($"not enough parameters\n");
3292                Compiler_Error($"not enough parameters\n");
3293                return false;
3294             }
3295             {
3296                Type paramDestType = paramDest;
3297                Type paramSourceType = paramSource;
3298                Type type = paramDestType;
3299
3300                // *** WORKING CODE: TESTING THIS HERE FOR TEMPLATES ***
3301                if(paramDest.kind == templateType && paramDest.templateParameter.type == TemplateParameterType::type && owningClassSource &&
3302                   paramSource.kind != templateType)
3303                {
3304                   int id = 0;
3305                   ClassTemplateParameter curParam;
3306                   Class sClass;
3307                   for(sClass = owningClassSource; sClass; sClass = sClass.base)
3308                   {
3309                      id = 0;
3310                      if(sClass.templateClass) sClass = sClass.templateClass;
3311                      for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3312                      {
3313                         if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
3314                         {
3315                            for(sClass = sClass.base; sClass; sClass = sClass.base)
3316                            {
3317                               if(sClass.templateClass) sClass = sClass.templateClass;
3318                               id += sClass.templateParams.count;
3319                            }
3320                            break;
3321                         }
3322                         id++;
3323                      }
3324                      if(curParam) break;
3325                   }
3326
3327                   if(curParam)
3328                   {
3329                      ClassTemplateArgument arg = owningClassSource.templateArgs[id];
3330                      paramDestType = type = ProcessTypeString(arg.dataTypeString, false);
3331                   }
3332                }
3333
3334                // paramDest must be derived from paramSource
3335                if(!MatchTypes(paramDestType, paramSourceType, null, null, null, true, true, false, false) && 
3336                   (!acceptReversedParams || !MatchTypes(paramSourceType, paramDestType, null, null, null, true, true, false, false)))
3337                {
3338                   char type[1024];
3339                   type[0] = 0;
3340                   PrintType(paramDest, type, false, true);
3341                   Compiler_Warning($"incompatible parameter %s (expected %s)\n", paramSource.name, type);
3342                   
3343                   if(paramDestType != paramDest)
3344                      FreeType(paramDestType);
3345                   return false;
3346                }
3347                if(paramDestType != paramDest)
3348                   FreeType(paramDestType);
3349             }
3350          
3351             paramSource = paramSource.next;
3352          }
3353          if(paramSource)
3354          {
3355             Compiler_Error($"too many parameters\n");
3356             return false;
3357          }
3358          return true;
3359       }
3360       else if((dest.kind == functionType || (dest.kind == pointerType && dest.type.kind == functionType) || dest.kind == methodType) && (source.kind == pointerType && source.type.kind == voidType))
3361       {
3362          return true;
3363       }
3364       else if((dest.kind == pointerType || dest.kind == arrayType) && 
3365          (source.kind == arrayType || source.kind == pointerType))
3366       {
3367          if(MatchTypes(source.type, dest.type, null, null, null, true, true, false, false))
3368             return true;
3369       }
3370    }
3371    return false;
3372 }
3373
3374 static void FreeConvert(Conversion convert)
3375 {
3376    if(convert.resultType)
3377       FreeType(convert.resultType);
3378 }
3379
3380 bool MatchWithEnums_NameSpace(NameSpace nameSpace, Expression sourceExp, Type dest, 
3381                               char * string, OldList conversions)
3382 {
3383    BTNamedLink link;
3384
3385    for(link = (BTNamedLink)nameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
3386    {
3387       Class _class = link.data;
3388       if(_class.type == enumClass)
3389       {
3390          OldList converts { };
3391          Type type { };
3392          type.kind = classType;
3393
3394          if(!_class.symbol)
3395             _class.symbol = FindClass(_class.fullName);
3396          type._class = _class.symbol;
3397
3398          if(MatchTypes(type, dest, &converts, null, null, true, false, false, false))
3399          {
3400             NamedLink value;
3401             Class enumClass = eSystem_FindClass(privateModule, "enum");
3402             if(enumClass)
3403             {
3404                Class baseClass;
3405                for(baseClass = _class ; baseClass && baseClass.type == ClassType::enumClass; baseClass = baseClass.base)
3406                {
3407                   EnumClassData e = ACCESS_CLASSDATA(baseClass, enumClass);
3408                   for(value = e.values.first; value; value = value.next)
3409                   {
3410                      if(!strcmp(value.name, string))
3411                         break;
3412                   }
3413                   if(value)
3414                   {
3415                      FreeExpContents(sourceExp);
3416                      FreeType(sourceExp.expType);
3417
3418                      sourceExp.isConstant = true;
3419                      sourceExp.expType = MkClassType(baseClass.fullName);
3420                      //if(inCompiler)
3421                      {
3422                         char constant[256];
3423                         sourceExp.type = constantExp;
3424                         if(!strcmp(baseClass.dataTypeString, "int"))
3425                            sprintf(constant, "%d",value.data);
3426                         else
3427                            sprintf(constant, "0x%X",value.data);
3428                         sourceExp.constant = CopyString(constant);
3429                         //for(;baseClass.base && baseClass.base.type != systemClass; baseClass = baseClass.base);
3430                      }
3431                   
3432                      while(converts.first)
3433                      {
3434                         Conversion convert = converts.first;
3435                         converts.Remove(convert);
3436                         conversions.Add(convert);
3437                      }
3438                      delete type;
3439                      return true;
3440                   }
3441                }
3442             }
3443          }
3444          if(converts.first)
3445             converts.Free(FreeConvert);
3446          delete type;
3447       }
3448    }
3449    for(nameSpace = (NameSpace *)nameSpace.nameSpaces.first; nameSpace != null; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
3450       if(MatchWithEnums_NameSpace(nameSpace, sourceExp, dest, string, conversions))
3451          return true;
3452    return false;
3453 }
3454
3455 public bool ModuleVisibility(Module searchIn, Module searchFor)
3456 {
3457    SubModule subModule;
3458    
3459    if(searchFor == searchIn)
3460       return true;
3461
3462    for(subModule = searchIn.modules.first; subModule; subModule = subModule.next)
3463    {
3464       if(subModule.importMode == publicAccess || searchIn == searchIn.application)
3465       {
3466          if(ModuleVisibility(subModule.module, searchFor))
3467             return true;
3468       }
3469    }
3470    return false;
3471 }
3472
3473 bool MatchWithEnums_Module(Module mainModule, Expression sourceExp, Type dest, char * string, OldList conversions)
3474 {
3475    Module module;
3476
3477    if(MatchWithEnums_NameSpace(mainModule.application.systemNameSpace, sourceExp, dest, string, conversions))
3478       return true;
3479    if(MatchWithEnums_NameSpace(mainModule.application.privateNameSpace, sourceExp, dest, string, conversions))
3480       return true;
3481    if(MatchWithEnums_NameSpace(mainModule.application.publicNameSpace, sourceExp, dest, string, conversions))
3482       return true;
3483
3484    for(module = mainModule.application.allModules.first; module; module = module.next)
3485    {
3486       if(ModuleVisibility(mainModule, module) && MatchWithEnums_NameSpace(module.publicNameSpace, sourceExp, dest, string, conversions))
3487          return true;
3488    }
3489    return false;
3490 }
3491
3492 bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, bool skipUnitBla)
3493 {
3494    Type source = sourceExp.expType;
3495    Type realDest = dest;
3496
3497    if(dest.kind == pointerType && sourceExp.type == constantExp && !strtoul(sourceExp.constant, null, 0))
3498       return true;
3499
3500    if(!skipUnitBla && source && dest && source.kind == classType && dest.kind == classType)
3501    {
3502        if(source._class && source._class.registered && source._class.registered.type == unitClass)
3503        {
3504           Class sourceBase, destBase;
3505           for(sourceBase = source._class.registered; 
3506               sourceBase && sourceBase.base && sourceBase.base.type != systemClass;
3507               sourceBase = sourceBase.base);
3508           for(destBase = dest._class.registered; 
3509               destBase && destBase.base && destBase.base.type != systemClass;
3510               destBase = destBase.base);
3511           //if(source._class.registered == dest._class.registered)
3512           if(sourceBase == destBase)
3513              return true;
3514        }
3515    }
3516
3517    if(source)
3518    {
3519       OldList * specs;
3520       bool flag = false;
3521       int64 value = MAXINT;
3522
3523       source.refCount++;
3524       dest.refCount++;
3525
3526       if(sourceExp.type == constantExp)
3527       {
3528          if(source.isSigned)
3529             value = strtoll(sourceExp.constant, null, 0);
3530          else
3531             value = strtoull(sourceExp.constant, null, 0);
3532       }
3533       else if(sourceExp.type == opExp && sourceExp.op.op == '-' && !sourceExp.op.exp1 && sourceExp.op.exp2 && sourceExp.op.exp2.type == constantExp)
3534       {
3535          if(source.isSigned)
3536             value = -strtoll(sourceExp.op.exp2.constant, null, 0);
3537          else
3538             value = -strtoull(sourceExp.op.exp2.constant, null, 0);
3539       }
3540
3541       if(dest.kind != classType && source.kind == classType && source._class && source._class.registered && 
3542          !strcmp(source._class.registered.fullName, "ecere::com::unichar"))
3543       {
3544          FreeType(source);
3545          source = Type { kind = intType, isSigned = false, refCount = 1 };
3546       }
3547
3548       if(dest.kind == classType)
3549       {
3550          Class _class = dest._class ? dest._class.registered : null;
3551
3552          if(_class && _class.type == unitClass)
3553          {
3554             if(source.kind != classType)
3555             {
3556                Type tempType { };
3557                Type tempDest, tempSource;
3558
3559                for(; _class.base.type != systemClass; _class = _class.base);
3560                tempSource = dest;
3561                tempDest = tempType;
3562
3563                tempType.kind = classType;
3564                if(!_class.symbol)
3565                   _class.symbol = FindClass(_class.fullName);
3566
3567                tempType._class = _class.symbol;
3568                tempType.truth = dest.truth;
3569                if(tempType._class)
3570                   MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
3571
3572                FreeType(sourceExp.expType);
3573                sourceExp.expType = dest; dest.refCount++;
3574
3575                //sourceExp.expType = MkClassType(_class.fullName);
3576                flag = true;            
3577
3578                delete tempType;
3579             }
3580          }
3581
3582
3583          // Why wasn't there something like this?
3584          if(_class && _class.type == bitClass && source.kind != classType)
3585          {
3586             if(!dest._class.registered.dataType)
3587                dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
3588             if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
3589             {
3590                FreeType(source);
3591                FreeType(sourceExp.expType);
3592                source = sourceExp.expType = MkClassType(dest._class.string);
3593                source.refCount++;
3594                
3595                //source.kind = classType;
3596                //source._class = dest._class;
3597             }
3598          }
3599
3600          // Adding two enumerations
3601          /*
3602          if(_class && _class.type == enumClass && source.kind == classType && source._class && source._class.registered && source._class.registered.type == enumClass)
3603          {
3604             if(!source._class.registered.dataType)
3605                source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3606             if(!dest._class.registered.dataType)
3607                dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
3608
3609             if(MatchTypes(source._class.registered.dataType, dest._class.registered.dataType, conversions, null, null, true, false, false))
3610             {
3611                FreeType(source);
3612                source = sourceExp.expType = MkClassType(dest._class.string);
3613                source.refCount++;
3614                
3615                //source.kind = classType;
3616                //source._class = dest._class;
3617             }
3618          }*/
3619
3620          if(_class && !strcmp(_class.fullName, "ecere::com::Class") && source.kind == pointerType && source.type && source.type.kind == charType && sourceExp.type == stringExp)
3621          {
3622             OldList * specs = MkList();
3623             Declarator decl;
3624             char string[1024];
3625
3626             ReadString(string, sourceExp.string);
3627             decl = SpecDeclFromString(string, specs, null);
3628
3629             FreeExpContents(sourceExp);
3630             FreeType(sourceExp.expType);
3631
3632             sourceExp.type = classExp;
3633             sourceExp._classExp.specifiers = specs;
3634             sourceExp._classExp.decl = decl;
3635             sourceExp.expType = dest;
3636             dest.refCount++;
3637
3638             FreeType(source);
3639             FreeType(dest);
3640             return true;
3641          }
3642       }
3643       else if(source.kind == classType)
3644       {
3645          Class _class = source._class ? source._class.registered : null;
3646
3647          if(_class && (_class.type == unitClass || !strcmp(_class.fullName, "bool") || /*_class.type == enumClass || */_class.type == bitClass ))  // TOCHECK: enumClass, bitClass is new here...
3648          {
3649             /*
3650             if(dest.kind != classType)
3651             {
3652                // Testing this simpler piece of code... (Broke Units Conversion to no unit Logic)
3653                if(!source._class.registered.dataType)
3654                   source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3655                
3656                FreeType(dest);
3657                dest = MkClassType(source._class.string);
3658                //if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, false, false))
3659                //   dest = MkClassType(source._class.string);
3660             }
3661             */
3662             
3663             if(dest.kind != classType)
3664             {
3665                Type tempType { };
3666                Type tempDest, tempSource;
3667
3668                if(!source._class.registered.dataType)
3669                   source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3670
3671                for(; _class.base.type != systemClass; _class = _class.base);
3672                tempDest = source;
3673                tempSource = tempType;
3674                tempType.kind = classType;
3675                tempType._class = FindClass(_class.fullName);
3676                tempType.truth = source.truth;
3677                tempType.classObjectType = source.classObjectType;
3678
3679                if(tempType._class)
3680                   MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
3681                
3682                // PUT THIS BACK TESTING UNITS?
3683                if(conversions.last)
3684                {
3685                   ((Conversion)(conversions.last)).resultType = dest;
3686                   dest.refCount++;
3687                }
3688                
3689                FreeType(sourceExp.expType);
3690                sourceExp.expType = MkClassType(_class.fullName);
3691                sourceExp.expType.truth = source.truth;
3692                sourceExp.expType.classObjectType = source.classObjectType;
3693
3694                // *** This if was commented out, put it back because "int a =^ Destroy()" shows up bool enum values in autocomplete ***
3695
3696                if(!sourceExp.destType)
3697                {
3698                   FreeType(sourceExp.destType);
3699                   sourceExp.destType = sourceExp.expType;
3700                   if(sourceExp.expType)
3701                      sourceExp.expType.refCount++;
3702                }
3703                //flag = true;
3704                //source = _class.dataType;
3705
3706
3707                // TOCHECK: TESTING THIS NEW CODE
3708                if(!_class.dataType)
3709                   _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3710                FreeType(dest);
3711                dest = MkClassType(source._class.string);
3712                dest.truth = source.truth;
3713                dest.classObjectType = source.classObjectType;
3714                
3715                FreeType(source);
3716                source = _class.dataType;
3717                source.refCount++;
3718
3719                delete tempType;
3720             }
3721          }
3722       }
3723
3724       if(!flag)
3725       {
3726          if(MatchTypes(source, dest, conversions, null, null, true, true, false, false))
3727          {
3728             FreeType(source);
3729             FreeType(dest);
3730             return true;
3731          }
3732       }
3733
3734       // Implicit Casts
3735       /*
3736       if(source.kind == classType)
3737       {
3738          Class _class = source._class.registered;
3739          if(_class.type == unitClass)
3740          {
3741             if(!_class.dataType)
3742                _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3743             source = _class.dataType;
3744          }
3745       }*/
3746
3747       if(dest.kind == classType)
3748       {
3749          Class _class = dest._class ? dest._class.registered : null;
3750          if(_class && !dest.truth && (_class.type == unitClass || !strcmp(_class.fullName, "bool") || 
3751             (/*_class.type == enumClass*/_class.type != structClass && !value && source.kind == intType) || _class.type == bitClass))   // TOCHECK: enumClass, bitClass is new here...
3752          {
3753             if(_class.type == normalClass || _class.type == noHeadClass)
3754             {
3755                Expression newExp { };
3756                *newExp = *sourceExp;
3757                if(sourceExp.destType) sourceExp.destType.refCount++;
3758                if(sourceExp.expType)  sourceExp.expType.refCount++;
3759                sourceExp.type = castExp;
3760                sourceExp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null));
3761                sourceExp.cast.exp = newExp;
3762                FreeType(sourceExp.expType);
3763                sourceExp.expType = null;
3764                ProcessExpressionType(sourceExp);
3765
3766                // In Debugger, this helps with addresses (e.g. null pointers) that end up casted to a void *: keeps a classType instead of a pointerType
3767                if(!inCompiler)
3768                {
3769                   FreeType(sourceExp.expType);
3770                   sourceExp.expType = dest;
3771                }
3772
3773                FreeType(source);
3774                if(inCompiler) FreeType(dest);
3775
3776                return true;
3777             }
3778
3779             if(!_class.dataType)
3780                _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3781             FreeType(dest);
3782             dest = _class.dataType;
3783             dest.refCount++;
3784          }
3785
3786          // Accept lower precision types for units, since we want to keep the unit type
3787          if(dest.kind == doubleType && 
3788             (source.kind == doubleType || source.kind == floatType || dest.kind == int64Type || source.kind == intType || source.kind == shortType ||
3789              source.kind == charType))
3790          {
3791             specs = MkListOne(MkSpecifier(DOUBLE));
3792          }
3793          else if(dest.kind == floatType && 
3794             (source.kind == floatType || dest.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType ||
3795             source.kind == doubleType))
3796          {
3797             specs = MkListOne(MkSpecifier(FLOAT));
3798          }
3799          else if(dest.kind == int64Type && (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType ||
3800             source.kind == floatType || source.kind == doubleType))
3801          {
3802             specs = MkList();
3803             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3804             ListAdd(specs, MkSpecifier(INT64));
3805          }
3806          else if(dest.kind == intType && (source.kind == intType || source.kind == shortType || source.kind == charType ||
3807             source.kind == floatType || source.kind == doubleType))
3808          {
3809             specs = MkList();
3810             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3811             ListAdd(specs, MkSpecifier(INT));
3812          }
3813          else if(dest.kind == shortType && (source.kind == shortType || source.kind == charType || source.kind == intType ||
3814             source.kind == floatType || source.kind == doubleType))
3815          {
3816             specs = MkList();
3817             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3818             ListAdd(specs, MkSpecifier(SHORT));
3819          }
3820          else if(dest.kind == charType && (source.kind == charType || source.kind == shortType || source.kind == intType ||
3821             source.kind == floatType || source.kind == doubleType))
3822          {
3823             specs = MkList();
3824             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3825             ListAdd(specs, MkSpecifier(CHAR));
3826          }
3827          else
3828          {
3829             FreeType(source);
3830             FreeType(dest);
3831             return false;
3832          }
3833       }
3834       else if(dest.kind == doubleType && 
3835          (source.kind == doubleType || source.kind == floatType || source.kind == int64Type || source.kind == intType || source.kind == enumType || source.kind == shortType ||
3836           source.kind == charType))
3837       {
3838          specs = MkListOne(MkSpecifier(DOUBLE));
3839       }
3840       else if(dest.kind == floatType && 
3841          (source.kind == floatType || source.kind == enumType || source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType))
3842       {
3843          specs = MkListOne(MkSpecifier(FLOAT));
3844       }
3845       else if(dest.kind == charType && (source.kind == charType || source.kind == enumType || source.kind == shortType || source.kind == intType) && 
3846          (dest.isSigned ? (value >= -128 && value <= 127) : (value >= 0 && value <= 255)))
3847       {
3848          specs = MkList();
3849          if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3850          ListAdd(specs, MkSpecifier(CHAR));
3851       }
3852       else if(dest.kind == shortType && (source.kind == enumType || source.kind == charType || source.kind == shortType || 
3853          (source.kind == intType && (dest.isSigned ? (value >= -32768 && value <= 32767) : (value >= 0 && value <= 65535)))))
3854       {
3855          specs = MkList();
3856          if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3857          ListAdd(specs, MkSpecifier(SHORT));
3858       }
3859       else if(dest.kind == intType && (source.kind == enumType || source.kind == shortType || source.kind == charType || source.kind == intType))
3860       {
3861          specs = MkList();
3862          if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3863          ListAdd(specs, MkSpecifier(INT));
3864       }
3865       else if(dest.kind == int64Type && (source.kind == enumType || source.kind == shortType || source.kind == charType || source.kind == intType || source.kind == int64Type))
3866       {
3867          specs = MkList();
3868          if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3869          ListAdd(specs, MkSpecifier(INT64));
3870       }
3871       else if(dest.kind == enumType && 
3872          (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType))
3873       {
3874          specs = MkListOne(MkEnum(MkIdentifier(dest.enumName), null));
3875       }
3876       else
3877       {
3878          FreeType(source);
3879          FreeType(dest);
3880          return false;
3881       }
3882
3883       if(!flag)
3884       {
3885          Expression newExp { };
3886          *newExp = *sourceExp;
3887          newExp.prev = null;
3888          newExp.next = null;
3889          if(sourceExp.destType) sourceExp.destType.refCount++;
3890          if(sourceExp.expType)  sourceExp.expType.refCount++;
3891
3892          sourceExp.type = castExp;
3893          if(realDest.kind == classType)
3894          {
3895             sourceExp.cast.typeName = QMkClass(realDest._class.string, null);
3896             FreeList(specs, FreeSpecifier);
3897          }
3898          else
3899             sourceExp.cast.typeName = MkTypeName(specs, null);
3900          if(newExp.type == opExp)
3901          {
3902             sourceExp.cast.exp = MkExpBrackets(MkListOne(newExp));
3903          }
3904          else
3905             sourceExp.cast.exp = newExp;
3906          
3907          FreeType(sourceExp.expType);
3908          sourceExp.expType = null;
3909          ProcessExpressionType(sourceExp);
3910       }
3911       else
3912          FreeList(specs, FreeSpecifier);
3913
3914       FreeType(dest);
3915       FreeType(source);
3916       return true;
3917    }
3918    else
3919    {
3920       while((sourceExp.type == bracketsExp || sourceExp.type == extensionExpressionExp) && sourceExp.list) sourceExp = sourceExp.list->last;
3921       if(sourceExp.type == identifierExp)
3922       {
3923          Identifier id = sourceExp.identifier;
3924          if(dest.kind == classType)
3925          {
3926             if(dest._class && dest._class.registered && dest._class.registered.type == enumClass)
3927             {
3928                Class _class = dest._class.registered;
3929                Class enumClass = eSystem_FindClass(privateModule, "enum");
3930                if(enumClass)
3931                {
3932                   for( ; _class && _class.type == ClassType::enumClass; _class = _class.base)
3933                   {
3934                      NamedLink value;
3935                      EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
3936                      for(value = e.values.first; value; value = value.next)
3937                      {
3938                         if(!strcmp(value.name, id.string))
3939                            break;
3940                      }
3941                      if(value)
3942                      {
3943                         FreeExpContents(sourceExp);
3944                         FreeType(sourceExp.expType);
3945
3946                         sourceExp.isConstant = true;
3947                         sourceExp.expType = MkClassType(_class.fullName);
3948                         //if(inCompiler)
3949                         {
3950                            char constant[256];
3951                            sourceExp.type = constantExp;
3952                            if(/*_class && */_class.dataTypeString && !strcmp(_class.dataTypeString, "int")) // _class cannot be null here!
3953                               sprintf(constant, "%d",value.data);
3954                            else
3955                               sprintf(constant, "0x%X",value.data);
3956                            sourceExp.constant = CopyString(constant);
3957                            //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
3958                         }
3959                         return true;
3960                      }
3961                   }
3962                }
3963             }
3964          }
3965
3966          // Loop through all enum classes
3967          if(dest.classObjectType != typedObject && dest.kind == classType /*!= ellipsisType */&& MatchWithEnums_Module(privateModule, sourceExp, dest, id.string, conversions))
3968             return true;
3969       }
3970    }
3971    return false;
3972 }
3973
3974 #define TERTIARY(o, name, m, t, p) \
3975    static bool name(Expression exp, Operand op1, Operand op2, Operand op3)   \
3976    {                                                              \
3977       exp.type = constantExp;                                    \
3978       exp.string = p(op1.m ? op2.m : op3.m);                     \
3979       if(!exp.expType) \
3980          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
3981       return true;                                                \
3982    }
3983
3984 #define BINARY(o, name, m, t, p) \
3985    static bool name(Expression exp, Operand op1, Operand op2)   \
3986    {                                                              \
3987       t value2 = op2.m;                                           \
3988       exp.type = constantExp;                                    \
3989       exp.string = p(op1.m o value2);                     \
3990       if(!exp.expType) \
3991          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
3992       return true;                                                \
3993    }
3994
3995 #define BINARY_DIVIDE(o, name, m, t, p) \
3996    static bool name(Expression exp, Operand op1, Operand op2)   \
3997    {                                                              \
3998       t value2 = op2.m;                                           \
3999       exp.type = constantExp;                                    \
4000       exp.string = p(value2 ? (op1.m o value2) : 0);             \
4001       if(!exp.expType) \
4002          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
4003       return true;                                                \
4004    }
4005
4006 #define UNARY(o, name, m, t, p) \
4007    static bool name(Expression exp, Operand op1)                \
4008    {                                                              \
4009       exp.type = constantExp;                                    \
4010       exp.string = p(o op1.m);                                   \
4011       if(!exp.expType) \
4012          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
4013       return true;                                                \
4014    }
4015
4016 #define OPERATOR_ALL(macro, o, name) \
4017    macro(o, Int##name, i, int, PrintInt) \
4018    macro(o, UInt##name, ui, unsigned int, PrintUInt) \
4019    macro(o, Short##name, s, short, PrintShort) \
4020    macro(o, UShort##name, us, unsigned short, PrintUShort) \
4021    macro(o, Char##name, c, char, PrintChar) \
4022    macro(o, UChar##name, uc, unsigned char, PrintUChar) \
4023    macro(o, Float##name, f, float, PrintFloat) \
4024    macro(o, Double##name, d, double, PrintDouble)
4025
4026 #define OPERATOR_INTTYPES(macro, o, name) \
4027    macro(o, Int##name, i, int, PrintInt) \
4028    macro(o, UInt##name, ui, unsigned int, PrintUInt) \
4029    macro(o, Short##name, s, short, PrintShort) \
4030    macro(o, UShort##name, us, unsigned short, PrintUShort) \
4031    macro(o, Char##name, c, char, PrintChar) \
4032    macro(o, UChar##name, uc, unsigned char, PrintUChar)
4033
4034
4035 // binary arithmetic
4036 OPERATOR_ALL(BINARY, +, Add)
4037 OPERATOR_ALL(BINARY, -, Sub)
4038 OPERATOR_ALL(BINARY, *, Mul)
4039 OPERATOR_ALL(BINARY_DIVIDE, /, Div)
4040 OPERATOR_INTTYPES(BINARY_DIVIDE, %, Mod)
4041
4042 // unary arithmetic
4043 OPERATOR_ALL(UNARY, -, Neg)
4044
4045 // unary arithmetic increment and decrement
4046 OPERATOR_ALL(UNARY, ++, Inc)
4047 OPERATOR_ALL(UNARY, --, Dec)
4048
4049 // binary arithmetic assignment
4050 OPERATOR_ALL(BINARY, =, Asign)
4051 OPERATOR_ALL(BINARY, +=, AddAsign)
4052 OPERATOR_ALL(BINARY, -=, SubAsign)
4053 OPERATOR_ALL(BINARY, *=, MulAsign)
4054 OPERATOR_ALL(BINARY_DIVIDE, /=, DivAsign)
4055 OPERATOR_INTTYPES(BINARY_DIVIDE, %=, ModAsign)
4056
4057 // binary bitwise
4058 OPERATOR_INTTYPES(BINARY, &, BitAnd)
4059 OPERATOR_INTTYPES(BINARY, |, BitOr)
4060 OPERATOR_INTTYPES(BINARY, ^, BitXor)
4061 OPERATOR_INTTYPES(BINARY, <<, LShift)
4062 OPERATOR_INTTYPES(BINARY, >>, RShift)
4063
4064 // unary bitwise
4065 OPERATOR_INTTYPES(UNARY, ~, BitNot)
4066
4067 // binary bitwise assignment
4068 OPERATOR_INTTYPES(BINARY, &=, AndAsign)
4069 OPERATOR_INTTYPES(BINARY, |=, OrAsign)
4070 OPERATOR_INTTYPES(BINARY, ^=, XorAsign)
4071 OPERATOR_INTTYPES(BINARY, <<=, LShiftAsign)
4072 OPERATOR_INTTYPES(BINARY, >>=, RShiftAsign)
4073
4074 // unary logical negation
4075 OPERATOR_INTTYPES(UNARY, !, Not)
4076
4077 // binary logical equality
4078 OPERATOR_ALL(BINARY, ==, Equ)
4079 OPERATOR_ALL(BINARY, !=, Nqu)
4080
4081 // binary logical
4082 OPERATOR_ALL(BINARY, &&, And)
4083 OPERATOR_ALL(BINARY, ||, Or)
4084
4085 // binary logical relational
4086 OPERATOR_ALL(BINARY, >, Grt)
4087 OPERATOR_ALL(BINARY, <, Sma)
4088 OPERATOR_ALL(BINARY, >=, GrtEqu)
4089 OPERATOR_ALL(BINARY, <=, SmaEqu)
4090
4091 // tertiary condition operator
4092 OPERATOR_ALL(TERTIARY, ?, Cond)
4093
4094 //Add, Sub, Mul, Div, Mod,     , Neg,     Inc, Dec,    Asign, AddAsign, SubAsign, MulAsign, DivAsign, ModAsign,     BitAnd, BitOr, BitXor, LShift, RShift, BitNot,     AndAsign, OrAsign, XorAsign, LShiftAsign, RShiftAsign,     Not,     Equ, Nqu,     And, Or,     Grt, Sma, GrtEqu, SmaEqu
4095 #define OPERATOR_TABLE_ALL(name, type) \
4096     OpTable name##Ops = { type##Add, type##Sub, type##Mul, type##Div, type##Mod, \
4097                           type##Neg, \
4098                           type##Inc, type##Dec, \
4099                           type##Asign, type##AddAsign, type##SubAsign, type##MulAsign, type##DivAsign, type##ModAsign, \
4100                           type##BitAnd, type##BitOr, type##BitXor, type##LShift, type##RShift, \
4101                           type##BitNot, \
4102                           type##AndAsign, type##OrAsign, type##XorAsign, type##LShiftAsign, type##RShiftAsign, \
4103                           type##Not, \
4104                           type##Equ, type##Nqu, \
4105                           type##And, type##Or, \
4106                           type##Grt, type##Sma, type##GrtEqu, type##SmaEqu, type##Cond \
4107                         }; \
4108
4109 #define OPERATOR_TABLE_INTTYPES(name, type) \
4110     OpTable name##Ops = { type##Add, type##Sub, type##Mul, type##Div, null, \
4111                           type##Neg, \
4112                           type##Inc, type##Dec, \
4113                           type##Asign, type##AddAsign, type##SubAsign, type##MulAsign, type##DivAsign, null, \
4114                           null, null, null, null, null, \
4115                           null, \
4116                           null, null, null, null, null, \
4117                           null, \
4118                           type##Equ, type##Nqu, \
4119                           type##And, type##Or, \
4120                           type##Grt, type##Sma, type##GrtEqu, type##SmaEqu \
4121                         }; \
4122
4123 OPERATOR_TABLE_ALL(int, Int)
4124 OPERATOR_TABLE_ALL(uint, UInt)
4125 OPERATOR_TABLE_ALL(short, Short)
4126 OPERATOR_TABLE_ALL(ushort, UShort)
4127 OPERATOR_TABLE_INTTYPES(float, Float)
4128 OPERATOR_TABLE_INTTYPES(double, Double)
4129 OPERATOR_TABLE_ALL(char, Char)
4130 OPERATOR_TABLE_ALL(uchar, UChar)
4131
4132 //OpTable intOps =    {    IntAdd,    IntSub,    IntMul,    IntDiv,    IntMod,    IntExp,    IntNot,    IntBwn,    IntOr,    IntAnd,    IntEqu,    IntNqu,    IntGrt,    IntSma,    IntGrtEqu,    IntSmaEqu,    IntNeg,    IntLBitSft,    IntRBitSft };
4133 //OpTable uintOps =   {   UIntAdd,   UIntSub,   UIntMul,   UIntDiv,   UIntMod,   UIntExp,   UIntNot,   UIntBwn,   UIntOr,   UIntAnd,   UIntEqu,   UIntNqu,   UIntGrt,   UIntSma,   UIntGrtEqu,   UIntSmaEqu,   UIntNeg,   UIntLBitSft,   UIntRBitSft };
4134 //OpTable shortOps =  {  ShortAdd,  ShortSub,  ShortMul,  ShortDiv,  ShortMod,  ShortExp,  ShortNot,  ShortBwn,  ShortOr,  ShortAnd,  ShortEqu,  ShortNqu,  ShortGrt,  ShortSma,  ShortGrtEqu,  ShortSmaEqu,  ShortNeg,  ShortLBitSft,  ShortRBitSft };
4135 //OpTable ushortOps = { UShortAdd, UShortSub, UShortMul, UShortDiv, UShortMod, UShortExp, UShortNot, UShortBwn, UShortOr, UShortAnd, UShortEqu, UShortNqu, UShortGrt, UShortSma, UShortGrtEqu, UShortSmaEqu, UShortNeg, UShortLBitSft, UShortRBitSft };
4136 //OpTable floatOps =  {  FloatAdd,  FloatSub,  FloatMul,  FloatDiv,      null,      null,      null,      null,     null,      null,  FloatEqu,  FloatNqu,  FloatGrt,  FloatSma,  FloatGrtEqu,  FloatSmaEqu,  FloatNeg,          null,          null };
4137 //OpTable doubleOps = { DoubleAdd, DoubleSub, DoubleMul, DoubleDiv,      null,      null,      null,      null,     null,      null, DoubleEqu, DoubleNqu, DoubleGrt, DoubleSma, DoubleGrtEqu, DoubleSmaEqu, DoubleNeg,          null,          null };
4138 //OpTable charOps =   {   CharAdd,   CharSub,   CharMul,   CharDiv,   CharMod,   CharExp,   CharNot,   CharBwn,   CharOr,   CharAnd,   CharEqu,   CharNqu,   CharGrt,   CharSma,   CharGrtEqu,   CharSmaEqu,   CharNeg,   CharLBitSft,   CharRBitSft };
4139 //OpTable ucharOps =  {  UCharAdd,  UCharSub,  UCharMul,  UCharDiv,  UCharMod,  UCharExp,  UCharNot,  UCharBwn,  UCharOr,  UCharAnd,  UCharEqu,  UCharNqu,  UCharGrt,  UCharSma,  UCharGrtEqu,  UCharSmaEqu,  UCharNeg,  UCharLBitSft,  UCharRBitSft };
4140
4141 public void ReadString(char * output,  char * string)
4142 {
4143    int len = strlen(string);
4144    int c,d = 0;
4145    bool quoted = false, escaped = false;
4146    for(c = 0; c<len; c++)
4147    {
4148       char ch = string[c];
4149       if(escaped)
4150       {
4151          switch(ch)
4152          {
4153             case 'n': output[d] = '\n'; break;
4154             case 't': output[d] = '\t'; break;
4155             case 'a': output[d] = '\a'; break;
4156             case 'b': output[d] = '\b'; break;
4157             case 'f': output[d] = '\f'; break;
4158             case 'r': output[d] = '\r'; break;
4159             case 'v': output[d] = '\v'; break;
4160             case '\\': output[d] = '\\'; break;
4161             case '\"': output[d] = '\"'; break;
4162             default: output[d++] = '\\'; output[d] = ch;
4163             //default: output[d] = ch;
4164          }
4165          d++;
4166          escaped = false;
4167       }
4168       else 
4169       {
4170          if(ch == '\"') 
4171             quoted ^= true;
4172          else if(quoted)
4173          {
4174             if(ch == '\\')
4175                escaped = true;
4176             else
4177                output[d++] = ch;
4178          }
4179       }
4180    }
4181    output[d] = '\0';
4182 }
4183
4184 public Operand GetOperand(Expression exp)
4185 {
4186    Operand op { };
4187    Type type = exp.expType;
4188    if(type)
4189    {
4190       while(type.kind == classType && 
4191          type._class.registered && (type._class.registered.type == bitClass || type._class.registered.type == unitClass || type._class.registered.type == enumClass))
4192       {
4193          if(!type._class.registered.dataType)
4194             type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
4195          type = type._class.registered.dataType;
4196          
4197       }
4198       op.kind = type.kind;
4199       op.type = exp.expType;
4200       if(exp.isConstant && exp.type == constantExp)
4201       {
4202          switch(op.kind)
4203          {
4204             case charType:
4205             {
4206                if(exp.constant[0] == '\'')
4207                   op.c = exp.constant[1];
4208                else if(type.isSigned)
4209                {
4210                   op.c = (char)strtol(exp.constant, null, 0);
4211                   op.ops = charOps;
4212                }
4213                else
4214                {
4215                   op.uc = (unsigned char)strtoul(exp.constant, null, 0);
4216                   op.ops = ucharOps;
4217                }
4218                break;
4219             }
4220             case shortType:
4221                if(type.isSigned)
4222                {
4223                   op.s = (short)strtol(exp.constant, null, 0);
4224                   op.ops = shortOps;
4225                }
4226                else
4227                {
4228                   op.us = (unsigned short)strtoul(exp.constant, null, 0);
4229                   op.ops = ushortOps;
4230                }
4231                break;
4232             case intType:
4233             case longType:
4234                if(type.isSigned)
4235                {
4236                   op.i = (int)strtol(exp.constant, null, 0);
4237                   op.ops = intOps;
4238                }
4239                else
4240                {
4241                   op.ui = (unsigned int)strtoul(exp.constant, null, 0);
4242                   op.ops = uintOps;
4243                }
4244                op.kind = intType;
4245                break;
4246             case int64Type:
4247                if(type.isSigned)
4248                {
4249                   op.i64 = (int64)_strtoi64(exp.constant, null, 0);
4250                   op.ops = intOps;
4251                }
4252                else
4253                {
4254                   op.ui64 = (uint64)_strtoui64(exp.constant, null, 0);
4255                   op.ops = uintOps;
4256                }
4257                op.kind = intType;
4258                break;
4259             case floatType:
4260                op.f = (float)strtod(exp.constant, null);
4261                op.ops = floatOps;
4262                break;
4263             case doubleType:
4264                op.d = (double)strtod(exp.constant, null);
4265                op.ops = doubleOps;
4266                break;
4267             //case classType:    For when we have operator overloading...
4268             // Pointer additions
4269             //case functionType:
4270             case arrayType:
4271             case pointerType:
4272             case classType:
4273                op.p = (unsigned char *)strtoul(exp.constant, null, 0);
4274                op.kind = pointerType;
4275                op.ops = uintOps;
4276                // op.ptrSize = 
4277                break;
4278          }
4279       }
4280    }
4281    return op;
4282 }
4283
4284 static void UnusedFunction()
4285 {
4286    int a;
4287    a.OnGetString(0,0,0);
4288 }
4289 default:
4290 extern int __ecereVMethodID_class_OnGetString;
4291 public:
4292
4293 static void PopulateInstanceProcessMember(Instantiation inst, OldList * memberList, DataMember parentDataMember, uint offset)
4294 {
4295    DataMember dataMember;
4296    for(dataMember = parentDataMember.members.first; dataMember; dataMember = dataMember.next)
4297    {
4298       if(!dataMember.name && (dataMember.type == structMember || dataMember.type == unionMember))
4299          PopulateInstanceProcessMember(inst, memberList, dataMember, offset + dataMember.offset);
4300       else
4301       {
4302          Expression exp { };
4303          MemberInit member = MkMemberInit(MkListOne(MkIdentifier(dataMember.name)), MkInitializerAssignment(exp));
4304          Type type;
4305          void * ptr = inst.data + dataMember.offset + offset;
4306          char * result = null;
4307          exp.loc = member.loc = inst.loc;
4308          ((Identifier)member.identifiers->first).loc = inst.loc;
4309
4310          if(!dataMember.dataType)
4311             dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4312          type = dataMember.dataType;
4313          if(type.kind == classType)
4314          {
4315             Class _class = type._class.registered;
4316             if(_class.type == enumClass)
4317             {
4318                Class enumClass = eSystem_FindClass(privateModule, "enum");
4319                if(enumClass)
4320                {
4321                   EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
4322                   NamedLink item;
4323                   for(item = e.values.first; item; item = item.next)
4324                   {
4325                      if((int)item.data == *(int *)ptr)
4326                      {
4327                         result = item.name;
4328                         break;
4329                      }
4330                   }
4331                   if(result)
4332                   {
4333                      exp.identifier = MkIdentifier(result);
4334                      exp.type = identifierExp;
4335                      exp.destType = MkClassType(_class.fullName);
4336                      ProcessExpressionType(exp);
4337                   }
4338                }
4339             }
4340             if(_class.type == enumClass || _class.type == unitClass || _class.type == bitClass)
4341             {
4342                if(!_class.dataType)
4343                   _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4344                type = _class.dataType;
4345             }
4346          }
4347          if(!result)
4348          {
4349             switch(type.kind)
4350             {
4351                case floatType:
4352                {
4353                   FreeExpContents(exp);
4354
4355                   exp.constant = PrintFloat(*(float*)ptr);
4356                   exp.type = constantExp;
4357                   break;
4358                }
4359                case doubleType:
4360                {
4361                   FreeExpContents(exp);
4362
4363                   exp.constant = PrintDouble(*(double*)ptr);
4364                   exp.type = constantExp;
4365                   break;
4366                }
4367                case intType:
4368                {
4369                   FreeExpContents(exp);
4370
4371                   exp.constant = PrintInt(*(int*)ptr);
4372                   exp.type = constantExp;
4373                   break;
4374                }
4375                case int64Type:
4376                {
4377                   FreeExpContents(exp);
4378
4379                   exp.constant = PrintInt64(*(int64*)ptr);
4380                   exp.type = constantExp;
4381                   break;
4382                }
4383                default:
4384                   Compiler_Error($"Unhandled type populating instance\n");
4385             }
4386          }
4387          ListAdd(memberList, member);
4388       }
4389
4390       if(parentDataMember.type == unionMember)
4391          break;
4392    }
4393 }
4394
4395 void PopulateInstance(Instantiation inst)
4396 {
4397    Symbol classSym = inst._class.symbol; // FindClass(inst._class.name);
4398    Class _class = classSym.registered;
4399    DataMember dataMember;
4400    OldList * memberList = MkList();
4401    inst.members = MkListOne(MkMembersInitList(memberList));
4402    for(dataMember = _class.membersAndProperties.first; dataMember; dataMember = dataMember.next)
4403    {
4404       if(!dataMember.isProperty)
4405       {
4406          if(!dataMember.name && (dataMember.type == structMember || dataMember.type == unionMember))
4407             PopulateInstanceProcessMember(inst, memberList, dataMember, dataMember.offset);
4408          else
4409          {
4410             Expression exp { };
4411             MemberInit member = MkMemberInit(MkListOne(MkIdentifier(dataMember.name)), MkInitializerAssignment(exp));
4412             Type type;
4413             void * ptr = inst.data + dataMember.offset;
4414             char * result = null;
4415
4416             exp.loc = member.loc = inst.loc;
4417             ((Identifier)member.identifiers->first).loc = inst.loc;
4418
4419             if(!dataMember.dataType)
4420                dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4421             type = dataMember.dataType;
4422             if(type.kind == classType)
4423             {
4424                Class _class = type._class.registered;
4425                if(_class.type == enumClass)
4426                {
4427                   Class enumClass = eSystem_FindClass(privateModule, "enum");
4428                   if(enumClass)
4429                   {
4430                      EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
4431                      NamedLink item;
4432                      for(item = e.values.first; item; item = item.next)
4433                      {
4434                         if((int)item.data == *(int *)ptr)
4435                         {
4436                            result = item.name;
4437                            break;
4438                         }
4439                      }
4440                   }
4441                   if(result)
4442                   {
4443                      exp.identifier = MkIdentifier(result);
4444                      exp.type = identifierExp;
4445                      exp.destType = MkClassType(_class.fullName);
4446                      ProcessExpressionType(exp);
4447                   }                     
4448                }
4449                if(_class.type == enumClass || _class.type == unitClass || _class.type == bitClass)
4450                {
4451                   if(!_class.dataType)
4452                      _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4453                   type = _class.dataType;
4454                }
4455             }
4456             if(!result)
4457             {
4458                switch(type.kind)
4459                {
4460                   case floatType:
4461                   {
4462                      exp.constant = PrintFloat(*(float*)ptr);
4463                      exp.type = constantExp;
4464                      break;
4465                   }
4466                   case doubleType:
4467                   {
4468                      exp.constant = PrintDouble(*(double*)ptr);
4469                      exp.type = constantExp;
4470                      break;
4471                   }
4472                   case intType:
4473                   {
4474                      exp.constant = PrintInt(*(int*)ptr);
4475                      exp.type = constantExp;
4476                      break;
4477                   }
4478                   case int64Type:
4479                   {
4480                      exp.constant = PrintInt64(*(int64*)ptr);
4481                      exp.type = constantExp;
4482                      break;
4483                   }
4484                   default:
4485                      Compiler_Error($"Unhandled type populating instance\n");
4486                }
4487             }
4488             ListAdd(memberList, member);
4489          }
4490       }
4491    }
4492 }
4493
4494 void ComputeInstantiation(Expression exp)
4495 {
4496    Instantiation inst = exp.instance;
4497    MembersInit members;
4498    Symbol classSym = inst._class ? inst._class.symbol : null; // FindClass(inst._class.name);
4499    Class _class = classSym ? classSym.registered : null;
4500    DataMember curMember = null;
4501    Class curClass = null;
4502    DataMember subMemberStack[256];
4503    int subMemberStackPos = 0;
4504    uint64 bits = 0;
4505
4506    if(_class && (_class.type == structClass || _class.type == normalClass || _class.type == noHeadClass ))
4507    {
4508       // Don't recompute the instantiation... 
4509       // Non Simple classes will have become constants by now
4510       if(inst.data) 
4511          return;
4512
4513       if(_class.type == normalClass || _class.type == noHeadClass)
4514          inst.data = (byte *)eInstance_New(_class);
4515       else
4516          inst.data = new0 byte[_class.structSize];
4517    }
4518
4519    if(inst.members)
4520    {
4521       for(members = inst.members->first; members; members = members.next)
4522       {
4523          switch(members.type)
4524          {
4525             case dataMembersInit:
4526             {
4527                if(members.dataMembers)
4528                {
4529                   MemberInit member;
4530                   for(member = members.dataMembers->first; member; member = member.next)
4531                   {
4532                      Identifier ident = member.identifiers ? member.identifiers->first : null;
4533                      bool found = false;
4534
4535                      Property prop = null;
4536                      DataMember dataMember = null;
4537                      Method method = null;
4538                      uint dataMemberOffset;
4539
4540                      if(!ident)
4541                      {
4542                         eClass_FindNextMember(_class, &curClass, &curMember, subMemberStack, &subMemberStackPos);
4543                         if(curMember)
4544                         {
4545                            if(curMember.isProperty)
4546                               prop = (Property)curMember;
4547                            else
4548                            {
4549                               dataMember = curMember;
4550                               
4551                               // CHANGED THIS HERE
4552                               eClass_FindDataMemberAndOffset(_class, dataMember.name, &dataMemberOffset, privateModule, null, null);
4553                               // dataMemberOffset = dataMember.offset;
4554                            }
4555                            found = true;
4556                         }
4557                      }
4558                      else
4559                      {
4560                         prop = eClass_FindProperty(_class, ident.string, privateModule);
4561                         if(prop)
4562                         {
4563                            found = true;
4564                            if(prop.memberAccess == publicAccess)
4565                            {
4566                               curMember = (DataMember)prop;
4567                               curClass = prop._class;
4568                            }
4569                         }
4570                         else
4571                         {
4572                            DataMember _subMemberStack[256];
4573                            int _subMemberStackPos = 0;
4574
4575                            // FILL MEMBER STACK
4576                            dataMember = eClass_FindDataMemberAndOffset(_class, ident.string, &dataMemberOffset, privateModule, _subMemberStack, &_subMemberStackPos);
4577
4578                            if(dataMember)
4579                            {
4580                               found = true;
4581                               if(dataMember.memberAccess == publicAccess)
4582                               {
4583                                  curMember = dataMember;
4584                                  curClass = dataMember._class;
4585                                  memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
4586                                  subMemberStackPos = _subMemberStackPos;
4587                               }
4588                            }
4589                         }
4590                      }
4591
4592                      if(found && member.initializer && member.initializer.type == expInitializer)
4593                      {
4594                         Expression value = member.initializer.exp;
4595                         Type type = null;
4596                         if(prop)
4597                         {
4598                            type = prop.dataType;
4599                         }
4600                         else if(dataMember)
4601                         {
4602                            if(!dataMember.dataType)
4603                               dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4604                            
4605                            type = dataMember.dataType;
4606                         }
4607
4608                         if(ident && ident.next)
4609                         {
4610                            // for(; ident && type; ident = ident.next)
4611                            for(ident = ident.next; ident && type; ident = ident.next)
4612                            {
4613                               if(type.kind == classType)
4614                               {
4615                                  prop = eClass_FindProperty(type._class.registered,
4616                                     ident.string, privateModule);
4617                                  if(prop)
4618                                     type = prop.dataType;
4619                                  else
4620                                  {
4621                                     dataMember = eClass_FindDataMemberAndOffset(type._class.registered, 
4622                                        ident.string, &dataMemberOffset, privateModule, null, null);
4623                                     if(dataMember)
4624                                        type = dataMember.dataType;
4625                                  }
4626                               }
4627                               else if(type.kind == structType || type.kind == unionType)
4628                               {
4629                                  Type memberType;
4630                                  for(memberType = type.members.first; memberType; memberType = memberType.next)
4631                                  {
4632                                     if(!strcmp(memberType.name, ident.string))
4633                                     {
4634                                        type = memberType;
4635                                        break;
4636                                     }
4637                                  }
4638                               }
4639                            }
4640                         }
4641                         if(value)
4642                         {
4643                            FreeType(value.destType);
4644                            value.destType = type;
4645                            if(type) type.refCount++;
4646                            ComputeExpression(value);
4647                         }
4648                         if(value && (_class.type == structClass || _class.type == normalClass || _class.type == noHeadClass /*&& value.expType.kind == type.kind*/))
4649                         {
4650                            if(type.kind == classType)
4651                            {
4652                               Class _class = type._class.registered;
4653                               if(_class.type == bitClass || _class.type == unitClass ||
4654                                  _class.type == enumClass)
4655                               {
4656                                  if(!_class.dataType)
4657                                     _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4658                                  type = _class.dataType;
4659                               }
4660                            }
4661
4662                            if(dataMember)
4663                            {
4664                               void * ptr = inst.data + dataMemberOffset;
4665                               
4666                               if(value.type == constantExp)
4667                               {
4668                                  switch(type.kind)
4669                                  {
4670                                     case intType:
4671                                     {
4672                                        GetInt(value, (int*)ptr);
4673                                        break;
4674                                     }
4675                                     case int64Type:
4676                                     {
4677                                        GetInt64(value, (int64*)ptr);
4678                                        break;
4679                                     }
4680                                     case floatType:
4681                                     {
4682                                        GetFloat(value, (float*)ptr);
4683                                        break;
4684                                     }
4685                                     case doubleType:
4686                                     {
4687                                        GetDouble(value, (double *)ptr);
4688                                        break;
4689                                     }
4690                                  }
4691                               }
4692                               else if(value.type == instanceExp)
4693                               {
4694                                  if(type.kind == classType)
4695                                  {
4696                                     Class _class = type._class.registered;
4697                                     if(_class.type == structClass)
4698                                     {
4699                                        ComputeTypeSize(type);
4700                                        if(value.instance.data)
4701                                           memcpy(ptr, value.instance.data, type.size);
4702                                     }
4703                                  }
4704                               }
4705                            }
4706                            else if(prop)
4707                            {
4708                               if(value.type == instanceExp && value.instance.data)
4709                               {
4710                                  void (*Set)(void *, void *) = (void *)prop.Set;
4711                                  Set(inst.data, value.instance.data);
4712                                  PopulateInstance(inst);
4713                               }
4714                               else if(value.type == constantExp)
4715                               {
4716                                  switch(type.kind)
4717                                  {
4718                                     case doubleType:
4719                                     {
4720                                        void (*Set)(void *, double) = (void *)prop.Set;
4721                                        Set(inst.data, strtod(value.constant, null) );
4722                                        break;
4723                                     }
4724                                     case floatType:
4725                                     {
4726                                        void (*Set)(void *, float) = (void *)prop.Set;
4727                                        Set(inst.data, (float)(strtod(value.constant, null)));
4728                                        break;
4729                                     }
4730                                     case intType:
4731                                     {
4732                                        void (*Set)(void *, int) = (void *)prop.Set;
4733                                        Set(inst.data, strtol(value.constant, null, 0));
4734                                        break;
4735                                     }
4736                                     case int64Type:
4737                                     {
4738                                        void (*Set)(void *, int64) = (void *)prop.Set;
4739                                        Set(inst.data, _strtoi64(value.constant, null, 0));
4740                                        break;
4741                                     }
4742                                  }
4743                               }
4744                               else if(value.type == stringExp)
4745                               {
4746                                  char temp[1024];
4747                                  ReadString(temp, value.string);
4748                                  prop.Set(inst.data, temp);
4749                               }
4750                            }
4751                         }
4752                         else if(_class.type == unitClass)
4753                         {
4754                            if(prop)
4755                            {
4756                               // Only support converting units to units for now...
4757                               if(value.type == constantExp)
4758                               {
4759                                  if(type.kind == classType)
4760                                  {
4761                                     Class _class = type._class.registered;
4762                                     if(_class.type == unitClass)
4763                                     {
4764                                        if(!_class.dataType)
4765                                           _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4766                                        type = _class.dataType;
4767                                     }
4768                                  }
4769                                  // TODO: Assuming same base type for units...
4770                                  switch(type.kind)
4771                                  {
4772                                     case floatType:
4773                                     {
4774                                        float fValue;
4775                                        float (*Set)(float) = (void *)prop.Set;
4776                                        GetFloat(member.initializer.exp, &fValue);
4777                                        exp.constant = PrintFloat(Set(fValue));
4778                                        exp.type = constantExp;
4779                                        break;
4780                                     }
4781                                     case doubleType:
4782                                     {
4783                                        double dValue;
4784                                        double (*Set)(double) = (void *)prop.Set;
4785                                        GetDouble(member.initializer.exp, &dValue);
4786                                        exp.constant = PrintDouble(Set(dValue));
4787                                        exp.type = constantExp;
4788                                        break;
4789                                     }
4790                                  }
4791                               }
4792                            }
4793                         }
4794                         else if(_class.type == bitClass)
4795                         {
4796                            if(prop)
4797                            {
4798                               if(value.type == instanceExp && value.instance.data)
4799                               {
4800                                  unsigned int (*Set)(void *) = (void *)prop.Set;
4801                                  bits = Set(value.instance.data);
4802                               }
4803                               else if(value.type == constantExp)
4804                               {
4805                               }
4806                            }
4807                            else if(dataMember)
4808                            {
4809                               BitMember bitMember = (BitMember) dataMember;
4810                               Type type;
4811                               int part = 0;
4812                               GetInt(value, &part);
4813                               bits = (bits & ~bitMember.mask);
4814                               if(!bitMember.dataType)
4815                                  bitMember.dataType = ProcessTypeString(bitMember.dataTypeString, false);
4816
4817                               type = bitMember.dataType;
4818
4819                               if(type.kind == classType && type._class && type._class.registered)
4820                               {
4821                                  if(!type._class.registered.dataType)
4822                                     type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);                                    
4823                                  type = type._class.registered.dataType;
4824                               }
4825
4826                               switch(type.kind)
4827                               {
4828                                  case charType:
4829                                     if(type.isSigned)
4830                                        bits |= ((char)part << bitMember.pos);
4831                                     else
4832                                        bits |= ((unsigned char)part << bitMember.pos);
4833                                     break;
4834                                  case shortType:
4835                                     if(type.isSigned)
4836                                        bits |= ((short)part << bitMember.pos);
4837                                     else
4838                                        bits |= ((unsigned short)part << bitMember.pos);
4839                                     break;
4840                                  case intType:
4841                                  case longType:
4842                                     if(type.isSigned)
4843                                        bits |= ((int)part << bitMember.pos);
4844                                     else
4845                                        bits |= ((unsigned int)part << bitMember.pos);
4846                                     break;
4847                                  case int64Type:
4848                                     if(type.isSigned)
4849                                        bits |= ((int64)part << bitMember.pos);
4850                                     else
4851                                        bits |= ((uint64)part << bitMember.pos);
4852                                     break;
4853                               }
4854                            }
4855                         }
4856                      }
4857                      else
4858                      {
4859                         if(_class && _class.type == unitClass)
4860                         {
4861                            ComputeExpression(member.initializer.exp);
4862                            exp.constant = member.initializer.exp.constant;
4863                            exp.type = constantExp;
4864                            
4865                            member.initializer.exp.constant = null;
4866                         }
4867                      }
4868                   }
4869                }
4870                break;
4871             }
4872          }
4873       }
4874    }
4875    if(_class && _class.type == bitClass)
4876    {
4877       exp.constant = PrintHexUInt(bits);
4878       exp.type = constantExp;
4879    }
4880    if(exp.type != instanceExp)
4881    {
4882       FreeInstance(inst);
4883    }
4884 }
4885
4886 void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1, Operand op2)
4887 {
4888    if(exp.op.op == SIZEOF)
4889    {
4890       FreeExpContents(exp);
4891       exp.type = constantExp;
4892       exp.constant = PrintUInt(ComputeTypeSize(op1.type));
4893    }
4894    else
4895    {
4896       if(!exp.op.exp1)
4897       {
4898          switch(exp.op.op)
4899          {
4900             // unary arithmetic
4901             case '+':
4902             {
4903                // Provide default unary +
4904                Expression exp2 = exp.op.exp2;
4905                exp.op.exp2 = null;
4906                FreeExpContents(exp);
4907                FreeType(exp.expType);
4908                FreeType(exp.destType);
4909                *exp = *exp2;
4910                delete exp2;
4911                break;
4912             }
4913             case '-':
4914                if(op1.ops.Neg) { FreeExpContents(exp); op1.ops.Neg(exp, op1); }
4915                break;
4916             // unary arithmetic increment and decrement
4917                   //OPERATOR_ALL(UNARY, ++, Inc)
4918                   //OPERATOR_ALL(UNARY, --, Dec)
4919             // unary bitwise
4920             case '~':
4921                if(op1.ops.BitNot) { FreeExpContents(exp); op1.ops.BitNot(exp, op1); }
4922                break;
4923             // unary logical negation
4924             case '!':
4925                if(op1.ops.Not) { FreeExpContents(exp); op1.ops.Not(exp, op1); }
4926                break;
4927          }
4928       }
4929       else
4930       {
4931          switch(exp.op.op)
4932          {
4933             // binary arithmetic
4934             case '+':
4935                if(op1.ops.Add) { FreeExpContents(exp); op1.ops.Add(exp, op1, op2); }
4936                break;
4937             case '-':
4938                if(op1.ops.Sub) { FreeExpContents(exp); op1.ops.Sub(exp, op1, op2); }
4939                break;
4940             case '*':
4941                if(op1.ops.Mul) { FreeExpContents(exp); op1.ops.Mul(exp, op1, op2); }
4942                break;
4943             case '/':
4944                if(op1.ops.Div) { FreeExpContents(exp); op1.ops.Div(exp, op1, op2); }
4945                break;
4946             case '%':
4947                if(op1.ops.Mod) { FreeExpContents(exp); op1.ops.Mod(exp, op1, op2); }
4948                break;
4949             // binary arithmetic assignment
4950                   //OPERATOR_ALL(BINARY, =, Asign)
4951                   //OPERATOR_ALL(BINARY, +=, AddAsign)
4952                   //OPERATOR_ALL(BINARY, -=, SubAsign)
4953                   //OPERATOR_ALL(BINARY, *=, MulAsign)
4954                   //OPERATOR_ALL(BINARY, /=, DivAsign)
4955                   //OPERATOR_ALL(BINARY, %=, ModAsign)
4956             // binary bitwise
4957             case '&':
4958                if(exp.op.exp2)
4959                {
4960                   if(op1.ops.BitAnd) { FreeExpContents(exp); op1.ops.BitAnd(exp, op1, op2); }
4961                }
4962                break;
4963             case '|':
4964                if(op1.ops.BitOr) { FreeExpContents(exp); op1.ops.BitOr(exp, op1, op2); }
4965                break;
4966             case '^':
4967                if(op1.ops.BitXor) { FreeExpContents(exp); op1.ops.BitXor(exp, op1, op2); }
4968                break;
4969             case LEFT_OP:
4970                if(op1.ops.LShift) { FreeExpContents(exp); op1.ops.LShift(exp, op1, op2); }
4971                break;
4972             case RIGHT_OP:
4973                if(op1.ops.RShift) { FreeExpContents(exp); op1.ops.RShift(exp, op1, op2); }
4974                break;
4975             // binary bitwise assignment
4976                   //OPERATOR_INTTYPES(BINARY, &=, AndAsign)
4977                   //OPERATOR_INTTYPES(BINARY, |=, OrAsign)
4978                   //OPERATOR_INTTYPES(BINARY, ^=, XorAsign)
4979                   //OPERATOR_INTTYPES(BINARY, <<=, LShiftAsign)
4980                   //OPERATOR_INTTYPES(BINARY, >>=, RShiftAsign)
4981             // binary logical equality
4982             case EQ_OP:
4983                if(op1.ops.Equ) { FreeExpContents(exp); op1.ops.Equ(exp, op1, op2); }
4984                break;
4985             case NE_OP:
4986                if(op1.ops.Nqu) { FreeExpContents(exp); op1.ops.Nqu(exp, op1, op2); }
4987                break;
4988             // binary logical
4989             case AND_OP:
4990                if(op1.ops.And) { FreeExpContents(exp); op1.ops.And(exp, op1, op2); }
4991                break;
4992             case OR_OP:
4993                if(op1.ops.Or) { FreeExpContents(exp); op1.ops.Or(exp, op1, op2); }
4994                break;
4995             // binary logical relational
4996             case '>':
4997                if(op1.ops.Grt) { FreeExpContents(exp); op1.ops.Grt(exp, op1, op2); }
4998                break;
4999             case '<':
5000                if(op1.ops.Sma) { FreeExpContents(exp); op1.ops.Sma(exp, op1, op2); }
5001                break;
5002             case GE_OP:
5003                if(op1.ops.GrtEqu) { FreeExpContents(exp); op1.ops.GrtEqu(exp, op1, op2); }
5004                break;
5005             case LE_OP:
5006                if(op1.ops.SmaEqu) { FreeExpContents(exp); op1.ops.SmaEqu(exp, op1, op2); }
5007                break;
5008          }
5009       }
5010    }
5011 }
5012
5013 void ComputeExpression(Expression exp)
5014 {
5015    char expString[10240];
5016    expString[0] = '\0';
5017 #ifdef _DEBUG
5018    PrintExpression(exp, expString);
5019 #endif
5020
5021    switch(exp.type)
5022    {
5023       case instanceExp:
5024       {
5025          ComputeInstantiation(exp);
5026          break;
5027       }
5028       /*
5029       case constantExp:
5030          break;
5031       */
5032       case opExp:
5033       {
5034          Expression exp1, exp2 = null;
5035          Operand op1 { };
5036          Operand op2 { };
5037
5038          // We don't care about operations with only exp2 (INC_OP, DEC_OP...)
5039          if(exp.op.exp2)
5040             ComputeExpression(exp.op.exp2);
5041          if(exp.op.exp1)
5042          {
5043             ComputeExpression(exp.op.exp1);
5044             exp1 = exp.op.exp1;
5045             exp2 = exp.op.exp2;
5046             op1 = GetOperand(exp1);
5047             if(op1.type) op1.type.refCount++;
5048             if(exp2)
5049             {
5050                op2 = GetOperand(exp2);
5051                if(op2.type) op2.type.refCount++;
5052             }
5053          }
5054          else 
5055          {
5056             exp1 = exp.op.exp2;
5057             op1 = GetOperand(exp1);
5058             if(op1.type) op1.type.refCount++;
5059          }
5060
5061          CallOperator(exp, exp1, exp2, op1, op2);
5062          /*
5063          switch(exp.op.op)
5064          {
5065             // Unary operators
5066             case '&':
5067                // Also binary
5068                if(exp.op.exp1 && exp.op.exp2)
5069                {
5070                   // Binary And
5071                   if(op1.ops.BitAnd)
5072                   {
5073                      FreeExpContents(exp);
5074                      op1.ops.BitAnd(exp, op1, op2);
5075                   }
5076                }
5077                break;
5078             case '*':
5079                if(exp.op.exp1)
5080                {
5081                   if(op1.ops.Mul)
5082                   {
5083                      FreeExpContents(exp);
5084                      op1.ops.Mul(exp, op1, op2);
5085                   }
5086                }
5087                break;
5088             case '+':
5089                if(exp.op.exp1)
5090                {
5091                   if(op1.ops.Add)
5092                   {
5093                      FreeExpContents(exp);
5094                      op1.ops.Add(exp, op1, op2);
5095                   }
5096                }
5097                else
5098                {
5099                   // Provide default unary +
5100                   Expression exp2 = exp.op.exp2;
5101                   exp.op.exp2 = null;
5102                   FreeExpContents(exp);
5103                   FreeType(exp.expType);
5104                   FreeType(exp.destType);
5105
5106                   *exp = *exp2;
5107                   delete exp2;
5108                }
5109                break;
5110             case '-':
5111                if(exp.op.exp1)
5112                {
5113                   if(op1.ops.Sub) 
5114                   {
5115                      FreeExpContents(exp);
5116                      op1.ops.Sub(exp, op1, op2);
5117                   }
5118                }
5119                else
5120                {
5121                   if(op1.ops.Neg) 
5122                   {
5123                      FreeExpContents(exp);
5124                      op1.ops.Neg(exp, op1);
5125                   }
5126                }
5127                break;
5128             case '~':
5129                if(op1.ops.BitNot)
5130                {
5131                   FreeExpContents(exp);
5132                   op1.ops.BitNot(exp, op1);
5133                }
5134                break;
5135             case '!':
5136                if(op1.ops.Not)
5137                {
5138                   FreeExpContents(exp);
5139                   op1.ops.Not(exp, op1);
5140                }
5141                break;
5142             // Binary only operators
5143             case '/':
5144                if(op1.ops.Div) 
5145                {
5146                   FreeExpContents(exp);
5147                   op1.ops.Div(exp, op1, op2);
5148                }
5149                break;
5150             case '%':
5151                if(op1.ops.Mod)
5152                {
5153                   FreeExpContents(exp);
5154                   op1.ops.Mod(exp, op1, op2);
5155                }
5156                break;
5157             case LEFT_OP:
5158                break;
5159             case RIGHT_OP:
5160                break;
5161             case '<':
5162                if(exp.op.exp1)
5163                {
5164                   if(op1.ops.Sma)
5165                   {
5166                      FreeExpContents(exp);
5167                      op1.ops.Sma(exp, op1, op2);
5168                   }
5169                }
5170                break;
5171             case '>':
5172                if(exp.op.exp1)
5173                {
5174                   if(op1.ops.Grt)
5175                   {
5176                      FreeExpContents(exp);
5177                      op1.ops.Grt(exp, op1, op2);
5178                   }
5179                }
5180                break;
5181             case LE_OP:
5182                if(exp.op.exp1)
5183                {
5184                   if(op1.ops.SmaEqu)
5185                   {
5186                      FreeExpContents(exp);
5187                      op1.ops.SmaEqu(exp, op1, op2);
5188                   }
5189                }
5190                break;
5191             case GE_OP:
5192                if(exp.op.exp1)
5193                {
5194                   if(op1.ops.GrtEqu)
5195                   {
5196                      FreeExpContents(exp);
5197                      op1.ops.GrtEqu(exp, op1, op2);
5198                   }
5199                }
5200                break;
5201             case EQ_OP:
5202                if(exp.op.exp1)
5203                {
5204                   if(op1.ops.Equ)
5205                   {
5206                      FreeExpContents(exp);
5207                      op1.ops.Equ(exp, op1, op2);
5208                   }
5209                }
5210                break;
5211             case NE_OP:
5212                if(exp.op.exp1)
5213                {
5214                   if(op1.ops.Nqu)
5215                   {
5216                      FreeExpContents(exp);
5217                      op1.ops.Nqu(exp, op1, op2);
5218                   }
5219                }
5220                break;
5221             case '|':
5222                if(op1.ops.BitOr) 
5223                {
5224                   FreeExpContents(exp);
5225                   op1.ops.BitOr(exp, op1, op2);
5226                }
5227                break;
5228             case '^':
5229                if(op1.ops.BitXor) 
5230                {
5231                   FreeExpContents(exp);
5232                   op1.ops.BitXor(exp, op1, op2);
5233                }
5234                break;
5235             case AND_OP:
5236                break;
5237             case OR_OP:
5238                break;
5239             case SIZEOF:
5240                FreeExpContents(exp);
5241                exp.type = constantExp;
5242                exp.constant = PrintUInt(ComputeTypeSize(op1.type));
5243                break;
5244          }
5245          */
5246          if(op1.type) FreeType(op1.type);
5247          if(op2.type) FreeType(op2.type);
5248          break;
5249       }
5250       case bracketsExp:
5251       case extensionExpressionExp:
5252       {
5253          Expression e, n;
5254          for(e = exp.list->first; e; e = n)
5255          {
5256             n = e.next;
5257             if(!n)
5258             {
5259                OldList * list = exp.list;
5260                ComputeExpression(e);
5261                //FreeExpContents(exp);
5262                FreeType(exp.expType);
5263                FreeType(exp.destType);
5264                *exp = *e;
5265                delete e;
5266                delete list;
5267             }
5268             else
5269             {
5270                FreeExpression(e);
5271             }
5272          }
5273          break;
5274       }
5275       /*
5276
5277       case ExpIndex:
5278       {
5279          Expression e;
5280          exp.isConstant = true;
5281
5282          ComputeExpression(exp.index.exp);
5283          if(!exp.index.exp.isConstant)
5284             exp.isConstant = false;
5285
5286          for(e = exp.index.index->first; e; e = e.next)
5287          {
5288             ComputeExpression(e);
5289             if(!e.next)
5290             {
5291                // Check if this type is int
5292             }
5293             if(!e.isConstant)
5294                exp.isConstant = false;
5295          }
5296          exp.expType = Dereference(exp.index.exp.expType);
5297          break;
5298       }
5299       */
5300       case memberExp:
5301       {
5302          Expression memberExp = exp.member.exp;
5303          Identifier memberID = exp.member.member;
5304
5305          Type type;
5306          ComputeExpression(exp.member.exp);
5307          type = exp.member.exp.expType;
5308          if(type)
5309          {
5310             Class _class = (exp.member.member && exp.member.member.classSym) ? exp.member.member.classSym.registered : (((type.kind == classType || type.kind == subClassType) && type._class) ? type._class.registered : null);
5311             Property prop = null;
5312             DataMember member = null;
5313             Class convertTo = null;
5314             if(type.kind == subClassType && exp.member.exp.type == classExp)
5315                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
5316
5317             if(!_class)
5318             {
5319                char string[256];
5320                Symbol classSym;
5321                string[0] = '\0';
5322                PrintType(type, string, false, true);
5323                classSym = FindClass(string);
5324                _class = classSym ? classSym.registered : null;
5325             }
5326
5327             if(exp.member.member)
5328             {
5329                prop = eClass_FindProperty(_class, exp.member.member.string, privateModule);
5330                if(!prop)
5331                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, null, null);
5332             }
5333             if(!prop && !member && _class && exp.member.member)
5334             {
5335                Symbol classSym = FindClass(exp.member.member.string);
5336                convertTo = _class;
5337                _class = classSym ? classSym.registered : null;
5338                prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
5339             }
5340       
5341             if(prop)
5342             {
5343                if(prop.compiled)
5344                {
5345                   Type type = prop.dataType;
5346                   // TODO: Assuming same base type for units...
5347                   if(_class.type == unitClass)
5348                   {
5349                      if(type.kind == classType)
5350                      {
5351                         Class _class = type._class.registered;
5352                         if(_class.type == unitClass)
5353                         {
5354                            if(!_class.dataType)
5355                               _class.dataType = ProcessTypeString(_class.dataTypeString, false);
5356                            type = _class.dataType;
5357                         }
5358                      }
5359                      switch(type.kind)
5360                      {
5361                         case floatType:
5362                         {
5363                            float value;
5364                            float (*Get)(float) = (void *)prop.Get;
5365                            GetFloat(exp.member.exp, &value);
5366                            exp.constant = PrintFloat(Get ? Get(value) : value);
5367                            exp.type = constantExp;
5368                            break;
5369                         }
5370                         case doubleType:
5371                         {
5372                            double value;
5373                            double (*Get)(double);
5374                            GetDouble(exp.member.exp, &value);
5375                      
5376                            if(convertTo)
5377                               Get = (void *)prop.Set;
5378                            else
5379                               Get = (void *)prop.Get;
5380                            exp.constant = PrintDouble(Get ? Get(value) : value);
5381                            exp.type = constantExp;
5382                            break;
5383                         }
5384                      }
5385                   }
5386                   else
5387                   {
5388                      if(convertTo)
5389                      {
5390                         Expression value = exp.member.exp;
5391                         Type type;
5392                         if(!prop.dataType)
5393                            ProcessPropertyType(prop);
5394
5395                         type = prop.dataType;
5396                         if(!type)
5397                         {
5398                             // printf("Investigate this\n");
5399                         }
5400                         else if(_class.type == structClass)
5401                         {
5402                            switch(type.kind)
5403                            {
5404                               case classType:
5405                               {
5406                                  Class propertyClass = type._class.registered;
5407                                  if(propertyClass.type == structClass && value.type == instanceExp)
5408                                  {
5409                                     void (*Set)(void *, void *) = (void *)prop.Set;
5410                                     exp.instance = Instantiation { };
5411                                     exp.instance.data = new0 byte[_class.structSize];
5412                                     exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5413                                     exp.instance.loc = exp.loc;
5414                                     exp.type = instanceExp;
5415                                     Set(exp.instance.data, value.instance.data);
5416                                     PopulateInstance(exp.instance);
5417                                  }
5418                                  break;
5419                               }
5420                               case intType:
5421                               {
5422                                  int intValue;
5423                                  void (*Set)(void *, int) = (void *)prop.Set;
5424
5425                                  exp.instance = Instantiation { };
5426                                  exp.instance.data = new0 byte[_class.structSize];
5427                                  exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5428                                  exp.instance.loc = exp.loc;
5429                                  exp.type = instanceExp;
5430                               
5431                                  GetInt(value, &intValue);
5432
5433                                  Set(exp.instance.data, intValue);
5434                                  PopulateInstance(exp.instance);
5435                                  break;
5436                               }
5437                               case int64Type:
5438                               {
5439                                  int64 intValue;
5440                                  void (*Set)(void *, int64) = (void *)prop.Set;
5441
5442                                  exp.instance = Instantiation { };
5443                                  exp.instance.data = new0 byte[_class.structSize];
5444                                  exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5445                                  exp.instance.loc = exp.loc;
5446                                  exp.type = instanceExp;
5447                               
5448                                  GetInt64(value, &intValue);
5449
5450                                  Set(exp.instance.data, intValue);
5451                                  PopulateInstance(exp.instance);
5452                                  break;
5453                               }
5454                               case doubleType:
5455                               {
5456                                  double doubleValue;
5457                                  void (*Set)(void *, double) = (void *)prop.Set;
5458
5459                                  exp.instance = Instantiation { };
5460                                  exp.instance.data = new0 byte[_class.structSize];
5461                                  exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5462                                  exp.instance.loc = exp.loc;
5463                                  exp.type = instanceExp;
5464                               
5465                                  GetDouble(value, &doubleValue);
5466
5467                                  Set(exp.instance.data, doubleValue);
5468                                  PopulateInstance(exp.instance);
5469                                  break;
5470                               }
5471                            }
5472                         }
5473                         else if(_class.type == bitClass)
5474                         {
5475                            switch(type.kind)
5476                            {
5477                               case classType:
5478                               {
5479                                  Class propertyClass = type._class.registered;
5480                                  if(propertyClass.type == structClass && value.instance.data)
5481                                  {
5482                                     unsigned int (*Set)(void *) = (void *)prop.Set;
5483                                     unsigned int bits = Set(value.instance.data);
5484                                     exp.constant = PrintHexUInt(bits);
5485                                     exp.type = constantExp;
5486                                     break;
5487                                  }
5488                                  else if(_class.type == bitClass)
5489                                  {
5490                                     unsigned int value;
5491                                     unsigned int (*Set)(unsigned int) = (void *)prop.Set;
5492                                     unsigned int bits;
5493
5494                                     GetUInt(exp.member.exp, &value);
5495                                     bits = Set(value);
5496                                     exp.constant = PrintHexUInt(bits);
5497                                     exp.type = constantExp;
5498                                  }
5499                               }
5500                            }
5501                         }
5502                      }
5503                      else
5504                      {
5505                         if(_class.type == bitClass)
5506                         {
5507                            unsigned int value;
5508                            GetUInt(exp.member.exp, &value);
5509
5510                            switch(type.kind)
5511                            {
5512                               case classType:
5513                               {
5514                                  Class _class = type._class.registered;
5515                                  if(_class.type == structClass)
5516                                  {
5517                                     void (*Get)(unsigned int, void *) = (void *)prop.Get;
5518
5519                                     exp.instance = Instantiation { };
5520                                     exp.instance.data = new0 byte[_class.structSize];
5521                                     exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5522                                     exp.instance.loc = exp.loc;
5523                                     //exp.instance.fullSet = true;
5524                                     exp.type = instanceExp;
5525                                     Get(value, exp.instance.data);
5526                                     PopulateInstance(exp.instance);
5527                                  }
5528                                  else if(_class.type == bitClass)
5529                                  {
5530                                     unsigned int (*Get)(unsigned int) = (void *)prop.Get;
5531                                     uint64 bits = Get(value);
5532                                     exp.constant = PrintHexUInt64(bits);
5533                                     exp.type = constantExp;
5534                                  }
5535                                  break;
5536                               }
5537                            }
5538                         }
5539                         else if(_class.type == structClass)
5540                         {
5541                            char * value = (exp.member.exp.type == instanceExp ) ? exp.member.exp.instance.data : null;
5542                            switch(type.kind)
5543                            {
5544                               case classType:
5545                               {
5546                                  Class _class = type._class.registered;
5547                                  if(_class.type == structClass && value)
5548                                  {
5549                                     void (*Get)(void *, void *) = (void *)prop.Get;
5550
5551                                     exp.instance = Instantiation { };
5552                                     exp.instance.data = new0 byte[_class.structSize];
5553                                     exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5554                                     exp.instance.loc = exp.loc;
5555                                     //exp.instance.fullSet = true;
5556                                     exp.type = instanceExp;
5557                                     Get(value, exp.instance.data);
5558                                     PopulateInstance(exp.instance);
5559                                  }
5560                                  break;
5561                               }
5562                            }
5563                         }
5564                         /*else
5565                         {
5566                            char * value = exp.member.exp.instance.data;
5567                            switch(type.kind)
5568                            {
5569                               case classType:
5570                               {
5571                                  Class _class = type._class.registered;
5572                                  if(_class.type == normalClass)
5573                                  {
5574                                     void *(*Get)(void *) = (void *)prop.Get;
5575
5576                                     exp.instance = Instantiation { };
5577                                     exp.instance._class = MkSpecifierName(_class.fullName); //MkClassName(_class.fullName);
5578                                     exp.type = instanceExp;
5579                                     exp.instance.data = Get(value, exp.instance.data);
5580                                  }
5581                                  break;
5582                               }
5583                            }
5584                         }
5585                         */
5586                      }
5587                   }
5588                }
5589                else
5590                {
5591                   exp.isConstant = false;
5592                }
5593             }
5594             else if(member)
5595             {
5596             }
5597          }
5598
5599          if(exp.type != ExpressionType::memberExp)
5600          {
5601             FreeExpression(memberExp);
5602             FreeIdentifier(memberID);
5603          }
5604          break;
5605       }
5606       case typeSizeExp:
5607       {
5608          Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
5609          FreeExpContents(exp);
5610          exp.constant = PrintUInt(ComputeTypeSize(type));
5611          exp.type = constantExp;         
5612          FreeType(type);
5613          break;
5614       }
5615       case classSizeExp:
5616       {
5617          Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
5618          if(classSym && classSym.registered)
5619          {
5620             if(classSym.registered.fixed)
5621             {
5622                FreeSpecifier(exp._class);
5623                exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
5624                exp.type = constantExp;
5625             }
5626             else
5627             {
5628                char className[1024];
5629                strcpy(className, "__ecereClass_");
5630                FullClassNameCat(className, classSym.string, true);
5631                MangleClassName(className);
5632
5633                FreeExpContents(exp);
5634                exp.type = pointerExp;
5635                exp.member.exp = MkExpIdentifier(MkIdentifier(className));
5636                exp.member.member = MkIdentifier("structSize");
5637             }
5638          }
5639          break;
5640       }
5641       case castExp:
5642       //case constantExp:
5643       {
5644          Type type;
5645          Expression e = exp;
5646          if(exp.type == castExp)
5647          {
5648             if(exp.cast.exp)
5649                ComputeExpression(exp.cast.exp);
5650             e = exp.cast.exp;
5651          }
5652          if(e && exp.expType)
5653          {
5654             /*if(exp.destType)
5655                type = exp.destType;
5656             else*/
5657                type = exp.expType;
5658             if(type.kind == classType)
5659             {
5660                Class _class = type._class.registered;
5661                if(_class && (_class.type == unitClass || _class.type == bitClass))
5662                {
5663                   if(!_class.dataType)
5664                      _class.dataType = ProcessTypeString(_class.dataTypeString, false);
5665                   type = _class.dataType;
5666                }
5667             }
5668             
5669             switch(type.kind)
5670             {
5671                case charType:
5672                   if(type.isSigned)
5673                   {
5674                      char value;
5675                      GetChar(e, &value);
5676                      FreeExpContents(exp);
5677                      exp.constant = PrintChar(value);
5678                      exp.type = constantExp;
5679                   }
5680                   else
5681                   {
5682                      unsigned char value;
5683                      GetUChar(e, &value);
5684                      FreeExpContents(exp);
5685                      exp.constant = PrintUChar(value);
5686                      exp.type = constantExp;
5687                   }
5688                   break;
5689                case shortType:
5690                   if(type.isSigned)
5691                   {
5692                      short value;
5693                      GetShort(e, &value);
5694                      FreeExpContents(exp);
5695                      exp.constant = PrintShort(value);
5696                      exp.type = constantExp;
5697                   }
5698                   else
5699                   {
5700                      unsigned short value;
5701                      GetUShort(e, &value);
5702                      FreeExpContents(exp);
5703                      exp.constant = PrintUShort(value);
5704                      exp.type = constantExp;
5705                   }
5706                   break;
5707                case intType:
5708                   if(type.isSigned)
5709                   {
5710                      int value;
5711                      GetInt(e, &value);
5712                      FreeExpContents(exp);
5713                      exp.constant = PrintInt(value);
5714                      exp.type = constantExp;
5715                   }
5716                   else
5717                   {
5718                      unsigned int value;
5719                      GetUInt(e, &value);
5720                      FreeExpContents(exp);
5721                      exp.constant = PrintUInt(value);
5722                      exp.type = constantExp;
5723                   }
5724                   break;
5725                case int64Type:
5726                   if(type.isSigned)
5727                   {
5728                      int64 value;
5729                      GetInt64(e, &value);
5730                      FreeExpContents(exp);
5731                      exp.constant = PrintInt64(value);
5732                      exp.type = constantExp;
5733                   }
5734                   else
5735                   {
5736                      uint64 value;
5737                      GetUInt64(e, &value);
5738                      FreeExpContents(exp);
5739                      exp.constant = PrintUInt64(value);
5740                      exp.type = constantExp;
5741                   }
5742                   break;
5743                case floatType:
5744                {
5745                   float value;
5746                   GetFloat(e, &value);
5747                   FreeExpContents(exp);
5748                   exp.constant = PrintFloat(value);
5749                   exp.type = constantExp;
5750                   break;
5751                }
5752                case doubleType:
5753                {  
5754                   double value;
5755                   GetDouble(e, &value);
5756                   FreeExpContents(exp);
5757                   exp.constant = PrintDouble(value);
5758                   exp.type = constantExp;
5759                   break;
5760                }
5761             }
5762          }
5763          break;
5764       }
5765       case conditionExp:
5766       {
5767          Operand op1 { };
5768          Operand op2 { };
5769          Operand op3 { };
5770
5771          if(exp.cond.exp)
5772             // Caring only about last expression for now...
5773             ComputeExpression(exp.cond.exp->last);
5774          if(exp.cond.elseExp)
5775             ComputeExpression(exp.cond.elseExp);
5776          if(exp.cond.cond)
5777             ComputeExpression(exp.cond.cond);
5778
5779          op1 = GetOperand(exp.cond.cond);
5780          if(op1.type) op1.type.refCount++;
5781          op2 = GetOperand(exp.cond.exp->last);
5782          if(op2.type) op2.type.refCount++;
5783          op3 = GetOperand(exp.cond.elseExp);
5784          if(op3.type) op3.type.refCount++;
5785
5786          if(op1.ops.Cond) { FreeExpContents(exp); op1.ops.Cond(exp, op1, op2, op3); }
5787          if(op1.type) FreeType(op1.type);
5788          if(op2.type) FreeType(op2.type);
5789          if(op3.type) FreeType(op3.type);
5790          break;
5791       }  
5792    }
5793 }
5794
5795 static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
5796 {
5797    bool result = true;
5798    if(destType)
5799    {
5800       OldList converts { };
5801       Conversion convert;
5802
5803       if(destType.kind == voidType)
5804          return false;
5805
5806       if(!MatchTypeExpression(exp, destType, &converts, skipUnitBla))
5807          result = false;
5808       if(converts.count)
5809       {
5810          // for(convert = converts.last; convert; convert = convert.prev)
5811          for(convert = converts.first; convert; convert = convert.next)
5812          {
5813             bool empty = !(convert.isGet ? (void *)convert.convert.Get : (void *)convert.convert.Set);
5814             if(!empty)
5815             {
5816                Expression newExp { };
5817                ClassObjectType objectType = exp.expType ? exp.expType.classObjectType : none;
5818
5819                // TODO: Check this...
5820                *newExp = *exp;
5821                newExp.destType = null;
5822
5823                if(convert.isGet)
5824                {
5825                   // [exp].ColorRGB
5826                   exp.type = memberExp;
5827                   exp.addedThis = true;
5828                   exp.member.exp = newExp;
5829                   FreeType(exp.member.exp.expType);
5830
5831                   exp.member.exp.expType = MkClassType(convert.convert._class.fullName);
5832                   exp.member.exp.expType.classObjectType = objectType;
5833                   exp.member.member = MkIdentifier(convert.convert.dataTypeString);
5834                   exp.member.memberType = propertyMember;
5835                   exp.expType = convert.resultType ? convert.resultType : convert.convert.dataType;
5836                   // TESTING THIS... for (int)degrees
5837                   exp.needCast = true;
5838                   if(exp.expType) exp.expType.refCount++;
5839                   ApplyAnyObjectLogic(exp.member.exp);
5840                }
5841                else
5842                {
5843                
5844                   /*if(exp.isConstant)
5845                   {
5846                      // Color { ColorRGB = [exp] };
5847                      exp.type = instanceExp;
5848                      exp.instance = MkInstantiation(MkSpecifierName((convert.convert._class.fullName), //MkClassName(convert.convert._class.fullName),
5849                         null, MkListOne(MkMembersInitList(MkListOne(MkMemberInit(
5850                         MkListOne(MkIdentifier(convert.convert.dataTypeString)), newExp)))));
5851                   }
5852                   else*/
5853                   {
5854                      // If not constant, don't turn it yet into an instantiation
5855                      // (Go through the deep members system first)
5856                      exp.type = memberExp;
5857                      exp.addedThis = true;
5858                      exp.member.exp = newExp;
5859
5860                      // ADDED THIS HERE TO SOLVE PROPERTY ISSUES WITH NOHEAD CLASSES
5861                      if(/*!notByReference && */newExp.expType && newExp.expType.kind == classType && newExp.expType._class && newExp.expType._class.registered &&
5862                         newExp.expType._class.registered.type == noHeadClass)
5863                      {
5864                         newExp.byReference = true;
5865                      }
5866
5867                      FreeType(exp.member.exp.expType);
5868                      /*exp.member.exp.expType = convert.convert.dataType;
5869                      if(convert.convert.dataType) convert.convert.dataType.refCount++;*/
5870                      exp.member.exp.expType = null;
5871                      if(convert.convert.dataType)
5872                      {
5873                         exp.member.exp.expType = { };
5874                         CopyTypeInto(exp.member.exp.expType, convert.convert.dataType);
5875                         exp.member.exp.expType.refCount = 1;
5876                         exp.member.exp.expType.classObjectType = objectType;
5877                         ApplyAnyObjectLogic(exp.member.exp);
5878                      }
5879
5880                      exp.member.member = MkIdentifier(convert.convert._class.fullName);
5881                      exp.member.memberType = reverseConversionMember;
5882                      exp.expType = convert.resultType ? convert.resultType :
5883                         MkClassType(convert.convert._class.fullName);
5884                      exp.needCast = true;
5885                      if(convert.resultType) convert.resultType.refCount++;
5886                   }
5887                }
5888             }
5889             else
5890             {
5891                FreeType(exp.expType);
5892                if(convert.isGet)
5893                {
5894                   exp.expType = convert.resultType ? convert.resultType : convert.convert.dataType;
5895                   exp.needCast = true;
5896                   if(exp.expType) exp.expType.refCount++;
5897                }
5898                else
5899                {
5900                   exp.expType = convert.resultType ? convert.resultType : MkClassType(convert.convert._class.fullName);
5901                   exp.needCast = true;
5902                   if(convert.resultType)
5903                      convert.resultType.refCount++;
5904                }
5905             }
5906          }
5907          if(exp.isConstant && inCompiler)
5908             ComputeExpression(exp);
5909
5910          converts.Free(FreeConvert);
5911       }
5912
5913       if(!result && exp.expType && converts.count)      // TO TEST: Added converts.count here to avoid a double warning with function type
5914       {
5915          result = MatchTypes(exp.expType, exp.destType, null, null, null, true, true, false, false);
5916       }
5917       if(!result && exp.expType && exp.destType)
5918       {
5919          if((exp.destType.kind == classType && exp.expType.kind == pointerType && 
5920              exp.expType.type.kind == classType && exp.expType.type._class == exp.destType._class && exp.destType._class.registered && exp.destType._class.registered.type == structClass) ||
5921             (exp.expType.kind == classType && exp.destType.kind == pointerType && 
5922             exp.destType.type.kind == classType && exp.destType.type._class == exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass))
5923             result = true;
5924       }
5925    }
5926    // if(result) CheckTemplateTypes(exp);
5927    return result;
5928 }
5929
5930 void CheckTemplateTypes(Expression exp)
5931 {
5932    if(exp.destType && exp.destType.passAsTemplate && exp.expType && exp.expType.kind != templateType && !exp.expType.passAsTemplate)
5933    {
5934       Expression newExp { };
5935       Statement compound;
5936       Context context;
5937       *newExp = *exp;
5938       if(exp.destType) exp.destType.refCount++;
5939       if(exp.expType)  exp.expType.refCount++;
5940       newExp.prev = null;
5941       newExp.next = null;
5942
5943       switch(exp.expType.kind)
5944       {
5945          case doubleType:
5946             if(exp.destType.classObjectType)
5947             {
5948                // We need to pass the address, just pass it along (Undo what was done above)
5949                if(exp.destType) exp.destType.refCount--;
5950                if(exp.expType)  exp.expType.refCount--;
5951                delete newExp;
5952             }
5953             else
5954             {
5955                // If we're looking for value:
5956                // ({ union { double d; uint64 i; } u; u.i = [newExp]; u.d; })
5957                OldList * specs;
5958                OldList * unionDefs = MkList();
5959                OldList * statements = MkList();
5960                context = PushContext();
5961                ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(DOUBLE)), MkListOne(MkDeclaratorIdentifier(MkIdentifier("d"))), null))); 
5962                ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifierName("uint64")), MkListOne(MkDeclaratorIdentifier(MkIdentifier("i"))), null)));
5963                specs = MkListOne(MkStructOrUnion(unionSpecifier, null, unionDefs ));
5964                exp.type = extensionCompoundExp;
5965                exp.compound = MkCompoundStmt(MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_union")), null)))),statements);
5966                ListAdd(statements, MkExpressionStmt(MkListOne(MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("d")), '=', newExp))));
5967                ListAdd(statements, MkExpressionStmt(MkListOne(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("i")))));
5968                exp.compound.compound.context = context;
5969                PopContext(context);
5970             }
5971             break;
5972          default:
5973             exp.type = castExp;
5974             exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
5975             exp.cast.exp = MkExpBrackets(MkListOne(newExp));
5976             break;
5977       }
5978    }
5979    else if(exp.expType && exp.expType.passAsTemplate && exp.destType && exp.usage.usageGet && exp.destType.kind != templateType && !exp.destType.passAsTemplate)
5980    {
5981       Expression newExp { };
5982       Statement compound;
5983       Context context;
5984       *newExp = *exp;
5985       if(exp.destType) exp.destType.refCount++;
5986       if(exp.expType)  exp.expType.refCount++;
5987       newExp.prev = null;
5988       newExp.next = null;
5989
5990       switch(exp.expType.kind)
5991       {
5992          case doubleType:
5993             if(exp.destType.classObjectType)
5994             {
5995                // We need to pass the address, just pass it along (Undo what was done above)
5996                if(exp.destType) exp.destType.refCount--;
5997                if(exp.expType)  exp.expType.refCount--;
5998                delete newExp;
5999             }
6000             else
6001             {
6002                // If we're looking for value:
6003                // ({ union { double d; uint64 i; } u; u.i = [newExp]; u.d; })
6004                OldList * specs;
6005                OldList * unionDefs = MkList();
6006                OldList * statements = MkList();
6007                context = PushContext();
6008                ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(DOUBLE)), MkListOne(MkDeclaratorIdentifier(MkIdentifier("d"))), null))); 
6009                ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifierName("uint64")), MkListOne(MkDeclaratorIdentifier(MkIdentifier("i"))), null)));
6010                specs = MkListOne(MkStructOrUnion(unionSpecifier, null, unionDefs ));
6011                exp.type = extensionCompoundExp;
6012                exp.compound = MkCompoundStmt(MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_union")), null)))),statements);
6013                ListAdd(statements, MkExpressionStmt(MkListOne(MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("i")), '=', newExp))));
6014                ListAdd(statements, MkExpressionStmt(MkListOne(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("d")))));
6015                exp.compound.compound.context = context;
6016                PopContext(context);
6017             }
6018             break;
6019          case classType:
6020          {
6021             if(exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass)
6022             {
6023                exp.type = bracketsExp;
6024                exp.list = MkListOne(MkExpOp(null, '*', MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)),
6025                   MkDeclaratorPointer(MkPointer(null, null), null)), newExp)));
6026                ProcessExpressionType(exp.list->first);
6027                break;
6028             }
6029             else
6030             {
6031                exp.type = bracketsExp;
6032                exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)), null), newExp));
6033                newExp.needCast = true;
6034                ProcessExpressionType(exp.list->first);
6035                break;
6036             }
6037          }
6038          default:
6039          {
6040             if(exp.expType.kind == templateType)
6041             {
6042                Type type = ProcessTemplateParameterType(exp.expType.templateParameter);
6043                if(type)
6044                {
6045                   FreeType(exp.destType);
6046                   FreeType(exp.expType);
6047                   delete newExp;
6048                   break;
6049                }
6050             }
6051             if(newExp.type == memberExp && newExp.member.memberType == dataMember)
6052             {
6053                exp.type = opExp;
6054                exp.op.op = '*';
6055                exp.op.exp1 = null;
6056                exp.op.exp2 = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)),
6057                   MkExpBrackets(MkListOne(MkExpOp(null, '&', newExp))));
6058             }
6059             else
6060             {
6061                char typeString[1024];
6062                Declarator decl;
6063                OldList * specs = MkList();
6064                typeString[0] = '\0';
6065                PrintType(exp.expType, typeString, false, false);
6066                decl = SpecDeclFromString(typeString, specs, null);
6067                
6068                exp.type = castExp;
6069                //exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
6070                exp.cast.typeName = MkTypeName(specs, decl);
6071                exp.cast.exp = MkExpBrackets(MkListOne(newExp));
6072                exp.cast.exp.needCast = true;
6073             }
6074             break;
6075          }
6076       }
6077    }
6078 }
6079 // TODO: The Symbol tree should be reorganized by namespaces
6080 // Name Space:
6081 //    - Tree of all symbols within (stored without namespace)
6082 //    - Tree of sub-namespaces
6083
6084 static Symbol ScanWithNameSpace(BinaryTree tree, char * nameSpace, char * name)
6085 {
6086    int nsLen = strlen(nameSpace);
6087    Symbol symbol;
6088    // Start at the name space prefix
6089    for(symbol = (Symbol)tree.FindPrefix(nameSpace); symbol; symbol = (Symbol)((BTNode)symbol).next)
6090    {
6091       char * s = symbol.string;
6092       if(!strncmp(s, nameSpace, nsLen))
6093       {
6094          // This supports e.g. matching ecere::Socket to ecere::net::Socket
6095          int c;
6096          char * namePart;
6097          for(c = strlen(s)-1; c >= 0; c--)
6098             if(s[c] == ':')
6099                break;
6100
6101          namePart = s+c+1;
6102          if(!strcmp(namePart, name))
6103          {
6104             // TODO: Error on ambiguity
6105             return symbol;
6106          }
6107       }
6108       else
6109          break;
6110    }
6111    return null;
6112 }
6113
6114 static Symbol FindWithNameSpace(BinaryTree tree, char * name)
6115 {
6116    int c;
6117    char nameSpace[1024];
6118    char * namePart;
6119    bool gotColon = false;
6120
6121    nameSpace[0] = '\0';
6122    for(c = strlen(name)-1; c >= 0; c--)
6123       if(name[c] == ':')
6124       {
6125          gotColon = true;
6126          break;
6127       }
6128
6129    namePart = name+c+1;
6130    while(c >= 0 && name[c] == ':') c--;
6131    if(c >= 0)
6132    {
6133       // Try an exact match first
6134       Symbol symbol = (Symbol)tree.FindString(name);
6135       if(symbol)
6136          return symbol;
6137
6138       // Namespace specified
6139       memcpy(nameSpace, name, c + 1);
6140       nameSpace[c+1] = 0;
6141
6142       return ScanWithNameSpace(tree, nameSpace, namePart);
6143    }
6144    else if(gotColon)
6145    {
6146       // Looking for a global symbol, e.g. ::Sleep()
6147       Symbol symbol = (Symbol)tree.FindString(namePart);
6148       return symbol;
6149    }
6150    else
6151    {
6152       // Name only (no namespace specified)
6153       Symbol symbol = (Symbol)tree.FindString(namePart);
6154       if(symbol)
6155          return symbol;
6156       return ScanWithNameSpace(tree, "", namePart);
6157    }
6158    return null;
6159 }
6160
6161 static void ProcessDeclaration(Declaration decl);
6162
6163 /*static */Symbol FindSymbol(char * name, Context startContext, Context endContext, bool isStruct, bool globalNameSpace)
6164 {
6165 #ifdef _DEBUG
6166    //Time startTime = GetTime();
6167 #endif
6168    // Optimize this later? Do this before/less?
6169    Context ctx;
6170    Symbol symbol = null;
6171    // First, check if the identifier is declared inside the function
6172    //for(ctx = curContext; ctx /*!= topContext.parent */&& !symbol; ctx = ctx.parent)
6173
6174    for(ctx = startContext; ctx /*!= topContext.parent */&& !symbol; ctx = ctx.parent)
6175    {
6176       if(ctx == globalContext && !globalNameSpace && ctx.hasNameSpace)
6177       {
6178          symbol = null;
6179          if(thisNameSpace)
6180          {
6181             char curName[1024];
6182             strcpy(curName, thisNameSpace);
6183             strcat(curName, "::");
6184             strcat(curName, name);
6185             // Try to resolve in current namespace first
6186             symbol = FindWithNameSpace(isStruct ? ctx.structSymbols : ctx.symbols, curName);
6187          }
6188          if(!symbol)
6189             symbol = FindWithNameSpace(isStruct ? ctx.structSymbols : ctx.symbols, name);
6190       }
6191       else
6192          symbol = (Symbol)(isStruct ? ctx.structSymbols : ctx.symbols).FindString(name);
6193
6194       if(symbol || ctx == endContext) break;
6195    }
6196    if(inCompiler && curExternal && symbol && ctx == globalContext && curExternal.symbol && symbol.id > curExternal.symbol.idCode && symbol.pointerExternal)
6197    {
6198       if(symbol.pointerExternal.type == functionExternal)
6199       {
6200          FunctionDefinition function = symbol.pointerExternal.function;
6201
6202          // Modified this recently...
6203          Context tmpContext = curContext;
6204          curContext = null;         
6205          symbol.pointerExternal = MkExternalDeclaration(MkDeclaration(CopyList(function.specifiers, CopySpecifier), MkListOne(MkInitDeclarator(CopyDeclarator(function.declarator), null))));
6206          curContext = tmpContext;
6207
6208          symbol.pointerExternal.symbol = symbol;
6209
6210          // TESTING THIS:
6211          DeclareType(symbol.type, true, true);
6212
6213          ast->Insert(curExternal.prev, symbol.pointerExternal);
6214
6215          symbol.id = curExternal.symbol.idCode;
6216
6217       }
6218       else if(symbol.pointerExternal.type == declarationExternal && curExternal.symbol.idCode < symbol.pointerExternal.symbol.id) // Added id comparison because Global Function prototypes were broken
6219       {
6220          ast->Move(symbol.pointerExternal, curExternal.prev);
6221          symbol.id = curExternal.symbol.idCode;
6222       }
6223    }
6224 #ifdef _DEBUG
6225    //findSymbolTotalTime += GetTime() - startTime;
6226 #endif
6227    return symbol;
6228 }
6229
6230 static void GetTypeSpecs(Type type, OldList * specs)
6231 {
6232    if(!type.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
6233    switch(type.kind)
6234    {
6235       case classType: 
6236       {
6237          if(type._class.registered)
6238          {
6239             if(!type._class.registered.dataType)
6240                type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
6241             GetTypeSpecs(type._class.registered.dataType, specs);
6242          }
6243          break;
6244       }
6245       case doubleType: ListAdd(specs, MkSpecifier(DOUBLE)); break;
6246       case floatType: ListAdd(specs, MkSpecifier(FLOAT)); break;
6247       case charType: ListAdd(specs, MkSpecifier(CHAR)); break;
6248       case shortType: ListAdd(specs, MkSpecifier(SHORT)); break;
6249       case int64Type: ListAdd(specs, MkSpecifier(INT64)); break;
6250       case intType: 
6251       default:
6252          ListAdd(specs, MkSpecifier(INT)); break;
6253    }
6254 }
6255
6256 // WARNING : This function expects a null terminated string since it recursively concatenate...
6257 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
6258 {
6259    if(type)
6260    {
6261       switch(type.kind)
6262       {
6263          case classType:
6264             if(type._class && type._class.string)
6265             {
6266                // TODO: typed_object does not fully qualify the type, as it may have taken up an actual class (Stored in _class) from overriding
6267                //       look into merging with thisclass ?
6268                if(type.classObjectType == typedObject)
6269                   strcat(string, "typed_object");
6270                else if(fullName)
6271                   strcat(string, type._class.string);
6272                else
6273                {
6274                   if(type._class.registered)
6275                      strcat(string, type._class.registered.name);
6276                   else
6277                      strcat(string, type._class.string);                     
6278                }
6279             }
6280             break;
6281          case pointerType:
6282          {
6283             /*Type funcType;
6284             for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6285             if(funcType && funcType.kind == functionType)
6286             {
6287                Type param;
6288                PrintType(funcType.returnType, string, false, fullName);
6289                strcat(string, "(*");
6290                if(printName || funcType.thisClass)
6291                {
6292                   strcat(string, " ");
6293                   if(funcType.thisClass)
6294                   {
6295                      strcat(string, funcType.thisClass.string);
6296                      strcat(string, "::");
6297                   }
6298                   if(type.name)
6299                      strcat(string, type.name);
6300                }
6301                strcat(string, ")(");
6302                for(param = funcType.params.first; param; param = param.next)
6303                {
6304                   PrintType(param, string, false, fullName);
6305                   if(param.next) strcat(string, ", ");
6306                }
6307                strcat(string, ")");               
6308             }
6309             else*/
6310             {
6311                _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
6312                strcat(string, " *");
6313             }
6314             break;
6315          }
6316          case voidType: strcat(string, "void"); break;
6317          case intType:  strcat(string, type.isSigned ? "int" : "uint"); break;
6318          case int64Type:  strcat(string, type.isSigned ? "int64" : "uint64"); break;
6319          case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
6320          case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
6321          case floatType: strcat(string, "float"); break;
6322          case doubleType: strcat(string, "double"); break;
6323          case structType:
6324             if(type.enumName)
6325             {
6326                strcat(string, "struct ");
6327                strcat(string, type.enumName);
6328             }
6329             else if(type.typeName)
6330             {
6331                strcat(string, type.typeName);
6332             }
6333             else
6334             {
6335                /*
6336                strcat(string, "struct ");
6337                strcat(string,"(unnamed)");
6338                */
6339                Type member;
6340                strcat(string, "struct {");
6341                for(member = type.members.first; member; member = member.next)
6342                {
6343                   PrintType(member, string, true, fullName);
6344                   strcat(string,"; ");
6345                }
6346                strcat(string,"}");
6347             }
6348             break;
6349          case unionType:
6350             if(type.enumName)
6351             {
6352                strcat(string, "union ");
6353                strcat(string, type.enumName);
6354             }
6355             else if(type.typeName)
6356             {
6357                strcat(string, type.typeName);
6358             }
6359             else
6360             {
6361                strcat(string, "union ");
6362                strcat(string,"(unnamed)");
6363             }
6364             break;
6365          case enumType:
6366             if(type.enumName)
6367             {
6368                strcat(string, "enum ");
6369                strcat(string, type.enumName);
6370             }
6371             else if(type.typeName)
6372             {
6373                strcat(string, type.typeName);
6374             }
6375             else
6376                strcat(string, "enum");
6377             break;
6378          case functionType:
6379          {
6380             if(printFunction)
6381             {
6382                if(type.dllExport)
6383                   strcat(string, "dllexport ");
6384                PrintType(type.returnType, string, false, fullName);
6385                strcat(string, " ");
6386             }
6387             
6388             // DANGER: Testing This
6389             if(printName)
6390             {
6391                if(type.name)
6392                {
6393                   if(fullName)
6394                      strcat(string, type.name);
6395                   else
6396                   {
6397                      char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
6398                      if(name) name += 2; else name = type.name;
6399                      strcat(string, name);
6400                   }
6401                }
6402 #ifdef _DEBUG
6403                else
6404                {
6405                   printf("");
6406                }
6407 #endif
6408             }
6409
6410             if(printFunction)
6411             {
6412                Type param;
6413                strcat(string, "(");
6414                for(param = type.params.first; param; param = param.next)
6415                {
6416                   PrintType(param, string, true, fullName);
6417                   if(param.next) strcat(string, ", ");
6418                }
6419                strcat(string, ")");
6420             }
6421             break;
6422          }
6423          case arrayType:
6424          {
6425             /*Type funcType;
6426             for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6427             if(funcType && funcType.kind == functionType)
6428             {
6429                Type param;
6430                PrintType(funcType.returnType, string, false, fullName);
6431                strcat(string, "(*");
6432                if(printName || funcType.thisClass)
6433                {
6434                   strcat(string, " ");
6435                   if(funcType.thisClass)
6436                   {
6437                      strcat(string, funcType.thisClass.string);
6438                      strcat(string, "::");
6439                   }
6440                   if(type.name)
6441                      strcat(string, type.name);
6442                }
6443                strcat(string, ")(");
6444                for(param = funcType.params.first; param; param = param.next)
6445                {
6446                   PrintType(param, string, false, fullName);
6447                   if(param.next) strcat(string, ", ");
6448                }
6449                strcat(string, ")");               
6450             }
6451             else*/
6452             {
6453                char baseType[1024], size[256];
6454                Type arrayType = type;
6455                baseType[0] = '\0';
6456                size[0] = '\0';
6457
6458                while(arrayType.kind == TypeKind::arrayType)
6459                {
6460                   strcat(size, "[");
6461                   if(arrayType.enumClass)
6462                      strcat(size, arrayType.enumClass.string);
6463                   else if(arrayType.arraySizeExp)
6464                      PrintExpression(arrayType.arraySizeExp, size);
6465                   //sprintf(string, "%s[%s]", baseType, size); 
6466                   strcat(size, "]");
6467
6468                   arrayType = arrayType.arrayType;
6469                }
6470                _PrintType(arrayType, baseType, printName, printFunction, fullName);
6471                strcat(string, baseType);
6472                strcat(string, size);
6473             }
6474
6475             /*
6476                PrintType(type.arrayType, baseType, printName, fullName);
6477                if(type.enumClass)
6478                   strcpy(size, type.enumClass.string);
6479                else if(type.arraySizeExp)
6480                   PrintExpression(type.arraySizeExp, size);
6481                //sprintf(string, "%s[%s]", baseType, size); 
6482                strcat(string, baseType);
6483                strcat(string, "[");
6484                strcat(string, size); 
6485                strcat(string, "]");
6486                */
6487
6488             printName = false;
6489             break;
6490          }
6491          case ellipsisType:
6492             strcat(string, "...");
6493             break;
6494          case methodType:
6495             _PrintType(type.method.dataType, string, false, printFunction, fullName);
6496             break;
6497          case subClassType:
6498             strcat(string, "subclass(");
6499             strcat(string, type._class ? type._class.string : "int");
6500             strcat(string, ")");                  
6501             break;
6502          case templateType:
6503             strcat(string, type.templateParameter.identifier.string);
6504             break;
6505          case thisClassType:
6506             strcat(string, "thisclass");
6507             break;
6508          case vaListType:
6509          strcat(string, "__builtin_va_list");
6510             break;
6511 #ifdef _DEBUG
6512          default:
6513             printf("");
6514 #endif
6515       }
6516       if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
6517       {
6518          strcat(string, " ");
6519          strcat(string, type.name);
6520       }
6521    }
6522 }
6523
6524 void PrintType(Type type, char * string, bool printName, bool fullName)
6525 {
6526    Type funcType;
6527    for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6528    if(funcType && funcType.kind == functionType && type != funcType)
6529    {
6530       char typeString[1024];
6531       Type param;
6532
6533       PrintType(funcType.returnType, string, false, fullName);
6534       strcat(string, "(");
6535       _PrintType(type, string, printName, false, fullName);
6536       strcat(string, ")");
6537       /*
6538       if(type.name)
6539          strcat(string, type.name);
6540       else
6541       {
6542          printf("");
6543       }
6544       */
6545       strcat(string, "(");
6546       for(param = funcType.params.first; param; param = param.next)
6547       {
6548          PrintType(param, string, true, fullName);
6549          if(param.next) strcat(string, ", ");
6550       }
6551       strcat(string, ")");
6552    }
6553    else
6554       _PrintType(type, string, printName, true, fullName);
6555    if(type.bitFieldCount)
6556    {
6557       char count[100];
6558       sprintf(count, ":%d", type.bitFieldCount);
6559       strcat(string, count);
6560    }
6561 }
6562
6563 static Type FindMember(Type type, char * string)
6564 {
6565    Type memberType;
6566    for(memberType = type.members.first; memberType; memberType = memberType.next)
6567    {
6568       if(!memberType.name)
6569       {
6570          Type subType = FindMember(memberType, string);
6571          if(subType)
6572             return subType;
6573       }
6574       else if(!strcmp(memberType.name, string))
6575          return memberType;
6576    }
6577    return null;
6578 }
6579
6580 Type FindMemberAndOffset(Type type, char * string, uint * offset)
6581 {
6582    Type memberType;
6583    for(memberType = type.members.first; memberType; memberType = memberType.next)
6584    {
6585       if(!memberType.name)
6586       {
6587          Type subType = FindMember(memberType, string);
6588          if(subType)
6589          {
6590             *offset += memberType.offset;
6591             return subType;
6592          }
6593       }
6594       else if(!strcmp(memberType.name, string))
6595       {
6596          *offset += memberType.offset;
6597          return memberType;
6598       }
6599    }
6600    return null;
6601 }
6602
6603 Expression ParseExpressionString(char * expression)
6604 {
6605    fileInput = TempFile { };
6606    fileInput.Write(expression, 1, strlen(expression));
6607    fileInput.Seek(0, start);
6608
6609    echoOn = false;
6610    parsedExpression = null;
6611    resetScanner();
6612    expression_yyparse();
6613    delete fileInput;
6614
6615    return parsedExpression;
6616 }
6617
6618 static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassCheck)
6619 {
6620    Identifier id = exp.identifier;
6621    Method method = null;
6622    Property prop = null;
6623    DataMember member = null;
6624    ClassProperty classProp = null;
6625
6626    if(_class && _class.type == enumClass)
6627    {
6628       NamedLink value = null;
6629       Class enumClass = eSystem_FindClass(privateModule, "enum");
6630       if(enumClass)
6631       {
6632          Class baseClass;
6633          for(baseClass = _class; baseClass && baseClass.type == ClassType::enumClass; baseClass = baseClass.base)
6634          {
6635             EnumClassData e = ACCESS_CLASSDATA(baseClass, enumClass);
6636             for(value = e.values.first; value; value = value.next)
6637             {
6638                if(!strcmp(value.name, id.string))
6639                   break;
6640             }
6641             if(value)
6642             {
6643                char constant[256];
6644
6645                FreeExpContents(exp);
6646
6647                exp.type = constantExp;
6648                exp.isConstant = true;
6649                if(!strcmp(baseClass.dataTypeString, "int"))
6650                   sprintf(constant, "%d",value.data);
6651                else
6652                   sprintf(constant, "0x%X",value.data);
6653                exp.constant = CopyString(constant);
6654                //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
6655                exp.expType = MkClassType(baseClass.fullName);
6656                break;
6657             }
6658          }
6659       }
6660       if(value)
6661          return true;
6662    }
6663    if((method = eClass_FindMethod(_class, id.string, privateModule)))
6664    {
6665       ProcessMethodType(method);
6666       exp.expType = Type
6667       {
6668          refCount = 1;
6669          kind = methodType;
6670          method = method;
6671          // Crash here?
6672          // TOCHECK: Put it back to what it was...
6673          // methodClass = _class;
6674          methodClass = (skipIDClassCheck || (id && id._class)) ? _class : null;
6675       };
6676       //id._class = null;
6677       return true;
6678    }
6679    else if((prop = eClass_FindProperty(_class, id.string, privateModule)))
6680    {
6681       if(!prop.dataType)
6682          ProcessPropertyType(prop);
6683       exp.expType = prop.dataType;
6684       if(prop.dataType) prop.dataType.refCount++;
6685       return true;
6686    }
6687    else if((member = eClass_FindDataMember(_class, id.string, privateModule, null, null)))
6688    {
6689       if(!member.dataType)
6690          member.dataType = ProcessTypeString(member.dataTypeString, false);
6691       exp.expType = member.dataType;
6692       if(member.dataType) member.dataType.refCount++;
6693       return true;
6694    }
6695    else if((classProp = eClass_FindClassProperty(_class, id.string)))
6696    {
6697       if(!classProp.dataType)
6698          classProp.dataType = ProcessTypeString(classProp.dataTypeString, false);
6699
6700       if(classProp.constant)
6701       {
6702          FreeExpContents(exp);
6703
6704          exp.isConstant = true;
6705          if(classProp.dataType.kind == pointerType && classProp.dataType.type.kind == charType)
6706          {
6707             //char constant[256];
6708             exp.type = stringExp;
6709             exp.constant = QMkString((char *)classProp.Get(_class));
6710          }
6711          else
6712          {
6713             char constant[256];
6714             exp.type = constantExp;
6715             sprintf(constant, "%d",classProp.Get(_class));
6716             exp.constant = CopyString(constant);
6717          }
6718       }
6719       else
6720       {
6721          // TO IMPLEMENT...
6722       }
6723
6724       exp.expType = classProp.dataType;
6725       if(classProp.dataType) classProp.dataType.refCount++;
6726       return true;
6727    }
6728    return false;
6729 }
6730
6731 static GlobalData ScanGlobalData(NameSpace nameSpace, char * name)
6732 {
6733    BinaryTree * tree = &nameSpace.functions;
6734    GlobalData data = (GlobalData)tree->FindString(name);
6735    NameSpace * child;
6736    if(!data)
6737    {
6738       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
6739       {
6740          data = ScanGlobalData(child, name);
6741          if(data)
6742             break;
6743       }
6744    }
6745    return data;
6746 }
6747
6748 static GlobalData FindGlobalData(char * name)
6749 {
6750    int start = 0, c;
6751    NameSpace * nameSpace;
6752    nameSpace = globalData;
6753    for(c = 0; name[c]; c++)
6754    {
6755       if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
6756       {
6757          NameSpace * newSpace;
6758          char * spaceName = new char[c - start + 1];
6759          strncpy(spaceName, name + start, c - start);
6760          spaceName[c-start] = '\0';
6761          newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
6762          delete spaceName;
6763          if(!newSpace)
6764             return null;
6765          nameSpace = newSpace;
6766          if(name[c] == ':') c++;
6767          start = c+1;
6768       }
6769    }
6770    if(c - start)
6771    {
6772       return ScanGlobalData(nameSpace, name + start);
6773    }
6774    return null;
6775 }
6776
6777 static int definedExpStackPos;
6778 static void * definedExpStack[512];
6779
6780 // This function makes checkedExp equivalent to newExp, ending up freeing newExp
6781 void ReplaceExpContents(Expression checkedExp, Expression newExp)
6782 {
6783    Expression prev = checkedExp.prev, next = checkedExp.next;
6784
6785    FreeExpContents(checkedExp);
6786    FreeType(checkedExp.expType);
6787    FreeType(checkedExp.destType);
6788
6789    *checkedExp = *newExp;
6790
6791    delete newExp;
6792
6793    checkedExp.prev = prev;
6794    checkedExp.next = next;
6795 }
6796
6797 void ApplyAnyObjectLogic(Expression e)
6798 {
6799    Type destType = /*(e.destType && e.destType.kind == ellipsisType) ? ellipsisDestType : */e.destType;
6800    if(destType && (/*destType.classObjectType == ClassObjectType::typedObject || */destType.classObjectType == anyObject))
6801    {
6802       //if(e.destType && e.destType.kind == ellipsisType) usedEllipsis = true;
6803       //ellipsisDestType = destType;
6804       if(e && e.expType)
6805       {
6806          Type type = e.expType;
6807          Class _class = null;
6808          //Type destType = e.destType;
6809
6810          if(type.kind == classType && type._class && type._class.registered)
6811          {
6812             _class = type._class.registered;
6813          }
6814          else if(type.kind == subClassType)
6815          {
6816             _class = FindClass("ecere::com::Class").registered;
6817          }
6818          else
6819          {
6820             char string[1024] = "";
6821             Symbol classSym;
6822
6823             PrintType(type, string, false, true);
6824             classSym = FindClass(string);
6825             if(classSym) _class = classSym.registered;
6826          }
6827
6828          if((_class && (_class.type == enumClass || _class.type == unitClass || _class.type == bitClass || _class.type == systemClass) && strcmp(_class.fullName, "class") && strcmp(_class.fullName, "ecere::com::Class")) || // Patched so that class isn't considered SYSTEM...
6829             (!e.expType.classObjectType && (((type.kind != pointerType && type.kind != subClassType && (type.kind != classType || !type._class || !type._class.registered || type._class.registered.type == structClass))) ||
6830             destType.byReference)))
6831          {
6832             if(!_class || strcmp(_class.fullName, "char *"))     // TESTING THIS WITH NEW String class...
6833             {
6834                Expression checkedExp = e, newExp;
6835
6836                while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
6837                {
6838                   if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
6839                   {
6840                      if(checkedExp.type == extensionCompoundExp)
6841                      {
6842                         checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
6843                      }
6844                      else
6845                         checkedExp = checkedExp.list->last;
6846                   }
6847                   else if(checkedExp.type == castExp)
6848                      checkedExp = checkedExp.cast.exp;
6849                }
6850
6851                if(checkedExp && checkedExp.type == opExp && checkedExp.op.op == '*' && !checkedExp.op.exp1)
6852                {
6853                   newExp = checkedExp.op.exp2;
6854                   checkedExp.op.exp2 = null;
6855                   FreeExpContents(checkedExp);
6856                   
6857                   if(e.expType && e.expType.passAsTemplate)
6858                   {
6859                      char size[100];
6860                      ComputeTypeSize(e.expType);
6861                      sprintf(size, "%d", e.expType.size);
6862                      newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
6863                         MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
6864                            MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
6865                   }
6866
6867                   ReplaceExpContents(checkedExp, newExp);
6868                   e.byReference = true;
6869                }
6870                else if(!e.byReference || (_class && _class.type == noHeadClass))     // TESTING THIS HERE...
6871                {
6872                   Expression checkedExp, newExp;
6873
6874                   {
6875                      // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
6876                      bool hasAddress =
6877                         e.type == identifierExp ||
6878                         (e.type == ExpressionType::memberExp && e.member.memberType == dataMember) ||
6879                         (e.type == ExpressionType::pointerExp && e.member.memberType == dataMember) ||
6880                         (e.type == opExp && !e.op.exp1 && e.op.op == '*') ||
6881                         e.type == indexExp;
6882
6883                      if(_class && _class.type != noHeadClass && _class.type != normalClass && _class.type != structClass && !hasAddress)
6884                      {
6885                         Context context = PushContext();
6886                         Declarator decl;
6887                         OldList * specs = MkList();
6888                         char typeString[1024];
6889                         Expression newExp { };
6890
6891                         typeString[0] = '\0';
6892                         *newExp = *e;
6893
6894                         //if(e.destType) e.destType.refCount++;
6895                         // if(exp.expType) exp.expType.refCount++;
6896                         newExp.prev = null;
6897                         newExp.next = null;
6898                         newExp.expType = null;
6899
6900                         PrintType(e.expType, typeString, false, true);
6901                         decl = SpecDeclFromString(typeString, specs, null);
6902                         newExp.destType = ProcessType(specs, decl);
6903
6904                         curContext = context;
6905                         e.type = extensionCompoundExp;
6906                         e.compound = MkCompoundStmt(
6907                            MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(
6908                               MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))), 
6909
6910                            MkListOne(MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier("__internalValue"))))));
6911                         
6912                         {
6913                            Type type = e.destType;
6914                            e.destType = { };
6915                            CopyTypeInto(e.destType, type);
6916                            e.destType.refCount = 1;
6917                            e.destType.classObjectType = none;
6918                            FreeType(type);
6919                         }
6920
6921                         e.compound.compound.context = context;
6922                         PopContext(context);
6923                         curContext = context.parent;
6924                      }
6925                   }
6926
6927                   // TODO: INTEGRATE THIS WITH VERSION ABOVE WHICH WAS ADDED TO ENCOMPASS OTHER CASE (*pointer)
6928                   checkedExp = e;
6929                   while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
6930                   {
6931                      if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
6932                      {
6933                         if(checkedExp.type == extensionCompoundExp)
6934                         {
6935                            checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
6936                         }
6937                         else
6938                            checkedExp = checkedExp.list->last;
6939                      }
6940                      else if(checkedExp.type == castExp)
6941                         checkedExp = checkedExp.cast.exp;
6942                   }
6943                   {
6944                      Expression operand { };
6945                      operand = *checkedExp;
6946                      checkedExp.destType = null;
6947                      checkedExp.expType = null;
6948                      checkedExp.Clear();
6949                      checkedExp.type = opExp;
6950                      checkedExp.op.op = '&';
6951                      checkedExp.op.exp1 = null;
6952                      checkedExp.op.exp2 = operand;
6953
6954                      //newExp = MkExpOp(null, '&', checkedExp);
6955                   }
6956                   //ReplaceExpContents(checkedExp, newExp);
6957                }
6958             }
6959          }
6960       }
6961    }
6962    {
6963       // If expression type is a simple class, make it an address
6964       // FixReference(e, true);
6965    }
6966 //#if 0
6967    if((!destType || destType.kind == ellipsisType || destType.kind == voidType) && e.expType && (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) && 
6968       (e.expType.byReference || (e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
6969          (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass ) )))
6970    {
6971       if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class"))
6972       {
6973          return;  // LEAVE THIS CASE (typed_object & :: methods 's this) TO PASS 2 FOR NOW
6974       }
6975       else
6976       {
6977          Expression thisExp { };
6978
6979          *thisExp = *e;
6980          thisExp.prev = null;
6981          thisExp.next = null;
6982          e.Clear();
6983
6984          e.type = bracketsExp;
6985          e.list = MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(thisExp))));
6986          if(thisExp.expType.kind == classType && thisExp.expType._class && thisExp.expType._class.registered && thisExp.expType._class.registered.type == noHeadClass)
6987             ((Expression)e.list->first).byReference = true;
6988
6989          /*if(thisExp.expType.kind == classType && thisExp.expType._class && thisExp.expType._class.registered && !strcmp(thisExp.expType._class.registered.name, "class"))
6990          {
6991             e.expType = thisExp.expType;
6992             e.expType.refCount++;
6993          }
6994          else*/
6995          {
6996             e.expType = { };
6997             CopyTypeInto(e.expType, thisExp.expType);
6998             e.expType.byReference = false;
6999             e.expType.refCount = 1;
7000
7001             if(e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
7002                (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass))
7003             {
7004                e.expType.classObjectType = none;
7005             }
7006          }
7007       }
7008    }
7009 // TOFIX: Try this for a nice IDE crash!
7010 //#endif
7011    // The other way around
7012    else 
7013 //#endif
7014    if(destType && e.expType && 
7015          //e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class") &&
7016          (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) && 
7017          !destType.classObjectType && /*(destType.kind != pointerType || !destType.type || destType.type.kind != voidType) &&*/ destType.kind != voidType)
7018    {
7019       if(destType.kind == ellipsisType)
7020       {
7021          Compiler_Error($"Unspecified type\n");
7022       }
7023       else if(!(destType.truth && e.expType.kind == classType && e.expType._class && e.expType._class.registered && e.expType._class.registered.type == structClass))
7024       {
7025          bool byReference = e.expType.byReference;
7026          Expression thisExp { };
7027          Declarator decl;
7028          OldList * specs = MkList();
7029          char typeString[1024]; // Watch buffer overruns
7030          Type type;
7031          ClassObjectType backupClassObjectType;
7032
7033          if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && strcmp(e.expType._class.registered.name, "class"))
7034             type = e.expType;
7035          else
7036             type = destType;            
7037
7038          backupClassObjectType = type.classObjectType;
7039
7040          type.classObjectType = none;
7041
7042          typeString[0] = '\0';
7043          PrintType(type, typeString, false, true);
7044          decl = SpecDeclFromString(typeString, specs, null);
7045
7046          type.classObjectType = backupClassObjectType;
7047
7048          *thisExp = *e;
7049          thisExp.prev = null;
7050          thisExp.next = null;
7051          e.Clear();
7052
7053          if( ( type.kind == classType && type._class && type._class.registered && strcmp(type._class.registered.fullName, "ecere::com::Instance") &&
7054                    (type._class.registered.type == systemClass || type._class.registered.type == bitClass || 
7055                     type._class.registered.type == enumClass || type._class.registered.type == unitClass) ) ||
7056              (type.kind != pointerType && type.kind != arrayType && type.kind != classType) ||
7057              (!destType.byReference && byReference && (destType.kind != pointerType || type.kind != pointerType)))
7058          {
7059             e.type = opExp;
7060             e.op.op = '*';
7061             e.op.exp1 = null;
7062             e.op.exp2 = MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), thisExp);
7063          }
7064          else
7065          {
7066             e.type = castExp;
7067             e.cast.typeName = MkTypeName(specs, decl);
7068             e.cast.exp = thisExp;
7069             e.byReference = true;
7070          }
7071          e.expType = type;
7072          e.destType = destType;
7073          type.refCount++;
7074          destType.refCount++;
7075       }
7076    }
7077 }
7078
7079 void ProcessExpressionType(Expression exp)
7080 {
7081    bool unresolved = false;
7082    Location oldyylloc = yylloc;
7083    bool notByReference = false;
7084 #ifdef _DEBUG   
7085    char debugExpString[4096];
7086    debugExpString[0] = '\0';
7087    PrintExpression(exp, debugExpString);
7088 #endif
7089    if(!exp || exp.expType) 
7090       return;
7091
7092    //eSystem_Logf("%s\n", expString);
7093    
7094    // Testing this here
7095    yylloc = exp.loc;
7096    switch(exp.type)
7097    {
7098       case identifierExp:
7099       {
7100          Identifier id = exp.identifier;
7101          if(!id) return;
7102
7103          // DOING THIS LATER NOW...
7104          if(id._class && id._class.name)
7105          {
7106             id.classSym = id._class.symbol; // FindClass(id._class.name);
7107             /* TODO: Name Space Fix ups
7108             if(!id.classSym)
7109                id.nameSpace = eSystem_FindNameSpace(privateModule, id._class.name);
7110             */
7111          }
7112
7113          /* WHY WAS THIS COMMENTED OUT? if(!strcmp(id.string, "__thisModule"))
7114          {
7115             exp.expType = ProcessTypeString("Module", true);
7116             break;
7117          }
7118          else */if(strstr(id.string, "__ecereClass") == id.string)
7119          {
7120             exp.expType = ProcessTypeString("ecere::com::Class", true);
7121             break;
7122          }
7123          else if(id._class && (id.classSym || (id._class.name && !strcmp(id._class.name, "property"))))
7124          {
7125             // Added this here as well
7126             ReplaceClassMembers(exp, thisClass);
7127             if(exp.type != identifierExp)
7128             {
7129                ProcessExpressionType(exp);
7130                break;
7131             }
7132
7133             if(id.classSym && ResolveIdWithClass(exp, id.classSym.registered, false))
7134                break;
7135          }
7136          else
7137          {
7138             Symbol symbol = FindSymbol(id.string, curContext, topContext /*exp.destType ? topContext : globalContext*/, false, id._class && id._class.name == null);
7139             // Enums should be resolved here (Special pass in opExp to fix identifiers not seen as enum on the first pass)
7140             if(!symbol/* && exp.destType*/)
7141             {
7142                if(exp.destType && CheckExpressionType(exp, exp.destType, false))
7143                   break;
7144                else
7145                {
7146                   if(thisClass)
7147                   {
7148                      ReplaceClassMembers(exp, thisClass ? thisClass : currentClass);
7149                      if(exp.type != identifierExp)
7150                      {
7151                         ProcessExpressionType(exp);
7152                         break;
7153                      }
7154                   }
7155                   // Static methods called from inside the _class
7156                   else if(currentClass && !id._class)
7157                   {
7158                      if(ResolveIdWithClass(exp, currentClass, true))
7159                         break;
7160                   }
7161                   symbol = FindSymbol(id.string, topContext.parent, globalContext, false, id._class && id._class.name == null);
7162                }
7163             }
7164
7165             // If we manage to resolve this symbol
7166             if(symbol)
7167             {
7168                Type type = symbol.type;
7169                Class _class = (type && type.kind == classType && type._class) ? type._class.registered : null;
7170
7171                if(_class && !strcmp(id.string, "this") && !type.classObjectType)
7172                {
7173                   Context context = SetupTemplatesContext(_class);
7174                   type = ReplaceThisClassType(_class);
7175                   FinishTemplatesContext(context);
7176                   if(type) type.refCount = 0;   // We'll be incrementing it right below...
7177                }
7178
7179                FreeSpecifier(id._class);
7180                id._class = null;
7181                delete id.string;
7182                id.string = CopyString(symbol.string);
7183
7184                id.classSym = null;
7185                exp.expType = type;
7186                if(type)
7187                   type.refCount++;
7188                if(type && (type.kind == enumType || (_class && _class.type == enumClass)))
7189                   // Add missing cases here... enum Classes...
7190                   exp.isConstant = true;
7191
7192                // TOCHECK: Why was !strcmp(id.string, "this") commented out?
7193                if(symbol.isParam || !strcmp(id.string, "this"))
7194                {
7195                   if(_class && _class.type == structClass)
7196                      exp.byReference = true;
7197                   
7198                   //TESTING COMMENTING THIS OUT IN FAVOR OF ApplyAnyObjectLogic
7199                   /*if(type && _class && (type.classObjectType == typedObject || type.classObjectType == anyObject) && 
7200                      ((_class.type == unitClass || _class.type == enumClass || _class.type == bitClass) || 
7201                      (type.byReference && (_class.type == normalClass || _class.type == noHeadClass))))
7202                   {
7203                      Identifier id = exp.identifier;
7204                      exp.type = bracketsExp;
7205                      exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(id)));
7206                   }*/
7207                }
7208
7209                if(symbol.isIterator)
7210                {
7211                   if(symbol.isIterator == 3)
7212                   {
7213                      exp.type = bracketsExp;
7214                      exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(exp.identifier)));
7215                      ((Expression)exp.list->first).op.exp2.expType = exp.expType;
7216                      exp.expType = null;
7217                      ProcessExpressionType(exp);                     
7218                   }
7219                   else if(symbol.isIterator != 4)
7220                   {
7221                      exp.type = memberExp;
7222                      exp.member.exp = MkExpIdentifier(exp.identifier);
7223                      exp.member.exp.expType = exp.expType;
7224                      /*if(symbol.isIterator == 6)
7225                         exp.member.member = MkIdentifier("key");
7226                      else*/
7227                         exp.member.member = MkIdentifier("data");
7228                      exp.expType = null;
7229                      ProcessExpressionType(exp);
7230                   }
7231                }
7232                break;
7233             }
7234             else
7235             {
7236                DefinedExpression definedExp = null;
7237                if(thisNameSpace && !(id._class && !id._class.name))
7238                {
7239                   char name[1024];
7240                   strcpy(name, thisNameSpace);
7241                   strcat(name, "::");
7242                   strcat(name, id.string);
7243                   definedExp = eSystem_FindDefine(privateModule, name);
7244                }
7245                if(!definedExp)
7246                   definedExp = eSystem_FindDefine(privateModule, id.string);
7247                if(definedExp)
7248                {
7249                   int c;
7250                   for(c = 0; c<definedExpStackPos; c++)
7251                      if(definedExpStack[c] == definedExp)
7252                         break;
7253                   if(c == definedExpStackPos && c < sizeof(definedExpStack) / sizeof(void *))
7254                   {
7255                      Location backupYylloc = yylloc;
7256                      definedExpStack[definedExpStackPos++] = definedExp;
7257                      fileInput = TempFile { };
7258                      fileInput.Write(definedExp.value, 1, strlen(definedExp.value));
7259                      fileInput.Seek(0, start);
7260
7261                      echoOn = false;
7262                      parsedExpression = null;
7263                      resetScanner();
7264                      expression_yyparse();
7265                      delete fileInput;
7266
7267                      yylloc = backupYylloc;
7268
7269                      if(parsedExpression)
7270                      {
7271                         FreeIdentifier(id);
7272                         exp.type = bracketsExp;
7273                         exp.list = MkListOne(parsedExpression);
7274                         parsedExpression.loc = yylloc;
7275                         ProcessExpressionType(exp);
7276                         definedExpStackPos--;
7277                         return;
7278                      }
7279                      definedExpStackPos--;
7280                   }
7281                   else
7282                   {
7283                      if(inCompiler)
7284                      {
7285                         Compiler_Error($"Recursion in defined expression %s\n", id.string);
7286                      }
7287                   }
7288                }
7289                else
7290                {
7291                   GlobalData data = null;
7292                   if(thisNameSpace && !(id._class && !id._class.name))
7293                   {
7294                      char name[1024];
7295                      strcpy(name, thisNameSpace);
7296                      strcat(name, "::");
7297                      strcat(name, id.string);
7298                      data = FindGlobalData(name);
7299                   }
7300                   if(!data)
7301                      data = FindGlobalData(id.string);
7302                   if(data)
7303                   {
7304                      DeclareGlobalData(data);
7305                      exp.expType = data.dataType;
7306                      if(data.dataType) data.dataType.refCount++;
7307
7308                      delete id.string;
7309                      id.string = CopyString(data.fullName);
7310                      FreeSpecifier(id._class);
7311                      id._class = null;
7312
7313                      break;
7314                   }
7315                   else
7316                   {
7317                      GlobalFunction function = null;
7318                      if(thisNameSpace && !(id._class && !id._class.name))
7319                      {
7320                         char name[1024];
7321                         strcpy(name, thisNameSpace);
7322                         strcat(name, "::");
7323                         strcat(name, id.string);
7324                         function = eSystem_FindFunction(privateModule, name);
7325                      }
7326                      if(!function)
7327                         function = eSystem_FindFunction(privateModule, id.string);
7328                      if(function)
7329                      {
7330                         char name[1024];
7331                         delete id.string;
7332                         id.string = CopyString(function.name);
7333                         name[0] = 0;
7334
7335                         if(function.module.importType != staticImport && (!function.dataType || !function.dataType.dllExport))
7336                            strcpy(name, "__ecereFunction_");
7337                         FullClassNameCat(name, id.string, false); // Why is this using FullClassNameCat ?
7338                         if(DeclareFunction(function, name))
7339                         {
7340                            delete id.string;
7341                            id.string = CopyString(name);
7342                         }
7343                         exp.expType = function.dataType;
7344                         if(function.dataType) function.dataType.refCount++;
7345
7346                         FreeSpecifier(id._class);
7347                         id._class = null;
7348
7349                         break;
7350                      }
7351                   }
7352                }
7353             }
7354          }
7355          unresolved = true;
7356          break;
7357       }
7358       case instanceExp:
7359       {
7360          Class _class;
7361          // Symbol classSym;
7362
7363          if(!exp.instance._class)
7364          {
7365             if(exp.destType && exp.destType.kind == classType && exp.destType._class)
7366             {
7367                exp.instance._class = MkSpecifierName(exp.destType._class.string);
7368             }
7369 #ifdef _DEBUG
7370             else 
7371             {
7372                printf("");               
7373             }
7374 #endif
7375          }
7376
7377          //classSym = FindClass(exp.instance._class.fullName);
7378          //_class = classSym ? classSym.registered : null;
7379
7380          ProcessInstantiationType(exp.instance);
7381          exp.isConstant = exp.instance.isConstant;
7382
7383          /*
7384          if(_class.type == unitClass && _class.base.type != systemClass)
7385          {
7386             {
7387                Type destType = exp.destType;
7388
7389                exp.destType = MkClassType(_class.base.fullName);
7390                exp.expType = MkClassType(_class.fullName);
7391                CheckExpressionType(exp, exp.destType, true);
7392
7393                exp.destType = destType;
7394             }
7395             exp.expType = MkClassType(_class.fullName);
7396          }
7397          else*/
7398          if(exp.instance._class)
7399          {
7400             exp.expType = MkClassType(exp.instance._class.name);
7401             /*if(exp.expType._class && exp.expType._class.registered && 
7402                (exp.expType._class.registered.type == normalClass || exp.expType._class.registered.type == noHeadClass))
7403                exp.expType.byReference = true;*/
7404          }         
7405          break;
7406       }
7407       case constantExp:
7408       {
7409          if(!exp.expType)
7410          {
7411             Type type
7412             {
7413                refCount = 1;
7414                constant = true;
7415             };
7416             exp.expType = type;
7417
7418             if(exp.constant[0] == '\'')
7419             {
7420                if((int)((byte *)exp.constant)[1] > 127)
7421                {
7422                   int nb;
7423                   unichar ch = UTF8GetChar(exp.constant + 1, &nb);
7424                   if(nb < 2) ch = exp.constant[1];
7425                   delete exp.constant;
7426                   exp.constant = PrintUInt(ch);
7427                   // type.kind = (ch > 0xFFFF) ? intType : shortType;
7428                   type.kind = classType; //(ch > 0xFFFF) ? intType : shortType;
7429                   type._class = FindClass("unichar");
7430
7431                   type.isSigned = false;
7432                }
7433                else
7434                {
7435                   type.kind = charType;
7436                   type.isSigned = true;
7437                }
7438             }
7439             else if(strchr(exp.constant, '.'))
7440             {
7441                char ch = exp.constant[strlen(exp.constant)-1];
7442                if(ch == 'f')
7443                   type.kind = floatType;
7444                else
7445                   type.kind = doubleType;
7446                type.isSigned = true;
7447             }
7448             else
7449             {
7450                if(exp.constant[0] == '0' && exp.constant[1])
7451                   type.isSigned = false;
7452                else if(strchr(exp.constant, 'L') || strchr(exp.constant, 'l'))
7453                   type.isSigned = false;
7454                else if(strtoll(exp.constant, null, 0) > MAXINT)
7455                   type.isSigned = false;
7456                else
7457                   type.isSigned = true;
7458                type.kind = intType;
7459             }
7460             exp.isConstant = true;
7461          }
7462          break;
7463       }
7464       case stringExp:
7465       {
7466          exp.isConstant = true;      // Why wasn't this constant?
7467          exp.expType = Type
7468          {
7469             refCount = 1;
7470             kind = pointerType;
7471             type = Type
7472             {
7473                refCount = 1;
7474                kind = charType;
7475                constant = true;
7476             }
7477          };
7478          break;
7479       }
7480       case newExp:
7481       case new0Exp:
7482          ProcessExpressionType(exp._new.size);
7483          exp.expType = Type
7484          {
7485             refCount = 1;
7486             kind = pointerType;
7487             type = ProcessType(exp._new.typeName.qualifiers, exp._new.typeName.declarator);
7488          };
7489          DeclareType(exp.expType.type, false, false);
7490          break;
7491       case renewExp:
7492       case renew0Exp:
7493          ProcessExpressionType(exp._renew.size);
7494          ProcessExpressionType(exp._renew.exp);
7495          exp.expType = Type
7496          {
7497             refCount = 1;
7498             kind = pointerType;
7499             type = ProcessType(exp._renew.typeName.qualifiers, exp._renew.typeName.declarator);
7500          };
7501          DeclareType(exp.expType.type, false, false);
7502          break;
7503       case opExp:
7504       {
7505          bool assign = false, boolResult = false, boolOps = false;
7506          Type type1 = null, type2 = null;
7507          bool useDestType = false, useSideType = false;
7508          Location oldyylloc = yylloc;
7509          bool useSideUnit = false;
7510
7511          // Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
7512          Type dummy
7513          {
7514             count = 1;
7515             refCount = 1;
7516          };
7517
7518          switch(exp.op.op)
7519          {
7520             // Assignment Operators
7521             case '=': 
7522             case MUL_ASSIGN:
7523             case DIV_ASSIGN:
7524             case MOD_ASSIGN:
7525             case ADD_ASSIGN:
7526             case SUB_ASSIGN:
7527             case LEFT_ASSIGN:
7528             case RIGHT_ASSIGN:
7529             case AND_ASSIGN:
7530             case XOR_ASSIGN:
7531             case OR_ASSIGN:
7532                assign = true;
7533                break;
7534             // boolean Operators
7535             case '!':
7536                // Expect boolean operators
7537                //boolOps = true;
7538                //boolResult = true;
7539                break;
7540             case AND_OP:
7541             case OR_OP:
7542                // Expect boolean operands
7543                boolOps = true;
7544                boolResult = true;
7545                break;
7546             // Comparisons
7547             case EQ_OP:
7548             case '<':
7549             case '>':
7550             case LE_OP:
7551             case GE_OP:
7552             case NE_OP:
7553                // Gives boolean result
7554                boolResult = true;
7555                useSideType = true;
7556                break;
7557             case '+':
7558             case '-':
7559                useSideUnit = true;
7560
7561                // Just added these... testing
7562             case '|':
7563             case '&':
7564             case '^':
7565
7566             // DANGER: Verify units
7567             case '/':
7568             case '%':
7569             case '*':
7570                
7571                if(exp.op.op != '*' || exp.op.exp1)
7572                {
7573                   useSideType = true;
7574                   useDestType = true;
7575                }
7576                break;
7577
7578             /*// Implement speed etc.
7579             case '*':
7580             case '/':
7581                break;
7582             */
7583          }
7584          if(exp.op.op == '&')
7585          {
7586             // Added this here earlier for Iterator address as key
7587             if(!exp.op.exp1 && exp.op.exp2 && exp.op.exp2.type == identifierExp && exp.op.exp2.identifier)
7588             {
7589                Identifier id = exp.op.exp2.identifier;
7590                Symbol symbol = FindSymbol(id.string, curContext, topContext, false, id._class && id._class.name == null);
7591                if(symbol && symbol.isIterator == 2)
7592                {
7593                   exp.type = memberExp;
7594                   exp.member.exp = exp.op.exp2;
7595                   exp.member.member = MkIdentifier("key");
7596                   exp.expType = null;
7597                   exp.op.exp2.expType = symbol.type;
7598                   symbol.type.refCount++;
7599                   ProcessExpressionType(exp);
7600                   FreeType(dummy);
7601                   break;
7602                }
7603                // exp.op.exp2.usage.usageRef = true;
7604             }
7605          }
7606
7607          //dummy.kind = TypeDummy;
7608
7609          if(exp.op.exp1)
7610          {
7611             if(exp.destType && exp.destType.kind == classType &&
7612                exp.destType._class && exp.destType._class.registered && useDestType &&
7613                
7614               ((exp.destType._class.registered.type == unitClass && useSideUnit) || 
7615                exp.destType._class.registered.type == enumClass ||
7616                exp.destType._class.registered.type == bitClass
7617                )) 
7618
7619               //(exp.destType._class.registered.type == unitClass || exp.destType._class.registered.type == enumClass) && useDestType)
7620             {
7621                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7622                exp.op.exp1.destType = exp.destType;
7623                if(exp.destType)
7624                   exp.destType.refCount++;
7625             }
7626             else if(!assign)
7627             {
7628                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7629                exp.op.exp1.destType = dummy;
7630                dummy.refCount++;               
7631             }
7632
7633             // TESTING THIS HERE...
7634             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count++;
7635             ProcessExpressionType(exp.op.exp1);
7636             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count--;
7637
7638             if(exp.op.exp1.destType == dummy)
7639             {
7640                FreeType(dummy);
7641                exp.op.exp1.destType = null;
7642             }
7643             type1 = exp.op.exp1.expType;
7644          }
7645
7646          if(exp.op.exp2)
7647          {
7648             char expString[10240];
7649             expString[0] = '\0';
7650             if(exp.op.exp2.type == instanceExp && !exp.op.exp2.instance._class)
7651             {
7652                if(exp.op.exp1)
7653                {
7654                   exp.op.exp2.destType = exp.op.exp1.expType;
7655                   if(exp.op.exp1.expType)
7656                      exp.op.exp1.expType.refCount++;
7657                }
7658                else
7659                {
7660                   exp.op.exp2.destType = exp.destType;
7661                   if(exp.destType)
7662                      exp.destType.refCount++;
7663                }
7664
7665                if(type1) type1.refCount++;
7666                exp.expType = type1;
7667             }
7668             else if(assign)
7669             {
7670                if(inCompiler)
7671                   PrintExpression(exp.op.exp2, expString);
7672
7673                if(type1 && type1.kind == pointerType)
7674                {
7675                   if(exp.op.op == MUL_ASSIGN || exp.op.op == DIV_ASSIGN ||exp.op.op == MOD_ASSIGN ||exp.op.op == LEFT_ASSIGN ||exp.op.op == RIGHT_ASSIGN ||
7676                      exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN)
7677                      Compiler_Error($"operator %s illegal on pointer\n", exp.op.op);
7678                   else if(exp.op.op == '=')
7679                   {
7680                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7681                      exp.op.exp2.destType = type1;
7682                      if(type1)
7683                         type1.refCount++;
7684                   }
7685                }
7686                else
7687                {
7688                   // Don't convert to the type for those... (e.g.: Degrees a; a /= 2;) 
7689                   if(exp.op.op == MUL_ASSIGN || exp.op.op == DIV_ASSIGN ||exp.op.op == MOD_ASSIGN ||exp.op.op == LEFT_ASSIGN ||exp.op.op == RIGHT_ASSIGN/* ||
7690                      exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN*/);
7691                   else
7692                   {
7693                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7694                      exp.op.exp2.destType = type1;
7695                      if(type1)
7696                         type1.refCount++;
7697                   }
7698                }
7699                if(type1) type1.refCount++;
7700                exp.expType = type1;
7701             }
7702             else if(exp.destType && exp.destType.kind == classType &&
7703                exp.destType._class && exp.destType._class.registered && 
7704                
7705                   ((exp.destType._class.registered.type == unitClass && useDestType && useSideUnit) || 
7706                   (exp.destType._class.registered.type == enumClass && useDestType)) 
7707                   )
7708             {
7709                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7710                exp.op.exp2.destType = exp.destType;
7711                if(exp.destType)
7712                   exp.destType.refCount++;
7713             }
7714             else
7715             {
7716                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7717                exp.op.exp2.destType = dummy;
7718                dummy.refCount++;
7719             }
7720
7721             // TESTING THIS HERE... (DANGEROUS)
7722             if(type1 && boolResult && useSideType && type1.kind == classType && type1._class && type1._class.registered && 
7723                (type1._class.registered.type == bitClass || type1._class.registered.type == enumClass))
7724             {
7725                FreeType(exp.op.exp2.destType);
7726                exp.op.exp2.destType = type1;
7727                type1.refCount++;
7728             }
7729             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count++;
7730             ProcessExpressionType(exp.op.exp2);
7731             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
7732
7733             if(assign && type1 && type1.kind == pointerType && exp.op.exp2.expType)
7734             {
7735                if(exp.op.exp2.expType.kind == int64Type || exp.op.exp2.expType.kind == intType || exp.op.exp2.expType.kind == shortType || exp.op.exp2.expType.kind == charType)
7736                {
7737                   if(exp.op.op != '=' && type1.type.kind == voidType) 
7738                      Compiler_Error($"void *: unknown size\n");
7739                }
7740                else if(exp.op.exp2.expType.kind == pointerType || exp.op.exp2.expType.kind == arrayType || exp.op.exp2.expType.kind == functionType || exp.op.exp2.expType.kind == methodType|| 
7741                            (type1.type.kind == voidType && exp.op.exp2.expType.kind == classType && exp.op.exp2.expType._class.registered &&
7742                               (exp.op.exp2.expType._class.registered.type == normalClass || 
7743                               exp.op.exp2.expType._class.registered.type == structClass ||
7744                               exp.op.exp2.expType._class.registered.type == noHeadClass)))
7745                {
7746                   if(exp.op.op == ADD_ASSIGN)
7747                      Compiler_Error($"cannot add two pointers\n");                   
7748                }
7749                else if((exp.op.exp2.expType.kind == classType && type1.kind == pointerType && type1.type.kind == classType && 
7750                   type1.type._class == exp.op.exp2.expType._class && exp.op.exp2.expType._class.registered && exp.op.exp2.expType._class.registered.type == structClass))
7751                {
7752                   if(exp.op.op == ADD_ASSIGN)
7753                      Compiler_Error($"cannot add two pointers\n");                   
7754                }
7755                else if(inCompiler)
7756                {
7757                   char type1String[1024];
7758                   char type2String[1024];
7759                   type1String[0] = '\0';
7760                   type2String[0] = '\0';
7761                   
7762                   PrintType(exp.op.exp2.expType, type1String, false, true);
7763                   PrintType(type1, type2String, false, true);
7764                   ChangeCh(expString, '\n', ' ');
7765                   Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1String, type2String);
7766                }
7767             }
7768
7769             if(exp.op.exp2.destType == dummy)
7770             {
7771                FreeType(dummy);
7772                exp.op.exp2.destType = null;
7773             }
7774
7775             type2 = exp.op.exp2.expType;
7776          }
7777
7778          dummy.kind = voidType;
7779
7780          if(exp.op.op == SIZEOF)
7781          {
7782             exp.expType = Type
7783             {
7784                refCount = 1;
7785                kind = intType;
7786             };
7787             exp.isConstant = true;
7788          }
7789          // Get type of dereferenced pointer
7790          else if(exp.op.op == '*' && !exp.op.exp1)
7791          {
7792             exp.expType = Dereference(type2);
7793             if(type2 && type2.kind == classType)
7794                notByReference = true;
7795          }
7796          else if(exp.op.op == '&' && !exp.op.exp1)
7797             exp.expType = Reference(type2);
7798          else if(!assign)
7799          {
7800             if(boolOps)
7801             {
7802                if(exp.op.exp1) 
7803                {
7804                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7805                   exp.op.exp1.destType = MkClassType("bool");
7806                   exp.op.exp1.destType.truth = true;
7807                   if(!exp.op.exp1.expType)
7808                      ProcessExpressionType(exp.op.exp1);
7809                   else
7810                      CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
7811                   FreeType(exp.op.exp1.expType);
7812                   exp.op.exp1.expType = MkClassType("bool");
7813                   exp.op.exp1.expType.truth = true;
7814                }
7815                if(exp.op.exp2) 
7816                {
7817                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7818                   exp.op.exp2.destType = MkClassType("bool");
7819                   exp.op.exp2.destType.truth = true;
7820                   if(!exp.op.exp2.expType)
7821                      ProcessExpressionType(exp.op.exp2);
7822                   else
7823                      CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
7824                   FreeType(exp.op.exp2.expType);
7825                   exp.op.exp2.expType = MkClassType("bool");
7826                   exp.op.exp2.expType.truth = true;
7827                }
7828             }
7829             else if(exp.op.exp1 && exp.op.exp2 && 
7830                ((useSideType /*&& 
7831                      (useSideUnit || 
7832                         ((!type1 || type1.kind != classType || type1._class.registered.type != unitClass) &&
7833                          (!type2 || type2.kind != classType || type2._class.registered.type != unitClass)))*/) ||
7834                   ((!type1 || type1.kind != classType || !strcmp(type1._class.string, "String")) && 
7835                   (!type2 || type2.kind != classType || !strcmp(type2._class.string, "String")))))
7836             {
7837                if(type1 && type2 &&
7838                   // If either both are class or both are not class
7839                   ((type1.kind == classType && strcmp(type1._class.string, "String")) == (type2.kind == classType && strcmp(type2._class.string, "String"))))
7840                {
7841                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7842                   exp.op.exp2.destType = type1;
7843                   type1.refCount++;
7844                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7845                   exp.op.exp1.destType = type2;
7846                   type2.refCount++;
7847                   // Warning here for adding Radians + Degrees with no destination type
7848                   if(!boolResult && type1.kind == classType && (!exp.destType || exp.destType.kind != classType) && 
7849                      type1._class.registered && type1._class.registered.type == unitClass && 
7850                      type2._class.registered && type2._class.registered.type == unitClass && 
7851                      type1._class.registered != type2._class.registered)
7852                      Compiler_Warning($"operating on %s and %s with an untyped result, assuming %s\n",
7853                         type1._class.string, type2._class.string, type1._class.string);
7854
7855                   if(type1.kind == pointerType && type1.type.kind == templateType && type2.kind != pointerType)
7856                   {
7857                      Expression argExp = GetTemplateArgExp(type1.type.templateParameter, thisClass, true);
7858                      if(argExp)
7859                      {
7860                         Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
7861
7862                         exp.op.exp1 = MkExpBrackets(MkListOne(MkExpCast(
7863                            MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), 
7864                            exp.op.exp1)));
7865
7866                         ProcessExpressionType(exp.op.exp1);
7867
7868                         if(type2.kind != pointerType)
7869                         {
7870                            ProcessExpressionType(classExp);
7871
7872                            exp.op.exp2 = MkExpBrackets(MkListOne(MkExpOp(exp.op.exp2, '*', 
7873                               // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
7874                               MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
7875                                  // noHeadClass
7876                                  MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("5")),
7877                                     OR_OP, 
7878                                  // normalClass
7879                                  MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("0"))))),
7880                                     MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
7881                                        MkPointer(null, null), null)))),                                  
7882                                        MkExpMember(classExp, MkIdentifier("typeSize"))))))));
7883
7884                            if(!exp.op.exp2.expType)
7885                               type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
7886
7887                            ProcessExpressionType(exp.op.exp2);
7888                         }
7889                      }
7890                   }
7891                   
7892                   if(!boolResult && ((type1.kind == pointerType || type1.kind == arrayType || (type1.kind == classType && !strcmp(type1._class.string, "String"))) && (type2.kind == int64Type || type2.kind == intType || type2.kind == shortType || type2.kind == charType)))
7893                   {
7894                      if(type1.kind != classType && type1.type.kind == voidType) 
7895                         Compiler_Error($"void *: unknown size\n");
7896                      exp.expType = type1;
7897                      if(type1) type1.refCount++;
7898                   }
7899                   else if(!boolResult && ((type2.kind == pointerType || type2.kind == arrayType || (type2.kind == classType && !strcmp(type2._class.string, "String"))) && (type1.kind == int64Type || type1.kind == intType || type1.kind == shortType || type1.kind == charType)))
7900                   {
7901                      if(type2.kind != classType && type2.type.kind == voidType) 
7902                         Compiler_Error($"void *: unknown size\n");
7903                      exp.expType = type2;
7904                      if(type2) type2.refCount++;
7905                   }
7906                   else if((type1.kind == pointerType && type2.kind != pointerType && type2.kind != arrayType && type2.kind != functionType && type2.kind != methodType && type2.kind != classType && type2.kind != subClassType) ||
7907                           (type2.kind == pointerType && type1.kind != pointerType && type1.kind != arrayType && type1.kind != functionType && type1.kind != methodType && type1.kind != classType && type1.kind != subClassType))
7908                   {
7909                      Compiler_Warning($"different levels of indirection\n");
7910                   }
7911                   else 
7912                   {
7913                      bool success = false;
7914                      if(type1.kind == pointerType && type2.kind == pointerType)
7915                      {
7916                         if(exp.op.op == '+')
7917                            Compiler_Error($"cannot add two pointers\n");
7918                         else if(exp.op.op == '-')
7919                         {
7920                            // Pointer Subtraction gives integer
7921                            if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false))
7922                            {
7923                               exp.expType = Type
7924                               {
7925                                  kind = intType;
7926                                  refCount = 1;
7927                               };
7928                               success = true;
7929
7930                               if(type1.type.kind == templateType)
7931                               {
7932                                  Expression argExp = GetTemplateArgExp(type1.type.templateParameter, thisClass, true);
7933                                  if(argExp)
7934                                  {
7935                                     Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
7936
7937                                     ProcessExpressionType(classExp);
7938
7939                                     exp.type = bracketsExp;
7940                                     exp.list = MkListOne(MkExpOp(
7941                                        MkExpBrackets(MkListOne(MkExpOp(
7942                                              MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp1)))
7943                                              , exp.op.op, 
7944                                              MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp2)))))), '/', 
7945                                           
7946                                              //MkExpMember(classExp, MkIdentifier("typeSize"))
7947
7948                                              // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
7949                                              MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
7950                                                 // noHeadClass
7951                                                 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass"))),
7952                                                    OR_OP, 
7953                                                 // normalClass
7954                                                 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass")))))),
7955                                                    MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
7956                                                       MkPointer(null, null), null)))),                                  
7957                                                       MkExpMember(classExp, MkIdentifier("typeSize")))))
7958
7959                                              
7960                                              ));
7961                                     
7962                                     ProcessExpressionType(((Expression)exp.list->first).op.exp2);
7963                                     FreeType(dummy);
7964                                     return;                                       
7965                                  }
7966                               }
7967                            }
7968                         }
7969                      }
7970
7971                      if(!success && exp.op.exp1.type == constantExp)
7972                      {
7973                         // If first expression is constant, try to match that first
7974                         if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
7975                         {
7976                            if(exp.expType) FreeType(exp.expType);
7977                            exp.expType = exp.op.exp1.destType;
7978                            if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
7979                            success = true;
7980                         }
7981                         else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
7982                         {
7983                            if(exp.expType) FreeType(exp.expType);
7984                            exp.expType = exp.op.exp2.destType;
7985                            if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
7986                            success = true;
7987                         }
7988                      }
7989                      else if(!success)
7990                      {
7991                         if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
7992                         {
7993                            if(exp.expType) FreeType(exp.expType);
7994                            exp.expType = exp.op.exp2.destType;
7995                            if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
7996                            success = true;
7997                         }
7998                         else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
7999                         {
8000                            if(exp.expType) FreeType(exp.expType);
8001                            exp.expType = exp.op.exp1.destType;
8002                            if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8003                            success = true;
8004                         }
8005                      }
8006                      if(!success)
8007                      {
8008                         char expString1[10240];
8009                         char expString2[10240];
8010                         char type1[1024];
8011                         char type2[1024];
8012                         expString1[0] = '\0';
8013                         expString2[0] = '\0';
8014                         type1[0] = '\0';
8015                         type2[0] = '\0';
8016                         if(inCompiler)
8017                         {
8018                            PrintExpression(exp.op.exp1, expString1);
8019                            ChangeCh(expString1, '\n', ' ');
8020                            PrintExpression(exp.op.exp2, expString2);
8021                            ChangeCh(expString2, '\n', ' ');
8022                            PrintType(exp.op.exp1.expType, type1, false, true);
8023                            PrintType(exp.op.exp2.expType, type2, false, true);
8024                         }
8025
8026                         Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1, expString2, type2);
8027                      }
8028                   }
8029                }
8030                // ADDED THESE TWO FROM OUTSIDE useSideType CHECK
8031                else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type2 && type1 && type2.kind == classType && type1.kind != classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
8032                {
8033                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8034                   // Convert e.g. / 4 into / 4.0
8035                   exp.op.exp1.destType = type2._class.registered.dataType;
8036                   if(type2._class.registered.dataType)
8037                      type2._class.registered.dataType.refCount++;
8038                   CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8039                   exp.expType = type2;
8040                   if(type2) type2.refCount++;
8041                }
8042                else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type1 && type2 && type1.kind == classType && type2.kind != classType && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
8043                {
8044                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8045                   // Convert e.g. / 4 into / 4.0
8046                   exp.op.exp2.destType = type1._class.registered.dataType;
8047                   if(type1._class.registered.dataType)
8048                      type1._class.registered.dataType.refCount++;
8049                   CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8050                   exp.expType = type1;
8051                   if(type1) type1.refCount++;
8052                }
8053                else if(type1)
8054                {
8055                   bool valid = false;
8056
8057                   if(!boolResult && useSideUnit && type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8058                   {
8059                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8060
8061                      if(!type1._class.registered.dataType)
8062                         type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
8063                      exp.op.exp2.destType = type1._class.registered.dataType;
8064                      exp.op.exp2.destType.refCount++;
8065
8066                      CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8067                      type2 = exp.op.exp2.destType;
8068
8069                      exp.expType = type2;
8070                      type2.refCount++;
8071                   }
8072                   
8073                   if(!boolResult && useSideUnit && type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8074                   {
8075                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8076
8077                      if(!type2._class.registered.dataType)
8078                         type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
8079                      exp.op.exp1.destType = type2._class.registered.dataType;
8080                      exp.op.exp1.destType.refCount++;
8081
8082                      CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8083                      type1 = exp.op.exp1.destType;
8084                      exp.expType = type1;
8085                      type1.refCount++;
8086                   }
8087
8088                   // TESTING THIS NEW CODE
8089                   if(!boolResult || exp.op.op == '>' || exp.op.op == '<')
8090                   {
8091                      if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass && exp.op.exp2.expType)
8092                      {
8093                         if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false))
8094                         {
8095                            if(exp.expType) FreeType(exp.expType);
8096                            exp.expType = exp.op.exp1.expType;
8097                            if(exp.op.exp2.expType) exp.op.exp1.expType.refCount++;
8098                            valid = true;
8099                         }
8100                      }
8101
8102                      else if(type2 && (type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass && exp.op.exp1.expType))
8103                      {
8104                         if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false))
8105                         {
8106                            if(exp.expType) FreeType(exp.expType);
8107                            exp.expType = exp.op.exp2.expType;
8108                            if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8109                            valid = true;
8110                         }
8111                      }
8112                   }
8113
8114                   if(!valid)
8115                   {
8116                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8117                      exp.op.exp2.destType = type1;
8118                      type1.refCount++;
8119
8120                      /*
8121                      // Maybe this was meant to be an enum...
8122                      if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8123                      {
8124                         Type oldType = exp.op.exp2.expType;
8125                         exp.op.exp2.expType = null;
8126                         if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8127                            FreeType(oldType);
8128                         else
8129                            exp.op.exp2.expType = oldType;
8130                      }
8131                      */
8132
8133                      /*
8134                      // TESTING THIS HERE... LATEST ADDITION
8135                      if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8136                      {
8137                         if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8138                         exp.op.exp2.destType = type2._class.registered.dataType;
8139                         if(type2._class.registered.dataType)
8140                            type2._class.registered.dataType.refCount++;
8141                         CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8142                         
8143                         //exp.expType = type2._class.registered.dataType; //type2;
8144                         //if(type2) type2.refCount++;
8145                      }
8146
8147                      // TESTING THIS HERE... LATEST ADDITION
8148                      if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8149                      {
8150                         if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8151                         exp.op.exp1.destType = type1._class.registered.dataType;
8152                         if(type1._class.registered.dataType)
8153                            type1._class.registered.dataType.refCount++;
8154                         CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8155                         exp.expType = type1._class.registered.dataType; //type1;
8156                         if(type1) type1.refCount++;
8157                      }
8158                      */
8159
8160                      if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8161                      {
8162                         if(exp.expType) FreeType(exp.expType);
8163                         exp.expType = exp.op.exp2.destType;
8164                         if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8165                      }
8166                      else if(type1 && type2)
8167                      {
8168                         char expString1[10240];
8169                         char expString2[10240];
8170                         char type1String[1024];
8171                         char type2String[1024];
8172                         expString1[0] = '\0';
8173                         expString2[0] = '\0';
8174                         type1String[0] = '\0';
8175                         type2String[0] = '\0';
8176                         if(inCompiler)
8177                         {
8178                            PrintExpression(exp.op.exp1, expString1);
8179                            ChangeCh(expString1, '\n', ' ');
8180                            PrintExpression(exp.op.exp2, expString2);
8181                            ChangeCh(expString2, '\n', ' ');
8182                            PrintType(exp.op.exp1.expType, type1String, false, true);
8183                            PrintType(exp.op.exp2.expType, type2String, false, true);
8184                         }
8185
8186                         Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
8187
8188                         if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8189                         {
8190                            exp.expType = exp.op.exp1.expType;
8191                            if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
8192                         }
8193                         else if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8194                         {
8195                            exp.expType = exp.op.exp2.expType;
8196                            if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8197                         }
8198                      }
8199                   }
8200                }
8201                else if(type2)
8202                {
8203                   // Maybe this was meant to be an enum...
8204                   if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8205                   {
8206                      Type oldType = exp.op.exp1.expType;
8207                      exp.op.exp1.expType = null;
8208                      if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8209                         FreeType(oldType);
8210                      else
8211                         exp.op.exp1.expType = oldType;
8212                   }
8213
8214                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8215                   exp.op.exp1.destType = type2;
8216                   type2.refCount++;
8217                   /*
8218                   // TESTING THIS HERE... LATEST ADDITION
8219                   if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8220                   {
8221                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8222                      exp.op.exp1.destType = type1._class.registered.dataType;
8223                      if(type1._class.registered.dataType)
8224                         type1._class.registered.dataType.refCount++;
8225                   }
8226
8227                   // TESTING THIS HERE... LATEST ADDITION
8228                   if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8229                   {
8230                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8231                      exp.op.exp2.destType = type2._class.registered.dataType;
8232                      if(type2._class.registered.dataType)
8233                         type2._class.registered.dataType.refCount++;
8234                   }
8235                   */
8236
8237                   if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8238                   {
8239                      if(exp.expType) FreeType(exp.expType);
8240                      exp.expType = exp.op.exp1.destType;
8241                      if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8242                   }
8243                }
8244             }
8245             else if(type2 && (!type1 || (type2.kind == classType && type1.kind != classType)))
8246             {
8247                if(type1 && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
8248                {
8249                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8250                   // Convert e.g. / 4 into / 4.0
8251                   exp.op.exp1.destType = type2._class.registered.dataType;
8252                   if(type2._class.registered.dataType)
8253                      type2._class.registered.dataType.refCount++;
8254                   CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8255                }
8256                if(exp.op.op == '!')
8257                {
8258                   exp.expType = MkClassType("bool");
8259                   exp.expType.truth = true;
8260                }
8261                else
8262                {
8263                   exp.expType = type2;
8264                   if(type2) type2.refCount++;
8265                }
8266             }
8267             else if(type1 && (!type2 || (type1.kind == classType && type2.kind != classType)))
8268             {
8269                if(type2 && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
8270                {
8271                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8272                   // Convert e.g. / 4 into / 4.0
8273                   exp.op.exp2.destType = type1._class.registered.dataType;
8274                   if(type1._class.registered.dataType)
8275                      type1._class.registered.dataType.refCount++;
8276                   CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8277                }
8278                exp.expType = type1;
8279                if(type1) type1.refCount++;
8280             }
8281          }
8282          
8283          yylloc = exp.loc;
8284          if(exp.op.exp1 && !exp.op.exp1.expType)
8285          {
8286             char expString[10000];
8287             expString[0] = '\0';
8288             if(inCompiler)
8289             {
8290                PrintExpression(exp.op.exp1, expString);
8291                ChangeCh(expString, '\n', ' ');
8292             }
8293             if(expString[0])
8294                Compiler_Error($"couldn't determine type of %s\n", expString);
8295          }
8296          if(exp.op.exp2 && !exp.op.exp2.expType)
8297          {
8298             char expString[10240];
8299             expString[0] = '\0';
8300             if(inCompiler)
8301             {
8302                PrintExpression(exp.op.exp2, expString);
8303                ChangeCh(expString, '\n', ' ');
8304             }
8305             if(expString[0])
8306                Compiler_Error($"couldn't determine type of %s\n", expString);
8307          }
8308
8309          if(boolResult)
8310          {
8311             FreeType(exp.expType);
8312             exp.expType = MkClassType("bool");
8313             exp.expType.truth = true;
8314          }
8315
8316          if(exp.op.op != SIZEOF)
8317             exp.isConstant = (!exp.op.exp1 || exp.op.exp1.isConstant) &&
8318                (!exp.op.exp2 || exp.op.exp2.isConstant);
8319
8320          if(exp.op.op == SIZEOF && exp.op.exp2.expType)
8321          {
8322             DeclareType(exp.op.exp2.expType, false, false);
8323          }
8324
8325          yylloc = oldyylloc;
8326
8327          FreeType(dummy);
8328          break;
8329       }
8330       case bracketsExp:
8331       case extensionExpressionExp:
8332       {
8333          Expression e;
8334          exp.isConstant = true;
8335          for(e = exp.list->first; e; e = e.next)
8336          {
8337             bool inced = false;
8338             if(!e.next)
8339             {
8340                FreeType(e.destType);
8341                e.destType = exp.destType;
8342                if(e.destType) { exp.destType.refCount++; e.destType.count++; inced = true; }
8343             }
8344             ProcessExpressionType(e);
8345             if(inced)
8346                exp.destType.count--;
8347             if(!exp.expType && !e.next)
8348             {
8349                exp.expType = e.expType;
8350                if(e.expType) e.expType.refCount++;
8351             }
8352             if(!e.isConstant)
8353                exp.isConstant = false;
8354          }
8355
8356          // In case a cast became a member...
8357          e = exp.list->first;
8358          if(!e.next && e.type == memberExp)
8359          {
8360             // Preserve prev, next
8361             Expression next = exp.next, prev = exp.prev;
8362
8363
8364             FreeType(exp.expType);
8365             FreeType(exp.destType);
8366             delete exp.list;
8367             
8368             *exp = *e;
8369
8370             exp.prev = prev;
8371             exp.next = next;
8372
8373             delete e;
8374
8375             ProcessExpressionType(exp);
8376          }
8377          break;
8378       }
8379       case indexExp:
8380       {
8381          Expression e;
8382          exp.isConstant = true;
8383
8384          ProcessExpressionType(exp.index.exp);
8385          if(!exp.index.exp.isConstant)
8386             exp.isConstant = false;
8387
8388          if(exp.index.exp.expType)
8389          {
8390             Type source = exp.index.exp.expType;
8391             if(source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
8392                eClass_IsDerived(source._class.registered, containerClass) && 
8393                source._class.registered.templateArgs)
8394             {
8395                Class _class = source._class.registered;
8396                exp.expType = ProcessTypeString(_class.templateArgs[2].dataTypeString, false);
8397
8398                if(exp.index.index && exp.index.index->last)
8399                {
8400                   ((Expression)exp.index.index->last).destType = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
8401                }
8402             }
8403          }
8404
8405          for(e = exp.index.index->first; e; e = e.next)
8406          {
8407             if(!e.next && exp.index.exp.expType && exp.index.exp.expType.kind == arrayType && exp.index.exp.expType.enumClass)
8408             {
8409                if(e.destType) FreeType(e.destType);
8410                e.destType = MkClassType(exp.index.exp.expType.enumClass.string);
8411             }
8412             ProcessExpressionType(e);
8413             if(!e.next)
8414             {
8415                // Check if this type is int
8416             }
8417             if(!e.isConstant)
8418                exp.isConstant = false;
8419          }
8420
8421          if(!exp.expType)
8422             exp.expType = Dereference(exp.index.exp.expType);
8423          if(exp.expType)
8424             DeclareType(exp.expType, false, false);
8425          break;
8426       }
8427       case callExp:
8428       {
8429          Expression e;
8430          Type functionType;
8431          Type methodType = null;
8432          char name[1024];
8433          name[0] = '\0';
8434
8435          if(inCompiler)
8436          {
8437             PrintExpression(exp.call.exp,  name);
8438             if(exp.call.exp.expType && !exp.call.exp.expType.returnType)
8439             {
8440                //exp.call.exp.expType = null;
8441                PrintExpression(exp.call.exp,  name);
8442             }
8443          }
8444          if(exp.call.exp.type == identifierExp)
8445          {
8446             Expression idExp = exp.call.exp;
8447             Identifier id = idExp.identifier;
8448             if(!strcmp(id.string, "__ENDIAN_PAD"))
8449             {
8450                exp.expType = ProcessTypeString("int", true);
8451                if(exp.call.arguments && exp.call.arguments->first)
8452                   ProcessExpressionType(exp.call.arguments->first);
8453                break;
8454             }
8455             else if(!strcmp(id.string, "Max") ||
8456                !strcmp(id.string, "Min") ||
8457                !strcmp(id.string, "Sgn") ||
8458                !strcmp(id.string, "Abs"))
8459             {
8460                Expression a = null;
8461                Expression b = null;
8462                Expression tempExp1 = null, tempExp2 = null;
8463                if((!strcmp(id.string, "Max") ||
8464                   !strcmp(id.string, "Min")) && exp.call.arguments->count == 2)
8465                {
8466                   a = exp.call.arguments->first;
8467                   b = exp.call.arguments->last;
8468                   tempExp1 = a;
8469                   tempExp2 = b;
8470                }
8471                else if(exp.call.arguments->count == 1)
8472                {
8473                   a = exp.call.arguments->first;
8474                   tempExp1 = a;
8475                }
8476                
8477                if(a)
8478                {
8479                   exp.call.arguments->Clear();
8480                   idExp.identifier = null;
8481
8482                   FreeExpContents(exp);
8483
8484                   ProcessExpressionType(a);
8485                   if(b)
8486                      ProcessExpressionType(b);
8487
8488                   exp.type = bracketsExp;
8489                   exp.list = MkList();
8490
8491                   if(a.expType && (!b || b.expType))
8492                   {
8493                      if((!a.isConstant && a.type != identifierExp) || (b && !b.isConstant && b.type != identifierExp))
8494                      {
8495                         // Use the simpleStruct name/ids for now...
8496                         if(inCompiler)
8497                         {
8498                            OldList * specs = MkList();
8499                            OldList * decls = MkList();
8500                            Declaration decl;
8501                            char temp1[1024], temp2[1024];
8502
8503                            GetTypeSpecs(a.expType, specs);
8504
8505                            if(a && !a.isConstant && a.type != identifierExp)
8506                            {
8507                               sprintf(temp1, "__simpleStruct%d", curContext.simpleID++);
8508                               ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp1)), null));
8509                               tempExp1 = QMkExpId(temp1);
8510                               tempExp1.expType = a.expType;
8511                               if(a.expType)
8512                                  a.expType.refCount++;
8513                               ListAdd(exp.list, MkExpOp(CopyExpression(tempExp1), '=', a));
8514                            }
8515                            if(b && !b.isConstant && b.type != identifierExp)
8516                            {
8517                               sprintf(temp2, "__simpleStruct%d", curContext.simpleID++);
8518                               ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp2)), null));
8519                               tempExp2 = QMkExpId(temp2);
8520                               tempExp2.expType = b.expType;
8521                               if(b.expType)
8522                                  b.expType.refCount++;
8523                               ListAdd(exp.list, MkExpOp(CopyExpression(tempExp2), '=', b));
8524                            }                        
8525
8526                            decl = MkDeclaration(specs, decls);
8527                            if(!curCompound.compound.declarations)
8528                               curCompound.compound.declarations = MkList();
8529                            curCompound.compound.declarations->Insert(null, decl);
8530                         }
8531                      }
8532                   }
8533
8534                   if(!strcmp(id.string, "Max") || !strcmp(id.string, "Min"))
8535                   {
8536                      int op = (!strcmp(id.string, "Max")) ? '>' : '<';
8537                      ListAdd(exp.list, 
8538                         MkExpCondition(MkExpBrackets(MkListOne(
8539                            MkExpOp(CopyExpression(tempExp1), op, CopyExpression(tempExp2)))),
8540                            MkListOne(CopyExpression(tempExp1)), CopyExpression(tempExp2)));
8541                      exp.expType = a.expType;
8542                      if(a.expType)
8543                         a.expType.refCount++;
8544                   }
8545                   else if(!strcmp(id.string, "Abs"))
8546                   {
8547                      ListAdd(exp.list, 
8548                         MkExpCondition(MkExpBrackets(MkListOne(
8549                            MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8550                            MkListOne(MkExpOp(null, '-', CopyExpression(tempExp1))), CopyExpression(tempExp1)));
8551                      exp.expType = a.expType;
8552                      if(a.expType)
8553                         a.expType.refCount++;
8554                   }
8555                   else if(!strcmp(id.string, "Sgn"))
8556                   {
8557                      // ((!(a))?(0):(((a)<0)?(-1):(1)))
8558                      ListAdd(exp.list, 
8559                         MkExpCondition(MkExpBrackets(MkListOne(
8560                            MkExpOp(null, '!', CopyExpression(tempExp1)))), MkListOne(MkExpConstant("0")),
8561                               MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(
8562                                  MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8563                                  MkListOne(MkExpConstant("-1")), MkExpConstant("1"))))));
8564                      exp.expType = ProcessTypeString("int", false);
8565                   }
8566
8567                   FreeExpression(tempExp1);
8568                   if(tempExp2) FreeExpression(tempExp2);
8569
8570                   FreeIdentifier(id);
8571                   break;
8572                }
8573             }
8574          }
8575
8576          {
8577             Type dummy
8578             {
8579                count = 1;
8580                refCount = 1;
8581             };
8582             if(!exp.call.exp.destType)
8583             {
8584                exp.call.exp.destType = dummy;
8585                dummy.refCount++;
8586             }
8587             ProcessExpressionType(exp.call.exp);
8588             if(exp.call.exp.destType == dummy)
8589             {
8590                FreeType(dummy);
8591                exp.call.exp.destType = null;
8592             }
8593             FreeType(dummy);
8594          }
8595
8596          // Check argument types against parameter types
8597          functionType = exp.call.exp.expType;
8598
8599          if(functionType && functionType.kind == TypeKind::methodType)
8600          {
8601             methodType = functionType;
8602             functionType = methodType.method.dataType;
8603             
8604             //if(functionType.returnType && functionType.returnType.kind == thisClassType)
8605             // TOCHECK: Instead of doing this here could this be done per param?
8606             if(exp.call.exp.expType.usedClass)
8607             {
8608                char typeString[1024];
8609                typeString[0] = '\0';
8610                PrintType(functionType, typeString, true, true);
8611                if(strstr(typeString, "thisclass"))
8612                {
8613                   OldList * specs = MkList();
8614                   Declarator decl;
8615                   {
8616                      Context context = SetupTemplatesContext(exp.call.exp.expType.usedClass);
8617
8618                      decl = SpecDeclFromString(typeString, specs, null);
8619                      
8620                      // SET THIS TO FALSE WHEN PROCESSING THISCLASS OUTSIDE THE CLASS
8621                      if(thisClass != (exp.call.exp.expType.usedClass.templateClass ? exp.call.exp.expType.usedClass.templateClass :
8622                         exp.call.exp.expType.usedClass))
8623                         thisClassParams = false;
8624                      
8625                      ReplaceThisClassSpecifiers(specs, exp.call.exp.expType.usedClass);
8626                      {
8627                         Class backupThisClass = thisClass;
8628                         thisClass = exp.call.exp.expType.usedClass;
8629                         ProcessDeclarator(decl);
8630                         thisClass = backupThisClass;
8631                      }
8632
8633                      thisClassParams = true;
8634
8635                      functionType = ProcessType(specs, decl);
8636                      functionType.refCount = 0;
8637                      FinishTemplatesContext(context);
8638                   }
8639
8640                   FreeList(specs, FreeSpecifier);
8641                   FreeDeclarator(decl);
8642                 }
8643             }
8644          }
8645          if(functionType && functionType.kind == pointerType && functionType.type && functionType.type.kind == TypeKind::functionType)
8646          {
8647             Type type = functionType.type;
8648             if(!functionType.refCount)
8649             {
8650                functionType.type = null;
8651                FreeType(functionType);
8652             }
8653             //methodType = functionType;
8654             functionType = type;
8655          }
8656          if(functionType && functionType.kind != TypeKind::functionType)
8657          {
8658             Compiler_Error($"called object %s is not a function\n", name);
8659          }
8660          else if(functionType)
8661          {
8662             bool emptyParams = false, noParams = false;
8663             Expression e = exp.call.arguments ? exp.call.arguments->first : null;
8664             Type type = functionType.params.first;
8665             Expression memberExp = (exp.call.exp.type == ExpressionType::memberExp) ? exp.call.exp : null;
8666             int extra = 0;
8667             Location oldyylloc = yylloc;
8668
8669             if(!type) emptyParams = true;
8670
8671             // WORKING ON THIS:
8672             if(functionType.extraParam && e)
8673             {
8674                e.destType = MkClassType(functionType.thisClass.string);
8675                e = e.next;
8676             }
8677
8678             // WHY WAS THIS COMMENTED OUT ? Broke DisplaySystem::FontExtent(this ? displaySystem : null, font, text, len, width, height);
8679             if(!functionType.staticMethod)
8680             {
8681                if(memberExp && memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.kind == subClassType && 
8682                   memberExp.member.exp.expType._class)
8683                {
8684                   type = MkClassType(memberExp.member.exp.expType._class.string);
8685                   if(e)
8686                   {
8687                      e.destType = type;
8688                      e = e.next;
8689                      type = functionType.params.first;
8690                   }
8691                   else
8692                      type.refCount = 0;
8693                }
8694                else if(!memberExp && (functionType.thisClass || (methodType && methodType.methodClass)))
8695                {
8696                   type = MkClassType(functionType.thisClass ? functionType.thisClass.string : (methodType ? methodType.methodClass.fullName : null));
8697                   if(e)
8698                   {
8699                      e.destType = type;
8700                      e = e.next;
8701                      type = functionType.params.first;
8702                   }
8703                   else
8704                      type.refCount = 0;
8705                   //extra = 1;
8706                }
8707             }
8708
8709             if(type && type.kind == voidType)
8710             {
8711                noParams = true;
8712                if(!type.refCount) FreeType(type);
8713                type = null;
8714             }
8715
8716             for( ; e; e = e.next)
8717             {
8718                if(!type && !emptyParams)
8719                {
8720                   yylloc = e.loc;
8721                   if(methodType && methodType.methodClass)
8722                      Compiler_Error($"too many arguments for method %s::%s (%d given, expected %d)\n",
8723                         methodType.methodClass.fullName, methodType.method.name, exp.call.arguments->count,
8724                         noParams ? 0 : functionType.params.count);
8725                   else
8726                      Compiler_Error($"too many arguments for function %s (%d given, expected %d)\n",
8727                         name /*exp.call.exp.identifier.string*/, exp.call.arguments->count,
8728                         noParams ? 0 : functionType.params.count);
8729                   break;
8730                }
8731
8732                if(methodType && type && type.kind == templateType && type.templateParameter.type == TemplateParameterType::type)
8733                {
8734                   Type templatedType = null;
8735                   Class _class = methodType.usedClass;
8736                   ClassTemplateParameter curParam = null;
8737                   int id = 0;
8738                   if(_class && _class.templateArgs /*&& _class.templateClass*/)
8739                   {
8740                      Class sClass;
8741                      for(sClass = _class; sClass; sClass = sClass.base)
8742                      {
8743                         if(sClass.templateClass) sClass = sClass.templateClass;
8744                         id = 0;
8745                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
8746                         {
8747                            if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
8748                            {
8749                               Class nextClass;
8750                               for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
8751                               {
8752                                  if(nextClass.templateClass) nextClass = nextClass.templateClass;
8753                                  id += nextClass.templateParams.count;
8754                               }
8755                               break;
8756                            }
8757                            id++;
8758                         }
8759                         if(curParam) break;
8760                      }
8761                   }
8762                   if(curParam && _class.templateArgs[id].dataTypeString)
8763                   {
8764                      ClassTemplateArgument arg = _class.templateArgs[id];
8765                      {
8766                         Context context = SetupTemplatesContext(_class);
8767                      
8768                         /*if(!arg.dataType)
8769                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
8770                         templatedType = ProcessTypeString(arg.dataTypeString, false);
8771                         FinishTemplatesContext(context);
8772                      }
8773                      e.destType = templatedType;
8774                      if(templatedType)
8775                      {
8776                         templatedType.passAsTemplate = true;
8777                         // templatedType.refCount++;
8778                      }
8779                   }
8780                   else
8781                   {
8782                      e.destType = type;
8783                      if(type) type.refCount++;
8784                   }
8785                }
8786                else
8787                {
8788                   e.destType = type;
8789                   if(type) type.refCount++;
8790                }
8791                // Don't reach the end for the ellipsis
8792                if(type && type.kind != ellipsisType)
8793                {
8794                   Type next = type.next;
8795                   if(!type.refCount) FreeType(type);
8796                   type = next;
8797                }
8798             }
8799
8800             if(type && type.kind != ellipsisType)
8801             {
8802                if(methodType && methodType.methodClass)
8803                   Compiler_Warning($"not enough arguments for method %s::%s (%d given, expected %d)\n",
8804                      methodType.methodClass.fullName, methodType.method.name, exp.call.arguments ? exp.call.arguments->count : 0,
8805                      functionType.params.count + extra);
8806                else
8807                   Compiler_Warning($"not enough arguments for function %s (%d given, expected %d)\n",
8808                      name /*exp.call.exp.identifier.string*/, exp.call.arguments ? exp.call.arguments->count : 0,
8809                      functionType.params.count + extra);
8810             }
8811             yylloc = oldyylloc;
8812             if(type && !type.refCount) FreeType(type);
8813          }
8814          else
8815          {
8816             functionType = Type
8817             {
8818                refCount = 0;
8819                kind = TypeKind::functionType;
8820             };
8821
8822             if(exp.call.exp.type == identifierExp)
8823             {
8824                char * string = exp.call.exp.identifier.string;
8825                if(inCompiler)
8826                {
8827                   Symbol symbol;
8828                   Location oldyylloc = yylloc;
8829
8830                   yylloc = exp.call.exp.identifier.loc;
8831                   if(strstr(string, "__builtin_") == string);
8832                   else
8833                      Compiler_Warning($"%s undefined; assuming extern returning int\n", string);
8834                   symbol = Symbol { string = CopyString(string), type = ProcessTypeString("int()", true) };
8835                   globalContext.symbols.Add((BTNode)symbol);
8836                   if(strstr(symbol.string, "::"))
8837                      globalContext.hasNameSpace = true;
8838
8839                   yylloc = oldyylloc;
8840                }
8841             }
8842             else if(exp.call.exp.type == memberExp)
8843             {
8844                /*Compiler_Warning($"%s undefined; assuming returning int\n",
8845                   exp.call.exp.member.member.string);*/
8846             }
8847             else
8848                Compiler_Warning($"callable object undefined; extern assuming returning int\n");
8849
8850             if(!functionType.returnType)
8851             {
8852                functionType.returnType = Type
8853                {
8854                   refCount = 1;
8855                   kind = intType;
8856                };
8857             }
8858          }
8859          if(functionType && functionType.kind == TypeKind::functionType)
8860          {
8861             exp.expType = functionType.returnType;
8862
8863             if(functionType.returnType)
8864                functionType.returnType.refCount++;
8865
8866             if(!functionType.refCount)
8867                FreeType(functionType);
8868          }
8869
8870          if(exp.call.arguments)
8871          {
8872             for(e = exp.call.arguments->first; e; e = e.next)
8873             {
8874                Type destType = e.destType;
8875                ProcessExpressionType(e);
8876             }
8877          }
8878          break;
8879       }
8880       case memberExp:
8881       {
8882          Type type;
8883          Location oldyylloc = yylloc;
8884          bool thisPtr = (exp.member.exp && exp.member.exp.type == identifierExp && !strcmp(exp.member.exp.identifier.string, "this"));
8885          exp.thisPtr = thisPtr;
8886
8887          // DOING THIS LATER NOW...
8888          if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
8889          {
8890             exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
8891             /* TODO: Name Space Fix ups
8892             if(!exp.member.member.classSym)
8893                exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.fullName);
8894             */
8895          }
8896
8897          ProcessExpressionType(exp.member.exp);
8898          if(exp.member.exp.expType && exp.member.exp.expType.kind == classType && exp.member.exp.expType._class && 
8899             exp.member.exp.expType._class.registered && exp.member.exp.expType._class.registered.type == normalClass)
8900          {
8901             exp.isConstant = false;
8902          }
8903          else
8904             exp.isConstant = exp.member.exp.isConstant;
8905          type = exp.member.exp.expType;
8906
8907          yylloc = exp.loc;
8908
8909          if(type && (type.kind == templateType))
8910          {
8911             Class _class = thisClass ? thisClass : currentClass;
8912             ClassTemplateParameter param = null;
8913             if(_class)
8914             {
8915                for(param = _class.templateParams.first; param; param = param.next)
8916                {
8917                   if(param.type == identifier && exp.member.member && exp.member.member.string && !strcmp(param.name, exp.member.member.string))
8918                      break;
8919                }
8920             }
8921             if(param && param.defaultArg.member)
8922             {
8923                Expression argExp = GetTemplateArgExpByName(param.name, thisClass, TemplateParameterType::identifier);
8924                if(argExp)
8925                {
8926                   Expression expMember = exp.member.exp;
8927                   Declarator decl;
8928                   OldList * specs = MkList();
8929                   char thisClassTypeString[1024];
8930
8931                   FreeIdentifier(exp.member.member);
8932
8933                   ProcessExpressionType(argExp);
8934
8935                   {
8936                      char * colon = strstr(param.defaultArg.memberString, "::");
8937                      if(colon)
8938                      {
8939                         char className[1024];
8940                         Class sClass;
8941
8942                         memcpy(thisClassTypeString, param.defaultArg.memberString, colon - param.defaultArg.memberString);
8943                         thisClassTypeString[colon - param.defaultArg.memberString] = '\0';
8944                      }
8945                      else
8946                         strcpy(thisClassTypeString, _class.fullName);
8947                   }
8948
8949                   decl = SpecDeclFromString(param.defaultArg.member.dataTypeString, specs, null);
8950
8951                   exp.expType = ProcessType(specs, decl);
8952                   if(exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.templateClass)
8953                   {
8954                      Class expClass = exp.expType._class.registered;
8955                      Class cClass = null;
8956                      int c;
8957                      int paramCount = 0;
8958                      int lastParam = -1;
8959                      
8960                      char templateString[1024];
8961                      ClassTemplateParameter param;
8962                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
8963                      for(cClass = expClass; cClass; cClass = cClass.base)
8964                      {
8965                         int p = 0;
8966                         for(param = cClass.templateParams.first; param; param = param.next)
8967                         {
8968                            int id = p;
8969                            Class sClass;
8970                            ClassTemplateArgument arg;
8971                            for(sClass = cClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
8972                            arg = expClass.templateArgs[id];
8973
8974                            for(sClass = _class /*expClass*/; sClass; sClass = sClass.base)
8975                            {
8976                               ClassTemplateParameter cParam;
8977                               //int p = numParams - sClass.templateParams.count;
8978                               int p = 0;
8979                               Class nextClass;
8980                               for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
8981                               
8982                               for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
8983                               {
8984                                  if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
8985                                  {
8986                                     if(_class.templateArgs && arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
8987                                     {
8988                                        arg.dataTypeString = _class.templateArgs[p].dataTypeString;
8989                                        arg.dataTypeClass = _class.templateArgs[p].dataTypeClass;
8990                                        break;
8991                                     }
8992                                  }
8993                               }
8994                            }
8995
8996                            {
8997                               char argument[256];
8998                               argument[0] = '\0';
8999                               /*if(arg.name)
9000                               {
9001                                  strcat(argument, arg.name.string);
9002                                  strcat(argument, " = ");
9003                               }*/
9004                               switch(param.type)
9005                               {
9006                                  case expression:
9007                                  {
9008                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
9009                                     char expString[1024];
9010                                     OldList * specs = MkList();
9011                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
9012                                     Expression exp;
9013                                     char * string = PrintHexUInt64(arg.expression.ui64);
9014                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
9015
9016                                     ProcessExpressionType(exp);
9017                                     ComputeExpression(exp);
9018                                     expString[0] = '\0';
9019                                     PrintExpression(exp, expString);
9020                                     strcat(argument, expString);
9021                                     // delete exp;
9022                                     FreeExpression(exp);
9023                                     break;
9024                                  }
9025                                  case identifier:
9026                                  {
9027                                     strcat(argument, arg.member.name);
9028                                     break;
9029                                  }
9030                                  case TemplateParameterType::type:
9031                                  {
9032                                     if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9033                                     {
9034                                        if(!strcmp(arg.dataTypeString, "thisclass"))
9035                                           strcat(argument, thisClassTypeString);
9036                                        else
9037                                           strcat(argument, arg.dataTypeString);
9038                                     }
9039                                     break;
9040                                  }
9041                               }
9042                               if(argument[0])
9043                               {
9044                                  if(paramCount) strcat(templateString, ", ");
9045                                  if(lastParam != p - 1)
9046                                  {
9047                                     strcat(templateString, param.name);
9048                                     strcat(templateString, " = ");
9049                                  }
9050                                  strcat(templateString, argument);
9051                                  paramCount++;
9052                                  lastParam = p;
9053                               }
9054                               p++;
9055                            }               
9056                         }
9057                      }
9058                      {
9059                         int len = strlen(templateString);
9060                         if(templateString[len-1] == '>') templateString[len++] = ' ';
9061                         templateString[len++] = '>';
9062                         templateString[len++] = '\0';
9063                      }
9064                      {
9065                         Context context = SetupTemplatesContext(_class);
9066                         FreeType(exp.expType);
9067                         exp.expType = ProcessTypeString(templateString, false);
9068                         FinishTemplatesContext(context);
9069                      }                     
9070                   }
9071
9072                   // *([expType] *)(((byte *)[exp.member.exp]) + [argExp].member.offset)
9073                   exp.type = bracketsExp;
9074                   exp.list = MkListOne(MkExpOp(null, '*',
9075                   /*opExp;
9076                   exp.op.op = '*';
9077                   exp.op.exp1 = null;
9078                   exp.op.exp2 = */
9079                   MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpBrackets(MkListOne(MkExpOp(
9080                      MkExpBrackets(MkListOne(
9081                         MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), expMember))),
9082                            '+',  
9083                            MkExpOp(MkExpMember(MkExpMember(argExp, MkIdentifier("member")), MkIdentifier("offset")), 
9084                            '+',
9085                            MkExpMember(MkExpMember(MkExpMember(CopyExpression(argExp), MkIdentifier("member")), MkIdentifier("_class")), MkIdentifier("offset")))))))
9086                            
9087                            ));
9088                }
9089             }
9090             else if(type.templateParameter && type.templateParameter.type == TemplateParameterType::type && 
9091                (type.templateParameter.dataType || type.templateParameter.dataTypeString))
9092             {
9093                type = ProcessTemplateParameterType(type.templateParameter);
9094             }
9095          }
9096
9097          if(type && (type.kind == templateType));
9098          else if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9099          {
9100             Identifier id = exp.member.member;
9101             TypeKind typeKind = type.kind;
9102             Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9103             if(typeKind == subClassType && exp.member.exp.type == classExp)
9104             {
9105                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
9106                typeKind = classType;
9107             }
9108
9109             if(id && (typeKind == intType || typeKind == enumType))
9110                _class = eSystem_FindClass(privateModule, "int");
9111
9112             if(_class && id)
9113             {
9114                /*bool thisPtr = 
9115                   (exp.member.exp.type == identifierExp && 
9116                   !strcmp(exp.member.exp.identifier.string, "this"));*/
9117                Property prop = null;
9118                Method method = null;
9119                DataMember member = null;
9120                Property revConvert = null;
9121                ClassProperty classProp = null;
9122
9123                if(id && id._class && id._class.name && !strcmp(id._class.name, "property"))
9124                   exp.member.memberType = propertyMember;
9125
9126                if(id && id._class && type._class && !eClass_IsDerived(type._class.registered, _class))
9127                   Compiler_Error($"invalid class specifier %s for object of class %s\n", _class.fullName, type._class.string);
9128
9129                if(typeKind != subClassType)
9130                {
9131                   // Prioritize data members over properties for "this"
9132                   if((exp.member.memberType == unresolvedMember && thisPtr) || exp.member.memberType == dataMember)
9133                   {
9134                      member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9135                      if(member && member._class != (_class.templateClass ? _class.templateClass : _class) && exp.member.memberType != dataMember)
9136                      {
9137                         prop = eClass_FindProperty(_class, id.string, privateModule);
9138                         if(prop)
9139                            member = null;
9140                      }
9141                      if(!member && !prop)
9142                         prop = eClass_FindProperty(_class, id.string, privateModule);
9143                      if((member && member._class == (_class.templateClass ? _class.templateClass : _class)) ||
9144                         (prop && prop._class == (_class.templateClass ? _class.templateClass : _class)))
9145                         exp.member.thisPtr = true;
9146                   }
9147                   // Prioritize properties over data members otherwise
9148                   else
9149                   {
9150                      // First look for Public Members (Unless class specifier is provided, which skips public priority)
9151                      if(!id.classSym)
9152                      {
9153                         prop = eClass_FindProperty(_class, id.string, null);
9154                         if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9155                            member = eClass_FindDataMember(_class, id.string, null, null, null);
9156                      }
9157
9158                      if(!prop && !member)
9159                      {
9160                         method = eClass_FindMethod(_class, id.string, null);
9161                         if(!method)
9162                         {
9163                            prop = eClass_FindProperty(_class, id.string, privateModule);
9164                            if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9165                               member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9166                         }
9167                      }
9168
9169                      if(member && prop)
9170                      {
9171                         if(member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class))
9172                            prop = null;
9173                         else
9174                            member = null;
9175                      }
9176                   }
9177                }
9178                if(!prop && !member)
9179                   method = eClass_FindMethod(_class, id.string, privateModule);
9180                if(!prop && !member && !method)
9181                {
9182                   if(typeKind == subClassType)
9183                   {
9184                      classProp = eClass_FindClassProperty(type._class.registered, exp.member.member.string);
9185                      if(classProp)
9186                      {
9187                         exp.member.memberType = classPropertyMember;
9188                         exp.expType = ProcessTypeString(classProp.dataTypeString, false);
9189                      }
9190                      else
9191                      {
9192                         // Assume this is a class_data member
9193                         char structName[1024];
9194                         Identifier id = exp.member.member;
9195                         Expression classExp = exp.member.exp;
9196                         type.refCount++;
9197
9198                         FreeType(classExp.expType);
9199                         classExp.expType = ProcessTypeString("ecere::com::Class", false);
9200                      
9201                         strcpy(structName, "__ecereClassData_");
9202                         FullClassNameCat(structName, type._class.string, false);
9203                         exp.type = pointerExp;
9204                         exp.member.member = id;
9205
9206                         exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9207                            MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), 
9208                               MkExpBrackets(MkListOne(MkExpOp(
9209                                  MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)), 
9210                                     MkExpMember(classExp, MkIdentifier("data"))), '+',
9211                                        MkExpMember(MkExpClass(MkListOne(MkSpecifierName(type._class.string)), null), MkIdentifier("offsetClass")))))
9212                                  )));
9213
9214                         FreeType(type);
9215
9216                         ProcessExpressionType(exp);
9217                         return;
9218                      }
9219                   }
9220                   else
9221                   {
9222                      // Check for reverse conversion
9223                      // (Convert in an instantiation later, so that we can use
9224                      //  deep properties system)
9225                      Symbol classSym = FindClass(id.string);
9226                      if(classSym)
9227                      {
9228                         Class convertClass = classSym.registered;
9229                         if(convertClass)
9230                            revConvert = eClass_FindProperty(convertClass, _class.fullName, privateModule);
9231                      }
9232                   }
9233                }
9234       
9235                if(prop)
9236                {
9237                   exp.member.memberType = propertyMember;
9238                   if(!prop.dataType)
9239                      ProcessPropertyType(prop);
9240                   exp.expType = prop.dataType;                     
9241                   if(prop.dataType) prop.dataType.refCount++;
9242                }
9243                else if(member)
9244                {
9245                   if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9246                   {
9247                      FreeExpContents(exp);
9248                      exp.type = identifierExp;
9249                      exp.identifier = MkIdentifier("class");
9250                      ProcessExpressionType(exp);
9251                      return;
9252                   }
9253
9254                   exp.member.memberType = dataMember;
9255                   DeclareStruct(_class.fullName, false);
9256                   if(!member.dataType)
9257                   {
9258                      Context context = SetupTemplatesContext(_class);
9259                      member.dataType = ProcessTypeString(member.dataTypeString, false);
9260                      FinishTemplatesContext(context);
9261                   }
9262                   exp.expType = member.dataType;
9263                   if(member.dataType) member.dataType.refCount++;
9264                }
9265                else if(revConvert)
9266                {
9267                   exp.member.memberType = reverseConversionMember;
9268                   exp.expType = MkClassType(revConvert._class.fullName);
9269                }
9270                else if(method)
9271                {
9272                   if(inCompiler)
9273                   {
9274                      /*if(id._class)
9275                      {
9276                         exp.type = identifierExp;
9277                         exp.identifier = exp.member.member;
9278                      }
9279                      else*/
9280                         exp.member.memberType = methodMember;
9281                   }
9282                   if(!method.dataType)
9283                      ProcessMethodType(method);
9284                   exp.expType = Type
9285                   {
9286                      refCount = 1;
9287                      kind = methodType;
9288                      method = method;
9289                   };
9290
9291                   // Tricky spot here... To use instance versus class virtual table
9292                   // Put it back to what it was... What did we break?
9293
9294                   // Had to put it back for overriding Main of Thread global instance
9295
9296                   //exp.expType.methodClass = _class;
9297                   exp.expType.methodClass = (id && id._class) ? _class : null;
9298
9299                   // Need the actual class used for templated classes
9300                   exp.expType.usedClass = _class;
9301                }
9302                else if(!classProp)
9303                {
9304                   if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9305                   {
9306                      FreeExpContents(exp);
9307                      exp.type = identifierExp;
9308                      exp.identifier = MkIdentifier("class");
9309                      ProcessExpressionType(exp);
9310                      return;
9311                   }
9312                   yylloc = exp.member.member.loc;
9313                   Compiler_Error($"couldn't find member %s in class %s\n", id.string, _class.fullName);
9314                   if(inCompiler)
9315                      eClass_AddDataMember(_class, id.string, "int", 0, 0, publicAccess);
9316                }
9317
9318                if(_class && /*(_class.templateClass || _class.templateArgs) && */exp.expType)
9319                {
9320                   Class tClass;
9321
9322                   tClass = _class;
9323                   while(tClass && !tClass.templateClass) tClass = tClass.base;
9324
9325                   if(tClass && exp.expType.kind == templateType && exp.expType.templateParameter.type == TemplateParameterType::type)
9326                   {
9327                      int id = 0;
9328                      ClassTemplateParameter curParam;
9329                      Class sClass;
9330
9331                      for(sClass = tClass; sClass; sClass = sClass.base)
9332                      {
9333                         id = 0;
9334                         if(sClass.templateClass) sClass = sClass.templateClass;
9335                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9336                         {
9337                            if(curParam.type == TemplateParameterType::type && !strcmp(exp.expType.templateParameter.identifier.string, curParam.name))
9338                            {
9339                               for(sClass = sClass.base; sClass; sClass = sClass.base)
9340                                  id += sClass.templateParams.count;
9341                               break;
9342                            }
9343                            id++;
9344                         }
9345                         if(curParam) break;
9346                      }
9347
9348                      if(curParam && tClass.templateArgs[id].dataTypeString)
9349                      {
9350                         ClassTemplateArgument arg = tClass.templateArgs[id];
9351                         Context context = SetupTemplatesContext(tClass);
9352                         /*if(!arg.dataType)
9353                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9354                         FreeType(exp.expType);
9355                         exp.expType = ProcessTypeString(arg.dataTypeString, false);
9356                         if(exp.expType)
9357                         {
9358                            if(exp.expType.kind == thisClassType)
9359                            {
9360                               FreeType(exp.expType);
9361                               exp.expType = ReplaceThisClassType(_class);
9362                            }
9363
9364                            if(tClass.templateClass)
9365                               exp.expType.passAsTemplate = true;
9366                            //exp.expType.refCount++;
9367                            if(!exp.destType)
9368                            {
9369                               exp.destType = ProcessTypeString(arg.dataTypeString, false);
9370                               //exp.destType.refCount++;
9371
9372                               if(exp.destType.kind == thisClassType)
9373                               {
9374                                  FreeType(exp.destType);
9375                                  exp.destType = ReplaceThisClassType(_class);
9376                               }
9377                            }
9378                         }
9379                         FinishTemplatesContext(context);
9380                      }
9381                   }
9382                   // TODO: MORE GENERIC SUPPORT FOR DEEPER TYPES
9383                   else if(tClass && exp.expType.kind == pointerType && exp.expType.type && exp.expType.type.kind == templateType && exp.expType.type.templateParameter.type == TemplateParameterType::type)
9384                   {
9385                      int id = 0;
9386                      ClassTemplateParameter curParam;
9387                      Class sClass;
9388
9389                      for(sClass = tClass; sClass; sClass = sClass.base)
9390                      {
9391                         id = 0;
9392                         if(sClass.templateClass) sClass = sClass.templateClass;
9393                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9394                         {
9395                            if(curParam.type == TemplateParameterType::type && 
9396                               !strcmp(exp.expType.type.templateParameter.identifier.string, curParam.name))
9397                            {
9398                               for(sClass = sClass.base; sClass; sClass = sClass.base)
9399                                  id += sClass.templateParams.count;
9400                               break;
9401                            }
9402                            id++;
9403                         }
9404                         if(curParam) break;
9405                      }
9406
9407                      if(curParam)
9408                      {
9409                         ClassTemplateArgument arg = tClass.templateArgs[id];
9410                         Context context = SetupTemplatesContext(tClass);
9411                         Type basicType;
9412                         /*if(!arg.dataType)
9413                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9414                         
9415                         basicType = ProcessTypeString(arg.dataTypeString, false);
9416                         if(basicType)
9417                         {
9418                            if(basicType.kind == thisClassType)
9419                            {
9420                               FreeType(basicType);
9421                               basicType = ReplaceThisClassType(_class);
9422                            }
9423
9424                            /*    DO WE REALLY WANT THIS HERE? IT SEEMS TO BE ONLY USED WITH Array::array which was causing bug 135
9425                            if(tClass.templateClass)
9426                               basicType.passAsTemplate = true;
9427                            */
9428                            
9429                            FreeType(exp.expType);
9430
9431                            exp.expType = Type { refCount = 1, kind = pointerType, type = basicType };
9432                            //exp.expType.refCount++;
9433                            if(!exp.destType)
9434                            {
9435                               exp.destType = exp.expType;
9436                               exp.destType.refCount++;
9437                            }
9438
9439                            {
9440                               Expression newExp { };
9441                               OldList * specs = MkList();
9442                               Declarator decl;
9443                               decl = SpecDeclFromString(arg.dataTypeString, specs, null);
9444                               *newExp = *exp;
9445                               if(exp.destType) exp.destType.refCount++;
9446                               if(exp.expType)  exp.expType.refCount++;
9447                               exp.type = castExp;
9448                               exp.cast.typeName = MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl));
9449                               exp.cast.exp = newExp;
9450                               //FreeType(exp.expType);
9451                               //exp.expType = null;
9452                               //ProcessExpressionType(sourceExp);
9453                            }
9454                         }
9455                         FinishTemplatesContext(context);
9456                      }
9457                   }
9458                   else if(tClass && exp.expType.kind == classType && exp.expType._class && strchr(exp.expType._class.string, '<'))
9459                   {
9460                      Class expClass = exp.expType._class.registered;
9461                      if(expClass)
9462                      {
9463                         Class cClass = null;
9464                         int c;
9465                         int p = 0;
9466                         int paramCount = 0;
9467                         int lastParam = -1;
9468                         char templateString[1024];
9469                         ClassTemplateParameter param;
9470                         sprintf(templateString, "%s<", expClass.templateClass.fullName);
9471                         while(cClass != expClass)
9472                         {
9473                            Class sClass;
9474                            for(sClass = expClass; sClass && sClass.base != cClass; sClass = sClass.base);
9475                            cClass = sClass;
9476
9477                            for(param = cClass.templateParams.first; param; param = param.next)
9478                            {
9479                               Class cClassCur = null;
9480                               int c;
9481                               int cp = 0;
9482                               ClassTemplateParameter paramCur = null;
9483                               ClassTemplateArgument arg;
9484                               while(cClassCur != tClass && !paramCur)
9485                               {
9486                                  Class sClassCur;
9487                                  for(sClassCur = tClass; sClassCur && sClassCur.base != cClassCur; sClassCur = sClassCur.base);
9488                                  cClassCur = sClassCur;
9489
9490                                  for(paramCur = cClassCur.templateParams.first; paramCur; paramCur = paramCur.next)
9491                                  {
9492                                     if(!strcmp(paramCur.name, param.name))
9493                                     {
9494                                        
9495                                        break;
9496                                     }
9497                                     cp++;
9498                                  }
9499                               }
9500                               if(paramCur && paramCur.type == TemplateParameterType::type)
9501                                  arg = tClass.templateArgs[cp];
9502                               else
9503                                  arg = expClass.templateArgs[p];
9504
9505                               {
9506                                  char argument[256];
9507                                  argument[0] = '\0';
9508                                  /*if(arg.name)
9509                                  {
9510                                     strcat(argument, arg.name.string);
9511                                     strcat(argument, " = ");
9512                                  }*/
9513                                  switch(param.type)
9514                                  {
9515                                     case expression:
9516                                     {
9517                                        // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
9518                                        char expString[1024];
9519                                        OldList * specs = MkList();
9520                                        Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
9521                                        Expression exp;
9522                                        char * string = PrintHexUInt64(arg.expression.ui64);
9523                                        exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
9524
9525                                        ProcessExpressionType(exp);
9526                                        ComputeExpression(exp);
9527                                        expString[0] = '\0';
9528                                        PrintExpression(exp, expString);
9529                                        strcat(argument, expString);
9530                                        // delete exp;
9531                                        FreeExpression(exp);
9532                                        break;
9533                                     }
9534                                     case identifier:
9535                                     {
9536                                        strcat(argument, arg.member.name);
9537                                        break;
9538                                     }
9539                                     case TemplateParameterType::type:
9540                                     {
9541                                        if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9542                                           strcat(argument, arg.dataTypeString);
9543                                        break;
9544                                     }
9545                                  }
9546                                  if(argument[0])
9547                                  {
9548                                     if(paramCount) strcat(templateString, ", ");
9549                                     if(lastParam != p - 1)
9550                                     {
9551                                        strcat(templateString, param.name);
9552                                        strcat(templateString, " = ");
9553                                     }                                       
9554                                     strcat(templateString, argument);
9555                                     paramCount++;
9556                                     lastParam = p;
9557                                  }
9558                               }
9559                               p++;
9560                            }
9561                         }
9562                         {
9563                            int len = strlen(templateString);
9564                            if(templateString[len-1] == '>') templateString[len++] = ' ';
9565                            templateString[len++] = '>';
9566                            templateString[len++] = '\0';
9567                         }
9568
9569                         FreeType(exp.expType);
9570                         {
9571                            Context context = SetupTemplatesContext(tClass);
9572                            exp.expType = ProcessTypeString(templateString, false);
9573                            FinishTemplatesContext(context);
9574                         }
9575                      }
9576                   }
9577                }
9578             }
9579             else
9580                Compiler_Error($"undefined class %s\n", (id && (!id._class || id._class.name))? (id.classSym ? id.classSym.string : (type._class ? type._class.string : null)) : "(null)");
9581          }
9582          else if(type && (type.kind == structType || type.kind == unionType))
9583          {
9584             Type memberType = exp.member.member ? FindMember(type, exp.member.member.string) : null;
9585             if(memberType)
9586             {
9587                exp.expType = memberType;
9588                if(memberType)
9589                   memberType.refCount++;
9590             }
9591          }
9592          else 
9593          {
9594             char expString[10240];
9595             expString[0] = '\0';
9596             if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
9597             Compiler_Error($"member operator on non-structure type expression %s\n", expString);
9598          }
9599
9600          if(exp.expType && exp.expType.kind == thisClassType && (!exp.destType || exp.destType.kind != thisClassType))
9601          {
9602             if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9603             {
9604                Identifier id = exp.member.member;
9605                Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9606                if(_class)
9607                {
9608                   FreeType(exp.expType);
9609                   exp.expType = ReplaceThisClassType(_class);
9610                }
9611             }
9612          }         
9613          yylloc = oldyylloc;
9614          break;
9615       }
9616       // Convert x->y into (*x).y
9617       case pointerExp:
9618       {
9619          Type destType = exp.destType;
9620
9621          // DOING THIS LATER NOW...
9622          if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
9623          {
9624             exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
9625             /* TODO: Name Space Fix ups
9626             if(!exp.member.member.classSym)
9627                exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.name);
9628             */
9629          }
9630
9631          exp.member.exp = MkExpBrackets(MkListOne(MkExpOp(null, '*', exp.member.exp)));
9632          exp.type = memberExp;
9633          if(destType)
9634             destType.count++;
9635          ProcessExpressionType(exp);
9636          if(destType)
9637             destType.count--;
9638          break;
9639       }
9640       case classSizeExp:
9641       {
9642          //ComputeExpression(exp);
9643
9644          Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
9645          if(classSym && classSym.registered)
9646          {
9647             if(classSym.registered.type == noHeadClass)
9648             {
9649                char name[1024];
9650                name[0] = '\0';
9651                DeclareStruct(classSym.string, false);
9652                FreeSpecifier(exp._class);
9653                exp.type = typeSizeExp;
9654                FullClassNameCat(name, classSym.string, false);
9655                exp.typeName = MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null);
9656             }
9657             else
9658             {
9659                if(classSym.registered.fixed)
9660                {
9661                   FreeSpecifier(exp._class);
9662                   exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
9663                   exp.type = constantExp;
9664                }
9665                else
9666                {
9667                   char className[1024];
9668                   strcpy(className, "__ecereClass_");
9669                   FullClassNameCat(className, classSym.string, true);
9670                   MangleClassName(className);
9671
9672                   DeclareClass(classSym, className);
9673
9674                   FreeExpContents(exp);
9675                   exp.type = pointerExp;
9676                   exp.member.exp = MkExpIdentifier(MkIdentifier(className));
9677                   exp.member.member = MkIdentifier("structSize");
9678                }
9679             }
9680          }
9681
9682          exp.expType = Type
9683          {
9684             refCount = 1;
9685             kind = intType;
9686          };
9687          // exp.isConstant = true;
9688          break;
9689       }
9690       case typeSizeExp:
9691       {
9692          Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
9693
9694          exp.expType = Type
9695          {
9696             refCount = 1;
9697             kind = intType;
9698          };
9699          exp.isConstant = true;
9700
9701          DeclareType(type, false, false);
9702          FreeType(type);
9703          break;
9704       }
9705       case castExp:
9706       {
9707          Type type = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
9708          type.count = 1;
9709          FreeType(exp.cast.exp.destType);
9710          exp.cast.exp.destType = type;
9711          type.refCount++;
9712          ProcessExpressionType(exp.cast.exp);
9713          type.count = 0;
9714          exp.expType = type;
9715          //type.refCount++;
9716          
9717          // if(!NeedCast(exp.cast.exp.expType, exp.cast.exp.destType))
9718          if(!exp.cast.exp.needCast && !NeedCast(exp.cast.exp.expType, type))
9719          {
9720             void * prev = exp.prev, * next = exp.next;
9721             Type expType = exp.cast.exp.destType;
9722             Expression castExp = exp.cast.exp;
9723             Type destType = exp.destType;
9724
9725             if(expType) expType.refCount++;
9726
9727             //FreeType(exp.destType);
9728             FreeType(exp.expType);
9729             FreeTypeName(exp.cast.typeName);
9730             
9731             *exp = *castExp;
9732             FreeType(exp.expType);
9733             FreeType(exp.destType);
9734
9735             exp.expType = expType;
9736             exp.destType = destType;
9737
9738             delete castExp;
9739
9740             exp.prev = prev;
9741             exp.next = next;
9742
9743          }
9744          else
9745          {
9746             exp.isConstant = exp.cast.exp.isConstant;
9747          }
9748          //FreeType(type);
9749          break;
9750       }
9751       case extensionInitializerExp:
9752       {
9753          Type type = ProcessType(exp.initializer.typeName.qualifiers, exp.initializer.typeName.declarator);
9754          type.refCount++;
9755
9756          // We have yet to support this... ( { } initializers are currently processed inside ProcessDeclaration()'s initDeclaration case statement
9757          // ProcessInitializer(exp.initializer.initializer, type);
9758          exp.expType = type;
9759          break;
9760       }
9761       case vaArgExp:
9762       {
9763          Type type = ProcessType(exp.vaArg.typeName.qualifiers, exp.vaArg.typeName.declarator);
9764          ProcessExpressionType(exp.vaArg.exp);
9765          type.refCount++;
9766          exp.expType = type;
9767          break;
9768       }
9769       case conditionExp:
9770       {
9771          Expression e;
9772          exp.isConstant = true;
9773
9774          FreeType(exp.cond.cond.destType);
9775          exp.cond.cond.destType = MkClassType("bool");
9776          exp.cond.cond.destType.truth = true;
9777          ProcessExpressionType(exp.cond.cond);
9778          if(!exp.cond.cond.isConstant)
9779             exp.isConstant = false;
9780          for(e = exp.cond.exp->first; e; e = e.next)
9781          {
9782             if(!e.next)
9783             {
9784                FreeType(e.destType);
9785                e.destType = exp.destType;
9786                if(e.destType) e.destType.refCount++;
9787             }
9788             ProcessExpressionType(e);
9789             if(!e.next)
9790             {
9791                exp.expType = e.expType;
9792                if(e.expType) e.expType.refCount++;
9793             }
9794             if(!e.isConstant)
9795                exp.isConstant = false;
9796          }
9797
9798          FreeType(exp.cond.elseExp.destType);
9799          // Added this check if we failed to find an expType
9800          // exp.cond.elseExp.destType = exp.expType ? exp.expType : exp.destType;
9801
9802          // Reversed it...
9803          exp.cond.elseExp.destType = exp.destType ? exp.destType : exp.expType;
9804
9805          if(exp.cond.elseExp.destType)
9806             exp.cond.elseExp.destType.refCount++;
9807          ProcessExpressionType(exp.cond.elseExp);
9808
9809          // FIXED THIS: Was done before calling process on elseExp
9810          if(!exp.cond.elseExp.isConstant)
9811             exp.isConstant = false;
9812          break;
9813       }
9814       case extensionCompoundExp:
9815       {
9816          if(exp.compound && exp.compound.compound.statements && exp.compound.compound.statements->last)
9817          {
9818             Statement last = exp.compound.compound.statements->last;
9819             if(last.type == expressionStmt && last.expressions && last.expressions->last)
9820             {
9821                ((Expression)last.expressions->last).destType = exp.destType;
9822                if(exp.destType)
9823                   exp.destType.refCount++;
9824             }
9825             ProcessStatement(exp.compound);
9826             exp.expType = ((Expression)last.expressions->last).expType;
9827             if(((Expression)last.expressions->last).expType)
9828                exp.expType.refCount++;
9829          }
9830          break;
9831       }
9832       case classExp:
9833       {
9834          Specifier spec = exp._classExp.specifiers->first;
9835          if(spec && spec.type == nameSpecifier)
9836          {
9837             exp.expType = MkClassType(spec.name);
9838             exp.expType.kind = subClassType;
9839             exp.byReference = true;
9840          }
9841          else
9842          {
9843             exp.expType = MkClassType("ecere::com::Class");
9844             exp.byReference = true;
9845          }
9846          break;
9847       }
9848       case classDataExp:
9849       {
9850          Class _class = thisClass ? thisClass : currentClass;
9851          if(_class)
9852          {
9853             Identifier id = exp.classData.id;
9854             char structName[1024];
9855             Expression classExp;
9856             strcpy(structName, "__ecereClassData_");
9857             FullClassNameCat(structName, _class.fullName, false);
9858             exp.type = pointerExp;
9859             exp.member.member = id;
9860             if(curCompound && FindSymbol("this", curContext, curCompound.compound.context, false, false))
9861                classExp = MkExpMember(MkExpIdentifier(MkIdentifier("this")), MkIdentifier("_class"));
9862             else
9863                classExp = MkExpIdentifier(MkIdentifier("class"));
9864
9865             exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9866                MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), 
9867                   MkExpBrackets(MkListOne(MkExpOp(
9868                      MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)), 
9869                         MkExpMember(classExp, MkIdentifier("data"))), '+',
9870                            MkExpMember(MkExpClass(MkListOne(MkSpecifierName(_class.fullName)), null), MkIdentifier("offsetClass")))))
9871                      )));
9872
9873             ProcessExpressionType(exp);
9874             return;
9875          }
9876          break;
9877       }
9878       case arrayExp:
9879       {
9880          Type type = null;
9881          char * typeString = null;
9882          char typeStringBuf[1024];
9883          if(exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
9884             exp.destType._class.registered != containerClass && eClass_IsDerived(exp.destType._class.registered, containerClass))
9885          {
9886             Class templateClass = exp.destType._class.registered;
9887             typeString = templateClass.templateArgs[2].dataTypeString;
9888          }
9889          else if(exp.list)
9890          {
9891             // Guess type from expressions in the array
9892             Expression e;
9893             for(e = exp.list->first; e; e = e.next)
9894             {
9895                ProcessExpressionType(e);
9896                if(e.expType)
9897                {
9898                   if(!type) { type = e.expType; type.refCount++; }
9899                   else
9900                   {
9901                      // if(!MatchType(e.expType, type, null, null, null, false, false, false))
9902                      if(!MatchTypeExpression(e, type, null, false))
9903                      {
9904                         FreeType(type);
9905                         type = e.expType;
9906                         e.expType = null;
9907                         
9908                         e = exp.list->first;
9909                         ProcessExpressionType(e);
9910                         if(e.expType)
9911                         {
9912                            //if(!MatchTypes(e.expType, type, null, null, null, false, false, false))
9913                            if(!MatchTypeExpression(e, type, null, false))
9914                            {
9915                               FreeType(e.expType);
9916                               e.expType = null;
9917                               FreeType(type);
9918                               type = null;
9919                               break;
9920                            }                           
9921                         }
9922                      }
9923                   }
9924                   if(e.expType)
9925                   {
9926                      FreeType(e.expType);
9927                      e.expType = null;
9928                   }
9929                }
9930             }
9931             if(type)
9932             {
9933                typeStringBuf[0] = '\0';
9934                PrintType(type, typeStringBuf, false, true);
9935                typeString = typeStringBuf;
9936                FreeType(type);
9937                type = null;
9938             }
9939          }
9940          if(typeString)
9941          {
9942             /*
9943             (Container)& (struct BuiltInContainer)
9944             {
9945                ._vTbl = class(BuiltInContainer)._vTbl,
9946                ._class = class(BuiltInContainer),
9947                .refCount = 0,
9948                .data = (int[]){ 1, 7, 3, 4, 5 },
9949                .count = 5,
9950                .type = class(int),
9951             }
9952             */
9953             char templateString[1024];
9954             OldList * initializers = MkList();
9955             OldList * structInitializers = MkList();
9956             OldList * specs = MkList();
9957             Expression expExt;
9958             Declarator decl = SpecDeclFromString(typeString, specs, null);
9959             sprintf(templateString, "Container<%s>", typeString);
9960
9961             if(exp.list)
9962             {
9963                Expression e;
9964                type = ProcessTypeString(typeString, false);
9965                while(e = exp.list->first)
9966                {
9967                   exp.list->Remove(e);
9968                   e.destType = type;
9969                   type.refCount++;
9970                   ProcessExpressionType(e);
9971                   ListAdd(initializers, MkInitializerAssignment(e));
9972                }
9973                FreeType(type);
9974                delete exp.list;
9975             }
9976             
9977             DeclareStruct("ecere::com::BuiltInContainer", false);
9978
9979             ListAdd(structInitializers, /*MkIdentifier("_vTbl")*/    MkInitializerAssignment(MkExpMember(MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null), MkIdentifier("_vTbl"))));
9980                ProcessExpressionType(((Initializer)structInitializers->last).exp);
9981             ListAdd(structInitializers, /*MkIdentifier("_class")*/   MkInitializerAssignment(MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null)));
9982                ProcessExpressionType(((Initializer)structInitializers->last).exp);
9983             ListAdd(structInitializers, /*MkIdentifier("_refCount")*/MkInitializerAssignment(MkExpConstant("0")));
9984                ProcessExpressionType(((Initializer)structInitializers->last).exp);
9985             ListAdd(structInitializers, /*MkIdentifier("data")*/     MkInitializerAssignment(MkExpExtensionInitializer(
9986                MkTypeName(specs, MkDeclaratorArray(decl, null)),
9987                MkInitializerList(initializers))));
9988                ProcessExpressionType(((Initializer)structInitializers->last).exp);
9989             ListAdd(structInitializers, /*MkIdentifier("count")*/    MkInitializerAssignment({ type = constantExp, constant = PrintString(initializers->count) }));
9990                ProcessExpressionType(((Initializer)structInitializers->last).exp);
9991             ListAdd(structInitializers, /*MkIdentifier("type")*/     MkInitializerAssignment(MkExpClass(CopyList(specs, CopySpecifier), CopyDeclarator(decl))));
9992                ProcessExpressionType(((Initializer)structInitializers->last).exp);
9993             exp.expType = ProcessTypeString(templateString, false);
9994             exp.type = bracketsExp;
9995             exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(templateString)), null),
9996                MkExpOp(null, '&',
9997                expExt = MkExpExtensionInitializer(MkTypeName(MkListOne(MkSpecifierName("BuiltInContainer")), null),
9998                   MkInitializerList(structInitializers)))));
9999             ProcessExpressionType(expExt);
10000          }
10001          else
10002          {
10003             exp.expType = ProcessTypeString("Container", false);
10004             Compiler_Error($"Couldn't determine type of array elements\n");
10005          }
10006          break;
10007       }
10008    }
10009
10010    if(exp.expType && exp.expType.kind == thisClassType && thisClass && (!exp.destType || exp.destType.kind != thisClassType))
10011    {
10012       FreeType(exp.expType);
10013       exp.expType = ReplaceThisClassType(thisClass);
10014    }
10015
10016    // Resolve structures here
10017    if(exp.expType && (exp.expType.kind == structType || exp.expType.kind == unionType || exp.expType.kind == enumType) && !exp.expType.members.first && exp.expType.enumName)
10018    {
10019       Symbol symbol = FindSymbol(exp.expType.enumName, curContext, globalContext, true, false);
10020       // TODO: Fix members reference...
10021       if(symbol)
10022       {
10023          if(exp.expType.kind != enumType)
10024          {
10025             Type member;
10026             String enumName = CopyString(exp.expType.enumName);
10027
10028             // Fixed a memory leak on self-referencing C structs typedefs
10029             // by instantiating a new type rather than simply copying members
10030             // into exp.expType
10031             FreeType(exp.expType);
10032             exp.expType = Type { };
10033             exp.expType.kind = symbol.type.kind;
10034             exp.expType.refCount++;
10035             exp.expType.enumName = enumName;
10036
10037             exp.expType.members = symbol.type.members;
10038             for(member = symbol.type.members.first; member; member = member.next)
10039                member.refCount++;
10040          }
10041          else
10042          {
10043             NamedLink member;
10044             for(member = symbol.type.members.first; member; member = member.next)
10045             {
10046                NamedLink value { name = CopyString(member.name) };
10047                exp.expType.members.Add(value);
10048             }
10049          }
10050       }
10051    }
10052
10053    yylloc = exp.loc;
10054    if(exp.destType && (exp.destType.kind == voidType || exp.destType.kind == dummyType) );
10055    else if(exp.destType && !exp.destType.keepCast)
10056    {
10057       if(!CheckExpressionType(exp, exp.destType, false))
10058       {
10059          if(!exp.destType.count || unresolved)
10060          {
10061             if(!exp.expType)
10062             {
10063                yylloc = exp.loc;
10064                if(exp.destType.kind != ellipsisType)
10065                {
10066                   char type2[1024];
10067                   type2[0] = '\0';
10068                   if(inCompiler)
10069                   {
10070                      char expString[10240];
10071                      expString[0] = '\0';
10072
10073                      PrintType(exp.destType, type2, false, true);
10074
10075                      if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10076                      if(unresolved)
10077                         Compiler_Error($"unresolved identifier %s; expected %s\n", expString, type2);
10078                      else if(exp.type != dummyExp)
10079                         Compiler_Error($"couldn't determine type of %s; expected %s\n", expString, type2);
10080                   }
10081                }
10082                else
10083                {
10084                   char expString[10240] ;
10085                   expString[0] = '\0';
10086                   if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10087
10088                   if(unresolved)
10089                      Compiler_Error($"unresolved identifier %s\n", expString);
10090                   else if(exp.type != dummyExp)
10091                      Compiler_Error($"couldn't determine type of %s\n", expString);
10092                }
10093             }
10094             else
10095             {
10096                char type1[1024];
10097                char type2[1024];
10098                type1[0] = '\0';
10099                type2[0] = '\0';
10100                if(inCompiler)
10101                {
10102                   PrintType(exp.expType, type1, false, true);
10103                   PrintType(exp.destType, type2, false, true);
10104                }
10105
10106                //CheckExpressionType(exp, exp.destType, false);
10107
10108                if(exp.destType.truth && exp.destType._class && exp.destType._class.registered && !strcmp(exp.destType._class.registered.name, "bool") &&
10109                   exp.expType.kind != voidType && exp.expType.kind != structType && exp.expType.kind != unionType && 
10110                   (exp.expType.kind != classType || exp.expType.classObjectType || (exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type != structClass)));
10111                else
10112                {
10113                   char expString[10240];
10114                   expString[0] = '\0';
10115                   if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10116
10117 #ifdef _DEBUG
10118                   CheckExpressionType(exp, exp.destType, false);
10119 #endif
10120                   Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
10121
10122                   // TO CHECK: FORCING HERE TO HELP DEBUGGER
10123                   FreeType(exp.expType);
10124                   exp.destType.refCount++;
10125                   exp.expType = exp.destType;
10126                }
10127             }
10128          }
10129       }
10130       else if(exp.destType && exp.destType.kind == ellipsisType && exp.expType && exp.expType.passAsTemplate)
10131       {
10132          Expression newExp { };
10133          char typeString[1024];
10134          OldList * specs = MkList();
10135          Declarator decl;
10136
10137          typeString[0] = '\0';
10138
10139          *newExp = *exp;
10140
10141          if(exp.expType)  exp.expType.refCount++;
10142          if(exp.expType)  exp.expType.refCount++;
10143          exp.type = castExp;
10144          newExp.destType = exp.expType;
10145
10146          PrintType(exp.expType, typeString, false, false);
10147          decl = SpecDeclFromString(typeString, specs, null);
10148          
10149          exp.cast.typeName = MkTypeName(specs, decl);
10150          exp.cast.exp = newExp;
10151       }
10152    }
10153    else if(unresolved)
10154    {
10155       if(exp.identifier._class && exp.identifier._class.name)
10156          Compiler_Error($"unresolved identifier %s::%s\n", exp.identifier._class.name, exp.identifier.string);
10157       else if(exp.identifier.string && exp.identifier.string[0])
10158          Compiler_Error($"unresolved identifier %s\n", exp.identifier.string);
10159    }
10160    else if(!exp.expType && exp.type != dummyExp)
10161    {
10162       char expString[10240];
10163       expString[0] = '\0';
10164       if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10165       Compiler_Error($"couldn't determine type of %s\n", expString);
10166    }
10167
10168    // Let's try to support any_object & typed_object here:
10169    ApplyAnyObjectLogic(exp);
10170
10171    if(!notByReference && exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
10172       exp.expType._class.registered.type == noHeadClass)
10173    {
10174       exp.byReference = true;
10175    }
10176    /*else if(!notByReference && exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
10177       exp.destType._class.registered.type == noHeadClass)
10178    {
10179       exp.byReference = true;
10180    }*/
10181    yylloc = oldyylloc;
10182 }
10183
10184 static void FindNextDataMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
10185 {
10186    // THIS CODE WILL FIND NEXT MEMBER...
10187    if(*curMember) 
10188    {
10189       *curMember = (*curMember).next;
10190
10191       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
10192       {
10193          *curMember = subMemberStack[--(*subMemberStackPos)];
10194          *curMember = (*curMember).next;
10195       }
10196
10197       // SKIP ALL PROPERTIES HERE...
10198       while((*curMember) && (*curMember).isProperty)
10199          *curMember = (*curMember).next;
10200
10201       if(subMemberStackPos)
10202       {
10203          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10204          {
10205             subMemberStack[(*subMemberStackPos)++] = *curMember;
10206
10207             *curMember = (*curMember).members.first;
10208             while(*curMember && (*curMember).isProperty)
10209                *curMember = (*curMember).next;                     
10210          }
10211       }
10212    }
10213    while(!*curMember)
10214    {
10215       if(!*curMember)
10216       {
10217          if(subMemberStackPos && *subMemberStackPos)
10218          {
10219             *curMember = subMemberStack[--(*subMemberStackPos)];
10220             *curMember = (*curMember).next;
10221          }
10222          else
10223          {
10224             Class lastCurClass = *curClass;
10225
10226             if(*curClass == _class) break;     // REACHED THE END
10227
10228             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass; *curClass = (*curClass).base);
10229             *curMember = (*curClass).membersAndProperties.first;
10230          }
10231
10232          while((*curMember) && (*curMember).isProperty)
10233             *curMember = (*curMember).next;
10234          if(subMemberStackPos)
10235          {
10236             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10237             {
10238                subMemberStack[(*subMemberStackPos)++] = *curMember;
10239
10240                *curMember = (*curMember).members.first;
10241                while(*curMember && (*curMember).isProperty)
10242                   *curMember = (*curMember).next;                     
10243             }
10244          }
10245       }
10246    }
10247 }
10248
10249
10250 static void ProcessInitializer(Initializer init, Type type)
10251 {
10252    switch(init.type)
10253    {
10254       case expInitializer:
10255          if(!init.exp || init.exp.type != instanceExp || !init.exp.instance || init.exp.instance._class || !type || type.kind == classType)
10256          {
10257             // TESTING THIS FOR SHUTTING = 0 WARNING
10258             if(init.exp && !init.exp.destType)
10259             {
10260                FreeType(init.exp.destType);
10261                init.exp.destType = type;
10262                if(type) type.refCount++;
10263             }
10264             if(init.exp)
10265             {
10266                ProcessExpressionType(init.exp);
10267                init.isConstant = init.exp.isConstant;
10268             }
10269             break;
10270          }
10271          else
10272          {
10273             Expression exp = init.exp;
10274             Instantiation inst = exp.instance;
10275             MembersInit members;
10276
10277             init.type = listInitializer;
10278             init.list = MkList();
10279
10280             if(inst.members)
10281             {
10282                for(members = inst.members->first; members; members = members.next)
10283                {
10284                   if(members.type == dataMembersInit)
10285                   {
10286                      MemberInit member;
10287                      for(member = members.dataMembers->first; member; member = member.next)
10288                      {
10289                         ListAdd(init.list, member.initializer);
10290                         member.initializer = null;
10291                      }
10292                   }
10293                   // Discard all MembersInitMethod
10294                }
10295             }
10296             FreeExpression(exp);
10297          }
10298       case listInitializer:
10299       {
10300          Initializer i;
10301          Type initializerType = null;
10302          Class curClass = null;
10303          DataMember curMember = null;
10304          DataMember subMemberStack[256];
10305          int subMemberStackPos = 0;
10306
10307          if(type && type.kind == arrayType)
10308             initializerType = Dereference(type);
10309          else if(type && (type.kind == structType || type.kind == unionType))
10310             initializerType = type.members.first;
10311
10312          for(i = init.list->first; i; i = i.next)
10313          {
10314             if(type && type.kind == classType && type._class && type._class.registered)
10315             {
10316                // THIS IS FOR A C STYLE INSTANTIATION OF STRUCT CLASSES ONLY... WE ONLY CARE ABOUT DATA MEMBERS, AND ACTUAL MEMORY ORDER (PRIVATE MEMBERS ARE INCLUDED)
10317                FindNextDataMember(type._class.registered, &curClass, &curMember, subMemberStack, &subMemberStackPos);
10318                // TODO: Generate error on initializing a private data member this way from another module...
10319                if(curMember)
10320                {
10321                   if(!curMember.dataType)
10322                      curMember.dataType = ProcessTypeString(curMember.dataTypeString, false);
10323                   initializerType = curMember.dataType;
10324                }
10325             }
10326             ProcessInitializer(i, initializerType);
10327             if(initializerType && type && (type.kind == structType || type.kind == unionType))
10328                initializerType = initializerType.next;
10329             if(!i.isConstant)
10330                init.isConstant = false;
10331          }
10332
10333          if(type && type.kind == arrayType)
10334             FreeType(initializerType);
10335
10336          if(type && type.kind != arrayType && type.kind != structType && type.kind != unionType && (type.kind != classType || !type._class.registered || type._class.registered.type != structClass))
10337          {
10338             Compiler_Error($"Assigning list initializer to non list\n");
10339          }
10340          break;
10341       }
10342    }
10343 }
10344
10345 static void ProcessSpecifier(Specifier spec, bool declareStruct)
10346 {
10347    switch(spec.type)
10348    {
10349       case baseSpecifier:
10350       {
10351          if(spec.specifier == THISCLASS)
10352          {
10353             if(thisClass)
10354             {
10355                spec.type = nameSpecifier;
10356                spec.name = ReplaceThisClass(thisClass);
10357                spec.symbol = FindClass(spec.name);
10358                ProcessSpecifier(spec, declareStruct);
10359             }
10360          }
10361          break;
10362       }
10363       case nameSpecifier:
10364       {
10365          Symbol symbol = FindType(curContext, spec.name);
10366          if(symbol)
10367             DeclareType(symbol.type, true, true);
10368          else if((symbol = spec.symbol /*FindClass(spec.name)*/) && symbol.registered && symbol.registered.type == structClass && declareStruct)
10369             DeclareStruct(spec.name, false);
10370          break;
10371       }
10372       case enumSpecifier:
10373       {
10374          Enumerator e;
10375          if(spec.list)
10376          {
10377             for(e = spec.list->first; e; e = e.next)
10378             {
10379                if(e.exp)
10380                   ProcessExpressionType(e.exp);
10381             }
10382          }
10383          break;
10384       }
10385       case structSpecifier:
10386       case unionSpecifier:
10387       {
10388          if(spec.definitions)
10389          {
10390             ClassDef def;
10391             Symbol symbol = spec.id ? FindClass(spec.id.string) : null;
10392             //if(symbol)
10393                ProcessClass(spec.definitions, symbol);
10394             /*else
10395             {
10396                for(def = spec.definitions->first; def; def = def.next)
10397                {
10398                   //if(def.type == declarationClassDef && def.decl && def.decl.type == DeclarationStruct)
10399                      ProcessDeclaration(def.decl);
10400                }
10401             }*/
10402          }
10403          break;
10404       }
10405       /*
10406       case classSpecifier:
10407       {
10408          Symbol classSym = FindClass(spec.name);
10409          if(classSym && classSym.registered && classSym.registered.type == structClass)
10410             DeclareStruct(spec.name, false);
10411          break;
10412       }
10413       */
10414    }
10415 }
10416
10417
10418 static void ProcessDeclarator(Declarator decl)
10419 {
10420    switch(decl.type)
10421    {
10422       case identifierDeclarator:
10423          if(decl.identifier.classSym /* TODO: Name Space Fix ups  || decl.identifier.nameSpace*/)
10424          {
10425             FreeSpecifier(decl.identifier._class);
10426             decl.identifier._class = null;
10427          }
10428          break;
10429       case arrayDeclarator:
10430          if(decl.array.exp)
10431             ProcessExpressionType(decl.array.exp);
10432       case structDeclarator:
10433       case bracketsDeclarator:
10434       case functionDeclarator:
10435       case pointerDeclarator:
10436       case extendedDeclarator:
10437       case extendedDeclaratorEnd:
10438          if(decl.declarator)
10439             ProcessDeclarator(decl.declarator);
10440          if(decl.type == functionDeclarator)
10441          {
10442             Identifier id = GetDeclId(decl);
10443             if(id && id._class)
10444             {
10445                TypeName param
10446                {
10447                   qualifiers = MkListOne(id._class);
10448                   declarator = null;
10449                };
10450                if(!decl.function.parameters)
10451                   decl.function.parameters = MkList();               
10452                decl.function.parameters->Insert(null, param);
10453                id._class = null;
10454             }
10455             if(decl.function.parameters)
10456             {
10457                TypeName param;
10458                
10459                for(param = decl.function.parameters->first; param; param = param.next)
10460                {
10461                   if(param.qualifiers && param.qualifiers->first)
10462                   {
10463                      Specifier spec = param.qualifiers->first;
10464                      if(spec && spec.specifier == TYPED_OBJECT)
10465                      {
10466                         Declarator d = param.declarator;
10467                         TypeName newParam
10468                         {
10469                            qualifiers = MkListOne(MkSpecifier(VOID));
10470                            declarator = MkDeclaratorPointer(MkPointer(null,null), d);
10471                         };
10472                         
10473                         FreeList(param.qualifiers, FreeSpecifier);
10474
10475                         param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
10476                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
10477
10478                         decl.function.parameters->Insert(param, newParam);
10479                         param = newParam;
10480                      }
10481                      else if(spec && spec.specifier == ANY_OBJECT)
10482                      {
10483                         Declarator d = param.declarator;
10484                         
10485                         FreeList(param.qualifiers, FreeSpecifier);
10486
10487                         param.qualifiers = MkListOne(MkSpecifier(VOID));
10488                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);                        
10489                      }
10490                      else if(spec.specifier == THISCLASS)
10491                      {
10492                         if(thisClass)
10493                         {
10494                            spec.type = nameSpecifier;
10495                            spec.name = ReplaceThisClass(thisClass);
10496                            spec.symbol = FindClass(spec.name);
10497                            ProcessSpecifier(spec, false);
10498                         }
10499                      }
10500                   }
10501
10502                   if(param.declarator)
10503                      ProcessDeclarator(param.declarator);
10504                }
10505             }
10506          }
10507          break;
10508    }
10509 }
10510
10511 static void ProcessDeclaration(Declaration decl)
10512 {
10513    yylloc = decl.loc;
10514    switch(decl.type)
10515    {
10516       case initDeclaration:
10517       {
10518          bool declareStruct = false;
10519          /*
10520          lineNum = decl.pos.line;
10521          column = decl.pos.col;
10522          */
10523
10524          if(decl.declarators)
10525          {
10526             InitDeclarator d;
10527          
10528             for(d = decl.declarators->first; d; d = d.next)
10529             {
10530                Type type, subType;
10531                ProcessDeclarator(d.declarator);
10532
10533                type = ProcessType(decl.specifiers, d.declarator);
10534
10535                if(d.initializer)
10536                {
10537                   ProcessInitializer(d.initializer, type);
10538
10539                   // Change "ColorRGB a = ColorRGB { 1,2,3 } => ColorRGB a { 1,2,3 }                  
10540                   
10541                   if(decl.declarators->count == 1 && d.initializer.type == expInitializer &&
10542                      d.initializer.exp.type == instanceExp)
10543                   {
10544                      if(type.kind == classType && type._class == 
10545                         d.initializer.exp.expType._class)
10546                      {
10547                         Instantiation inst = d.initializer.exp.instance;
10548                         inst.exp = MkExpIdentifier(CopyIdentifier(GetDeclId(d.declarator)));
10549                         
10550                         d.initializer.exp.instance = null;
10551                         if(decl.specifiers)
10552                            FreeList(decl.specifiers, FreeSpecifier);
10553                         FreeList(decl.declarators, FreeInitDeclarator);
10554
10555                         d = null;
10556
10557                         decl.type = instDeclaration;
10558                         decl.inst = inst;
10559                      }
10560                   }
10561                }
10562                for(subType = type; subType;)
10563                {
10564                   if(subType.kind == classType)
10565                   {
10566                      declareStruct = true;
10567                      break;
10568                   }
10569                   else if(subType.kind == pointerType)
10570                      break;
10571                   else if(subType.kind == arrayType)
10572                      subType = subType.arrayType;
10573                   else
10574                      break;
10575                }
10576
10577                FreeType(type);
10578                if(!d) break;
10579             }
10580          }
10581
10582          if(decl.specifiers)
10583          {
10584             Specifier s;
10585             for(s = decl.specifiers->first; s; s = s.next)
10586             {
10587                ProcessSpecifier(s, declareStruct);
10588             }
10589          }
10590          break;
10591       }
10592       case instDeclaration:
10593       {
10594          ProcessInstantiationType(decl.inst);
10595          break;
10596       }
10597       case structDeclaration:
10598       {
10599          Specifier spec;
10600          Declarator d;
10601          bool declareStruct = false;
10602
10603          if(decl.declarators)
10604          {
10605             for(d = decl.declarators->first; d; d = d.next)
10606             {
10607                Type type = ProcessType(decl.specifiers, d.declarator);
10608                Type subType;
10609                ProcessDeclarator(d);
10610                for(subType = type; subType;)
10611                {
10612                   if(subType.kind == classType)
10613                   {
10614                      declareStruct = true;
10615                      break;
10616                   }
10617                   else if(subType.kind == pointerType)
10618                      break;
10619                   else if(subType.kind == arrayType)
10620                      subType = subType.arrayType;
10621                   else
10622                      break;
10623                }
10624                FreeType(type);
10625             }
10626          }
10627          if(decl.specifiers)
10628          {
10629             for(spec = decl.specifiers->first; spec; spec = spec.next)
10630                ProcessSpecifier(spec, declareStruct);
10631          }
10632          break;
10633       }
10634    }
10635 }
10636
10637 static FunctionDefinition curFunction;
10638
10639 static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
10640 {
10641    char propName[1024], propNameM[1024];
10642    char getName[1024], setName[1024];
10643    OldList * args;
10644
10645    DeclareProperty(prop, setName, getName);
10646
10647    // eInstance_FireWatchers(object, prop);
10648    strcpy(propName, "__ecereProp_");
10649    FullClassNameCat(propName, prop._class.fullName, false);
10650    strcat(propName, "_");
10651    // strcat(propName, prop.name);
10652    FullClassNameCat(propName, prop.name, true);
10653    MangleClassName(propName);
10654
10655    strcpy(propNameM, "__ecerePropM_");
10656    FullClassNameCat(propNameM, prop._class.fullName, false);
10657    strcat(propNameM, "_");
10658    // strcat(propNameM, prop.name);
10659    FullClassNameCat(propNameM, prop.name, true);
10660    MangleClassName(propNameM);
10661
10662    if(prop.isWatchable)
10663    {
10664       args = MkList();
10665       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10666       ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10667       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10668
10669       args = MkList();
10670       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10671       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10672       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10673    }
10674
10675    
10676    {
10677       args = MkList();
10678       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10679       ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10680       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10681
10682       args = MkList();
10683       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10684       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10685       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10686    }
10687    
10688    if(curFunction.propSet && !strcmp(curFunction.propSet.string, prop.name) && 
10689       (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
10690       curFunction.propSet.fireWatchersDone = true;
10691 }
10692
10693 static void ProcessStatement(Statement stmt)
10694 {
10695    yylloc = stmt.loc;
10696    /*
10697    lineNum = stmt.pos.line;
10698    column = stmt.pos.col;
10699    */
10700    switch(stmt.type)
10701    {
10702       case labeledStmt:
10703          ProcessStatement(stmt.labeled.stmt);
10704          break;
10705       case caseStmt:
10706          // This expression should be constant...
10707          if(stmt.caseStmt.exp)
10708          {
10709             FreeType(stmt.caseStmt.exp.destType);
10710             stmt.caseStmt.exp.destType = curSwitchType;
10711             if(curSwitchType) curSwitchType.refCount++;
10712             ProcessExpressionType(stmt.caseStmt.exp);
10713             ComputeExpression(stmt.caseStmt.exp);
10714          }
10715          if(stmt.caseStmt.stmt)
10716             ProcessStatement(stmt.caseStmt.stmt);
10717          break;
10718       case compoundStmt:
10719       {
10720          if(stmt.compound.context)
10721          {
10722             Declaration decl;
10723             Statement s;
10724
10725             Statement prevCompound = curCompound;
10726             Context prevContext = curContext;
10727
10728             if(!stmt.compound.isSwitch)
10729             {
10730                curCompound = stmt;
10731                curContext = stmt.compound.context;
10732             }
10733
10734             if(stmt.compound.declarations)
10735             {
10736                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
10737                   ProcessDeclaration(decl);
10738             }
10739             if(stmt.compound.statements)
10740             {
10741                for(s = stmt.compound.statements->first; s; s = s.next)
10742                   ProcessStatement(s);
10743             }
10744
10745             curContext = prevContext;
10746             curCompound = prevCompound;
10747          }
10748          break;
10749       }
10750       case expressionStmt:
10751       {
10752          Expression exp;
10753          if(stmt.expressions)
10754          {
10755             for(exp = stmt.expressions->first; exp; exp = exp.next)
10756                ProcessExpressionType(exp);
10757          }
10758          break;
10759       }
10760       case ifStmt:
10761       {
10762          Expression exp;
10763
10764          FreeType(((Expression)stmt.ifStmt.exp->last).destType);
10765          ((Expression)stmt.ifStmt.exp->last).destType = MkClassType("bool");
10766          ((Expression)stmt.ifStmt.exp->last).destType.truth = true;
10767          for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
10768          {
10769             ProcessExpressionType(exp);
10770          }
10771          if(stmt.ifStmt.stmt)
10772             ProcessStatement(stmt.ifStmt.stmt);
10773          if(stmt.ifStmt.elseStmt)
10774             ProcessStatement(stmt.ifStmt.elseStmt);
10775          break;
10776       }
10777       case switchStmt:
10778       {
10779          Type oldSwitchType = curSwitchType;
10780          if(stmt.switchStmt.exp)
10781          {
10782             Expression exp;
10783             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
10784             {
10785                if(!exp.next)
10786                {
10787                   /*
10788                   Type destType
10789                   {
10790                      kind = intType;
10791                      refCount = 1;
10792                   };
10793                   e.exp.destType = destType;
10794                   */
10795
10796                   ProcessExpressionType(exp);
10797                }
10798                if(!exp.next)
10799                   curSwitchType = exp.expType;
10800             }
10801          }
10802          ProcessStatement(stmt.switchStmt.stmt);
10803          curSwitchType = oldSwitchType;
10804          break;
10805       }
10806       case whileStmt:
10807       {
10808          if(stmt.whileStmt.exp)
10809          {
10810             Expression exp;
10811
10812             FreeType(((Expression)stmt.whileStmt.exp->last).destType);
10813             ((Expression)stmt.whileStmt.exp->last).destType = MkClassType("bool");
10814             ((Expression)stmt.whileStmt.exp->last).destType.truth = true;
10815             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
10816             {
10817                ProcessExpressionType(exp);
10818             }
10819          }
10820          if(stmt.whileStmt.stmt)
10821             ProcessStatement(stmt.whileStmt.stmt);
10822          break;
10823       }
10824       case doWhileStmt:
10825       {
10826          if(stmt.doWhile.exp)
10827          {
10828             Expression exp;
10829
10830             if(stmt.doWhile.exp->last)
10831             {
10832                FreeType(((Expression)stmt.doWhile.exp->last).destType);
10833                ((Expression)stmt.doWhile.exp->last).destType = MkClassType("bool");
10834                ((Expression)stmt.doWhile.exp->last).destType.truth = true;
10835             }
10836             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
10837             {
10838                ProcessExpressionType(exp);
10839             }
10840          }
10841          if(stmt.doWhile.stmt)
10842             ProcessStatement(stmt.doWhile.stmt);
10843          break;
10844       }
10845       case forStmt:
10846       {
10847          Expression exp;
10848          if(stmt.forStmt.init)
10849             ProcessStatement(stmt.forStmt.init);
10850
10851          if(stmt.forStmt.check && stmt.forStmt.check.expressions)
10852          {
10853             FreeType(((Expression)stmt.forStmt.check.expressions->last).destType);
10854             ((Expression)stmt.forStmt.check.expressions->last).destType = MkClassType("bool");
10855             ((Expression)stmt.forStmt.check.expressions->last).destType.truth = true;
10856          }
10857
10858          if(stmt.forStmt.check)
10859             ProcessStatement(stmt.forStmt.check);
10860          if(stmt.forStmt.increment)
10861          {
10862             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
10863                ProcessExpressionType(exp);
10864          }
10865
10866          if(stmt.forStmt.stmt)
10867             ProcessStatement(stmt.forStmt.stmt);
10868          break;
10869       }
10870       case forEachStmt:
10871       {
10872          Identifier id = stmt.forEachStmt.id;
10873          OldList * exp = stmt.forEachStmt.exp;
10874          OldList * filter = stmt.forEachStmt.filter;
10875          Statement block = stmt.forEachStmt.stmt;
10876          char iteratorType[1024];
10877          Type source;
10878          Expression e;
10879          bool isBuiltin = exp && exp->last && 
10880             (((Expression)exp->last).type == ExpressionType::arrayExp || 
10881               (((Expression)exp->last).type == castExp && ((Expression)exp->last).cast.exp.type == ExpressionType::arrayExp));
10882          Expression arrayExp;
10883          char * typeString = null;
10884          int builtinCount = 0;
10885
10886          for(e = exp ? exp->first : null; e; e = e.next)
10887          {
10888             if(!e.next)
10889             {
10890                FreeType(e.destType);
10891                e.destType = ProcessTypeString("Container", false);
10892             }
10893             if(!isBuiltin || e.next)
10894                ProcessExpressionType(e);
10895          }
10896
10897          source = (exp && exp->last) ? ((Expression)exp->last).expType : null;
10898          if(isBuiltin || (source && source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
10899             eClass_IsDerived(source._class.registered, containerClass)))
10900          {
10901             Class _class = source ? source._class.registered : null;
10902             Symbol symbol;
10903             Expression expIt = null;
10904             bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false, isAVLTree = false;
10905             Class arrayClass = eSystem_FindClass(privateModule, "Array");
10906             Class linkListClass = eSystem_FindClass(privateModule, "LinkList");
10907             Class customAVLTreeClass = eSystem_FindClass(privateModule, "CustomAVLTree");
10908             stmt.type = compoundStmt;
10909             
10910             stmt.compound.context = Context { };
10911             stmt.compound.context.parent = curContext;
10912             curContext = stmt.compound.context;
10913
10914             if(source && eClass_IsDerived(source._class.registered, customAVLTreeClass))
10915             {
10916                Class mapClass = eSystem_FindClass(privateModule, "Map");
10917                Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
10918                isCustomAVLTree = true;
10919                if(eClass_IsDerived(source._class.registered, avlTreeClass))
10920                   isAVLTree = true;
10921                else if(eClass_IsDerived(source._class.registered, mapClass))
10922                   isMap = true;
10923             }
10924             else if(source && eClass_IsDerived(source._class.registered, arrayClass)) isArray = true;
10925             else if(source && eClass_IsDerived(source._class.registered, linkListClass)) 
10926             {
10927                Class listClass = eSystem_FindClass(privateModule, "List");
10928                isLinkList = true;
10929                isList = eClass_IsDerived(source._class.registered, listClass);
10930             }
10931
10932             if(isArray)
10933             {
10934                Declarator decl;
10935                OldList * specs = MkList();
10936                decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
10937                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
10938                stmt.compound.declarations = MkListOne(
10939                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
10940                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
10941                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalArray")), 
10942                      MkInitializerAssignment(MkExpBrackets(exp))))));
10943             }
10944             else if(isBuiltin)
10945             {
10946                Type type = null;
10947                char typeStringBuf[1024];
10948                
10949                // TODO: Merge this code?
10950                arrayExp = (((Expression)exp->last).type == ExpressionType::arrayExp) ? (Expression)exp->last : ((Expression)exp->last).cast.exp;
10951                if(((Expression)exp->last).type == castExp)
10952                {
10953                   TypeName typeName = ((Expression)exp->last).cast.typeName;
10954                   if(typeName)
10955                      arrayExp.destType = ProcessType(typeName.qualifiers, typeName.declarator);
10956                }
10957
10958                if(arrayExp.destType && arrayExp.destType.kind == classType && arrayExp.destType._class && arrayExp.destType._class.registered &&
10959                   arrayExp.destType._class.registered != containerClass && eClass_IsDerived(arrayExp.destType._class.registered, containerClass) &&
10960                   arrayExp.destType._class.registered.templateArgs)
10961                {
10962                   Class templateClass = arrayExp.destType._class.registered;
10963                   typeString = templateClass.templateArgs[2].dataTypeString;
10964                }
10965                else if(arrayExp.list)
10966                {
10967                   // Guess type from expressions in the array
10968                   Expression e;
10969                   for(e = arrayExp.list->first; e; e = e.next)
10970                   {
10971                      ProcessExpressionType(e);
10972                      if(e.expType)
10973                      {
10974                         if(!type) { type = e.expType; type.refCount++; }
10975                         else
10976                         {
10977                            // if(!MatchType(e.expType, type, null, null, null, false, false, false))
10978                            if(!MatchTypeExpression(e, type, null, false))
10979                            {
10980                               FreeType(type);
10981                               type = e.expType;
10982                               e.expType = null;
10983                               
10984                               e = arrayExp.list->first;
10985                               ProcessExpressionType(e);
10986                               if(e.expType)
10987                               {
10988                                  //if(!MatchTypes(e.expType, type, null, null, null, false, false, false, false))
10989                                  if(!MatchTypeExpression(e, type, null, false))
10990                                  {
10991                                     FreeType(e.expType);
10992                                     e.expType = null;
10993                                     FreeType(type);
10994                                     type = null;
10995                                     break;
10996                                  }                           
10997                               }
10998                            }
10999                         }
11000                         if(e.expType)
11001                         {
11002                            FreeType(e.expType);
11003                            e.expType = null;
11004                         }
11005                      }
11006                   }
11007                   if(type)
11008                   {
11009                      typeStringBuf[0] = '\0';
11010                      PrintType(type, typeStringBuf, false, true);
11011                      typeString = typeStringBuf;
11012                      FreeType(type);
11013                   }
11014                }
11015                if(typeString)
11016                {
11017                   OldList * initializers = MkList();
11018                   Declarator decl;
11019                   OldList * specs = MkList();
11020                   if(arrayExp.list)
11021                   {
11022                      Expression e;
11023
11024                      builtinCount = arrayExp.list->count;
11025                      type = ProcessTypeString(typeString, false);
11026                      while(e = arrayExp.list->first)
11027                      {
11028                         arrayExp.list->Remove(e);
11029                         e.destType = type;
11030                         type.refCount++;
11031                         ProcessExpressionType(e);
11032                         ListAdd(initializers, MkInitializerAssignment(e));
11033                      }
11034                      FreeType(type);
11035                      delete arrayExp.list;
11036                   }
11037                   decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
11038                   stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier), 
11039                      MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
11040
11041                   ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorArray(PlugDeclarator(
11042                      /*CopyDeclarator(*/decl/*)*/, MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), null), MkInitializerList(initializers)))));
11043                   
11044                   FreeList(exp, FreeExpression);
11045                }
11046                else
11047                {
11048                   arrayExp.expType = ProcessTypeString("Container", false);
11049                   Compiler_Error($"Couldn't determine type of array elements\n");
11050                }
11051
11052                /*
11053                Declarator decl;
11054                OldList * specs = MkList();
11055
11056                decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
11057                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
11058                stmt.compound.declarations = MkListOne(
11059                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11060                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName("BuiltInContainer")),
11061                   MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), 
11062                      MkInitializerAssignment(MkExpBrackets(exp))))));
11063                */
11064             }
11065             else if(isLinkList && !isList)
11066             {
11067                Declarator decl;
11068                OldList * specs = MkList();
11069                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11070                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11071                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11072                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalLinkList")), 
11073                      MkInitializerAssignment(MkExpBrackets(exp))))));
11074             }
11075             /*else if(isCustomAVLTree)
11076             {
11077                Declarator decl;
11078                OldList * specs = MkList();
11079                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11080                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11081                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11082                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalTree")), 
11083                      MkInitializerAssignment(MkExpBrackets(exp))))));
11084             }*/
11085             else if(_class.templateArgs)
11086             {
11087                if(isMap)
11088                   sprintf(iteratorType, "MapIterator<%s, %s >", _class.templateArgs[5].dataTypeString, _class.templateArgs[6].dataTypeString);
11089                else
11090                   sprintf(iteratorType, "Iterator<%s, %s >", _class.templateArgs[2].dataTypeString, _class.templateArgs[1].dataTypeString);
11091
11092                stmt.compound.declarations = MkListOne(
11093                   MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName(iteratorType)),
11094                   MkExpIdentifier(id), MkListOne(MkMembersInitList(MkListOne(MkMemberInit(isMap ? MkListOne(MkIdentifier("map")) : null, 
11095                   MkInitializerAssignment(MkExpBrackets(exp)))))))));
11096             }
11097             symbol = FindSymbol(id.string, curContext, curContext, false, false);
11098
11099             if(block && block.type == compoundStmt && block.compound.context)
11100             {
11101                block.compound.context.parent = stmt.compound.context;
11102             }
11103             if(filter)
11104             {
11105                block = MkIfStmt(filter, block, null);
11106             }
11107             if(isArray)
11108             {
11109                stmt.compound.statements = MkListOne(MkForStmt(
11110                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
11111                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11112                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11113                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11114                   block));
11115               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11116               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11117               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11118             }
11119             else if(isBuiltin)
11120             {
11121                char count[128];
11122                //OldList * specs = MkList();
11123                // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11124
11125                sprintf(count, "%d", builtinCount);
11126
11127                stmt.compound.statements = MkListOne(MkForStmt(
11128                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
11129                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11130                      MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
11131                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11132                   block));
11133
11134                /*
11135                Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11136                stmt.compound.statements = MkListOne(MkForStmt(
11137                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
11138                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11139                      MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11140                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11141                   block));
11142               */
11143               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11144               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11145               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11146             }
11147             else if(isLinkList && !isList)
11148             {
11149                Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
11150                Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
11151                if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString && 
11152                   !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
11153                {
11154                   stmt.compound.statements = MkListOne(MkForStmt(
11155                      MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11156                      MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11157                      MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11158                      block));
11159                }
11160                else
11161                {
11162                   OldList * specs = MkList();
11163                   Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
11164                   stmt.compound.statements = MkListOne(MkForStmt(
11165                      MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11166                      MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11167                      MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
11168                         MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
11169                            MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
11170                      block));
11171                }
11172                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11173                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11174                ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11175             }
11176             /*else if(isCustomAVLTree)
11177             {
11178                stmt.compound.statements = MkListOne(MkForStmt(
11179                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
11180                      MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
11181                   MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11182                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11183                   block));
11184
11185                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11186                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11187                ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11188             }*/
11189             else
11190             {
11191                stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
11192                   MkIdentifier("Next")), null)), block));
11193             }
11194             ProcessExpressionType(expIt);
11195             if(stmt.compound.declarations->first)
11196                ProcessDeclaration(stmt.compound.declarations->first);
11197
11198             if(symbol) 
11199                symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
11200
11201             ProcessStatement(stmt);
11202             curContext = stmt.compound.context.parent;
11203             break;
11204          }
11205          else
11206          {
11207             Compiler_Error($"Expression is not a container\n");
11208          }
11209          break;
11210       }
11211       case gotoStmt:
11212          break;
11213       case continueStmt:
11214          break;
11215       case breakStmt:
11216          break;
11217       case returnStmt:
11218       {
11219          Expression exp;
11220          if(stmt.expressions)
11221          {
11222             for(exp = stmt.expressions->first; exp; exp = exp.next)
11223             {
11224                if(!exp.next)
11225                {
11226                   if(curFunction && !curFunction.type)
11227                      curFunction.type = ProcessType(
11228                         curFunction.specifiers, curFunction.declarator);
11229                   FreeType(exp.destType);
11230                   exp.destType = (curFunction && curFunction.type && curFunction.type.kind == functionType) ? curFunction.type.returnType : null;
11231                   if(exp.destType) exp.destType.refCount++;
11232                }
11233                ProcessExpressionType(exp);
11234             }
11235          }
11236          break;
11237       }
11238       case badDeclarationStmt:
11239       {
11240          ProcessDeclaration(stmt.decl);
11241          break;
11242       }
11243       case asmStmt:
11244       {
11245          AsmField field;
11246          if(stmt.asmStmt.inputFields)
11247          {
11248             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
11249                if(field.expression)
11250                   ProcessExpressionType(field.expression);
11251          }
11252          if(stmt.asmStmt.outputFields)
11253          {
11254             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
11255                if(field.expression)
11256                   ProcessExpressionType(field.expression);
11257          }
11258          if(stmt.asmStmt.clobberedFields)
11259          {
11260             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
11261             {
11262                if(field.expression)
11263                   ProcessExpressionType(field.expression);
11264             }
11265          }
11266          break;
11267       }
11268       case watchStmt:
11269       {
11270          PropertyWatch propWatch;
11271          OldList * watches = stmt._watch.watches;
11272          Expression object = stmt._watch.object;
11273          Expression watcher = stmt._watch.watcher;
11274          if(watcher)
11275             ProcessExpressionType(watcher);
11276          if(object)
11277             ProcessExpressionType(object);
11278
11279          if(inCompiler)
11280          {
11281             if(watcher || thisClass)
11282             {
11283                External external = curExternal;
11284                Context context = curContext;
11285
11286                stmt.type = expressionStmt;
11287                stmt.expressions = MkList();
11288
11289                curExternal = external.prev;
11290
11291                for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11292                {
11293                   ClassFunction func;
11294                   char watcherName[1024];
11295                   Class watcherClass = watcher ? 
11296                      ((watcher.expType && watcher.expType.kind == classType && watcher.expType._class) ? watcher.expType._class.registered : null) : thisClass;
11297                   External createdExternal;
11298
11299                   // Create a declaration above
11300                   External externalDecl = MkExternalDeclaration(null);
11301                   ast->Insert(curExternal.prev, externalDecl);
11302
11303                   sprintf(watcherName,"__ecerePropertyWatcher_%d", propWatcherID++);
11304                   if(propWatch.deleteWatch)
11305                      strcat(watcherName, "_delete");
11306                   else
11307                   {
11308                      Identifier propID;
11309                      for(propID = propWatch.properties->first; propID; propID = propID.next)
11310                      {
11311                         strcat(watcherName, "_");
11312                         strcat(watcherName, propID.string);
11313                      }
11314                   }
11315
11316                   if(object && object.expType && object.expType.kind == classType && object.expType._class && object.expType._class.registered)
11317                   {
11318                      // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
11319                      func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)),
11320                         //MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null))), null);
11321                         MkListOne(MkTypeName(MkListOne(MkSpecifierName(object.expType._class.string)), MkDeclaratorIdentifier(MkIdentifier("value"))))), null);
11322                      ProcessClassFunctionBody(func, propWatch.compound);
11323                      propWatch.compound = null;
11324
11325                      //afterExternal = afterExternal ? afterExternal : curExternal;
11326
11327                      //createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal.prev);
11328                      createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal, true);
11329                      // TESTING THIS...
11330                      createdExternal.symbol.idCode = external.symbol.idCode;
11331
11332                      curExternal = createdExternal;
11333                      ProcessFunction(createdExternal.function);
11334
11335
11336                      // Create a declaration above
11337                      {
11338                         Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier), 
11339                            MkListOne(MkInitDeclarator(CopyDeclarator(createdExternal.function.declarator), null)));
11340                         externalDecl.declaration = decl;
11341                         if(decl.symbol && !decl.symbol.pointerExternal)
11342                            decl.symbol.pointerExternal = externalDecl;
11343                      }
11344
11345                      if(propWatch.deleteWatch)
11346                      {
11347                         OldList * args = MkList();
11348                         ListAdd(args, CopyExpression(object));
11349                         ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11350                         ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11351                         ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_WatchDestruction")), args));
11352                      }
11353                      else
11354                      {
11355                         Class _class = object.expType._class.registered;
11356                         Identifier propID;
11357
11358                         for(propID = propWatch.properties->first; propID; propID = propID.next)
11359                         {
11360                            char propName[1024];
11361                            Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11362                            if(prop)
11363                            {
11364                               char getName[1024], setName[1024];
11365                               OldList * args = MkList();
11366
11367                               DeclareProperty(prop, setName, getName);                              
11368                               
11369                               // eInstance_Watch(stmt.watch.object, prop, stmt.watch.watcher, callback);
11370                               strcpy(propName, "__ecereProp_");
11371                               FullClassNameCat(propName, prop._class.fullName, false);
11372                               strcat(propName, "_");
11373                               // strcat(propName, prop.name);
11374                               FullClassNameCat(propName, prop.name, true);
11375
11376                               ListAdd(args, CopyExpression(object));
11377                               ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11378                               ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11379                               ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11380
11381                               ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), args));
11382                            }
11383                            else
11384                               Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
11385                         }
11386                      }
11387                   }
11388                   else
11389                      Compiler_Error($"Invalid watched object\n");
11390                }
11391
11392                curExternal = external;
11393                curContext = context;
11394
11395                if(watcher)
11396                   FreeExpression(watcher);
11397                if(object)
11398                   FreeExpression(object);
11399                FreeList(watches, FreePropertyWatch);
11400             }
11401             else
11402                Compiler_Error($"No observer specified and not inside a _class\n");
11403          }
11404          else
11405          {
11406             for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11407             {
11408                ProcessStatement(propWatch.compound);
11409             }
11410
11411          }
11412          break;
11413       }
11414       case fireWatchersStmt:
11415       {
11416          OldList * watches = stmt._watch.watches;
11417          Expression object = stmt._watch.object;
11418          Class _class;
11419          // DEBUGGER BUG: Why doesn't watches evaluate to null??
11420          // printf("%X\n", watches);
11421          // printf("%X\n", stmt._watch.watches);
11422          if(object)
11423             ProcessExpressionType(object);
11424
11425          if(inCompiler)
11426          {
11427             _class = object ? 
11428                   ((object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null) : thisClass;
11429
11430             if(_class)
11431             {
11432                Identifier propID;
11433
11434                stmt.type = expressionStmt;
11435                stmt.expressions = MkList();
11436
11437                // Check if we're inside a property set
11438                if(!watches && curFunction.propSet && (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
11439                {
11440                   watches = MkListOne(MkIdentifier(curFunction.propSet.string));
11441                }
11442                else if(!watches)
11443                {
11444                   //Compiler_Error($"No property specified and not inside a property set\n");
11445                }
11446                if(watches)
11447                {
11448                   for(propID = watches->first; propID; propID = propID.next)
11449                   {
11450                      Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11451                      if(prop)
11452                      {
11453                         CreateFireWatcher(prop, object, stmt);
11454                      }
11455                      else
11456                         Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
11457                   }
11458                }
11459                else
11460                {
11461                   // Fire all properties!
11462                   Property prop;
11463                   Class base;
11464                   for(base = _class; base; base = base.base)
11465                   {
11466                      for(prop = base.membersAndProperties.first; prop; prop = prop.next)
11467                      {
11468                         if(prop.isProperty && prop.isWatchable)
11469                         {
11470                            CreateFireWatcher(prop, object, stmt);
11471                         }
11472                      }
11473                   }
11474                }
11475
11476                if(object)
11477                   FreeExpression(object);
11478                FreeList(watches, FreeIdentifier);
11479             }
11480             else
11481                Compiler_Error($"Invalid object specified and not inside a class\n");
11482          }
11483          break;
11484       }
11485       case stopWatchingStmt:
11486       {
11487          OldList * watches = stmt._watch.watches;
11488          Expression object = stmt._watch.object;
11489          Expression watcher = stmt._watch.watcher;
11490          Class _class;
11491          if(object)
11492             ProcessExpressionType(object);
11493          if(watcher)
11494             ProcessExpressionType(watcher);
11495          if(inCompiler)
11496          {
11497             _class = (object && object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null;
11498
11499             if(watcher || thisClass)
11500             {
11501                if(_class)
11502                {
11503                   Identifier propID;
11504
11505                   stmt.type = expressionStmt;
11506                   stmt.expressions = MkList();
11507
11508                   if(!watches)
11509                   {
11510                      OldList * args;
11511                      // eInstance_StopWatching(object, null, watcher); 
11512                      args = MkList();
11513                      ListAdd(args, CopyExpression(object));
11514                      ListAdd(args, MkExpConstant("0"));
11515                      ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11516                      ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11517                   }
11518                   else
11519                   {
11520                      for(propID = watches->first; propID; propID = propID.next)
11521                      {
11522                         char propName[1024];
11523                         Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11524                         if(prop)
11525                         {
11526                            char getName[1024], setName[1024];
11527                            OldList * args = MkList();
11528
11529                            DeclareProperty(prop, setName, getName);
11530          
11531                            // eInstance_StopWatching(object, prop, watcher); 
11532                            strcpy(propName, "__ecereProp_");
11533                            FullClassNameCat(propName, prop._class.fullName, false);
11534                            strcat(propName, "_");
11535                            // strcat(propName, prop.name);
11536                            FullClassNameCat(propName, prop.name, true);
11537                            MangleClassName(propName);
11538
11539                            ListAdd(args, CopyExpression(object));
11540                            ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11541                            ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11542                            ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11543                         }
11544                         else
11545                            Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
11546                      }
11547                   }
11548
11549                   if(object)
11550                      FreeExpression(object);
11551                   if(watcher)
11552                      FreeExpression(watcher);
11553                   FreeList(watches, FreeIdentifier);
11554                }
11555                else
11556                   Compiler_Error($"Invalid object specified and not inside a class\n");
11557             }
11558             else
11559                Compiler_Error($"No observer specified and not inside a class\n");
11560          }
11561          break;
11562       }
11563    }
11564 }
11565
11566 static void ProcessFunction(FunctionDefinition function)
11567 {
11568    Identifier id = GetDeclId(function.declarator);
11569    Symbol symbol = function.declarator ? function.declarator.symbol : null;
11570    Type type = symbol ? symbol.type : null;
11571    Class oldThisClass = thisClass;
11572    Context oldTopContext = topContext;
11573
11574    yylloc = function.loc;
11575    // Process thisClass
11576    
11577    if(type && type.thisClass)
11578    {
11579       Symbol classSym = type.thisClass;
11580       Class _class = type.thisClass.registered;
11581       char className[1024];
11582       char structName[1024];
11583       Declarator funcDecl;
11584       Symbol thisSymbol;
11585
11586       bool typedObject = false;
11587
11588       if(_class && !_class.base)
11589       {
11590          _class = currentClass;
11591          if(_class && !_class.symbol)
11592             _class.symbol = FindClass(_class.fullName);
11593          classSym = _class ? _class.symbol : null;
11594          typedObject = true;
11595       }
11596
11597       thisClass = _class;
11598
11599       if(inCompiler && _class)
11600       {
11601          if(type.kind == functionType)
11602          {
11603             if(symbol.type.params.count == 1 && ((Type)symbol.type.params.first).kind == voidType)
11604             {
11605                //TypeName param = symbol.type.params.first;
11606                Type param = symbol.type.params.first;
11607                symbol.type.params.Remove(param);
11608                //FreeTypeName(param);
11609                FreeType(param);
11610             }
11611             if(type.classObjectType != classPointer)
11612             {
11613                symbol.type.params.Insert(null, MkClassType(_class.fullName));
11614                symbol.type.staticMethod = true;
11615                symbol.type.thisClass = null;
11616
11617                // HIGH DANGER: VERIFYING THIS...
11618                symbol.type.extraParam = false;
11619             }
11620          }
11621
11622          strcpy(className, "__ecereClass_");
11623          FullClassNameCat(className, _class.fullName, true);
11624
11625          MangleClassName(className);
11626
11627          structName[0] = 0;
11628          FullClassNameCat(structName, _class.fullName, false);
11629
11630          // [class] this
11631          
11632
11633          funcDecl = GetFuncDecl(function.declarator);
11634          if(funcDecl)
11635          {
11636             if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11637             {
11638                TypeName param = funcDecl.function.parameters->first;
11639                if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11640                {
11641                   funcDecl.function.parameters->Remove(param);
11642                   FreeTypeName(param);
11643                }
11644             }
11645
11646             // DANGER: Watch for this... Check if it's a Conversion?
11647             // if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11648             
11649             // WAS TRYING THIS FOR CONVERSION PROPERTIES ON NOHEAD CLASSES: if((_class.type == structClass) || function != (FunctionDefinition)symbol.externalSet)
11650             if(!function.propertyNoThis)
11651             {
11652                TypeName thisParam;
11653                
11654                if(type.classObjectType != classPointer)
11655                {
11656                   thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11657                   if(!funcDecl.function.parameters)
11658                      funcDecl.function.parameters = MkList();
11659                   funcDecl.function.parameters->Insert(null, thisParam);
11660                }
11661
11662                if(typedObject)
11663                {
11664                   if(type.classObjectType != classPointer)
11665                   {
11666                      if(type.byReference || _class.type == unitClass || _class.type == systemClass || _class.type == enumClass || _class.type == bitClass)
11667                         thisParam.declarator = MkDeclaratorPointer(MkPointer(null,null), thisParam.declarator);
11668                   }
11669
11670                   thisParam = TypeName
11671                   {
11672                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
11673                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
11674                   };
11675                   funcDecl.function.parameters->Insert(null, thisParam);
11676                }
11677             }
11678          }
11679
11680          if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11681          {
11682             InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11683             funcDecl = GetFuncDecl(initDecl.declarator);
11684             if(funcDecl)
11685             {
11686                if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11687                {
11688                   TypeName param = funcDecl.function.parameters->first;
11689                   if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11690                   {
11691                      funcDecl.function.parameters->Remove(param);
11692                      FreeTypeName(param);
11693                   }
11694                }
11695
11696                if(type.classObjectType != classPointer)
11697                {
11698                   // DANGER: Watch for this... Check if it's a Conversion?
11699                   if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11700                   {
11701                      TypeName thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11702
11703                      if(!funcDecl.function.parameters)
11704                         funcDecl.function.parameters = MkList();
11705                      funcDecl.function.parameters->Insert(null, thisParam);
11706                   }
11707                }
11708             }         
11709          }
11710       }
11711       
11712       // Add this to the context
11713       if(function.body)
11714       {
11715          if(type.classObjectType != classPointer)
11716          {
11717             thisSymbol = Symbol
11718             {
11719                string = CopyString("this");
11720                type = classSym ? MkClassType(classSym.string) : null; //_class.fullName);
11721             };
11722             function.body.compound.context.symbols.Add((BTNode)thisSymbol);
11723
11724             if(typedObject && thisSymbol.type)
11725             {
11726                thisSymbol.type.classObjectType = ClassObjectType::typedObject;
11727                thisSymbol.type.byReference = type.byReference;
11728                /*
11729                thisSymbol = Symbol { string = CopyString("class") };
11730                function.body.compound.context.symbols.Add(thisSymbol);
11731                */
11732             }
11733          }
11734       }
11735
11736       // Pointer to class data
11737       
11738       if(inCompiler && _class && (_class.type == normalClass /*|| _class.type == noHeadClass*/) && type.classObjectType != classPointer)
11739       {
11740          DataMember member = null;
11741          {
11742             Class base;
11743             for(base = _class; base && base.type != systemClass; base = base.next)
11744             {
11745                for(member = base.membersAndProperties.first; member; member = member.next)
11746                   if(!member.isProperty)
11747                      break;
11748                if(member)
11749                   break;
11750             }
11751          }
11752          for(member = _class.membersAndProperties.first; member; member = member.next)
11753             if(!member.isProperty)
11754                break;
11755          if(member)
11756          {
11757             char pointerName[1024];
11758    
11759             Declaration decl;
11760             Initializer initializer;
11761             Expression exp, bytePtr;
11762    
11763             strcpy(pointerName, "__ecerePointer_");
11764             FullClassNameCat(pointerName, _class.fullName, false);
11765             {
11766                char className[1024];
11767                strcpy(className, "__ecereClass_");
11768                FullClassNameCat(className, classSym.string, true);
11769                MangleClassName(className);
11770
11771                // Testing This
11772                DeclareClass(classSym, className);
11773             }
11774
11775             // ((byte *) this)
11776             bytePtr = QBrackets(MkExpCast(QMkType("char", QMkPtrDecl(null)), QMkExpId("this")));
11777
11778             if(_class.fixed)
11779             {
11780                char string[256];
11781                sprintf(string, "%d", _class.offset);
11782                exp = QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string)));
11783             }
11784             else
11785             {
11786                // ([bytePtr] + [className]->offset)
11787                exp = QBrackets(MkExpOp(bytePtr, '+',
11788                   MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
11789             }
11790
11791             // (this ? [exp] : 0)
11792             exp = QBrackets(QMkExpCond(QMkExpId("this"), exp, MkExpConstant("0")));
11793             exp.expType = Type
11794             {
11795                refCount = 1;
11796                kind = pointerType;
11797                type = Type { refCount = 1, kind = voidType };
11798             };
11799    
11800             if(function.body)
11801             {
11802                yylloc = function.body.loc;
11803                // ([structName] *) [exp]
11804                // initializer = MkInitializerAssignment(MkExpCast(QMkType(structName, QMkPtrDecl(null)), exp));
11805                initializer = MkInitializerAssignment(
11806                   MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), exp));
11807
11808                // [structName] * [pointerName] = [initializer];
11809                // decl = QMkDeclaration(structName, MkInitDeclarator(QMkPtrDecl(pointerName), initializer));
11810
11811                {
11812                   Context prevContext = curContext;
11813                   curContext = function.body.compound.context;
11814
11815                   decl = MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
11816                      MkListOne(MkInitDeclarator(QMkPtrDecl(pointerName), initializer)));
11817
11818                   curContext = prevContext;
11819                }
11820
11821                // WHY?
11822                decl.symbol = null;
11823
11824                if(!function.body.compound.declarations)
11825                   function.body.compound.declarations = MkList();
11826                function.body.compound.declarations->Insert(null, decl);
11827             }
11828          }
11829       }
11830       
11831
11832       // Loop through the function and replace undeclared identifiers
11833       // which are a member of the class (methods, properties or data)
11834       // by "this.[member]"
11835    }
11836    else
11837       thisClass = null;
11838
11839    if(id)
11840    {
11841       FreeSpecifier(id._class);
11842       id._class = null;
11843
11844       if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11845       {
11846          InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11847          id = GetDeclId(initDecl.declarator);
11848
11849          FreeSpecifier(id._class);
11850          id._class = null;
11851       }
11852    }
11853    if(function.body)
11854       topContext = function.body.compound.context;
11855    {
11856       FunctionDefinition oldFunction = curFunction;
11857       curFunction = function;
11858       if(function.body)
11859          ProcessStatement(function.body);
11860
11861       // If this is a property set and no firewatchers has been done yet, add one here
11862       if(inCompiler && function.propSet && !function.propSet.fireWatchersDone)
11863       {
11864          Statement prevCompound = curCompound;
11865          Context prevContext = curContext;
11866
11867          Statement fireWatchers = MkFireWatchersStmt(null, null);
11868          if(!function.body.compound.statements) function.body.compound.statements = MkList();
11869          ListAdd(function.body.compound.statements, fireWatchers);
11870
11871          curCompound = function.body;
11872          curContext = function.body.compound.context;
11873
11874          ProcessStatement(fireWatchers);
11875
11876          curContext = prevContext;
11877          curCompound = prevCompound;
11878
11879       }
11880
11881       curFunction = oldFunction;
11882    }
11883
11884    if(function.declarator)
11885    {
11886       ProcessDeclarator(function.declarator);
11887    }
11888
11889    topContext = oldTopContext;
11890    thisClass = oldThisClass;
11891 }
11892
11893 /////////// INSTANTIATIONS / DATA TYPES PASS /////////////////////////////////////////////
11894 static void ProcessClass(OldList definitions, Symbol symbol)
11895 {
11896    ClassDef def;
11897    External external = curExternal;
11898    Class regClass = symbol ? symbol.registered : null;
11899
11900    // Process all functions
11901    for(def = definitions.first; def; def = def.next)
11902    {
11903       if(def.type == functionClassDef)
11904       {
11905          if(def.function.declarator)
11906             curExternal = def.function.declarator.symbol.pointerExternal;
11907          else
11908             curExternal = external;
11909
11910          ProcessFunction((FunctionDefinition)def.function);
11911       }
11912       else if(def.type == declarationClassDef)
11913       {
11914          if(def.decl.type == instDeclaration)
11915          {
11916             thisClass = regClass;
11917             ProcessInstantiationType(def.decl.inst);
11918             thisClass = null;
11919          }
11920          // Testing this
11921          else
11922          {
11923             Class backThisClass = thisClass;
11924             if(regClass) thisClass = regClass;
11925             ProcessDeclaration(def.decl);
11926             thisClass = backThisClass;
11927          }
11928       }
11929       else if(def.type == defaultPropertiesClassDef && def.defProperties)
11930       {
11931          MemberInit defProperty;
11932
11933          // Add this to the context
11934          Symbol thisSymbol = Symbol
11935          {
11936             string = CopyString("this");
11937             type = regClass ? MkClassType(regClass.fullName) : null;
11938          };
11939          globalContext.symbols.Add((BTNode)thisSymbol);
11940          
11941          for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
11942          {
11943             thisClass = regClass;
11944             ProcessMemberInitData(defProperty, regClass, null, null, null, null);
11945             thisClass = null;
11946          }
11947
11948          globalContext.symbols.Remove((BTNode)thisSymbol);
11949          FreeSymbol(thisSymbol);
11950       }
11951       else if(def.type == propertyClassDef && def.propertyDef)
11952       {
11953          PropertyDef prop = def.propertyDef;
11954
11955          // Add this to the context
11956          /*
11957          Symbol thisSymbol = Symbol { string = CopyString("this"), type = MkClassType(regClass.fullName) };
11958          globalContext.symbols.Add(thisSymbol);
11959          */
11960          
11961          thisClass = regClass;
11962          if(prop.setStmt)
11963          {
11964             if(regClass)
11965             {
11966                Symbol thisSymbol
11967                {
11968                   string = CopyString("this");
11969                   type = MkClassType(regClass.fullName);
11970                };
11971                prop.setStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11972             }
11973
11974             curExternal = prop.symbol ? prop.symbol.externalSet : null;
11975             ProcessStatement(prop.setStmt);
11976          }
11977          if(prop.getStmt)
11978          {
11979             if(regClass)
11980             {
11981                Symbol thisSymbol
11982                {
11983                   string = CopyString("this");
11984                   type = MkClassType(regClass.fullName);
11985                };
11986                prop.getStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11987             }
11988
11989             curExternal = prop.symbol ? prop.symbol.externalGet : null;
11990             ProcessStatement(prop.getStmt);
11991          }
11992          if(prop.issetStmt)
11993          {
11994             if(regClass)
11995             {
11996                Symbol thisSymbol
11997                {
11998                   string = CopyString("this");
11999                   type = MkClassType(regClass.fullName);
12000                };
12001                prop.issetStmt.compound.context.symbols.Add((BTNode)thisSymbol);
12002             }
12003
12004             curExternal = prop.symbol ? prop.symbol.externalIsSet : null;
12005             ProcessStatement(prop.issetStmt);
12006          }
12007
12008          thisClass = null;
12009
12010          /*
12011          globalContext.symbols.Remove(thisSymbol);
12012          FreeSymbol(thisSymbol);
12013          */
12014       }
12015       else if(def.type == propertyWatchClassDef && def.propertyWatch)
12016       {
12017          PropertyWatch propertyWatch = def.propertyWatch;
12018         
12019          thisClass = regClass;
12020          if(propertyWatch.compound)
12021          {
12022             Symbol thisSymbol
12023             {
12024                string = CopyString("this");
12025                type = regClass ? MkClassType(regClass.fullName) : null;
12026             };
12027
12028             propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
12029
12030             curExternal = null;
12031             ProcessStatement(propertyWatch.compound);
12032          }
12033          thisClass = null;
12034       }
12035    }
12036 }
12037
12038 void ComputeDataTypes()
12039 {
12040    External external;
12041    External temp { };
12042    currentClass = null;
12043
12044    containerClass = eSystem_FindClass(GetPrivateModule(), "Container");
12045
12046    temp.symbol = Symbol { id = -1000, idCode = -1000 };
12047
12048    // WHERE SHOULD THIS GO?
12049    // curExternal = ast->first;
12050    ast->Insert(null, temp);
12051
12052    curExternal = temp;
12053
12054    DeclareStruct("ecere::com::Class", false);
12055    DeclareStruct("ecere::com::Instance", false);
12056    DeclareStruct("ecere::com::Property", false);
12057    DeclareStruct("ecere::com::DataMember", false);
12058    DeclareStruct("ecere::com::Method", false);
12059    DeclareStruct("ecere::com::SerialBuffer", false);
12060    DeclareStruct("ecere::com::ClassTemplateArgument", false);
12061
12062    ast->Remove(temp);
12063
12064    for(external = ast->first; external; external = external.next)
12065    {
12066       afterExternal = curExternal = external;
12067       if(external.type == functionExternal)
12068       {
12069          currentClass = external.function._class;
12070          ProcessFunction(external.function);
12071       }
12072       // There shouldn't be any _class member access here anyways...
12073       else if(external.type == declarationExternal)
12074       {
12075          currentClass = null;
12076          ProcessDeclaration(external.declaration);
12077       }
12078       else if(external.type == classExternal)
12079       {
12080          ClassDefinition _class = external._class;
12081          currentClass = external.symbol.registered;
12082          if(_class.definitions)
12083          {
12084             ProcessClass(_class.definitions, _class.symbol);
12085          }
12086          if(inCompiler)
12087          {
12088             // Free class data...
12089             ast->Remove(external);
12090             delete external;
12091          }
12092       }
12093       else if(external.type == nameSpaceExternal)
12094       {
12095          thisNameSpace = external.id.string;
12096       }
12097    }
12098    currentClass = null;
12099    thisNameSpace = null;
12100
12101    delete temp.symbol;
12102    delete temp;
12103 }