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