compiler/libec: Fixed a uninitialized variable Valgrind complaint
[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 = null;
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 // *****
6527 // TODO: Add a max buffer size to avoid overflows. This function is used with static size char arrays.
6528 // *****
6529 void PrintType(Type type, char * string, bool printName, bool fullName)
6530 {
6531    Type funcType;
6532    for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6533    if(funcType && funcType.kind == functionType && type != funcType)
6534    {
6535       char typeString[1024];
6536       Type param;
6537
6538       PrintType(funcType.returnType, string, false, fullName);
6539       strcat(string, "(");
6540       _PrintType(type, string, printName, false, fullName);
6541       strcat(string, ")");
6542       /*
6543       if(type.name)
6544          strcat(string, type.name);
6545       else
6546       {
6547          printf("");
6548       }
6549       */
6550       strcat(string, "(");
6551       for(param = funcType.params.first; param; param = param.next)
6552       {
6553          PrintType(param, string, true, fullName);
6554          if(param.next) strcat(string, ", ");
6555       }
6556       strcat(string, ")");
6557    }
6558    else
6559       _PrintType(type, string, printName, true, fullName);
6560    if(type.bitFieldCount)
6561    {
6562       char count[100];
6563       sprintf(count, ":%d", type.bitFieldCount);
6564       strcat(string, count);
6565    }
6566 }
6567
6568 static Type FindMember(Type type, char * string)
6569 {
6570    Type memberType;
6571    for(memberType = type.members.first; memberType; memberType = memberType.next)
6572    {
6573       if(!memberType.name)
6574       {
6575          Type subType = FindMember(memberType, string);
6576          if(subType)
6577             return subType;
6578       }
6579       else if(!strcmp(memberType.name, string))
6580          return memberType;
6581    }
6582    return null;
6583 }
6584
6585 Type FindMemberAndOffset(Type type, char * string, uint * offset)
6586 {
6587    Type memberType;
6588    for(memberType = type.members.first; memberType; memberType = memberType.next)
6589    {
6590       if(!memberType.name)
6591       {
6592          Type subType = FindMember(memberType, string);
6593          if(subType)
6594          {
6595             *offset += memberType.offset;
6596             return subType;
6597          }
6598       }
6599       else if(!strcmp(memberType.name, string))
6600       {
6601          *offset += memberType.offset;
6602          return memberType;
6603       }
6604    }
6605    return null;
6606 }
6607
6608 Expression ParseExpressionString(char * expression)
6609 {
6610    fileInput = TempFile { };
6611    fileInput.Write(expression, 1, strlen(expression));
6612    fileInput.Seek(0, start);
6613
6614    echoOn = false;
6615    parsedExpression = null;
6616    resetScanner();
6617    expression_yyparse();
6618    delete fileInput;
6619
6620    return parsedExpression;
6621 }
6622
6623 static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassCheck)
6624 {
6625    Identifier id = exp.identifier;
6626    Method method = null;
6627    Property prop = null;
6628    DataMember member = null;
6629    ClassProperty classProp = null;
6630
6631    if(_class && _class.type == enumClass)
6632    {
6633       NamedLink value = null;
6634       Class enumClass = eSystem_FindClass(privateModule, "enum");
6635       if(enumClass)
6636       {
6637          Class baseClass;
6638          for(baseClass = _class; baseClass && baseClass.type == ClassType::enumClass; baseClass = baseClass.base)
6639          {
6640             EnumClassData e = ACCESS_CLASSDATA(baseClass, enumClass);
6641             for(value = e.values.first; value; value = value.next)
6642             {
6643                if(!strcmp(value.name, id.string))
6644                   break;
6645             }
6646             if(value)
6647             {
6648                char constant[256];
6649
6650                FreeExpContents(exp);
6651
6652                exp.type = constantExp;
6653                exp.isConstant = true;
6654                if(!strcmp(baseClass.dataTypeString, "int"))
6655                   sprintf(constant, "%d",value.data);
6656                else
6657                   sprintf(constant, "0x%X",value.data);
6658                exp.constant = CopyString(constant);
6659                //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
6660                exp.expType = MkClassType(baseClass.fullName);
6661                break;
6662             }
6663          }
6664       }
6665       if(value)
6666          return true;
6667    }
6668    if((method = eClass_FindMethod(_class, id.string, privateModule)))
6669    {
6670       ProcessMethodType(method);
6671       exp.expType = Type
6672       {
6673          refCount = 1;
6674          kind = methodType;
6675          method = method;
6676          // Crash here?
6677          // TOCHECK: Put it back to what it was...
6678          // methodClass = _class;
6679          methodClass = (skipIDClassCheck || (id && id._class)) ? _class : null;
6680       };
6681       //id._class = null;
6682       return true;
6683    }
6684    else if((prop = eClass_FindProperty(_class, id.string, privateModule)))
6685    {
6686       if(!prop.dataType)
6687          ProcessPropertyType(prop);
6688       exp.expType = prop.dataType;
6689       if(prop.dataType) prop.dataType.refCount++;
6690       return true;
6691    }
6692    else if((member = eClass_FindDataMember(_class, id.string, privateModule, null, null)))
6693    {
6694       if(!member.dataType)
6695          member.dataType = ProcessTypeString(member.dataTypeString, false);
6696       exp.expType = member.dataType;
6697       if(member.dataType) member.dataType.refCount++;
6698       return true;
6699    }
6700    else if((classProp = eClass_FindClassProperty(_class, id.string)))
6701    {
6702       if(!classProp.dataType)
6703          classProp.dataType = ProcessTypeString(classProp.dataTypeString, false);
6704
6705       if(classProp.constant)
6706       {
6707          FreeExpContents(exp);
6708
6709          exp.isConstant = true;
6710          if(classProp.dataType.kind == pointerType && classProp.dataType.type.kind == charType)
6711          {
6712             //char constant[256];
6713             exp.type = stringExp;
6714             exp.constant = QMkString((char *)classProp.Get(_class));
6715          }
6716          else
6717          {
6718             char constant[256];
6719             exp.type = constantExp;
6720             sprintf(constant, "%d",classProp.Get(_class));
6721             exp.constant = CopyString(constant);
6722          }
6723       }
6724       else
6725       {
6726          // TO IMPLEMENT...
6727       }
6728
6729       exp.expType = classProp.dataType;
6730       if(classProp.dataType) classProp.dataType.refCount++;
6731       return true;
6732    }
6733    return false;
6734 }
6735
6736 static GlobalData ScanGlobalData(NameSpace nameSpace, char * name)
6737 {
6738    BinaryTree * tree = &nameSpace.functions;
6739    GlobalData data = (GlobalData)tree->FindString(name);
6740    NameSpace * child;
6741    if(!data)
6742    {
6743       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
6744       {
6745          data = ScanGlobalData(child, name);
6746          if(data)
6747             break;
6748       }
6749    }
6750    return data;
6751 }
6752
6753 static GlobalData FindGlobalData(char * name)
6754 {
6755    int start = 0, c;
6756    NameSpace * nameSpace;
6757    nameSpace = globalData;
6758    for(c = 0; name[c]; c++)
6759    {
6760       if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
6761       {
6762          NameSpace * newSpace;
6763          char * spaceName = new char[c - start + 1];
6764          strncpy(spaceName, name + start, c - start);
6765          spaceName[c-start] = '\0';
6766          newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
6767          delete spaceName;
6768          if(!newSpace)
6769             return null;
6770          nameSpace = newSpace;
6771          if(name[c] == ':') c++;
6772          start = c+1;
6773       }
6774    }
6775    if(c - start)
6776    {
6777       return ScanGlobalData(nameSpace, name + start);
6778    }
6779    return null;
6780 }
6781
6782 static int definedExpStackPos;
6783 static void * definedExpStack[512];
6784
6785 // This function makes checkedExp equivalent to newExp, ending up freeing newExp
6786 void ReplaceExpContents(Expression checkedExp, Expression newExp)
6787 {
6788    Expression prev = checkedExp.prev, next = checkedExp.next;
6789
6790    FreeExpContents(checkedExp);
6791    FreeType(checkedExp.expType);
6792    FreeType(checkedExp.destType);
6793
6794    *checkedExp = *newExp;
6795
6796    delete newExp;
6797
6798    checkedExp.prev = prev;
6799    checkedExp.next = next;
6800 }
6801
6802 void ApplyAnyObjectLogic(Expression e)
6803 {
6804    Type destType = /*(e.destType && e.destType.kind == ellipsisType) ? ellipsisDestType : */e.destType;
6805    if(destType && (/*destType.classObjectType == ClassObjectType::typedObject || */destType.classObjectType == anyObject))
6806    {
6807       //if(e.destType && e.destType.kind == ellipsisType) usedEllipsis = true;
6808       //ellipsisDestType = destType;
6809       if(e && e.expType)
6810       {
6811          Type type = e.expType;
6812          Class _class = null;
6813          //Type destType = e.destType;
6814
6815          if(type.kind == classType && type._class && type._class.registered)
6816          {
6817             _class = type._class.registered;
6818          }
6819          else if(type.kind == subClassType)
6820          {
6821             _class = FindClass("ecere::com::Class").registered;
6822          }
6823          else
6824          {
6825             char string[1024] = "";
6826             Symbol classSym;
6827
6828             PrintType(type, string, false, true);
6829             classSym = FindClass(string);
6830             if(classSym) _class = classSym.registered;
6831          }
6832
6833          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...
6834             (!e.expType.classObjectType && (((type.kind != pointerType && type.kind != subClassType && (type.kind != classType || !type._class || !type._class.registered || type._class.registered.type == structClass))) ||
6835             destType.byReference)))
6836          {
6837             if(!_class || strcmp(_class.fullName, "char *"))     // TESTING THIS WITH NEW String class...
6838             {
6839                Expression checkedExp = e, newExp;
6840
6841                while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
6842                {
6843                   if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
6844                   {
6845                      if(checkedExp.type == extensionCompoundExp)
6846                      {
6847                         checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
6848                      }
6849                      else
6850                         checkedExp = checkedExp.list->last;
6851                   }
6852                   else if(checkedExp.type == castExp)
6853                      checkedExp = checkedExp.cast.exp;
6854                }
6855
6856                if(checkedExp && checkedExp.type == opExp && checkedExp.op.op == '*' && !checkedExp.op.exp1)
6857                {
6858                   newExp = checkedExp.op.exp2;
6859                   checkedExp.op.exp2 = null;
6860                   FreeExpContents(checkedExp);
6861                   
6862                   if(e.expType && e.expType.passAsTemplate)
6863                   {
6864                      char size[100];
6865                      ComputeTypeSize(e.expType);
6866                      sprintf(size, "%d", e.expType.size);
6867                      newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
6868                         MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
6869                            MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
6870                   }
6871
6872                   ReplaceExpContents(checkedExp, newExp);
6873                   e.byReference = true;
6874                }
6875                else if(!e.byReference || (_class && _class.type == noHeadClass))     // TESTING THIS HERE...
6876                {
6877                   Expression checkedExp, newExp;
6878
6879                   {
6880                      // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
6881                      bool hasAddress =
6882                         e.type == identifierExp ||
6883                         (e.type == ExpressionType::memberExp && e.member.memberType == dataMember) ||
6884                         (e.type == ExpressionType::pointerExp && e.member.memberType == dataMember) ||
6885                         (e.type == opExp && !e.op.exp1 && e.op.op == '*') ||
6886                         e.type == indexExp;
6887
6888                      if(_class && _class.type != noHeadClass && _class.type != normalClass && _class.type != structClass && !hasAddress)
6889                      {
6890                         Context context = PushContext();
6891                         Declarator decl;
6892                         OldList * specs = MkList();
6893                         char typeString[1024];
6894                         Expression newExp { };
6895
6896                         typeString[0] = '\0';
6897                         *newExp = *e;
6898
6899                         //if(e.destType) e.destType.refCount++;
6900                         // if(exp.expType) exp.expType.refCount++;
6901                         newExp.prev = null;
6902                         newExp.next = null;
6903                         newExp.expType = null;
6904
6905                         PrintType(e.expType, typeString, false, true);
6906                         decl = SpecDeclFromString(typeString, specs, null);
6907                         newExp.destType = ProcessType(specs, decl);
6908
6909                         curContext = context;
6910                         e.type = extensionCompoundExp;
6911
6912                         // We need a current compound for this
6913                         if(curCompound)
6914                         {
6915                            char name[100];
6916                            OldList * stmts = MkList();
6917                            sprintf(name, "__internalValue%03X", internalValueCounter++);
6918                            if(!curCompound.compound.declarations)
6919                               curCompound.compound.declarations = MkList();
6920                            curCompound.compound.declarations->Insert(null, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(name)), null))));
6921                            ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', newExp))));
6922                            ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier(name)))));
6923                            e.compound = MkCompoundStmt(null, stmts);
6924                         }
6925                         else
6926                            printf("libec: compiler error, curCompound is null in ApplyAnyObjectLogic\n");
6927
6928                         /*
6929                         e.compound = MkCompoundStmt(
6930                            MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(
6931                               MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))), 
6932
6933                            MkListOne(MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier("__internalValue"))))));
6934                         */
6935                         
6936                         {
6937                            Type type = e.destType;
6938                            e.destType = { };
6939                            CopyTypeInto(e.destType, type);
6940                            e.destType.refCount = 1;
6941                            e.destType.classObjectType = none;
6942                            FreeType(type);
6943                         }
6944
6945                         e.compound.compound.context = context;
6946                         PopContext(context);
6947                         curContext = context.parent;
6948                      }
6949                   }
6950
6951                   // TODO: INTEGRATE THIS WITH VERSION ABOVE WHICH WAS ADDED TO ENCOMPASS OTHER CASE (*pointer)
6952                   checkedExp = e;
6953                   while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
6954                   {
6955                      if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
6956                      {
6957                         if(checkedExp.type == extensionCompoundExp)
6958                         {
6959                            checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
6960                         }
6961                         else
6962                            checkedExp = checkedExp.list->last;
6963                      }
6964                      else if(checkedExp.type == castExp)
6965                         checkedExp = checkedExp.cast.exp;
6966                   }
6967                   {
6968                      Expression operand { };
6969                      operand = *checkedExp;
6970                      checkedExp.destType = null;
6971                      checkedExp.expType = null;
6972                      checkedExp.Clear();
6973                      checkedExp.type = opExp;
6974                      checkedExp.op.op = '&';
6975                      checkedExp.op.exp1 = null;
6976                      checkedExp.op.exp2 = operand;
6977
6978                      //newExp = MkExpOp(null, '&', checkedExp);
6979                   }
6980                   //ReplaceExpContents(checkedExp, newExp);
6981                }
6982             }
6983          }
6984       }
6985    }
6986    {
6987       // If expression type is a simple class, make it an address
6988       // FixReference(e, true);
6989    }
6990 //#if 0
6991    if((!destType || destType.kind == ellipsisType || destType.kind == voidType) && e.expType && (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) && 
6992       (e.expType.byReference || (e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
6993          (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass ) )))
6994    {
6995       if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class"))
6996       {
6997          return;  // LEAVE THIS CASE (typed_object & :: methods 's this) TO PASS 2 FOR NOW
6998       }
6999       else
7000       {
7001          Expression thisExp { };
7002
7003          *thisExp = *e;
7004          thisExp.prev = null;
7005          thisExp.next = null;
7006          e.Clear();
7007
7008          e.type = bracketsExp;
7009          e.list = MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(thisExp))));
7010          if(thisExp.expType.kind == classType && thisExp.expType._class && thisExp.expType._class.registered && thisExp.expType._class.registered.type == noHeadClass)
7011             ((Expression)e.list->first).byReference = true;
7012
7013          /*if(thisExp.expType.kind == classType && thisExp.expType._class && thisExp.expType._class.registered && !strcmp(thisExp.expType._class.registered.name, "class"))
7014          {
7015             e.expType = thisExp.expType;
7016             e.expType.refCount++;
7017          }
7018          else*/
7019          {
7020             e.expType = { };
7021             CopyTypeInto(e.expType, thisExp.expType);
7022             e.expType.byReference = false;
7023             e.expType.refCount = 1;
7024
7025             if(e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
7026                (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass))
7027             {
7028                e.expType.classObjectType = none;
7029             }
7030          }
7031       }
7032    }
7033 // TOFIX: Try this for a nice IDE crash!
7034 //#endif
7035    // The other way around
7036    else 
7037 //#endif
7038    if(destType && e.expType && 
7039          //e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class") &&
7040          (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) && 
7041          !destType.classObjectType && /*(destType.kind != pointerType || !destType.type || destType.type.kind != voidType) &&*/ destType.kind != voidType)
7042    {
7043       if(destType.kind == ellipsisType)
7044       {
7045          Compiler_Error($"Unspecified type\n");
7046       }
7047       else if(!(destType.truth && e.expType.kind == classType && e.expType._class && e.expType._class.registered && e.expType._class.registered.type == structClass))
7048       {
7049          bool byReference = e.expType.byReference;
7050          Expression thisExp { };
7051          Declarator decl;
7052          OldList * specs = MkList();
7053          char typeString[1024]; // Watch buffer overruns
7054          Type type;
7055          ClassObjectType backupClassObjectType;
7056
7057          if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && strcmp(e.expType._class.registered.name, "class"))
7058             type = e.expType;
7059          else
7060             type = destType;            
7061
7062          backupClassObjectType = type.classObjectType;
7063
7064          type.classObjectType = none;
7065
7066          typeString[0] = '\0';
7067          PrintType(type, typeString, false, true);
7068          decl = SpecDeclFromString(typeString, specs, null);
7069
7070          type.classObjectType = backupClassObjectType;
7071
7072          *thisExp = *e;
7073          thisExp.prev = null;
7074          thisExp.next = null;
7075          e.Clear();
7076
7077          if( ( type.kind == classType && type._class && type._class.registered && strcmp(type._class.registered.fullName, "ecere::com::Instance") &&
7078                    (type._class.registered.type == systemClass || type._class.registered.type == bitClass || 
7079                     type._class.registered.type == enumClass || type._class.registered.type == unitClass) ) ||
7080              (type.kind != pointerType && type.kind != arrayType && type.kind != classType) ||
7081              (!destType.byReference && byReference && (destType.kind != pointerType || type.kind != pointerType)))
7082          {
7083             e.type = opExp;
7084             e.op.op = '*';
7085             e.op.exp1 = null;
7086             e.op.exp2 = MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), thisExp);
7087          }
7088          else
7089          {
7090             e.type = castExp;
7091             e.cast.typeName = MkTypeName(specs, decl);
7092             e.cast.exp = thisExp;
7093             e.byReference = true;
7094          }
7095          e.expType = type;
7096          e.destType = destType;
7097          type.refCount++;
7098          destType.refCount++;
7099       }
7100    }
7101 }
7102
7103 void ProcessExpressionType(Expression exp)
7104 {
7105    bool unresolved = false;
7106    Location oldyylloc = yylloc;
7107    bool notByReference = false;
7108 #ifdef _DEBUG   
7109    char debugExpString[4096];
7110    debugExpString[0] = '\0';
7111    PrintExpression(exp, debugExpString);
7112 #endif
7113    if(!exp || exp.expType) 
7114       return;
7115
7116    //eSystem_Logf("%s\n", expString);
7117    
7118    // Testing this here
7119    yylloc = exp.loc;
7120    switch(exp.type)
7121    {
7122       case identifierExp:
7123       {
7124          Identifier id = exp.identifier;
7125          if(!id) return;
7126
7127          // DOING THIS LATER NOW...
7128          if(id._class && id._class.name)
7129          {
7130             id.classSym = id._class.symbol; // FindClass(id._class.name);
7131             /* TODO: Name Space Fix ups
7132             if(!id.classSym)
7133                id.nameSpace = eSystem_FindNameSpace(privateModule, id._class.name);
7134             */
7135          }
7136
7137          /* WHY WAS THIS COMMENTED OUT? if(!strcmp(id.string, "__thisModule"))
7138          {
7139             exp.expType = ProcessTypeString("Module", true);
7140             break;
7141          }
7142          else */if(strstr(id.string, "__ecereClass") == id.string)
7143          {
7144             exp.expType = ProcessTypeString("ecere::com::Class", true);
7145             break;
7146          }
7147          else if(id._class && (id.classSym || (id._class.name && !strcmp(id._class.name, "property"))))
7148          {
7149             // Added this here as well
7150             ReplaceClassMembers(exp, thisClass);
7151             if(exp.type != identifierExp)
7152             {
7153                ProcessExpressionType(exp);
7154                break;
7155             }
7156
7157             if(id.classSym && ResolveIdWithClass(exp, id.classSym.registered, false))
7158                break;
7159          }
7160          else
7161          {
7162             Symbol symbol = FindSymbol(id.string, curContext, topContext /*exp.destType ? topContext : globalContext*/, false, id._class && id._class.name == null);
7163             // Enums should be resolved here (Special pass in opExp to fix identifiers not seen as enum on the first pass)
7164             if(!symbol/* && exp.destType*/)
7165             {
7166                if(exp.destType && CheckExpressionType(exp, exp.destType, false))
7167                   break;
7168                else
7169                {
7170                   if(thisClass)
7171                   {
7172                      ReplaceClassMembers(exp, thisClass ? thisClass : currentClass);
7173                      if(exp.type != identifierExp)
7174                      {
7175                         ProcessExpressionType(exp);
7176                         break;
7177                      }
7178                   }
7179                   // Static methods called from inside the _class
7180                   else if(currentClass && !id._class)
7181                   {
7182                      if(ResolveIdWithClass(exp, currentClass, true))
7183                         break;
7184                   }
7185                   symbol = FindSymbol(id.string, topContext.parent, globalContext, false, id._class && id._class.name == null);
7186                }
7187             }
7188
7189             // If we manage to resolve this symbol
7190             if(symbol)
7191             {
7192                Type type = symbol.type;
7193                Class _class = (type && type.kind == classType && type._class) ? type._class.registered : null;
7194
7195                if(_class && !strcmp(id.string, "this") && !type.classObjectType)
7196                {
7197                   Context context = SetupTemplatesContext(_class);
7198                   type = ReplaceThisClassType(_class);
7199                   FinishTemplatesContext(context);
7200                   if(type) type.refCount = 0;   // We'll be incrementing it right below...
7201                }
7202
7203                FreeSpecifier(id._class);
7204                id._class = null;
7205                delete id.string;
7206                id.string = CopyString(symbol.string);
7207
7208                id.classSym = null;
7209                exp.expType = type;
7210                if(type)
7211                   type.refCount++;
7212                if(type && (type.kind == enumType || (_class && _class.type == enumClass)))
7213                   // Add missing cases here... enum Classes...
7214                   exp.isConstant = true;
7215
7216                // TOCHECK: Why was !strcmp(id.string, "this") commented out?
7217                if(symbol.isParam || !strcmp(id.string, "this"))
7218                {
7219                   if(_class && _class.type == structClass)
7220                      exp.byReference = true;
7221                   
7222                   //TESTING COMMENTING THIS OUT IN FAVOR OF ApplyAnyObjectLogic
7223                   /*if(type && _class && (type.classObjectType == typedObject || type.classObjectType == anyObject) && 
7224                      ((_class.type == unitClass || _class.type == enumClass || _class.type == bitClass) || 
7225                      (type.byReference && (_class.type == normalClass || _class.type == noHeadClass))))
7226                   {
7227                      Identifier id = exp.identifier;
7228                      exp.type = bracketsExp;
7229                      exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(id)));
7230                   }*/
7231                }
7232
7233                if(symbol.isIterator)
7234                {
7235                   if(symbol.isIterator == 3)
7236                   {
7237                      exp.type = bracketsExp;
7238                      exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(exp.identifier)));
7239                      ((Expression)exp.list->first).op.exp2.expType = exp.expType;
7240                      exp.expType = null;
7241                      ProcessExpressionType(exp);                     
7242                   }
7243                   else if(symbol.isIterator != 4)
7244                   {
7245                      exp.type = memberExp;
7246                      exp.member.exp = MkExpIdentifier(exp.identifier);
7247                      exp.member.exp.expType = exp.expType;
7248                      /*if(symbol.isIterator == 6)
7249                         exp.member.member = MkIdentifier("key");
7250                      else*/
7251                         exp.member.member = MkIdentifier("data");
7252                      exp.expType = null;
7253                      ProcessExpressionType(exp);
7254                   }
7255                }
7256                break;
7257             }
7258             else
7259             {
7260                DefinedExpression definedExp = null;
7261                if(thisNameSpace && !(id._class && !id._class.name))
7262                {
7263                   char name[1024];
7264                   strcpy(name, thisNameSpace);
7265                   strcat(name, "::");
7266                   strcat(name, id.string);
7267                   definedExp = eSystem_FindDefine(privateModule, name);
7268                }
7269                if(!definedExp)
7270                   definedExp = eSystem_FindDefine(privateModule, id.string);
7271                if(definedExp)
7272                {
7273                   int c;
7274                   for(c = 0; c<definedExpStackPos; c++)
7275                      if(definedExpStack[c] == definedExp)
7276                         break;
7277                   if(c == definedExpStackPos && c < sizeof(definedExpStack) / sizeof(void *))
7278                   {
7279                      Location backupYylloc = yylloc;
7280                      definedExpStack[definedExpStackPos++] = definedExp;
7281                      fileInput = TempFile { };
7282                      fileInput.Write(definedExp.value, 1, strlen(definedExp.value));
7283                      fileInput.Seek(0, start);
7284
7285                      echoOn = false;
7286                      parsedExpression = null;
7287                      resetScanner();
7288                      expression_yyparse();
7289                      delete fileInput;
7290
7291                      yylloc = backupYylloc;
7292
7293                      if(parsedExpression)
7294                      {
7295                         FreeIdentifier(id);
7296                         exp.type = bracketsExp;
7297                         exp.list = MkListOne(parsedExpression);
7298                         parsedExpression.loc = yylloc;
7299                         ProcessExpressionType(exp);
7300                         definedExpStackPos--;
7301                         return;
7302                      }
7303                      definedExpStackPos--;
7304                   }
7305                   else
7306                   {
7307                      if(inCompiler)
7308                      {
7309                         Compiler_Error($"Recursion in defined expression %s\n", id.string);
7310                      }
7311                   }
7312                }
7313                else
7314                {
7315                   GlobalData data = null;
7316                   if(thisNameSpace && !(id._class && !id._class.name))
7317                   {
7318                      char name[1024];
7319                      strcpy(name, thisNameSpace);
7320                      strcat(name, "::");
7321                      strcat(name, id.string);
7322                      data = FindGlobalData(name);
7323                   }
7324                   if(!data)
7325                      data = FindGlobalData(id.string);
7326                   if(data)
7327                   {
7328                      DeclareGlobalData(data);
7329                      exp.expType = data.dataType;
7330                      if(data.dataType) data.dataType.refCount++;
7331
7332                      delete id.string;
7333                      id.string = CopyString(data.fullName);
7334                      FreeSpecifier(id._class);
7335                      id._class = null;
7336
7337                      break;
7338                   }
7339                   else
7340                   {
7341                      GlobalFunction function = null;
7342                      if(thisNameSpace && !(id._class && !id._class.name))
7343                      {
7344                         char name[1024];
7345                         strcpy(name, thisNameSpace);
7346                         strcat(name, "::");
7347                         strcat(name, id.string);
7348                         function = eSystem_FindFunction(privateModule, name);
7349                      }
7350                      if(!function)
7351                         function = eSystem_FindFunction(privateModule, id.string);
7352                      if(function)
7353                      {
7354                         char name[1024];
7355                         delete id.string;
7356                         id.string = CopyString(function.name);
7357                         name[0] = 0;
7358
7359                         if(function.module.importType != staticImport && (!function.dataType || !function.dataType.dllExport))
7360                            strcpy(name, "__ecereFunction_");
7361                         FullClassNameCat(name, id.string, false); // Why is this using FullClassNameCat ?
7362                         if(DeclareFunction(function, name))
7363                         {
7364                            delete id.string;
7365                            id.string = CopyString(name);
7366                         }
7367                         exp.expType = function.dataType;
7368                         if(function.dataType) function.dataType.refCount++;
7369
7370                         FreeSpecifier(id._class);
7371                         id._class = null;
7372
7373                         break;
7374                      }
7375                   }
7376                }
7377             }
7378          }
7379          unresolved = true;
7380          break;
7381       }
7382       case instanceExp:
7383       {
7384          Class _class;
7385          // Symbol classSym;
7386
7387          if(!exp.instance._class)
7388          {
7389             if(exp.destType && exp.destType.kind == classType && exp.destType._class)
7390             {
7391                exp.instance._class = MkSpecifierName(exp.destType._class.string);
7392             }
7393 #ifdef _DEBUG
7394             else 
7395             {
7396                printf("");               
7397             }
7398 #endif
7399          }
7400
7401          //classSym = FindClass(exp.instance._class.fullName);
7402          //_class = classSym ? classSym.registered : null;
7403
7404          ProcessInstantiationType(exp.instance);
7405          exp.isConstant = exp.instance.isConstant;
7406
7407          /*
7408          if(_class.type == unitClass && _class.base.type != systemClass)
7409          {
7410             {
7411                Type destType = exp.destType;
7412
7413                exp.destType = MkClassType(_class.base.fullName);
7414                exp.expType = MkClassType(_class.fullName);
7415                CheckExpressionType(exp, exp.destType, true);
7416
7417                exp.destType = destType;
7418             }
7419             exp.expType = MkClassType(_class.fullName);
7420          }
7421          else*/
7422          if(exp.instance._class)
7423          {
7424             exp.expType = MkClassType(exp.instance._class.name);
7425             /*if(exp.expType._class && exp.expType._class.registered && 
7426                (exp.expType._class.registered.type == normalClass || exp.expType._class.registered.type == noHeadClass))
7427                exp.expType.byReference = true;*/
7428          }         
7429          break;
7430       }
7431       case constantExp:
7432       {
7433          if(!exp.expType)
7434          {
7435             Type type
7436             {
7437                refCount = 1;
7438                constant = true;
7439             };
7440             exp.expType = type;
7441
7442             if(exp.constant[0] == '\'')
7443             {
7444                if((int)((byte *)exp.constant)[1] > 127)
7445                {
7446                   int nb;
7447                   unichar ch = UTF8GetChar(exp.constant + 1, &nb);
7448                   if(nb < 2) ch = exp.constant[1];
7449                   delete exp.constant;
7450                   exp.constant = PrintUInt(ch);
7451                   // type.kind = (ch > 0xFFFF) ? intType : shortType;
7452                   type.kind = classType; //(ch > 0xFFFF) ? intType : shortType;
7453                   type._class = FindClass("unichar");
7454
7455                   type.isSigned = false;
7456                }
7457                else
7458                {
7459                   type.kind = charType;
7460                   type.isSigned = true;
7461                }
7462             }
7463             else if(strchr(exp.constant, '.'))
7464             {
7465                char ch = exp.constant[strlen(exp.constant)-1];
7466                if(ch == 'f')
7467                   type.kind = floatType;
7468                else
7469                   type.kind = doubleType;
7470                type.isSigned = true;
7471             }
7472             else
7473             {
7474                if(exp.constant[0] == '0' && exp.constant[1])
7475                   type.isSigned = false;
7476                else if(strchr(exp.constant, 'L') || strchr(exp.constant, 'l'))
7477                   type.isSigned = false;
7478                else if(strtoll(exp.constant, null, 0) > MAXINT)
7479                   type.isSigned = false;
7480                else
7481                   type.isSigned = true;
7482                type.kind = intType;
7483             }
7484             exp.isConstant = true;
7485          }
7486          break;
7487       }
7488       case stringExp:
7489       {
7490          exp.isConstant = true;      // Why wasn't this constant?
7491          exp.expType = Type
7492          {
7493             refCount = 1;
7494             kind = pointerType;
7495             type = Type
7496             {
7497                refCount = 1;
7498                kind = charType;
7499                constant = true;
7500             }
7501          };
7502          break;
7503       }
7504       case newExp:
7505       case new0Exp:
7506          ProcessExpressionType(exp._new.size);
7507          exp.expType = Type
7508          {
7509             refCount = 1;
7510             kind = pointerType;
7511             type = ProcessType(exp._new.typeName.qualifiers, exp._new.typeName.declarator);
7512          };
7513          DeclareType(exp.expType.type, false, false);
7514          break;
7515       case renewExp:
7516       case renew0Exp:
7517          ProcessExpressionType(exp._renew.size);
7518          ProcessExpressionType(exp._renew.exp);
7519          exp.expType = Type
7520          {
7521             refCount = 1;
7522             kind = pointerType;
7523             type = ProcessType(exp._renew.typeName.qualifiers, exp._renew.typeName.declarator);
7524          };
7525          DeclareType(exp.expType.type, false, false);
7526          break;
7527       case opExp:
7528       {
7529          bool assign = false, boolResult = false, boolOps = false;
7530          Type type1 = null, type2 = null;
7531          bool useDestType = false, useSideType = false;
7532          Location oldyylloc = yylloc;
7533          bool useSideUnit = false;
7534
7535          // Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
7536          Type dummy
7537          {
7538             count = 1;
7539             refCount = 1;
7540          };
7541
7542          switch(exp.op.op)
7543          {
7544             // Assignment Operators
7545             case '=': 
7546             case MUL_ASSIGN:
7547             case DIV_ASSIGN:
7548             case MOD_ASSIGN:
7549             case ADD_ASSIGN:
7550             case SUB_ASSIGN:
7551             case LEFT_ASSIGN:
7552             case RIGHT_ASSIGN:
7553             case AND_ASSIGN:
7554             case XOR_ASSIGN:
7555             case OR_ASSIGN:
7556                assign = true;
7557                break;
7558             // boolean Operators
7559             case '!':
7560                // Expect boolean operators
7561                //boolOps = true;
7562                //boolResult = true;
7563                break;
7564             case AND_OP:
7565             case OR_OP:
7566                // Expect boolean operands
7567                boolOps = true;
7568                boolResult = true;
7569                break;
7570             // Comparisons
7571             case EQ_OP:
7572             case '<':
7573             case '>':
7574             case LE_OP:
7575             case GE_OP:
7576             case NE_OP:
7577                // Gives boolean result
7578                boolResult = true;
7579                useSideType = true;
7580                break;
7581             case '+':
7582             case '-':
7583                useSideUnit = true;
7584
7585                // Just added these... testing
7586             case '|':
7587             case '&':
7588             case '^':
7589
7590             // DANGER: Verify units
7591             case '/':
7592             case '%':
7593             case '*':
7594                
7595                if(exp.op.op != '*' || exp.op.exp1)
7596                {
7597                   useSideType = true;
7598                   useDestType = true;
7599                }
7600                break;
7601
7602             /*// Implement speed etc.
7603             case '*':
7604             case '/':
7605                break;
7606             */
7607          }
7608          if(exp.op.op == '&')
7609          {
7610             // Added this here earlier for Iterator address as key
7611             if(!exp.op.exp1 && exp.op.exp2 && exp.op.exp2.type == identifierExp && exp.op.exp2.identifier)
7612             {
7613                Identifier id = exp.op.exp2.identifier;
7614                Symbol symbol = FindSymbol(id.string, curContext, topContext, false, id._class && id._class.name == null);
7615                if(symbol && symbol.isIterator == 2)
7616                {
7617                   exp.type = memberExp;
7618                   exp.member.exp = exp.op.exp2;
7619                   exp.member.member = MkIdentifier("key");
7620                   exp.expType = null;
7621                   exp.op.exp2.expType = symbol.type;
7622                   symbol.type.refCount++;
7623                   ProcessExpressionType(exp);
7624                   FreeType(dummy);
7625                   break;
7626                }
7627                // exp.op.exp2.usage.usageRef = true;
7628             }
7629          }
7630
7631          //dummy.kind = TypeDummy;
7632
7633          if(exp.op.exp1)
7634          {
7635             if(exp.destType && exp.destType.kind == classType &&
7636                exp.destType._class && exp.destType._class.registered && useDestType &&
7637                
7638               ((exp.destType._class.registered.type == unitClass && useSideUnit) || 
7639                exp.destType._class.registered.type == enumClass ||
7640                exp.destType._class.registered.type == bitClass
7641                )) 
7642
7643               //(exp.destType._class.registered.type == unitClass || exp.destType._class.registered.type == enumClass) && useDestType)
7644             {
7645                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7646                exp.op.exp1.destType = exp.destType;
7647                if(exp.destType)
7648                   exp.destType.refCount++;
7649             }
7650             else if(!assign)
7651             {
7652                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7653                exp.op.exp1.destType = dummy;
7654                dummy.refCount++;               
7655             }
7656
7657             // TESTING THIS HERE...
7658             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count++;
7659             ProcessExpressionType(exp.op.exp1);
7660             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count--;
7661
7662             if(exp.op.exp1.destType == dummy)
7663             {
7664                FreeType(dummy);
7665                exp.op.exp1.destType = null;
7666             }
7667             type1 = exp.op.exp1.expType;
7668          }
7669
7670          if(exp.op.exp2)
7671          {
7672             char expString[10240];
7673             expString[0] = '\0';
7674             if(exp.op.exp2.type == instanceExp && !exp.op.exp2.instance._class)
7675             {
7676                if(exp.op.exp1)
7677                {
7678                   exp.op.exp2.destType = exp.op.exp1.expType;
7679                   if(exp.op.exp1.expType)
7680                      exp.op.exp1.expType.refCount++;
7681                }
7682                else
7683                {
7684                   exp.op.exp2.destType = exp.destType;
7685                   if(exp.destType)
7686                      exp.destType.refCount++;
7687                }
7688
7689                if(type1) type1.refCount++;
7690                exp.expType = type1;
7691             }
7692             else if(assign)
7693             {
7694                if(inCompiler)
7695                   PrintExpression(exp.op.exp2, expString);
7696
7697                if(type1 && type1.kind == pointerType)
7698                {
7699                   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 ||
7700                      exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN)
7701                      Compiler_Error($"operator %s illegal on pointer\n", exp.op.op);
7702                   else if(exp.op.op == '=')
7703                   {
7704                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7705                      exp.op.exp2.destType = type1;
7706                      if(type1)
7707                         type1.refCount++;
7708                   }
7709                }
7710                else
7711                {
7712                   // Don't convert to the type for those... (e.g.: Degrees a; a /= 2;) 
7713                   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/* ||
7714                      exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN*/);
7715                   else
7716                   {
7717                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7718                      exp.op.exp2.destType = type1;
7719                      if(type1)
7720                         type1.refCount++;
7721                   }
7722                }
7723                if(type1) type1.refCount++;
7724                exp.expType = type1;
7725             }
7726             else if(exp.destType && exp.destType.kind == classType &&
7727                exp.destType._class && exp.destType._class.registered && 
7728                
7729                   ((exp.destType._class.registered.type == unitClass && useDestType && useSideUnit) || 
7730                   (exp.destType._class.registered.type == enumClass && useDestType)) 
7731                   )
7732             {
7733                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7734                exp.op.exp2.destType = exp.destType;
7735                if(exp.destType)
7736                   exp.destType.refCount++;
7737             }
7738             else
7739             {
7740                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7741                exp.op.exp2.destType = dummy;
7742                dummy.refCount++;
7743             }
7744
7745             // TESTING THIS HERE... (DANGEROUS)
7746             if(type1 && boolResult && useSideType && type1.kind == classType && type1._class && type1._class.registered && 
7747                (type1._class.registered.type == bitClass || type1._class.registered.type == enumClass))
7748             {
7749                FreeType(exp.op.exp2.destType);
7750                exp.op.exp2.destType = type1;
7751                type1.refCount++;
7752             }
7753             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count++;
7754             ProcessExpressionType(exp.op.exp2);
7755             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
7756
7757             if(assign && type1 && type1.kind == pointerType && exp.op.exp2.expType)
7758             {
7759                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)
7760                {
7761                   if(exp.op.op != '=' && type1.type.kind == voidType) 
7762                      Compiler_Error($"void *: unknown size\n");
7763                }
7764                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|| 
7765                            (type1.type.kind == voidType && exp.op.exp2.expType.kind == classType && exp.op.exp2.expType._class.registered &&
7766                               (exp.op.exp2.expType._class.registered.type == normalClass || 
7767                               exp.op.exp2.expType._class.registered.type == structClass ||
7768                               exp.op.exp2.expType._class.registered.type == noHeadClass)))
7769                {
7770                   if(exp.op.op == ADD_ASSIGN)
7771                      Compiler_Error($"cannot add two pointers\n");                   
7772                }
7773                else if((exp.op.exp2.expType.kind == classType && type1.kind == pointerType && type1.type.kind == classType && 
7774                   type1.type._class == exp.op.exp2.expType._class && exp.op.exp2.expType._class.registered && exp.op.exp2.expType._class.registered.type == structClass))
7775                {
7776                   if(exp.op.op == ADD_ASSIGN)
7777                      Compiler_Error($"cannot add two pointers\n");                   
7778                }
7779                else if(inCompiler)
7780                {
7781                   char type1String[1024];
7782                   char type2String[1024];
7783                   type1String[0] = '\0';
7784                   type2String[0] = '\0';
7785                   
7786                   PrintType(exp.op.exp2.expType, type1String, false, true);
7787                   PrintType(type1, type2String, false, true);
7788                   ChangeCh(expString, '\n', ' ');
7789                   Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1String, type2String);
7790                }
7791             }
7792
7793             if(exp.op.exp2.destType == dummy)
7794             {
7795                FreeType(dummy);
7796                exp.op.exp2.destType = null;
7797             }
7798
7799             type2 = exp.op.exp2.expType;
7800          }
7801
7802          dummy.kind = voidType;
7803
7804          if(exp.op.op == SIZEOF)
7805          {
7806             exp.expType = Type
7807             {
7808                refCount = 1;
7809                kind = intType;
7810             };
7811             exp.isConstant = true;
7812          }
7813          // Get type of dereferenced pointer
7814          else if(exp.op.op == '*' && !exp.op.exp1)
7815          {
7816             exp.expType = Dereference(type2);
7817             if(type2 && type2.kind == classType)
7818                notByReference = true;
7819          }
7820          else if(exp.op.op == '&' && !exp.op.exp1)
7821             exp.expType = Reference(type2);
7822          else if(!assign)
7823          {
7824             if(boolOps)
7825             {
7826                if(exp.op.exp1) 
7827                {
7828                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7829                   exp.op.exp1.destType = MkClassType("bool");
7830                   exp.op.exp1.destType.truth = true;
7831                   if(!exp.op.exp1.expType)
7832                      ProcessExpressionType(exp.op.exp1);
7833                   else
7834                      CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
7835                   FreeType(exp.op.exp1.expType);
7836                   exp.op.exp1.expType = MkClassType("bool");
7837                   exp.op.exp1.expType.truth = true;
7838                }
7839                if(exp.op.exp2) 
7840                {
7841                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7842                   exp.op.exp2.destType = MkClassType("bool");
7843                   exp.op.exp2.destType.truth = true;
7844                   if(!exp.op.exp2.expType)
7845                      ProcessExpressionType(exp.op.exp2);
7846                   else
7847                      CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
7848                   FreeType(exp.op.exp2.expType);
7849                   exp.op.exp2.expType = MkClassType("bool");
7850                   exp.op.exp2.expType.truth = true;
7851                }
7852             }
7853             else if(exp.op.exp1 && exp.op.exp2 && 
7854                ((useSideType /*&& 
7855                      (useSideUnit || 
7856                         ((!type1 || type1.kind != classType || type1._class.registered.type != unitClass) &&
7857                          (!type2 || type2.kind != classType || type2._class.registered.type != unitClass)))*/) ||
7858                   ((!type1 || type1.kind != classType || !strcmp(type1._class.string, "String")) && 
7859                   (!type2 || type2.kind != classType || !strcmp(type2._class.string, "String")))))
7860             {
7861                if(type1 && type2 &&
7862                   // If either both are class or both are not class
7863                   ((type1.kind == classType && type1._class && strcmp(type1._class.string, "String")) == (type2.kind == classType && type2._class && strcmp(type2._class.string, "String"))))
7864                {
7865                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7866                   exp.op.exp2.destType = type1;
7867                   type1.refCount++;
7868                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7869                   exp.op.exp1.destType = type2;
7870                   type2.refCount++;
7871                   // Warning here for adding Radians + Degrees with no destination type
7872                   if(!boolResult && type1.kind == classType && (!exp.destType || exp.destType.kind != classType) && 
7873                      type1._class.registered && type1._class.registered.type == unitClass && 
7874                      type2._class.registered && type2._class.registered.type == unitClass && 
7875                      type1._class.registered != type2._class.registered)
7876                      Compiler_Warning($"operating on %s and %s with an untyped result, assuming %s\n",
7877                         type1._class.string, type2._class.string, type1._class.string);
7878
7879                   if(type1.kind == pointerType && type1.type.kind == templateType && type2.kind != pointerType)
7880                   {
7881                      Expression argExp = GetTemplateArgExp(type1.type.templateParameter, thisClass, true);
7882                      if(argExp)
7883                      {
7884                         Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
7885
7886                         exp.op.exp1 = MkExpBrackets(MkListOne(MkExpCast(
7887                            MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), 
7888                            exp.op.exp1)));
7889
7890                         ProcessExpressionType(exp.op.exp1);
7891
7892                         if(type2.kind != pointerType)
7893                         {
7894                            ProcessExpressionType(classExp);
7895
7896                            exp.op.exp2 = MkExpBrackets(MkListOne(MkExpOp(exp.op.exp2, '*', 
7897                               // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
7898                               MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
7899                                  // noHeadClass
7900                                  MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("5")),
7901                                     OR_OP, 
7902                                  // normalClass
7903                                  MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("0"))))),
7904                                     MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
7905                                        MkPointer(null, null), null)))),                                  
7906                                        MkExpMember(classExp, MkIdentifier("typeSize"))))))));
7907
7908                            if(!exp.op.exp2.expType)
7909                               type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
7910
7911                            ProcessExpressionType(exp.op.exp2);
7912                         }
7913                      }
7914                   }
7915                   
7916                   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)))
7917                   {
7918                      if(type1.kind != classType && type1.type.kind == voidType) 
7919                         Compiler_Error($"void *: unknown size\n");
7920                      exp.expType = type1;
7921                      if(type1) type1.refCount++;
7922                   }
7923                   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)))
7924                   {
7925                      if(type2.kind != classType && type2.type.kind == voidType) 
7926                         Compiler_Error($"void *: unknown size\n");
7927                      exp.expType = type2;
7928                      if(type2) type2.refCount++;
7929                   }
7930                   else if((type1.kind == pointerType && type2.kind != pointerType && type2.kind != arrayType && type2.kind != functionType && type2.kind != methodType && type2.kind != classType && type2.kind != subClassType) ||
7931                           (type2.kind == pointerType && type1.kind != pointerType && type1.kind != arrayType && type1.kind != functionType && type1.kind != methodType && type1.kind != classType && type1.kind != subClassType))
7932                   {
7933                      Compiler_Warning($"different levels of indirection\n");
7934                   }
7935                   else 
7936                   {
7937                      bool success = false;
7938                      if(type1.kind == pointerType && type2.kind == pointerType)
7939                      {
7940                         if(exp.op.op == '+')
7941                            Compiler_Error($"cannot add two pointers\n");
7942                         else if(exp.op.op == '-')
7943                         {
7944                            // Pointer Subtraction gives integer
7945                            if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false))
7946                            {
7947                               exp.expType = Type
7948                               {
7949                                  kind = intType;
7950                                  refCount = 1;
7951                               };
7952                               success = true;
7953
7954                               if(type1.type.kind == templateType)
7955                               {
7956                                  Expression argExp = GetTemplateArgExp(type1.type.templateParameter, thisClass, true);
7957                                  if(argExp)
7958                                  {
7959                                     Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
7960
7961                                     ProcessExpressionType(classExp);
7962
7963                                     exp.type = bracketsExp;
7964                                     exp.list = MkListOne(MkExpOp(
7965                                        MkExpBrackets(MkListOne(MkExpOp(
7966                                              MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp1)))
7967                                              , exp.op.op, 
7968                                              MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp2)))))), '/', 
7969                                           
7970                                              //MkExpMember(classExp, MkIdentifier("typeSize"))
7971
7972                                              // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
7973                                              MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
7974                                                 // noHeadClass
7975                                                 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass"))),
7976                                                    OR_OP, 
7977                                                 // normalClass
7978                                                 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass")))))),
7979                                                    MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
7980                                                       MkPointer(null, null), null)))),                                  
7981                                                       MkExpMember(classExp, MkIdentifier("typeSize")))))
7982
7983                                              
7984                                              ));
7985                                     
7986                                     ProcessExpressionType(((Expression)exp.list->first).op.exp2);
7987                                     FreeType(dummy);
7988                                     return;                                       
7989                                  }
7990                               }
7991                            }
7992                         }
7993                      }
7994
7995                      if(!success && exp.op.exp1.type == constantExp)
7996                      {
7997                         // If first expression is constant, try to match that first
7998                         if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
7999                         {
8000                            if(exp.expType) FreeType(exp.expType);
8001                            exp.expType = exp.op.exp1.destType;
8002                            if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8003                            success = true;
8004                         }
8005                         else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8006                         {
8007                            if(exp.expType) FreeType(exp.expType);
8008                            exp.expType = exp.op.exp2.destType;
8009                            if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8010                            success = true;
8011                         }
8012                      }
8013                      else if(!success)
8014                      {
8015                         if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8016                         {
8017                            if(exp.expType) FreeType(exp.expType);
8018                            exp.expType = exp.op.exp2.destType;
8019                            if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8020                            success = true;
8021                         }
8022                         else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8023                         {
8024                            if(exp.expType) FreeType(exp.expType);
8025                            exp.expType = exp.op.exp1.destType;
8026                            if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8027                            success = true;
8028                         }
8029                      }
8030                      if(!success)
8031                      {
8032                         char expString1[10240];
8033                         char expString2[10240];
8034                         char type1[1024];
8035                         char type2[1024];
8036                         expString1[0] = '\0';
8037                         expString2[0] = '\0';
8038                         type1[0] = '\0';
8039                         type2[0] = '\0';
8040                         if(inCompiler)
8041                         {
8042                            PrintExpression(exp.op.exp1, expString1);
8043                            ChangeCh(expString1, '\n', ' ');
8044                            PrintExpression(exp.op.exp2, expString2);
8045                            ChangeCh(expString2, '\n', ' ');
8046                            PrintType(exp.op.exp1.expType, type1, false, true);
8047                            PrintType(exp.op.exp2.expType, type2, false, true);
8048                         }
8049
8050                         Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1, expString2, type2);
8051                      }
8052                   }
8053                }
8054                // ADDED THESE TWO FROM OUTSIDE useSideType CHECK
8055                else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type2 && type1 && type2.kind == classType && type1.kind != classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
8056                {
8057                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8058                   // Convert e.g. / 4 into / 4.0
8059                   exp.op.exp1.destType = type2._class.registered.dataType;
8060                   if(type2._class.registered.dataType)
8061                      type2._class.registered.dataType.refCount++;
8062                   CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8063                   exp.expType = type2;
8064                   if(type2) type2.refCount++;
8065                }
8066                else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type1 && type2 && type1.kind == classType && type2.kind != classType && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
8067                {
8068                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8069                   // Convert e.g. / 4 into / 4.0
8070                   exp.op.exp2.destType = type1._class.registered.dataType;
8071                   if(type1._class.registered.dataType)
8072                      type1._class.registered.dataType.refCount++;
8073                   CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8074                   exp.expType = type1;
8075                   if(type1) type1.refCount++;
8076                }
8077                else if(type1)
8078                {
8079                   bool valid = false;
8080
8081                   if(!boolResult && useSideUnit && type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8082                   {
8083                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8084
8085                      if(!type1._class.registered.dataType)
8086                         type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
8087                      exp.op.exp2.destType = type1._class.registered.dataType;
8088                      exp.op.exp2.destType.refCount++;
8089
8090                      CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8091                      type2 = exp.op.exp2.destType;
8092
8093                      exp.expType = type2;
8094                      type2.refCount++;
8095                   }
8096                   
8097                   if(!boolResult && useSideUnit && type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8098                   {
8099                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8100
8101                      if(!type2._class.registered.dataType)
8102                         type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
8103                      exp.op.exp1.destType = type2._class.registered.dataType;
8104                      exp.op.exp1.destType.refCount++;
8105
8106                      CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8107                      type1 = exp.op.exp1.destType;
8108                      exp.expType = type1;
8109                      type1.refCount++;
8110                   }
8111
8112                   // TESTING THIS NEW CODE
8113                   if(!boolResult || exp.op.op == '>' || exp.op.op == '<')
8114                   {
8115                      if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass && exp.op.exp2.expType)
8116                      {
8117                         if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false))
8118                         {
8119                            if(exp.expType) FreeType(exp.expType);
8120                            exp.expType = exp.op.exp1.expType;
8121                            if(exp.op.exp2.expType) exp.op.exp1.expType.refCount++;
8122                            valid = true;
8123                         }
8124                      }
8125
8126                      else if(type2 && (type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass && exp.op.exp1.expType))
8127                      {
8128                         if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false))
8129                         {
8130                            if(exp.expType) FreeType(exp.expType);
8131                            exp.expType = exp.op.exp2.expType;
8132                            if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8133                            valid = true;
8134                         }
8135                      }
8136                   }
8137
8138                   if(!valid)
8139                   {
8140                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8141                      exp.op.exp2.destType = type1;
8142                      type1.refCount++;
8143
8144                      /*
8145                      // Maybe this was meant to be an enum...
8146                      if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8147                      {
8148                         Type oldType = exp.op.exp2.expType;
8149                         exp.op.exp2.expType = null;
8150                         if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8151                            FreeType(oldType);
8152                         else
8153                            exp.op.exp2.expType = oldType;
8154                      }
8155                      */
8156
8157                      /*
8158                      // TESTING THIS HERE... LATEST ADDITION
8159                      if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8160                      {
8161                         if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8162                         exp.op.exp2.destType = type2._class.registered.dataType;
8163                         if(type2._class.registered.dataType)
8164                            type2._class.registered.dataType.refCount++;
8165                         CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8166                         
8167                         //exp.expType = type2._class.registered.dataType; //type2;
8168                         //if(type2) type2.refCount++;
8169                      }
8170
8171                      // TESTING THIS HERE... LATEST ADDITION
8172                      if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8173                      {
8174                         if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8175                         exp.op.exp1.destType = type1._class.registered.dataType;
8176                         if(type1._class.registered.dataType)
8177                            type1._class.registered.dataType.refCount++;
8178                         CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8179                         exp.expType = type1._class.registered.dataType; //type1;
8180                         if(type1) type1.refCount++;
8181                      }
8182                      */
8183
8184                      if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8185                      {
8186                         if(exp.expType) FreeType(exp.expType);
8187                         exp.expType = exp.op.exp2.destType;
8188                         if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8189                      }
8190                      else if(type1 && type2)
8191                      {
8192                         char expString1[10240];
8193                         char expString2[10240];
8194                         char type1String[1024];
8195                         char type2String[1024];
8196                         expString1[0] = '\0';
8197                         expString2[0] = '\0';
8198                         type1String[0] = '\0';
8199                         type2String[0] = '\0';
8200                         if(inCompiler)
8201                         {
8202                            PrintExpression(exp.op.exp1, expString1);
8203                            ChangeCh(expString1, '\n', ' ');
8204                            PrintExpression(exp.op.exp2, expString2);
8205                            ChangeCh(expString2, '\n', ' ');
8206                            PrintType(exp.op.exp1.expType, type1String, false, true);
8207                            PrintType(exp.op.exp2.expType, type2String, false, true);
8208                         }
8209
8210                         Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
8211
8212                         if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8213                         {
8214                            exp.expType = exp.op.exp1.expType;
8215                            if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
8216                         }
8217                         else if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8218                         {
8219                            exp.expType = exp.op.exp2.expType;
8220                            if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8221                         }
8222                      }
8223                   }
8224                }
8225                else if(type2)
8226                {
8227                   // Maybe this was meant to be an enum...
8228                   if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8229                   {
8230                      Type oldType = exp.op.exp1.expType;
8231                      exp.op.exp1.expType = null;
8232                      if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8233                         FreeType(oldType);
8234                      else
8235                         exp.op.exp1.expType = oldType;
8236                   }
8237
8238                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8239                   exp.op.exp1.destType = type2;
8240                   type2.refCount++;
8241                   /*
8242                   // TESTING THIS HERE... LATEST ADDITION
8243                   if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8244                   {
8245                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8246                      exp.op.exp1.destType = type1._class.registered.dataType;
8247                      if(type1._class.registered.dataType)
8248                         type1._class.registered.dataType.refCount++;
8249                   }
8250
8251                   // TESTING THIS HERE... LATEST ADDITION
8252                   if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8253                   {
8254                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8255                      exp.op.exp2.destType = type2._class.registered.dataType;
8256                      if(type2._class.registered.dataType)
8257                         type2._class.registered.dataType.refCount++;
8258                   }
8259                   */
8260
8261                   if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8262                   {
8263                      if(exp.expType) FreeType(exp.expType);
8264                      exp.expType = exp.op.exp1.destType;
8265                      if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8266                   }
8267                }
8268             }
8269             else if(type2 && (!type1 || (type2.kind == classType && type1.kind != classType)))
8270             {
8271                if(type1 && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
8272                {
8273                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8274                   // Convert e.g. / 4 into / 4.0
8275                   exp.op.exp1.destType = type2._class.registered.dataType;
8276                   if(type2._class.registered.dataType)
8277                      type2._class.registered.dataType.refCount++;
8278                   CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8279                }
8280                if(exp.op.op == '!')
8281                {
8282                   exp.expType = MkClassType("bool");
8283                   exp.expType.truth = true;
8284                }
8285                else
8286                {
8287                   exp.expType = type2;
8288                   if(type2) type2.refCount++;
8289                }
8290             }
8291             else if(type1 && (!type2 || (type1.kind == classType && type2.kind != classType)))
8292             {
8293                if(type2 && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
8294                {
8295                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8296                   // Convert e.g. / 4 into / 4.0
8297                   exp.op.exp2.destType = type1._class.registered.dataType;
8298                   if(type1._class.registered.dataType)
8299                      type1._class.registered.dataType.refCount++;
8300                   CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8301                }
8302                exp.expType = type1;
8303                if(type1) type1.refCount++;
8304             }
8305          }
8306          
8307          yylloc = exp.loc;
8308          if(exp.op.exp1 && !exp.op.exp1.expType)
8309          {
8310             char expString[10000];
8311             expString[0] = '\0';
8312             if(inCompiler)
8313             {
8314                PrintExpression(exp.op.exp1, expString);
8315                ChangeCh(expString, '\n', ' ');
8316             }
8317             if(expString[0])
8318                Compiler_Error($"couldn't determine type of %s\n", expString);
8319          }
8320          if(exp.op.exp2 && !exp.op.exp2.expType)
8321          {
8322             char expString[10240];
8323             expString[0] = '\0';
8324             if(inCompiler)
8325             {
8326                PrintExpression(exp.op.exp2, expString);
8327                ChangeCh(expString, '\n', ' ');
8328             }
8329             if(expString[0])
8330                Compiler_Error($"couldn't determine type of %s\n", expString);
8331          }
8332
8333          if(boolResult)
8334          {
8335             FreeType(exp.expType);
8336             exp.expType = MkClassType("bool");
8337             exp.expType.truth = true;
8338          }
8339
8340          if(exp.op.op != SIZEOF)
8341             exp.isConstant = (!exp.op.exp1 || exp.op.exp1.isConstant) &&
8342                (!exp.op.exp2 || exp.op.exp2.isConstant);
8343
8344          if(exp.op.op == SIZEOF && exp.op.exp2.expType)
8345          {
8346             DeclareType(exp.op.exp2.expType, false, false);
8347          }
8348
8349          yylloc = oldyylloc;
8350
8351          FreeType(dummy);
8352          break;
8353       }
8354       case bracketsExp:
8355       case extensionExpressionExp:
8356       {
8357          Expression e;
8358          exp.isConstant = true;
8359          for(e = exp.list->first; e; e = e.next)
8360          {
8361             bool inced = false;
8362             if(!e.next)
8363             {
8364                FreeType(e.destType);
8365                e.destType = exp.destType;
8366                if(e.destType) { exp.destType.refCount++; e.destType.count++; inced = true; }
8367             }
8368             ProcessExpressionType(e);
8369             if(inced)
8370                exp.destType.count--;
8371             if(!exp.expType && !e.next)
8372             {
8373                exp.expType = e.expType;
8374                if(e.expType) e.expType.refCount++;
8375             }
8376             if(!e.isConstant)
8377                exp.isConstant = false;
8378          }
8379
8380          // In case a cast became a member...
8381          e = exp.list->first;
8382          if(!e.next && e.type == memberExp)
8383          {
8384             // Preserve prev, next
8385             Expression next = exp.next, prev = exp.prev;
8386
8387
8388             FreeType(exp.expType);
8389             FreeType(exp.destType);
8390             delete exp.list;
8391             
8392             *exp = *e;
8393
8394             exp.prev = prev;
8395             exp.next = next;
8396
8397             delete e;
8398
8399             ProcessExpressionType(exp);
8400          }
8401          break;
8402       }
8403       case indexExp:
8404       {
8405          Expression e;
8406          exp.isConstant = true;
8407
8408          ProcessExpressionType(exp.index.exp);
8409          if(!exp.index.exp.isConstant)
8410             exp.isConstant = false;
8411
8412          if(exp.index.exp.expType)
8413          {
8414             Type source = exp.index.exp.expType;
8415             if(source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
8416                eClass_IsDerived(source._class.registered, containerClass) && 
8417                source._class.registered.templateArgs)
8418             {
8419                Class _class = source._class.registered;
8420                exp.expType = ProcessTypeString(_class.templateArgs[2].dataTypeString, false);
8421
8422                if(exp.index.index && exp.index.index->last)
8423                {
8424                   ((Expression)exp.index.index->last).destType = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
8425                }
8426             }
8427          }
8428
8429          for(e = exp.index.index->first; e; e = e.next)
8430          {
8431             if(!e.next && exp.index.exp.expType && exp.index.exp.expType.kind == arrayType && exp.index.exp.expType.enumClass)
8432             {
8433                if(e.destType) FreeType(e.destType);
8434                e.destType = MkClassType(exp.index.exp.expType.enumClass.string);
8435             }
8436             ProcessExpressionType(e);
8437             if(!e.next)
8438             {
8439                // Check if this type is int
8440             }
8441             if(!e.isConstant)
8442                exp.isConstant = false;
8443          }
8444
8445          if(!exp.expType)
8446             exp.expType = Dereference(exp.index.exp.expType);
8447          if(exp.expType)
8448             DeclareType(exp.expType, false, false);
8449          break;
8450       }
8451       case callExp:
8452       {
8453          Expression e;
8454          Type functionType;
8455          Type methodType = null;
8456          char name[1024];
8457          name[0] = '\0';
8458
8459          if(inCompiler)
8460          {
8461             PrintExpression(exp.call.exp,  name);
8462             if(exp.call.exp.expType && !exp.call.exp.expType.returnType)
8463             {
8464                //exp.call.exp.expType = null;
8465                PrintExpression(exp.call.exp,  name);
8466             }
8467          }
8468          if(exp.call.exp.type == identifierExp)
8469          {
8470             Expression idExp = exp.call.exp;
8471             Identifier id = idExp.identifier;
8472             if(!strcmp(id.string, "__ENDIAN_PAD"))
8473             {
8474                exp.expType = ProcessTypeString("int", true);
8475                if(exp.call.arguments && exp.call.arguments->first)
8476                   ProcessExpressionType(exp.call.arguments->first);
8477                break;
8478             }
8479             else if(!strcmp(id.string, "Max") ||
8480                !strcmp(id.string, "Min") ||
8481                !strcmp(id.string, "Sgn") ||
8482                !strcmp(id.string, "Abs"))
8483             {
8484                Expression a = null;
8485                Expression b = null;
8486                Expression tempExp1 = null, tempExp2 = null;
8487                if((!strcmp(id.string, "Max") ||
8488                   !strcmp(id.string, "Min")) && exp.call.arguments->count == 2)
8489                {
8490                   a = exp.call.arguments->first;
8491                   b = exp.call.arguments->last;
8492                   tempExp1 = a;
8493                   tempExp2 = b;
8494                }
8495                else if(exp.call.arguments->count == 1)
8496                {
8497                   a = exp.call.arguments->first;
8498                   tempExp1 = a;
8499                }
8500                
8501                if(a)
8502                {
8503                   exp.call.arguments->Clear();
8504                   idExp.identifier = null;
8505
8506                   FreeExpContents(exp);
8507
8508                   ProcessExpressionType(a);
8509                   if(b)
8510                      ProcessExpressionType(b);
8511
8512                   exp.type = bracketsExp;
8513                   exp.list = MkList();
8514
8515                   if(a.expType && (!b || b.expType))
8516                   {
8517                      if((!a.isConstant && a.type != identifierExp) || (b && !b.isConstant && b.type != identifierExp))
8518                      {
8519                         // Use the simpleStruct name/ids for now...
8520                         if(inCompiler)
8521                         {
8522                            OldList * specs = MkList();
8523                            OldList * decls = MkList();
8524                            Declaration decl;
8525                            char temp1[1024], temp2[1024];
8526
8527                            GetTypeSpecs(a.expType, specs);
8528
8529                            if(a && !a.isConstant && a.type != identifierExp)
8530                            {
8531                               sprintf(temp1, "__simpleStruct%d", curContext.simpleID++);
8532                               ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp1)), null));
8533                               tempExp1 = QMkExpId(temp1);
8534                               tempExp1.expType = a.expType;
8535                               if(a.expType)
8536                                  a.expType.refCount++;
8537                               ListAdd(exp.list, MkExpOp(CopyExpression(tempExp1), '=', a));
8538                            }
8539                            if(b && !b.isConstant && b.type != identifierExp)
8540                            {
8541                               sprintf(temp2, "__simpleStruct%d", curContext.simpleID++);
8542                               ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp2)), null));
8543                               tempExp2 = QMkExpId(temp2);
8544                               tempExp2.expType = b.expType;
8545                               if(b.expType)
8546                                  b.expType.refCount++;
8547                               ListAdd(exp.list, MkExpOp(CopyExpression(tempExp2), '=', b));
8548                            }                        
8549
8550                            decl = MkDeclaration(specs, decls);
8551                            if(!curCompound.compound.declarations)
8552                               curCompound.compound.declarations = MkList();
8553                            curCompound.compound.declarations->Insert(null, decl);
8554                         }
8555                      }
8556                   }
8557
8558                   if(!strcmp(id.string, "Max") || !strcmp(id.string, "Min"))
8559                   {
8560                      int op = (!strcmp(id.string, "Max")) ? '>' : '<';
8561                      ListAdd(exp.list, 
8562                         MkExpCondition(MkExpBrackets(MkListOne(
8563                            MkExpOp(CopyExpression(tempExp1), op, CopyExpression(tempExp2)))),
8564                            MkListOne(CopyExpression(tempExp1)), CopyExpression(tempExp2)));
8565                      exp.expType = a.expType;
8566                      if(a.expType)
8567                         a.expType.refCount++;
8568                   }
8569                   else if(!strcmp(id.string, "Abs"))
8570                   {
8571                      ListAdd(exp.list, 
8572                         MkExpCondition(MkExpBrackets(MkListOne(
8573                            MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8574                            MkListOne(MkExpOp(null, '-', CopyExpression(tempExp1))), CopyExpression(tempExp1)));
8575                      exp.expType = a.expType;
8576                      if(a.expType)
8577                         a.expType.refCount++;
8578                   }
8579                   else if(!strcmp(id.string, "Sgn"))
8580                   {
8581                      // ((!(a))?(0):(((a)<0)?(-1):(1)))
8582                      ListAdd(exp.list, 
8583                         MkExpCondition(MkExpBrackets(MkListOne(
8584                            MkExpOp(null, '!', CopyExpression(tempExp1)))), MkListOne(MkExpConstant("0")),
8585                               MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(
8586                                  MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8587                                  MkListOne(MkExpConstant("-1")), MkExpConstant("1"))))));
8588                      exp.expType = ProcessTypeString("int", false);
8589                   }
8590
8591                   FreeExpression(tempExp1);
8592                   if(tempExp2) FreeExpression(tempExp2);
8593
8594                   FreeIdentifier(id);
8595                   break;
8596                }
8597             }
8598          }
8599
8600          {
8601             Type dummy
8602             {
8603                count = 1;
8604                refCount = 1;
8605             };
8606             if(!exp.call.exp.destType)
8607             {
8608                exp.call.exp.destType = dummy;
8609                dummy.refCount++;
8610             }
8611             ProcessExpressionType(exp.call.exp);
8612             if(exp.call.exp.destType == dummy)
8613             {
8614                FreeType(dummy);
8615                exp.call.exp.destType = null;
8616             }
8617             FreeType(dummy);
8618          }
8619
8620          // Check argument types against parameter types
8621          functionType = exp.call.exp.expType;
8622
8623          if(functionType && functionType.kind == TypeKind::methodType)
8624          {
8625             methodType = functionType;
8626             functionType = methodType.method.dataType;
8627             
8628             //if(functionType.returnType && functionType.returnType.kind == thisClassType)
8629             // TOCHECK: Instead of doing this here could this be done per param?
8630             if(exp.call.exp.expType.usedClass)
8631             {
8632                char typeString[1024];
8633                typeString[0] = '\0';
8634                PrintType(functionType, typeString, true, true);
8635                if(strstr(typeString, "thisclass"))
8636                {
8637                   OldList * specs = MkList();
8638                   Declarator decl;
8639                   {
8640                      Context context = SetupTemplatesContext(exp.call.exp.expType.usedClass);
8641
8642                      decl = SpecDeclFromString(typeString, specs, null);
8643                      
8644                      // SET THIS TO FALSE WHEN PROCESSING THISCLASS OUTSIDE THE CLASS
8645                      if(thisClass != (exp.call.exp.expType.usedClass.templateClass ? exp.call.exp.expType.usedClass.templateClass :
8646                         exp.call.exp.expType.usedClass))
8647                         thisClassParams = false;
8648                      
8649                      ReplaceThisClassSpecifiers(specs, exp.call.exp.expType.usedClass);
8650                      {
8651                         Class backupThisClass = thisClass;
8652                         thisClass = exp.call.exp.expType.usedClass;
8653                         ProcessDeclarator(decl);
8654                         thisClass = backupThisClass;
8655                      }
8656
8657                      thisClassParams = true;
8658
8659                      functionType = ProcessType(specs, decl);
8660                      functionType.refCount = 0;
8661                      FinishTemplatesContext(context);
8662                   }
8663
8664                   FreeList(specs, FreeSpecifier);
8665                   FreeDeclarator(decl);
8666                 }
8667             }
8668          }
8669          if(functionType && functionType.kind == pointerType && functionType.type && functionType.type.kind == TypeKind::functionType)
8670          {
8671             Type type = functionType.type;
8672             if(!functionType.refCount)
8673             {
8674                functionType.type = null;
8675                FreeType(functionType);
8676             }
8677             //methodType = functionType;
8678             functionType = type;
8679          }
8680          if(functionType && functionType.kind != TypeKind::functionType)
8681          {
8682             Compiler_Error($"called object %s is not a function\n", name);
8683          }
8684          else if(functionType)
8685          {
8686             bool emptyParams = false, noParams = false;
8687             Expression e = exp.call.arguments ? exp.call.arguments->first : null;
8688             Type type = functionType.params.first;
8689             Expression memberExp = (exp.call.exp.type == ExpressionType::memberExp) ? exp.call.exp : null;
8690             int extra = 0;
8691             Location oldyylloc = yylloc;
8692
8693             if(!type) emptyParams = true;
8694
8695             // WORKING ON THIS:
8696             if(functionType.extraParam && e)
8697             {
8698                e.destType = MkClassType(functionType.thisClass.string);
8699                e = e.next;
8700             }
8701
8702             // WHY WAS THIS COMMENTED OUT ? Broke DisplaySystem::FontExtent(this ? displaySystem : null, font, text, len, width, height);
8703             if(!functionType.staticMethod)
8704             {
8705                if(memberExp && memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.kind == subClassType && 
8706                   memberExp.member.exp.expType._class)
8707                {
8708                   type = MkClassType(memberExp.member.exp.expType._class.string);
8709                   if(e)
8710                   {
8711                      e.destType = type;
8712                      e = e.next;
8713                      type = functionType.params.first;
8714                   }
8715                   else
8716                      type.refCount = 0;
8717                }
8718                else if(!memberExp && (functionType.thisClass || (methodType && methodType.methodClass)))
8719                {
8720                   type = MkClassType(functionType.thisClass ? functionType.thisClass.string : (methodType ? methodType.methodClass.fullName : null));
8721                   if(e)
8722                   {
8723                      e.destType = type;
8724                      e = e.next;
8725                      type = functionType.params.first;
8726                   }
8727                   else
8728                      type.refCount = 0;
8729                   //extra = 1;
8730                }
8731             }
8732
8733             if(type && type.kind == voidType)
8734             {
8735                noParams = true;
8736                if(!type.refCount) FreeType(type);
8737                type = null;
8738             }
8739
8740             for( ; e; e = e.next)
8741             {
8742                if(!type && !emptyParams)
8743                {
8744                   yylloc = e.loc;
8745                   if(methodType && methodType.methodClass)
8746                      Compiler_Error($"too many arguments for method %s::%s (%d given, expected %d)\n",
8747                         methodType.methodClass.fullName, methodType.method.name, exp.call.arguments->count,
8748                         noParams ? 0 : functionType.params.count);
8749                   else
8750                      Compiler_Error($"too many arguments for function %s (%d given, expected %d)\n",
8751                         name /*exp.call.exp.identifier.string*/, exp.call.arguments->count,
8752                         noParams ? 0 : functionType.params.count);
8753                   break;
8754                }
8755
8756                if(methodType && type && type.kind == templateType && type.templateParameter.type == TemplateParameterType::type)
8757                {
8758                   Type templatedType = null;
8759                   Class _class = methodType.usedClass;
8760                   ClassTemplateParameter curParam = null;
8761                   int id = 0;
8762                   if(_class && _class.templateArgs /*&& _class.templateClass*/)
8763                   {
8764                      Class sClass;
8765                      for(sClass = _class; sClass; sClass = sClass.base)
8766                      {
8767                         if(sClass.templateClass) sClass = sClass.templateClass;
8768                         id = 0;
8769                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
8770                         {
8771                            if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
8772                            {
8773                               Class nextClass;
8774                               for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
8775                               {
8776                                  if(nextClass.templateClass) nextClass = nextClass.templateClass;
8777                                  id += nextClass.templateParams.count;
8778                               }
8779                               break;
8780                            }
8781                            id++;
8782                         }
8783                         if(curParam) break;
8784                      }
8785                   }
8786                   if(curParam && _class.templateArgs[id].dataTypeString)
8787                   {
8788                      ClassTemplateArgument arg = _class.templateArgs[id];
8789                      {
8790                         Context context = SetupTemplatesContext(_class);
8791                      
8792                         /*if(!arg.dataType)
8793                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
8794                         templatedType = ProcessTypeString(arg.dataTypeString, false);
8795                         FinishTemplatesContext(context);
8796                      }
8797                      e.destType = templatedType;
8798                      if(templatedType)
8799                      {
8800                         templatedType.passAsTemplate = true;
8801                         // templatedType.refCount++;
8802                      }
8803                   }
8804                   else
8805                   {
8806                      e.destType = type;
8807                      if(type) type.refCount++;
8808                   }
8809                }
8810                else
8811                {
8812                   e.destType = type;
8813                   if(type) type.refCount++;
8814                }
8815                // Don't reach the end for the ellipsis
8816                if(type && type.kind != ellipsisType)
8817                {
8818                   Type next = type.next;
8819                   if(!type.refCount) FreeType(type);
8820                   type = next;
8821                }
8822             }
8823
8824             if(type && type.kind != ellipsisType)
8825             {
8826                if(methodType && methodType.methodClass)
8827                   Compiler_Warning($"not enough arguments for method %s::%s (%d given, expected %d)\n",
8828                      methodType.methodClass.fullName, methodType.method.name, exp.call.arguments ? exp.call.arguments->count : 0,
8829                      functionType.params.count + extra);
8830                else
8831                   Compiler_Warning($"not enough arguments for function %s (%d given, expected %d)\n",
8832                      name /*exp.call.exp.identifier.string*/, exp.call.arguments ? exp.call.arguments->count : 0,
8833                      functionType.params.count + extra);
8834             }
8835             yylloc = oldyylloc;
8836             if(type && !type.refCount) FreeType(type);
8837          }
8838          else
8839          {
8840             functionType = Type
8841             {
8842                refCount = 0;
8843                kind = TypeKind::functionType;
8844             };
8845
8846             if(exp.call.exp.type == identifierExp)
8847             {
8848                char * string = exp.call.exp.identifier.string;
8849                if(inCompiler)
8850                {
8851                   Symbol symbol;
8852                   Location oldyylloc = yylloc;
8853
8854                   yylloc = exp.call.exp.identifier.loc;
8855                   if(strstr(string, "__builtin_") == string);
8856                   else
8857                      Compiler_Warning($"%s undefined; assuming extern returning int\n", string);
8858                   symbol = Symbol { string = CopyString(string), type = ProcessTypeString("int()", true) };
8859                   globalContext.symbols.Add((BTNode)symbol);
8860                   if(strstr(symbol.string, "::"))
8861                      globalContext.hasNameSpace = true;
8862
8863                   yylloc = oldyylloc;
8864                }
8865             }
8866             else if(exp.call.exp.type == memberExp)
8867             {
8868                /*Compiler_Warning($"%s undefined; assuming returning int\n",
8869                   exp.call.exp.member.member.string);*/
8870             }
8871             else
8872                Compiler_Warning($"callable object undefined; extern assuming returning int\n");
8873
8874             if(!functionType.returnType)
8875             {
8876                functionType.returnType = Type
8877                {
8878                   refCount = 1;
8879                   kind = intType;
8880                };
8881             }
8882          }
8883          if(functionType && functionType.kind == TypeKind::functionType)
8884          {
8885             exp.expType = functionType.returnType;
8886
8887             if(functionType.returnType)
8888                functionType.returnType.refCount++;
8889
8890             if(!functionType.refCount)
8891                FreeType(functionType);
8892          }
8893
8894          if(exp.call.arguments)
8895          {
8896             for(e = exp.call.arguments->first; e; e = e.next)
8897             {
8898                Type destType = e.destType;
8899                ProcessExpressionType(e);
8900             }
8901          }
8902          break;
8903       }
8904       case memberExp:
8905       {
8906          Type type;
8907          Location oldyylloc = yylloc;
8908          bool thisPtr = (exp.member.exp && exp.member.exp.type == identifierExp && !strcmp(exp.member.exp.identifier.string, "this"));
8909          exp.thisPtr = thisPtr;
8910
8911          // DOING THIS LATER NOW...
8912          if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
8913          {
8914             exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
8915             /* TODO: Name Space Fix ups
8916             if(!exp.member.member.classSym)
8917                exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.fullName);
8918             */
8919          }
8920
8921          ProcessExpressionType(exp.member.exp);
8922          if(exp.member.exp.expType && exp.member.exp.expType.kind == classType && exp.member.exp.expType._class && 
8923             exp.member.exp.expType._class.registered && exp.member.exp.expType._class.registered.type == normalClass)
8924          {
8925             exp.isConstant = false;
8926          }
8927          else
8928             exp.isConstant = exp.member.exp.isConstant;
8929          type = exp.member.exp.expType;
8930
8931          yylloc = exp.loc;
8932
8933          if(type && (type.kind == templateType))
8934          {
8935             Class _class = thisClass ? thisClass : currentClass;
8936             ClassTemplateParameter param = null;
8937             if(_class)
8938             {
8939                for(param = _class.templateParams.first; param; param = param.next)
8940                {
8941                   if(param.type == identifier && exp.member.member && exp.member.member.string && !strcmp(param.name, exp.member.member.string))
8942                      break;
8943                }
8944             }
8945             if(param && param.defaultArg.member)
8946             {
8947                Expression argExp = GetTemplateArgExpByName(param.name, thisClass, TemplateParameterType::identifier);
8948                if(argExp)
8949                {
8950                   Expression expMember = exp.member.exp;
8951                   Declarator decl;
8952                   OldList * specs = MkList();
8953                   char thisClassTypeString[1024];
8954
8955                   FreeIdentifier(exp.member.member);
8956
8957                   ProcessExpressionType(argExp);
8958
8959                   {
8960                      char * colon = strstr(param.defaultArg.memberString, "::");
8961                      if(colon)
8962                      {
8963                         char className[1024];
8964                         Class sClass;
8965
8966                         memcpy(thisClassTypeString, param.defaultArg.memberString, colon - param.defaultArg.memberString);
8967                         thisClassTypeString[colon - param.defaultArg.memberString] = '\0';
8968                      }
8969                      else
8970                         strcpy(thisClassTypeString, _class.fullName);
8971                   }
8972
8973                   decl = SpecDeclFromString(param.defaultArg.member.dataTypeString, specs, null);
8974
8975                   exp.expType = ProcessType(specs, decl);
8976                   if(exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.templateClass)
8977                   {
8978                      Class expClass = exp.expType._class.registered;
8979                      Class cClass = null;
8980                      int c;
8981                      int paramCount = 0;
8982                      int lastParam = -1;
8983                      
8984                      char templateString[1024];
8985                      ClassTemplateParameter param;
8986                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
8987                      for(cClass = expClass; cClass; cClass = cClass.base)
8988                      {
8989                         int p = 0;
8990                         for(param = cClass.templateParams.first; param; param = param.next)
8991                         {
8992                            int id = p;
8993                            Class sClass;
8994                            ClassTemplateArgument arg;
8995                            for(sClass = cClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
8996                            arg = expClass.templateArgs[id];
8997
8998                            for(sClass = _class /*expClass*/; sClass; sClass = sClass.base)
8999                            {
9000                               ClassTemplateParameter cParam;
9001                               //int p = numParams - sClass.templateParams.count;
9002                               int p = 0;
9003                               Class nextClass;
9004                               for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
9005                               
9006                               for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
9007                               {
9008                                  if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
9009                                  {
9010                                     if(_class.templateArgs && arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9011                                     {
9012                                        arg.dataTypeString = _class.templateArgs[p].dataTypeString;
9013                                        arg.dataTypeClass = _class.templateArgs[p].dataTypeClass;
9014                                        break;
9015                                     }
9016                                  }
9017                               }
9018                            }
9019
9020                            {
9021                               char argument[256];
9022                               argument[0] = '\0';
9023                               /*if(arg.name)
9024                               {
9025                                  strcat(argument, arg.name.string);
9026                                  strcat(argument, " = ");
9027                               }*/
9028                               switch(param.type)
9029                               {
9030                                  case expression:
9031                                  {
9032                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
9033                                     char expString[1024];
9034                                     OldList * specs = MkList();
9035                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
9036                                     Expression exp;
9037                                     char * string = PrintHexUInt64(arg.expression.ui64);
9038                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
9039
9040                                     ProcessExpressionType(exp);
9041                                     ComputeExpression(exp);
9042                                     expString[0] = '\0';
9043                                     PrintExpression(exp, expString);
9044                                     strcat(argument, expString);
9045                                     // delete exp;
9046                                     FreeExpression(exp);
9047                                     break;
9048                                  }
9049                                  case identifier:
9050                                  {
9051                                     strcat(argument, arg.member.name);
9052                                     break;
9053                                  }
9054                                  case TemplateParameterType::type:
9055                                  {
9056                                     if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9057                                     {
9058                                        if(!strcmp(arg.dataTypeString, "thisclass"))
9059                                           strcat(argument, thisClassTypeString);
9060                                        else
9061                                           strcat(argument, arg.dataTypeString);
9062                                     }
9063                                     break;
9064                                  }
9065                               }
9066                               if(argument[0])
9067                               {
9068                                  if(paramCount) strcat(templateString, ", ");
9069                                  if(lastParam != p - 1)
9070                                  {
9071                                     strcat(templateString, param.name);
9072                                     strcat(templateString, " = ");
9073                                  }
9074                                  strcat(templateString, argument);
9075                                  paramCount++;
9076                                  lastParam = p;
9077                               }
9078                               p++;
9079                            }               
9080                         }
9081                      }
9082                      {
9083                         int len = strlen(templateString);
9084                         if(templateString[len-1] == '>') templateString[len++] = ' ';
9085                         templateString[len++] = '>';
9086                         templateString[len++] = '\0';
9087                      }
9088                      {
9089                         Context context = SetupTemplatesContext(_class);
9090                         FreeType(exp.expType);
9091                         exp.expType = ProcessTypeString(templateString, false);
9092                         FinishTemplatesContext(context);
9093                      }                     
9094                   }
9095
9096                   // *([expType] *)(((byte *)[exp.member.exp]) + [argExp].member.offset)
9097                   exp.type = bracketsExp;
9098                   exp.list = MkListOne(MkExpOp(null, '*',
9099                   /*opExp;
9100                   exp.op.op = '*';
9101                   exp.op.exp1 = null;
9102                   exp.op.exp2 = */
9103                   MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpBrackets(MkListOne(MkExpOp(
9104                      MkExpBrackets(MkListOne(
9105                         MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), expMember))),
9106                            '+',  
9107                            MkExpOp(MkExpMember(MkExpMember(argExp, MkIdentifier("member")), MkIdentifier("offset")), 
9108                            '+',
9109                            MkExpMember(MkExpMember(MkExpMember(CopyExpression(argExp), MkIdentifier("member")), MkIdentifier("_class")), MkIdentifier("offset")))))))
9110                            
9111                            ));
9112                }
9113             }
9114             else if(type.templateParameter && type.templateParameter.type == TemplateParameterType::type && 
9115                (type.templateParameter.dataType || type.templateParameter.dataTypeString))
9116             {
9117                type = ProcessTemplateParameterType(type.templateParameter);
9118             }
9119          }
9120
9121          if(type && (type.kind == templateType));
9122          else if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9123          {
9124             Identifier id = exp.member.member;
9125             TypeKind typeKind = type.kind;
9126             Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9127             if(typeKind == subClassType && exp.member.exp.type == classExp)
9128             {
9129                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
9130                typeKind = classType;
9131             }
9132
9133             if(id && (typeKind == intType || typeKind == enumType))
9134                _class = eSystem_FindClass(privateModule, "int");
9135
9136             if(_class && id)
9137             {
9138                /*bool thisPtr = 
9139                   (exp.member.exp.type == identifierExp && 
9140                   !strcmp(exp.member.exp.identifier.string, "this"));*/
9141                Property prop = null;
9142                Method method = null;
9143                DataMember member = null;
9144                Property revConvert = null;
9145                ClassProperty classProp = null;
9146
9147                if(id && id._class && id._class.name && !strcmp(id._class.name, "property"))
9148                   exp.member.memberType = propertyMember;
9149
9150                if(id && id._class && type._class && !eClass_IsDerived(type._class.registered, _class))
9151                   Compiler_Error($"invalid class specifier %s for object of class %s\n", _class.fullName, type._class.string);
9152
9153                if(typeKind != subClassType)
9154                {
9155                   // Prioritize data members over properties for "this"
9156                   if((exp.member.memberType == unresolvedMember && thisPtr) || exp.member.memberType == dataMember)
9157                   {
9158                      member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9159                      if(member && member._class != (_class.templateClass ? _class.templateClass : _class) && exp.member.memberType != dataMember)
9160                      {
9161                         prop = eClass_FindProperty(_class, id.string, privateModule);
9162                         if(prop)
9163                            member = null;
9164                      }
9165                      if(!member && !prop)
9166                         prop = eClass_FindProperty(_class, id.string, privateModule);
9167                      if((member && member._class == (_class.templateClass ? _class.templateClass : _class)) ||
9168                         (prop && prop._class == (_class.templateClass ? _class.templateClass : _class)))
9169                         exp.member.thisPtr = true;
9170                   }
9171                   // Prioritize properties over data members otherwise
9172                   else
9173                   {
9174                      // First look for Public Members (Unless class specifier is provided, which skips public priority)
9175                      if(!id.classSym)
9176                      {
9177                         prop = eClass_FindProperty(_class, id.string, null);
9178                         if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9179                            member = eClass_FindDataMember(_class, id.string, null, null, null);
9180                      }
9181
9182                      if(!prop && !member)
9183                      {
9184                         method = eClass_FindMethod(_class, id.string, null);
9185                         if(!method)
9186                         {
9187                            prop = eClass_FindProperty(_class, id.string, privateModule);
9188                            if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9189                               member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9190                         }
9191                      }
9192
9193                      if(member && prop)
9194                      {
9195                         if(member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class))
9196                            prop = null;
9197                         else
9198                            member = null;
9199                      }
9200                   }
9201                }
9202                if(!prop && !member)
9203                   method = eClass_FindMethod(_class, id.string, privateModule);
9204                if(!prop && !member && !method)
9205                {
9206                   if(typeKind == subClassType)
9207                   {
9208                      classProp = eClass_FindClassProperty(type._class.registered, exp.member.member.string);
9209                      if(classProp)
9210                      {
9211                         exp.member.memberType = classPropertyMember;
9212                         exp.expType = ProcessTypeString(classProp.dataTypeString, false);
9213                      }
9214                      else
9215                      {
9216                         // Assume this is a class_data member
9217                         char structName[1024];
9218                         Identifier id = exp.member.member;
9219                         Expression classExp = exp.member.exp;
9220                         type.refCount++;
9221
9222                         FreeType(classExp.expType);
9223                         classExp.expType = ProcessTypeString("ecere::com::Class", false);
9224                      
9225                         strcpy(structName, "__ecereClassData_");
9226                         FullClassNameCat(structName, type._class.string, false);
9227                         exp.type = pointerExp;
9228                         exp.member.member = id;
9229
9230                         exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9231                            MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), 
9232                               MkExpBrackets(MkListOne(MkExpOp(
9233                                  MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)), 
9234                                     MkExpMember(classExp, MkIdentifier("data"))), '+',
9235                                        MkExpMember(MkExpClass(MkListOne(MkSpecifierName(type._class.string)), null), MkIdentifier("offsetClass")))))
9236                                  )));
9237
9238                         FreeType(type);
9239
9240                         ProcessExpressionType(exp);
9241                         return;
9242                      }
9243                   }
9244                   else
9245                   {
9246                      // Check for reverse conversion
9247                      // (Convert in an instantiation later, so that we can use
9248                      //  deep properties system)
9249                      Symbol classSym = FindClass(id.string);
9250                      if(classSym)
9251                      {
9252                         Class convertClass = classSym.registered;
9253                         if(convertClass)
9254                            revConvert = eClass_FindProperty(convertClass, _class.fullName, privateModule);
9255                      }
9256                   }
9257                }
9258       
9259                if(prop)
9260                {
9261                   exp.member.memberType = propertyMember;
9262                   if(!prop.dataType)
9263                      ProcessPropertyType(prop);
9264                   exp.expType = prop.dataType;                     
9265                   if(prop.dataType) prop.dataType.refCount++;
9266                }
9267                else if(member)
9268                {
9269                   if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9270                   {
9271                      FreeExpContents(exp);
9272                      exp.type = identifierExp;
9273                      exp.identifier = MkIdentifier("class");
9274                      ProcessExpressionType(exp);
9275                      return;
9276                   }
9277
9278                   exp.member.memberType = dataMember;
9279                   DeclareStruct(_class.fullName, false);
9280                   if(!member.dataType)
9281                   {
9282                      Context context = SetupTemplatesContext(_class);
9283                      member.dataType = ProcessTypeString(member.dataTypeString, false);
9284                      FinishTemplatesContext(context);
9285                   }
9286                   exp.expType = member.dataType;
9287                   if(member.dataType) member.dataType.refCount++;
9288                }
9289                else if(revConvert)
9290                {
9291                   exp.member.memberType = reverseConversionMember;
9292                   exp.expType = MkClassType(revConvert._class.fullName);
9293                }
9294                else if(method)
9295                {
9296                   if(inCompiler)
9297                   {
9298                      /*if(id._class)
9299                      {
9300                         exp.type = identifierExp;
9301                         exp.identifier = exp.member.member;
9302                      }
9303                      else*/
9304                         exp.member.memberType = methodMember;
9305                   }
9306                   if(!method.dataType)
9307                      ProcessMethodType(method);
9308                   exp.expType = Type
9309                   {
9310                      refCount = 1;
9311                      kind = methodType;
9312                      method = method;
9313                   };
9314
9315                   // Tricky spot here... To use instance versus class virtual table
9316                   // Put it back to what it was... What did we break?
9317
9318                   // Had to put it back for overriding Main of Thread global instance
9319
9320                   //exp.expType.methodClass = _class;
9321                   exp.expType.methodClass = (id && id._class) ? _class : null;
9322
9323                   // Need the actual class used for templated classes
9324                   exp.expType.usedClass = _class;
9325                }
9326                else if(!classProp)
9327                {
9328                   if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9329                   {
9330                      FreeExpContents(exp);
9331                      exp.type = identifierExp;
9332                      exp.identifier = MkIdentifier("class");
9333                      ProcessExpressionType(exp);
9334                      return;
9335                   }
9336                   yylloc = exp.member.member.loc;
9337                   Compiler_Error($"couldn't find member %s in class %s\n", id.string, _class.fullName);
9338                   if(inCompiler)
9339                      eClass_AddDataMember(_class, id.string, "int", 0, 0, publicAccess);
9340                }
9341
9342                if(_class && /*(_class.templateClass || _class.templateArgs) && */exp.expType)
9343                {
9344                   Class tClass;
9345
9346                   tClass = _class;
9347                   while(tClass && !tClass.templateClass) tClass = tClass.base;
9348
9349                   if(tClass && exp.expType.kind == templateType && exp.expType.templateParameter.type == TemplateParameterType::type)
9350                   {
9351                      int id = 0;
9352                      ClassTemplateParameter curParam = null;
9353                      Class sClass;
9354
9355                      for(sClass = tClass; sClass; sClass = sClass.base)
9356                      {
9357                         id = 0;
9358                         if(sClass.templateClass) sClass = sClass.templateClass;
9359                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9360                         {
9361                            if(curParam.type == TemplateParameterType::type && !strcmp(exp.expType.templateParameter.identifier.string, curParam.name))
9362                            {
9363                               for(sClass = sClass.base; sClass; sClass = sClass.base)
9364                                  id += sClass.templateParams.count;
9365                               break;
9366                            }
9367                            id++;
9368                         }
9369                         if(curParam) break;
9370                      }
9371
9372                      if(curParam && tClass.templateArgs[id].dataTypeString)
9373                      {
9374                         ClassTemplateArgument arg = tClass.templateArgs[id];
9375                         Context context = SetupTemplatesContext(tClass);
9376                         /*if(!arg.dataType)
9377                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9378                         FreeType(exp.expType);
9379                         exp.expType = ProcessTypeString(arg.dataTypeString, false);
9380                         if(exp.expType)
9381                         {
9382                            if(exp.expType.kind == thisClassType)
9383                            {
9384                               FreeType(exp.expType);
9385                               exp.expType = ReplaceThisClassType(_class);
9386                            }
9387
9388                            if(tClass.templateClass)
9389                               exp.expType.passAsTemplate = true;
9390                            //exp.expType.refCount++;
9391                            if(!exp.destType)
9392                            {
9393                               exp.destType = ProcessTypeString(arg.dataTypeString, false);
9394                               //exp.destType.refCount++;
9395
9396                               if(exp.destType.kind == thisClassType)
9397                               {
9398                                  FreeType(exp.destType);
9399                                  exp.destType = ReplaceThisClassType(_class);
9400                               }
9401                            }
9402                         }
9403                         FinishTemplatesContext(context);
9404                      }
9405                   }
9406                   // TODO: MORE GENERIC SUPPORT FOR DEEPER TYPES
9407                   else if(tClass && exp.expType.kind == pointerType && exp.expType.type && exp.expType.type.kind == templateType && exp.expType.type.templateParameter.type == TemplateParameterType::type)
9408                   {
9409                      int id = 0;
9410                      ClassTemplateParameter curParam = null;
9411                      Class sClass;
9412
9413                      for(sClass = tClass; sClass; sClass = sClass.base)
9414                      {
9415                         id = 0;
9416                         if(sClass.templateClass) sClass = sClass.templateClass;
9417                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9418                         {
9419                            if(curParam.type == TemplateParameterType::type && 
9420                               !strcmp(exp.expType.type.templateParameter.identifier.string, curParam.name))
9421                            {
9422                               for(sClass = sClass.base; sClass; sClass = sClass.base)
9423                                  id += sClass.templateParams.count;
9424                               break;
9425                            }
9426                            id++;
9427                         }
9428                         if(curParam) break;
9429                      }
9430
9431                      if(curParam)
9432                      {
9433                         ClassTemplateArgument arg = tClass.templateArgs[id];
9434                         Context context = SetupTemplatesContext(tClass);
9435                         Type basicType;
9436                         /*if(!arg.dataType)
9437                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9438                         
9439                         basicType = ProcessTypeString(arg.dataTypeString, false);
9440                         if(basicType)
9441                         {
9442                            if(basicType.kind == thisClassType)
9443                            {
9444                               FreeType(basicType);
9445                               basicType = ReplaceThisClassType(_class);
9446                            }
9447
9448                            /*    DO WE REALLY WANT THIS HERE? IT SEEMS TO BE ONLY USED WITH Array::array which was causing bug 135
9449                            if(tClass.templateClass)
9450                               basicType.passAsTemplate = true;
9451                            */
9452                            
9453                            FreeType(exp.expType);
9454
9455                            exp.expType = Type { refCount = 1, kind = pointerType, type = basicType };
9456                            //exp.expType.refCount++;
9457                            if(!exp.destType)
9458                            {
9459                               exp.destType = exp.expType;
9460                               exp.destType.refCount++;
9461                            }
9462
9463                            {
9464                               Expression newExp { };
9465                               OldList * specs = MkList();
9466                               Declarator decl;
9467                               decl = SpecDeclFromString(arg.dataTypeString, specs, null);
9468                               *newExp = *exp;
9469                               if(exp.destType) exp.destType.refCount++;
9470                               if(exp.expType)  exp.expType.refCount++;
9471                               exp.type = castExp;
9472                               exp.cast.typeName = MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl));
9473                               exp.cast.exp = newExp;
9474                               //FreeType(exp.expType);
9475                               //exp.expType = null;
9476                               //ProcessExpressionType(sourceExp);
9477                            }
9478                         }
9479                         FinishTemplatesContext(context);
9480                      }
9481                   }
9482                   else if(tClass && exp.expType.kind == classType && exp.expType._class && strchr(exp.expType._class.string, '<'))
9483                   {
9484                      Class expClass = exp.expType._class.registered;
9485                      if(expClass)
9486                      {
9487                         Class cClass = null;
9488                         int c;
9489                         int p = 0;
9490                         int paramCount = 0;
9491                         int lastParam = -1;
9492                         char templateString[1024];
9493                         ClassTemplateParameter param;
9494                         sprintf(templateString, "%s<", expClass.templateClass.fullName);
9495                         while(cClass != expClass)
9496                         {
9497                            Class sClass;
9498                            for(sClass = expClass; sClass && sClass.base != cClass; sClass = sClass.base);
9499                            cClass = sClass;
9500
9501                            for(param = cClass.templateParams.first; param; param = param.next)
9502                            {
9503                               Class cClassCur = null;
9504                               int c;
9505                               int cp = 0;
9506                               ClassTemplateParameter paramCur = null;
9507                               ClassTemplateArgument arg;
9508                               while(cClassCur != tClass && !paramCur)
9509                               {
9510                                  Class sClassCur;
9511                                  for(sClassCur = tClass; sClassCur && sClassCur.base != cClassCur; sClassCur = sClassCur.base);
9512                                  cClassCur = sClassCur;
9513
9514                                  for(paramCur = cClassCur.templateParams.first; paramCur; paramCur = paramCur.next)
9515                                  {
9516                                     if(!strcmp(paramCur.name, param.name))
9517                                     {
9518                                        
9519                                        break;
9520                                     }
9521                                     cp++;
9522                                  }
9523                               }
9524                               if(paramCur && paramCur.type == TemplateParameterType::type)
9525                                  arg = tClass.templateArgs[cp];
9526                               else
9527                                  arg = expClass.templateArgs[p];
9528
9529                               {
9530                                  char argument[256];
9531                                  argument[0] = '\0';
9532                                  /*if(arg.name)
9533                                  {
9534                                     strcat(argument, arg.name.string);
9535                                     strcat(argument, " = ");
9536                                  }*/
9537                                  switch(param.type)
9538                                  {
9539                                     case expression:
9540                                     {
9541                                        // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
9542                                        char expString[1024];
9543                                        OldList * specs = MkList();
9544                                        Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
9545                                        Expression exp;
9546                                        char * string = PrintHexUInt64(arg.expression.ui64);
9547                                        exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
9548
9549                                        ProcessExpressionType(exp);
9550                                        ComputeExpression(exp);
9551                                        expString[0] = '\0';
9552                                        PrintExpression(exp, expString);
9553                                        strcat(argument, expString);
9554                                        // delete exp;
9555                                        FreeExpression(exp);
9556                                        break;
9557                                     }
9558                                     case identifier:
9559                                     {
9560                                        strcat(argument, arg.member.name);
9561                                        break;
9562                                     }
9563                                     case TemplateParameterType::type:
9564                                     {
9565                                        if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9566                                           strcat(argument, arg.dataTypeString);
9567                                        break;
9568                                     }
9569                                  }
9570                                  if(argument[0])
9571                                  {
9572                                     if(paramCount) strcat(templateString, ", ");
9573                                     if(lastParam != p - 1)
9574                                     {
9575                                        strcat(templateString, param.name);
9576                                        strcat(templateString, " = ");
9577                                     }                                       
9578                                     strcat(templateString, argument);
9579                                     paramCount++;
9580                                     lastParam = p;
9581                                  }
9582                               }
9583                               p++;
9584                            }
9585                         }
9586                         {
9587                            int len = strlen(templateString);
9588                            if(templateString[len-1] == '>') templateString[len++] = ' ';
9589                            templateString[len++] = '>';
9590                            templateString[len++] = '\0';
9591                         }
9592
9593                         FreeType(exp.expType);
9594                         {
9595                            Context context = SetupTemplatesContext(tClass);
9596                            exp.expType = ProcessTypeString(templateString, false);
9597                            FinishTemplatesContext(context);
9598                         }
9599                      }
9600                   }
9601                }
9602             }
9603             else
9604                Compiler_Error($"undefined class %s\n", (id && (!id._class || id._class.name))? (id.classSym ? id.classSym.string : (type._class ? type._class.string : null)) : "(null)");
9605          }
9606          else if(type && (type.kind == structType || type.kind == unionType))
9607          {
9608             Type memberType = exp.member.member ? FindMember(type, exp.member.member.string) : null;
9609             if(memberType)
9610             {
9611                exp.expType = memberType;
9612                if(memberType)
9613                   memberType.refCount++;
9614             }
9615          }
9616          else 
9617          {
9618             char expString[10240];
9619             expString[0] = '\0';
9620             if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
9621             Compiler_Error($"member operator on non-structure type expression %s\n", expString);
9622          }
9623
9624          if(exp.expType && exp.expType.kind == thisClassType && (!exp.destType || exp.destType.kind != thisClassType))
9625          {
9626             if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9627             {
9628                Identifier id = exp.member.member;
9629                Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9630                if(_class)
9631                {
9632                   FreeType(exp.expType);
9633                   exp.expType = ReplaceThisClassType(_class);
9634                }
9635             }
9636          }         
9637          yylloc = oldyylloc;
9638          break;
9639       }
9640       // Convert x->y into (*x).y
9641       case pointerExp:
9642       {
9643          Type destType = exp.destType;
9644
9645          // DOING THIS LATER NOW...
9646          if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
9647          {
9648             exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
9649             /* TODO: Name Space Fix ups
9650             if(!exp.member.member.classSym)
9651                exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.name);
9652             */
9653          }
9654
9655          exp.member.exp = MkExpBrackets(MkListOne(MkExpOp(null, '*', exp.member.exp)));
9656          exp.type = memberExp;
9657          if(destType)
9658             destType.count++;
9659          ProcessExpressionType(exp);
9660          if(destType)
9661             destType.count--;
9662          break;
9663       }
9664       case classSizeExp:
9665       {
9666          //ComputeExpression(exp);
9667
9668          Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
9669          if(classSym && classSym.registered)
9670          {
9671             if(classSym.registered.type == noHeadClass)
9672             {
9673                char name[1024];
9674                name[0] = '\0';
9675                DeclareStruct(classSym.string, false);
9676                FreeSpecifier(exp._class);
9677                exp.type = typeSizeExp;
9678                FullClassNameCat(name, classSym.string, false);
9679                exp.typeName = MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null);
9680             }
9681             else
9682             {
9683                if(classSym.registered.fixed)
9684                {
9685                   FreeSpecifier(exp._class);
9686                   exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
9687                   exp.type = constantExp;
9688                }
9689                else
9690                {
9691                   char className[1024];
9692                   strcpy(className, "__ecereClass_");
9693                   FullClassNameCat(className, classSym.string, true);
9694                   MangleClassName(className);
9695
9696                   DeclareClass(classSym, className);
9697
9698                   FreeExpContents(exp);
9699                   exp.type = pointerExp;
9700                   exp.member.exp = MkExpIdentifier(MkIdentifier(className));
9701                   exp.member.member = MkIdentifier("structSize");
9702                }
9703             }
9704          }
9705
9706          exp.expType = Type
9707          {
9708             refCount = 1;
9709             kind = intType;
9710          };
9711          // exp.isConstant = true;
9712          break;
9713       }
9714       case typeSizeExp:
9715       {
9716          Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
9717
9718          exp.expType = Type
9719          {
9720             refCount = 1;
9721             kind = intType;
9722          };
9723          exp.isConstant = true;
9724
9725          DeclareType(type, false, false);
9726          FreeType(type);
9727          break;
9728       }
9729       case castExp:
9730       {
9731          Type type = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
9732          type.count = 1;
9733          FreeType(exp.cast.exp.destType);
9734          exp.cast.exp.destType = type;
9735          type.refCount++;
9736          ProcessExpressionType(exp.cast.exp);
9737          type.count = 0;
9738          exp.expType = type;
9739          //type.refCount++;
9740          
9741          // if(!NeedCast(exp.cast.exp.expType, exp.cast.exp.destType))
9742          if(!exp.cast.exp.needCast && !NeedCast(exp.cast.exp.expType, type))
9743          {
9744             void * prev = exp.prev, * next = exp.next;
9745             Type expType = exp.cast.exp.destType;
9746             Expression castExp = exp.cast.exp;
9747             Type destType = exp.destType;
9748
9749             if(expType) expType.refCount++;
9750
9751             //FreeType(exp.destType);
9752             FreeType(exp.expType);
9753             FreeTypeName(exp.cast.typeName);
9754             
9755             *exp = *castExp;
9756             FreeType(exp.expType);
9757             FreeType(exp.destType);
9758
9759             exp.expType = expType;
9760             exp.destType = destType;
9761
9762             delete castExp;
9763
9764             exp.prev = prev;
9765             exp.next = next;
9766
9767          }
9768          else
9769          {
9770             exp.isConstant = exp.cast.exp.isConstant;
9771          }
9772          //FreeType(type);
9773          break;
9774       }
9775       case extensionInitializerExp:
9776       {
9777          Type type = ProcessType(exp.initializer.typeName.qualifiers, exp.initializer.typeName.declarator);
9778          type.refCount++;
9779
9780          // We have yet to support this... ( { } initializers are currently processed inside ProcessDeclaration()'s initDeclaration case statement
9781          // ProcessInitializer(exp.initializer.initializer, type);
9782          exp.expType = type;
9783          break;
9784       }
9785       case vaArgExp:
9786       {
9787          Type type = ProcessType(exp.vaArg.typeName.qualifiers, exp.vaArg.typeName.declarator);
9788          ProcessExpressionType(exp.vaArg.exp);
9789          type.refCount++;
9790          exp.expType = type;
9791          break;
9792       }
9793       case conditionExp:
9794       {
9795          Expression e;
9796          exp.isConstant = true;
9797
9798          FreeType(exp.cond.cond.destType);
9799          exp.cond.cond.destType = MkClassType("bool");
9800          exp.cond.cond.destType.truth = true;
9801          ProcessExpressionType(exp.cond.cond);
9802          if(!exp.cond.cond.isConstant)
9803             exp.isConstant = false;
9804          for(e = exp.cond.exp->first; e; e = e.next)
9805          {
9806             if(!e.next)
9807             {
9808                FreeType(e.destType);
9809                e.destType = exp.destType;
9810                if(e.destType) e.destType.refCount++;
9811             }
9812             ProcessExpressionType(e);
9813             if(!e.next)
9814             {
9815                exp.expType = e.expType;
9816                if(e.expType) e.expType.refCount++;
9817             }
9818             if(!e.isConstant)
9819                exp.isConstant = false;
9820          }
9821
9822          FreeType(exp.cond.elseExp.destType);
9823          // Added this check if we failed to find an expType
9824          // exp.cond.elseExp.destType = exp.expType ? exp.expType : exp.destType;
9825
9826          // Reversed it...
9827          exp.cond.elseExp.destType = exp.destType ? exp.destType : exp.expType;
9828
9829          if(exp.cond.elseExp.destType)
9830             exp.cond.elseExp.destType.refCount++;
9831          ProcessExpressionType(exp.cond.elseExp);
9832
9833          // FIXED THIS: Was done before calling process on elseExp
9834          if(!exp.cond.elseExp.isConstant)
9835             exp.isConstant = false;
9836          break;
9837       }
9838       case extensionCompoundExp:
9839       {
9840          if(exp.compound && exp.compound.compound.statements && exp.compound.compound.statements->last)
9841          {
9842             Statement last = exp.compound.compound.statements->last;
9843             if(last.type == expressionStmt && last.expressions && last.expressions->last)
9844             {
9845                ((Expression)last.expressions->last).destType = exp.destType;
9846                if(exp.destType)
9847                   exp.destType.refCount++;
9848             }
9849             ProcessStatement(exp.compound);
9850             exp.expType = ((Expression)last.expressions->last).expType;
9851             if(((Expression)last.expressions->last).expType)
9852                exp.expType.refCount++;
9853          }
9854          break;
9855       }
9856       case classExp:
9857       {
9858          Specifier spec = exp._classExp.specifiers->first;
9859          if(spec && spec.type == nameSpecifier)
9860          {
9861             exp.expType = MkClassType(spec.name);
9862             exp.expType.kind = subClassType;
9863             exp.byReference = true;
9864          }
9865          else
9866          {
9867             exp.expType = MkClassType("ecere::com::Class");
9868             exp.byReference = true;
9869          }
9870          break;
9871       }
9872       case classDataExp:
9873       {
9874          Class _class = thisClass ? thisClass : currentClass;
9875          if(_class)
9876          {
9877             Identifier id = exp.classData.id;
9878             char structName[1024];
9879             Expression classExp;
9880             strcpy(structName, "__ecereClassData_");
9881             FullClassNameCat(structName, _class.fullName, false);
9882             exp.type = pointerExp;
9883             exp.member.member = id;
9884             if(curCompound && FindSymbol("this", curContext, curCompound.compound.context, false, false))
9885                classExp = MkExpMember(MkExpIdentifier(MkIdentifier("this")), MkIdentifier("_class"));
9886             else
9887                classExp = MkExpIdentifier(MkIdentifier("class"));
9888
9889             exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9890                MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), 
9891                   MkExpBrackets(MkListOne(MkExpOp(
9892                      MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)), 
9893                         MkExpMember(classExp, MkIdentifier("data"))), '+',
9894                            MkExpMember(MkExpClass(MkListOne(MkSpecifierName(_class.fullName)), null), MkIdentifier("offsetClass")))))
9895                      )));
9896
9897             ProcessExpressionType(exp);
9898             return;
9899          }
9900          break;
9901       }
9902       case arrayExp:
9903       {
9904          Type type = null;
9905          char * typeString = null;
9906          char typeStringBuf[1024];
9907          if(exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
9908             exp.destType._class.registered != containerClass && eClass_IsDerived(exp.destType._class.registered, containerClass))
9909          {
9910             Class templateClass = exp.destType._class.registered;
9911             typeString = templateClass.templateArgs[2].dataTypeString;
9912          }
9913          else if(exp.list)
9914          {
9915             // Guess type from expressions in the array
9916             Expression e;
9917             for(e = exp.list->first; e; e = e.next)
9918             {
9919                ProcessExpressionType(e);
9920                if(e.expType)
9921                {
9922                   if(!type) { type = e.expType; type.refCount++; }
9923                   else
9924                   {
9925                      // if(!MatchType(e.expType, type, null, null, null, false, false, false))
9926                      if(!MatchTypeExpression(e, type, null, false))
9927                      {
9928                         FreeType(type);
9929                         type = e.expType;
9930                         e.expType = null;
9931                         
9932                         e = exp.list->first;
9933                         ProcessExpressionType(e);
9934                         if(e.expType)
9935                         {
9936                            //if(!MatchTypes(e.expType, type, null, null, null, false, false, false))
9937                            if(!MatchTypeExpression(e, type, null, false))
9938                            {
9939                               FreeType(e.expType);
9940                               e.expType = null;
9941                               FreeType(type);
9942                               type = null;
9943                               break;
9944                            }                           
9945                         }
9946                      }
9947                   }
9948                   if(e.expType)
9949                   {
9950                      FreeType(e.expType);
9951                      e.expType = null;
9952                   }
9953                }
9954             }
9955             if(type)
9956             {
9957                typeStringBuf[0] = '\0';
9958                PrintType(type, typeStringBuf, false, true);
9959                typeString = typeStringBuf;
9960                FreeType(type);
9961                type = null;
9962             }
9963          }
9964          if(typeString)
9965          {
9966             /*
9967             (Container)& (struct BuiltInContainer)
9968             {
9969                ._vTbl = class(BuiltInContainer)._vTbl,
9970                ._class = class(BuiltInContainer),
9971                .refCount = 0,
9972                .data = (int[]){ 1, 7, 3, 4, 5 },
9973                .count = 5,
9974                .type = class(int),
9975             }
9976             */
9977             char templateString[1024];
9978             OldList * initializers = MkList();
9979             OldList * structInitializers = MkList();
9980             OldList * specs = MkList();
9981             Expression expExt;
9982             Declarator decl = SpecDeclFromString(typeString, specs, null);
9983             sprintf(templateString, "Container<%s>", typeString);
9984
9985             if(exp.list)
9986             {
9987                Expression e;
9988                type = ProcessTypeString(typeString, false);
9989                while(e = exp.list->first)
9990                {
9991                   exp.list->Remove(e);
9992                   e.destType = type;
9993                   type.refCount++;
9994                   ProcessExpressionType(e);
9995                   ListAdd(initializers, MkInitializerAssignment(e));
9996                }
9997                FreeType(type);
9998                delete exp.list;
9999             }
10000             
10001             DeclareStruct("ecere::com::BuiltInContainer", false);
10002
10003             ListAdd(structInitializers, /*MkIdentifier("_vTbl")*/    MkInitializerAssignment(MkExpMember(MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null), MkIdentifier("_vTbl"))));
10004                ProcessExpressionType(((Initializer)structInitializers->last).exp);
10005             ListAdd(structInitializers, /*MkIdentifier("_class")*/   MkInitializerAssignment(MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null)));
10006                ProcessExpressionType(((Initializer)structInitializers->last).exp);
10007             ListAdd(structInitializers, /*MkIdentifier("_refCount")*/MkInitializerAssignment(MkExpConstant("0")));
10008                ProcessExpressionType(((Initializer)structInitializers->last).exp);
10009             ListAdd(structInitializers, /*MkIdentifier("data")*/     MkInitializerAssignment(MkExpExtensionInitializer(
10010                MkTypeName(specs, MkDeclaratorArray(decl, null)),
10011                MkInitializerList(initializers))));
10012                ProcessExpressionType(((Initializer)structInitializers->last).exp);
10013             ListAdd(structInitializers, /*MkIdentifier("count")*/    MkInitializerAssignment({ type = constantExp, constant = PrintString(initializers->count) }));
10014                ProcessExpressionType(((Initializer)structInitializers->last).exp);
10015             ListAdd(structInitializers, /*MkIdentifier("type")*/     MkInitializerAssignment(MkExpClass(CopyList(specs, CopySpecifier), CopyDeclarator(decl))));
10016                ProcessExpressionType(((Initializer)structInitializers->last).exp);
10017             exp.expType = ProcessTypeString(templateString, false);
10018             exp.type = bracketsExp;
10019             exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(templateString)), null),
10020                MkExpOp(null, '&',
10021                expExt = MkExpExtensionInitializer(MkTypeName(MkListOne(MkSpecifierName("BuiltInContainer")), null),
10022                   MkInitializerList(structInitializers)))));
10023             ProcessExpressionType(expExt);
10024          }
10025          else
10026          {
10027             exp.expType = ProcessTypeString("Container", false);
10028             Compiler_Error($"Couldn't determine type of array elements\n");
10029          }
10030          break;
10031       }
10032    }
10033
10034    if(exp.expType && exp.expType.kind == thisClassType && thisClass && (!exp.destType || exp.destType.kind != thisClassType))
10035    {
10036       FreeType(exp.expType);
10037       exp.expType = ReplaceThisClassType(thisClass);
10038    }
10039
10040    // Resolve structures here
10041    if(exp.expType && (exp.expType.kind == structType || exp.expType.kind == unionType || exp.expType.kind == enumType) && !exp.expType.members.first && exp.expType.enumName)
10042    {
10043       Symbol symbol = FindSymbol(exp.expType.enumName, curContext, globalContext, true, false);
10044       // TODO: Fix members reference...
10045       if(symbol)
10046       {
10047          if(exp.expType.kind != enumType)
10048          {
10049             Type member;
10050             String enumName = CopyString(exp.expType.enumName);
10051
10052             // Fixed a memory leak on self-referencing C structs typedefs
10053             // by instantiating a new type rather than simply copying members
10054             // into exp.expType
10055             FreeType(exp.expType);
10056             exp.expType = Type { };
10057             exp.expType.kind = symbol.type.kind;
10058             exp.expType.refCount++;
10059             exp.expType.enumName = enumName;
10060
10061             exp.expType.members = symbol.type.members;
10062             for(member = symbol.type.members.first; member; member = member.next)
10063                member.refCount++;
10064          }
10065          else
10066          {
10067             NamedLink member;
10068             for(member = symbol.type.members.first; member; member = member.next)
10069             {
10070                NamedLink value { name = CopyString(member.name) };
10071                exp.expType.members.Add(value);
10072             }
10073          }
10074       }
10075    }
10076
10077    yylloc = exp.loc;
10078    if(exp.destType && (exp.destType.kind == voidType || exp.destType.kind == dummyType) );
10079    else if(exp.destType && !exp.destType.keepCast)
10080    {
10081       if(!CheckExpressionType(exp, exp.destType, false))
10082       {
10083          if(!exp.destType.count || unresolved)
10084          {
10085             if(!exp.expType)
10086             {
10087                yylloc = exp.loc;
10088                if(exp.destType.kind != ellipsisType)
10089                {
10090                   char type2[1024];
10091                   type2[0] = '\0';
10092                   if(inCompiler)
10093                   {
10094                      char expString[10240];
10095                      expString[0] = '\0';
10096
10097                      PrintType(exp.destType, type2, false, true);
10098
10099                      if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10100                      if(unresolved)
10101                         Compiler_Error($"unresolved identifier %s; expected %s\n", expString, type2);
10102                      else if(exp.type != dummyExp)
10103                         Compiler_Error($"couldn't determine type of %s; expected %s\n", expString, type2);
10104                   }
10105                }
10106                else
10107                {
10108                   char expString[10240] ;
10109                   expString[0] = '\0';
10110                   if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10111
10112                   if(unresolved)
10113                      Compiler_Error($"unresolved identifier %s\n", expString);
10114                   else if(exp.type != dummyExp)
10115                      Compiler_Error($"couldn't determine type of %s\n", expString);
10116                }
10117             }
10118             else
10119             {
10120                char type1[1024];
10121                char type2[1024];
10122                type1[0] = '\0';
10123                type2[0] = '\0';
10124                if(inCompiler)
10125                {
10126                   PrintType(exp.expType, type1, false, true);
10127                   PrintType(exp.destType, type2, false, true);
10128                }
10129
10130                //CheckExpressionType(exp, exp.destType, false);
10131
10132                if(exp.destType.truth && exp.destType._class && exp.destType._class.registered && !strcmp(exp.destType._class.registered.name, "bool") &&
10133                   exp.expType.kind != voidType && exp.expType.kind != structType && exp.expType.kind != unionType && 
10134                   (exp.expType.kind != classType || exp.expType.classObjectType || (exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type != structClass)));
10135                else
10136                {
10137                   char expString[10240];
10138                   expString[0] = '\0';
10139                   if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10140
10141 #ifdef _DEBUG
10142                   CheckExpressionType(exp, exp.destType, false);
10143 #endif
10144                   // Flex & Bison generate code that triggers this, so we ignore it for a quiet sdk build:
10145                   if(!sourceFile || (strcmp(sourceFile, "src\\lexer.ec") && strcmp(sourceFile, "src/lexer.ec") && strcmp(sourceFile, "src\\grammar.ec") && strcmp(sourceFile, "src/grammar.ec")))
10146                      Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
10147
10148                   // TO CHECK: FORCING HERE TO HELP DEBUGGER
10149                   FreeType(exp.expType);
10150                   exp.destType.refCount++;
10151                   exp.expType = exp.destType;
10152                }
10153             }
10154          }
10155       }
10156       else if(exp.destType && exp.destType.kind == ellipsisType && exp.expType && exp.expType.passAsTemplate)
10157       {
10158          Expression newExp { };
10159          char typeString[1024];
10160          OldList * specs = MkList();
10161          Declarator decl;
10162
10163          typeString[0] = '\0';
10164
10165          *newExp = *exp;
10166
10167          if(exp.expType)  exp.expType.refCount++;
10168          if(exp.expType)  exp.expType.refCount++;
10169          exp.type = castExp;
10170          newExp.destType = exp.expType;
10171
10172          PrintType(exp.expType, typeString, false, false);
10173          decl = SpecDeclFromString(typeString, specs, null);
10174          
10175          exp.cast.typeName = MkTypeName(specs, decl);
10176          exp.cast.exp = newExp;
10177       }
10178    }
10179    else if(unresolved)
10180    {
10181       if(exp.identifier._class && exp.identifier._class.name)
10182          Compiler_Error($"unresolved identifier %s::%s\n", exp.identifier._class.name, exp.identifier.string);
10183       else if(exp.identifier.string && exp.identifier.string[0])
10184          Compiler_Error($"unresolved identifier %s\n", exp.identifier.string);
10185    }
10186    else if(!exp.expType && exp.type != dummyExp)
10187    {
10188       char expString[10240];
10189       expString[0] = '\0';
10190       if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10191       Compiler_Error($"couldn't determine type of %s\n", expString);
10192    }
10193
10194    // Let's try to support any_object & typed_object here:
10195    ApplyAnyObjectLogic(exp);
10196
10197    if(!notByReference && exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
10198       exp.expType._class.registered.type == noHeadClass)
10199    {
10200       exp.byReference = true;
10201    }
10202    /*else if(!notByReference && exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
10203       exp.destType._class.registered.type == noHeadClass)
10204    {
10205       exp.byReference = true;
10206    }*/
10207    yylloc = oldyylloc;
10208 }
10209
10210 static void FindNextDataMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
10211 {
10212    // THIS CODE WILL FIND NEXT MEMBER...
10213    if(*curMember) 
10214    {
10215       *curMember = (*curMember).next;
10216
10217       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
10218       {
10219          *curMember = subMemberStack[--(*subMemberStackPos)];
10220          *curMember = (*curMember).next;
10221       }
10222
10223       // SKIP ALL PROPERTIES HERE...
10224       while((*curMember) && (*curMember).isProperty)
10225          *curMember = (*curMember).next;
10226
10227       if(subMemberStackPos)
10228       {
10229          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10230          {
10231             subMemberStack[(*subMemberStackPos)++] = *curMember;
10232
10233             *curMember = (*curMember).members.first;
10234             while(*curMember && (*curMember).isProperty)
10235                *curMember = (*curMember).next;                     
10236          }
10237       }
10238    }
10239    while(!*curMember)
10240    {
10241       if(!*curMember)
10242       {
10243          if(subMemberStackPos && *subMemberStackPos)
10244          {
10245             *curMember = subMemberStack[--(*subMemberStackPos)];
10246             *curMember = (*curMember).next;
10247          }
10248          else
10249          {
10250             Class lastCurClass = *curClass;
10251
10252             if(*curClass == _class) break;     // REACHED THE END
10253
10254             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass; *curClass = (*curClass).base);
10255             *curMember = (*curClass).membersAndProperties.first;
10256          }
10257
10258          while((*curMember) && (*curMember).isProperty)
10259             *curMember = (*curMember).next;
10260          if(subMemberStackPos)
10261          {
10262             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10263             {
10264                subMemberStack[(*subMemberStackPos)++] = *curMember;
10265
10266                *curMember = (*curMember).members.first;
10267                while(*curMember && (*curMember).isProperty)
10268                   *curMember = (*curMember).next;                     
10269             }
10270          }
10271       }
10272    }
10273 }
10274
10275
10276 static void ProcessInitializer(Initializer init, Type type)
10277 {
10278    switch(init.type)
10279    {
10280       case expInitializer:
10281          if(!init.exp || init.exp.type != instanceExp || !init.exp.instance || init.exp.instance._class || !type || type.kind == classType)
10282          {
10283             // TESTING THIS FOR SHUTTING = 0 WARNING
10284             if(init.exp && !init.exp.destType)
10285             {
10286                FreeType(init.exp.destType);
10287                init.exp.destType = type;
10288                if(type) type.refCount++;
10289             }
10290             if(init.exp)
10291             {
10292                ProcessExpressionType(init.exp);
10293                init.isConstant = init.exp.isConstant;
10294             }
10295             break;
10296          }
10297          else
10298          {
10299             Expression exp = init.exp;
10300             Instantiation inst = exp.instance;
10301             MembersInit members;
10302
10303             init.type = listInitializer;
10304             init.list = MkList();
10305
10306             if(inst.members)
10307             {
10308                for(members = inst.members->first; members; members = members.next)
10309                {
10310                   if(members.type == dataMembersInit)
10311                   {
10312                      MemberInit member;
10313                      for(member = members.dataMembers->first; member; member = member.next)
10314                      {
10315                         ListAdd(init.list, member.initializer);
10316                         member.initializer = null;
10317                      }
10318                   }
10319                   // Discard all MembersInitMethod
10320                }
10321             }
10322             FreeExpression(exp);
10323          }
10324       case listInitializer:
10325       {
10326          Initializer i;
10327          Type initializerType = null;
10328          Class curClass = null;
10329          DataMember curMember = null;
10330          DataMember subMemberStack[256];
10331          int subMemberStackPos = 0;
10332
10333          if(type && type.kind == arrayType)
10334             initializerType = Dereference(type);
10335          else if(type && (type.kind == structType || type.kind == unionType))
10336             initializerType = type.members.first;
10337
10338          for(i = init.list->first; i; i = i.next)
10339          {
10340             if(type && type.kind == classType && type._class && type._class.registered)
10341             {
10342                // 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)
10343                FindNextDataMember(type._class.registered, &curClass, &curMember, subMemberStack, &subMemberStackPos);
10344                // TODO: Generate error on initializing a private data member this way from another module...
10345                if(curMember)
10346                {
10347                   if(!curMember.dataType)
10348                      curMember.dataType = ProcessTypeString(curMember.dataTypeString, false);
10349                   initializerType = curMember.dataType;
10350                }
10351             }
10352             ProcessInitializer(i, initializerType);
10353             if(initializerType && type && (type.kind == structType || type.kind == unionType))
10354                initializerType = initializerType.next;
10355             if(!i.isConstant)
10356                init.isConstant = false;
10357          }
10358
10359          if(type && type.kind == arrayType)
10360             FreeType(initializerType);
10361
10362          if(type && type.kind != arrayType && type.kind != structType && type.kind != unionType && (type.kind != classType || !type._class.registered || type._class.registered.type != structClass))
10363          {
10364             Compiler_Error($"Assigning list initializer to non list\n");
10365          }
10366          break;
10367       }
10368    }
10369 }
10370
10371 static void ProcessSpecifier(Specifier spec, bool declareStruct)
10372 {
10373    switch(spec.type)
10374    {
10375       case baseSpecifier:
10376       {
10377          if(spec.specifier == THISCLASS)
10378          {
10379             if(thisClass)
10380             {
10381                spec.type = nameSpecifier;
10382                spec.name = ReplaceThisClass(thisClass);
10383                spec.symbol = FindClass(spec.name);
10384                ProcessSpecifier(spec, declareStruct);
10385             }
10386          }
10387          break;
10388       }
10389       case nameSpecifier:
10390       {
10391          Symbol symbol = FindType(curContext, spec.name);
10392          if(symbol)
10393             DeclareType(symbol.type, true, true);
10394          else if((symbol = spec.symbol /*FindClass(spec.name)*/) && symbol.registered && symbol.registered.type == structClass && declareStruct)
10395             DeclareStruct(spec.name, false);
10396          break;
10397       }
10398       case enumSpecifier:
10399       {
10400          Enumerator e;
10401          if(spec.list)
10402          {
10403             for(e = spec.list->first; e; e = e.next)
10404             {
10405                if(e.exp)
10406                   ProcessExpressionType(e.exp);
10407             }
10408          }
10409          break;
10410       }
10411       case structSpecifier:
10412       case unionSpecifier:
10413       {
10414          if(spec.definitions)
10415          {
10416             ClassDef def;
10417             Symbol symbol = spec.id ? FindClass(spec.id.string) : null;
10418             //if(symbol)
10419                ProcessClass(spec.definitions, symbol);
10420             /*else
10421             {
10422                for(def = spec.definitions->first; def; def = def.next)
10423                {
10424                   //if(def.type == declarationClassDef && def.decl && def.decl.type == DeclarationStruct)
10425                      ProcessDeclaration(def.decl);
10426                }
10427             }*/
10428          }
10429          break;
10430       }
10431       /*
10432       case classSpecifier:
10433       {
10434          Symbol classSym = FindClass(spec.name);
10435          if(classSym && classSym.registered && classSym.registered.type == structClass)
10436             DeclareStruct(spec.name, false);
10437          break;
10438       }
10439       */
10440    }
10441 }
10442
10443
10444 static void ProcessDeclarator(Declarator decl)
10445 {
10446    switch(decl.type)
10447    {
10448       case identifierDeclarator:
10449          if(decl.identifier.classSym /* TODO: Name Space Fix ups  || decl.identifier.nameSpace*/)
10450          {
10451             FreeSpecifier(decl.identifier._class);
10452             decl.identifier._class = null;
10453          }
10454          break;
10455       case arrayDeclarator:
10456          if(decl.array.exp)
10457             ProcessExpressionType(decl.array.exp);
10458       case structDeclarator:
10459       case bracketsDeclarator:
10460       case functionDeclarator:
10461       case pointerDeclarator:
10462       case extendedDeclarator:
10463       case extendedDeclaratorEnd:
10464          if(decl.declarator)
10465             ProcessDeclarator(decl.declarator);
10466          if(decl.type == functionDeclarator)
10467          {
10468             Identifier id = GetDeclId(decl);
10469             if(id && id._class)
10470             {
10471                TypeName param
10472                {
10473                   qualifiers = MkListOne(id._class);
10474                   declarator = null;
10475                };
10476                if(!decl.function.parameters)
10477                   decl.function.parameters = MkList();               
10478                decl.function.parameters->Insert(null, param);
10479                id._class = null;
10480             }
10481             if(decl.function.parameters)
10482             {
10483                TypeName param;
10484                
10485                for(param = decl.function.parameters->first; param; param = param.next)
10486                {
10487                   if(param.qualifiers && param.qualifiers->first)
10488                   {
10489                      Specifier spec = param.qualifiers->first;
10490                      if(spec && spec.specifier == TYPED_OBJECT)
10491                      {
10492                         Declarator d = param.declarator;
10493                         TypeName newParam
10494                         {
10495                            qualifiers = MkListOne(MkSpecifier(VOID));
10496                            declarator = MkDeclaratorPointer(MkPointer(null,null), d);
10497                         };
10498                         
10499                         FreeList(param.qualifiers, FreeSpecifier);
10500
10501                         param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
10502                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
10503
10504                         decl.function.parameters->Insert(param, newParam);
10505                         param = newParam;
10506                      }
10507                      else if(spec && spec.specifier == ANY_OBJECT)
10508                      {
10509                         Declarator d = param.declarator;
10510                         
10511                         FreeList(param.qualifiers, FreeSpecifier);
10512
10513                         param.qualifiers = MkListOne(MkSpecifier(VOID));
10514                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);                        
10515                      }
10516                      else if(spec.specifier == THISCLASS)
10517                      {
10518                         if(thisClass)
10519                         {
10520                            spec.type = nameSpecifier;
10521                            spec.name = ReplaceThisClass(thisClass);
10522                            spec.symbol = FindClass(spec.name);
10523                            ProcessSpecifier(spec, false);
10524                         }
10525                      }
10526                   }
10527
10528                   if(param.declarator)
10529                      ProcessDeclarator(param.declarator);
10530                }
10531             }
10532          }
10533          break;
10534    }
10535 }
10536
10537 static void ProcessDeclaration(Declaration decl)
10538 {
10539    yylloc = decl.loc;
10540    switch(decl.type)
10541    {
10542       case initDeclaration:
10543       {
10544          bool declareStruct = false;
10545          /*
10546          lineNum = decl.pos.line;
10547          column = decl.pos.col;
10548          */
10549
10550          if(decl.declarators)
10551          {
10552             InitDeclarator d;
10553          
10554             for(d = decl.declarators->first; d; d = d.next)
10555             {
10556                Type type, subType;
10557                ProcessDeclarator(d.declarator);
10558
10559                type = ProcessType(decl.specifiers, d.declarator);
10560
10561                if(d.initializer)
10562                {
10563                   ProcessInitializer(d.initializer, type);
10564
10565                   // Change "ColorRGB a = ColorRGB { 1,2,3 } => ColorRGB a { 1,2,3 }                  
10566                   
10567                   if(decl.declarators->count == 1 && d.initializer.type == expInitializer &&
10568                      d.initializer.exp.type == instanceExp)
10569                   {
10570                      if(type.kind == classType && type._class == 
10571                         d.initializer.exp.expType._class)
10572                      {
10573                         Instantiation inst = d.initializer.exp.instance;
10574                         inst.exp = MkExpIdentifier(CopyIdentifier(GetDeclId(d.declarator)));
10575                         
10576                         d.initializer.exp.instance = null;
10577                         if(decl.specifiers)
10578                            FreeList(decl.specifiers, FreeSpecifier);
10579                         FreeList(decl.declarators, FreeInitDeclarator);
10580
10581                         d = null;
10582
10583                         decl.type = instDeclaration;
10584                         decl.inst = inst;
10585                      }
10586                   }
10587                }
10588                for(subType = type; subType;)
10589                {
10590                   if(subType.kind == classType)
10591                   {
10592                      declareStruct = true;
10593                      break;
10594                   }
10595                   else if(subType.kind == pointerType)
10596                      break;
10597                   else if(subType.kind == arrayType)
10598                      subType = subType.arrayType;
10599                   else
10600                      break;
10601                }
10602
10603                FreeType(type);
10604                if(!d) break;
10605             }
10606          }
10607
10608          if(decl.specifiers)
10609          {
10610             Specifier s;
10611             for(s = decl.specifiers->first; s; s = s.next)
10612             {
10613                ProcessSpecifier(s, declareStruct);
10614             }
10615          }
10616          break;
10617       }
10618       case instDeclaration:
10619       {
10620          ProcessInstantiationType(decl.inst);
10621          break;
10622       }
10623       case structDeclaration:
10624       {
10625          Specifier spec;
10626          Declarator d;
10627          bool declareStruct = false;
10628
10629          if(decl.declarators)
10630          {
10631             for(d = decl.declarators->first; d; d = d.next)
10632             {
10633                Type type = ProcessType(decl.specifiers, d.declarator);
10634                Type subType;
10635                ProcessDeclarator(d);
10636                for(subType = type; subType;)
10637                {
10638                   if(subType.kind == classType)
10639                   {
10640                      declareStruct = true;
10641                      break;
10642                   }
10643                   else if(subType.kind == pointerType)
10644                      break;
10645                   else if(subType.kind == arrayType)
10646                      subType = subType.arrayType;
10647                   else
10648                      break;
10649                }
10650                FreeType(type);
10651             }
10652          }
10653          if(decl.specifiers)
10654          {
10655             for(spec = decl.specifiers->first; spec; spec = spec.next)
10656                ProcessSpecifier(spec, declareStruct);
10657          }
10658          break;
10659       }
10660    }
10661 }
10662
10663 static FunctionDefinition curFunction;
10664
10665 static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
10666 {
10667    char propName[1024], propNameM[1024];
10668    char getName[1024], setName[1024];
10669    OldList * args;
10670
10671    DeclareProperty(prop, setName, getName);
10672
10673    // eInstance_FireWatchers(object, prop);
10674    strcpy(propName, "__ecereProp_");
10675    FullClassNameCat(propName, prop._class.fullName, false);
10676    strcat(propName, "_");
10677    // strcat(propName, prop.name);
10678    FullClassNameCat(propName, prop.name, true);
10679    MangleClassName(propName);
10680
10681    strcpy(propNameM, "__ecerePropM_");
10682    FullClassNameCat(propNameM, prop._class.fullName, false);
10683    strcat(propNameM, "_");
10684    // strcat(propNameM, prop.name);
10685    FullClassNameCat(propNameM, prop.name, true);
10686    MangleClassName(propNameM);
10687
10688    if(prop.isWatchable)
10689    {
10690       args = MkList();
10691       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10692       ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10693       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10694
10695       args = MkList();
10696       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10697       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10698       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10699    }
10700
10701    
10702    {
10703       args = MkList();
10704       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10705       ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10706       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10707
10708       args = MkList();
10709       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10710       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10711       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10712    }
10713    
10714    if(curFunction.propSet && !strcmp(curFunction.propSet.string, prop.name) && 
10715       (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
10716       curFunction.propSet.fireWatchersDone = true;
10717 }
10718
10719 static void ProcessStatement(Statement stmt)
10720 {
10721    yylloc = stmt.loc;
10722    /*
10723    lineNum = stmt.pos.line;
10724    column = stmt.pos.col;
10725    */
10726    switch(stmt.type)
10727    {
10728       case labeledStmt:
10729          ProcessStatement(stmt.labeled.stmt);
10730          break;
10731       case caseStmt:
10732          // This expression should be constant...
10733          if(stmt.caseStmt.exp)
10734          {
10735             FreeType(stmt.caseStmt.exp.destType);
10736             stmt.caseStmt.exp.destType = curSwitchType;
10737             if(curSwitchType) curSwitchType.refCount++;
10738             ProcessExpressionType(stmt.caseStmt.exp);
10739             ComputeExpression(stmt.caseStmt.exp);
10740          }
10741          if(stmt.caseStmt.stmt)
10742             ProcessStatement(stmt.caseStmt.stmt);
10743          break;
10744       case compoundStmt:
10745       {
10746          if(stmt.compound.context)
10747          {
10748             Declaration decl;
10749             Statement s;
10750
10751             Statement prevCompound = curCompound;
10752             Context prevContext = curContext;
10753
10754             if(!stmt.compound.isSwitch)
10755             {
10756                curCompound = stmt;
10757                curContext = stmt.compound.context;
10758             }
10759
10760             if(stmt.compound.declarations)
10761             {
10762                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
10763                   ProcessDeclaration(decl);
10764             }
10765             if(stmt.compound.statements)
10766             {
10767                for(s = stmt.compound.statements->first; s; s = s.next)
10768                   ProcessStatement(s);
10769             }
10770
10771             curContext = prevContext;
10772             curCompound = prevCompound;
10773          }
10774          break;
10775       }
10776       case expressionStmt:
10777       {
10778          Expression exp;
10779          if(stmt.expressions)
10780          {
10781             for(exp = stmt.expressions->first; exp; exp = exp.next)
10782                ProcessExpressionType(exp);
10783          }
10784          break;
10785       }
10786       case ifStmt:
10787       {
10788          Expression exp;
10789
10790          FreeType(((Expression)stmt.ifStmt.exp->last).destType);
10791          ((Expression)stmt.ifStmt.exp->last).destType = MkClassType("bool");
10792          ((Expression)stmt.ifStmt.exp->last).destType.truth = true;
10793          for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
10794          {
10795             ProcessExpressionType(exp);
10796          }
10797          if(stmt.ifStmt.stmt)
10798             ProcessStatement(stmt.ifStmt.stmt);
10799          if(stmt.ifStmt.elseStmt)
10800             ProcessStatement(stmt.ifStmt.elseStmt);
10801          break;
10802       }
10803       case switchStmt:
10804       {
10805          Type oldSwitchType = curSwitchType;
10806          if(stmt.switchStmt.exp)
10807          {
10808             Expression exp;
10809             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
10810             {
10811                if(!exp.next)
10812                {
10813                   /*
10814                   Type destType
10815                   {
10816                      kind = intType;
10817                      refCount = 1;
10818                   };
10819                   e.exp.destType = destType;
10820                   */
10821
10822                   ProcessExpressionType(exp);
10823                }
10824                if(!exp.next)
10825                   curSwitchType = exp.expType;
10826             }
10827          }
10828          ProcessStatement(stmt.switchStmt.stmt);
10829          curSwitchType = oldSwitchType;
10830          break;
10831       }
10832       case whileStmt:
10833       {
10834          if(stmt.whileStmt.exp)
10835          {
10836             Expression exp;
10837
10838             FreeType(((Expression)stmt.whileStmt.exp->last).destType);
10839             ((Expression)stmt.whileStmt.exp->last).destType = MkClassType("bool");
10840             ((Expression)stmt.whileStmt.exp->last).destType.truth = true;
10841             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
10842             {
10843                ProcessExpressionType(exp);
10844             }
10845          }
10846          if(stmt.whileStmt.stmt)
10847             ProcessStatement(stmt.whileStmt.stmt);
10848          break;
10849       }
10850       case doWhileStmt:
10851       {
10852          if(stmt.doWhile.exp)
10853          {
10854             Expression exp;
10855
10856             if(stmt.doWhile.exp->last)
10857             {
10858                FreeType(((Expression)stmt.doWhile.exp->last).destType);
10859                ((Expression)stmt.doWhile.exp->last).destType = MkClassType("bool");
10860                ((Expression)stmt.doWhile.exp->last).destType.truth = true;
10861             }
10862             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
10863             {
10864                ProcessExpressionType(exp);
10865             }
10866          }
10867          if(stmt.doWhile.stmt)
10868             ProcessStatement(stmt.doWhile.stmt);
10869          break;
10870       }
10871       case forStmt:
10872       {
10873          Expression exp;
10874          if(stmt.forStmt.init)
10875             ProcessStatement(stmt.forStmt.init);
10876
10877          if(stmt.forStmt.check && stmt.forStmt.check.expressions)
10878          {
10879             FreeType(((Expression)stmt.forStmt.check.expressions->last).destType);
10880             ((Expression)stmt.forStmt.check.expressions->last).destType = MkClassType("bool");
10881             ((Expression)stmt.forStmt.check.expressions->last).destType.truth = true;
10882          }
10883
10884          if(stmt.forStmt.check)
10885             ProcessStatement(stmt.forStmt.check);
10886          if(stmt.forStmt.increment)
10887          {
10888             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
10889                ProcessExpressionType(exp);
10890          }
10891
10892          if(stmt.forStmt.stmt)
10893             ProcessStatement(stmt.forStmt.stmt);
10894          break;
10895       }
10896       case forEachStmt:
10897       {
10898          Identifier id = stmt.forEachStmt.id;
10899          OldList * exp = stmt.forEachStmt.exp;
10900          OldList * filter = stmt.forEachStmt.filter;
10901          Statement block = stmt.forEachStmt.stmt;
10902          char iteratorType[1024];
10903          Type source;
10904          Expression e;
10905          bool isBuiltin = exp && exp->last && 
10906             (((Expression)exp->last).type == ExpressionType::arrayExp || 
10907               (((Expression)exp->last).type == castExp && ((Expression)exp->last).cast.exp.type == ExpressionType::arrayExp));
10908          Expression arrayExp;
10909          char * typeString = null;
10910          int builtinCount = 0;
10911
10912          for(e = exp ? exp->first : null; e; e = e.next)
10913          {
10914             if(!e.next)
10915             {
10916                FreeType(e.destType);
10917                e.destType = ProcessTypeString("Container", false);
10918             }
10919             if(!isBuiltin || e.next)
10920                ProcessExpressionType(e);
10921          }
10922
10923          source = (exp && exp->last) ? ((Expression)exp->last).expType : null;
10924          if(isBuiltin || (source && source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
10925             eClass_IsDerived(source._class.registered, containerClass)))
10926          {
10927             Class _class = source ? source._class.registered : null;
10928             Symbol symbol;
10929             Expression expIt = null;
10930             bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false, isAVLTree = false;
10931             Class arrayClass = eSystem_FindClass(privateModule, "Array");
10932             Class linkListClass = eSystem_FindClass(privateModule, "LinkList");
10933             Class customAVLTreeClass = eSystem_FindClass(privateModule, "CustomAVLTree");
10934             stmt.type = compoundStmt;
10935             
10936             stmt.compound.context = Context { };
10937             stmt.compound.context.parent = curContext;
10938             curContext = stmt.compound.context;
10939
10940             if(source && eClass_IsDerived(source._class.registered, customAVLTreeClass))
10941             {
10942                Class mapClass = eSystem_FindClass(privateModule, "Map");
10943                Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
10944                isCustomAVLTree = true;
10945                if(eClass_IsDerived(source._class.registered, avlTreeClass))
10946                   isAVLTree = true;
10947                else if(eClass_IsDerived(source._class.registered, mapClass))
10948                   isMap = true;
10949             }
10950             else if(source && eClass_IsDerived(source._class.registered, arrayClass)) isArray = true;
10951             else if(source && eClass_IsDerived(source._class.registered, linkListClass)) 
10952             {
10953                Class listClass = eSystem_FindClass(privateModule, "List");
10954                isLinkList = true;
10955                isList = eClass_IsDerived(source._class.registered, listClass);
10956             }
10957
10958             if(isArray)
10959             {
10960                Declarator decl;
10961                OldList * specs = MkList();
10962                decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
10963                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
10964                stmt.compound.declarations = MkListOne(
10965                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
10966                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
10967                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalArray")), 
10968                      MkInitializerAssignment(MkExpBrackets(exp))))));
10969             }
10970             else if(isBuiltin)
10971             {
10972                Type type = null;
10973                char typeStringBuf[1024];
10974                
10975                // TODO: Merge this code?
10976                arrayExp = (((Expression)exp->last).type == ExpressionType::arrayExp) ? (Expression)exp->last : ((Expression)exp->last).cast.exp;
10977                if(((Expression)exp->last).type == castExp)
10978                {
10979                   TypeName typeName = ((Expression)exp->last).cast.typeName;
10980                   if(typeName)
10981                      arrayExp.destType = ProcessType(typeName.qualifiers, typeName.declarator);
10982                }
10983
10984                if(arrayExp.destType && arrayExp.destType.kind == classType && arrayExp.destType._class && arrayExp.destType._class.registered &&
10985                   arrayExp.destType._class.registered != containerClass && eClass_IsDerived(arrayExp.destType._class.registered, containerClass) &&
10986                   arrayExp.destType._class.registered.templateArgs)
10987                {
10988                   Class templateClass = arrayExp.destType._class.registered;
10989                   typeString = templateClass.templateArgs[2].dataTypeString;
10990                }
10991                else if(arrayExp.list)
10992                {
10993                   // Guess type from expressions in the array
10994                   Expression e;
10995                   for(e = arrayExp.list->first; e; e = e.next)
10996                   {
10997                      ProcessExpressionType(e);
10998                      if(e.expType)
10999                      {
11000                         if(!type) { type = e.expType; type.refCount++; }
11001                         else
11002                         {
11003                            // if(!MatchType(e.expType, type, null, null, null, false, false, false))
11004                            if(!MatchTypeExpression(e, type, null, false))
11005                            {
11006                               FreeType(type);
11007                               type = e.expType;
11008                               e.expType = null;
11009                               
11010                               e = arrayExp.list->first;
11011                               ProcessExpressionType(e);
11012                               if(e.expType)
11013                               {
11014                                  //if(!MatchTypes(e.expType, type, null, null, null, false, false, false, false))
11015                                  if(!MatchTypeExpression(e, type, null, false))
11016                                  {
11017                                     FreeType(e.expType);
11018                                     e.expType = null;
11019                                     FreeType(type);
11020                                     type = null;
11021                                     break;
11022                                  }                           
11023                               }
11024                            }
11025                         }
11026                         if(e.expType)
11027                         {
11028                            FreeType(e.expType);
11029                            e.expType = null;
11030                         }
11031                      }
11032                   }
11033                   if(type)
11034                   {
11035                      typeStringBuf[0] = '\0';
11036                      PrintType(type, typeStringBuf, false, true);
11037                      typeString = typeStringBuf;
11038                      FreeType(type);
11039                   }
11040                }
11041                if(typeString)
11042                {
11043                   OldList * initializers = MkList();
11044                   Declarator decl;
11045                   OldList * specs = MkList();
11046                   if(arrayExp.list)
11047                   {
11048                      Expression e;
11049
11050                      builtinCount = arrayExp.list->count;
11051                      type = ProcessTypeString(typeString, false);
11052                      while(e = arrayExp.list->first)
11053                      {
11054                         arrayExp.list->Remove(e);
11055                         e.destType = type;
11056                         type.refCount++;
11057                         ProcessExpressionType(e);
11058                         ListAdd(initializers, MkInitializerAssignment(e));
11059                      }
11060                      FreeType(type);
11061                      delete arrayExp.list;
11062                   }
11063                   decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
11064                   stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier), 
11065                      MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
11066
11067                   ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorArray(PlugDeclarator(
11068                      /*CopyDeclarator(*/decl/*)*/, MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), null), MkInitializerList(initializers)))));
11069                   
11070                   FreeList(exp, FreeExpression);
11071                }
11072                else
11073                {
11074                   arrayExp.expType = ProcessTypeString("Container", false);
11075                   Compiler_Error($"Couldn't determine type of array elements\n");
11076                }
11077
11078                /*
11079                Declarator decl;
11080                OldList * specs = MkList();
11081
11082                decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
11083                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
11084                stmt.compound.declarations = MkListOne(
11085                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11086                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName("BuiltInContainer")),
11087                   MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), 
11088                      MkInitializerAssignment(MkExpBrackets(exp))))));
11089                */
11090             }
11091             else if(isLinkList && !isList)
11092             {
11093                Declarator decl;
11094                OldList * specs = MkList();
11095                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11096                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11097                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11098                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalLinkList")), 
11099                      MkInitializerAssignment(MkExpBrackets(exp))))));
11100             }
11101             /*else if(isCustomAVLTree)
11102             {
11103                Declarator decl;
11104                OldList * specs = MkList();
11105                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11106                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11107                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11108                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalTree")), 
11109                      MkInitializerAssignment(MkExpBrackets(exp))))));
11110             }*/
11111             else if(_class.templateArgs)
11112             {
11113                if(isMap)
11114                   sprintf(iteratorType, "MapIterator<%s, %s >", _class.templateArgs[5].dataTypeString, _class.templateArgs[6].dataTypeString);
11115                else
11116                   sprintf(iteratorType, "Iterator<%s, %s >", _class.templateArgs[2].dataTypeString, _class.templateArgs[1].dataTypeString);
11117
11118                stmt.compound.declarations = MkListOne(
11119                   MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName(iteratorType)),
11120                   MkExpIdentifier(id), MkListOne(MkMembersInitList(MkListOne(MkMemberInit(isMap ? MkListOne(MkIdentifier("map")) : null, 
11121                   MkInitializerAssignment(MkExpBrackets(exp)))))))));
11122             }
11123             symbol = FindSymbol(id.string, curContext, curContext, false, false);
11124
11125             if(block && block.type == compoundStmt && block.compound.context)
11126             {
11127                block.compound.context.parent = stmt.compound.context;
11128             }
11129             if(filter)
11130             {
11131                block = MkIfStmt(filter, block, null);
11132             }
11133             if(isArray)
11134             {
11135                stmt.compound.statements = MkListOne(MkForStmt(
11136                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
11137                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11138                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11139                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11140                   block));
11141               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11142               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11143               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11144             }
11145             else if(isBuiltin)
11146             {
11147                char count[128];
11148                //OldList * specs = MkList();
11149                // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11150
11151                sprintf(count, "%d", builtinCount);
11152
11153                stmt.compound.statements = MkListOne(MkForStmt(
11154                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
11155                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11156                      MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
11157                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11158                   block));
11159
11160                /*
11161                Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11162                stmt.compound.statements = MkListOne(MkForStmt(
11163                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
11164                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11165                      MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11166                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11167                   block));
11168               */
11169               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11170               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11171               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11172             }
11173             else if(isLinkList && !isList)
11174             {
11175                Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
11176                Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
11177                if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString && 
11178                   !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
11179                {
11180                   stmt.compound.statements = MkListOne(MkForStmt(
11181                      MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11182                      MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11183                      MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11184                      block));
11185                }
11186                else
11187                {
11188                   OldList * specs = MkList();
11189                   Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
11190                   stmt.compound.statements = MkListOne(MkForStmt(
11191                      MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11192                      MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11193                      MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
11194                         MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
11195                            MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
11196                      block));
11197                }
11198                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11199                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11200                ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11201             }
11202             /*else if(isCustomAVLTree)
11203             {
11204                stmt.compound.statements = MkListOne(MkForStmt(
11205                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
11206                      MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
11207                   MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11208                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11209                   block));
11210
11211                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11212                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11213                ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11214             }*/
11215             else
11216             {
11217                stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
11218                   MkIdentifier("Next")), null)), block));
11219             }
11220             ProcessExpressionType(expIt);
11221             if(stmt.compound.declarations->first)
11222                ProcessDeclaration(stmt.compound.declarations->first);
11223
11224             if(symbol) 
11225                symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
11226
11227             ProcessStatement(stmt);
11228             curContext = stmt.compound.context.parent;
11229             break;
11230          }
11231          else
11232          {
11233             Compiler_Error($"Expression is not a container\n");
11234          }
11235          break;
11236       }
11237       case gotoStmt:
11238          break;
11239       case continueStmt:
11240          break;
11241       case breakStmt:
11242          break;
11243       case returnStmt:
11244       {
11245          Expression exp;
11246          if(stmt.expressions)
11247          {
11248             for(exp = stmt.expressions->first; exp; exp = exp.next)
11249             {
11250                if(!exp.next)
11251                {
11252                   if(curFunction && !curFunction.type)
11253                      curFunction.type = ProcessType(
11254                         curFunction.specifiers, curFunction.declarator);
11255                   FreeType(exp.destType);
11256                   exp.destType = (curFunction && curFunction.type && curFunction.type.kind == functionType) ? curFunction.type.returnType : null;
11257                   if(exp.destType) exp.destType.refCount++;
11258                }
11259                ProcessExpressionType(exp);
11260             }
11261          }
11262          break;
11263       }
11264       case badDeclarationStmt:
11265       {
11266          ProcessDeclaration(stmt.decl);
11267          break;
11268       }
11269       case asmStmt:
11270       {
11271          AsmField field;
11272          if(stmt.asmStmt.inputFields)
11273          {
11274             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
11275                if(field.expression)
11276                   ProcessExpressionType(field.expression);
11277          }
11278          if(stmt.asmStmt.outputFields)
11279          {
11280             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
11281                if(field.expression)
11282                   ProcessExpressionType(field.expression);
11283          }
11284          if(stmt.asmStmt.clobberedFields)
11285          {
11286             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
11287             {
11288                if(field.expression)
11289                   ProcessExpressionType(field.expression);
11290             }
11291          }
11292          break;
11293       }
11294       case watchStmt:
11295       {
11296          PropertyWatch propWatch;
11297          OldList * watches = stmt._watch.watches;
11298          Expression object = stmt._watch.object;
11299          Expression watcher = stmt._watch.watcher;
11300          if(watcher)
11301             ProcessExpressionType(watcher);
11302          if(object)
11303             ProcessExpressionType(object);
11304
11305          if(inCompiler)
11306          {
11307             if(watcher || thisClass)
11308             {
11309                External external = curExternal;
11310                Context context = curContext;
11311
11312                stmt.type = expressionStmt;
11313                stmt.expressions = MkList();
11314
11315                curExternal = external.prev;
11316
11317                for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11318                {
11319                   ClassFunction func;
11320                   char watcherName[1024];
11321                   Class watcherClass = watcher ? 
11322                      ((watcher.expType && watcher.expType.kind == classType && watcher.expType._class) ? watcher.expType._class.registered : null) : thisClass;
11323                   External createdExternal;
11324
11325                   // Create a declaration above
11326                   External externalDecl = MkExternalDeclaration(null);
11327                   ast->Insert(curExternal.prev, externalDecl);
11328
11329                   sprintf(watcherName,"__ecerePropertyWatcher_%d", propWatcherID++);
11330                   if(propWatch.deleteWatch)
11331                      strcat(watcherName, "_delete");
11332                   else
11333                   {
11334                      Identifier propID;
11335                      for(propID = propWatch.properties->first; propID; propID = propID.next)
11336                      {
11337                         strcat(watcherName, "_");
11338                         strcat(watcherName, propID.string);
11339                      }
11340                   }
11341
11342                   if(object && object.expType && object.expType.kind == classType && object.expType._class && object.expType._class.registered)
11343                   {
11344                      // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
11345                      func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)),
11346                         //MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null))), null);
11347                         MkListOne(MkTypeName(MkListOne(MkSpecifierName(object.expType._class.string)), MkDeclaratorIdentifier(MkIdentifier("value"))))), null);
11348                      ProcessClassFunctionBody(func, propWatch.compound);
11349                      propWatch.compound = null;
11350
11351                      //afterExternal = afterExternal ? afterExternal : curExternal;
11352
11353                      //createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal.prev);
11354                      createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal, true);
11355                      // TESTING THIS...
11356                      createdExternal.symbol.idCode = external.symbol.idCode;
11357
11358                      curExternal = createdExternal;
11359                      ProcessFunction(createdExternal.function);
11360
11361
11362                      // Create a declaration above
11363                      {
11364                         Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier), 
11365                            MkListOne(MkInitDeclarator(CopyDeclarator(createdExternal.function.declarator), null)));
11366                         externalDecl.declaration = decl;
11367                         if(decl.symbol && !decl.symbol.pointerExternal)
11368                            decl.symbol.pointerExternal = externalDecl;
11369                      }
11370
11371                      if(propWatch.deleteWatch)
11372                      {
11373                         OldList * args = MkList();
11374                         ListAdd(args, CopyExpression(object));
11375                         ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11376                         ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11377                         ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_WatchDestruction")), args));
11378                      }
11379                      else
11380                      {
11381                         Class _class = object.expType._class.registered;
11382                         Identifier propID;
11383
11384                         for(propID = propWatch.properties->first; propID; propID = propID.next)
11385                         {
11386                            char propName[1024];
11387                            Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11388                            if(prop)
11389                            {
11390                               char getName[1024], setName[1024];
11391                               OldList * args = MkList();
11392
11393                               DeclareProperty(prop, setName, getName);                              
11394                               
11395                               // eInstance_Watch(stmt.watch.object, prop, stmt.watch.watcher, callback);
11396                               strcpy(propName, "__ecereProp_");
11397                               FullClassNameCat(propName, prop._class.fullName, false);
11398                               strcat(propName, "_");
11399                               // strcat(propName, prop.name);
11400                               FullClassNameCat(propName, prop.name, true);
11401
11402                               ListAdd(args, CopyExpression(object));
11403                               ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11404                               ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11405                               ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11406
11407                               ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), args));
11408                            }
11409                            else
11410                               Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
11411                         }
11412                      }
11413                   }
11414                   else
11415                      Compiler_Error($"Invalid watched object\n");
11416                }
11417
11418                curExternal = external;
11419                curContext = context;
11420
11421                if(watcher)
11422                   FreeExpression(watcher);
11423                if(object)
11424                   FreeExpression(object);
11425                FreeList(watches, FreePropertyWatch);
11426             }
11427             else
11428                Compiler_Error($"No observer specified and not inside a _class\n");
11429          }
11430          else
11431          {
11432             for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11433             {
11434                ProcessStatement(propWatch.compound);
11435             }
11436
11437          }
11438          break;
11439       }
11440       case fireWatchersStmt:
11441       {
11442          OldList * watches = stmt._watch.watches;
11443          Expression object = stmt._watch.object;
11444          Class _class;
11445          // DEBUGGER BUG: Why doesn't watches evaluate to null??
11446          // printf("%X\n", watches);
11447          // printf("%X\n", stmt._watch.watches);
11448          if(object)
11449             ProcessExpressionType(object);
11450
11451          if(inCompiler)
11452          {
11453             _class = object ? 
11454                   ((object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null) : thisClass;
11455
11456             if(_class)
11457             {
11458                Identifier propID;
11459
11460                stmt.type = expressionStmt;
11461                stmt.expressions = MkList();
11462
11463                // Check if we're inside a property set
11464                if(!watches && curFunction.propSet && (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
11465                {
11466                   watches = MkListOne(MkIdentifier(curFunction.propSet.string));
11467                }
11468                else if(!watches)
11469                {
11470                   //Compiler_Error($"No property specified and not inside a property set\n");
11471                }
11472                if(watches)
11473                {
11474                   for(propID = watches->first; propID; propID = propID.next)
11475                   {
11476                      Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11477                      if(prop)
11478                      {
11479                         CreateFireWatcher(prop, object, stmt);
11480                      }
11481                      else
11482                         Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
11483                   }
11484                }
11485                else
11486                {
11487                   // Fire all properties!
11488                   Property prop;
11489                   Class base;
11490                   for(base = _class; base; base = base.base)
11491                   {
11492                      for(prop = base.membersAndProperties.first; prop; prop = prop.next)
11493                      {
11494                         if(prop.isProperty && prop.isWatchable)
11495                         {
11496                            CreateFireWatcher(prop, object, stmt);
11497                         }
11498                      }
11499                   }
11500                }
11501
11502                if(object)
11503                   FreeExpression(object);
11504                FreeList(watches, FreeIdentifier);
11505             }
11506             else
11507                Compiler_Error($"Invalid object specified and not inside a class\n");
11508          }
11509          break;
11510       }
11511       case stopWatchingStmt:
11512       {
11513          OldList * watches = stmt._watch.watches;
11514          Expression object = stmt._watch.object;
11515          Expression watcher = stmt._watch.watcher;
11516          Class _class;
11517          if(object)
11518             ProcessExpressionType(object);
11519          if(watcher)
11520             ProcessExpressionType(watcher);
11521          if(inCompiler)
11522          {
11523             _class = (object && object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null;
11524
11525             if(watcher || thisClass)
11526             {
11527                if(_class)
11528                {
11529                   Identifier propID;
11530
11531                   stmt.type = expressionStmt;
11532                   stmt.expressions = MkList();
11533
11534                   if(!watches)
11535                   {
11536                      OldList * args;
11537                      // eInstance_StopWatching(object, null, watcher); 
11538                      args = MkList();
11539                      ListAdd(args, CopyExpression(object));
11540                      ListAdd(args, MkExpConstant("0"));
11541                      ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11542                      ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11543                   }
11544                   else
11545                   {
11546                      for(propID = watches->first; propID; propID = propID.next)
11547                      {
11548                         char propName[1024];
11549                         Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11550                         if(prop)
11551                         {
11552                            char getName[1024], setName[1024];
11553                            OldList * args = MkList();
11554
11555                            DeclareProperty(prop, setName, getName);
11556          
11557                            // eInstance_StopWatching(object, prop, watcher); 
11558                            strcpy(propName, "__ecereProp_");
11559                            FullClassNameCat(propName, prop._class.fullName, false);
11560                            strcat(propName, "_");
11561                            // strcat(propName, prop.name);
11562                            FullClassNameCat(propName, prop.name, true);
11563                            MangleClassName(propName);
11564
11565                            ListAdd(args, CopyExpression(object));
11566                            ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11567                            ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11568                            ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11569                         }
11570                         else
11571                            Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
11572                      }
11573                   }
11574
11575                   if(object)
11576                      FreeExpression(object);
11577                   if(watcher)
11578                      FreeExpression(watcher);
11579                   FreeList(watches, FreeIdentifier);
11580                }
11581                else
11582                   Compiler_Error($"Invalid object specified and not inside a class\n");
11583             }
11584             else
11585                Compiler_Error($"No observer specified and not inside a class\n");
11586          }
11587          break;
11588       }
11589    }
11590 }
11591
11592 static void ProcessFunction(FunctionDefinition function)
11593 {
11594    Identifier id = GetDeclId(function.declarator);
11595    Symbol symbol = function.declarator ? function.declarator.symbol : null;
11596    Type type = symbol ? symbol.type : null;
11597    Class oldThisClass = thisClass;
11598    Context oldTopContext = topContext;
11599
11600    yylloc = function.loc;
11601    // Process thisClass
11602    
11603    if(type && type.thisClass)
11604    {
11605       Symbol classSym = type.thisClass;
11606       Class _class = type.thisClass.registered;
11607       char className[1024];
11608       char structName[1024];
11609       Declarator funcDecl;
11610       Symbol thisSymbol;
11611
11612       bool typedObject = false;
11613
11614       if(_class && !_class.base)
11615       {
11616          _class = currentClass;
11617          if(_class && !_class.symbol)
11618             _class.symbol = FindClass(_class.fullName);
11619          classSym = _class ? _class.symbol : null;
11620          typedObject = true;
11621       }
11622
11623       thisClass = _class;
11624
11625       if(inCompiler && _class)
11626       {
11627          if(type.kind == functionType)
11628          {
11629             if(symbol.type.params.count == 1 && ((Type)symbol.type.params.first).kind == voidType)
11630             {
11631                //TypeName param = symbol.type.params.first;
11632                Type param = symbol.type.params.first;
11633                symbol.type.params.Remove(param);
11634                //FreeTypeName(param);
11635                FreeType(param);
11636             }
11637             if(type.classObjectType != classPointer)
11638             {
11639                symbol.type.params.Insert(null, MkClassType(_class.fullName));
11640                symbol.type.staticMethod = true;
11641                symbol.type.thisClass = null;
11642
11643                // HIGH DANGER: VERIFYING THIS...
11644                symbol.type.extraParam = false;
11645             }
11646          }
11647
11648          strcpy(className, "__ecereClass_");
11649          FullClassNameCat(className, _class.fullName, true);
11650
11651          MangleClassName(className);
11652
11653          structName[0] = 0;
11654          FullClassNameCat(structName, _class.fullName, false);
11655
11656          // [class] this
11657          
11658
11659          funcDecl = GetFuncDecl(function.declarator);
11660          if(funcDecl)
11661          {
11662             if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11663             {
11664                TypeName param = funcDecl.function.parameters->first;
11665                if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11666                {
11667                   funcDecl.function.parameters->Remove(param);
11668                   FreeTypeName(param);
11669                }
11670             }
11671
11672             // DANGER: Watch for this... Check if it's a Conversion?
11673             // if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11674             
11675             // WAS TRYING THIS FOR CONVERSION PROPERTIES ON NOHEAD CLASSES: if((_class.type == structClass) || function != (FunctionDefinition)symbol.externalSet)
11676             if(!function.propertyNoThis)
11677             {
11678                TypeName thisParam;
11679                
11680                if(type.classObjectType != classPointer)
11681                {
11682                   thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11683                   if(!funcDecl.function.parameters)
11684                      funcDecl.function.parameters = MkList();
11685                   funcDecl.function.parameters->Insert(null, thisParam);
11686                }
11687
11688                if(typedObject)
11689                {
11690                   if(type.classObjectType != classPointer)
11691                   {
11692                      if(type.byReference || _class.type == unitClass || _class.type == systemClass || _class.type == enumClass || _class.type == bitClass)
11693                         thisParam.declarator = MkDeclaratorPointer(MkPointer(null,null), thisParam.declarator);
11694                   }
11695
11696                   thisParam = TypeName
11697                   {
11698                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
11699                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
11700                   };
11701                   funcDecl.function.parameters->Insert(null, thisParam);
11702                }
11703             }
11704          }
11705
11706          if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11707          {
11708             InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11709             funcDecl = GetFuncDecl(initDecl.declarator);
11710             if(funcDecl)
11711             {
11712                if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11713                {
11714                   TypeName param = funcDecl.function.parameters->first;
11715                   if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11716                   {
11717                      funcDecl.function.parameters->Remove(param);
11718                      FreeTypeName(param);
11719                   }
11720                }
11721
11722                if(type.classObjectType != classPointer)
11723                {
11724                   // DANGER: Watch for this... Check if it's a Conversion?
11725                   if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11726                   {
11727                      TypeName thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11728
11729                      if(!funcDecl.function.parameters)
11730                         funcDecl.function.parameters = MkList();
11731                      funcDecl.function.parameters->Insert(null, thisParam);
11732                   }
11733                }
11734             }         
11735          }
11736       }
11737       
11738       // Add this to the context
11739       if(function.body)
11740       {
11741          if(type.classObjectType != classPointer)
11742          {
11743             thisSymbol = Symbol
11744             {
11745                string = CopyString("this");
11746                type = classSym ? MkClassType(classSym.string) : null; //_class.fullName);
11747             };
11748             function.body.compound.context.symbols.Add((BTNode)thisSymbol);
11749
11750             if(typedObject && thisSymbol.type)
11751             {
11752                thisSymbol.type.classObjectType = ClassObjectType::typedObject;
11753                thisSymbol.type.byReference = type.byReference;
11754                /*
11755                thisSymbol = Symbol { string = CopyString("class") };
11756                function.body.compound.context.symbols.Add(thisSymbol);
11757                */
11758             }
11759          }
11760       }
11761
11762       // Pointer to class data
11763       
11764       if(inCompiler && _class && (_class.type == normalClass /*|| _class.type == noHeadClass*/) && type.classObjectType != classPointer)
11765       {
11766          DataMember member = null;
11767          {
11768             Class base;
11769             for(base = _class; base && base.type != systemClass; base = base.next)
11770             {
11771                for(member = base.membersAndProperties.first; member; member = member.next)
11772                   if(!member.isProperty)
11773                      break;
11774                if(member)
11775                   break;
11776             }
11777          }
11778          for(member = _class.membersAndProperties.first; member; member = member.next)
11779             if(!member.isProperty)
11780                break;
11781          if(member)
11782          {
11783             char pointerName[1024];
11784    
11785             Declaration decl;
11786             Initializer initializer;
11787             Expression exp, bytePtr;
11788    
11789             strcpy(pointerName, "__ecerePointer_");
11790             FullClassNameCat(pointerName, _class.fullName, false);
11791             {
11792                char className[1024];
11793                strcpy(className, "__ecereClass_");
11794                FullClassNameCat(className, classSym.string, true);
11795                MangleClassName(className);
11796
11797                // Testing This
11798                DeclareClass(classSym, className);
11799             }
11800
11801             // ((byte *) this)
11802             bytePtr = QBrackets(MkExpCast(QMkType("char", QMkPtrDecl(null)), QMkExpId("this")));
11803
11804             if(_class.fixed)
11805             {
11806                char string[256];
11807                sprintf(string, "%d", _class.offset);
11808                exp = QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string)));
11809             }
11810             else
11811             {
11812                // ([bytePtr] + [className]->offset)
11813                exp = QBrackets(MkExpOp(bytePtr, '+',
11814                   MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
11815             }
11816
11817             // (this ? [exp] : 0)
11818             exp = QBrackets(QMkExpCond(QMkExpId("this"), exp, MkExpConstant("0")));
11819             exp.expType = Type
11820             {
11821                refCount = 1;
11822                kind = pointerType;
11823                type = Type { refCount = 1, kind = voidType };
11824             };
11825    
11826             if(function.body)
11827             {
11828                yylloc = function.body.loc;
11829                // ([structName] *) [exp]
11830                // initializer = MkInitializerAssignment(MkExpCast(QMkType(structName, QMkPtrDecl(null)), exp));
11831                initializer = MkInitializerAssignment(
11832                   MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), exp));
11833
11834                // [structName] * [pointerName] = [initializer];
11835                // decl = QMkDeclaration(structName, MkInitDeclarator(QMkPtrDecl(pointerName), initializer));
11836
11837                {
11838                   Context prevContext = curContext;
11839                   curContext = function.body.compound.context;
11840
11841                   decl = MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
11842                      MkListOne(MkInitDeclarator(QMkPtrDecl(pointerName), initializer)));
11843
11844                   curContext = prevContext;
11845                }
11846
11847                // WHY?
11848                decl.symbol = null;
11849
11850                if(!function.body.compound.declarations)
11851                   function.body.compound.declarations = MkList();
11852                function.body.compound.declarations->Insert(null, decl);
11853             }
11854          }
11855       }
11856       
11857
11858       // Loop through the function and replace undeclared identifiers
11859       // which are a member of the class (methods, properties or data)
11860       // by "this.[member]"
11861    }
11862    else
11863       thisClass = null;
11864
11865    if(id)
11866    {
11867       FreeSpecifier(id._class);
11868       id._class = null;
11869
11870       if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11871       {
11872          InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11873          id = GetDeclId(initDecl.declarator);
11874
11875          FreeSpecifier(id._class);
11876          id._class = null;
11877       }
11878    }
11879    if(function.body)
11880       topContext = function.body.compound.context;
11881    {
11882       FunctionDefinition oldFunction = curFunction;
11883       curFunction = function;
11884       if(function.body)
11885          ProcessStatement(function.body);
11886
11887       // If this is a property set and no firewatchers has been done yet, add one here
11888       if(inCompiler && function.propSet && !function.propSet.fireWatchersDone)
11889       {
11890          Statement prevCompound = curCompound;
11891          Context prevContext = curContext;
11892
11893          Statement fireWatchers = MkFireWatchersStmt(null, null);
11894          if(!function.body.compound.statements) function.body.compound.statements = MkList();
11895          ListAdd(function.body.compound.statements, fireWatchers);
11896
11897          curCompound = function.body;
11898          curContext = function.body.compound.context;
11899
11900          ProcessStatement(fireWatchers);
11901
11902          curContext = prevContext;
11903          curCompound = prevCompound;
11904
11905       }
11906
11907       curFunction = oldFunction;
11908    }
11909
11910    if(function.declarator)
11911    {
11912       ProcessDeclarator(function.declarator);
11913    }
11914
11915    topContext = oldTopContext;
11916    thisClass = oldThisClass;
11917 }
11918
11919 /////////// INSTANTIATIONS / DATA TYPES PASS /////////////////////////////////////////////
11920 static void ProcessClass(OldList definitions, Symbol symbol)
11921 {
11922    ClassDef def;
11923    External external = curExternal;
11924    Class regClass = symbol ? symbol.registered : null;
11925
11926    // Process all functions
11927    for(def = definitions.first; def; def = def.next)
11928    {
11929       if(def.type == functionClassDef)
11930       {
11931          if(def.function.declarator)
11932             curExternal = def.function.declarator.symbol.pointerExternal;
11933          else
11934             curExternal = external;
11935
11936          ProcessFunction((FunctionDefinition)def.function);
11937       }
11938       else if(def.type == declarationClassDef)
11939       {
11940          if(def.decl.type == instDeclaration)
11941          {
11942             thisClass = regClass;
11943             ProcessInstantiationType(def.decl.inst);
11944             thisClass = null;
11945          }
11946          // Testing this
11947          else
11948          {
11949             Class backThisClass = thisClass;
11950             if(regClass) thisClass = regClass;
11951             ProcessDeclaration(def.decl);
11952             thisClass = backThisClass;
11953          }
11954       }
11955       else if(def.type == defaultPropertiesClassDef && def.defProperties)
11956       {
11957          MemberInit defProperty;
11958
11959          // Add this to the context
11960          Symbol thisSymbol = Symbol
11961          {
11962             string = CopyString("this");
11963             type = regClass ? MkClassType(regClass.fullName) : null;
11964          };
11965          globalContext.symbols.Add((BTNode)thisSymbol);
11966          
11967          for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
11968          {
11969             thisClass = regClass;
11970             ProcessMemberInitData(defProperty, regClass, null, null, null, null);
11971             thisClass = null;
11972          }
11973
11974          globalContext.symbols.Remove((BTNode)thisSymbol);
11975          FreeSymbol(thisSymbol);
11976       }
11977       else if(def.type == propertyClassDef && def.propertyDef)
11978       {
11979          PropertyDef prop = def.propertyDef;
11980
11981          // Add this to the context
11982          /*
11983          Symbol thisSymbol = Symbol { string = CopyString("this"), type = MkClassType(regClass.fullName) };
11984          globalContext.symbols.Add(thisSymbol);
11985          */
11986          
11987          thisClass = regClass;
11988          if(prop.setStmt)
11989          {
11990             if(regClass)
11991             {
11992                Symbol thisSymbol
11993                {
11994                   string = CopyString("this");
11995                   type = MkClassType(regClass.fullName);
11996                };
11997                prop.setStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11998             }
11999
12000             curExternal = prop.symbol ? prop.symbol.externalSet : null;
12001             ProcessStatement(prop.setStmt);
12002          }
12003          if(prop.getStmt)
12004          {
12005             if(regClass)
12006             {
12007                Symbol thisSymbol
12008                {
12009                   string = CopyString("this");
12010                   type = MkClassType(regClass.fullName);
12011                };
12012                prop.getStmt.compound.context.symbols.Add((BTNode)thisSymbol);
12013             }
12014
12015             curExternal = prop.symbol ? prop.symbol.externalGet : null;
12016             ProcessStatement(prop.getStmt);
12017          }
12018          if(prop.issetStmt)
12019          {
12020             if(regClass)
12021             {
12022                Symbol thisSymbol
12023                {
12024                   string = CopyString("this");
12025                   type = MkClassType(regClass.fullName);
12026                };
12027                prop.issetStmt.compound.context.symbols.Add((BTNode)thisSymbol);
12028             }
12029
12030             curExternal = prop.symbol ? prop.symbol.externalIsSet : null;
12031             ProcessStatement(prop.issetStmt);
12032          }
12033
12034          thisClass = null;
12035
12036          /*
12037          globalContext.symbols.Remove(thisSymbol);
12038          FreeSymbol(thisSymbol);
12039          */
12040       }
12041       else if(def.type == propertyWatchClassDef && def.propertyWatch)
12042       {
12043          PropertyWatch propertyWatch = def.propertyWatch;
12044         
12045          thisClass = regClass;
12046          if(propertyWatch.compound)
12047          {
12048             Symbol thisSymbol
12049             {
12050                string = CopyString("this");
12051                type = regClass ? MkClassType(regClass.fullName) : null;
12052             };
12053
12054             propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
12055
12056             curExternal = null;
12057             ProcessStatement(propertyWatch.compound);
12058          }
12059          thisClass = null;
12060       }
12061    }
12062 }
12063
12064 void ComputeDataTypes()
12065 {
12066    External external;
12067    External temp { };
12068    currentClass = null;
12069
12070    containerClass = eSystem_FindClass(GetPrivateModule(), "Container");
12071
12072    temp.symbol = Symbol { id = -1000, idCode = -1000 };
12073
12074    // WHERE SHOULD THIS GO?
12075    // curExternal = ast->first;
12076    ast->Insert(null, temp);
12077
12078    curExternal = temp;
12079
12080    DeclareStruct("ecere::com::Class", false);
12081    DeclareStruct("ecere::com::Instance", false);
12082    DeclareStruct("ecere::com::Property", false);
12083    DeclareStruct("ecere::com::DataMember", false);
12084    DeclareStruct("ecere::com::Method", false);
12085    DeclareStruct("ecere::com::SerialBuffer", false);
12086    DeclareStruct("ecere::com::ClassTemplateArgument", false);
12087
12088    ast->Remove(temp);
12089
12090    for(external = ast->first; external; external = external.next)
12091    {
12092       afterExternal = curExternal = external;
12093       if(external.type == functionExternal)
12094       {
12095          currentClass = external.function._class;
12096          ProcessFunction(external.function);
12097       }
12098       // There shouldn't be any _class member access here anyways...
12099       else if(external.type == declarationExternal)
12100       {
12101          currentClass = null;
12102          ProcessDeclaration(external.declaration);
12103       }
12104       else if(external.type == classExternal)
12105       {
12106          ClassDefinition _class = external._class;
12107          currentClass = external.symbol.registered;
12108          if(_class.definitions)
12109          {
12110             ProcessClass(_class.definitions, _class.symbol);
12111          }
12112          if(inCompiler)
12113          {
12114             // Free class data...
12115             ast->Remove(external);
12116             delete external;
12117          }
12118       }
12119       else if(external.type == nameSpaceExternal)
12120       {
12121          thisNameSpace = external.id.string;
12122       }
12123    }
12124    currentClass = null;
12125    thisNameSpace = null;
12126
12127    delete temp.symbol;
12128    delete temp;
12129 }