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