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