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