compiler/libec: Proper __attribute__ support and other fixes to compile for Android
[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 && spec.extDecl && spec.extDecl.type == extDeclString && !strcmp(spec.extDecl.s, "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 && type1._class && strcmp(type1._class.string, "String")) == (type2.kind == classType && type2._class && 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                   // Flex & Bison generate code that triggers this, so we ignore it for a quiet sdk build:
10142                   if(!sourceFile || (strcmp(sourceFile, "src\\lexer.ec") && strcmp(sourceFile, "src/lexer.ec") && strcmp(sourceFile, "src\\grammar.ec") && strcmp(sourceFile, "src/grammar.ec")))
10143                      Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
10144
10145                   // TO CHECK: FORCING HERE TO HELP DEBUGGER
10146                   FreeType(exp.expType);
10147                   exp.destType.refCount++;
10148                   exp.expType = exp.destType;
10149                }
10150             }
10151          }
10152       }
10153       else if(exp.destType && exp.destType.kind == ellipsisType && exp.expType && exp.expType.passAsTemplate)
10154       {
10155          Expression newExp { };
10156          char typeString[1024];
10157          OldList * specs = MkList();
10158          Declarator decl;
10159
10160          typeString[0] = '\0';
10161
10162          *newExp = *exp;
10163
10164          if(exp.expType)  exp.expType.refCount++;
10165          if(exp.expType)  exp.expType.refCount++;
10166          exp.type = castExp;
10167          newExp.destType = exp.expType;
10168
10169          PrintType(exp.expType, typeString, false, false);
10170          decl = SpecDeclFromString(typeString, specs, null);
10171          
10172          exp.cast.typeName = MkTypeName(specs, decl);
10173          exp.cast.exp = newExp;
10174       }
10175    }
10176    else if(unresolved)
10177    {
10178       if(exp.identifier._class && exp.identifier._class.name)
10179          Compiler_Error($"unresolved identifier %s::%s\n", exp.identifier._class.name, exp.identifier.string);
10180       else if(exp.identifier.string && exp.identifier.string[0])
10181          Compiler_Error($"unresolved identifier %s\n", exp.identifier.string);
10182    }
10183    else if(!exp.expType && exp.type != dummyExp)
10184    {
10185       char expString[10240];
10186       expString[0] = '\0';
10187       if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10188       Compiler_Error($"couldn't determine type of %s\n", expString);
10189    }
10190
10191    // Let's try to support any_object & typed_object here:
10192    ApplyAnyObjectLogic(exp);
10193
10194    if(!notByReference && exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
10195       exp.expType._class.registered.type == noHeadClass)
10196    {
10197       exp.byReference = true;
10198    }
10199    /*else if(!notByReference && exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
10200       exp.destType._class.registered.type == noHeadClass)
10201    {
10202       exp.byReference = true;
10203    }*/
10204    yylloc = oldyylloc;
10205 }
10206
10207 static void FindNextDataMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
10208 {
10209    // THIS CODE WILL FIND NEXT MEMBER...
10210    if(*curMember) 
10211    {
10212       *curMember = (*curMember).next;
10213
10214       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
10215       {
10216          *curMember = subMemberStack[--(*subMemberStackPos)];
10217          *curMember = (*curMember).next;
10218       }
10219
10220       // SKIP ALL PROPERTIES HERE...
10221       while((*curMember) && (*curMember).isProperty)
10222          *curMember = (*curMember).next;
10223
10224       if(subMemberStackPos)
10225       {
10226          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10227          {
10228             subMemberStack[(*subMemberStackPos)++] = *curMember;
10229
10230             *curMember = (*curMember).members.first;
10231             while(*curMember && (*curMember).isProperty)
10232                *curMember = (*curMember).next;                     
10233          }
10234       }
10235    }
10236    while(!*curMember)
10237    {
10238       if(!*curMember)
10239       {
10240          if(subMemberStackPos && *subMemberStackPos)
10241          {
10242             *curMember = subMemberStack[--(*subMemberStackPos)];
10243             *curMember = (*curMember).next;
10244          }
10245          else
10246          {
10247             Class lastCurClass = *curClass;
10248
10249             if(*curClass == _class) break;     // REACHED THE END
10250
10251             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass; *curClass = (*curClass).base);
10252             *curMember = (*curClass).membersAndProperties.first;
10253          }
10254
10255          while((*curMember) && (*curMember).isProperty)
10256             *curMember = (*curMember).next;
10257          if(subMemberStackPos)
10258          {
10259             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10260             {
10261                subMemberStack[(*subMemberStackPos)++] = *curMember;
10262
10263                *curMember = (*curMember).members.first;
10264                while(*curMember && (*curMember).isProperty)
10265                   *curMember = (*curMember).next;                     
10266             }
10267          }
10268       }
10269    }
10270 }
10271
10272
10273 static void ProcessInitializer(Initializer init, Type type)
10274 {
10275    switch(init.type)
10276    {
10277       case expInitializer:
10278          if(!init.exp || init.exp.type != instanceExp || !init.exp.instance || init.exp.instance._class || !type || type.kind == classType)
10279          {
10280             // TESTING THIS FOR SHUTTING = 0 WARNING
10281             if(init.exp && !init.exp.destType)
10282             {
10283                FreeType(init.exp.destType);
10284                init.exp.destType = type;
10285                if(type) type.refCount++;
10286             }
10287             if(init.exp)
10288             {
10289                ProcessExpressionType(init.exp);
10290                init.isConstant = init.exp.isConstant;
10291             }
10292             break;
10293          }
10294          else
10295          {
10296             Expression exp = init.exp;
10297             Instantiation inst = exp.instance;
10298             MembersInit members;
10299
10300             init.type = listInitializer;
10301             init.list = MkList();
10302
10303             if(inst.members)
10304             {
10305                for(members = inst.members->first; members; members = members.next)
10306                {
10307                   if(members.type == dataMembersInit)
10308                   {
10309                      MemberInit member;
10310                      for(member = members.dataMembers->first; member; member = member.next)
10311                      {
10312                         ListAdd(init.list, member.initializer);
10313                         member.initializer = null;
10314                      }
10315                   }
10316                   // Discard all MembersInitMethod
10317                }
10318             }
10319             FreeExpression(exp);
10320          }
10321       case listInitializer:
10322       {
10323          Initializer i;
10324          Type initializerType = null;
10325          Class curClass = null;
10326          DataMember curMember = null;
10327          DataMember subMemberStack[256];
10328          int subMemberStackPos = 0;
10329
10330          if(type && type.kind == arrayType)
10331             initializerType = Dereference(type);
10332          else if(type && (type.kind == structType || type.kind == unionType))
10333             initializerType = type.members.first;
10334
10335          for(i = init.list->first; i; i = i.next)
10336          {
10337             if(type && type.kind == classType && type._class && type._class.registered)
10338             {
10339                // 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)
10340                FindNextDataMember(type._class.registered, &curClass, &curMember, subMemberStack, &subMemberStackPos);
10341                // TODO: Generate error on initializing a private data member this way from another module...
10342                if(curMember)
10343                {
10344                   if(!curMember.dataType)
10345                      curMember.dataType = ProcessTypeString(curMember.dataTypeString, false);
10346                   initializerType = curMember.dataType;
10347                }
10348             }
10349             ProcessInitializer(i, initializerType);
10350             if(initializerType && type && (type.kind == structType || type.kind == unionType))
10351                initializerType = initializerType.next;
10352             if(!i.isConstant)
10353                init.isConstant = false;
10354          }
10355
10356          if(type && type.kind == arrayType)
10357             FreeType(initializerType);
10358
10359          if(type && type.kind != arrayType && type.kind != structType && type.kind != unionType && (type.kind != classType || !type._class.registered || type._class.registered.type != structClass))
10360          {
10361             Compiler_Error($"Assigning list initializer to non list\n");
10362          }
10363          break;
10364       }
10365    }
10366 }
10367
10368 static void ProcessSpecifier(Specifier spec, bool declareStruct)
10369 {
10370    switch(spec.type)
10371    {
10372       case baseSpecifier:
10373       {
10374          if(spec.specifier == THISCLASS)
10375          {
10376             if(thisClass)
10377             {
10378                spec.type = nameSpecifier;
10379                spec.name = ReplaceThisClass(thisClass);
10380                spec.symbol = FindClass(spec.name);
10381                ProcessSpecifier(spec, declareStruct);
10382             }
10383          }
10384          break;
10385       }
10386       case nameSpecifier:
10387       {
10388          Symbol symbol = FindType(curContext, spec.name);
10389          if(symbol)
10390             DeclareType(symbol.type, true, true);
10391          else if((symbol = spec.symbol /*FindClass(spec.name)*/) && symbol.registered && symbol.registered.type == structClass && declareStruct)
10392             DeclareStruct(spec.name, false);
10393          break;
10394       }
10395       case enumSpecifier:
10396       {
10397          Enumerator e;
10398          if(spec.list)
10399          {
10400             for(e = spec.list->first; e; e = e.next)
10401             {
10402                if(e.exp)
10403                   ProcessExpressionType(e.exp);
10404             }
10405          }
10406          break;
10407       }
10408       case structSpecifier:
10409       case unionSpecifier:
10410       {
10411          if(spec.definitions)
10412          {
10413             ClassDef def;
10414             Symbol symbol = spec.id ? FindClass(spec.id.string) : null;
10415             //if(symbol)
10416                ProcessClass(spec.definitions, symbol);
10417             /*else
10418             {
10419                for(def = spec.definitions->first; def; def = def.next)
10420                {
10421                   //if(def.type == declarationClassDef && def.decl && def.decl.type == DeclarationStruct)
10422                      ProcessDeclaration(def.decl);
10423                }
10424             }*/
10425          }
10426          break;
10427       }
10428       /*
10429       case classSpecifier:
10430       {
10431          Symbol classSym = FindClass(spec.name);
10432          if(classSym && classSym.registered && classSym.registered.type == structClass)
10433             DeclareStruct(spec.name, false);
10434          break;
10435       }
10436       */
10437    }
10438 }
10439
10440
10441 static void ProcessDeclarator(Declarator decl)
10442 {
10443    switch(decl.type)
10444    {
10445       case identifierDeclarator:
10446          if(decl.identifier.classSym /* TODO: Name Space Fix ups  || decl.identifier.nameSpace*/)
10447          {
10448             FreeSpecifier(decl.identifier._class);
10449             decl.identifier._class = null;
10450          }
10451          break;
10452       case arrayDeclarator:
10453          if(decl.array.exp)
10454             ProcessExpressionType(decl.array.exp);
10455       case structDeclarator:
10456       case bracketsDeclarator:
10457       case functionDeclarator:
10458       case pointerDeclarator:
10459       case extendedDeclarator:
10460       case extendedDeclaratorEnd:
10461          if(decl.declarator)
10462             ProcessDeclarator(decl.declarator);
10463          if(decl.type == functionDeclarator)
10464          {
10465             Identifier id = GetDeclId(decl);
10466             if(id && id._class)
10467             {
10468                TypeName param
10469                {
10470                   qualifiers = MkListOne(id._class);
10471                   declarator = null;
10472                };
10473                if(!decl.function.parameters)
10474                   decl.function.parameters = MkList();               
10475                decl.function.parameters->Insert(null, param);
10476                id._class = null;
10477             }
10478             if(decl.function.parameters)
10479             {
10480                TypeName param;
10481                
10482                for(param = decl.function.parameters->first; param; param = param.next)
10483                {
10484                   if(param.qualifiers && param.qualifiers->first)
10485                   {
10486                      Specifier spec = param.qualifiers->first;
10487                      if(spec && spec.specifier == TYPED_OBJECT)
10488                      {
10489                         Declarator d = param.declarator;
10490                         TypeName newParam
10491                         {
10492                            qualifiers = MkListOne(MkSpecifier(VOID));
10493                            declarator = MkDeclaratorPointer(MkPointer(null,null), d);
10494                         };
10495                         
10496                         FreeList(param.qualifiers, FreeSpecifier);
10497
10498                         param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
10499                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
10500
10501                         decl.function.parameters->Insert(param, newParam);
10502                         param = newParam;
10503                      }
10504                      else if(spec && spec.specifier == ANY_OBJECT)
10505                      {
10506                         Declarator d = param.declarator;
10507                         
10508                         FreeList(param.qualifiers, FreeSpecifier);
10509
10510                         param.qualifiers = MkListOne(MkSpecifier(VOID));
10511                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);                        
10512                      }
10513                      else if(spec.specifier == THISCLASS)
10514                      {
10515                         if(thisClass)
10516                         {
10517                            spec.type = nameSpecifier;
10518                            spec.name = ReplaceThisClass(thisClass);
10519                            spec.symbol = FindClass(spec.name);
10520                            ProcessSpecifier(spec, false);
10521                         }
10522                      }
10523                   }
10524
10525                   if(param.declarator)
10526                      ProcessDeclarator(param.declarator);
10527                }
10528             }
10529          }
10530          break;
10531    }
10532 }
10533
10534 static void ProcessDeclaration(Declaration decl)
10535 {
10536    yylloc = decl.loc;
10537    switch(decl.type)
10538    {
10539       case initDeclaration:
10540       {
10541          bool declareStruct = false;
10542          /*
10543          lineNum = decl.pos.line;
10544          column = decl.pos.col;
10545          */
10546
10547          if(decl.declarators)
10548          {
10549             InitDeclarator d;
10550          
10551             for(d = decl.declarators->first; d; d = d.next)
10552             {
10553                Type type, subType;
10554                ProcessDeclarator(d.declarator);
10555
10556                type = ProcessType(decl.specifiers, d.declarator);
10557
10558                if(d.initializer)
10559                {
10560                   ProcessInitializer(d.initializer, type);
10561
10562                   // Change "ColorRGB a = ColorRGB { 1,2,3 } => ColorRGB a { 1,2,3 }                  
10563                   
10564                   if(decl.declarators->count == 1 && d.initializer.type == expInitializer &&
10565                      d.initializer.exp.type == instanceExp)
10566                   {
10567                      if(type.kind == classType && type._class == 
10568                         d.initializer.exp.expType._class)
10569                      {
10570                         Instantiation inst = d.initializer.exp.instance;
10571                         inst.exp = MkExpIdentifier(CopyIdentifier(GetDeclId(d.declarator)));
10572                         
10573                         d.initializer.exp.instance = null;
10574                         if(decl.specifiers)
10575                            FreeList(decl.specifiers, FreeSpecifier);
10576                         FreeList(decl.declarators, FreeInitDeclarator);
10577
10578                         d = null;
10579
10580                         decl.type = instDeclaration;
10581                         decl.inst = inst;
10582                      }
10583                   }
10584                }
10585                for(subType = type; subType;)
10586                {
10587                   if(subType.kind == classType)
10588                   {
10589                      declareStruct = true;
10590                      break;
10591                   }
10592                   else if(subType.kind == pointerType)
10593                      break;
10594                   else if(subType.kind == arrayType)
10595                      subType = subType.arrayType;
10596                   else
10597                      break;
10598                }
10599
10600                FreeType(type);
10601                if(!d) break;
10602             }
10603          }
10604
10605          if(decl.specifiers)
10606          {
10607             Specifier s;
10608             for(s = decl.specifiers->first; s; s = s.next)
10609             {
10610                ProcessSpecifier(s, declareStruct);
10611             }
10612          }
10613          break;
10614       }
10615       case instDeclaration:
10616       {
10617          ProcessInstantiationType(decl.inst);
10618          break;
10619       }
10620       case structDeclaration:
10621       {
10622          Specifier spec;
10623          Declarator d;
10624          bool declareStruct = false;
10625
10626          if(decl.declarators)
10627          {
10628             for(d = decl.declarators->first; d; d = d.next)
10629             {
10630                Type type = ProcessType(decl.specifiers, d.declarator);
10631                Type subType;
10632                ProcessDeclarator(d);
10633                for(subType = type; subType;)
10634                {
10635                   if(subType.kind == classType)
10636                   {
10637                      declareStruct = true;
10638                      break;
10639                   }
10640                   else if(subType.kind == pointerType)
10641                      break;
10642                   else if(subType.kind == arrayType)
10643                      subType = subType.arrayType;
10644                   else
10645                      break;
10646                }
10647                FreeType(type);
10648             }
10649          }
10650          if(decl.specifiers)
10651          {
10652             for(spec = decl.specifiers->first; spec; spec = spec.next)
10653                ProcessSpecifier(spec, declareStruct);
10654          }
10655          break;
10656       }
10657    }
10658 }
10659
10660 static FunctionDefinition curFunction;
10661
10662 static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
10663 {
10664    char propName[1024], propNameM[1024];
10665    char getName[1024], setName[1024];
10666    OldList * args;
10667
10668    DeclareProperty(prop, setName, getName);
10669
10670    // eInstance_FireWatchers(object, prop);
10671    strcpy(propName, "__ecereProp_");
10672    FullClassNameCat(propName, prop._class.fullName, false);
10673    strcat(propName, "_");
10674    // strcat(propName, prop.name);
10675    FullClassNameCat(propName, prop.name, true);
10676    MangleClassName(propName);
10677
10678    strcpy(propNameM, "__ecerePropM_");
10679    FullClassNameCat(propNameM, prop._class.fullName, false);
10680    strcat(propNameM, "_");
10681    // strcat(propNameM, prop.name);
10682    FullClassNameCat(propNameM, prop.name, true);
10683    MangleClassName(propNameM);
10684
10685    if(prop.isWatchable)
10686    {
10687       args = MkList();
10688       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10689       ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10690       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10691
10692       args = MkList();
10693       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10694       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10695       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10696    }
10697
10698    
10699    {
10700       args = MkList();
10701       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10702       ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10703       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10704
10705       args = MkList();
10706       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10707       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10708       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10709    }
10710    
10711    if(curFunction.propSet && !strcmp(curFunction.propSet.string, prop.name) && 
10712       (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
10713       curFunction.propSet.fireWatchersDone = true;
10714 }
10715
10716 static void ProcessStatement(Statement stmt)
10717 {
10718    yylloc = stmt.loc;
10719    /*
10720    lineNum = stmt.pos.line;
10721    column = stmt.pos.col;
10722    */
10723    switch(stmt.type)
10724    {
10725       case labeledStmt:
10726          ProcessStatement(stmt.labeled.stmt);
10727          break;
10728       case caseStmt:
10729          // This expression should be constant...
10730          if(stmt.caseStmt.exp)
10731          {
10732             FreeType(stmt.caseStmt.exp.destType);
10733             stmt.caseStmt.exp.destType = curSwitchType;
10734             if(curSwitchType) curSwitchType.refCount++;
10735             ProcessExpressionType(stmt.caseStmt.exp);
10736             ComputeExpression(stmt.caseStmt.exp);
10737          }
10738          if(stmt.caseStmt.stmt)
10739             ProcessStatement(stmt.caseStmt.stmt);
10740          break;
10741       case compoundStmt:
10742       {
10743          if(stmt.compound.context)
10744          {
10745             Declaration decl;
10746             Statement s;
10747
10748             Statement prevCompound = curCompound;
10749             Context prevContext = curContext;
10750
10751             if(!stmt.compound.isSwitch)
10752             {
10753                curCompound = stmt;
10754                curContext = stmt.compound.context;
10755             }
10756
10757             if(stmt.compound.declarations)
10758             {
10759                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
10760                   ProcessDeclaration(decl);
10761             }
10762             if(stmt.compound.statements)
10763             {
10764                for(s = stmt.compound.statements->first; s; s = s.next)
10765                   ProcessStatement(s);
10766             }
10767
10768             curContext = prevContext;
10769             curCompound = prevCompound;
10770          }
10771          break;
10772       }
10773       case expressionStmt:
10774       {
10775          Expression exp;
10776          if(stmt.expressions)
10777          {
10778             for(exp = stmt.expressions->first; exp; exp = exp.next)
10779                ProcessExpressionType(exp);
10780          }
10781          break;
10782       }
10783       case ifStmt:
10784       {
10785          Expression exp;
10786
10787          FreeType(((Expression)stmt.ifStmt.exp->last).destType);
10788          ((Expression)stmt.ifStmt.exp->last).destType = MkClassType("bool");
10789          ((Expression)stmt.ifStmt.exp->last).destType.truth = true;
10790          for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
10791          {
10792             ProcessExpressionType(exp);
10793          }
10794          if(stmt.ifStmt.stmt)
10795             ProcessStatement(stmt.ifStmt.stmt);
10796          if(stmt.ifStmt.elseStmt)
10797             ProcessStatement(stmt.ifStmt.elseStmt);
10798          break;
10799       }
10800       case switchStmt:
10801       {
10802          Type oldSwitchType = curSwitchType;
10803          if(stmt.switchStmt.exp)
10804          {
10805             Expression exp;
10806             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
10807             {
10808                if(!exp.next)
10809                {
10810                   /*
10811                   Type destType
10812                   {
10813                      kind = intType;
10814                      refCount = 1;
10815                   };
10816                   e.exp.destType = destType;
10817                   */
10818
10819                   ProcessExpressionType(exp);
10820                }
10821                if(!exp.next)
10822                   curSwitchType = exp.expType;
10823             }
10824          }
10825          ProcessStatement(stmt.switchStmt.stmt);
10826          curSwitchType = oldSwitchType;
10827          break;
10828       }
10829       case whileStmt:
10830       {
10831          if(stmt.whileStmt.exp)
10832          {
10833             Expression exp;
10834
10835             FreeType(((Expression)stmt.whileStmt.exp->last).destType);
10836             ((Expression)stmt.whileStmt.exp->last).destType = MkClassType("bool");
10837             ((Expression)stmt.whileStmt.exp->last).destType.truth = true;
10838             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
10839             {
10840                ProcessExpressionType(exp);
10841             }
10842          }
10843          if(stmt.whileStmt.stmt)
10844             ProcessStatement(stmt.whileStmt.stmt);
10845          break;
10846       }
10847       case doWhileStmt:
10848       {
10849          if(stmt.doWhile.exp)
10850          {
10851             Expression exp;
10852
10853             if(stmt.doWhile.exp->last)
10854             {
10855                FreeType(((Expression)stmt.doWhile.exp->last).destType);
10856                ((Expression)stmt.doWhile.exp->last).destType = MkClassType("bool");
10857                ((Expression)stmt.doWhile.exp->last).destType.truth = true;
10858             }
10859             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
10860             {
10861                ProcessExpressionType(exp);
10862             }
10863          }
10864          if(stmt.doWhile.stmt)
10865             ProcessStatement(stmt.doWhile.stmt);
10866          break;
10867       }
10868       case forStmt:
10869       {
10870          Expression exp;
10871          if(stmt.forStmt.init)
10872             ProcessStatement(stmt.forStmt.init);
10873
10874          if(stmt.forStmt.check && stmt.forStmt.check.expressions)
10875          {
10876             FreeType(((Expression)stmt.forStmt.check.expressions->last).destType);
10877             ((Expression)stmt.forStmt.check.expressions->last).destType = MkClassType("bool");
10878             ((Expression)stmt.forStmt.check.expressions->last).destType.truth = true;
10879          }
10880
10881          if(stmt.forStmt.check)
10882             ProcessStatement(stmt.forStmt.check);
10883          if(stmt.forStmt.increment)
10884          {
10885             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
10886                ProcessExpressionType(exp);
10887          }
10888
10889          if(stmt.forStmt.stmt)
10890             ProcessStatement(stmt.forStmt.stmt);
10891          break;
10892       }
10893       case forEachStmt:
10894       {
10895          Identifier id = stmt.forEachStmt.id;
10896          OldList * exp = stmt.forEachStmt.exp;
10897          OldList * filter = stmt.forEachStmt.filter;
10898          Statement block = stmt.forEachStmt.stmt;
10899          char iteratorType[1024];
10900          Type source;
10901          Expression e;
10902          bool isBuiltin = exp && exp->last && 
10903             (((Expression)exp->last).type == ExpressionType::arrayExp || 
10904               (((Expression)exp->last).type == castExp && ((Expression)exp->last).cast.exp.type == ExpressionType::arrayExp));
10905          Expression arrayExp;
10906          char * typeString = null;
10907          int builtinCount = 0;
10908
10909          for(e = exp ? exp->first : null; e; e = e.next)
10910          {
10911             if(!e.next)
10912             {
10913                FreeType(e.destType);
10914                e.destType = ProcessTypeString("Container", false);
10915             }
10916             if(!isBuiltin || e.next)
10917                ProcessExpressionType(e);
10918          }
10919
10920          source = (exp && exp->last) ? ((Expression)exp->last).expType : null;
10921          if(isBuiltin || (source && source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
10922             eClass_IsDerived(source._class.registered, containerClass)))
10923          {
10924             Class _class = source ? source._class.registered : null;
10925             Symbol symbol;
10926             Expression expIt = null;
10927             bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false, isAVLTree = false;
10928             Class arrayClass = eSystem_FindClass(privateModule, "Array");
10929             Class linkListClass = eSystem_FindClass(privateModule, "LinkList");
10930             Class customAVLTreeClass = eSystem_FindClass(privateModule, "CustomAVLTree");
10931             stmt.type = compoundStmt;
10932             
10933             stmt.compound.context = Context { };
10934             stmt.compound.context.parent = curContext;
10935             curContext = stmt.compound.context;
10936
10937             if(source && eClass_IsDerived(source._class.registered, customAVLTreeClass))
10938             {
10939                Class mapClass = eSystem_FindClass(privateModule, "Map");
10940                Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
10941                isCustomAVLTree = true;
10942                if(eClass_IsDerived(source._class.registered, avlTreeClass))
10943                   isAVLTree = true;
10944                else if(eClass_IsDerived(source._class.registered, mapClass))
10945                   isMap = true;
10946             }
10947             else if(source && eClass_IsDerived(source._class.registered, arrayClass)) isArray = true;
10948             else if(source && eClass_IsDerived(source._class.registered, linkListClass)) 
10949             {
10950                Class listClass = eSystem_FindClass(privateModule, "List");
10951                isLinkList = true;
10952                isList = eClass_IsDerived(source._class.registered, listClass);
10953             }
10954
10955             if(isArray)
10956             {
10957                Declarator decl;
10958                OldList * specs = MkList();
10959                decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
10960                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
10961                stmt.compound.declarations = MkListOne(
10962                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
10963                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
10964                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalArray")), 
10965                      MkInitializerAssignment(MkExpBrackets(exp))))));
10966             }
10967             else if(isBuiltin)
10968             {
10969                Type type = null;
10970                char typeStringBuf[1024];
10971                
10972                // TODO: Merge this code?
10973                arrayExp = (((Expression)exp->last).type == ExpressionType::arrayExp) ? (Expression)exp->last : ((Expression)exp->last).cast.exp;
10974                if(((Expression)exp->last).type == castExp)
10975                {
10976                   TypeName typeName = ((Expression)exp->last).cast.typeName;
10977                   if(typeName)
10978                      arrayExp.destType = ProcessType(typeName.qualifiers, typeName.declarator);
10979                }
10980
10981                if(arrayExp.destType && arrayExp.destType.kind == classType && arrayExp.destType._class && arrayExp.destType._class.registered &&
10982                   arrayExp.destType._class.registered != containerClass && eClass_IsDerived(arrayExp.destType._class.registered, containerClass) &&
10983                   arrayExp.destType._class.registered.templateArgs)
10984                {
10985                   Class templateClass = arrayExp.destType._class.registered;
10986                   typeString = templateClass.templateArgs[2].dataTypeString;
10987                }
10988                else if(arrayExp.list)
10989                {
10990                   // Guess type from expressions in the array
10991                   Expression e;
10992                   for(e = arrayExp.list->first; e; e = e.next)
10993                   {
10994                      ProcessExpressionType(e);
10995                      if(e.expType)
10996                      {
10997                         if(!type) { type = e.expType; type.refCount++; }
10998                         else
10999                         {
11000                            // if(!MatchType(e.expType, type, null, null, null, false, false, false))
11001                            if(!MatchTypeExpression(e, type, null, false))
11002                            {
11003                               FreeType(type);
11004                               type = e.expType;
11005                               e.expType = null;
11006                               
11007                               e = arrayExp.list->first;
11008                               ProcessExpressionType(e);
11009                               if(e.expType)
11010                               {
11011                                  //if(!MatchTypes(e.expType, type, null, null, null, false, false, false, false))
11012                                  if(!MatchTypeExpression(e, type, null, false))
11013                                  {
11014                                     FreeType(e.expType);
11015                                     e.expType = null;
11016                                     FreeType(type);
11017                                     type = null;
11018                                     break;
11019                                  }                           
11020                               }
11021                            }
11022                         }
11023                         if(e.expType)
11024                         {
11025                            FreeType(e.expType);
11026                            e.expType = null;
11027                         }
11028                      }
11029                   }
11030                   if(type)
11031                   {
11032                      typeStringBuf[0] = '\0';
11033                      PrintType(type, typeStringBuf, false, true);
11034                      typeString = typeStringBuf;
11035                      FreeType(type);
11036                   }
11037                }
11038                if(typeString)
11039                {
11040                   OldList * initializers = MkList();
11041                   Declarator decl;
11042                   OldList * specs = MkList();
11043                   if(arrayExp.list)
11044                   {
11045                      Expression e;
11046
11047                      builtinCount = arrayExp.list->count;
11048                      type = ProcessTypeString(typeString, false);
11049                      while(e = arrayExp.list->first)
11050                      {
11051                         arrayExp.list->Remove(e);
11052                         e.destType = type;
11053                         type.refCount++;
11054                         ProcessExpressionType(e);
11055                         ListAdd(initializers, MkInitializerAssignment(e));
11056                      }
11057                      FreeType(type);
11058                      delete arrayExp.list;
11059                   }
11060                   decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
11061                   stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier), 
11062                      MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
11063
11064                   ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorArray(PlugDeclarator(
11065                      /*CopyDeclarator(*/decl/*)*/, MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), null), MkInitializerList(initializers)))));
11066                   
11067                   FreeList(exp, FreeExpression);
11068                }
11069                else
11070                {
11071                   arrayExp.expType = ProcessTypeString("Container", false);
11072                   Compiler_Error($"Couldn't determine type of array elements\n");
11073                }
11074
11075                /*
11076                Declarator decl;
11077                OldList * specs = MkList();
11078
11079                decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
11080                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
11081                stmt.compound.declarations = MkListOne(
11082                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11083                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName("BuiltInContainer")),
11084                   MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), 
11085                      MkInitializerAssignment(MkExpBrackets(exp))))));
11086                */
11087             }
11088             else if(isLinkList && !isList)
11089             {
11090                Declarator decl;
11091                OldList * specs = MkList();
11092                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11093                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11094                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11095                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalLinkList")), 
11096                      MkInitializerAssignment(MkExpBrackets(exp))))));
11097             }
11098             /*else if(isCustomAVLTree)
11099             {
11100                Declarator decl;
11101                OldList * specs = MkList();
11102                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11103                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11104                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11105                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalTree")), 
11106                      MkInitializerAssignment(MkExpBrackets(exp))))));
11107             }*/
11108             else if(_class.templateArgs)
11109             {
11110                if(isMap)
11111                   sprintf(iteratorType, "MapIterator<%s, %s >", _class.templateArgs[5].dataTypeString, _class.templateArgs[6].dataTypeString);
11112                else
11113                   sprintf(iteratorType, "Iterator<%s, %s >", _class.templateArgs[2].dataTypeString, _class.templateArgs[1].dataTypeString);
11114
11115                stmt.compound.declarations = MkListOne(
11116                   MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName(iteratorType)),
11117                   MkExpIdentifier(id), MkListOne(MkMembersInitList(MkListOne(MkMemberInit(isMap ? MkListOne(MkIdentifier("map")) : null, 
11118                   MkInitializerAssignment(MkExpBrackets(exp)))))))));
11119             }
11120             symbol = FindSymbol(id.string, curContext, curContext, false, false);
11121
11122             if(block && block.type == compoundStmt && block.compound.context)
11123             {
11124                block.compound.context.parent = stmt.compound.context;
11125             }
11126             if(filter)
11127             {
11128                block = MkIfStmt(filter, block, null);
11129             }
11130             if(isArray)
11131             {
11132                stmt.compound.statements = MkListOne(MkForStmt(
11133                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
11134                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11135                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11136                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11137                   block));
11138               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11139               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11140               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11141             }
11142             else if(isBuiltin)
11143             {
11144                char count[128];
11145                //OldList * specs = MkList();
11146                // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11147
11148                sprintf(count, "%d", builtinCount);
11149
11150                stmt.compound.statements = MkListOne(MkForStmt(
11151                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
11152                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11153                      MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
11154                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11155                   block));
11156
11157                /*
11158                Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11159                stmt.compound.statements = MkListOne(MkForStmt(
11160                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
11161                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11162                      MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11163                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11164                   block));
11165               */
11166               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11167               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11168               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11169             }
11170             else if(isLinkList && !isList)
11171             {
11172                Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
11173                Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
11174                if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString && 
11175                   !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
11176                {
11177                   stmt.compound.statements = MkListOne(MkForStmt(
11178                      MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11179                      MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11180                      MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11181                      block));
11182                }
11183                else
11184                {
11185                   OldList * specs = MkList();
11186                   Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
11187                   stmt.compound.statements = MkListOne(MkForStmt(
11188                      MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11189                      MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11190                      MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
11191                         MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
11192                            MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
11193                      block));
11194                }
11195                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11196                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11197                ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11198             }
11199             /*else if(isCustomAVLTree)
11200             {
11201                stmt.compound.statements = MkListOne(MkForStmt(
11202                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
11203                      MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
11204                   MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11205                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11206                   block));
11207
11208                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11209                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11210                ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11211             }*/
11212             else
11213             {
11214                stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
11215                   MkIdentifier("Next")), null)), block));
11216             }
11217             ProcessExpressionType(expIt);
11218             if(stmt.compound.declarations->first)
11219                ProcessDeclaration(stmt.compound.declarations->first);
11220
11221             if(symbol) 
11222                symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
11223
11224             ProcessStatement(stmt);
11225             curContext = stmt.compound.context.parent;
11226             break;
11227          }
11228          else
11229          {
11230             Compiler_Error($"Expression is not a container\n");
11231          }
11232          break;
11233       }
11234       case gotoStmt:
11235          break;
11236       case continueStmt:
11237          break;
11238       case breakStmt:
11239          break;
11240       case returnStmt:
11241       {
11242          Expression exp;
11243          if(stmt.expressions)
11244          {
11245             for(exp = stmt.expressions->first; exp; exp = exp.next)
11246             {
11247                if(!exp.next)
11248                {
11249                   if(curFunction && !curFunction.type)
11250                      curFunction.type = ProcessType(
11251                         curFunction.specifiers, curFunction.declarator);
11252                   FreeType(exp.destType);
11253                   exp.destType = (curFunction && curFunction.type && curFunction.type.kind == functionType) ? curFunction.type.returnType : null;
11254                   if(exp.destType) exp.destType.refCount++;
11255                }
11256                ProcessExpressionType(exp);
11257             }
11258          }
11259          break;
11260       }
11261       case badDeclarationStmt:
11262       {
11263          ProcessDeclaration(stmt.decl);
11264          break;
11265       }
11266       case asmStmt:
11267       {
11268          AsmField field;
11269          if(stmt.asmStmt.inputFields)
11270          {
11271             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
11272                if(field.expression)
11273                   ProcessExpressionType(field.expression);
11274          }
11275          if(stmt.asmStmt.outputFields)
11276          {
11277             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
11278                if(field.expression)
11279                   ProcessExpressionType(field.expression);
11280          }
11281          if(stmt.asmStmt.clobberedFields)
11282          {
11283             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
11284             {
11285                if(field.expression)
11286                   ProcessExpressionType(field.expression);
11287             }
11288          }
11289          break;
11290       }
11291       case watchStmt:
11292       {
11293          PropertyWatch propWatch;
11294          OldList * watches = stmt._watch.watches;
11295          Expression object = stmt._watch.object;
11296          Expression watcher = stmt._watch.watcher;
11297          if(watcher)
11298             ProcessExpressionType(watcher);
11299          if(object)
11300             ProcessExpressionType(object);
11301
11302          if(inCompiler)
11303          {
11304             if(watcher || thisClass)
11305             {
11306                External external = curExternal;
11307                Context context = curContext;
11308
11309                stmt.type = expressionStmt;
11310                stmt.expressions = MkList();
11311
11312                curExternal = external.prev;
11313
11314                for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11315                {
11316                   ClassFunction func;
11317                   char watcherName[1024];
11318                   Class watcherClass = watcher ? 
11319                      ((watcher.expType && watcher.expType.kind == classType && watcher.expType._class) ? watcher.expType._class.registered : null) : thisClass;
11320                   External createdExternal;
11321
11322                   // Create a declaration above
11323                   External externalDecl = MkExternalDeclaration(null);
11324                   ast->Insert(curExternal.prev, externalDecl);
11325
11326                   sprintf(watcherName,"__ecerePropertyWatcher_%d", propWatcherID++);
11327                   if(propWatch.deleteWatch)
11328                      strcat(watcherName, "_delete");
11329                   else
11330                   {
11331                      Identifier propID;
11332                      for(propID = propWatch.properties->first; propID; propID = propID.next)
11333                      {
11334                         strcat(watcherName, "_");
11335                         strcat(watcherName, propID.string);
11336                      }
11337                   }
11338
11339                   if(object && object.expType && object.expType.kind == classType && object.expType._class && object.expType._class.registered)
11340                   {
11341                      // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
11342                      func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)),
11343                         //MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null))), null);
11344                         MkListOne(MkTypeName(MkListOne(MkSpecifierName(object.expType._class.string)), MkDeclaratorIdentifier(MkIdentifier("value"))))), null);
11345                      ProcessClassFunctionBody(func, propWatch.compound);
11346                      propWatch.compound = null;
11347
11348                      //afterExternal = afterExternal ? afterExternal : curExternal;
11349
11350                      //createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal.prev);
11351                      createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal, true);
11352                      // TESTING THIS...
11353                      createdExternal.symbol.idCode = external.symbol.idCode;
11354
11355                      curExternal = createdExternal;
11356                      ProcessFunction(createdExternal.function);
11357
11358
11359                      // Create a declaration above
11360                      {
11361                         Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier), 
11362                            MkListOne(MkInitDeclarator(CopyDeclarator(createdExternal.function.declarator), null)));
11363                         externalDecl.declaration = decl;
11364                         if(decl.symbol && !decl.symbol.pointerExternal)
11365                            decl.symbol.pointerExternal = externalDecl;
11366                      }
11367
11368                      if(propWatch.deleteWatch)
11369                      {
11370                         OldList * args = MkList();
11371                         ListAdd(args, CopyExpression(object));
11372                         ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11373                         ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11374                         ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_WatchDestruction")), args));
11375                      }
11376                      else
11377                      {
11378                         Class _class = object.expType._class.registered;
11379                         Identifier propID;
11380
11381                         for(propID = propWatch.properties->first; propID; propID = propID.next)
11382                         {
11383                            char propName[1024];
11384                            Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11385                            if(prop)
11386                            {
11387                               char getName[1024], setName[1024];
11388                               OldList * args = MkList();
11389
11390                               DeclareProperty(prop, setName, getName);                              
11391                               
11392                               // eInstance_Watch(stmt.watch.object, prop, stmt.watch.watcher, callback);
11393                               strcpy(propName, "__ecereProp_");
11394                               FullClassNameCat(propName, prop._class.fullName, false);
11395                               strcat(propName, "_");
11396                               // strcat(propName, prop.name);
11397                               FullClassNameCat(propName, prop.name, true);
11398
11399                               ListAdd(args, CopyExpression(object));
11400                               ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11401                               ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11402                               ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11403
11404                               ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), args));
11405                            }
11406                            else
11407                               Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
11408                         }
11409                      }
11410                   }
11411                   else
11412                      Compiler_Error($"Invalid watched object\n");
11413                }
11414
11415                curExternal = external;
11416                curContext = context;
11417
11418                if(watcher)
11419                   FreeExpression(watcher);
11420                if(object)
11421                   FreeExpression(object);
11422                FreeList(watches, FreePropertyWatch);
11423             }
11424             else
11425                Compiler_Error($"No observer specified and not inside a _class\n");
11426          }
11427          else
11428          {
11429             for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11430             {
11431                ProcessStatement(propWatch.compound);
11432             }
11433
11434          }
11435          break;
11436       }
11437       case fireWatchersStmt:
11438       {
11439          OldList * watches = stmt._watch.watches;
11440          Expression object = stmt._watch.object;
11441          Class _class;
11442          // DEBUGGER BUG: Why doesn't watches evaluate to null??
11443          // printf("%X\n", watches);
11444          // printf("%X\n", stmt._watch.watches);
11445          if(object)
11446             ProcessExpressionType(object);
11447
11448          if(inCompiler)
11449          {
11450             _class = object ? 
11451                   ((object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null) : thisClass;
11452
11453             if(_class)
11454             {
11455                Identifier propID;
11456
11457                stmt.type = expressionStmt;
11458                stmt.expressions = MkList();
11459
11460                // Check if we're inside a property set
11461                if(!watches && curFunction.propSet && (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
11462                {
11463                   watches = MkListOne(MkIdentifier(curFunction.propSet.string));
11464                }
11465                else if(!watches)
11466                {
11467                   //Compiler_Error($"No property specified and not inside a property set\n");
11468                }
11469                if(watches)
11470                {
11471                   for(propID = watches->first; propID; propID = propID.next)
11472                   {
11473                      Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11474                      if(prop)
11475                      {
11476                         CreateFireWatcher(prop, object, stmt);
11477                      }
11478                      else
11479                         Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
11480                   }
11481                }
11482                else
11483                {
11484                   // Fire all properties!
11485                   Property prop;
11486                   Class base;
11487                   for(base = _class; base; base = base.base)
11488                   {
11489                      for(prop = base.membersAndProperties.first; prop; prop = prop.next)
11490                      {
11491                         if(prop.isProperty && prop.isWatchable)
11492                         {
11493                            CreateFireWatcher(prop, object, stmt);
11494                         }
11495                      }
11496                   }
11497                }
11498
11499                if(object)
11500                   FreeExpression(object);
11501                FreeList(watches, FreeIdentifier);
11502             }
11503             else
11504                Compiler_Error($"Invalid object specified and not inside a class\n");
11505          }
11506          break;
11507       }
11508       case stopWatchingStmt:
11509       {
11510          OldList * watches = stmt._watch.watches;
11511          Expression object = stmt._watch.object;
11512          Expression watcher = stmt._watch.watcher;
11513          Class _class;
11514          if(object)
11515             ProcessExpressionType(object);
11516          if(watcher)
11517             ProcessExpressionType(watcher);
11518          if(inCompiler)
11519          {
11520             _class = (object && object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null;
11521
11522             if(watcher || thisClass)
11523             {
11524                if(_class)
11525                {
11526                   Identifier propID;
11527
11528                   stmt.type = expressionStmt;
11529                   stmt.expressions = MkList();
11530
11531                   if(!watches)
11532                   {
11533                      OldList * args;
11534                      // eInstance_StopWatching(object, null, watcher); 
11535                      args = MkList();
11536                      ListAdd(args, CopyExpression(object));
11537                      ListAdd(args, MkExpConstant("0"));
11538                      ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11539                      ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11540                   }
11541                   else
11542                   {
11543                      for(propID = watches->first; propID; propID = propID.next)
11544                      {
11545                         char propName[1024];
11546                         Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11547                         if(prop)
11548                         {
11549                            char getName[1024], setName[1024];
11550                            OldList * args = MkList();
11551
11552                            DeclareProperty(prop, setName, getName);
11553          
11554                            // eInstance_StopWatching(object, prop, watcher); 
11555                            strcpy(propName, "__ecereProp_");
11556                            FullClassNameCat(propName, prop._class.fullName, false);
11557                            strcat(propName, "_");
11558                            // strcat(propName, prop.name);
11559                            FullClassNameCat(propName, prop.name, true);
11560                            MangleClassName(propName);
11561
11562                            ListAdd(args, CopyExpression(object));
11563                            ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11564                            ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11565                            ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11566                         }
11567                         else
11568                            Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
11569                      }
11570                   }
11571
11572                   if(object)
11573                      FreeExpression(object);
11574                   if(watcher)
11575                      FreeExpression(watcher);
11576                   FreeList(watches, FreeIdentifier);
11577                }
11578                else
11579                   Compiler_Error($"Invalid object specified and not inside a class\n");
11580             }
11581             else
11582                Compiler_Error($"No observer specified and not inside a class\n");
11583          }
11584          break;
11585       }
11586    }
11587 }
11588
11589 static void ProcessFunction(FunctionDefinition function)
11590 {
11591    Identifier id = GetDeclId(function.declarator);
11592    Symbol symbol = function.declarator ? function.declarator.symbol : null;
11593    Type type = symbol ? symbol.type : null;
11594    Class oldThisClass = thisClass;
11595    Context oldTopContext = topContext;
11596
11597    yylloc = function.loc;
11598    // Process thisClass
11599    
11600    if(type && type.thisClass)
11601    {
11602       Symbol classSym = type.thisClass;
11603       Class _class = type.thisClass.registered;
11604       char className[1024];
11605       char structName[1024];
11606       Declarator funcDecl;
11607       Symbol thisSymbol;
11608
11609       bool typedObject = false;
11610
11611       if(_class && !_class.base)
11612       {
11613          _class = currentClass;
11614          if(_class && !_class.symbol)
11615             _class.symbol = FindClass(_class.fullName);
11616          classSym = _class ? _class.symbol : null;
11617          typedObject = true;
11618       }
11619
11620       thisClass = _class;
11621
11622       if(inCompiler && _class)
11623       {
11624          if(type.kind == functionType)
11625          {
11626             if(symbol.type.params.count == 1 && ((Type)symbol.type.params.first).kind == voidType)
11627             {
11628                //TypeName param = symbol.type.params.first;
11629                Type param = symbol.type.params.first;
11630                symbol.type.params.Remove(param);
11631                //FreeTypeName(param);
11632                FreeType(param);
11633             }
11634             if(type.classObjectType != classPointer)
11635             {
11636                symbol.type.params.Insert(null, MkClassType(_class.fullName));
11637                symbol.type.staticMethod = true;
11638                symbol.type.thisClass = null;
11639
11640                // HIGH DANGER: VERIFYING THIS...
11641                symbol.type.extraParam = false;
11642             }
11643          }
11644
11645          strcpy(className, "__ecereClass_");
11646          FullClassNameCat(className, _class.fullName, true);
11647
11648          MangleClassName(className);
11649
11650          structName[0] = 0;
11651          FullClassNameCat(structName, _class.fullName, false);
11652
11653          // [class] this
11654          
11655
11656          funcDecl = GetFuncDecl(function.declarator);
11657          if(funcDecl)
11658          {
11659             if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11660             {
11661                TypeName param = funcDecl.function.parameters->first;
11662                if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11663                {
11664                   funcDecl.function.parameters->Remove(param);
11665                   FreeTypeName(param);
11666                }
11667             }
11668
11669             // DANGER: Watch for this... Check if it's a Conversion?
11670             // if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11671             
11672             // WAS TRYING THIS FOR CONVERSION PROPERTIES ON NOHEAD CLASSES: if((_class.type == structClass) || function != (FunctionDefinition)symbol.externalSet)
11673             if(!function.propertyNoThis)
11674             {
11675                TypeName thisParam;
11676                
11677                if(type.classObjectType != classPointer)
11678                {
11679                   thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11680                   if(!funcDecl.function.parameters)
11681                      funcDecl.function.parameters = MkList();
11682                   funcDecl.function.parameters->Insert(null, thisParam);
11683                }
11684
11685                if(typedObject)
11686                {
11687                   if(type.classObjectType != classPointer)
11688                   {
11689                      if(type.byReference || _class.type == unitClass || _class.type == systemClass || _class.type == enumClass || _class.type == bitClass)
11690                         thisParam.declarator = MkDeclaratorPointer(MkPointer(null,null), thisParam.declarator);
11691                   }
11692
11693                   thisParam = TypeName
11694                   {
11695                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
11696                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
11697                   };
11698                   funcDecl.function.parameters->Insert(null, thisParam);
11699                }
11700             }
11701          }
11702
11703          if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11704          {
11705             InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11706             funcDecl = GetFuncDecl(initDecl.declarator);
11707             if(funcDecl)
11708             {
11709                if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11710                {
11711                   TypeName param = funcDecl.function.parameters->first;
11712                   if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11713                   {
11714                      funcDecl.function.parameters->Remove(param);
11715                      FreeTypeName(param);
11716                   }
11717                }
11718
11719                if(type.classObjectType != classPointer)
11720                {
11721                   // DANGER: Watch for this... Check if it's a Conversion?
11722                   if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11723                   {
11724                      TypeName thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11725
11726                      if(!funcDecl.function.parameters)
11727                         funcDecl.function.parameters = MkList();
11728                      funcDecl.function.parameters->Insert(null, thisParam);
11729                   }
11730                }
11731             }         
11732          }
11733       }
11734       
11735       // Add this to the context
11736       if(function.body)
11737       {
11738          if(type.classObjectType != classPointer)
11739          {
11740             thisSymbol = Symbol
11741             {
11742                string = CopyString("this");
11743                type = classSym ? MkClassType(classSym.string) : null; //_class.fullName);
11744             };
11745             function.body.compound.context.symbols.Add((BTNode)thisSymbol);
11746
11747             if(typedObject && thisSymbol.type)
11748             {
11749                thisSymbol.type.classObjectType = ClassObjectType::typedObject;
11750                thisSymbol.type.byReference = type.byReference;
11751                /*
11752                thisSymbol = Symbol { string = CopyString("class") };
11753                function.body.compound.context.symbols.Add(thisSymbol);
11754                */
11755             }
11756          }
11757       }
11758
11759       // Pointer to class data
11760       
11761       if(inCompiler && _class && (_class.type == normalClass /*|| _class.type == noHeadClass*/) && type.classObjectType != classPointer)
11762       {
11763          DataMember member = null;
11764          {
11765             Class base;
11766             for(base = _class; base && base.type != systemClass; base = base.next)
11767             {
11768                for(member = base.membersAndProperties.first; member; member = member.next)
11769                   if(!member.isProperty)
11770                      break;
11771                if(member)
11772                   break;
11773             }
11774          }
11775          for(member = _class.membersAndProperties.first; member; member = member.next)
11776             if(!member.isProperty)
11777                break;
11778          if(member)
11779          {
11780             char pointerName[1024];
11781    
11782             Declaration decl;
11783             Initializer initializer;
11784             Expression exp, bytePtr;
11785    
11786             strcpy(pointerName, "__ecerePointer_");
11787             FullClassNameCat(pointerName, _class.fullName, false);
11788             {
11789                char className[1024];
11790                strcpy(className, "__ecereClass_");
11791                FullClassNameCat(className, classSym.string, true);
11792                MangleClassName(className);
11793
11794                // Testing This
11795                DeclareClass(classSym, className);
11796             }
11797
11798             // ((byte *) this)
11799             bytePtr = QBrackets(MkExpCast(QMkType("char", QMkPtrDecl(null)), QMkExpId("this")));
11800
11801             if(_class.fixed)
11802             {
11803                char string[256];
11804                sprintf(string, "%d", _class.offset);
11805                exp = QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string)));
11806             }
11807             else
11808             {
11809                // ([bytePtr] + [className]->offset)
11810                exp = QBrackets(MkExpOp(bytePtr, '+',
11811                   MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
11812             }
11813
11814             // (this ? [exp] : 0)
11815             exp = QBrackets(QMkExpCond(QMkExpId("this"), exp, MkExpConstant("0")));
11816             exp.expType = Type
11817             {
11818                refCount = 1;
11819                kind = pointerType;
11820                type = Type { refCount = 1, kind = voidType };
11821             };
11822    
11823             if(function.body)
11824             {
11825                yylloc = function.body.loc;
11826                // ([structName] *) [exp]
11827                // initializer = MkInitializerAssignment(MkExpCast(QMkType(structName, QMkPtrDecl(null)), exp));
11828                initializer = MkInitializerAssignment(
11829                   MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), exp));
11830
11831                // [structName] * [pointerName] = [initializer];
11832                // decl = QMkDeclaration(structName, MkInitDeclarator(QMkPtrDecl(pointerName), initializer));
11833
11834                {
11835                   Context prevContext = curContext;
11836                   curContext = function.body.compound.context;
11837
11838                   decl = MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
11839                      MkListOne(MkInitDeclarator(QMkPtrDecl(pointerName), initializer)));
11840
11841                   curContext = prevContext;
11842                }
11843
11844                // WHY?
11845                decl.symbol = null;
11846
11847                if(!function.body.compound.declarations)
11848                   function.body.compound.declarations = MkList();
11849                function.body.compound.declarations->Insert(null, decl);
11850             }
11851          }
11852       }
11853       
11854
11855       // Loop through the function and replace undeclared identifiers
11856       // which are a member of the class (methods, properties or data)
11857       // by "this.[member]"
11858    }
11859    else
11860       thisClass = null;
11861
11862    if(id)
11863    {
11864       FreeSpecifier(id._class);
11865       id._class = null;
11866
11867       if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11868       {
11869          InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11870          id = GetDeclId(initDecl.declarator);
11871
11872          FreeSpecifier(id._class);
11873          id._class = null;
11874       }
11875    }
11876    if(function.body)
11877       topContext = function.body.compound.context;
11878    {
11879       FunctionDefinition oldFunction = curFunction;
11880       curFunction = function;
11881       if(function.body)
11882          ProcessStatement(function.body);
11883
11884       // If this is a property set and no firewatchers has been done yet, add one here
11885       if(inCompiler && function.propSet && !function.propSet.fireWatchersDone)
11886       {
11887          Statement prevCompound = curCompound;
11888          Context prevContext = curContext;
11889
11890          Statement fireWatchers = MkFireWatchersStmt(null, null);
11891          if(!function.body.compound.statements) function.body.compound.statements = MkList();
11892          ListAdd(function.body.compound.statements, fireWatchers);
11893
11894          curCompound = function.body;
11895          curContext = function.body.compound.context;
11896
11897          ProcessStatement(fireWatchers);
11898
11899          curContext = prevContext;
11900          curCompound = prevCompound;
11901
11902       }
11903
11904       curFunction = oldFunction;
11905    }
11906
11907    if(function.declarator)
11908    {
11909       ProcessDeclarator(function.declarator);
11910    }
11911
11912    topContext = oldTopContext;
11913    thisClass = oldThisClass;
11914 }
11915
11916 /////////// INSTANTIATIONS / DATA TYPES PASS /////////////////////////////////////////////
11917 static void ProcessClass(OldList definitions, Symbol symbol)
11918 {
11919    ClassDef def;
11920    External external = curExternal;
11921    Class regClass = symbol ? symbol.registered : null;
11922
11923    // Process all functions
11924    for(def = definitions.first; def; def = def.next)
11925    {
11926       if(def.type == functionClassDef)
11927       {
11928          if(def.function.declarator)
11929             curExternal = def.function.declarator.symbol.pointerExternal;
11930          else
11931             curExternal = external;
11932
11933          ProcessFunction((FunctionDefinition)def.function);
11934       }
11935       else if(def.type == declarationClassDef)
11936       {
11937          if(def.decl.type == instDeclaration)
11938          {
11939             thisClass = regClass;
11940             ProcessInstantiationType(def.decl.inst);
11941             thisClass = null;
11942          }
11943          // Testing this
11944          else
11945          {
11946             Class backThisClass = thisClass;
11947             if(regClass) thisClass = regClass;
11948             ProcessDeclaration(def.decl);
11949             thisClass = backThisClass;
11950          }
11951       }
11952       else if(def.type == defaultPropertiesClassDef && def.defProperties)
11953       {
11954          MemberInit defProperty;
11955
11956          // Add this to the context
11957          Symbol thisSymbol = Symbol
11958          {
11959             string = CopyString("this");
11960             type = regClass ? MkClassType(regClass.fullName) : null;
11961          };
11962          globalContext.symbols.Add((BTNode)thisSymbol);
11963          
11964          for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
11965          {
11966             thisClass = regClass;
11967             ProcessMemberInitData(defProperty, regClass, null, null, null, null);
11968             thisClass = null;
11969          }
11970
11971          globalContext.symbols.Remove((BTNode)thisSymbol);
11972          FreeSymbol(thisSymbol);
11973       }
11974       else if(def.type == propertyClassDef && def.propertyDef)
11975       {
11976          PropertyDef prop = def.propertyDef;
11977
11978          // Add this to the context
11979          /*
11980          Symbol thisSymbol = Symbol { string = CopyString("this"), type = MkClassType(regClass.fullName) };
11981          globalContext.symbols.Add(thisSymbol);
11982          */
11983          
11984          thisClass = regClass;
11985          if(prop.setStmt)
11986          {
11987             if(regClass)
11988             {
11989                Symbol thisSymbol
11990                {
11991                   string = CopyString("this");
11992                   type = MkClassType(regClass.fullName);
11993                };
11994                prop.setStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11995             }
11996
11997             curExternal = prop.symbol ? prop.symbol.externalSet : null;
11998             ProcessStatement(prop.setStmt);
11999          }
12000          if(prop.getStmt)
12001          {
12002             if(regClass)
12003             {
12004                Symbol thisSymbol
12005                {
12006                   string = CopyString("this");
12007                   type = MkClassType(regClass.fullName);
12008                };
12009                prop.getStmt.compound.context.symbols.Add((BTNode)thisSymbol);
12010             }
12011
12012             curExternal = prop.symbol ? prop.symbol.externalGet : null;
12013             ProcessStatement(prop.getStmt);
12014          }
12015          if(prop.issetStmt)
12016          {
12017             if(regClass)
12018             {
12019                Symbol thisSymbol
12020                {
12021                   string = CopyString("this");
12022                   type = MkClassType(regClass.fullName);
12023                };
12024                prop.issetStmt.compound.context.symbols.Add((BTNode)thisSymbol);
12025             }
12026
12027             curExternal = prop.symbol ? prop.symbol.externalIsSet : null;
12028             ProcessStatement(prop.issetStmt);
12029          }
12030
12031          thisClass = null;
12032
12033          /*
12034          globalContext.symbols.Remove(thisSymbol);
12035          FreeSymbol(thisSymbol);
12036          */
12037       }
12038       else if(def.type == propertyWatchClassDef && def.propertyWatch)
12039       {
12040          PropertyWatch propertyWatch = def.propertyWatch;
12041         
12042          thisClass = regClass;
12043          if(propertyWatch.compound)
12044          {
12045             Symbol thisSymbol
12046             {
12047                string = CopyString("this");
12048                type = regClass ? MkClassType(regClass.fullName) : null;
12049             };
12050
12051             propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
12052
12053             curExternal = null;
12054             ProcessStatement(propertyWatch.compound);
12055          }
12056          thisClass = null;
12057       }
12058    }
12059 }
12060
12061 void ComputeDataTypes()
12062 {
12063    External external;
12064    External temp { };
12065    currentClass = null;
12066
12067    containerClass = eSystem_FindClass(GetPrivateModule(), "Container");
12068
12069    temp.symbol = Symbol { id = -1000, idCode = -1000 };
12070
12071    // WHERE SHOULD THIS GO?
12072    // curExternal = ast->first;
12073    ast->Insert(null, temp);
12074
12075    curExternal = temp;
12076
12077    DeclareStruct("ecere::com::Class", false);
12078    DeclareStruct("ecere::com::Instance", false);
12079    DeclareStruct("ecere::com::Property", false);
12080    DeclareStruct("ecere::com::DataMember", false);
12081    DeclareStruct("ecere::com::Method", false);
12082    DeclareStruct("ecere::com::SerialBuffer", false);
12083    DeclareStruct("ecere::com::ClassTemplateArgument", false);
12084
12085    ast->Remove(temp);
12086
12087    for(external = ast->first; external; external = external.next)
12088    {
12089       afterExternal = curExternal = external;
12090       if(external.type == functionExternal)
12091       {
12092          currentClass = external.function._class;
12093          ProcessFunction(external.function);
12094       }
12095       // There shouldn't be any _class member access here anyways...
12096       else if(external.type == declarationExternal)
12097       {
12098          currentClass = null;
12099          ProcessDeclaration(external.declaration);
12100       }
12101       else if(external.type == classExternal)
12102       {
12103          ClassDefinition _class = external._class;
12104          currentClass = external.symbol.registered;
12105          if(_class.definitions)
12106          {
12107             ProcessClass(_class.definitions, _class.symbol);
12108          }
12109          if(inCompiler)
12110          {
12111             // Free class data...
12112             ast->Remove(external);
12113             delete external;
12114          }
12115       }
12116       else if(external.type == nameSpaceExternal)
12117       {
12118          thisNameSpace = external.id.string;
12119       }
12120    }
12121    currentClass = null;
12122    thisNameSpace = null;
12123
12124    delete temp.symbol;
12125    delete temp;
12126 }