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