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