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