ecere & compiler: Built-in internationalization support
[sdk] / compiler / libec / src / pass15.ec
1 import "ecdefs"
2
3 #define uint _uint
4 #include <stdlib.h>  // For strtoll
5 #undef uint
6
7 // UNTIL IMPLEMENTED IN GRAMMAR
8 #define ACCESS_CLASSDATA(_class, baseClass) \
9    (_class ? ((void *)(((char *)_class.data) + baseClass.offsetClass)) : null)
10
11 #define YYLTYPE Location
12 #include "grammar.eh"
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             return true;
3633          }
3634       }
3635       else if(source.kind == classType)
3636       {
3637          Class _class = source._class ? source._class.registered : null;
3638
3639          if(_class && (_class.type == unitClass || !strcmp(_class.fullName, "bool") || /*_class.type == enumClass || */_class.type == bitClass ))  // TOCHECK: enumClass, bitClass is new here...
3640          {
3641             /*
3642             if(dest.kind != classType)
3643             {
3644                // Testing this simpler piece of code... (Broke Units Conversion to no unit Logic)
3645                if(!source._class.registered.dataType)
3646                   source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3647                
3648                FreeType(dest);
3649                dest = MkClassType(source._class.string);
3650                //if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, false, false))
3651                //   dest = MkClassType(source._class.string);
3652             }
3653             */
3654             
3655             if(dest.kind != classType)
3656             {
3657                Type tempType { };
3658                Type tempDest, tempSource;
3659
3660                if(!source._class.registered.dataType)
3661                   source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3662
3663                for(; _class.base.type != systemClass; _class = _class.base);
3664                tempDest = source;
3665                tempSource = tempType;
3666                tempType.kind = classType;
3667                tempType._class = FindClass(_class.fullName);
3668                tempType.truth = source.truth;
3669                tempType.classObjectType = source.classObjectType;
3670
3671                if(tempType._class)
3672                   MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
3673                
3674                // PUT THIS BACK TESTING UNITS?
3675                if(conversions.last)
3676                {
3677                   ((Conversion)(conversions.last)).resultType = dest;
3678                   dest.refCount++;
3679                }
3680                
3681                FreeType(sourceExp.expType);
3682                sourceExp.expType = MkClassType(_class.fullName);
3683                sourceExp.expType.truth = source.truth;
3684                sourceExp.expType.classObjectType = source.classObjectType;
3685
3686                // *** This if was commented out, put it back because "int a =^ Destroy()" shows up bool enum values in autocomplete ***
3687
3688                if(!sourceExp.destType)
3689                {
3690                   FreeType(sourceExp.destType);
3691                   sourceExp.destType = sourceExp.expType;
3692                   if(sourceExp.expType)
3693                      sourceExp.expType.refCount++;
3694                }
3695                //flag = true;
3696                //source = _class.dataType;
3697
3698
3699                // TOCHECK: TESTING THIS NEW CODE
3700                if(!_class.dataType)
3701                   _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3702                FreeType(dest);
3703                dest = MkClassType(source._class.string);
3704                dest.truth = source.truth;
3705                dest.classObjectType = source.classObjectType;
3706                
3707                FreeType(source);
3708                source = _class.dataType;
3709                source.refCount++;
3710
3711                delete tempType;
3712             }
3713          }
3714       }
3715
3716       if(!flag)
3717       {
3718          if(MatchTypes(source, dest, conversions, null, null, true, true, false, false))
3719          {
3720             FreeType(source);
3721             FreeType(dest);
3722             return true;
3723          }
3724       }
3725
3726       // Implicit Casts
3727       /*
3728       if(source.kind == classType)
3729       {
3730          Class _class = source._class.registered;
3731          if(_class.type == unitClass)
3732          {
3733             if(!_class.dataType)
3734                _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3735             source = _class.dataType;
3736          }
3737       }*/
3738
3739       if(dest.kind == classType)
3740       {
3741          Class _class = dest._class ? dest._class.registered : null;
3742          if(_class && !dest.truth && (_class.type == unitClass || !strcmp(_class.fullName, "bool") || 
3743             (/*_class.type == enumClass*/_class.type != structClass && !value && source.kind == intType) || _class.type == bitClass))   // TOCHECK: enumClass, bitClass is new here...
3744          {
3745             if(_class.type == normalClass || _class.type == noHeadClass)
3746             {
3747                Expression newExp { };
3748                *newExp = *sourceExp;
3749                if(sourceExp.destType) sourceExp.destType.refCount++;
3750                if(sourceExp.expType)  sourceExp.expType.refCount++;
3751                sourceExp.type = castExp;
3752                sourceExp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null));
3753                sourceExp.cast.exp = newExp;
3754                FreeType(sourceExp.expType);
3755                sourceExp.expType = null;
3756                ProcessExpressionType(sourceExp);
3757
3758                // In Debugger, this helps with addresses (e.g. null pointers) that end up casted to a void *: keeps a classType instead of a pointerType
3759                if(!inCompiler)
3760                {
3761                   FreeType(sourceExp.expType);
3762                   sourceExp.expType = dest;
3763                }
3764
3765                FreeType(source);
3766                if(inCompiler) FreeType(dest);
3767
3768                return true;
3769             }
3770
3771             if(!_class.dataType)
3772                _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3773             FreeType(dest);
3774             dest = _class.dataType;
3775             dest.refCount++;
3776          }
3777
3778          // Accept lower precision types for units, since we want to keep the unit type
3779          if(dest.kind == doubleType && 
3780             (source.kind == doubleType || source.kind == floatType || dest.kind == int64Type || source.kind == intType || source.kind == shortType ||
3781              source.kind == charType))
3782          {
3783             specs = MkListOne(MkSpecifier(DOUBLE));
3784          }
3785          else if(dest.kind == floatType && 
3786             (source.kind == floatType || dest.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType ||
3787             source.kind == doubleType))
3788          {
3789             specs = MkListOne(MkSpecifier(FLOAT));
3790          }
3791          else if(dest.kind == int64Type && (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType ||
3792             source.kind == floatType || source.kind == doubleType))
3793          {
3794             specs = MkList();
3795             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3796             ListAdd(specs, MkSpecifier(INT64));
3797          }
3798          else if(dest.kind == intType && (source.kind == intType || source.kind == shortType || source.kind == charType ||
3799             source.kind == floatType || source.kind == doubleType))
3800          {
3801             specs = MkList();
3802             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3803             ListAdd(specs, MkSpecifier(INT));
3804          }
3805          else if(dest.kind == shortType && (source.kind == shortType || source.kind == charType || source.kind == intType ||
3806             source.kind == floatType || source.kind == doubleType))
3807          {
3808             specs = MkList();
3809             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3810             ListAdd(specs, MkSpecifier(SHORT));
3811          }
3812          else if(dest.kind == charType && (source.kind == charType || source.kind == shortType || source.kind == intType ||
3813             source.kind == floatType || source.kind == doubleType))
3814          {
3815             specs = MkList();
3816             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3817             ListAdd(specs, MkSpecifier(CHAR));
3818          }
3819          else
3820          {
3821             FreeType(source);
3822             FreeType(dest);
3823             return false;
3824          }
3825       }
3826       else if(dest.kind == doubleType && 
3827          (source.kind == doubleType || source.kind == floatType || source.kind == int64Type || source.kind == intType || source.kind == enumType || source.kind == shortType ||
3828           source.kind == charType))
3829       {
3830          specs = MkListOne(MkSpecifier(DOUBLE));
3831       }
3832       else if(dest.kind == floatType && 
3833          (source.kind == floatType || source.kind == enumType || source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType))
3834       {
3835          specs = MkListOne(MkSpecifier(FLOAT));
3836       }
3837       else if(dest.kind == charType && (source.kind == charType || source.kind == enumType || source.kind == shortType || source.kind == intType) && 
3838          (dest.isSigned ? (value >= -128 && value <= 127) : (value >= 0 && value <= 255)))
3839       {
3840          specs = MkList();
3841          if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3842          ListAdd(specs, MkSpecifier(CHAR));
3843       }
3844       else if(dest.kind == shortType && (source.kind == enumType || source.kind == charType || source.kind == shortType || 
3845          (source.kind == intType && (dest.isSigned ? (value >= -32768 && value <= 32767) : (value >= 0 && value <= 65535)))))
3846       {
3847          specs = MkList();
3848          if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3849          ListAdd(specs, MkSpecifier(SHORT));
3850       }
3851       else if(dest.kind == intType && (source.kind == enumType || source.kind == shortType || source.kind == charType || source.kind == intType))
3852       {
3853          specs = MkList();
3854          if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3855          ListAdd(specs, MkSpecifier(INT));
3856       }
3857       else if(dest.kind == int64Type && (source.kind == enumType || source.kind == shortType || source.kind == charType || source.kind == intType || source.kind == int64Type))
3858       {
3859          specs = MkList();
3860          if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3861          ListAdd(specs, MkSpecifier(INT64));
3862       }
3863       else if(dest.kind == enumType && 
3864          (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType))
3865       {
3866          specs = MkListOne(MkEnum(MkIdentifier(dest.enumName), null));
3867       }
3868       else
3869       {
3870          FreeType(source);
3871          FreeType(dest);
3872          return false;
3873       }
3874
3875       if(!flag)
3876       {
3877          Expression newExp { };
3878          *newExp = *sourceExp;
3879          newExp.prev = null;
3880          newExp.next = null;
3881          if(sourceExp.destType) sourceExp.destType.refCount++;
3882          if(sourceExp.expType)  sourceExp.expType.refCount++;
3883
3884          sourceExp.type = castExp;
3885          if(realDest.kind == classType)
3886          {
3887             sourceExp.cast.typeName = QMkClass(realDest._class.string, null);
3888             FreeList(specs, FreeSpecifier);
3889          }
3890          else
3891             sourceExp.cast.typeName = MkTypeName(specs, null);
3892          if(newExp.type == opExp)
3893          {
3894             sourceExp.cast.exp = MkExpBrackets(MkListOne(newExp));
3895          }
3896          else
3897             sourceExp.cast.exp = newExp;
3898          
3899          FreeType(sourceExp.expType);
3900          sourceExp.expType = null;
3901          ProcessExpressionType(sourceExp);
3902       }
3903       else
3904          FreeList(specs, FreeSpecifier);
3905
3906       FreeType(dest);
3907       FreeType(source);
3908       return true;
3909    }
3910    else
3911    {
3912       while((sourceExp.type == bracketsExp || sourceExp.type == extensionExpressionExp) && sourceExp.list) sourceExp = sourceExp.list->last;
3913       if(sourceExp.type == identifierExp)
3914       {
3915          Identifier id = sourceExp.identifier;
3916          if(dest.kind == classType)
3917          {
3918             if(dest._class && dest._class.registered && dest._class.registered.type == enumClass)
3919             {
3920                Class _class = dest._class.registered;
3921                Class enumClass = eSystem_FindClass(privateModule, "enum");
3922                if(enumClass)
3923                {
3924                   for( ; _class && _class.type == ClassType::enumClass; _class = _class.base)
3925                   {
3926                      NamedLink value;
3927                      EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
3928                      for(value = e.values.first; value; value = value.next)
3929                      {
3930                         if(!strcmp(value.name, id.string))
3931                            break;
3932                      }
3933                      if(value)
3934                      {
3935                         FreeExpContents(sourceExp);
3936                         FreeType(sourceExp.expType);
3937
3938                         sourceExp.isConstant = true;
3939                         sourceExp.expType = MkClassType(_class.fullName);
3940                         //if(inCompiler)
3941                         {
3942                            char constant[256];
3943                            sourceExp.type = constantExp;
3944                            if(/*_class && */_class.dataTypeString && !strcmp(_class.dataTypeString, "int")) // _class cannot be null here!
3945                               sprintf(constant, "%d",value.data);
3946                            else
3947                               sprintf(constant, "0x%X",value.data);
3948                            sourceExp.constant = CopyString(constant);
3949                            //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
3950                         }
3951                         return true;
3952                      }
3953                   }
3954                }
3955             }
3956          }
3957
3958          // Loop through all enum classes
3959          if(dest.classObjectType != typedObject && dest.kind == classType /*!= ellipsisType */&& MatchWithEnums_Module(privateModule, sourceExp, dest, id.string, conversions))
3960             return true;
3961       }
3962    }
3963    return false;
3964 }
3965
3966 #define TERTIARY(o, name, m, t, p) \
3967    static bool name(Expression exp, Operand op1, Operand op2, Operand op3)   \
3968    {                                                              \
3969       exp.type = constantExp;                                    \
3970       exp.string = p(op1.m ? op2.m : op3.m);                     \
3971       if(!exp.expType) \
3972          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
3973       return true;                                                \
3974    }
3975
3976 #define BINARY(o, name, m, t, p) \
3977    static bool name(Expression exp, Operand op1, Operand op2)   \
3978    {                                                              \
3979       t value2 = op2.m;                                           \
3980       exp.type = constantExp;                                    \
3981       exp.string = p(op1.m o value2);                     \
3982       if(!exp.expType) \
3983          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
3984       return true;                                                \
3985    }
3986
3987 #define BINARY_DIVIDE(o, name, m, t, p) \
3988    static bool name(Expression exp, Operand op1, Operand op2)   \
3989    {                                                              \
3990       t value2 = op2.m;                                           \
3991       exp.type = constantExp;                                    \
3992       exp.string = p(value2 ? (op1.m o value2) : 0);             \
3993       if(!exp.expType) \
3994          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
3995       return true;                                                \
3996    }
3997
3998 #define UNARY(o, name, m, t, p) \
3999    static bool name(Expression exp, Operand op1)                \
4000    {                                                              \
4001       exp.type = constantExp;                                    \
4002       exp.string = p(o op1.m);                                   \
4003       if(!exp.expType) \
4004          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
4005       return true;                                                \
4006    }
4007
4008 #define OPERATOR_ALL(macro, o, name) \
4009    macro(o, Int##name, i, int, PrintInt) \
4010    macro(o, UInt##name, ui, unsigned int, PrintUInt) \
4011    macro(o, Short##name, s, short, PrintShort) \
4012    macro(o, UShort##name, us, unsigned short, PrintUShort) \
4013    macro(o, Char##name, c, char, PrintChar) \
4014    macro(o, UChar##name, uc, unsigned char, PrintUChar) \
4015    macro(o, Float##name, f, float, PrintFloat) \
4016    macro(o, Double##name, d, double, PrintDouble)
4017
4018 #define OPERATOR_INTTYPES(macro, o, name) \
4019    macro(o, Int##name, i, int, PrintInt) \
4020    macro(o, UInt##name, ui, unsigned int, PrintUInt) \
4021    macro(o, Short##name, s, short, PrintShort) \
4022    macro(o, UShort##name, us, unsigned short, PrintUShort) \
4023    macro(o, Char##name, c, char, PrintChar) \
4024    macro(o, UChar##name, uc, unsigned char, PrintUChar)
4025
4026
4027 // binary arithmetic
4028 OPERATOR_ALL(BINARY, +, Add)
4029 OPERATOR_ALL(BINARY, -, Sub)
4030 OPERATOR_ALL(BINARY, *, Mul)
4031 OPERATOR_ALL(BINARY_DIVIDE, /, Div)
4032 OPERATOR_INTTYPES(BINARY_DIVIDE, %, Mod)
4033
4034 // unary arithmetic
4035 OPERATOR_ALL(UNARY, -, Neg)
4036
4037 // unary arithmetic increment and decrement
4038 OPERATOR_ALL(UNARY, ++, Inc)
4039 OPERATOR_ALL(UNARY, --, Dec)
4040
4041 // binary arithmetic assignment
4042 OPERATOR_ALL(BINARY, =, Asign)
4043 OPERATOR_ALL(BINARY, +=, AddAsign)
4044 OPERATOR_ALL(BINARY, -=, SubAsign)
4045 OPERATOR_ALL(BINARY, *=, MulAsign)
4046 OPERATOR_ALL(BINARY_DIVIDE, /=, DivAsign)
4047 OPERATOR_INTTYPES(BINARY_DIVIDE, %=, ModAsign)
4048
4049 // binary bitwise
4050 OPERATOR_INTTYPES(BINARY, &, BitAnd)
4051 OPERATOR_INTTYPES(BINARY, |, BitOr)
4052 OPERATOR_INTTYPES(BINARY, ^, BitXor)
4053 OPERATOR_INTTYPES(BINARY, <<, LShift)
4054 OPERATOR_INTTYPES(BINARY, >>, RShift)
4055
4056 // unary bitwise
4057 OPERATOR_INTTYPES(UNARY, ~, BitNot)
4058
4059 // binary bitwise assignment
4060 OPERATOR_INTTYPES(BINARY, &=, AndAsign)
4061 OPERATOR_INTTYPES(BINARY, |=, OrAsign)
4062 OPERATOR_INTTYPES(BINARY, ^=, XorAsign)
4063 OPERATOR_INTTYPES(BINARY, <<=, LShiftAsign)
4064 OPERATOR_INTTYPES(BINARY, >>=, RShiftAsign)
4065
4066 // unary logical negation
4067 OPERATOR_INTTYPES(UNARY, !, Not)
4068
4069 // binary logical equality
4070 OPERATOR_ALL(BINARY, ==, Equ)
4071 OPERATOR_ALL(BINARY, !=, Nqu)
4072
4073 // binary logical
4074 OPERATOR_ALL(BINARY, &&, And)
4075 OPERATOR_ALL(BINARY, ||, Or)
4076
4077 // binary logical relational
4078 OPERATOR_ALL(BINARY, >, Grt)
4079 OPERATOR_ALL(BINARY, <, Sma)
4080 OPERATOR_ALL(BINARY, >=, GrtEqu)
4081 OPERATOR_ALL(BINARY, <=, SmaEqu)
4082
4083 // tertiary condition operator
4084 OPERATOR_ALL(TERTIARY, ?, Cond)
4085
4086 //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
4087 #define OPERATOR_TABLE_ALL(name, type) \
4088     OpTable name##Ops = { type##Add, type##Sub, type##Mul, type##Div, type##Mod, \
4089                           type##Neg, \
4090                           type##Inc, type##Dec, \
4091                           type##Asign, type##AddAsign, type##SubAsign, type##MulAsign, type##DivAsign, type##ModAsign, \
4092                           type##BitAnd, type##BitOr, type##BitXor, type##LShift, type##RShift, \
4093                           type##BitNot, \
4094                           type##AndAsign, type##OrAsign, type##XorAsign, type##LShiftAsign, type##RShiftAsign, \
4095                           type##Not, \
4096                           type##Equ, type##Nqu, \
4097                           type##And, type##Or, \
4098                           type##Grt, type##Sma, type##GrtEqu, type##SmaEqu, type##Cond \
4099                         }; \
4100
4101 #define OPERATOR_TABLE_INTTYPES(name, type) \
4102     OpTable name##Ops = { type##Add, type##Sub, type##Mul, type##Div, null, \
4103                           type##Neg, \
4104                           type##Inc, type##Dec, \
4105                           type##Asign, type##AddAsign, type##SubAsign, type##MulAsign, type##DivAsign, null, \
4106                           null, null, null, null, null, \
4107                           null, \
4108                           null, null, null, null, null, \
4109                           null, \
4110                           type##Equ, type##Nqu, \
4111                           type##And, type##Or, \
4112                           type##Grt, type##Sma, type##GrtEqu, type##SmaEqu \
4113                         }; \
4114
4115 OPERATOR_TABLE_ALL(int, Int)
4116 OPERATOR_TABLE_ALL(uint, UInt)
4117 OPERATOR_TABLE_ALL(short, Short)
4118 OPERATOR_TABLE_ALL(ushort, UShort)
4119 OPERATOR_TABLE_INTTYPES(float, Float)
4120 OPERATOR_TABLE_INTTYPES(double, Double)
4121 OPERATOR_TABLE_ALL(char, Char)
4122 OPERATOR_TABLE_ALL(uchar, UChar)
4123
4124 //OpTable intOps =    {    IntAdd,    IntSub,    IntMul,    IntDiv,    IntMod,    IntExp,    IntNot,    IntBwn,    IntOr,    IntAnd,    IntEqu,    IntNqu,    IntGrt,    IntSma,    IntGrtEqu,    IntSmaEqu,    IntNeg,    IntLBitSft,    IntRBitSft };
4125 //OpTable uintOps =   {   UIntAdd,   UIntSub,   UIntMul,   UIntDiv,   UIntMod,   UIntExp,   UIntNot,   UIntBwn,   UIntOr,   UIntAnd,   UIntEqu,   UIntNqu,   UIntGrt,   UIntSma,   UIntGrtEqu,   UIntSmaEqu,   UIntNeg,   UIntLBitSft,   UIntRBitSft };
4126 //OpTable shortOps =  {  ShortAdd,  ShortSub,  ShortMul,  ShortDiv,  ShortMod,  ShortExp,  ShortNot,  ShortBwn,  ShortOr,  ShortAnd,  ShortEqu,  ShortNqu,  ShortGrt,  ShortSma,  ShortGrtEqu,  ShortSmaEqu,  ShortNeg,  ShortLBitSft,  ShortRBitSft };
4127 //OpTable ushortOps = { UShortAdd, UShortSub, UShortMul, UShortDiv, UShortMod, UShortExp, UShortNot, UShortBwn, UShortOr, UShortAnd, UShortEqu, UShortNqu, UShortGrt, UShortSma, UShortGrtEqu, UShortSmaEqu, UShortNeg, UShortLBitSft, UShortRBitSft };
4128 //OpTable floatOps =  {  FloatAdd,  FloatSub,  FloatMul,  FloatDiv,      null,      null,      null,      null,     null,      null,  FloatEqu,  FloatNqu,  FloatGrt,  FloatSma,  FloatGrtEqu,  FloatSmaEqu,  FloatNeg,          null,          null };
4129 //OpTable doubleOps = { DoubleAdd, DoubleSub, DoubleMul, DoubleDiv,      null,      null,      null,      null,     null,      null, DoubleEqu, DoubleNqu, DoubleGrt, DoubleSma, DoubleGrtEqu, DoubleSmaEqu, DoubleNeg,          null,          null };
4130 //OpTable charOps =   {   CharAdd,   CharSub,   CharMul,   CharDiv,   CharMod,   CharExp,   CharNot,   CharBwn,   CharOr,   CharAnd,   CharEqu,   CharNqu,   CharGrt,   CharSma,   CharGrtEqu,   CharSmaEqu,   CharNeg,   CharLBitSft,   CharRBitSft };
4131 //OpTable ucharOps =  {  UCharAdd,  UCharSub,  UCharMul,  UCharDiv,  UCharMod,  UCharExp,  UCharNot,  UCharBwn,  UCharOr,  UCharAnd,  UCharEqu,  UCharNqu,  UCharGrt,  UCharSma,  UCharGrtEqu,  UCharSmaEqu,  UCharNeg,  UCharLBitSft,  UCharRBitSft };
4132
4133 public void ReadString(char * output,  char * string)
4134 {
4135    int len = strlen(string);
4136    int c,d = 0;
4137    bool quoted = false, escaped = false;
4138    for(c = 0; c<len; c++)
4139    {
4140       char ch = string[c];
4141       if(escaped)
4142       {
4143          switch(ch)
4144          {
4145             case 'n': output[d] = '\n'; break;
4146             case 't': output[d] = '\t'; break;
4147             case 'a': output[d] = '\a'; break;
4148             case 'b': output[d] = '\b'; break;
4149             case 'f': output[d] = '\f'; break;
4150             case 'r': output[d] = '\r'; break;
4151             case 'v': output[d] = '\v'; break;
4152             case '\\': output[d] = '\\'; break;
4153             case '\"': output[d] = '\"'; break;
4154             default: output[d++] = '\\'; output[d] = ch;
4155             //default: output[d] = ch;
4156          }
4157          d++;
4158          escaped = false;
4159       }
4160       else 
4161       {
4162          if(ch == '\"') 
4163             quoted ^= true;
4164          else if(quoted)
4165          {
4166             if(ch == '\\')
4167                escaped = true;
4168             else
4169                output[d++] = ch;
4170          }
4171       }
4172    }
4173    output[d] = '\0';
4174 }
4175
4176 public Operand GetOperand(Expression exp)
4177 {
4178    Operand op { };
4179    Type type = exp.expType;
4180    if(type)
4181    {
4182       while(type.kind == classType && 
4183          type._class.registered && (type._class.registered.type == bitClass || type._class.registered.type == unitClass || type._class.registered.type == enumClass))
4184       {
4185          if(!type._class.registered.dataType)
4186             type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
4187          type = type._class.registered.dataType;
4188          
4189       }
4190       op.kind = type.kind;
4191       op.type = exp.expType;
4192       if(exp.isConstant && exp.type == constantExp)
4193       {
4194          switch(op.kind)
4195          {
4196             case charType:
4197             {
4198                if(exp.constant[0] == '\'')
4199                   op.c = exp.constant[1];
4200                else if(type.isSigned)
4201                {
4202                   op.c = (char)strtol(exp.constant, null, 0);
4203                   op.ops = charOps;
4204                }
4205                else
4206                {
4207                   op.uc = (unsigned char)strtoul(exp.constant, null, 0);
4208                   op.ops = ucharOps;
4209                }
4210                break;
4211             }
4212             case shortType:
4213                if(type.isSigned)
4214                {
4215                   op.s = (short)strtol(exp.constant, null, 0);
4216                   op.ops = shortOps;
4217                }
4218                else
4219                {
4220                   op.us = (unsigned short)strtoul(exp.constant, null, 0);
4221                   op.ops = ushortOps;
4222                }
4223                break;
4224             case intType:
4225             case longType:
4226                if(type.isSigned)
4227                {
4228                   op.i = (int)strtol(exp.constant, null, 0);
4229                   op.ops = intOps;
4230                }
4231                else
4232                {
4233                   op.ui = (unsigned int)strtoul(exp.constant, null, 0);
4234                   op.ops = uintOps;
4235                }
4236                op.kind = intType;
4237                break;
4238             case int64Type:
4239                if(type.isSigned)
4240                {
4241                   op.i64 = (int64)_strtoi64(exp.constant, null, 0);
4242                   op.ops = intOps;
4243                }
4244                else
4245                {
4246                   op.ui64 = (uint64)_strtoui64(exp.constant, null, 0);
4247                   op.ops = uintOps;
4248                }
4249                op.kind = intType;
4250                break;
4251             case floatType:
4252                op.f = (float)strtod(exp.constant, null);
4253                op.ops = floatOps;
4254                break;
4255             case doubleType:
4256                op.d = (double)strtod(exp.constant, null);
4257                op.ops = doubleOps;
4258                break;
4259             //case classType:    For when we have operator overloading...
4260             // Pointer additions
4261             //case functionType:
4262             case arrayType:
4263             case pointerType:
4264             case classType:
4265                op.p = (unsigned char *)strtoul(exp.constant, null, 0);
4266                op.kind = pointerType;
4267                op.ops = uintOps;
4268                // op.ptrSize = 
4269                break;
4270          }
4271       }
4272    }
4273    return op;
4274 }
4275
4276 static void UnusedFunction()
4277 {
4278    int a;
4279    a.OnGetString(0,0,0);
4280 }
4281 default:
4282 extern int __ecereVMethodID_class_OnGetString;
4283 public:
4284
4285 static void PopulateInstanceProcessMember(Instantiation inst, OldList * memberList, DataMember parentDataMember, uint offset)
4286 {
4287    DataMember dataMember;
4288    for(dataMember = parentDataMember.members.first; dataMember; dataMember = dataMember.next)
4289    {
4290       if(!dataMember.name && (dataMember.type == structMember || dataMember.type == unionMember))
4291          PopulateInstanceProcessMember(inst, memberList, dataMember, offset + dataMember.offset);
4292       else
4293       {
4294          Expression exp { };
4295          MemberInit member = MkMemberInit(MkListOne(MkIdentifier(dataMember.name)), MkInitializerAssignment(exp));
4296          Type type;
4297          void * ptr = inst.data + dataMember.offset + offset;
4298          char * result = null;
4299          exp.loc = member.loc = inst.loc;
4300          ((Identifier)member.identifiers->first).loc = inst.loc;
4301
4302          if(!dataMember.dataType)
4303             dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4304          type = dataMember.dataType;
4305          if(type.kind == classType)
4306          {
4307             Class _class = type._class.registered;
4308             if(_class.type == enumClass)
4309             {
4310                Class enumClass = eSystem_FindClass(privateModule, "enum");
4311                if(enumClass)
4312                {
4313                   EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
4314                   NamedLink item;
4315                   for(item = e.values.first; item; item = item.next)
4316                   {
4317                      if((int)item.data == *(int *)ptr)
4318                      {
4319                         result = item.name;
4320                         break;
4321                      }
4322                   }
4323                   if(result)
4324                   {
4325                      exp.identifier = MkIdentifier(result);
4326                      exp.type = identifierExp;
4327                      exp.destType = MkClassType(_class.fullName);
4328                      ProcessExpressionType(exp);
4329                   }
4330                }
4331             }
4332             if(_class.type == enumClass || _class.type == unitClass || _class.type == bitClass)
4333             {
4334                if(!_class.dataType)
4335                   _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4336                type = _class.dataType;
4337             }
4338          }
4339          if(!result)
4340          {
4341             switch(type.kind)
4342             {
4343                case floatType:
4344                {
4345                   FreeExpContents(exp);
4346
4347                   exp.constant = PrintFloat(*(float*)ptr);
4348                   exp.type = constantExp;
4349                   break;
4350                }
4351                case doubleType:
4352                {
4353                   FreeExpContents(exp);
4354
4355                   exp.constant = PrintDouble(*(double*)ptr);
4356                   exp.type = constantExp;
4357                   break;
4358                }
4359                case intType:
4360                {
4361                   FreeExpContents(exp);
4362
4363                   exp.constant = PrintInt(*(int*)ptr);
4364                   exp.type = constantExp;
4365                   break;
4366                }
4367                case int64Type:
4368                {
4369                   FreeExpContents(exp);
4370
4371                   exp.constant = PrintInt64(*(int64*)ptr);
4372                   exp.type = constantExp;
4373                   break;
4374                }
4375                default:
4376                   printf("error: unhandled type populating instance\n");
4377             }
4378          }
4379          ListAdd(memberList, member);
4380       }
4381
4382       if(parentDataMember.type == unionMember)
4383          break;
4384    }
4385 }
4386
4387 void PopulateInstance(Instantiation inst)
4388 {
4389    Symbol classSym = inst._class.symbol; // FindClass(inst._class.name);
4390    Class _class = classSym.registered;
4391    DataMember dataMember;
4392    OldList * memberList = MkList();
4393    inst.members = MkListOne(MkMembersInitList(memberList));
4394    for(dataMember = _class.membersAndProperties.first; dataMember; dataMember = dataMember.next)
4395    {
4396       if(!dataMember.isProperty)
4397       {
4398          if(!dataMember.name && (dataMember.type == structMember || dataMember.type == unionMember))
4399             PopulateInstanceProcessMember(inst, memberList, dataMember, dataMember.offset);
4400          else
4401          {
4402             Expression exp { };
4403             MemberInit member = MkMemberInit(MkListOne(MkIdentifier(dataMember.name)), MkInitializerAssignment(exp));
4404             Type type;
4405             void * ptr = inst.data + dataMember.offset;
4406             char * result = null;
4407
4408             exp.loc = member.loc = inst.loc;
4409             ((Identifier)member.identifiers->first).loc = inst.loc;
4410
4411             if(!dataMember.dataType)
4412                dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4413             type = dataMember.dataType;
4414             if(type.kind == classType)
4415             {
4416                Class _class = type._class.registered;
4417                if(_class.type == enumClass)
4418                {
4419                   Class enumClass = eSystem_FindClass(privateModule, "enum");
4420                   if(enumClass)
4421                   {
4422                      EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
4423                      NamedLink item;
4424                      for(item = e.values.first; item; item = item.next)
4425                      {
4426                         if((int)item.data == *(int *)ptr)
4427                         {
4428                            result = item.name;
4429                            break;
4430                         }
4431                      }
4432                   }
4433                   if(result)
4434                   {
4435                      exp.identifier = MkIdentifier(result);
4436                      exp.type = identifierExp;
4437                      exp.destType = MkClassType(_class.fullName);
4438                      ProcessExpressionType(exp);
4439                   }                     
4440                }
4441                if(_class.type == enumClass || _class.type == unitClass || _class.type == bitClass)
4442                {
4443                   if(!_class.dataType)
4444                      _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4445                   type = _class.dataType;
4446                }
4447             }
4448             if(!result)
4449             {
4450                switch(type.kind)
4451                {
4452                   case floatType:
4453                   {
4454                      exp.constant = PrintFloat(*(float*)ptr);
4455                      exp.type = constantExp;
4456                      break;
4457                   }
4458                   case doubleType:
4459                   {
4460                      exp.constant = PrintDouble(*(double*)ptr);
4461                      exp.type = constantExp;
4462                      break;
4463                   }
4464                   case intType:
4465                   {
4466                      exp.constant = PrintInt(*(int*)ptr);
4467                      exp.type = constantExp;
4468                      break;
4469                   }
4470                   case int64Type:
4471                   {
4472                      exp.constant = PrintInt64(*(int64*)ptr);
4473                      exp.type = constantExp;
4474                      break;
4475                   }
4476                   default:
4477                      printf("error: unhandled type populating instance\n");
4478                }
4479             }
4480             ListAdd(memberList, member);
4481          }
4482       }
4483    }
4484 }
4485
4486 void ComputeInstantiation(Expression exp)
4487 {
4488    Instantiation inst = exp.instance;
4489    MembersInit members;
4490    Symbol classSym = inst._class ? inst._class.symbol : null; // FindClass(inst._class.name);
4491    Class _class = classSym ? classSym.registered : null;
4492    DataMember curMember = null;
4493    Class curClass = null;
4494    DataMember subMemberStack[256];
4495    int subMemberStackPos = 0;
4496    uint64 bits = 0;
4497
4498    if(_class && (_class.type == structClass || _class.type == normalClass || _class.type == noHeadClass ))
4499    {
4500       // Don't recompute the instantiation... 
4501       // Non Simple classes will have become constants by now
4502       if(inst.data) 
4503          return;
4504
4505       if(_class.type == normalClass || _class.type == noHeadClass)
4506          inst.data = (byte *)eInstance_New(_class);
4507       else
4508          inst.data = new0 byte[_class.structSize];
4509    }
4510
4511    if(inst.members)
4512    {
4513       for(members = inst.members->first; members; members = members.next)
4514       {
4515          switch(members.type)
4516          {
4517             case dataMembersInit:
4518             {
4519                if(members.dataMembers)
4520                {
4521                   MemberInit member;
4522                   for(member = members.dataMembers->first; member; member = member.next)
4523                   {
4524                      Identifier ident = member.identifiers ? member.identifiers->first : null;
4525                      bool found = false;
4526
4527                      Property prop = null;
4528                      DataMember dataMember = null;
4529                      Method method = null;
4530                      uint dataMemberOffset;
4531
4532                      if(!ident)
4533                      {
4534                         eClass_FindNextMember(_class, &curClass, &curMember, subMemberStack, &subMemberStackPos);
4535                         if(curMember)
4536                         {
4537                            if(curMember.isProperty)
4538                               prop = (Property)curMember;
4539                            else
4540                            {
4541                               dataMember = curMember;
4542                               
4543                               // CHANGED THIS HERE
4544                               eClass_FindDataMemberAndOffset(_class, dataMember.name, &dataMemberOffset, privateModule, null, null);
4545                               // dataMemberOffset = dataMember.offset;
4546                            }
4547                            found = true;
4548                         }
4549                      }
4550                      else
4551                      {
4552                         prop = eClass_FindProperty(_class, ident.string, privateModule);
4553                         if(prop)
4554                         {
4555                            found = true;
4556                            if(prop.memberAccess == publicAccess)
4557                            {
4558                               curMember = (DataMember)prop;
4559                               curClass = prop._class;
4560                            }
4561                         }
4562                         else
4563                         {
4564                            DataMember _subMemberStack[256];
4565                            int _subMemberStackPos = 0;
4566
4567                            // FILL MEMBER STACK
4568                            dataMember = eClass_FindDataMemberAndOffset(_class, ident.string, &dataMemberOffset, privateModule, _subMemberStack, &_subMemberStackPos);
4569
4570                            if(dataMember)
4571                            {
4572                               found = true;
4573                               if(dataMember.memberAccess == publicAccess)
4574                               {
4575                                  curMember = dataMember;
4576                                  curClass = dataMember._class;
4577                                  memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
4578                                  subMemberStackPos = _subMemberStackPos;
4579                               }
4580                            }
4581                         }
4582                      }
4583
4584                      if(found && member.initializer && member.initializer.type == expInitializer)
4585                      {
4586                         Expression value = member.initializer.exp;
4587                         Type type = null;
4588                         if(prop)
4589                         {
4590                            type = prop.dataType;
4591                         }
4592                         else if(dataMember)
4593                         {
4594                            if(!dataMember.dataType)
4595                               dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4596                            
4597                            type = dataMember.dataType;
4598                         }
4599
4600                         if(ident && ident.next)
4601                         {
4602                            // for(; ident && type; ident = ident.next)
4603                            for(ident = ident.next; ident && type; ident = ident.next)
4604                            {
4605                               if(type.kind == classType)
4606                               {
4607                                  prop = eClass_FindProperty(type._class.registered,
4608                                     ident.string, privateModule);
4609                                  if(prop)
4610                                     type = prop.dataType;
4611                                  else
4612                                  {
4613                                     dataMember = eClass_FindDataMemberAndOffset(type._class.registered, 
4614                                        ident.string, &dataMemberOffset, privateModule, null, null);
4615                                     if(dataMember)
4616                                        type = dataMember.dataType;
4617                                  }
4618                               }
4619                               else if(type.kind == structType || type.kind == unionType)
4620                               {
4621                                  Type memberType;
4622                                  for(memberType = type.members.first; memberType; memberType = memberType.next)
4623                                  {
4624                                     if(!strcmp(memberType.name, ident.string))
4625                                     {
4626                                        type = memberType;
4627                                        break;
4628                                     }
4629                                  }
4630                               }
4631                            }
4632                         }
4633                         if(value)
4634                         {
4635                            FreeType(value.destType);
4636                            value.destType = type;
4637                            if(type) type.refCount++;
4638                            ComputeExpression(value);
4639                         }
4640                         if(value && (_class.type == structClass || _class.type == normalClass || _class.type == noHeadClass /*&& value.expType.kind == type.kind*/))
4641                         {
4642                            if(type.kind == classType)
4643                            {
4644                               Class _class = type._class.registered;
4645                               if(_class.type == bitClass || _class.type == unitClass ||
4646                                  _class.type == enumClass)
4647                               {
4648                                  if(!_class.dataType)
4649                                     _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4650                                  type = _class.dataType;
4651                               }
4652                            }
4653
4654                            if(dataMember)
4655                            {
4656                               void * ptr = inst.data + dataMemberOffset;
4657                               
4658                               if(value.type == constantExp)
4659                               {
4660                                  switch(type.kind)
4661                                  {
4662                                     case intType:
4663                                     {
4664                                        GetInt(value, (int*)ptr);
4665                                        break;
4666                                     }
4667                                     case int64Type:
4668                                     {
4669                                        GetInt64(value, (int64*)ptr);
4670                                        break;
4671                                     }
4672                                     case floatType:
4673                                     {
4674                                        GetFloat(value, (float*)ptr);
4675                                        break;
4676                                     }
4677                                     case doubleType:
4678                                     {
4679                                        GetDouble(value, (double *)ptr);
4680                                        break;
4681                                     }
4682                                  }
4683                               }
4684                               else if(value.type == instanceExp)
4685                               {
4686                                  if(type.kind == classType)
4687                                  {
4688                                     Class _class = type._class.registered;
4689                                     if(_class.type == structClass)
4690                                     {
4691                                        ComputeTypeSize(type);
4692                                        if(value.instance.data)
4693                                           memcpy(ptr, value.instance.data, type.size);
4694                                     }
4695                                  }
4696                               }
4697                            }
4698                            else if(prop)
4699                            {
4700                               if(value.type == instanceExp && value.instance.data)
4701                               {
4702                                  void (*Set)(void *, void *) = (void *)prop.Set;
4703                                  Set(inst.data, value.instance.data);
4704                                  PopulateInstance(inst);
4705                               }
4706                               else if(value.type == constantExp)
4707                               {
4708                                  switch(type.kind)
4709                                  {
4710                                     case doubleType:
4711                                     {
4712                                        void (*Set)(void *, double) = (void *)prop.Set;
4713                                        Set(inst.data, strtod(value.constant, null) );
4714                                        break;
4715                                     }
4716                                     case floatType:
4717                                     {
4718                                        void (*Set)(void *, float) = (void *)prop.Set;
4719                                        Set(inst.data, (float)(strtod(value.constant, null)));
4720                                        break;
4721                                     }
4722                                     case intType:
4723                                     {
4724                                        void (*Set)(void *, int) = (void *)prop.Set;
4725                                        Set(inst.data, strtol(value.constant, null, 0));
4726                                        break;
4727                                     }
4728                                     case int64Type:
4729                                     {
4730                                        void (*Set)(void *, int64) = (void *)prop.Set;
4731                                        Set(inst.data, _strtoi64(value.constant, null, 0));
4732                                        break;
4733                                     }
4734                                  }
4735                               }
4736                               else if(value.type == stringExp)
4737                               {
4738                                  char temp[1024];
4739                                  ReadString(temp, value.string);
4740                                  prop.Set(inst.data, temp);
4741                               }
4742                            }
4743                         }
4744                         else if(_class.type == unitClass)
4745                         {
4746                            if(prop)
4747                            {
4748                               // Only support converting units to units for now...
4749                               if(value.type == constantExp)
4750                               {
4751                                  if(type.kind == classType)
4752                                  {
4753                                     Class _class = type._class.registered;
4754                                     if(_class.type == unitClass)
4755                                     {
4756                                        if(!_class.dataType)
4757                                           _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4758                                        type = _class.dataType;
4759                                     }
4760                                  }
4761                                  // TODO: Assuming same base type for units...
4762                                  switch(type.kind)
4763                                  {
4764                                     case floatType:
4765                                     {
4766                                        float fValue;
4767                                        float (*Set)(float) = (void *)prop.Set;
4768                                        GetFloat(member.initializer.exp, &fValue);
4769                                        exp.constant = PrintFloat(Set(fValue));
4770                                        exp.type = constantExp;
4771                                        break;
4772                                     }
4773                                     case doubleType:
4774                                     {
4775                                        double dValue;
4776                                        double (*Set)(double) = (void *)prop.Set;
4777                                        GetDouble(member.initializer.exp, &dValue);
4778                                        exp.constant = PrintDouble(Set(dValue));
4779                                        exp.type = constantExp;
4780                                        break;
4781                                     }
4782                                  }
4783                               }
4784                            }
4785                         }
4786                         else if(_class.type == bitClass)
4787                         {
4788                            if(prop)
4789                            {
4790                               if(value.type == instanceExp && value.instance.data)
4791                               {
4792                                  unsigned int (*Set)(void *) = (void *)prop.Set;
4793                                  bits = Set(value.instance.data);
4794                               }
4795                               else if(value.type == constantExp)
4796                               {
4797                               }
4798                            }
4799                            else if(dataMember)
4800                            {
4801                               BitMember bitMember = (BitMember) dataMember;
4802                               Type type;
4803                               int part = 0;
4804                               GetInt(value, &part);
4805                               bits = (bits & ~bitMember.mask);
4806                               if(!bitMember.dataType)
4807                                  bitMember.dataType = ProcessTypeString(bitMember.dataTypeString, false);
4808
4809                               type = bitMember.dataType;
4810
4811                               if(type.kind == classType && type._class && type._class.registered)
4812                               {
4813                                  if(!type._class.registered.dataType)
4814                                     type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);                                    
4815                                  type = type._class.registered.dataType;
4816                               }
4817
4818                               switch(type.kind)
4819                               {
4820                                  case charType:
4821                                     if(type.isSigned)
4822                                        bits |= ((char)part << bitMember.pos);
4823                                     else
4824                                        bits |= ((unsigned char)part << bitMember.pos);
4825                                     break;
4826                                  case shortType:
4827                                     if(type.isSigned)
4828                                        bits |= ((short)part << bitMember.pos);
4829                                     else
4830                                        bits |= ((unsigned short)part << bitMember.pos);
4831                                     break;
4832                                  case intType:
4833                                  case longType:
4834                                     if(type.isSigned)
4835                                        bits |= ((int)part << bitMember.pos);
4836                                     else
4837                                        bits |= ((unsigned int)part << bitMember.pos);
4838                                     break;
4839                                  case int64Type:
4840                                     if(type.isSigned)
4841                                        bits |= ((int64)part << bitMember.pos);
4842                                     else
4843                                        bits |= ((uint64)part << bitMember.pos);
4844                                     break;
4845                               }
4846                            }
4847                         }
4848                      }
4849                      else
4850                      {
4851                         if(_class && _class.type == unitClass)
4852                         {
4853                            ComputeExpression(member.initializer.exp);
4854                            exp.constant = member.initializer.exp.constant;
4855                            exp.type = constantExp;
4856                            
4857                            member.initializer.exp.constant = null;
4858                         }
4859                      }
4860                   }
4861                }
4862                break;
4863             }
4864          }
4865       }
4866    }
4867    if(_class && _class.type == bitClass)
4868    {
4869       exp.constant = PrintHexUInt(bits);
4870       exp.type = constantExp;
4871    }
4872    if(exp.type != instanceExp)
4873    {
4874       FreeInstance(inst);
4875    }
4876 }
4877
4878 void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1, Operand op2)
4879 {
4880    if(exp.op.op == SIZEOF)
4881    {
4882       FreeExpContents(exp);
4883       exp.type = constantExp;
4884       exp.constant = PrintUInt(ComputeTypeSize(op1.type));
4885    }
4886    else
4887    {
4888       if(!exp.op.exp1)
4889       {
4890          switch(exp.op.op)
4891          {
4892             // unary arithmetic
4893             case '+':
4894             {
4895                // Provide default unary +
4896                Expression exp2 = exp.op.exp2;
4897                exp.op.exp2 = null;
4898                FreeExpContents(exp);
4899                FreeType(exp.expType);
4900                FreeType(exp.destType);
4901                *exp = *exp2;
4902                delete exp2;
4903                break;
4904             }
4905             case '-':
4906                if(op1.ops.Neg) { FreeExpContents(exp); op1.ops.Neg(exp, op1); }
4907                break;
4908             // unary arithmetic increment and decrement
4909                   //OPERATOR_ALL(UNARY, ++, Inc)
4910                   //OPERATOR_ALL(UNARY, --, Dec)
4911             // unary bitwise
4912             case '~':
4913                if(op1.ops.BitNot) { FreeExpContents(exp); op1.ops.BitNot(exp, op1); }
4914                break;
4915             // unary logical negation
4916             case '!':
4917                if(op1.ops.Not) { FreeExpContents(exp); op1.ops.Not(exp, op1); }
4918                break;
4919          }
4920       }
4921       else
4922       {
4923          switch(exp.op.op)
4924          {
4925             // binary arithmetic
4926             case '+':
4927                if(op1.ops.Add) { FreeExpContents(exp); op1.ops.Add(exp, op1, op2); }
4928                break;
4929             case '-':
4930                if(op1.ops.Sub) { FreeExpContents(exp); op1.ops.Sub(exp, op1, op2); }
4931                break;
4932             case '*':
4933                if(op1.ops.Mul) { FreeExpContents(exp); op1.ops.Mul(exp, op1, op2); }
4934                break;
4935             case '/':
4936                if(op1.ops.Div) { FreeExpContents(exp); op1.ops.Div(exp, op1, op2); }
4937                break;
4938             case '%':
4939                if(op1.ops.Mod) { FreeExpContents(exp); op1.ops.Mod(exp, op1, op2); }
4940                break;
4941             // binary arithmetic assignment
4942                   //OPERATOR_ALL(BINARY, =, Asign)
4943                   //OPERATOR_ALL(BINARY, +=, AddAsign)
4944                   //OPERATOR_ALL(BINARY, -=, SubAsign)
4945                   //OPERATOR_ALL(BINARY, *=, MulAsign)
4946                   //OPERATOR_ALL(BINARY, /=, DivAsign)
4947                   //OPERATOR_ALL(BINARY, %=, ModAsign)
4948             // binary bitwise
4949             case '&':
4950                if(exp.op.exp2)
4951                {
4952                   if(op1.ops.BitAnd) { FreeExpContents(exp); op1.ops.BitAnd(exp, op1, op2); }
4953                }
4954                break;
4955             case '|':
4956                if(op1.ops.BitOr) { FreeExpContents(exp); op1.ops.BitOr(exp, op1, op2); }
4957                break;
4958             case '^':
4959                if(op1.ops.BitXor) { FreeExpContents(exp); op1.ops.BitXor(exp, op1, op2); }
4960                break;
4961             case LEFT_OP:
4962                if(op1.ops.LShift) { FreeExpContents(exp); op1.ops.LShift(exp, op1, op2); }
4963                break;
4964             case RIGHT_OP:
4965                if(op1.ops.RShift) { FreeExpContents(exp); op1.ops.RShift(exp, op1, op2); }
4966                break;
4967             // binary bitwise assignment
4968                   //OPERATOR_INTTYPES(BINARY, &=, AndAsign)
4969                   //OPERATOR_INTTYPES(BINARY, |=, OrAsign)
4970                   //OPERATOR_INTTYPES(BINARY, ^=, XorAsign)
4971                   //OPERATOR_INTTYPES(BINARY, <<=, LShiftAsign)
4972                   //OPERATOR_INTTYPES(BINARY, >>=, RShiftAsign)
4973             // binary logical equality
4974             case EQ_OP:
4975                if(op1.ops.Equ) { FreeExpContents(exp); op1.ops.Equ(exp, op1, op2); }
4976                break;
4977             case NE_OP:
4978                if(op1.ops.Nqu) { FreeExpContents(exp); op1.ops.Nqu(exp, op1, op2); }
4979                break;
4980             // binary logical
4981             case AND_OP:
4982                if(op1.ops.And) { FreeExpContents(exp); op1.ops.And(exp, op1, op2); }
4983                break;
4984             case OR_OP:
4985                if(op1.ops.Or) { FreeExpContents(exp); op1.ops.Or(exp, op1, op2); }
4986                break;
4987             // binary logical relational
4988             case '>':
4989                if(op1.ops.Grt) { FreeExpContents(exp); op1.ops.Grt(exp, op1, op2); }
4990                break;
4991             case '<':
4992                if(op1.ops.Sma) { FreeExpContents(exp); op1.ops.Sma(exp, op1, op2); }
4993                break;
4994             case GE_OP:
4995                if(op1.ops.GrtEqu) { FreeExpContents(exp); op1.ops.GrtEqu(exp, op1, op2); }
4996                break;
4997             case LE_OP:
4998                if(op1.ops.SmaEqu) { FreeExpContents(exp); op1.ops.SmaEqu(exp, op1, op2); }
4999                break;
5000          }
5001       }
5002    }
5003 }
5004
5005 void ComputeExpression(Expression exp)
5006 {
5007    char expString[10240];
5008    expString[0] = '\0';
5009 #ifdef _DEBUG
5010    PrintExpression(exp, expString);
5011 #endif
5012
5013    switch(exp.type)
5014    {
5015       case instanceExp:
5016       {
5017          ComputeInstantiation(exp);
5018          break;
5019       }
5020       /*
5021       case constantExp:
5022          break;
5023       */
5024       case opExp:
5025       {
5026          Expression exp1, exp2 = null;
5027          Operand op1 { };
5028          Operand op2 { };
5029
5030          // We don't care about operations with only exp2 (INC_OP, DEC_OP...)
5031          if(exp.op.exp2)
5032             ComputeExpression(exp.op.exp2);
5033          if(exp.op.exp1)
5034          {
5035             ComputeExpression(exp.op.exp1);
5036             exp1 = exp.op.exp1;
5037             exp2 = exp.op.exp2;
5038             op1 = GetOperand(exp1);
5039             if(op1.type) op1.type.refCount++;
5040             if(exp2)
5041             {
5042                op2 = GetOperand(exp2);
5043                if(op2.type) op2.type.refCount++;
5044             }
5045          }
5046          else 
5047          {
5048             exp1 = exp.op.exp2;
5049             op1 = GetOperand(exp1);
5050             if(op1.type) op1.type.refCount++;
5051          }
5052
5053          CallOperator(exp, exp1, exp2, op1, op2);
5054          /*
5055          switch(exp.op.op)
5056          {
5057             // Unary operators
5058             case '&':
5059                // Also binary
5060                if(exp.op.exp1 && exp.op.exp2)
5061                {
5062                   // Binary And
5063                   if(op1.ops.BitAnd)
5064                   {
5065                      FreeExpContents(exp);
5066                      op1.ops.BitAnd(exp, op1, op2);
5067                   }
5068                }
5069                break;
5070             case '*':
5071                if(exp.op.exp1)
5072                {
5073                   if(op1.ops.Mul)
5074                   {
5075                      FreeExpContents(exp);
5076                      op1.ops.Mul(exp, op1, op2);
5077                   }
5078                }
5079                break;
5080             case '+':
5081                if(exp.op.exp1)
5082                {
5083                   if(op1.ops.Add)
5084                   {
5085                      FreeExpContents(exp);
5086                      op1.ops.Add(exp, op1, op2);
5087                   }
5088                }
5089                else
5090                {
5091                   // Provide default unary +
5092                   Expression exp2 = exp.op.exp2;
5093                   exp.op.exp2 = null;
5094                   FreeExpContents(exp);
5095                   FreeType(exp.expType);
5096                   FreeType(exp.destType);
5097
5098                   *exp = *exp2;
5099                   delete exp2;
5100                }
5101                break;
5102             case '-':
5103                if(exp.op.exp1)
5104                {
5105                   if(op1.ops.Sub) 
5106                   {
5107                      FreeExpContents(exp);
5108                      op1.ops.Sub(exp, op1, op2);
5109                   }
5110                }
5111                else
5112                {
5113                   if(op1.ops.Neg) 
5114                   {
5115                      FreeExpContents(exp);
5116                      op1.ops.Neg(exp, op1);
5117                   }
5118                }
5119                break;
5120             case '~':
5121                if(op1.ops.BitNot)
5122                {
5123                   FreeExpContents(exp);
5124                   op1.ops.BitNot(exp, op1);
5125                }
5126                break;
5127             case '!':
5128                if(op1.ops.Not)
5129                {
5130                   FreeExpContents(exp);
5131                   op1.ops.Not(exp, op1);
5132                }
5133                break;
5134             // Binary only operators
5135             case '/':
5136                if(op1.ops.Div) 
5137                {
5138                   FreeExpContents(exp);
5139                   op1.ops.Div(exp, op1, op2);
5140                }
5141                break;
5142             case '%':
5143                if(op1.ops.Mod)
5144                {
5145                   FreeExpContents(exp);
5146                   op1.ops.Mod(exp, op1, op2);
5147                }
5148                break;
5149             case LEFT_OP:
5150                break;
5151             case RIGHT_OP:
5152                break;
5153             case '<':
5154                if(exp.op.exp1)
5155                {
5156                   if(op1.ops.Sma)
5157                   {
5158                      FreeExpContents(exp);
5159                      op1.ops.Sma(exp, op1, op2);
5160                   }
5161                }
5162                break;
5163             case '>':
5164                if(exp.op.exp1)
5165                {
5166                   if(op1.ops.Grt)
5167                   {
5168                      FreeExpContents(exp);
5169                      op1.ops.Grt(exp, op1, op2);
5170                   }
5171                }
5172                break;
5173             case LE_OP:
5174                if(exp.op.exp1)
5175                {
5176                   if(op1.ops.SmaEqu)
5177                   {
5178                      FreeExpContents(exp);
5179                      op1.ops.SmaEqu(exp, op1, op2);
5180                   }
5181                }
5182                break;
5183             case GE_OP:
5184                if(exp.op.exp1)
5185                {
5186                   if(op1.ops.GrtEqu)
5187                   {
5188                      FreeExpContents(exp);
5189                      op1.ops.GrtEqu(exp, op1, op2);
5190                   }
5191                }
5192                break;
5193             case EQ_OP:
5194                if(exp.op.exp1)
5195                {
5196                   if(op1.ops.Equ)
5197                   {
5198                      FreeExpContents(exp);
5199                      op1.ops.Equ(exp, op1, op2);
5200                   }
5201                }
5202                break;
5203             case NE_OP:
5204                if(exp.op.exp1)
5205                {
5206                   if(op1.ops.Nqu)
5207                   {
5208                      FreeExpContents(exp);
5209                      op1.ops.Nqu(exp, op1, op2);
5210                   }
5211                }
5212                break;
5213             case '|':
5214                if(op1.ops.BitOr) 
5215                {
5216                   FreeExpContents(exp);
5217                   op1.ops.BitOr(exp, op1, op2);
5218                }
5219                break;
5220             case '^':
5221                if(op1.ops.BitXor) 
5222                {
5223                   FreeExpContents(exp);
5224                   op1.ops.BitXor(exp, op1, op2);
5225                }
5226                break;
5227             case AND_OP:
5228                break;
5229             case OR_OP:
5230                break;
5231             case SIZEOF:
5232                FreeExpContents(exp);
5233                exp.type = constantExp;
5234                exp.constant = PrintUInt(ComputeTypeSize(op1.type));
5235                break;
5236          }
5237          */
5238          if(op1.type) FreeType(op1.type);
5239          if(op2.type) FreeType(op2.type);
5240          break;
5241       }
5242       case bracketsExp:
5243       case extensionExpressionExp:
5244       {
5245          Expression e, n;
5246          for(e = exp.list->first; e; e = n)
5247          {
5248             n = e.next;
5249             if(!n)
5250             {
5251                OldList * list = exp.list;
5252                ComputeExpression(e);
5253                //FreeExpContents(exp);
5254                FreeType(exp.expType);
5255                FreeType(exp.destType);
5256                *exp = *e;
5257                delete e;
5258                delete list;
5259             }
5260             else
5261             {
5262                FreeExpression(e);
5263             }
5264          }
5265          break;
5266       }
5267       /*
5268
5269       case ExpIndex:
5270       {
5271          Expression e;
5272          exp.isConstant = true;
5273
5274          ComputeExpression(exp.index.exp);
5275          if(!exp.index.exp.isConstant)
5276             exp.isConstant = false;
5277
5278          for(e = exp.index.index->first; e; e = e.next)
5279          {
5280             ComputeExpression(e);
5281             if(!e.next)
5282             {
5283                // Check if this type is int
5284             }
5285             if(!e.isConstant)
5286                exp.isConstant = false;
5287          }
5288          exp.expType = Dereference(exp.index.exp.expType);
5289          break;
5290       }
5291       */
5292       case memberExp:
5293       {
5294          Expression memberExp = exp.member.exp;
5295          Identifier memberID = exp.member.member;
5296
5297          Type type;
5298          ComputeExpression(exp.member.exp);
5299          type = exp.member.exp.expType;
5300          if(type)
5301          {
5302             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);
5303             Property prop = null;
5304             DataMember member = null;
5305             Class convertTo = null;
5306             if(type.kind == subClassType && exp.member.exp.type == classExp)
5307                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
5308
5309             if(!_class)
5310             {
5311                char string[256];
5312                Symbol classSym;
5313                string[0] = '\0';
5314                PrintType(type, string, false, true);
5315                classSym = FindClass(string);
5316                _class = classSym ? classSym.registered : null;
5317             }
5318
5319             if(exp.member.member)
5320             {
5321                prop = eClass_FindProperty(_class, exp.member.member.string, privateModule);
5322                if(!prop)
5323                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, null, null);
5324             }
5325             if(!prop && !member && _class && exp.member.member)
5326             {
5327                Symbol classSym = FindClass(exp.member.member.string);
5328                convertTo = _class;
5329                _class = classSym ? classSym.registered : null;
5330                prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
5331             }
5332       
5333             if(prop)
5334             {
5335                if(prop.compiled)
5336                {
5337                   Type type = prop.dataType;
5338                   // TODO: Assuming same base type for units...
5339                   if(_class.type == unitClass)
5340                   {
5341                      if(type.kind == classType)
5342                      {
5343                         Class _class = type._class.registered;
5344                         if(_class.type == unitClass)
5345                         {
5346                            if(!_class.dataType)
5347                               _class.dataType = ProcessTypeString(_class.dataTypeString, false);
5348                            type = _class.dataType;
5349                         }
5350                      }
5351                      switch(type.kind)
5352                      {
5353                         case floatType:
5354                         {
5355                            float value;
5356                            float (*Get)(float) = (void *)prop.Get;
5357                            GetFloat(exp.member.exp, &value);
5358                            exp.constant = PrintFloat(Get ? Get(value) : value);
5359                            exp.type = constantExp;
5360                            break;
5361                         }
5362                         case doubleType:
5363                         {
5364                            double value;
5365                            double (*Get)(double);
5366                            GetDouble(exp.member.exp, &value);
5367                      
5368                            if(convertTo)
5369                               Get = (void *)prop.Set;
5370                            else
5371                               Get = (void *)prop.Get;
5372                            exp.constant = PrintDouble(Get ? Get(value) : value);
5373                            exp.type = constantExp;
5374                            break;
5375                         }
5376                      }
5377                   }
5378                   else
5379                   {
5380                      if(convertTo)
5381                      {
5382                         Expression value = exp.member.exp;
5383                         Type type;
5384                         if(!prop.dataType)
5385                            ProcessPropertyType(prop);
5386
5387                         type = prop.dataType;
5388                         if(!type)
5389                         {
5390                             // printf("Investigate this\n");
5391                         }
5392                         else if(_class.type == structClass)
5393                         {
5394                            switch(type.kind)
5395                            {
5396                               case classType:
5397                               {
5398                                  Class propertyClass = type._class.registered;
5399                                  if(propertyClass.type == structClass && value.type == instanceExp)
5400                                  {
5401                                     void (*Set)(void *, void *) = (void *)prop.Set;
5402                                     exp.instance = Instantiation { };
5403                                     exp.instance.data = new0 byte[_class.structSize];
5404                                     exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5405                                     exp.instance.loc = exp.loc;
5406                                     exp.type = instanceExp;
5407                                     Set(exp.instance.data, value.instance.data);
5408                                     PopulateInstance(exp.instance);
5409                                  }
5410                                  break;
5411                               }
5412                               case intType:
5413                               {
5414                                  int intValue;
5415                                  void (*Set)(void *, int) = (void *)prop.Set;
5416
5417                                  exp.instance = Instantiation { };
5418                                  exp.instance.data = new0 byte[_class.structSize];
5419                                  exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5420                                  exp.instance.loc = exp.loc;
5421                                  exp.type = instanceExp;
5422                               
5423                                  GetInt(value, &intValue);
5424
5425                                  Set(exp.instance.data, intValue);
5426                                  PopulateInstance(exp.instance);
5427                                  break;
5428                               }
5429                               case int64Type:
5430                               {
5431                                  int64 intValue;
5432                                  void (*Set)(void *, int64) = (void *)prop.Set;
5433
5434                                  exp.instance = Instantiation { };
5435                                  exp.instance.data = new0 byte[_class.structSize];
5436                                  exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5437                                  exp.instance.loc = exp.loc;
5438                                  exp.type = instanceExp;
5439                               
5440                                  GetInt64(value, &intValue);
5441
5442                                  Set(exp.instance.data, intValue);
5443                                  PopulateInstance(exp.instance);
5444                                  break;
5445                               }
5446                               case doubleType:
5447                               {
5448                                  double doubleValue;
5449                                  void (*Set)(void *, double) = (void *)prop.Set;
5450
5451                                  exp.instance = Instantiation { };
5452                                  exp.instance.data = new0 byte[_class.structSize];
5453                                  exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5454                                  exp.instance.loc = exp.loc;
5455                                  exp.type = instanceExp;
5456                               
5457                                  GetDouble(value, &doubleValue);
5458
5459                                  Set(exp.instance.data, doubleValue);
5460                                  PopulateInstance(exp.instance);
5461                                  break;
5462                               }
5463                            }
5464                         }
5465                         else if(_class.type == bitClass)
5466                         {
5467                            switch(type.kind)
5468                            {
5469                               case classType:
5470                               {
5471                                  Class propertyClass = type._class.registered;
5472                                  if(propertyClass.type == structClass && value.instance.data)
5473                                  {
5474                                     unsigned int (*Set)(void *) = (void *)prop.Set;
5475                                     unsigned int bits = Set(value.instance.data);
5476                                     exp.constant = PrintHexUInt(bits);
5477                                     exp.type = constantExp;
5478                                     break;
5479                                  }
5480                                  else if(_class.type == bitClass)
5481                                  {
5482                                     unsigned int value;
5483                                     unsigned int (*Set)(unsigned int) = (void *)prop.Set;
5484                                     unsigned int bits;
5485
5486                                     GetUInt(exp.member.exp, &value);
5487                                     bits = Set(value);
5488                                     exp.constant = PrintHexUInt(bits);
5489                                     exp.type = constantExp;
5490                                  }
5491                               }
5492                            }
5493                         }
5494                      }
5495                      else
5496                      {
5497                         if(_class.type == bitClass)
5498                         {
5499                            unsigned int value;
5500                            GetUInt(exp.member.exp, &value);
5501
5502                            switch(type.kind)
5503                            {
5504                               case classType:
5505                               {
5506                                  Class _class = type._class.registered;
5507                                  if(_class.type == structClass)
5508                                  {
5509                                     void (*Get)(unsigned int, void *) = (void *)prop.Get;
5510
5511                                     exp.instance = Instantiation { };
5512                                     exp.instance.data = new0 byte[_class.structSize];
5513                                     exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5514                                     exp.instance.loc = exp.loc;
5515                                     //exp.instance.fullSet = true;
5516                                     exp.type = instanceExp;
5517                                     Get(value, exp.instance.data);
5518                                     PopulateInstance(exp.instance);
5519                                  }
5520                                  else if(_class.type == bitClass)
5521                                  {
5522                                     unsigned int (*Get)(unsigned int) = (void *)prop.Get;
5523                                     uint64 bits = Get(value);
5524                                     exp.constant = PrintHexUInt64(bits);
5525                                     exp.type = constantExp;
5526                                  }
5527                                  break;
5528                               }
5529                            }
5530                         }
5531                         else if(_class.type == structClass)
5532                         {
5533                            char * value = (exp.member.exp.type == instanceExp ) ? exp.member.exp.instance.data : null;
5534                            switch(type.kind)
5535                            {
5536                               case classType:
5537                               {
5538                                  Class _class = type._class.registered;
5539                                  if(_class.type == structClass && value)
5540                                  {
5541                                     void (*Get)(void *, void *) = (void *)prop.Get;
5542
5543                                     exp.instance = Instantiation { };
5544                                     exp.instance.data = new0 byte[_class.structSize];
5545                                     exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5546                                     exp.instance.loc = exp.loc;
5547                                     //exp.instance.fullSet = true;
5548                                     exp.type = instanceExp;
5549                                     Get(value, exp.instance.data);
5550                                     PopulateInstance(exp.instance);
5551                                  }
5552                                  break;
5553                               }
5554                            }
5555                         }
5556                         /*else
5557                         {
5558                            char * value = exp.member.exp.instance.data;
5559                            switch(type.kind)
5560                            {
5561                               case classType:
5562                               {
5563                                  Class _class = type._class.registered;
5564                                  if(_class.type == normalClass)
5565                                  {
5566                                     void *(*Get)(void *) = (void *)prop.Get;
5567
5568                                     exp.instance = Instantiation { };
5569                                     exp.instance._class = MkSpecifierName(_class.fullName); //MkClassName(_class.fullName);
5570                                     exp.type = instanceExp;
5571                                     exp.instance.data = Get(value, exp.instance.data);
5572                                  }
5573                                  break;
5574                               }
5575                            }
5576                         }
5577                         */
5578                      }
5579                   }
5580                }
5581                else
5582                {
5583                   exp.isConstant = false;
5584                }
5585             }
5586             else if(member)
5587             {
5588             }
5589          }
5590
5591          if(exp.type != ExpressionType::memberExp)
5592          {
5593             FreeExpression(memberExp);
5594             FreeIdentifier(memberID);
5595          }
5596          break;
5597       }
5598       case typeSizeExp:
5599       {
5600          Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
5601          FreeExpContents(exp);
5602          exp.constant = PrintUInt(ComputeTypeSize(type));
5603          exp.type = constantExp;         
5604          FreeType(type);
5605          break;
5606       }
5607       case classSizeExp:
5608       {
5609          Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
5610          if(classSym && classSym.registered)
5611          {
5612             if(classSym.registered.fixed)
5613             {
5614                FreeSpecifier(exp._class);
5615                exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
5616                exp.type = constantExp;
5617             }
5618             else
5619             {
5620                char className[1024];
5621                strcpy(className, "__ecereClass_");
5622                FullClassNameCat(className, classSym.string, true);
5623                MangleClassName(className);
5624
5625                FreeExpContents(exp);
5626                exp.type = pointerExp;
5627                exp.member.exp = MkExpIdentifier(MkIdentifier(className));
5628                exp.member.member = MkIdentifier("structSize");
5629             }
5630          }
5631          break;
5632       }
5633       case castExp:
5634       //case constantExp:
5635       {
5636          Type type;
5637          Expression e = exp;
5638          if(exp.type == castExp)
5639          {
5640             if(exp.cast.exp)
5641                ComputeExpression(exp.cast.exp);
5642             e = exp.cast.exp;
5643          }
5644          if(e && exp.expType)
5645          {
5646             /*if(exp.destType)
5647                type = exp.destType;
5648             else*/
5649                type = exp.expType;
5650             if(type.kind == classType)
5651             {
5652                Class _class = type._class.registered;
5653                if(_class && (_class.type == unitClass || _class.type == bitClass))
5654                {
5655                   if(!_class.dataType)
5656                      _class.dataType = ProcessTypeString(_class.dataTypeString, false);
5657                   type = _class.dataType;
5658                }
5659             }
5660             
5661             switch(type.kind)
5662             {
5663                case charType:
5664                   if(type.isSigned)
5665                   {
5666                      char value;
5667                      GetChar(e, &value);
5668                      FreeExpContents(exp);
5669                      exp.constant = PrintChar(value);
5670                      exp.type = constantExp;
5671                   }
5672                   else
5673                   {
5674                      unsigned char value;
5675                      GetUChar(e, &value);
5676                      FreeExpContents(exp);
5677                      exp.constant = PrintUChar(value);
5678                      exp.type = constantExp;
5679                   }
5680                   break;
5681                case shortType:
5682                   if(type.isSigned)
5683                   {
5684                      short value;
5685                      GetShort(e, &value);
5686                      FreeExpContents(exp);
5687                      exp.constant = PrintShort(value);
5688                      exp.type = constantExp;
5689                   }
5690                   else
5691                   {
5692                      unsigned short value;
5693                      GetUShort(e, &value);
5694                      FreeExpContents(exp);
5695                      exp.constant = PrintUShort(value);
5696                      exp.type = constantExp;
5697                   }
5698                   break;
5699                case intType:
5700                   if(type.isSigned)
5701                   {
5702                      int value;
5703                      GetInt(e, &value);
5704                      FreeExpContents(exp);
5705                      exp.constant = PrintInt(value);
5706                      exp.type = constantExp;
5707                   }
5708                   else
5709                   {
5710                      unsigned int value;
5711                      GetUInt(e, &value);
5712                      FreeExpContents(exp);
5713                      exp.constant = PrintUInt(value);
5714                      exp.type = constantExp;
5715                   }
5716                   break;
5717                case int64Type:
5718                   if(type.isSigned)
5719                   {
5720                      int64 value;
5721                      GetInt64(e, &value);
5722                      FreeExpContents(exp);
5723                      exp.constant = PrintInt64(value);
5724                      exp.type = constantExp;
5725                   }
5726                   else
5727                   {
5728                      uint64 value;
5729                      GetUInt64(e, &value);
5730                      FreeExpContents(exp);
5731                      exp.constant = PrintUInt64(value);
5732                      exp.type = constantExp;
5733                   }
5734                   break;
5735                case floatType:
5736                {
5737                   float value;
5738                   GetFloat(e, &value);
5739                   FreeExpContents(exp);
5740                   exp.constant = PrintFloat(value);
5741                   exp.type = constantExp;
5742                   break;
5743                }
5744                case doubleType:
5745                {  
5746                   double value;
5747                   GetDouble(e, &value);
5748                   FreeExpContents(exp);
5749                   exp.constant = PrintDouble(value);
5750                   exp.type = constantExp;
5751                   break;
5752                }
5753             }
5754          }
5755          break;
5756       }
5757       case conditionExp:
5758       {
5759          Operand op1 { };
5760          Operand op2 { };
5761          Operand op3 { };
5762
5763          if(exp.cond.exp)
5764             // Caring only about last expression for now...
5765             ComputeExpression(exp.cond.exp->last);
5766          if(exp.cond.elseExp)
5767             ComputeExpression(exp.cond.elseExp);
5768          if(exp.cond.cond)
5769             ComputeExpression(exp.cond.cond);
5770
5771          op1 = GetOperand(exp.cond.cond);
5772          if(op1.type) op1.type.refCount++;
5773          op2 = GetOperand(exp.cond.exp->last);
5774          if(op2.type) op2.type.refCount++;
5775          op3 = GetOperand(exp.cond.elseExp);
5776          if(op3.type) op3.type.refCount++;
5777
5778          if(op1.ops.Cond) { FreeExpContents(exp); op1.ops.Cond(exp, op1, op2, op3); }
5779          if(op1.type) FreeType(op1.type);
5780          if(op2.type) FreeType(op2.type);
5781          if(op3.type) FreeType(op3.type);
5782          break;
5783       }  
5784    }
5785 }
5786
5787 static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
5788 {
5789    bool result = true;
5790    if(destType)
5791    {
5792       OldList converts { };
5793       Conversion convert;
5794
5795       if(destType.kind == voidType)
5796          return false;
5797
5798       if(!MatchTypeExpression(exp, destType, &converts, skipUnitBla))
5799          result = false;
5800       if(converts.count)
5801       {
5802          // for(convert = converts.last; convert; convert = convert.prev)
5803          for(convert = converts.first; convert; convert = convert.next)
5804          {
5805             bool empty = !(convert.isGet ? (void *)convert.convert.Get : (void *)convert.convert.Set);
5806             if(!empty)
5807             {
5808                Expression newExp { };
5809                ClassObjectType objectType = exp.expType ? exp.expType.classObjectType : none;
5810
5811                // TODO: Check this...
5812                *newExp = *exp;
5813                newExp.destType = null;
5814
5815                if(convert.isGet)
5816                {
5817                   // [exp].ColorRGB
5818                   exp.type = memberExp;
5819                   exp.addedThis = true;
5820                   exp.member.exp = newExp;
5821                   FreeType(exp.member.exp.expType);
5822
5823                   exp.member.exp.expType = MkClassType(convert.convert._class.fullName);
5824                   exp.member.exp.expType.classObjectType = objectType;
5825                   exp.member.member = MkIdentifier(convert.convert.dataTypeString);
5826                   exp.member.memberType = propertyMember;
5827                   exp.expType = convert.resultType ? convert.resultType : convert.convert.dataType;
5828                   // TESTING THIS... for (int)degrees
5829                   exp.needCast = true;
5830                   if(exp.expType) exp.expType.refCount++;
5831                   ApplyAnyObjectLogic(exp.member.exp);
5832                }
5833                else
5834                {
5835                
5836                   /*if(exp.isConstant)
5837                   {
5838                      // Color { ColorRGB = [exp] };
5839                      exp.type = instanceExp;
5840                      exp.instance = MkInstantiation(MkSpecifierName((convert.convert._class.fullName), //MkClassName(convert.convert._class.fullName),
5841                         null, MkListOne(MkMembersInitList(MkListOne(MkMemberInit(
5842                         MkListOne(MkIdentifier(convert.convert.dataTypeString)), newExp)))));
5843                   }
5844                   else*/
5845                   {
5846                      // If not constant, don't turn it yet into an instantiation
5847                      // (Go through the deep members system first)
5848                      exp.type = memberExp;
5849                      exp.addedThis = true;
5850                      exp.member.exp = newExp;
5851
5852                      // ADDED THIS HERE TO SOLVE PROPERTY ISSUES WITH NOHEAD CLASSES
5853                      if(/*!notByReference && */newExp.expType && newExp.expType.kind == classType && newExp.expType._class && newExp.expType._class.registered &&
5854                         newExp.expType._class.registered.type == noHeadClass)
5855                      {
5856                         newExp.byReference = true;
5857                      }
5858
5859                      FreeType(exp.member.exp.expType);
5860                      /*exp.member.exp.expType = convert.convert.dataType;
5861                      if(convert.convert.dataType) convert.convert.dataType.refCount++;*/
5862                      exp.member.exp.expType = null;
5863                      if(convert.convert.dataType)
5864                      {
5865                         exp.member.exp.expType = { };
5866                         CopyTypeInto(exp.member.exp.expType, convert.convert.dataType);
5867                         exp.member.exp.expType.refCount = 1;
5868                         exp.member.exp.expType.classObjectType = objectType;
5869                         ApplyAnyObjectLogic(exp.member.exp);
5870                      }
5871
5872                      exp.member.member = MkIdentifier(convert.convert._class.fullName);
5873                      exp.member.memberType = reverseConversionMember;
5874                      exp.expType = convert.resultType ? convert.resultType :
5875                         MkClassType(convert.convert._class.fullName);
5876                      exp.needCast = true;
5877                      if(convert.resultType) convert.resultType.refCount++;
5878                   }
5879                }
5880             }
5881             else
5882             {
5883                FreeType(exp.expType);
5884                if(convert.isGet)
5885                {
5886                   exp.expType = convert.resultType ? convert.resultType : convert.convert.dataType;
5887                   exp.needCast = true;
5888                   if(exp.expType) exp.expType.refCount++;
5889                }
5890                else
5891                {
5892                   exp.expType = convert.resultType ? convert.resultType : MkClassType(convert.convert._class.fullName);
5893                   exp.needCast = true;
5894                   if(convert.resultType)
5895                      convert.resultType.refCount++;
5896                }
5897             }
5898          }
5899          if(exp.isConstant && inCompiler)
5900             ComputeExpression(exp);
5901
5902          converts.Free(FreeConvert);
5903       }
5904
5905       if(!result && exp.expType && converts.count)      // TO TEST: Added converts.count here to avoid a double warning with function type
5906       {
5907          result = MatchTypes(exp.expType, exp.destType, null, null, null, true, true, false, false);
5908       }
5909       if(!result && exp.expType && exp.destType)
5910       {
5911          if((exp.destType.kind == classType && exp.expType.kind == pointerType && 
5912              exp.expType.type.kind == classType && exp.expType.type._class == exp.destType._class && exp.destType._class.registered && exp.destType._class.registered.type == structClass) ||
5913             (exp.expType.kind == classType && exp.destType.kind == pointerType && 
5914             exp.destType.type.kind == classType && exp.destType.type._class == exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass))
5915             result = true;
5916       }
5917    }
5918    // if(result) CheckTemplateTypes(exp);
5919    return result;
5920 }
5921
5922 void CheckTemplateTypes(Expression exp)
5923 {
5924    if(exp.destType && exp.destType.passAsTemplate && exp.expType && exp.expType.kind != templateType && !exp.expType.passAsTemplate)
5925    {
5926       Expression newExp { };
5927       Statement compound;
5928       Context context;
5929       *newExp = *exp;
5930       if(exp.destType) exp.destType.refCount++;
5931       if(exp.expType)  exp.expType.refCount++;
5932       newExp.prev = null;
5933       newExp.next = null;
5934
5935       switch(exp.expType.kind)
5936       {
5937          case doubleType:
5938             exp.type = opExp;
5939             exp.op.exp1 = null;
5940             context = PushContext();               
5941             exp.op.exp2 = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)), 
5942                MkExpExtensionCompound(compound = MkCompoundStmt(
5943                   MkListOne(MkDeclaration(MkListOne(MkSpecifier(DOUBLE)), 
5944                      MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal")), MkInitializerAssignment(newExp))))),
5945                   MkListOne(MkExpressionStmt(MkListOne(MkExpOp(null, '&', MkExpIdentifier(MkIdentifier("__internal")))))))));
5946             compound.compound.context = context;
5947             PopContext(context);
5948             exp.op.op = '*';
5949             break;
5950          default:
5951             exp.type = castExp;
5952             exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
5953             exp.cast.exp = MkExpBrackets(MkListOne(newExp));
5954             break;
5955       }
5956    }
5957    else if(exp.expType && exp.expType.passAsTemplate && exp.destType && exp.usage.usageGet && exp.destType.kind != templateType && !exp.destType.passAsTemplate)
5958    {
5959       Expression newExp { };
5960       Statement compound;
5961       Context context;
5962       *newExp = *exp;
5963       if(exp.destType) exp.destType.refCount++;
5964       if(exp.expType)  exp.expType.refCount++;
5965       newExp.prev = null;
5966       newExp.next = null;
5967
5968       switch(exp.expType.kind)
5969       {
5970          case doubleType:
5971             exp.type = opExp;
5972             exp.op.exp1 = null;
5973             context = PushContext();               
5974             exp.op.exp2 = MkExpCast(MkTypeName(MkListOne(MkSpecifier(DOUBLE)), MkDeclaratorPointer(MkPointer(null, null), null)), 
5975                MkExpExtensionCompound(compound = MkCompoundStmt(
5976                   MkListOne(MkDeclaration(MkListOne(MkSpecifierName("uint64")), 
5977                      MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal")), MkInitializerAssignment(newExp))))),
5978                   MkListOne(MkExpressionStmt(MkListOne(MkExpOp(null, '&', MkExpIdentifier(MkIdentifier("__internal")))))))));
5979             compound.compound.context = context;
5980             PopContext(context);
5981             exp.op.op = '*';
5982             ProcessExpressionType(exp.op.exp2);
5983             break;
5984          case classType:
5985          {
5986             if(exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass)
5987             {
5988                exp.type = bracketsExp;
5989                exp.list = MkListOne(MkExpOp(null, '*', MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)),
5990                   MkDeclaratorPointer(MkPointer(null, null), null)), newExp)));
5991                ProcessExpressionType(exp.list->first);
5992                break;
5993             }
5994             else
5995             {
5996                exp.type = bracketsExp;
5997                exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)), null), newExp));
5998                newExp.needCast = true;
5999                ProcessExpressionType(exp.list->first);
6000                break;
6001             }
6002          }
6003          default:
6004          {
6005             if(exp.expType.kind == templateType)
6006             {
6007                Type type = ProcessTemplateParameterType(exp.expType.templateParameter);
6008                if(type)
6009                {
6010                   FreeType(exp.destType);
6011                   FreeType(exp.expType);
6012                   delete newExp;
6013                   break;
6014                }
6015             }
6016             if(newExp.type == memberExp && newExp.member.memberType == dataMember)
6017             {
6018                exp.type = opExp;
6019                exp.op.op = '*';
6020                exp.op.exp1 = null;
6021                exp.op.exp2 = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)),
6022                   MkExpBrackets(MkListOne(MkExpOp(null, '&', newExp))));
6023             }
6024             else
6025             {
6026                char typeString[1024];
6027                Declarator decl;
6028                OldList * specs = MkList();
6029                typeString[0] = '\0';
6030                PrintType(exp.expType, typeString, false, false);
6031                decl = SpecDeclFromString(typeString, specs, null);
6032                
6033                exp.type = castExp;
6034                //exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
6035                exp.cast.typeName = MkTypeName(specs, decl);
6036                exp.cast.exp = MkExpBrackets(MkListOne(newExp));
6037                exp.cast.exp.needCast = true;
6038             }
6039             break;
6040          }
6041       }
6042    }
6043 }
6044
6045 static Symbol ScanWithNameSpace(BinaryTree tree, char * nameSpace, char * name)
6046 {
6047    Symbol symbol;
6048    int nsLen = strlen(nameSpace);
6049    for(symbol = (Symbol)tree.first; symbol; symbol = (Symbol)((BTNode)symbol).next)
6050    {
6051       if(!strncmp(symbol.string, nameSpace, nsLen))
6052       {
6053          int c;
6054          char * namePart;
6055          for(c = strlen(symbol.string)-1; c >= 0; c--)
6056             if(symbol.string[c] == ':')
6057                break;
6058
6059          namePart = symbol.string+c+1;
6060          if(!strcmp(namePart, name))
6061          {
6062             // TODO: Error on ambiguity
6063             return symbol;
6064          }
6065       }
6066    }
6067    return null;
6068 }
6069
6070 static Symbol FindWithNameSpace(BinaryTree tree, char * name)
6071 {
6072    int c;
6073    char nameSpace[1024];
6074    char * namePart;
6075    bool gotColon = false;
6076
6077    nameSpace[0] = '\0';
6078    for(c = strlen(name)-1; c >= 0; c--)
6079       if(name[c] == ':')
6080       {
6081          gotColon = true;
6082          break;
6083       }
6084
6085    namePart = name+c+1;
6086    while(c >= 0 && name[c] == ':') c--;
6087    if(c >= 0)
6088    {
6089       memcpy(nameSpace, name, c + 1);
6090       nameSpace[c+1] = 0;
6091       return ScanWithNameSpace(tree, nameSpace, namePart);
6092    }
6093    else if(gotColon)
6094    {
6095       Symbol symbol = (Symbol)tree.FindString(namePart);
6096       return symbol;
6097    }
6098    else
6099       return ScanWithNameSpace(tree, "", namePart);
6100    return null;
6101 }
6102
6103 static void ProcessDeclaration(Declaration decl);
6104
6105 /*static */Symbol FindSymbol(char * name, Context startContext, Context endContext, bool isStruct, bool globalNameSpace)
6106 {
6107 #ifdef _DEBUG
6108    //Time startTime = GetTime();
6109 #endif
6110    // Optimize this later? Do this before/less?
6111    Context ctx;
6112    Symbol symbol = null;
6113    // First, check if the identifier is declared inside the function
6114    //for(ctx = curContext; ctx /*!= topContext.parent */&& !symbol; ctx = ctx.parent)
6115
6116    for(ctx = startContext; ctx /*!= topContext.parent */&& !symbol; ctx = ctx.parent)
6117    {
6118       if(ctx == globalContext && !globalNameSpace)
6119       {
6120          symbol = null;
6121          if(thisNameSpace)
6122          {
6123             char curName[1024];
6124             strcpy(curName, thisNameSpace);
6125             strcat(curName, "::");
6126             strcat(curName, name);
6127             symbol = FindWithNameSpace(isStruct ? ctx.structSymbols : ctx.symbols, curName);
6128          }
6129          if(!symbol)
6130             symbol = FindWithNameSpace(isStruct ? ctx.structSymbols : ctx.symbols, name);
6131       }
6132       else if(isStruct)
6133          symbol = (Symbol)ctx.structSymbols.FindString(name);
6134       else
6135          symbol = (Symbol)ctx.symbols.FindString(name);
6136
6137       if(symbol || ctx == endContext) break;
6138    }
6139    if(inCompiler && curExternal && symbol && ctx == globalContext && curExternal.symbol && symbol.id > curExternal.symbol.idCode && symbol.pointerExternal)
6140    {
6141       if(symbol.pointerExternal.type == functionExternal)
6142       {
6143          FunctionDefinition function = symbol.pointerExternal.function;
6144
6145          // Modified this recently...
6146          Context tmpContext = curContext;
6147          curContext = null;         
6148          symbol.pointerExternal = MkExternalDeclaration(MkDeclaration(CopyList(function.specifiers, CopySpecifier), MkListOne(MkInitDeclarator(CopyDeclarator(function.declarator), null))));
6149          curContext = tmpContext;
6150
6151          symbol.pointerExternal.symbol = symbol;
6152
6153          // TESTING THIS:
6154          DeclareType(symbol.type, true, true);
6155
6156          ast->Insert(curExternal.prev, symbol.pointerExternal);
6157
6158          symbol.id = curExternal.symbol.idCode;
6159
6160       }
6161       else if(symbol.pointerExternal.type == declarationExternal && curExternal.symbol.idCode < symbol.pointerExternal.symbol.id) // Added id comparison because Global Function prototypes were broken
6162       {
6163          ast->Move(symbol.pointerExternal, curExternal.prev);
6164          symbol.id = curExternal.symbol.idCode;
6165       }
6166    }
6167 #ifdef _DEBUG
6168    //findSymbolTotalTime += GetTime() - startTime;
6169 #endif
6170    return symbol;
6171 }
6172
6173 static void GetTypeSpecs(Type type, OldList * specs)
6174 {
6175    if(!type.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
6176    switch(type.kind)
6177    {
6178       case classType: 
6179       {
6180          if(type._class.registered)
6181          {
6182             if(!type._class.registered.dataType)
6183                type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
6184             GetTypeSpecs(type._class.registered.dataType, specs);
6185          }
6186          break;
6187       }
6188       case doubleType: ListAdd(specs, MkSpecifier(DOUBLE)); break;
6189       case floatType: ListAdd(specs, MkSpecifier(FLOAT)); break;
6190       case charType: ListAdd(specs, MkSpecifier(CHAR)); break;
6191       case shortType: ListAdd(specs, MkSpecifier(SHORT)); break;
6192       case int64Type: ListAdd(specs, MkSpecifier(INT64)); break;
6193       case intType: 
6194       default:
6195          ListAdd(specs, MkSpecifier(INT)); break;
6196    }
6197 }
6198
6199 // WARNING : This function expects a null terminated string since it recursively concatenate...
6200 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
6201 {
6202    if(type)
6203    {
6204       switch(type.kind)
6205       {
6206          case classType:
6207             if(type._class && type._class.string)
6208             {
6209                // TODO: typed_object does not fully qualify the type, as it may have taken up an actual class (Stored in _class) from overriding
6210                //       look into merging with thisclass ?
6211                if(type.classObjectType == typedObject)
6212                   strcat(string, "typed_object");
6213                else if(fullName)
6214                   strcat(string, type._class.string);
6215                else
6216                {
6217                   if(type._class.registered)
6218                      strcat(string, type._class.registered.name);
6219                   else
6220                      strcat(string, type._class.string);                     
6221                }
6222             }
6223             break;
6224          case pointerType:
6225          {
6226             /*Type funcType;
6227             for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6228             if(funcType && funcType.kind == functionType)
6229             {
6230                Type param;
6231                PrintType(funcType.returnType, string, false, fullName);
6232                strcat(string, "(*");
6233                if(printName || funcType.thisClass)
6234                {
6235                   strcat(string, " ");
6236                   if(funcType.thisClass)
6237                   {
6238                      strcat(string, funcType.thisClass.string);
6239                      strcat(string, "::");
6240                   }
6241                   if(type.name)
6242                      strcat(string, type.name);
6243                }
6244                strcat(string, ")(");
6245                for(param = funcType.params.first; param; param = param.next)
6246                {
6247                   PrintType(param, string, false, fullName);
6248                   if(param.next) strcat(string, ", ");
6249                }
6250                strcat(string, ")");               
6251             }
6252             else*/
6253             {
6254                _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
6255                strcat(string, " *");
6256             }
6257             break;
6258          }
6259          case voidType: strcat(string, "void"); break;
6260          case intType:  strcat(string, type.isSigned ? "int" : "uint"); break;
6261          case int64Type:  strcat(string, type.isSigned ? "int64" : "uint64"); break;
6262          case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
6263          case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
6264          case floatType: strcat(string, "float"); break;
6265          case doubleType: strcat(string, "double"); break;
6266          case structType:
6267             if(type.enumName)
6268             {
6269                strcat(string, "struct ");
6270                strcat(string, type.enumName);
6271             }
6272             else if(type.typeName)
6273             {
6274                strcat(string, type.typeName);
6275             }
6276             else
6277             {
6278                /*
6279                strcat(string, "struct ");
6280                strcat(string,"(unnamed)");
6281                */
6282                Type member;
6283                strcat(string, "struct {");
6284                for(member = type.members.first; member; member = member.next)
6285                {
6286                   PrintType(member, string, true, fullName);
6287                   strcat(string,"; ");
6288                }
6289                strcat(string,"}");
6290             }
6291             break;
6292          case unionType:
6293             if(type.enumName)
6294             {
6295                strcat(string, "union ");
6296                strcat(string, type.enumName);
6297             }
6298             else if(type.typeName)
6299             {
6300                strcat(string, type.typeName);
6301             }
6302             else
6303             {
6304                strcat(string, "union ");
6305                strcat(string,"(unnamed)");
6306             }
6307             break;
6308          case enumType:
6309             if(type.enumName)
6310             {
6311                strcat(string, "enum ");
6312                strcat(string, type.enumName);
6313             }
6314             else if(type.typeName)
6315             {
6316                strcat(string, type.typeName);
6317             }
6318             else
6319                strcat(string, "enum");
6320             break;
6321          case functionType:
6322          {
6323             if(printFunction)
6324             {
6325                if(type.dllExport)
6326                   strcat(string, "dllexport ");
6327                PrintType(type.returnType, string, false, fullName);
6328                strcat(string, " ");
6329             }
6330             
6331             // DANGER: Testing This
6332             if(printName)
6333             {
6334                if(type.name)
6335                {
6336                   if(fullName)
6337                      strcat(string, type.name);
6338                   else
6339                   {
6340                      char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
6341                      if(name) name += 2; else name = type.name;
6342                      strcat(string, name);
6343                   }
6344                }
6345 #ifdef _DEBUG
6346                else
6347                {
6348                   printf("");
6349                }
6350 #endif
6351             }
6352
6353             if(printFunction)
6354             {
6355                Type param;
6356                strcat(string, "(");
6357                for(param = type.params.first; param; param = param.next)
6358                {
6359                   PrintType(param, string, true, fullName);
6360                   if(param.next) strcat(string, ", ");
6361                }
6362                strcat(string, ")");
6363             }
6364             break;
6365          }
6366          case arrayType:
6367          {
6368             /*Type funcType;
6369             for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6370             if(funcType && funcType.kind == functionType)
6371             {
6372                Type param;
6373                PrintType(funcType.returnType, string, false, fullName);
6374                strcat(string, "(*");
6375                if(printName || funcType.thisClass)
6376                {
6377                   strcat(string, " ");
6378                   if(funcType.thisClass)
6379                   {
6380                      strcat(string, funcType.thisClass.string);
6381                      strcat(string, "::");
6382                   }
6383                   if(type.name)
6384                      strcat(string, type.name);
6385                }
6386                strcat(string, ")(");
6387                for(param = funcType.params.first; param; param = param.next)
6388                {
6389                   PrintType(param, string, false, fullName);
6390                   if(param.next) strcat(string, ", ");
6391                }
6392                strcat(string, ")");               
6393             }
6394             else*/
6395             {
6396                char baseType[1024], size[256];
6397                Type arrayType = type;
6398                baseType[0] = '\0';
6399                size[0] = '\0';
6400
6401                while(arrayType.kind == TypeKind::arrayType)
6402                {
6403                   strcat(size, "[");
6404                   if(arrayType.enumClass)
6405                      strcat(size, arrayType.enumClass.string);
6406                   else if(arrayType.arraySizeExp)
6407                      PrintExpression(arrayType.arraySizeExp, size);
6408                   //sprintf(string, "%s[%s]", baseType, size); 
6409                   strcat(size, "]");
6410
6411                   arrayType = arrayType.arrayType;
6412                }
6413                _PrintType(arrayType, baseType, printName, printFunction, fullName);
6414                strcat(string, baseType);
6415                strcat(string, size);
6416             }
6417
6418             /*
6419                PrintType(type.arrayType, baseType, printName, fullName);
6420                if(type.enumClass)
6421                   strcpy(size, type.enumClass.string);
6422                else if(type.arraySizeExp)
6423                   PrintExpression(type.arraySizeExp, size);
6424                //sprintf(string, "%s[%s]", baseType, size); 
6425                strcat(string, baseType);
6426                strcat(string, "[");
6427                strcat(string, size); 
6428                strcat(string, "]");
6429                */
6430
6431             printName = false;
6432             break;
6433          }
6434          case ellipsisType:
6435             strcat(string, "...");
6436             break;
6437          case methodType:
6438             _PrintType(type.method.dataType, string, false, printFunction, fullName);
6439             break;
6440          case subClassType:
6441             strcat(string, "subclass(");
6442             strcat(string, type._class ? type._class.string : "int");
6443             strcat(string, ")");                  
6444             break;
6445          case templateType:
6446             strcat(string, type.templateParameter.identifier.string);
6447             break;
6448          case thisClassType:
6449             strcat(string, "thisclass");
6450             break;
6451          case vaListType:
6452          strcat(string, "__builtin_va_list");
6453             break;
6454 #ifdef _DEBUG
6455          default:
6456             printf("");
6457 #endif
6458       }
6459       if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
6460       {
6461          strcat(string, " ");
6462          strcat(string, type.name);
6463       }
6464    }
6465 }
6466
6467 void PrintType(Type type, char * string, bool printName, bool fullName)
6468 {
6469    Type funcType;
6470    for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6471    if(funcType && funcType.kind == functionType && type != funcType)
6472    {
6473       char typeString[1024];
6474       Type param;
6475
6476       PrintType(funcType.returnType, string, false, fullName);
6477       strcat(string, "(");
6478       _PrintType(type, string, printName, false, fullName);
6479       strcat(string, ")");
6480       /*
6481       if(type.name)
6482          strcat(string, type.name);
6483       else
6484       {
6485          printf("");
6486       }
6487       */
6488       strcat(string, "(");
6489       for(param = funcType.params.first; param; param = param.next)
6490       {
6491          PrintType(param, string, true, fullName);
6492          if(param.next) strcat(string, ", ");
6493       }
6494       strcat(string, ")");
6495    }
6496    else
6497       _PrintType(type, string, printName, true, fullName);
6498    if(type.bitFieldCount)
6499    {
6500       char count[100];
6501       sprintf(count, ":%d", type.bitFieldCount);
6502       strcat(string, count);
6503    }
6504 }
6505
6506 static Type FindMember(Type type, char * string)
6507 {
6508    Type memberType;
6509    for(memberType = type.members.first; memberType; memberType = memberType.next)
6510    {
6511       if(!memberType.name)
6512       {
6513          Type subType = FindMember(memberType, string);
6514          if(subType)
6515             return subType;
6516       }
6517       else if(!strcmp(memberType.name, string))
6518          return memberType;
6519    }
6520    return null;
6521 }
6522
6523 Type FindMemberAndOffset(Type type, char * string, uint * offset)
6524 {
6525    Type memberType;
6526    for(memberType = type.members.first; memberType; memberType = memberType.next)
6527    {
6528       if(!memberType.name)
6529       {
6530          Type subType = FindMember(memberType, string);
6531          if(subType)
6532          {
6533             *offset += memberType.offset;
6534             return subType;
6535          }
6536       }
6537       else if(!strcmp(memberType.name, string))
6538       {
6539          *offset += memberType.offset;
6540          return memberType;
6541       }
6542    }
6543    return null;
6544 }
6545
6546 Expression ParseExpressionString(char * expression)
6547 {
6548    fileInput = TempFile { };
6549    fileInput.Write(expression, 1, strlen(expression));
6550    fileInput.Seek(0, start);
6551
6552    echoOn = false;
6553    parsedExpression = null;
6554    resetScanner();
6555    expression_yyparse();
6556    delete fileInput;
6557
6558    return parsedExpression;
6559 }
6560
6561 static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassCheck)
6562 {
6563    Identifier id = exp.identifier;
6564    Method method = null;
6565    Property prop = null;
6566    DataMember member = null;
6567    ClassProperty classProp = null;
6568
6569    if(_class && _class.type == enumClass)
6570    {
6571       NamedLink value = null;
6572       Class enumClass = eSystem_FindClass(privateModule, "enum");
6573       if(enumClass)
6574       {
6575          Class baseClass;
6576          for(baseClass = _class; baseClass && baseClass.type == ClassType::enumClass; baseClass = baseClass.base)
6577          {
6578             EnumClassData e = ACCESS_CLASSDATA(baseClass, enumClass);
6579             for(value = e.values.first; value; value = value.next)
6580             {
6581                if(!strcmp(value.name, id.string))
6582                   break;
6583             }
6584             if(value)
6585             {
6586                char constant[256];
6587
6588                FreeExpContents(exp);
6589
6590                exp.type = constantExp;
6591                exp.isConstant = true;
6592                if(!strcmp(baseClass.dataTypeString, "int"))
6593                   sprintf(constant, "%d",value.data);
6594                else
6595                   sprintf(constant, "0x%X",value.data);
6596                exp.constant = CopyString(constant);
6597                //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
6598                exp.expType = MkClassType(baseClass.fullName);
6599                break;
6600             }
6601          }
6602       }
6603       if(value)
6604          return true;
6605    }
6606    if((method = eClass_FindMethod(_class, id.string, privateModule)))
6607    {
6608       ProcessMethodType(method);
6609       exp.expType = Type
6610       {
6611          refCount = 1;
6612          kind = methodType;
6613          method = method;
6614          // Crash here?
6615          // TOCHECK: Put it back to what it was...
6616          // methodClass = _class;
6617          methodClass = (skipIDClassCheck || (id && id._class)) ? _class : null;
6618       };
6619       //id._class = null;
6620       return true;
6621    }
6622    else if((prop = eClass_FindProperty(_class, id.string, privateModule)))
6623    {
6624       if(!prop.dataType)
6625          ProcessPropertyType(prop);
6626       exp.expType = prop.dataType;
6627       if(prop.dataType) prop.dataType.refCount++;
6628       return true;
6629    }
6630    else if((member = eClass_FindDataMember(_class, id.string, privateModule, null, null)))
6631    {
6632       if(!member.dataType)
6633          member.dataType = ProcessTypeString(member.dataTypeString, false);
6634       exp.expType = member.dataType;
6635       if(member.dataType) member.dataType.refCount++;
6636       return true;
6637    }
6638    else if((classProp = eClass_FindClassProperty(_class, id.string)))
6639    {
6640       if(!classProp.dataType)
6641          classProp.dataType = ProcessTypeString(classProp.dataTypeString, false);
6642
6643       if(classProp.constant)
6644       {
6645          FreeExpContents(exp);
6646
6647          exp.isConstant = true;
6648          if(classProp.dataType.kind == pointerType && classProp.dataType.type.kind == charType)
6649          {
6650             //char constant[256];
6651             exp.type = stringExp;
6652             exp.constant = QMkString((char *)classProp.Get(_class));
6653          }
6654          else
6655          {
6656             char constant[256];
6657             exp.type = constantExp;
6658             sprintf(constant, "%d",classProp.Get(_class));
6659             exp.constant = CopyString(constant);
6660          }
6661       }
6662       else
6663       {
6664          // TO IMPLEMENT...
6665       }
6666
6667       exp.expType = classProp.dataType;
6668       if(classProp.dataType) classProp.dataType.refCount++;
6669       return true;
6670    }
6671    return false;
6672 }
6673
6674 static GlobalData ScanGlobalData(NameSpace nameSpace, char * name)
6675 {
6676    BinaryTree * tree = &nameSpace.functions;
6677    GlobalData data = (GlobalData)tree->FindString(name);
6678    NameSpace * child;
6679    if(!data)
6680    {
6681       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
6682       {
6683          data = ScanGlobalData(child, name);
6684          if(data)
6685             break;
6686       }
6687    }
6688    return data;
6689 }
6690
6691 static GlobalData FindGlobalData(char * name)
6692 {
6693    int start = 0, c;
6694    NameSpace * nameSpace;
6695    nameSpace = globalData;
6696    for(c = 0; name[c]; c++)
6697    {
6698       if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
6699       {
6700          NameSpace * newSpace;
6701          char * spaceName = new char[c - start + 1];
6702          strncpy(spaceName, name + start, c - start);
6703          spaceName[c-start] = '\0';
6704          newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
6705          delete spaceName;
6706          if(!newSpace)
6707             return null;
6708          nameSpace = newSpace;
6709          if(name[c] == ':') c++;
6710          start = c+1;
6711       }
6712    }
6713    if(c - start)
6714    {
6715       return ScanGlobalData(nameSpace, name + start);
6716    }
6717    return null;
6718 }
6719
6720 static int definedExpStackPos;
6721 static void * definedExpStack[512];
6722
6723 // This function makes checkedExp equivalent to newExp, ending up freeing newExp
6724 void ReplaceExpContents(Expression checkedExp, Expression newExp)
6725 {
6726    Expression prev = checkedExp.prev, next = checkedExp.next;
6727
6728    FreeExpContents(checkedExp);
6729    FreeType(checkedExp.expType);
6730    FreeType(checkedExp.destType);
6731
6732    *checkedExp = *newExp;
6733
6734    delete newExp;
6735
6736    checkedExp.prev = prev;
6737    checkedExp.next = next;
6738 }
6739
6740 void ApplyAnyObjectLogic(Expression e)
6741 {
6742    Type destType = /*(e.destType && e.destType.kind == ellipsisType) ? ellipsisDestType : */e.destType;
6743    if(destType && (/*destType.classObjectType == ClassObjectType::typedObject || */destType.classObjectType == anyObject))
6744    {
6745       //if(e.destType && e.destType.kind == ellipsisType) usedEllipsis = true;
6746       //ellipsisDestType = destType;
6747       if(e && e.expType)
6748       {
6749          Type type = e.expType;
6750          Class _class = null;
6751          //Type destType = e.destType;
6752
6753          if(type.kind == classType && type._class && type._class.registered)
6754          {
6755             _class = type._class.registered;
6756          }
6757          else if(type.kind == subClassType)
6758          {
6759             _class = FindClass("ecere::com::Class").registered;
6760          }
6761          else
6762          {
6763             char string[1024] = "";
6764             Symbol classSym;
6765
6766             PrintType(type, string, false, true);
6767             classSym = FindClass(string);
6768             if(classSym) _class = classSym.registered;
6769          }
6770
6771          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...
6772             (!e.expType.classObjectType && (((type.kind != pointerType && type.kind != subClassType && (type.kind != classType || !type._class || !type._class.registered || type._class.registered.type == structClass))) ||
6773             destType.byReference)))
6774          {
6775             if(!_class || strcmp(_class.fullName, "char *"))     // TESTING THIS WITH NEW String class...
6776             {
6777                Expression checkedExp = e, newExp;
6778
6779                while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
6780                {
6781                   if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
6782                   {
6783                      if(checkedExp.type == extensionCompoundExp)
6784                      {
6785                         checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
6786                      }
6787                      else
6788                         checkedExp = checkedExp.list->last;
6789                   }
6790                   else if(checkedExp.type == castExp)
6791                      checkedExp = checkedExp.cast.exp;
6792                }
6793
6794                if(checkedExp && checkedExp.type == opExp && checkedExp.op.op == '*' && !checkedExp.op.exp1)
6795                {
6796                   newExp = checkedExp.op.exp2;
6797                   checkedExp.op.exp2 = null;
6798                   FreeExpContents(checkedExp);
6799                   
6800                   if(e.expType && e.expType.passAsTemplate)
6801                   {
6802                      char size[100];
6803                      ComputeTypeSize(e.expType);
6804                      sprintf(size, "%d", e.expType.size);
6805                      newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
6806                         MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
6807                            MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
6808                   }
6809
6810                   ReplaceExpContents(checkedExp, newExp);
6811                   e.byReference = true;
6812                }
6813                else if(!e.byReference || (_class && _class.type == noHeadClass))     // TESTING THIS HERE...
6814                {
6815                   Expression checkedExp, newExp;
6816
6817                   {
6818                      // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
6819                      bool hasAddress =
6820                         e.type == identifierExp ||
6821                         (e.type == ExpressionType::memberExp && e.member.memberType == dataMember) ||
6822                         (e.type == ExpressionType::pointerExp && e.member.memberType == dataMember) ||
6823                         (e.type == opExp && !e.op.exp1 && e.op.op == '*') ||
6824                         e.type == indexExp;
6825
6826                      if(_class && _class.type != noHeadClass && _class.type != normalClass && _class.type != structClass && !hasAddress)
6827                      {
6828                         Context context = PushContext();
6829                         Declarator decl;
6830                         OldList * specs = MkList();
6831                         char typeString[1024];
6832                         Expression newExp { };
6833
6834                         typeString[0] = '\0';
6835                         *newExp = *e;
6836
6837                         //if(e.destType) e.destType.refCount++;
6838                         // if(exp.expType) exp.expType.refCount++;
6839                         newExp.prev = null;
6840                         newExp.next = null;
6841                         newExp.expType = null;
6842
6843                         PrintType(e.expType, typeString, false, true);
6844                         decl = SpecDeclFromString(typeString, specs, null);
6845                         newExp.destType = ProcessType(specs, decl);
6846
6847                         curContext = context;
6848                         e.type = extensionCompoundExp;
6849                         e.compound = MkCompoundStmt(
6850                            MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(
6851                               MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))), 
6852
6853                            MkListOne(MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier("__internalValue"))))));
6854                         
6855                         {
6856                            Type type = e.destType;
6857                            e.destType = { };
6858                            CopyTypeInto(e.destType, type);
6859                            e.destType.refCount = 1;
6860                            e.destType.classObjectType = none;
6861                            FreeType(type);
6862                         }
6863
6864                         e.compound.compound.context = context;
6865                         PopContext(context);
6866                         curContext = context.parent;
6867                      }
6868                   }
6869
6870                   // TODO: INTEGRATE THIS WITH VERSION ABOVE WHICH WAS ADDED TO ENCOMPASS OTHER CASE (*pointer)
6871                   checkedExp = e;
6872                   while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
6873                   {
6874                      if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
6875                      {
6876                         if(checkedExp.type == extensionCompoundExp)
6877                         {
6878                            checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
6879                         }
6880                         else
6881                            checkedExp = checkedExp.list->last;
6882                      }
6883                      else if(checkedExp.type == castExp)
6884                         checkedExp = checkedExp.cast.exp;
6885                   }
6886                   {
6887                      Expression operand { };
6888                      operand = *checkedExp;
6889                      checkedExp.destType = null;
6890                      checkedExp.expType = null;
6891                      checkedExp.Clear();
6892                      checkedExp.type = opExp;
6893                      checkedExp.op.op = '&';
6894                      checkedExp.op.exp1 = null;
6895                      checkedExp.op.exp2 = operand;
6896
6897                      //newExp = MkExpOp(null, '&', checkedExp);
6898                   }
6899                   //ReplaceExpContents(checkedExp, newExp);
6900                }
6901             }
6902          }
6903       }
6904    }
6905    {
6906       // If expression type is a simple class, make it an address
6907       // FixReference(e, true);
6908    }
6909 //#if 0
6910    if((!destType || destType.kind == ellipsisType || destType.kind == voidType) && e.expType && (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) && 
6911       (e.expType.byReference || (e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
6912          (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass ) )))
6913    {
6914       if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class"))
6915       {
6916          return;  // LEAVE THIS CASE (typed_object & :: methods 's this) TO PASS 2 FOR NOW
6917       }
6918       else
6919       {
6920          Expression thisExp { };
6921
6922          *thisExp = *e;
6923          thisExp.prev = null;
6924          thisExp.next = null;
6925          e.Clear();
6926
6927          e.type = bracketsExp;
6928          e.list = MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(thisExp))));
6929          if(thisExp.expType.kind == classType && thisExp.expType._class && thisExp.expType._class.registered && thisExp.expType._class.registered.type == noHeadClass)
6930             ((Expression)e.list->first).byReference = true;
6931
6932          /*if(thisExp.expType.kind == classType && thisExp.expType._class && thisExp.expType._class.registered && !strcmp(thisExp.expType._class.registered.name, "class"))
6933          {
6934             e.expType = thisExp.expType;
6935             e.expType.refCount++;
6936          }
6937          else*/
6938          {
6939             e.expType = { };
6940             CopyTypeInto(e.expType, thisExp.expType);
6941             e.expType.byReference = false;
6942             e.expType.refCount = 1;
6943
6944             if(e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
6945                (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass))
6946             {
6947                e.expType.classObjectType = none;
6948             }
6949          }
6950       }
6951    }
6952 // TOFIX: Try this for a nice IDE crash!
6953 //#endif
6954    // The other way around
6955    else 
6956 //#endif
6957    if(destType && e.expType && 
6958          //e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class") &&
6959          (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) && 
6960          !destType.classObjectType && /*(destType.kind != pointerType || !destType.type || destType.type.kind != voidType) &&*/ destType.kind != voidType)
6961    {
6962       if(destType.kind == ellipsisType)
6963       {
6964          Compiler_Error("Unspecified type\n");
6965       }
6966       else if(!(destType.truth && e.expType.kind == classType && e.expType._class && e.expType._class.registered && e.expType._class.registered.type == structClass))
6967       {
6968          bool byReference = e.expType.byReference;
6969          Expression thisExp { };
6970          Declarator decl;
6971          OldList * specs = MkList();
6972          char typeString[1024]; // Watch buffer overruns
6973          Type type;
6974          ClassObjectType backupClassObjectType;
6975
6976          if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && strcmp(e.expType._class.registered.name, "class"))
6977             type = e.expType;
6978          else
6979             type = destType;            
6980
6981          backupClassObjectType = type.classObjectType;
6982
6983          type.classObjectType = none;
6984
6985          typeString[0] = '\0';
6986          PrintType(type, typeString, false, true);
6987          decl = SpecDeclFromString(typeString, specs, null);
6988
6989          type.classObjectType = backupClassObjectType;
6990
6991          *thisExp = *e;
6992          thisExp.prev = null;
6993          thisExp.next = null;
6994          e.Clear();
6995
6996          if( ( type.kind == classType && type._class && type._class.registered && strcmp(type._class.registered.fullName, "ecere::com::Instance") &&
6997                    (type._class.registered.type == systemClass || type._class.registered.type == bitClass || 
6998                     type._class.registered.type == enumClass || type._class.registered.type == unitClass) ) ||
6999              (type.kind != pointerType && type.kind != arrayType && type.kind != classType) ||
7000              (!destType.byReference && byReference && (destType.kind != pointerType || type.kind != pointerType)))
7001          {
7002             e.type = opExp;
7003             e.op.op = '*';
7004             e.op.exp1 = null;
7005             e.op.exp2 = MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), thisExp);
7006          }
7007          else
7008          {
7009             e.type = castExp;
7010             e.cast.typeName = MkTypeName(specs, decl);
7011             e.cast.exp = thisExp;
7012             e.byReference = true;
7013          }
7014          e.expType = type;
7015          e.destType = destType;
7016          type.refCount++;
7017          destType.refCount++;
7018       }
7019    }
7020 }
7021
7022 void ProcessExpressionType(Expression exp)
7023 {
7024    bool unresolved = false;
7025    Location oldyylloc = yylloc;
7026    bool notByReference = false;
7027 #ifdef _DEBUG   
7028    char debugExpString[4096];
7029    debugExpString[0] = '\0';
7030    PrintExpression(exp, debugExpString);
7031 #endif
7032    if(!exp || exp.expType) 
7033       return;
7034
7035    //eSystem_Logf("%s\n", expString);
7036    
7037    // Testing this here
7038    yylloc = exp.loc;
7039    switch(exp.type)
7040    {
7041       case identifierExp:
7042       {
7043          Identifier id = exp.identifier;
7044          if(!id) return;
7045
7046          // DOING THIS LATER NOW...
7047          if(id._class && id._class.name)
7048          {
7049             id.classSym = id._class.symbol; // FindClass(id._class.name);
7050             /* TODO: Name Space Fix ups
7051             if(!id.classSym)
7052                id.nameSpace = eSystem_FindNameSpace(privateModule, id._class.name);
7053             */
7054          }
7055
7056          /* WHY WAS THIS COMMENTED OUT? if(!strcmp(id.string, "__thisModule"))
7057          {
7058             exp.expType = ProcessTypeString("Module", true);
7059             break;
7060          }
7061          else */if(strstr(id.string, "__ecereClass") == id.string)
7062          {
7063             exp.expType = ProcessTypeString("ecere::com::Class", true);
7064             break;
7065          }
7066          else if(id._class && (id.classSym || (id._class.name && !strcmp(id._class.name, "property"))))
7067          {
7068             // Added this here as well
7069             ReplaceClassMembers(exp, thisClass);
7070             if(exp.type != identifierExp)
7071             {
7072                ProcessExpressionType(exp);
7073                break;
7074             }
7075
7076             if(id.classSym && ResolveIdWithClass(exp, id.classSym.registered, false))
7077                break;
7078          }
7079          else
7080          {
7081             Symbol symbol = FindSymbol(id.string, curContext, topContext /*exp.destType ? topContext : globalContext*/, false, id._class && id._class.name == null);
7082             // Enums should be resolved here (Special pass in opExp to fix identifiers not seen as enum on the first pass)
7083             if(!symbol/* && exp.destType*/)
7084             {
7085                if(exp.destType && CheckExpressionType(exp, exp.destType, false))
7086                   break;
7087                else
7088                {
7089                   if(thisClass)
7090                   {
7091                      ReplaceClassMembers(exp, thisClass ? thisClass : currentClass);
7092                      if(exp.type != identifierExp)
7093                      {
7094                         ProcessExpressionType(exp);
7095                         break;
7096                      }
7097                   }
7098                   // Static methods called from inside the _class
7099                   else if(currentClass && !id._class)
7100                   {
7101                      if(ResolveIdWithClass(exp, currentClass, true))
7102                         break;
7103                   }
7104                   symbol = FindSymbol(id.string, topContext.parent, globalContext, false, id._class && id._class.name == null);
7105                }
7106             }
7107
7108             // If we manage to resolve this symbol
7109             if(symbol)
7110             {
7111                Type type = symbol.type;
7112                Class _class = (type && type.kind == classType && type._class) ? type._class.registered : null;
7113
7114                if(_class && !strcmp(id.string, "this") && !type.classObjectType)
7115                {
7116                   Context context = SetupTemplatesContext(_class);
7117                   type = ReplaceThisClassType(_class);
7118                   FinishTemplatesContext(context);
7119                   if(type) type.refCount = 0;   // We'll be incrementing it right below...
7120                }
7121
7122                FreeSpecifier(id._class);
7123                id._class = null;
7124                delete id.string;
7125                id.string = CopyString(symbol.string);
7126
7127                id.classSym = null;
7128                exp.expType = type;
7129                if(type)
7130                   type.refCount++;
7131                if(type && (type.kind == enumType || (_class && _class.type == enumClass)))
7132                   // Add missing cases here... enum Classes...
7133                   exp.isConstant = true;
7134
7135                // TOCHECK: Why was !strcmp(id.string, "this") commented out?
7136                if(symbol.isParam || !strcmp(id.string, "this"))
7137                {
7138                   if(_class && _class.type == structClass)
7139                      exp.byReference = true;
7140                   
7141                   //TESTING COMMENTING THIS OUT IN FAVOR OF ApplyAnyObjectLogic
7142                   /*if(type && _class && (type.classObjectType == typedObject || type.classObjectType == anyObject) && 
7143                      ((_class.type == unitClass || _class.type == enumClass || _class.type == bitClass) || 
7144                      (type.byReference && (_class.type == normalClass || _class.type == noHeadClass))))
7145                   {
7146                      Identifier id = exp.identifier;
7147                      exp.type = bracketsExp;
7148                      exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(id)));
7149                   }*/
7150                }
7151
7152                if(symbol.isIterator)
7153                {
7154                   if(symbol.isIterator == 3)
7155                   {
7156                      exp.type = bracketsExp;
7157                      exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(exp.identifier)));
7158                      ((Expression)exp.list->first).op.exp2.expType = exp.expType;
7159                      exp.expType = null;
7160                      ProcessExpressionType(exp);                     
7161                   }
7162                   else if(symbol.isIterator != 4)
7163                   {
7164                      exp.type = memberExp;
7165                      exp.member.exp = MkExpIdentifier(exp.identifier);
7166                      exp.member.exp.expType = exp.expType;
7167                      /*if(symbol.isIterator == 6)
7168                         exp.member.member = MkIdentifier("key");
7169                      else*/
7170                         exp.member.member = MkIdentifier("data");
7171                      exp.expType = null;
7172                      ProcessExpressionType(exp);
7173                   }
7174                }
7175                break;
7176             }
7177             else
7178             {
7179                DefinedExpression definedExp = null;
7180                if(thisNameSpace && !(id._class && !id._class.name))
7181                {
7182                   char name[1024];
7183                   strcpy(name, thisNameSpace);
7184                   strcat(name, "::");
7185                   strcat(name, id.string);
7186                   definedExp = eSystem_FindDefine(privateModule, name);
7187                }
7188                if(!definedExp)
7189                   definedExp = eSystem_FindDefine(privateModule, id.string);
7190                if(definedExp)
7191                {
7192                   int c;
7193                   for(c = 0; c<definedExpStackPos; c++)
7194                      if(definedExpStack[c] == definedExp)
7195                         break;
7196                   if(c == definedExpStackPos && c < sizeof(definedExpStack) / sizeof(void *))
7197                   {
7198                      Location backupYylloc = yylloc;
7199                      definedExpStack[definedExpStackPos++] = definedExp;
7200                      fileInput = TempFile { };
7201                      fileInput.Write(definedExp.value, 1, strlen(definedExp.value));
7202                      fileInput.Seek(0, start);
7203
7204                      echoOn = false;
7205                      parsedExpression = null;
7206                      resetScanner();
7207                      expression_yyparse();
7208                      delete fileInput;
7209
7210                      yylloc = backupYylloc;
7211
7212                      if(parsedExpression)
7213                      {
7214                         FreeIdentifier(id);
7215                         exp.type = bracketsExp;
7216                         exp.list = MkListOne(parsedExpression);
7217                         parsedExpression.loc = yylloc;
7218                         ProcessExpressionType(exp);
7219                         definedExpStackPos--;
7220                         return;
7221                      }
7222                      definedExpStackPos--;
7223                   }
7224                   else
7225                   {
7226                      if(inCompiler)
7227                      {
7228                         Compiler_Error("Recursion in defined expression %s\n", id.string);
7229                      }
7230                   }
7231                }
7232                else
7233                {
7234                   GlobalData data = null;
7235                   if(thisNameSpace && !(id._class && !id._class.name))
7236                   {
7237                      char name[1024];
7238                      strcpy(name, thisNameSpace);
7239                      strcat(name, "::");
7240                      strcat(name, id.string);
7241                      data = FindGlobalData(name);
7242                   }
7243                   if(!data)
7244                      data = FindGlobalData(id.string);
7245                   if(data)
7246                   {
7247                      DeclareGlobalData(data);
7248                      exp.expType = data.dataType;
7249                      if(data.dataType) data.dataType.refCount++;
7250
7251                      delete id.string;
7252                      id.string = CopyString(data.fullName);
7253                      FreeSpecifier(id._class);
7254                      id._class = null;
7255
7256                      break;
7257                   }
7258                   else
7259                   {
7260                      GlobalFunction function = null;
7261                      if(thisNameSpace && !(id._class && !id._class.name))
7262                      {
7263                         char name[1024];
7264                         strcpy(name, thisNameSpace);
7265                         strcat(name, "::");
7266                         strcat(name, id.string);
7267                         function = eSystem_FindFunction(privateModule, name);
7268                      }
7269                      if(!function)
7270                         function = eSystem_FindFunction(privateModule, id.string);
7271                      if(function)
7272                      {
7273                         char name[1024];
7274                         delete id.string;
7275                         id.string = CopyString(function.name);
7276                         name[0] = 0;
7277
7278                         if(function.module.importType != staticImport && (!function.dataType || !function.dataType.dllExport))
7279                            strcpy(name, "__ecereFunction_");
7280                         FullClassNameCat(name, id.string, false); // Why is this using FullClassNameCat ?
7281                         if(DeclareFunction(function, name))
7282                         {
7283                            delete id.string;
7284                            id.string = CopyString(name);
7285                         }
7286                         exp.expType = function.dataType;
7287                         if(function.dataType) function.dataType.refCount++;
7288
7289                         FreeSpecifier(id._class);
7290                         id._class = null;
7291
7292                         break;
7293                      }
7294                   }
7295                }
7296             }
7297          }
7298          unresolved = true;
7299          break;
7300       }
7301       case instanceExp:
7302       {
7303          Class _class;
7304          // Symbol classSym;
7305
7306          if(!exp.instance._class)
7307          {
7308             if(exp.destType && exp.destType.kind == classType && exp.destType._class)
7309             {
7310                exp.instance._class = MkSpecifierName(exp.destType._class.string);
7311             }
7312 #ifdef _DEBUG
7313             else 
7314             {
7315                printf("");               
7316             }
7317 #endif
7318          }
7319
7320          //classSym = FindClass(exp.instance._class.fullName);
7321          //_class = classSym ? classSym.registered : null;
7322
7323          ProcessInstantiationType(exp.instance);
7324          exp.isConstant = exp.instance.isConstant;
7325
7326          /*
7327          if(_class.type == unitClass && _class.base.type != systemClass)
7328          {
7329             {
7330                Type destType = exp.destType;
7331
7332                exp.destType = MkClassType(_class.base.fullName);
7333                exp.expType = MkClassType(_class.fullName);
7334                CheckExpressionType(exp, exp.destType, true);
7335
7336                exp.destType = destType;
7337             }
7338             exp.expType = MkClassType(_class.fullName);
7339          }
7340          else*/
7341          if(exp.instance._class)
7342          {
7343             exp.expType = MkClassType(exp.instance._class.name);
7344             /*if(exp.expType._class && exp.expType._class.registered && 
7345                (exp.expType._class.registered.type == normalClass || exp.expType._class.registered.type == noHeadClass))
7346                exp.expType.byReference = true;*/
7347          }         
7348          break;
7349       }
7350       case constantExp:
7351       {
7352          if(!exp.expType)
7353          {
7354             Type type
7355             {
7356                refCount = 1;
7357                constant = true;
7358             };
7359             exp.expType = type;
7360
7361             if(exp.constant[0] == '\'')
7362             {
7363                if((int)((byte *)exp.constant)[1] > 127)
7364                {
7365                   int nb;
7366                   unichar ch = UTF8GetChar(exp.constant + 1, &nb);
7367                   if(nb < 2) ch = exp.constant[1];
7368                   delete exp.constant;
7369                   exp.constant = PrintUInt(ch);
7370                   // type.kind = (ch > 0xFFFF) ? intType : shortType;
7371                   type.kind = classType; //(ch > 0xFFFF) ? intType : shortType;
7372                   type._class = FindClass("unichar");
7373
7374                   type.isSigned = false;
7375                }
7376                else
7377                {
7378                   type.kind = charType;
7379                   type.isSigned = true;
7380                }
7381             }
7382             else if(strchr(exp.constant, '.'))
7383             {
7384                char ch = exp.constant[strlen(exp.constant)-1];
7385                if(ch == 'f')
7386                   type.kind = floatType;
7387                else
7388                   type.kind = doubleType;
7389                type.isSigned = true;
7390             }
7391             else
7392             {
7393                if(exp.constant[0] == '0' && exp.constant[1])
7394                   type.isSigned = false;
7395                else if(strchr(exp.constant, 'L') || strchr(exp.constant, 'l'))
7396                   type.isSigned = false;
7397                else if(strtoll(exp.constant, null, 0) > MAXINT)
7398                   type.isSigned = false;
7399                else
7400                   type.isSigned = true;
7401                type.kind = intType;
7402             }
7403             exp.isConstant = true;
7404          }
7405          break;
7406       }
7407       case stringExp:
7408       {
7409          exp.isConstant = true;      // Why wasn't this constant?
7410          exp.expType = Type
7411          {
7412             refCount = 1;
7413             kind = pointerType;
7414             type = Type
7415             {
7416                refCount = 1;
7417                kind = charType;
7418                constant = true;
7419             }
7420          };
7421          break;
7422       }
7423       case newExp:
7424       case new0Exp:
7425          ProcessExpressionType(exp._new.size);
7426          exp.expType = Type
7427          {
7428             refCount = 1;
7429             kind = pointerType;
7430             type = ProcessType(exp._new.typeName.qualifiers, exp._new.typeName.declarator);
7431          };
7432          DeclareType(exp.expType.type, false, false);
7433          break;
7434       case renewExp:
7435       case renew0Exp:
7436          ProcessExpressionType(exp._renew.size);
7437          ProcessExpressionType(exp._renew.exp);
7438          exp.expType = Type
7439          {
7440             refCount = 1;
7441             kind = pointerType;
7442             type = ProcessType(exp._renew.typeName.qualifiers, exp._renew.typeName.declarator);
7443          };
7444          DeclareType(exp.expType.type, false, false);
7445          break;
7446       case opExp:
7447       {
7448          bool assign = false, boolResult = false, boolOps = false;
7449          Type type1 = null, type2 = null;
7450          bool useDestType = false, useSideType = false;
7451          Location oldyylloc = yylloc;
7452          bool useSideUnit = false;
7453
7454          // Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
7455          Type dummy
7456          {
7457             count = 1;
7458             refCount = 1;
7459          };
7460
7461          switch(exp.op.op)
7462          {
7463             // Assignment Operators
7464             case '=': 
7465             case MUL_ASSIGN:
7466             case DIV_ASSIGN:
7467             case MOD_ASSIGN:
7468             case ADD_ASSIGN:
7469             case SUB_ASSIGN:
7470             case LEFT_ASSIGN:
7471             case RIGHT_ASSIGN:
7472             case AND_ASSIGN:
7473             case XOR_ASSIGN:
7474             case OR_ASSIGN:
7475                assign = true;
7476                break;
7477             // boolean Operators
7478             case '!':
7479                // Expect boolean operators
7480                //boolOps = true;
7481                //boolResult = true;
7482                break;
7483             case AND_OP:
7484             case OR_OP:
7485                // Expect boolean operands
7486                boolOps = true;
7487                boolResult = true;
7488                break;
7489             // Comparisons
7490             case EQ_OP:
7491             case '<':
7492             case '>':
7493             case LE_OP:
7494             case GE_OP:
7495             case NE_OP:
7496                // Gives boolean result
7497                boolResult = true;
7498                useSideType = true;
7499                break;
7500             case '+':
7501             case '-':
7502                useSideUnit = true;
7503
7504                // Just added these... testing
7505             case '|':
7506             case '&':
7507             case '^':
7508
7509             // DANGER: Verify units
7510             case '/':
7511             case '%':
7512             case '*':
7513                
7514                if(exp.op.op != '*' || exp.op.exp1)
7515                {
7516                   useSideType = true;
7517                   useDestType = true;
7518                }
7519                break;
7520
7521             /*// Implement speed etc.
7522             case '*':
7523             case '/':
7524                break;
7525             */
7526          }
7527          if(exp.op.op == '&')
7528          {
7529             // Added this here earlier for Iterator address as key
7530             if(!exp.op.exp1 && exp.op.exp2 && exp.op.exp2.type == identifierExp && exp.op.exp2.identifier)
7531             {
7532                Identifier id = exp.op.exp2.identifier;
7533                Symbol symbol = FindSymbol(id.string, curContext, topContext, false, id._class && id._class.name == null);
7534                if(symbol && symbol.isIterator == 2)
7535                {
7536                   exp.type = memberExp;
7537                   exp.member.exp = exp.op.exp2;
7538                   exp.member.member = MkIdentifier("key");
7539                   exp.expType = null;
7540                   exp.op.exp2.expType = symbol.type;
7541                   symbol.type.refCount++;
7542                   ProcessExpressionType(exp);
7543                   FreeType(dummy);
7544                   break;
7545                }
7546                // exp.op.exp2.usage.usageRef = true;
7547             }
7548          }
7549
7550          //dummy.kind = TypeDummy;
7551
7552          if(exp.op.exp1)
7553          {
7554             if(exp.destType && exp.destType.kind == classType &&
7555                exp.destType._class && exp.destType._class.registered && useDestType &&
7556                
7557               ((exp.destType._class.registered.type == unitClass && useSideUnit) || 
7558                exp.destType._class.registered.type == enumClass ||
7559                exp.destType._class.registered.type == bitClass
7560                )) 
7561
7562               //(exp.destType._class.registered.type == unitClass || exp.destType._class.registered.type == enumClass) && useDestType)
7563             {
7564                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7565                exp.op.exp1.destType = exp.destType;
7566                if(exp.destType)
7567                   exp.destType.refCount++;
7568             }
7569             else if(!assign)
7570             {
7571                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7572                exp.op.exp1.destType = dummy;
7573                dummy.refCount++;               
7574             }
7575
7576             // TESTING THIS HERE...
7577             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count++;
7578             ProcessExpressionType(exp.op.exp1);
7579             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count--;
7580
7581             if(exp.op.exp1.destType == dummy)
7582             {
7583                FreeType(dummy);
7584                exp.op.exp1.destType = null;
7585             }
7586             type1 = exp.op.exp1.expType;
7587          }
7588
7589          if(exp.op.exp2)
7590          {
7591             char expString[10240];
7592             expString[0] = '\0';
7593             if(exp.op.exp2.type == instanceExp && !exp.op.exp2.instance._class)
7594             {
7595                if(exp.op.exp1)
7596                {
7597                   exp.op.exp2.destType = exp.op.exp1.expType;
7598                   if(exp.op.exp1.expType)
7599                      exp.op.exp1.expType.refCount++;
7600                }
7601                else
7602                {
7603                   exp.op.exp2.destType = exp.destType;
7604                   if(exp.destType)
7605                      exp.destType.refCount++;
7606                }
7607
7608                if(type1) type1.refCount++;
7609                exp.expType = type1;
7610             }
7611             else if(assign)
7612             {
7613                if(inCompiler)
7614                   PrintExpression(exp.op.exp2, expString);
7615
7616                if(type1 && type1.kind == pointerType)
7617                {
7618                   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 ||
7619                      exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN)
7620                      Compiler_Error("operator %s illegal on pointer\n", exp.op.op);
7621                   else if(exp.op.op == '=')
7622                   {
7623                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7624                      exp.op.exp2.destType = type1;
7625                      if(type1)
7626                         type1.refCount++;
7627                   }
7628                }
7629                else
7630                {
7631                   // Don't convert to the type for those... (e.g.: Degrees a; a /= 2;) 
7632                   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/* ||
7633                      exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN*/);
7634                   else
7635                   {
7636                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7637                      exp.op.exp2.destType = type1;
7638                      if(type1)
7639                         type1.refCount++;
7640                   }
7641                }
7642                if(type1) type1.refCount++;
7643                exp.expType = type1;
7644             }
7645             else if(exp.destType && exp.destType.kind == classType &&
7646                exp.destType._class && exp.destType._class.registered && 
7647                
7648                   ((exp.destType._class.registered.type == unitClass && useDestType && useSideUnit) || 
7649                   (exp.destType._class.registered.type == enumClass && useDestType)) 
7650                   )
7651             {
7652                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7653                exp.op.exp2.destType = exp.destType;
7654                if(exp.destType)
7655                   exp.destType.refCount++;
7656             }
7657             else
7658             {
7659                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7660                exp.op.exp2.destType = dummy;
7661                dummy.refCount++;
7662             }
7663
7664             // TESTING THIS HERE... (DANGEROUS)
7665             if(type1 && boolResult && useSideType && type1.kind == classType && type1._class && type1._class.registered && 
7666                (type1._class.registered.type == bitClass || type1._class.registered.type == enumClass))
7667             {
7668                FreeType(exp.op.exp2.destType);
7669                exp.op.exp2.destType = type1;
7670                type1.refCount++;
7671             }
7672             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count++;
7673             ProcessExpressionType(exp.op.exp2);
7674             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
7675
7676             if(assign && type1 && type1.kind == pointerType && exp.op.exp2.expType)
7677             {
7678                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)
7679                {
7680                   if(exp.op.op != '=' && type1.type.kind == voidType) 
7681                      Compiler_Error("void *: unknown size\n");
7682                }
7683                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|| 
7684                            (type1.type.kind == voidType && exp.op.exp2.expType.kind == classType && exp.op.exp2.expType._class.registered &&
7685                               (exp.op.exp2.expType._class.registered.type == normalClass || 
7686                               exp.op.exp2.expType._class.registered.type == structClass ||
7687                               exp.op.exp2.expType._class.registered.type == noHeadClass)))
7688                {
7689                   if(exp.op.op == ADD_ASSIGN)
7690                      Compiler_Error("cannot add two pointers\n");                   
7691                }
7692                else if((exp.op.exp2.expType.kind == classType && type1.kind == pointerType && type1.type.kind == classType && 
7693                   type1.type._class == exp.op.exp2.expType._class && exp.op.exp2.expType._class.registered && exp.op.exp2.expType._class.registered.type == structClass))
7694                {
7695                   if(exp.op.op == ADD_ASSIGN)
7696                      Compiler_Error("cannot add two pointers\n");                   
7697                }
7698                else if(inCompiler)
7699                {
7700                   char type1String[1024];
7701                   char type2String[1024];
7702                   type1String[0] = '\0';
7703                   type2String[0] = '\0';
7704                   
7705                   PrintType(exp.op.exp2.expType, type1String, false, true);
7706                   PrintType(type1, type2String, false, true);
7707                   ChangeCh(expString, '\n', ' ');
7708                   Compiler_Warning("incompatible expression %s (%s); expected %s\n", expString, type1String, type2String);
7709                }
7710             }
7711
7712             if(exp.op.exp2.destType == dummy)
7713             {
7714                FreeType(dummy);
7715                exp.op.exp2.destType = null;
7716             }
7717
7718             type2 = exp.op.exp2.expType;
7719          }
7720
7721          dummy.kind = voidType;
7722
7723          if(exp.op.op == SIZEOF)
7724          {
7725             exp.expType = Type
7726             {
7727                refCount = 1;
7728                kind = intType;
7729             };
7730             exp.isConstant = true;
7731          }
7732          // Get type of dereferenced pointer
7733          else if(exp.op.op == '*' && !exp.op.exp1)
7734          {
7735             exp.expType = Dereference(type2);
7736             if(type2 && type2.kind == classType)
7737                notByReference = true;
7738          }
7739          else if(exp.op.op == '&' && !exp.op.exp1)
7740             exp.expType = Reference(type2);
7741          else if(!assign)
7742          {
7743             if(boolOps)
7744             {
7745                if(exp.op.exp1) 
7746                {
7747                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7748                   exp.op.exp1.destType = MkClassType("bool");
7749                   exp.op.exp1.destType.truth = true;
7750                   if(!exp.op.exp1.expType)
7751                      ProcessExpressionType(exp.op.exp1);
7752                   else
7753                      CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
7754                   FreeType(exp.op.exp1.expType);
7755                   exp.op.exp1.expType = MkClassType("bool");
7756                   exp.op.exp1.expType.truth = true;
7757                }
7758                if(exp.op.exp2) 
7759                {
7760                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7761                   exp.op.exp2.destType = MkClassType("bool");
7762                   exp.op.exp2.destType.truth = true;
7763                   if(!exp.op.exp2.expType)
7764                      ProcessExpressionType(exp.op.exp2);
7765                   else
7766                      CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
7767                   FreeType(exp.op.exp2.expType);
7768                   exp.op.exp2.expType = MkClassType("bool");
7769                   exp.op.exp2.expType.truth = true;
7770                }
7771             }
7772             else if(exp.op.exp1 && exp.op.exp2 && 
7773                ((useSideType /*&& 
7774                      (useSideUnit || 
7775                         ((!type1 || type1.kind != classType || type1._class.registered.type != unitClass) &&
7776                          (!type2 || type2.kind != classType || type2._class.registered.type != unitClass)))*/) ||
7777                   ((!type1 || type1.kind != classType || !strcmp(type1._class.string, "String")) && 
7778                   (!type2 || type2.kind != classType || !strcmp(type2._class.string, "String")))))
7779             {
7780                if(type1 && type2 &&
7781                   // If either both are class or both are not class
7782                   ((type1.kind == classType && strcmp(type1._class.string, "String")) == (type2.kind == classType && strcmp(type2._class.string, "String"))))
7783                {
7784                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7785                   exp.op.exp2.destType = type1;
7786                   type1.refCount++;
7787                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7788                   exp.op.exp1.destType = type2;
7789                   type2.refCount++;
7790                   // Warning here for adding Radians + Degrees with no destination type
7791                   if(!boolResult && type1.kind == classType && (!exp.destType || exp.destType.kind != classType) && 
7792                      type1._class.registered && type1._class.registered.type == unitClass && 
7793                      type2._class.registered && type2._class.registered.type == unitClass && 
7794                      type1._class.registered != type2._class.registered)
7795                      Compiler_Warning("operating on %s and %s with an untyped result, assuming %s\n",
7796                         type1._class.string, type2._class.string, type1._class.string);
7797
7798                   if(type1.kind == pointerType && type1.type.kind == templateType && type2.kind != pointerType)
7799                   {
7800                      Expression argExp = GetTemplateArgExp(type1.type.templateParameter, thisClass, true);
7801                      if(argExp)
7802                      {
7803                         Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
7804
7805                         exp.op.exp1 = MkExpBrackets(MkListOne(MkExpCast(
7806                            MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), 
7807                            exp.op.exp1)));
7808
7809                         ProcessExpressionType(exp.op.exp1);
7810
7811                         if(type2.kind != pointerType)
7812                         {
7813                            ProcessExpressionType(classExp);
7814
7815                            exp.op.exp2 = MkExpBrackets(MkListOne(MkExpOp(exp.op.exp2, '*', 
7816                               // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
7817                               MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
7818                                  // noHeadClass
7819                                  MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("5")),
7820                                     OR_OP, 
7821                                  // normalClass
7822                                  MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("0"))))),
7823                                     MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
7824                                        MkPointer(null, null), null)))),                                  
7825                                        MkExpMember(classExp, MkIdentifier("typeSize"))))))));
7826
7827                            if(!exp.op.exp2.expType)
7828                               type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
7829
7830                            ProcessExpressionType(exp.op.exp2);
7831                         }
7832                      }
7833                   }
7834                   
7835                   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)))
7836                   {
7837                      if(type1.kind != classType && type1.type.kind == voidType) 
7838                         Compiler_Error("void *: unknown size\n");
7839                      exp.expType = type1;
7840                      if(type1) type1.refCount++;
7841                   }
7842                   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)))
7843                   {
7844                      if(type2.kind != classType && type2.type.kind == voidType) 
7845                         Compiler_Error("void *: unknown size\n");
7846                      exp.expType = type2;
7847                      if(type2) type2.refCount++;
7848                   }
7849                   else if((type1.kind == pointerType && type2.kind != pointerType && type2.kind != arrayType && type2.kind != functionType && type2.kind != methodType && type2.kind != classType && type2.kind != subClassType) ||
7850                           (type2.kind == pointerType && type1.kind != pointerType && type1.kind != arrayType && type1.kind != functionType && type1.kind != methodType && type1.kind != classType && type1.kind != subClassType))
7851                   {
7852                      Compiler_Warning("different levels of indirection\n");
7853                   }
7854                   else 
7855                   {
7856                      bool success = false;
7857                      if(type1.kind == pointerType && type2.kind == pointerType)
7858                      {
7859                         if(exp.op.op == '+')
7860                            Compiler_Error("cannot add two pointers\n");
7861                         else if(exp.op.op == '-')
7862                         {
7863                            // Pointer Subtraction gives integer
7864                            if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false))
7865                            {
7866                               exp.expType = Type
7867                               {
7868                                  kind = intType;
7869                                  refCount = 1;
7870                               };
7871                               success = true;
7872
7873                               if(type1.type.kind == templateType)
7874                               {
7875                                  Expression argExp = GetTemplateArgExp(type1.type.templateParameter, thisClass, true);
7876                                  if(argExp)
7877                                  {
7878                                     Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
7879
7880                                     ProcessExpressionType(classExp);
7881
7882                                     exp.type = bracketsExp;
7883                                     exp.list = MkListOne(MkExpOp(
7884                                        MkExpBrackets(MkListOne(MkExpOp(
7885                                              MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp1)))
7886                                              , exp.op.op, 
7887                                              MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp2)))))), '/', 
7888                                           
7889                                              //MkExpMember(classExp, MkIdentifier("typeSize"))
7890
7891                                              // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
7892                                              MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
7893                                                 // noHeadClass
7894                                                 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass"))),
7895                                                    OR_OP, 
7896                                                 // normalClass
7897                                                 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass")))))),
7898                                                    MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
7899                                                       MkPointer(null, null), null)))),                                  
7900                                                       MkExpMember(classExp, MkIdentifier("typeSize")))))
7901
7902                                              
7903                                              ));
7904                                     
7905                                     ProcessExpressionType(((Expression)exp.list->first).op.exp2);
7906                                     FreeType(dummy);
7907                                     return;                                       
7908                                  }
7909                               }
7910                            }
7911                         }
7912                      }
7913
7914                      if(!success && exp.op.exp1.type == constantExp)
7915                      {
7916                         // If first expression is constant, try to match that first
7917                         if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
7918                         {
7919                            exp.expType = exp.op.exp1.destType;
7920                            if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
7921                            success = true;
7922                         }
7923                         else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
7924                         {
7925                            exp.expType = exp.op.exp2.destType;
7926                            if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
7927                            success = true;
7928                         }
7929                      }
7930                      else if(!success)
7931                      {
7932                         if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
7933                         {
7934                            exp.expType = exp.op.exp2.destType;
7935                            if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
7936                            success = true;
7937                         }
7938                         else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
7939                         {
7940                            exp.expType = exp.op.exp1.destType;
7941                            if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
7942                            success = true;
7943                         }
7944                      }
7945                      if(!success)
7946                      {
7947                         char expString1[10240];
7948                         char expString2[10240];
7949                         char type1[1024];
7950                         char type2[1024];
7951                         expString1[0] = '\0';
7952                         expString2[0] = '\0';
7953                         type1[0] = '\0';
7954                         type2[0] = '\0';
7955                         if(inCompiler)
7956                         {
7957                            PrintExpression(exp.op.exp1, expString1);
7958                            ChangeCh(expString1, '\n', ' ');
7959                            PrintExpression(exp.op.exp2, expString2);
7960                            ChangeCh(expString2, '\n', ' ');
7961                            PrintType(exp.op.exp1.expType, type1, false, true);
7962                            PrintType(exp.op.exp2.expType, type2, false, true);
7963                         }
7964
7965                         Compiler_Warning("incompatible expressions %s (%s) and %s (%s)\n", expString1, type1, expString2, type2);
7966                      }
7967                   }
7968                }
7969                // ADDED THESE TWO FROM OUTSIDE useSideType CHECK
7970                else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type2 && type1 && type2.kind == classType && type1.kind != classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
7971                {
7972                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7973                   // Convert e.g. / 4 into / 4.0
7974                   exp.op.exp1.destType = type2._class.registered.dataType;
7975                   if(type2._class.registered.dataType)
7976                      type2._class.registered.dataType.refCount++;
7977                   CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
7978                   exp.expType = type2;
7979                   if(type2) type2.refCount++;
7980                }
7981                else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type1 && type2 && type1.kind == classType && type2.kind != classType && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
7982                {
7983                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7984                   // Convert e.g. / 4 into / 4.0
7985                   exp.op.exp2.destType = type1._class.registered.dataType;
7986                   if(type1._class.registered.dataType)
7987                      type1._class.registered.dataType.refCount++;
7988                   CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
7989                   exp.expType = type1;
7990                   if(type1) type1.refCount++;
7991                }
7992                else if(type1)
7993                {
7994                   bool valid = false;
7995
7996                   if(!boolResult && useSideUnit && type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
7997                   {
7998                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7999
8000                      if(!type1._class.registered.dataType)
8001                         type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
8002                      exp.op.exp2.destType = type1._class.registered.dataType;
8003                      exp.op.exp2.destType.refCount++;
8004
8005                      CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8006                      type2 = exp.op.exp2.destType;
8007                      exp.expType = type2;
8008                      type2.refCount++;
8009                   }
8010                   
8011                   if(!boolResult && useSideUnit && type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8012                   {
8013                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8014
8015                      if(!type2._class.registered.dataType)
8016                         type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
8017                      exp.op.exp1.destType = type2._class.registered.dataType;
8018                      exp.op.exp1.destType.refCount++;
8019
8020                      CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8021                      type1 = exp.op.exp1.destType;
8022                      exp.expType = type1;
8023                      type1.refCount++;
8024                   }
8025
8026                   // TESTING THIS NEW CODE
8027                   if(!boolResult || exp.op.op == '>' || exp.op.op == '<')
8028                   {
8029                      if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass && exp.op.exp2.expType)
8030                      {
8031                         if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false))
8032                         {
8033                            exp.expType = exp.op.exp1.expType;
8034                            if(exp.op.exp2.expType) exp.op.exp1.expType.refCount++;
8035                            valid = true;
8036                         }
8037                      }
8038                      else if(type2 && (type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass && exp.op.exp1.expType))
8039                      {
8040                         if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false))
8041                         {
8042                            exp.expType = exp.op.exp2.expType;
8043                            if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8044                            valid = true;
8045                         }
8046                      }
8047                   }
8048
8049                   if(!valid)
8050                   {
8051                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8052                      exp.op.exp2.destType = type1;
8053                      type1.refCount++;
8054
8055                      /*
8056                      // Maybe this was meant to be an enum...
8057                      if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8058                      {
8059                         Type oldType = exp.op.exp2.expType;
8060                         exp.op.exp2.expType = null;
8061                         if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8062                            FreeType(oldType);
8063                         else
8064                            exp.op.exp2.expType = oldType;
8065                      }
8066                      */
8067
8068                      /*
8069                      // TESTING THIS HERE... LATEST ADDITION
8070                      if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8071                      {
8072                         if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8073                         exp.op.exp2.destType = type2._class.registered.dataType;
8074                         if(type2._class.registered.dataType)
8075                            type2._class.registered.dataType.refCount++;
8076                         CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8077                         
8078                         //exp.expType = type2._class.registered.dataType; //type2;
8079                         //if(type2) type2.refCount++;
8080                      }
8081
8082                      // TESTING THIS HERE... LATEST ADDITION
8083                      if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8084                      {
8085                         if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8086                         exp.op.exp1.destType = type1._class.registered.dataType;
8087                         if(type1._class.registered.dataType)
8088                            type1._class.registered.dataType.refCount++;
8089                         CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8090                         exp.expType = type1._class.registered.dataType; //type1;
8091                         if(type1) type1.refCount++;
8092                      }
8093                      */
8094
8095                      if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8096                      {
8097                         exp.expType = exp.op.exp2.destType;
8098                         if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8099                      }
8100                      else if(type1 && type2)
8101                      {
8102                         char expString1[10240];
8103                         char expString2[10240];
8104                         char type1String[1024];
8105                         char type2String[1024];
8106                         expString1[0] = '\0';
8107                         expString2[0] = '\0';
8108                         type1String[0] = '\0';
8109                         type2String[0] = '\0';
8110                         if(inCompiler)
8111                         {
8112                            PrintExpression(exp.op.exp1, expString1);
8113                            ChangeCh(expString1, '\n', ' ');
8114                            PrintExpression(exp.op.exp2, expString2);
8115                            ChangeCh(expString2, '\n', ' ');
8116                            PrintType(exp.op.exp1.expType, type1String, false, true);
8117                            PrintType(exp.op.exp2.expType, type2String, false, true);
8118                         }
8119
8120                         Compiler_Warning("incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
8121
8122                         if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8123                         {
8124                            exp.expType = exp.op.exp1.expType;
8125                            if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
8126                         }
8127                         else if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8128                         {
8129                            exp.expType = exp.op.exp2.expType;
8130                            if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8131                         }
8132                      }
8133                   }
8134                }
8135                else if(type2)
8136                {
8137                   // Maybe this was meant to be an enum...
8138                   if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8139                   {
8140                      Type oldType = exp.op.exp1.expType;
8141                      exp.op.exp1.expType = null;
8142                      if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8143                         FreeType(oldType);
8144                      else
8145                         exp.op.exp1.expType = oldType;
8146                   }
8147
8148                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8149                   exp.op.exp1.destType = type2;
8150                   type2.refCount++;
8151                   /*
8152                   // TESTING THIS HERE... LATEST ADDITION
8153                   if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8154                   {
8155                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8156                      exp.op.exp1.destType = type1._class.registered.dataType;
8157                      if(type1._class.registered.dataType)
8158                         type1._class.registered.dataType.refCount++;
8159                   }
8160
8161                   // TESTING THIS HERE... LATEST ADDITION
8162                   if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8163                   {
8164                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8165                      exp.op.exp2.destType = type2._class.registered.dataType;
8166                      if(type2._class.registered.dataType)
8167                         type2._class.registered.dataType.refCount++;
8168                   }
8169                   */
8170
8171                   if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8172                   {
8173                      exp.expType = exp.op.exp1.destType;
8174                      if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8175                   }
8176                }
8177             }
8178             else if(type2 && (!type1 || (type2.kind == classType && type1.kind != classType)))
8179             {
8180                if(type1 && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
8181                {
8182                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8183                   // Convert e.g. / 4 into / 4.0
8184                   exp.op.exp1.destType = type2._class.registered.dataType;
8185                   if(type2._class.registered.dataType)
8186                      type2._class.registered.dataType.refCount++;
8187                   CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8188                }
8189                if(exp.op.op == '!')
8190                {
8191                   exp.expType = MkClassType("bool");
8192                   exp.expType.truth = true;
8193                }
8194                else
8195                {
8196                   exp.expType = type2;
8197                   if(type2) type2.refCount++;
8198                }
8199             }
8200             else if(type1 && (!type2 || (type1.kind == classType && type2.kind != classType)))
8201             {
8202                if(type2 && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
8203                {
8204                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8205                   // Convert e.g. / 4 into / 4.0
8206                   exp.op.exp2.destType = type1._class.registered.dataType;
8207                   if(type1._class.registered.dataType)
8208                      type1._class.registered.dataType.refCount++;
8209                   CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8210                }
8211                exp.expType = type1;
8212                if(type1) type1.refCount++;
8213             }
8214          }
8215          
8216          yylloc = exp.loc;
8217          if(exp.op.exp1 && !exp.op.exp1.expType)
8218          {
8219             char expString[10000];
8220             expString[0] = '\0';
8221             if(inCompiler)
8222             {
8223                PrintExpression(exp.op.exp1, expString);
8224                ChangeCh(expString, '\n', ' ');
8225             }
8226             if(expString[0])
8227                Compiler_Error("couldn't determine type of %s\n", expString);
8228          }
8229          if(exp.op.exp2 && !exp.op.exp2.expType)
8230          {
8231             char expString[10240];
8232             expString[0] = '\0';
8233             if(inCompiler)
8234             {
8235                PrintExpression(exp.op.exp2, expString);
8236                ChangeCh(expString, '\n', ' ');
8237             }
8238             if(expString[0])
8239                Compiler_Error("couldn't determine type of %s\n", expString);
8240          }
8241
8242          if(boolResult)
8243          {
8244             FreeType(exp.expType);
8245             exp.expType = MkClassType("bool");
8246             exp.expType.truth = true;
8247          }
8248
8249          if(exp.op.op != SIZEOF)
8250             exp.isConstant = (!exp.op.exp1 || exp.op.exp1.isConstant) &&
8251                (!exp.op.exp2 || exp.op.exp2.isConstant);
8252
8253          if(exp.op.op == SIZEOF && exp.op.exp2.expType)
8254          {
8255             DeclareType(exp.op.exp2.expType, false, false);
8256          }
8257
8258          yylloc = oldyylloc;
8259
8260          FreeType(dummy);
8261          break;
8262       }
8263       case bracketsExp:
8264       case extensionExpressionExp:
8265       {
8266          Expression e;
8267          exp.isConstant = true;
8268          for(e = exp.list->first; e; e = e.next)
8269          {
8270             bool inced = false;
8271             if(!e.next)
8272             {
8273                FreeType(e.destType);
8274                e.destType = exp.destType;
8275                if(e.destType) { exp.destType.refCount++; e.destType.count++; inced = true; }
8276             }
8277             ProcessExpressionType(e);
8278             if(inced)
8279                exp.destType.count--;
8280             if(!exp.expType && !e.next)
8281             {
8282                exp.expType = e.expType;
8283                if(e.expType) e.expType.refCount++;
8284             }
8285             if(!e.isConstant)
8286                exp.isConstant = false;
8287          }
8288
8289          // In case a cast became a member...
8290          e = exp.list->first;
8291          if(!e.next && e.type == memberExp)
8292          {
8293             // Preserve prev, next
8294             Expression next = exp.next, prev = exp.prev;
8295
8296
8297             FreeType(exp.expType);
8298             FreeType(exp.destType);
8299             delete exp.list;
8300             
8301             *exp = *e;
8302
8303             exp.prev = prev;
8304             exp.next = next;
8305
8306             delete e;
8307
8308             ProcessExpressionType(exp);
8309          }
8310          break;
8311       }
8312       case indexExp:
8313       {
8314          Expression e;
8315          exp.isConstant = true;
8316
8317          ProcessExpressionType(exp.index.exp);
8318          if(!exp.index.exp.isConstant)
8319             exp.isConstant = false;
8320
8321          if(exp.index.exp.expType)
8322          {
8323             Type source = exp.index.exp.expType;
8324             if(source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
8325                eClass_IsDerived(source._class.registered, containerClass) && 
8326                source._class.registered.templateArgs)
8327             {
8328                Class _class = source._class.registered;
8329                exp.expType = ProcessTypeString(_class.templateArgs[2].dataTypeString, false);
8330
8331                if(exp.index.index && exp.index.index->last)
8332                {
8333                   ((Expression)exp.index.index->last).destType = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
8334                }
8335             }
8336          }
8337
8338          for(e = exp.index.index->first; e; e = e.next)
8339          {
8340             if(!e.next && exp.index.exp.expType && exp.index.exp.expType.kind == arrayType && exp.index.exp.expType.enumClass)
8341             {
8342                if(e.destType) FreeType(e.destType);
8343                e.destType = MkClassType(exp.index.exp.expType.enumClass.string);
8344             }
8345             ProcessExpressionType(e);
8346             if(!e.next)
8347             {
8348                // Check if this type is int
8349             }
8350             if(!e.isConstant)
8351                exp.isConstant = false;
8352          }
8353
8354          if(!exp.expType)
8355             exp.expType = Dereference(exp.index.exp.expType);
8356          if(exp.expType)
8357             DeclareType(exp.expType, false, false);
8358          break;
8359       }
8360       case callExp:
8361       {
8362          Expression e;
8363          Type functionType;
8364          Type methodType = null;
8365          char name[1024];
8366          name[0] = '\0';
8367
8368          if(inCompiler)
8369          {
8370             PrintExpression(exp.call.exp,  name);
8371             if(exp.call.exp.expType && !exp.call.exp.expType.returnType)
8372             {
8373                //exp.call.exp.expType = null;
8374                PrintExpression(exp.call.exp,  name);
8375             }
8376          }
8377          if(exp.call.exp.type == identifierExp)
8378          {
8379             Expression idExp = exp.call.exp;
8380             Identifier id = idExp.identifier;
8381             if(!strcmp(id.string, "__ENDIAN_PAD"))
8382             {
8383                exp.expType = ProcessTypeString("int", true);
8384                if(exp.call.arguments && exp.call.arguments->first)
8385                   ProcessExpressionType(exp.call.arguments->first);
8386                break;
8387             }
8388             else if(!strcmp(id.string, "Max") ||
8389                !strcmp(id.string, "Min") ||
8390                !strcmp(id.string, "Sgn") ||
8391                !strcmp(id.string, "Abs"))
8392             {
8393                Expression a = null;
8394                Expression b = null;
8395                Expression tempExp1 = null, tempExp2 = null;
8396                if((!strcmp(id.string, "Max") ||
8397                   !strcmp(id.string, "Min")) && exp.call.arguments->count == 2)
8398                {
8399                   a = exp.call.arguments->first;
8400                   b = exp.call.arguments->last;
8401                   tempExp1 = a;
8402                   tempExp2 = b;
8403                }
8404                else if(exp.call.arguments->count == 1)
8405                {
8406                   a = exp.call.arguments->first;
8407                   tempExp1 = a;
8408                }
8409                
8410                if(a)
8411                {
8412                   exp.call.arguments->Clear();
8413                   idExp.identifier = null;
8414
8415                   FreeExpContents(exp);
8416
8417                   ProcessExpressionType(a);
8418                   if(b)
8419                      ProcessExpressionType(b);
8420
8421                   exp.type = bracketsExp;
8422                   exp.list = MkList();
8423
8424                   if(a.expType && (!b || b.expType))
8425                   {
8426                      if((!a.isConstant && a.type != identifierExp) || (b && !b.isConstant && b.type != identifierExp))
8427                      {
8428                         // Use the simpleStruct name/ids for now...
8429                         if(inCompiler)
8430                         {
8431                            OldList * specs = MkList();
8432                            OldList * decls = MkList();
8433                            Declaration decl;
8434                            char temp1[1024], temp2[1024];
8435
8436                            GetTypeSpecs(a.expType, specs);
8437
8438                            if(a && !a.isConstant && a.type != identifierExp)
8439                            {
8440                               sprintf(temp1, "__simpleStruct%d", curContext.simpleID++);
8441                               ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp1)), null));
8442                               tempExp1 = QMkExpId(temp1);
8443                               tempExp1.expType = a.expType;
8444                               if(a.expType)
8445                                  a.expType.refCount++;
8446                               ListAdd(exp.list, MkExpOp(CopyExpression(tempExp1), '=', a));
8447                            }
8448                            if(b && !b.isConstant && b.type != identifierExp)
8449                            {
8450                               sprintf(temp2, "__simpleStruct%d", curContext.simpleID++);
8451                               ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp2)), null));
8452                               tempExp2 = QMkExpId(temp2);
8453                               tempExp2.expType = b.expType;
8454                               if(b.expType)
8455                                  b.expType.refCount++;
8456                               ListAdd(exp.list, MkExpOp(CopyExpression(tempExp2), '=', b));
8457                            }                        
8458
8459                            decl = MkDeclaration(specs, decls);
8460                            if(!curCompound.compound.declarations)
8461                               curCompound.compound.declarations = MkList();
8462                            curCompound.compound.declarations->Insert(null, decl);
8463                         }
8464                      }
8465                   }
8466
8467                   if(!strcmp(id.string, "Max") || !strcmp(id.string, "Min"))
8468                   {
8469                      int op = (!strcmp(id.string, "Max")) ? '>' : '<';
8470                      ListAdd(exp.list, 
8471                         MkExpCondition(MkExpBrackets(MkListOne(
8472                            MkExpOp(CopyExpression(tempExp1), op, CopyExpression(tempExp2)))),
8473                            MkListOne(CopyExpression(tempExp1)), CopyExpression(tempExp2)));
8474                      exp.expType = a.expType;
8475                      if(a.expType)
8476                         a.expType.refCount++;
8477                   }
8478                   else if(!strcmp(id.string, "Abs"))
8479                   {
8480                      ListAdd(exp.list, 
8481                         MkExpCondition(MkExpBrackets(MkListOne(
8482                            MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8483                            MkListOne(MkExpOp(null, '-', CopyExpression(tempExp1))), CopyExpression(tempExp1)));
8484                      exp.expType = a.expType;
8485                      if(a.expType)
8486                         a.expType.refCount++;
8487                   }
8488                   else if(!strcmp(id.string, "Sgn"))
8489                   {
8490                      // ((!(a))?(0):(((a)<0)?(-1):(1)))
8491                      ListAdd(exp.list, 
8492                         MkExpCondition(MkExpBrackets(MkListOne(
8493                            MkExpOp(null, '!', CopyExpression(tempExp1)))), MkListOne(MkExpConstant("0")),
8494                               MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(
8495                                  MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8496                                  MkListOne(MkExpConstant("-1")), MkExpConstant("1"))))));
8497                      exp.expType = ProcessTypeString("int", false);
8498                   }
8499
8500                   FreeExpression(tempExp1);
8501                   if(tempExp2) FreeExpression(tempExp2);
8502
8503                   FreeIdentifier(id);
8504                   break;
8505                }
8506             }
8507          }
8508
8509          {
8510             Type dummy
8511             {
8512                count = 1;
8513                refCount = 1;
8514             };
8515             if(!exp.call.exp.destType)
8516             {
8517                exp.call.exp.destType = dummy;
8518                dummy.refCount++;
8519             }
8520             ProcessExpressionType(exp.call.exp);
8521             if(exp.call.exp.destType == dummy)
8522             {
8523                FreeType(dummy);
8524                exp.call.exp.destType = null;
8525             }
8526             FreeType(dummy);
8527          }
8528
8529          // Check argument types against parameter types
8530          functionType = exp.call.exp.expType;
8531
8532          if(functionType && functionType.kind == TypeKind::methodType)
8533          {
8534             methodType = functionType;
8535             functionType = methodType.method.dataType;
8536             
8537             //if(functionType.returnType && functionType.returnType.kind == thisClassType)
8538             // TOCHECK: Instead of doing this here could this be done per param?
8539             if(exp.call.exp.expType.usedClass)
8540             {
8541                char typeString[1024];
8542                typeString[0] = '\0';
8543                PrintType(functionType, typeString, true, true);
8544                if(strstr(typeString, "thisclass"))
8545                {
8546                   OldList * specs = MkList();
8547                   Declarator decl;
8548                   {
8549                      Context context = SetupTemplatesContext(exp.call.exp.expType.usedClass);
8550
8551                      decl = SpecDeclFromString(typeString, specs, null);
8552                      
8553                      // SET THIS TO FALSE WHEN PROCESSING THISCLASS OUTSIDE THE CLASS
8554                      if(thisClass != (exp.call.exp.expType.usedClass.templateClass ? exp.call.exp.expType.usedClass.templateClass :
8555                         exp.call.exp.expType.usedClass))
8556                         thisClassParams = false;
8557                      
8558                      ReplaceThisClassSpecifiers(specs, exp.call.exp.expType.usedClass);
8559                      {
8560                         Class backupThisClass = thisClass;
8561                         thisClass = exp.call.exp.expType.usedClass;
8562                         ProcessDeclarator(decl);
8563                         thisClass = backupThisClass;
8564                      }
8565
8566                      thisClassParams = true;
8567
8568                      functionType = ProcessType(specs, decl);
8569                      functionType.refCount = 0;
8570                      FinishTemplatesContext(context);
8571                   }
8572
8573                   FreeList(specs, FreeSpecifier);
8574                   FreeDeclarator(decl);
8575                 }
8576             }
8577          }
8578          if(functionType && functionType.kind == pointerType && functionType.type && functionType.type.kind == TypeKind::functionType)
8579          {
8580             Type type = functionType.type;
8581             if(!functionType.refCount)
8582             {
8583                functionType.type = null;
8584                FreeType(functionType);
8585             }
8586             //methodType = functionType;
8587             functionType = type;
8588          }
8589          if(functionType && functionType.kind != TypeKind::functionType)
8590          {
8591             Compiler_Error("called object %s is not a function\n", name);
8592          }
8593          else if(functionType)
8594          {
8595             bool emptyParams = false, noParams = false;
8596             Expression e = exp.call.arguments ? exp.call.arguments->first : null;
8597             Type type = functionType.params.first;
8598             Expression memberExp = (exp.call.exp.type == ExpressionType::memberExp) ? exp.call.exp : null;
8599             int extra = 0;
8600             Location oldyylloc = yylloc;
8601
8602             if(!type) emptyParams = true;
8603
8604             // WORKING ON THIS:
8605             if(functionType.extraParam && e)
8606             {
8607                e.destType = MkClassType(functionType.thisClass.string);
8608                e = e.next;
8609             }
8610
8611             // WHY WAS THIS COMMENTED OUT ? Broke DisplaySystem::FontExtent(this ? displaySystem : null, font, text, len, width, height);
8612             if(!functionType.staticMethod)
8613             {
8614                if(memberExp && memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.kind == subClassType && 
8615                   memberExp.member.exp.expType._class)
8616                {
8617                   type = MkClassType(memberExp.member.exp.expType._class.string);
8618                   if(e)
8619                   {
8620                      e.destType = type;
8621                      e = e.next;
8622                      type = functionType.params.first;
8623                   }
8624                   else
8625                      type.refCount = 0;
8626                }
8627                else if(!memberExp && (functionType.thisClass || (methodType && methodType.methodClass)))
8628                {
8629                   type = MkClassType(functionType.thisClass ? functionType.thisClass.string : (methodType ? methodType.methodClass.fullName : null));
8630                   if(e)
8631                   {
8632                      e.destType = type;
8633                      e = e.next;
8634                      type = functionType.params.first;
8635                   }
8636                   else
8637                      type.refCount = 0;
8638                   //extra = 1;
8639                }
8640             }
8641
8642             if(type && type.kind == voidType)
8643             {
8644                noParams = true;
8645                if(!type.refCount) FreeType(type);
8646                type = null;
8647             }
8648
8649             for( ; e; e = e.next)
8650             {
8651                if(!type && !emptyParams)
8652                {
8653                   yylloc = e.loc;
8654                   if(methodType && methodType.methodClass)
8655                      Compiler_Error("too many arguments for method %s::%s (%d given, expected %d)\n",
8656                         methodType.methodClass.fullName, methodType.method.name, exp.call.arguments->count,
8657                         noParams ? 0 : functionType.params.count);
8658                   else
8659                      Compiler_Error("too many arguments for function %s (%d given, expected %d)\n",
8660                         name /*exp.call.exp.identifier.string*/, exp.call.arguments->count,
8661                         noParams ? 0 : functionType.params.count);
8662                   break;
8663                }
8664
8665                if(methodType && type && type.kind == templateType && type.templateParameter.type == TemplateParameterType::type)
8666                {
8667                   Type templatedType = null;
8668                   Class _class = methodType.usedClass;
8669                   ClassTemplateParameter curParam = null;
8670                   int id = 0;
8671                   if(_class && _class.templateArgs /*&& _class.templateClass*/)
8672                   {
8673                      Class sClass;
8674                      for(sClass = _class; sClass; sClass = sClass.base)
8675                      {
8676                         if(sClass.templateClass) sClass = sClass.templateClass;
8677                         id = 0;
8678                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
8679                         {
8680                            if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
8681                            {
8682                               Class nextClass;
8683                               for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
8684                               {
8685                                  if(nextClass.templateClass) nextClass = nextClass.templateClass;
8686                                  id += nextClass.templateParams.count;
8687                               }
8688                               break;
8689                            }
8690                            id++;
8691                         }
8692                         if(curParam) break;
8693                      }
8694                   }
8695                   if(curParam && _class.templateArgs[id].dataTypeString)
8696                   {
8697                      ClassTemplateArgument arg = _class.templateArgs[id];
8698                      {
8699                         Context context = SetupTemplatesContext(_class);
8700                      
8701                         /*if(!arg.dataType)
8702                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
8703                         templatedType = ProcessTypeString(arg.dataTypeString, false);
8704                         FinishTemplatesContext(context);
8705                      }
8706                      e.destType = templatedType;
8707                      if(templatedType)
8708                      {
8709                         templatedType.passAsTemplate = true;
8710                         // templatedType.refCount++;
8711                      }
8712                   }
8713                   else
8714                   {
8715                      e.destType = type;
8716                      if(type) type.refCount++;
8717                   }
8718                }
8719                else
8720                {
8721                   e.destType = type;
8722                   if(type) type.refCount++;
8723                }
8724                // Don't reach the end for the ellipsis
8725                if(type && type.kind != ellipsisType)
8726                {
8727                   Type next = type.next;
8728                   if(!type.refCount) FreeType(type);
8729                   type = next;
8730                }
8731             }
8732
8733             if(type && type.kind != ellipsisType)
8734             {
8735                if(methodType && methodType.methodClass)
8736                   Compiler_Warning("not enough arguments for method %s::%s (%d given, expected %d)\n",
8737                      methodType.methodClass.fullName, methodType.method.name, exp.call.arguments ? exp.call.arguments->count : 0,
8738                      functionType.params.count + extra);
8739                else
8740                   Compiler_Warning("not enough arguments for function %s (%d given, expected %d)\n",
8741                      name /*exp.call.exp.identifier.string*/, exp.call.arguments ? exp.call.arguments->count : 0,
8742                      functionType.params.count + extra);
8743             }
8744             yylloc = oldyylloc;
8745             if(type && !type.refCount) FreeType(type);
8746          }
8747          else
8748          {
8749             functionType = Type
8750             {
8751                refCount = 0;
8752                kind = TypeKind::functionType;
8753             };
8754
8755             if(exp.call.exp.type == identifierExp)
8756             {
8757                char * string = exp.call.exp.identifier.string;
8758                if(inCompiler)
8759                {
8760                   Symbol symbol;
8761                   Location oldyylloc = yylloc;
8762
8763                   yylloc = exp.call.exp.identifier.loc;
8764                   if(strstr(string, "__builtin_") == string);
8765                   else
8766                      Compiler_Warning("%s undefined; assuming extern returning int\n", string);
8767                   symbol = Symbol { string = CopyString(string), type = ProcessTypeString("int()", true) };
8768                   globalContext.symbols.Add((BTNode)symbol);
8769
8770                   yylloc = oldyylloc;
8771                }
8772             }
8773             else if(exp.call.exp.type == memberExp)
8774             {
8775                /*Compiler_Warning("%s undefined; assuming returning int\n",
8776                   exp.call.exp.member.member.string);*/
8777             }
8778             else
8779                Compiler_Warning("callable object undefined; extern assuming returning int\n");
8780
8781             if(!functionType.returnType)
8782             {
8783                functionType.returnType = Type
8784                {
8785                   refCount = 1;
8786                   kind = intType;
8787                };
8788             }
8789          }
8790          if(functionType && functionType.kind == TypeKind::functionType)
8791          {
8792             exp.expType = functionType.returnType;
8793
8794             if(functionType.returnType)
8795                functionType.returnType.refCount++;
8796
8797             if(!functionType.refCount)
8798                FreeType(functionType);
8799          }
8800
8801          if(exp.call.arguments)
8802          {
8803             for(e = exp.call.arguments->first; e; e = e.next)
8804             {
8805                Type destType = e.destType;
8806                ProcessExpressionType(e);
8807             }
8808          }
8809          break;
8810       }
8811       case memberExp:
8812       {
8813          Type type;
8814          Location oldyylloc = yylloc;
8815          bool thisPtr = (exp.member.exp && exp.member.exp.type == identifierExp && !strcmp(exp.member.exp.identifier.string, "this"));
8816          exp.thisPtr = thisPtr;
8817
8818          // DOING THIS LATER NOW...
8819          if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
8820          {
8821             exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
8822             /* TODO: Name Space Fix ups
8823             if(!exp.member.member.classSym)
8824                exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.fullName);
8825             */
8826          }
8827
8828          ProcessExpressionType(exp.member.exp);
8829          if(exp.member.exp.expType && exp.member.exp.expType.kind == classType && exp.member.exp.expType._class && 
8830             exp.member.exp.expType._class.registered && exp.member.exp.expType._class.registered.type == normalClass)
8831          {
8832             exp.isConstant = false;
8833          }
8834          else
8835             exp.isConstant = exp.member.exp.isConstant;
8836          type = exp.member.exp.expType;
8837
8838          yylloc = exp.loc;
8839
8840          if(type && (type.kind == templateType))
8841          {
8842             Class _class = thisClass ? thisClass : currentClass;
8843             ClassTemplateParameter param = null;
8844             if(_class)
8845             {
8846                for(param = _class.templateParams.first; param; param = param.next)
8847                {
8848                   if(param.type == identifier && !strcmp(param.name, exp.member.member.string))
8849                      break;
8850                }
8851             }
8852             if(param && param.defaultArg.member)
8853             {
8854                Expression argExp = GetTemplateArgExpByName(param.name, thisClass, TemplateParameterType::identifier);
8855                if(argExp)
8856                {
8857                   Expression expMember = exp.member.exp;
8858                   Declarator decl;
8859                   OldList * specs = MkList();
8860                   char thisClassTypeString[1024];
8861
8862                   FreeIdentifier(exp.member.member);
8863
8864                   ProcessExpressionType(argExp);
8865
8866                   {
8867                      char * colon = strstr(param.defaultArg.memberString, "::");
8868                      if(colon)
8869                      {
8870                         char className[1024];
8871                         Class sClass;
8872
8873                         memcpy(thisClassTypeString, param.defaultArg.memberString, colon - param.defaultArg.memberString);
8874                         thisClassTypeString[colon - param.defaultArg.memberString] = '\0';
8875                      }
8876                      else
8877                         strcpy(thisClassTypeString, _class.fullName);
8878                   }
8879
8880                   decl = SpecDeclFromString(param.defaultArg.member.dataTypeString, specs, null);
8881
8882                   exp.expType = ProcessType(specs, decl);
8883                   if(exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.templateClass)
8884                   {
8885                      Class expClass = exp.expType._class.registered;
8886                      Class cClass = null;
8887                      int c;
8888                      int paramCount = 0;
8889                      int lastParam = -1;
8890                      
8891                      char templateString[1024];
8892                      ClassTemplateParameter param;
8893                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
8894                      for(cClass = expClass; cClass; cClass = cClass.base)
8895                      {
8896                         int p = 0;
8897                         for(param = cClass.templateParams.first; param; param = param.next)
8898                         {
8899                            int id = p;
8900                            Class sClass;
8901                            ClassTemplateArgument arg;
8902                            for(sClass = cClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
8903                            arg = expClass.templateArgs[id];
8904
8905                            for(sClass = _class /*expClass*/; sClass; sClass = sClass.base)
8906                            {
8907                               ClassTemplateParameter cParam;
8908                               //int p = numParams - sClass.templateParams.count;
8909                               int p = 0;
8910                               Class nextClass;
8911                               for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
8912                               
8913                               for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
8914                               {
8915                                  if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
8916                                  {
8917                                     if(_class.templateArgs && arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
8918                                     {
8919                                        arg.dataTypeString = _class.templateArgs[p].dataTypeString;
8920                                        arg.dataTypeClass = _class.templateArgs[p].dataTypeClass;
8921                                        break;
8922                                     }
8923                                  }
8924                               }
8925                            }
8926
8927                            {
8928                               char argument[256];
8929                               argument[0] = '\0';
8930                               /*if(arg.name)
8931                               {
8932                                  strcat(argument, arg.name.string);
8933                                  strcat(argument, " = ");
8934                               }*/
8935                               switch(param.type)
8936                               {
8937                                  case expression:
8938                                  {
8939                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
8940                                     char expString[1024];
8941                                     OldList * specs = MkList();
8942                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
8943                                     Expression exp;
8944                                     char * string = PrintHexUInt64(arg.expression.ui64);
8945                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
8946
8947                                     ProcessExpressionType(exp);
8948                                     ComputeExpression(exp);
8949                                     expString[0] = '\0';
8950                                     PrintExpression(exp, expString);
8951                                     strcat(argument, expString);
8952                                     // delete exp;
8953                                     FreeExpression(exp);
8954                                     break;
8955                                  }
8956                                  case identifier:
8957                                  {
8958                                     strcat(argument, arg.member.name);
8959                                     break;
8960                                  }
8961                                  case TemplateParameterType::type:
8962                                  {
8963                                     if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
8964                                     {
8965                                        if(!strcmp(arg.dataTypeString, "thisclass"))
8966                                           strcat(argument, thisClassTypeString);
8967                                        else
8968                                           strcat(argument, arg.dataTypeString);
8969                                     }
8970                                     break;
8971                                  }
8972                               }
8973                               if(argument[0])
8974                               {
8975                                  if(paramCount) strcat(templateString, ", ");
8976                                  if(lastParam != p - 1)
8977                                  {
8978                                     strcat(templateString, param.name);
8979                                     strcat(templateString, " = ");
8980                                  }
8981                                  strcat(templateString, argument);
8982                                  paramCount++;
8983                                  lastParam = p;
8984                               }
8985                               p++;
8986                            }               
8987                         }
8988                      }
8989                      {
8990                         int len = strlen(templateString);
8991                         if(templateString[len-1] == '>') templateString[len++] = ' ';
8992                         templateString[len++] = '>';
8993                         templateString[len++] = '\0';
8994                      }
8995                      {
8996                         Context context = SetupTemplatesContext(_class);
8997                         FreeType(exp.expType);
8998                         exp.expType = ProcessTypeString(templateString, false);
8999                         FinishTemplatesContext(context);
9000                      }                     
9001                   }
9002
9003                   // *([expType] *)(((byte *)[exp.member.exp]) + [argExp].member.offset)
9004                   exp.type = bracketsExp;
9005                   exp.list = MkListOne(MkExpOp(null, '*',
9006                   /*opExp;
9007                   exp.op.op = '*';
9008                   exp.op.exp1 = null;
9009                   exp.op.exp2 = */
9010                   MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpBrackets(MkListOne(MkExpOp(
9011                      MkExpBrackets(MkListOne(
9012                         MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), expMember))),
9013                            '+',  
9014                            MkExpOp(MkExpMember(MkExpMember(argExp, MkIdentifier("member")), MkIdentifier("offset")), 
9015                            '+',
9016                            MkExpMember(MkExpMember(MkExpMember(CopyExpression(argExp), MkIdentifier("member")), MkIdentifier("_class")), MkIdentifier("offset")))))))
9017                            
9018                            ));
9019                }
9020             }
9021             else if(type.templateParameter && type.templateParameter.type == TemplateParameterType::type && 
9022                (type.templateParameter.dataType || type.templateParameter.dataTypeString))
9023             {
9024                type = ProcessTemplateParameterType(type.templateParameter);
9025             }
9026          }
9027
9028          if(type && (type.kind == templateType));
9029          else if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9030          {
9031             Identifier id = exp.member.member;
9032             TypeKind typeKind = type.kind;
9033             Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9034             if(typeKind == subClassType && exp.member.exp.type == classExp)
9035             {
9036                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
9037                typeKind = classType;
9038             }
9039
9040             if(id && (typeKind == intType || typeKind == enumType))
9041                _class = eSystem_FindClass(privateModule, "int");
9042
9043             if(_class && id)
9044             {
9045                /*bool thisPtr = 
9046                   (exp.member.exp.type == identifierExp && 
9047                   !strcmp(exp.member.exp.identifier.string, "this"));*/
9048                Property prop = null;
9049                Method method = null;
9050                DataMember member = null;
9051                Property revConvert = null;
9052                ClassProperty classProp = null;
9053
9054                if(id && id._class && id._class.name && !strcmp(id._class.name, "property"))
9055                   exp.member.memberType = propertyMember;
9056
9057                if(id && id._class && type._class && !eClass_IsDerived(type._class.registered, _class))
9058                   Compiler_Error("invalid class specifier %s for object of class %s\n", _class.fullName, type._class.string);
9059
9060                if(typeKind != subClassType)
9061                {
9062                   // Prioritize data members over properties for "this"
9063                   if((exp.member.memberType == unresolvedMember && thisPtr) || exp.member.memberType == dataMember)
9064                   {
9065                      member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9066                      if(member && member._class != (_class.templateClass ? _class.templateClass : _class) && exp.member.memberType != dataMember)
9067                      {
9068                         prop = eClass_FindProperty(_class, id.string, privateModule);
9069                         if(prop)
9070                            member = null;
9071                      }
9072                      if(!member && !prop)
9073                         prop = eClass_FindProperty(_class, id.string, privateModule);
9074                      if((member && member._class == (_class.templateClass ? _class.templateClass : _class)) ||
9075                         (prop && prop._class == (_class.templateClass ? _class.templateClass : _class)))
9076                         exp.member.thisPtr = true;
9077                   }
9078                   // Prioritize properties over data members otherwise
9079                   else
9080                   {
9081                      // First look for Public Members (Unless class specifier is provided, which skips public priority)
9082                      if(!id.classSym)
9083                      {
9084                         prop = eClass_FindProperty(_class, id.string, null);
9085                         if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9086                            member = eClass_FindDataMember(_class, id.string, null, null, null);
9087                      }
9088
9089                      if(!prop && !member)
9090                      {
9091                         method = eClass_FindMethod(_class, id.string, null);
9092                         if(!method)
9093                         {
9094                            prop = eClass_FindProperty(_class, id.string, privateModule);
9095                            if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9096                               member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9097                         }
9098                      }
9099
9100                      if(member && prop)
9101                      {
9102                         if(member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class))
9103                            prop = null;
9104                         else
9105                            member = null;
9106                      }
9107                   }
9108                }
9109                if(!prop && !member)
9110                   method = eClass_FindMethod(_class, id.string, privateModule);
9111                if(!prop && !member && !method)
9112                {
9113                   if(typeKind == subClassType)
9114                   {
9115                      classProp = eClass_FindClassProperty(type._class.registered, exp.member.member.string);
9116                      if(classProp)
9117                      {
9118                         exp.member.memberType = classPropertyMember;
9119                         exp.expType = ProcessTypeString(classProp.dataTypeString, false);
9120                      }
9121                      else
9122                      {
9123                         // Assume this is a class_data member
9124                         char structName[1024];
9125                         Identifier id = exp.member.member;
9126                         Expression classExp = exp.member.exp;
9127                         type.refCount++;
9128
9129                         FreeType(classExp.expType);
9130                         classExp.expType = ProcessTypeString("ecere::com::Class", false);
9131                      
9132                         strcpy(structName, "__ecereClassData_");
9133                         FullClassNameCat(structName, type._class.string, false);
9134                         exp.type = pointerExp;
9135                         exp.member.member = id;
9136
9137                         exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9138                            MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), 
9139                               MkExpBrackets(MkListOne(MkExpOp(
9140                                  MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)), 
9141                                     MkExpMember(classExp, MkIdentifier("data"))), '+',
9142                                        MkExpMember(MkExpClass(MkListOne(MkSpecifierName(type._class.string)), null), MkIdentifier("offsetClass")))))
9143                                  )));
9144
9145                         FreeType(type);
9146
9147                         ProcessExpressionType(exp);
9148                         return;
9149                      }
9150                   }
9151                   else
9152                   {
9153                      // Check for reverse conversion
9154                      // (Convert in an instantiation later, so that we can use
9155                      //  deep properties system)
9156                      Symbol classSym = FindClass(id.string);
9157                      if(classSym)
9158                      {
9159                         Class convertClass = classSym.registered;
9160                         if(convertClass)
9161                            revConvert = eClass_FindProperty(convertClass, _class.fullName, privateModule);
9162                      }
9163                   }
9164                }
9165       
9166                if(prop)
9167                {
9168                   exp.member.memberType = propertyMember;
9169                   if(!prop.dataType)
9170                      ProcessPropertyType(prop);
9171                   exp.expType = prop.dataType;                     
9172                   if(prop.dataType) prop.dataType.refCount++;
9173                }
9174                else if(member)
9175                {
9176                   if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9177                   {
9178                      FreeExpContents(exp);
9179                      exp.type = identifierExp;
9180                      exp.identifier = MkIdentifier("class");
9181                      ProcessExpressionType(exp);
9182                      return;
9183                   }
9184
9185                   exp.member.memberType = dataMember;
9186                   DeclareStruct(_class.fullName, false);
9187                   if(!member.dataType)
9188                   {
9189                      Context context = SetupTemplatesContext(_class);
9190                      member.dataType = ProcessTypeString(member.dataTypeString, false);
9191                      FinishTemplatesContext(context);
9192                   }
9193                   exp.expType = member.dataType;
9194                   if(member.dataType) member.dataType.refCount++;
9195                }
9196                else if(revConvert)
9197                {
9198                   exp.member.memberType = reverseConversionMember;
9199                   exp.expType = MkClassType(revConvert._class.fullName);
9200                }
9201                else if(method)
9202                {
9203                   if(inCompiler)
9204                   {
9205                      /*if(id._class)
9206                      {
9207                         exp.type = identifierExp;
9208                         exp.identifier = exp.member.member;
9209                      }
9210                      else*/
9211                         exp.member.memberType = methodMember;
9212                   }
9213                   if(!method.dataType)
9214                      ProcessMethodType(method);
9215                   exp.expType = Type
9216                   {
9217                      refCount = 1;
9218                      kind = methodType;
9219                      method = method;
9220                   };
9221
9222                   // Tricky spot here... To use instance versus class virtual table
9223                   // Put it back to what it was... What did we break?
9224
9225                   // Had to put it back for overriding Main of Thread global instance
9226
9227                   //exp.expType.methodClass = _class;
9228                   exp.expType.methodClass = (id && id._class) ? _class : null;
9229
9230                   // Need the actual class used for templated classes
9231                   exp.expType.usedClass = _class;
9232                }
9233                else if(!classProp)
9234                {
9235                   if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9236                   {
9237                      FreeExpContents(exp);
9238                      exp.type = identifierExp;
9239                      exp.identifier = MkIdentifier("class");
9240                      ProcessExpressionType(exp);
9241                      return;
9242                   }
9243                   yylloc = exp.member.member.loc;
9244                   Compiler_Error("couldn't find member %s in class %s\n", id.string, _class.fullName);
9245                   if(inCompiler)
9246                      eClass_AddDataMember(_class, id.string, "int", 0, 0, publicAccess);
9247                }
9248
9249                if(_class && /*(_class.templateClass || _class.templateArgs) && */exp.expType)
9250                {
9251                   Class tClass;
9252
9253                   tClass = _class;
9254                   while(tClass && !tClass.templateClass) tClass = tClass.base;
9255
9256                   if(tClass && exp.expType.kind == templateType && exp.expType.templateParameter.type == TemplateParameterType::type)
9257                   {
9258                      int id = 0;
9259                      ClassTemplateParameter curParam;
9260                      Class sClass;
9261
9262                      for(sClass = tClass; sClass; sClass = sClass.base)
9263                      {
9264                         id = 0;
9265                         if(sClass.templateClass) sClass = sClass.templateClass;
9266                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9267                         {
9268                            if(curParam.type == TemplateParameterType::type && !strcmp(exp.expType.templateParameter.identifier.string, curParam.name))
9269                            {
9270                               for(sClass = sClass.base; sClass; sClass = sClass.base)
9271                                  id += sClass.templateParams.count;
9272                               break;
9273                            }
9274                            id++;
9275                         }
9276                         if(curParam) break;
9277                      }
9278
9279                      if(curParam && tClass.templateArgs[id].dataTypeString)
9280                      {
9281                         ClassTemplateArgument arg = tClass.templateArgs[id];
9282                         Context context = SetupTemplatesContext(tClass);
9283                         /*if(!arg.dataType)
9284                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9285                         FreeType(exp.expType);
9286                         exp.expType = ProcessTypeString(arg.dataTypeString, false);
9287                         if(exp.expType)
9288                         {
9289                            if(exp.expType.kind == thisClassType)
9290                            {
9291                               FreeType(exp.expType);
9292                               exp.expType = ReplaceThisClassType(_class);
9293                            }
9294
9295                            if(tClass.templateClass)
9296                               exp.expType.passAsTemplate = true;
9297                            //exp.expType.refCount++;
9298                            if(!exp.destType)
9299                            {
9300                               exp.destType = ProcessTypeString(arg.dataTypeString, false);
9301                               //exp.destType.refCount++;
9302
9303                               if(exp.destType.kind == thisClassType)
9304                               {
9305                                  FreeType(exp.destType);
9306                                  exp.destType = ReplaceThisClassType(_class);
9307                               }
9308                            }
9309                         }
9310                         FinishTemplatesContext(context);
9311                      }
9312                   }
9313                   // TODO: MORE GENERIC SUPPORT FOR DEEPER TYPES
9314                   else if(tClass && exp.expType.kind == pointerType && exp.expType.type && exp.expType.type.kind == templateType && exp.expType.type.templateParameter.type == TemplateParameterType::type)
9315                   {
9316                      int id = 0;
9317                      ClassTemplateParameter curParam;
9318                      Class sClass;
9319
9320                      for(sClass = tClass; sClass; sClass = sClass.base)
9321                      {
9322                         id = 0;
9323                         if(sClass.templateClass) sClass = sClass.templateClass;
9324                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9325                         {
9326                            if(curParam.type == TemplateParameterType::type && 
9327                               !strcmp(exp.expType.type.templateParameter.identifier.string, curParam.name))
9328                            {
9329                               for(sClass = sClass.base; sClass; sClass = sClass.base)
9330                                  id += sClass.templateParams.count;
9331                               break;
9332                            }
9333                            id++;
9334                         }
9335                         if(curParam) break;
9336                      }
9337
9338                      if(curParam)
9339                      {
9340                         ClassTemplateArgument arg = tClass.templateArgs[id];
9341                         Context context = SetupTemplatesContext(tClass);
9342                         Type basicType;
9343                         /*if(!arg.dataType)
9344                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9345                         
9346                         basicType = ProcessTypeString(arg.dataTypeString, false);
9347                         if(basicType)
9348                         {
9349                            if(basicType.kind == thisClassType)
9350                            {
9351                               FreeType(basicType);
9352                               basicType = ReplaceThisClassType(_class);
9353                            }
9354
9355                            /*    DO WE REALLY WANT THIS HERE? IT SEEMS TO BE ONLY USED WITH Array::array which was causing bug 135
9356                            if(tClass.templateClass)
9357                               basicType.passAsTemplate = true;
9358                            */
9359                            
9360                            FreeType(exp.expType);
9361
9362                            exp.expType = Type { refCount = 1, kind = pointerType, type = basicType };
9363                            //exp.expType.refCount++;
9364                            if(!exp.destType)
9365                            {
9366                               exp.destType = exp.expType;
9367                               exp.destType.refCount++;
9368                            }
9369
9370                            {
9371                               Expression newExp { };
9372                               OldList * specs = MkList();
9373                               Declarator decl;
9374                               decl = SpecDeclFromString(arg.dataTypeString, specs, null);
9375                               *newExp = *exp;
9376                               if(exp.destType) exp.destType.refCount++;
9377                               if(exp.expType)  exp.expType.refCount++;
9378                               exp.type = castExp;
9379                               exp.cast.typeName = MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl));
9380                               exp.cast.exp = newExp;
9381                               //FreeType(exp.expType);
9382                               //exp.expType = null;
9383                               //ProcessExpressionType(sourceExp);
9384                            }
9385                         }
9386                         FinishTemplatesContext(context);
9387                      }
9388                   }
9389                   else if(tClass && exp.expType.kind == classType && exp.expType._class && strchr(exp.expType._class.string, '<'))
9390                   {
9391                      Class expClass = exp.expType._class.registered;
9392                      if(expClass)
9393                      {
9394                         Class cClass = null;
9395                         int c;
9396                         int p = 0;
9397                         int paramCount = 0;
9398                         int lastParam = -1;
9399                         char templateString[1024];
9400                         ClassTemplateParameter param;
9401                         sprintf(templateString, "%s<", expClass.templateClass.fullName);
9402                         while(cClass != expClass)
9403                         {
9404                            Class sClass;
9405                            for(sClass = expClass; sClass && sClass.base != cClass; sClass = sClass.base);
9406                            cClass = sClass;
9407
9408                            for(param = cClass.templateParams.first; param; param = param.next)
9409                            {
9410                               Class cClassCur = null;
9411                               int c;
9412                               int cp = 0;
9413                               ClassTemplateParameter paramCur = null;
9414                               ClassTemplateArgument arg;
9415                               while(cClassCur != tClass && !paramCur)
9416                               {
9417                                  Class sClassCur;
9418                                  for(sClassCur = tClass; sClassCur && sClassCur.base != cClassCur; sClassCur = sClassCur.base);
9419                                  cClassCur = sClassCur;
9420
9421                                  for(paramCur = cClassCur.templateParams.first; paramCur; paramCur = paramCur.next)
9422                                  {
9423                                     if(!strcmp(paramCur.name, param.name))
9424                                     {
9425                                        
9426                                        break;
9427                                     }
9428                                     cp++;
9429                                  }
9430                               }
9431                               if(paramCur && paramCur.type == TemplateParameterType::type)
9432                                  arg = tClass.templateArgs[cp];
9433                               else
9434                                  arg = expClass.templateArgs[p];
9435
9436                               {
9437                                  char argument[256];
9438                                  argument[0] = '\0';
9439                                  /*if(arg.name)
9440                                  {
9441                                     strcat(argument, arg.name.string);
9442                                     strcat(argument, " = ");
9443                                  }*/
9444                                  switch(param.type)
9445                                  {
9446                                     case expression:
9447                                     {
9448                                        // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
9449                                        char expString[1024];
9450                                        OldList * specs = MkList();
9451                                        Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
9452                                        Expression exp;
9453                                        char * string = PrintHexUInt64(arg.expression.ui64);
9454                                        exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
9455
9456                                        ProcessExpressionType(exp);
9457                                        ComputeExpression(exp);
9458                                        expString[0] = '\0';
9459                                        PrintExpression(exp, expString);
9460                                        strcat(argument, expString);
9461                                        // delete exp;
9462                                        FreeExpression(exp);
9463                                        break;
9464                                     }
9465                                     case identifier:
9466                                     {
9467                                        strcat(argument, arg.member.name);
9468                                        break;
9469                                     }
9470                                     case TemplateParameterType::type:
9471                                     {
9472                                        if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9473                                           strcat(argument, arg.dataTypeString);
9474                                        break;
9475                                     }
9476                                  }
9477                                  if(argument[0])
9478                                  {
9479                                     if(paramCount) strcat(templateString, ", ");
9480                                     if(lastParam != p - 1)
9481                                     {
9482                                        strcat(templateString, param.name);
9483                                        strcat(templateString, " = ");
9484                                     }                                       
9485                                     strcat(templateString, argument);
9486                                     paramCount++;
9487                                     lastParam = p;
9488                                  }
9489                               }
9490                               p++;
9491                            }
9492                         }
9493                         {
9494                            int len = strlen(templateString);
9495                            if(templateString[len-1] == '>') templateString[len++] = ' ';
9496                            templateString[len++] = '>';
9497                            templateString[len++] = '\0';
9498                         }
9499
9500                         FreeType(exp.expType);
9501                         {
9502                            Context context = SetupTemplatesContext(tClass);
9503                            exp.expType = ProcessTypeString(templateString, false);
9504                            FinishTemplatesContext(context);
9505                         }
9506                      }
9507                   }
9508                }
9509             }
9510             else
9511                Compiler_Error("undefined class %s\n", (id && (!id._class || id._class.name))? (id.classSym ? id.classSym.string : (type._class ? type._class.string : null)) : "(null)");
9512          }
9513          else if(type && (type.kind == structType || type.kind == unionType))
9514          {
9515             Type memberType = exp.member.member ? FindMember(type, exp.member.member.string) : null;
9516             if(memberType)
9517             {
9518                exp.expType = memberType;
9519                if(memberType)
9520                   memberType.refCount++;
9521             }
9522          }
9523          else 
9524          {
9525             char expString[10240];
9526             expString[0] = '\0';
9527             if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
9528             Compiler_Error("member operator on non-structure type expression %s\n", expString);
9529          }
9530
9531          if(exp.expType && exp.expType.kind == thisClassType && (!exp.destType || exp.destType.kind != thisClassType))
9532          {
9533             if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9534             {
9535                Identifier id = exp.member.member;
9536                Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9537                if(_class)
9538                {
9539                   FreeType(exp.expType);
9540                   exp.expType = ReplaceThisClassType(_class);
9541                }
9542             }
9543          }         
9544          yylloc = oldyylloc;
9545          break;
9546       }
9547       // Convert x->y into (*x).y
9548       case pointerExp:
9549       {
9550          Type destType = exp.destType;
9551
9552          // DOING THIS LATER NOW...
9553          if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
9554          {
9555             exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
9556             /* TODO: Name Space Fix ups
9557             if(!exp.member.member.classSym)
9558                exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.name);
9559             */
9560          }
9561
9562          exp.member.exp = MkExpBrackets(MkListOne(MkExpOp(null, '*', exp.member.exp)));
9563          exp.type = memberExp;
9564          if(destType)
9565             destType.count++;
9566          ProcessExpressionType(exp);
9567          if(destType)
9568             destType.count--;
9569          break;
9570       }
9571       case classSizeExp:
9572       {
9573          //ComputeExpression(exp);
9574
9575          Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
9576          if(classSym && classSym.registered)
9577          {
9578             if(classSym.registered.type == noHeadClass)
9579             {
9580                char name[1024];
9581                name[0] = '\0';
9582                DeclareStruct(classSym.string, false);
9583                FreeSpecifier(exp._class);
9584                exp.type = typeSizeExp;
9585                FullClassNameCat(name, classSym.string, false);
9586                exp.typeName = MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null);
9587             }
9588             else
9589             {
9590                if(classSym.registered.fixed)
9591                {
9592                   FreeSpecifier(exp._class);
9593                   exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
9594                   exp.type = constantExp;
9595                }
9596                else
9597                {
9598                   char className[1024];
9599                   strcpy(className, "__ecereClass_");
9600                   FullClassNameCat(className, classSym.string, true);
9601                   MangleClassName(className);
9602
9603                   DeclareClass(classSym, className);
9604
9605                   FreeExpContents(exp);
9606                   exp.type = pointerExp;
9607                   exp.member.exp = MkExpIdentifier(MkIdentifier(className));
9608                   exp.member.member = MkIdentifier("structSize");
9609                }
9610             }
9611          }
9612
9613          exp.expType = Type
9614          {
9615             refCount = 1;
9616             kind = intType;
9617          };
9618          // exp.isConstant = true;
9619          break;
9620       }
9621       case typeSizeExp:
9622       {
9623          Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
9624
9625          exp.expType = Type
9626          {
9627             refCount = 1;
9628             kind = intType;
9629          };
9630          exp.isConstant = true;
9631
9632          DeclareType(type, false, false);
9633          FreeType(type);
9634          break;
9635       }
9636       case castExp:
9637       {
9638          Type type = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
9639          type.count = 1;
9640          FreeType(exp.cast.exp.destType);
9641          exp.cast.exp.destType = type;
9642          type.refCount++;
9643          ProcessExpressionType(exp.cast.exp);
9644          type.count = 0;
9645          exp.expType = type;
9646          //type.refCount++;
9647          
9648          // if(!NeedCast(exp.cast.exp.expType, exp.cast.exp.destType))
9649          if(!exp.cast.exp.needCast && !NeedCast(exp.cast.exp.expType, type))
9650          {
9651             void * prev = exp.prev, * next = exp.next;
9652             Type expType = exp.cast.exp.destType;
9653             Expression castExp = exp.cast.exp;
9654             Type destType = exp.destType;
9655
9656             if(expType) expType.refCount++;
9657
9658             //FreeType(exp.destType);
9659             FreeType(exp.expType);
9660             FreeTypeName(exp.cast.typeName);
9661             
9662             *exp = *castExp;
9663             FreeType(exp.expType);
9664             FreeType(exp.destType);
9665
9666             exp.expType = expType;
9667             exp.destType = destType;
9668
9669             delete castExp;
9670
9671             exp.prev = prev;
9672             exp.next = next;
9673
9674          }
9675          else
9676          {
9677             exp.isConstant = exp.cast.exp.isConstant;
9678          }
9679          //FreeType(type);
9680          break;
9681       }
9682       case extensionInitializerExp:
9683       {
9684          Type type = ProcessType(exp.initializer.typeName.qualifiers, exp.initializer.typeName.declarator);
9685          type.refCount++;
9686          // ProcessInitializer(exp.initializer.initializer, type);
9687          exp.expType = type;
9688          break;
9689       }
9690       case vaArgExp:
9691       {
9692          Type type = ProcessType(exp.vaArg.typeName.qualifiers, exp.vaArg.typeName.declarator);
9693          ProcessExpressionType(exp.vaArg.exp);
9694          type.refCount++;
9695          exp.expType = type;
9696          break;
9697       }
9698       case conditionExp:
9699       {
9700          Expression e;
9701          exp.isConstant = true;
9702
9703          FreeType(exp.cond.cond.destType);
9704          exp.cond.cond.destType = MkClassType("bool");
9705          exp.cond.cond.destType.truth = true;
9706          ProcessExpressionType(exp.cond.cond);
9707          if(!exp.cond.cond.isConstant)
9708             exp.isConstant = false;
9709          for(e = exp.cond.exp->first; e; e = e.next)
9710          {
9711             if(!e.next)
9712             {
9713                FreeType(e.destType);
9714                e.destType = exp.destType;
9715                if(e.destType) e.destType.refCount++;
9716             }
9717             ProcessExpressionType(e);
9718             if(!e.next)
9719             {
9720                exp.expType = e.expType;
9721                if(e.expType) e.expType.refCount++;
9722             }
9723             if(!e.isConstant)
9724                exp.isConstant = false;
9725          }
9726
9727          FreeType(exp.cond.elseExp.destType);
9728          // Added this check if we failed to find an expType
9729          // exp.cond.elseExp.destType = exp.expType ? exp.expType : exp.destType;
9730
9731          // Reversed it...
9732          exp.cond.elseExp.destType = exp.destType ? exp.destType : exp.expType;
9733
9734          if(exp.cond.elseExp.destType)
9735             exp.cond.elseExp.destType.refCount++;
9736          ProcessExpressionType(exp.cond.elseExp);
9737
9738          // FIXED THIS: Was done before calling process on elseExp
9739          if(!exp.cond.elseExp.isConstant)
9740             exp.isConstant = false;
9741          break;
9742       }
9743       case extensionCompoundExp:
9744       {
9745          if(exp.compound && exp.compound.compound.statements && exp.compound.compound.statements->last)
9746          {
9747             Statement last = exp.compound.compound.statements->last;
9748             if(last.type == expressionStmt && last.expressions && last.expressions->last)
9749             {
9750                ((Expression)last.expressions->last).destType = exp.destType;
9751                if(exp.destType)
9752                   exp.destType.refCount++;
9753             }
9754             ProcessStatement(exp.compound);
9755             exp.expType = ((Expression)last.expressions->last).expType;
9756             if(((Expression)last.expressions->last).expType)
9757                exp.expType.refCount++;
9758          }
9759          break;
9760       }
9761       case classExp:
9762       {
9763          Specifier spec = exp._classExp.specifiers->first;
9764          if(spec && spec.type == nameSpecifier)
9765          {
9766             exp.expType = MkClassType(spec.name);
9767             exp.expType.kind = subClassType;
9768             exp.byReference = true;
9769          }
9770          else
9771          {
9772             exp.expType = MkClassType("ecere::com::Class");
9773             exp.byReference = true;
9774          }
9775          break;
9776       }
9777       case classDataExp:
9778       {
9779          Class _class = thisClass ? thisClass : currentClass;
9780          if(_class)
9781          {
9782             Identifier id = exp.classData.id;
9783             char structName[1024];
9784             Expression classExp;
9785             strcpy(structName, "__ecereClassData_");
9786             FullClassNameCat(structName, _class.fullName, false);
9787             exp.type = pointerExp;
9788             exp.member.member = id;
9789             if(curCompound && FindSymbol("this", curContext, curCompound.compound.context, false, false))
9790                classExp = MkExpMember(MkExpIdentifier(MkIdentifier("this")), MkIdentifier("_class"));
9791             else
9792                classExp = MkExpIdentifier(MkIdentifier("class"));
9793
9794             exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9795                MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), 
9796                   MkExpBrackets(MkListOne(MkExpOp(
9797                      MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)), 
9798                         MkExpMember(classExp, MkIdentifier("data"))), '+',
9799                            MkExpMember(MkExpClass(MkListOne(MkSpecifierName(_class.fullName)), null), MkIdentifier("offsetClass")))))
9800                      )));
9801
9802             ProcessExpressionType(exp);
9803             return;
9804          }
9805          break;
9806       }
9807       case arrayExp:
9808       {
9809          Type type = null;
9810          char * typeString = null;
9811          char typeStringBuf[1024];
9812          if(exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
9813             exp.destType._class.registered != containerClass && eClass_IsDerived(exp.destType._class.registered, containerClass))
9814          {
9815             Class templateClass = exp.destType._class.registered;
9816             typeString = templateClass.templateArgs[2].dataTypeString;
9817          }
9818          else if(exp.list)
9819          {
9820             // Guess type from expressions in the array
9821             Expression e;
9822             for(e = exp.list->first; e; e = e.next)
9823             {
9824                ProcessExpressionType(e);
9825                if(e.expType)
9826                {
9827                   if(!type) { type = e.expType; type.refCount++; }
9828                   else
9829                   {
9830                      // if(!MatchType(e.expType, type, null, null, null, false, false, false))
9831                      if(!MatchTypeExpression(e, type, null, false))
9832                      {
9833                         FreeType(type);
9834                         type = e.expType;
9835                         e.expType = null;
9836                         
9837                         e = exp.list->first;
9838                         ProcessExpressionType(e);
9839                         if(e.expType)
9840                         {
9841                            //if(!MatchTypes(e.expType, type, null, null, null, false, false, false))
9842                            if(!MatchTypeExpression(e, type, null, false))
9843                            {
9844                               FreeType(e.expType);
9845                               e.expType = null;
9846                               FreeType(type);
9847                               type = null;
9848                               break;
9849                            }                           
9850                         }
9851                      }
9852                   }
9853                   if(e.expType)
9854                   {
9855                      FreeType(e.expType);
9856                      e.expType = null;
9857                   }
9858                }
9859             }
9860             if(type)
9861             {
9862                typeStringBuf[0] = '\0';
9863                PrintType(type, typeStringBuf, false, true);
9864                typeString = typeStringBuf;
9865                FreeType(type);
9866                type = null;
9867             }
9868          }
9869          if(typeString)
9870          {
9871             /*
9872             (Container)(__extension__( { 
9873                int __arrayMembers[] = { 1, 7, 3, 4, 5 };
9874                BuiltInContainer __baseContainer
9875                {
9876                   data = __arrayMembers,
9877                   count = 5,
9878                   type = class(int),
9879                   _vTbl = class(BuiltInContainer)._vTbl,
9880                   _class = class(BuiltInContainer) };
9881                &__baseContainer;
9882              }))
9883             */
9884             
9885             char templateString[1024];
9886             OldList * declarations = MkList();
9887             OldList * instMembers = MkList();
9888             OldList * specs = MkList();
9889             OldList * initializers = MkList();
9890             char count[128];
9891             Expression e;
9892             Expression expExt;
9893             Declarator decl = SpecDeclFromString(typeString, specs, null);
9894             Context context = PushContext();
9895
9896             // sprintf(templateString, "Container<%s >", typeString);
9897             sprintf(templateString, "Container<%s>", typeString);
9898    
9899             ListAdd(instMembers, MkMemberInit(MkListOne(MkIdentifier("data")), MkInitializerAssignment(MkExpIdentifier(MkIdentifier("__internalList")))));
9900
9901             sprintf(count, "%d", exp.list->count);
9902             ListAdd(instMembers, MkMemberInit(MkListOne(MkIdentifier("count")), MkInitializerAssignment(MkExpConstant(count))));
9903
9904             ListAdd(instMembers, MkMemberInit(MkListOne(MkIdentifier("type")), MkInitializerAssignment(MkExpClass(CopyList(specs, CopySpecifier), 
9905                CopyDeclarator(decl)))));
9906
9907             ListAdd(instMembers, MkMemberInit(MkListOne(MkIdentifier("_vTbl")), MkInitializerAssignment(MkExpMember(
9908                MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null), MkIdentifier("_vTbl")))));
9909
9910             ListAdd(instMembers, MkMemberInit(MkListOne(MkIdentifier("_class")), MkInitializerAssignment(
9911                MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null))));
9912
9913             if(exp.list)
9914             {
9915                type = ProcessTypeString(typeString, false);
9916                while(e = exp.list->first)
9917                {
9918                   exp.list->Remove(e);
9919                   e.destType = type;
9920                   type.refCount++;
9921                   ProcessExpressionType(e);
9922                   ListAdd(initializers, MkInitializerAssignment(e));
9923                }
9924                FreeType(type);
9925                delete exp.list;
9926             }
9927             
9928             ListAdd(declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorArray(PlugDeclarator(decl, 
9929                MkDeclaratorIdentifier(MkIdentifier("__internalList"))), null),
9930                MkInitializerList(initializers)))));
9931             ListAdd(declarations, MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName("BuiltInContainer")),
9932                MkExpIdentifier(MkIdentifier("__internalContainer")), MkListOne(MkMembersInitList(instMembers)))));
9933
9934             exp.expType = ProcessTypeString(templateString, false);
9935             exp.type = bracketsExp;
9936             exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(templateString)), null),
9937                (expExt = MkExpExtensionCompound(MkCompoundStmt(
9938                   declarations, MkListOne(MkExpressionStmt(MkListOne(MkExpOp(null, '&', MkExpIdentifier(MkIdentifier("__internalContainer")))))))))));
9939             expExt.compound.compound.context = context;
9940             PopContext(context);
9941             ProcessExpressionType(expExt);
9942          }
9943          else
9944          {
9945             exp.expType = ProcessTypeString("Container", false);
9946             Compiler_Error("Couldn't determine type of array elements\n");
9947          }
9948          break;
9949       }
9950    }
9951
9952    if(exp.expType && exp.expType.kind == thisClassType && thisClass && (!exp.destType || exp.destType.kind != thisClassType))
9953    {
9954       FreeType(exp.expType);
9955       exp.expType = ReplaceThisClassType(thisClass);
9956    }
9957
9958    // Resolve structures here
9959    if(exp.expType && (exp.expType.kind == structType || exp.expType.kind == unionType || exp.expType.kind == enumType) && !exp.expType.members.first && exp.expType.enumName)
9960    {
9961       Symbol symbol = FindSymbol(exp.expType.enumName, curContext, globalContext, true, false);
9962       // TODO: Fix members reference...
9963       if(symbol)
9964       {
9965          if(exp.expType.kind != enumType)
9966          {
9967             Type member;
9968             exp.expType.members = symbol.type.members;
9969             for(member = symbol.type.members.first; member; member = member.next)
9970                member.refCount++;
9971          }
9972          else
9973          {
9974             NamedLink member;
9975             for(member = symbol.type.members.first; member; member = member.next)
9976             {
9977                NamedLink value { name = CopyString(member.name) };
9978                exp.expType.members.Add(value);
9979             }
9980          }
9981       }
9982    }
9983
9984    yylloc = exp.loc;
9985    if(exp.destType && (exp.destType.kind == voidType || exp.destType.kind == dummyType) );
9986    else if(exp.destType && !exp.destType.keepCast)
9987    {
9988       if(!CheckExpressionType(exp, exp.destType, false))
9989       {
9990          if(!exp.destType.count || unresolved)
9991          {
9992             if(!exp.expType)
9993             {
9994                yylloc = exp.loc;
9995                if(exp.destType.kind != ellipsisType)
9996                {
9997                   char type2[1024];
9998                   type2[0] = '\0';
9999                   if(inCompiler)
10000                   {
10001                      char expString[10240];
10002                      expString[0] = '\0';
10003
10004                      PrintType(exp.destType, type2, false, true);
10005
10006                      if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10007                      if(unresolved)
10008                         Compiler_Error("unresolved identifier %s; expected %s\n", expString, type2);
10009                      else if(exp.type != dummyExp)
10010                         Compiler_Error("couldn't determine type of %s; expected %s\n", expString, type2);
10011                   }
10012                }
10013                else
10014                {
10015                   char expString[10240] ;
10016                   expString[0] = '\0';
10017                   if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10018
10019                   if(unresolved)
10020                      Compiler_Error("unresolved identifier %s\n", expString);
10021                   else if(exp.type != dummyExp)
10022                      Compiler_Error("couldn't determine type of %s\n", expString);
10023                }
10024             }
10025             else
10026             {
10027                char type1[1024];
10028                char type2[1024];
10029                type1[0] = '\0';
10030                type2[0] = '\0';
10031                if(inCompiler)
10032                {
10033                   PrintType(exp.expType, type1, false, true);
10034                   PrintType(exp.destType, type2, false, true);
10035                }
10036
10037                //CheckExpressionType(exp, exp.destType, false);
10038
10039                if(exp.destType.truth && exp.destType._class && exp.destType._class.registered && !strcmp(exp.destType._class.registered.name, "bool") &&
10040                   exp.expType.kind != voidType && exp.expType.kind != structType && exp.expType.kind != unionType && 
10041                   (exp.expType.kind != classType || exp.expType.classObjectType || (exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type != structClass)));
10042                else
10043                {
10044                   char expString[10240];
10045                   expString[0] = '\0';
10046                   if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10047
10048 #ifdef _DEBUG
10049                   CheckExpressionType(exp, exp.destType, false);
10050 #endif
10051                   Compiler_Warning("incompatible expression %s (%s); expected %s\n", expString, type1, type2);
10052
10053                   // TO CHECK: FORCING HERE TO HELP DEBUGGER
10054                   FreeType(exp.expType);
10055                   exp.destType.refCount++;
10056                   exp.expType = exp.destType;
10057                }
10058             }
10059          }
10060       }
10061       else if(exp.destType && exp.destType.kind == ellipsisType && exp.expType && exp.expType.passAsTemplate)
10062       {
10063          Expression newExp { };
10064          char typeString[1024];
10065          OldList * specs = MkList();
10066          Declarator decl;
10067
10068          typeString[0] = '\0';
10069
10070          *newExp = *exp;
10071
10072          if(exp.expType)  exp.expType.refCount++;
10073          if(exp.expType)  exp.expType.refCount++;
10074          exp.type = castExp;
10075          newExp.destType = exp.expType;
10076
10077          PrintType(exp.expType, typeString, false, false);
10078          decl = SpecDeclFromString(typeString, specs, null);
10079          
10080          exp.cast.typeName = MkTypeName(specs, decl);
10081          exp.cast.exp = newExp;
10082       }
10083    }
10084    else if(unresolved)
10085    {
10086       if(exp.identifier._class && exp.identifier._class.name)
10087          Compiler_Error("unresolved identifier %s::%s\n", exp.identifier._class.name, exp.identifier.string);
10088       else if(exp.identifier.string && exp.identifier.string[0])
10089          Compiler_Error("unresolved identifier %s\n", exp.identifier.string);
10090    }
10091    else if(!exp.expType && exp.type != dummyExp)
10092    {
10093       char expString[10240];
10094       expString[0] = '\0';
10095       if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10096       Compiler_Error("couldn't determine type of %s\n", expString);
10097    }
10098
10099    // Let's try to support any_object & typed_object here:
10100    ApplyAnyObjectLogic(exp);
10101
10102    if(!notByReference && exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
10103       exp.expType._class.registered.type == noHeadClass)
10104    {
10105       exp.byReference = true;
10106    }
10107    /*else if(!notByReference && exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
10108       exp.destType._class.registered.type == noHeadClass)
10109    {
10110       exp.byReference = true;
10111    }*/
10112    yylloc = oldyylloc;
10113 }
10114
10115 static void FindNextDataMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
10116 {
10117    // THIS CODE WILL FIND NEXT MEMBER...
10118    if(*curMember) 
10119    {
10120       *curMember = (*curMember).next;
10121
10122       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
10123       {
10124          *curMember = subMemberStack[--(*subMemberStackPos)];
10125          *curMember = (*curMember).next;
10126       }
10127
10128       // SKIP ALL PROPERTIES HERE...
10129       while((*curMember) && (*curMember).isProperty)
10130          *curMember = (*curMember).next;
10131
10132       if(subMemberStackPos)
10133       {
10134          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10135          {
10136             subMemberStack[(*subMemberStackPos)++] = *curMember;
10137
10138             *curMember = (*curMember).members.first;
10139             while(*curMember && (*curMember).isProperty)
10140                *curMember = (*curMember).next;                     
10141          }
10142       }
10143    }
10144    while(!*curMember)
10145    {
10146       if(!*curMember)
10147       {
10148          if(subMemberStackPos && *subMemberStackPos)
10149          {
10150             *curMember = subMemberStack[--(*subMemberStackPos)];
10151             *curMember = (*curMember).next;
10152          }
10153          else
10154          {
10155             Class lastCurClass = *curClass;
10156
10157             if(*curClass == _class) break;     // REACHED THE END
10158
10159             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass; *curClass = (*curClass).base);
10160             *curMember = (*curClass).membersAndProperties.first;
10161          }
10162
10163          while((*curMember) && (*curMember).isProperty)
10164             *curMember = (*curMember).next;
10165          if(subMemberStackPos)
10166          {
10167             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10168             {
10169                subMemberStack[(*subMemberStackPos)++] = *curMember;
10170
10171                *curMember = (*curMember).members.first;
10172                while(*curMember && (*curMember).isProperty)
10173                   *curMember = (*curMember).next;                     
10174             }
10175          }
10176       }
10177    }
10178 }
10179
10180
10181 static void ProcessInitializer(Initializer init, Type type)
10182 {
10183    switch(init.type)
10184    {
10185       case expInitializer:
10186          if(!init.exp || init.exp.type != instanceExp || !init.exp.instance || init.exp.instance._class || !type || type.kind == classType)
10187          {
10188             // TESTING THIS FOR SHUTTING = 0 WARNING
10189             if(init.exp && !init.exp.destType)
10190             {
10191                FreeType(init.exp.destType);
10192                init.exp.destType = type;
10193                if(type) type.refCount++;
10194             }
10195             if(init.exp)
10196             {
10197                ProcessExpressionType(init.exp);
10198                init.isConstant = init.exp.isConstant;
10199             }
10200             break;
10201          }
10202          else
10203          {
10204             Expression exp = init.exp;
10205             Instantiation inst = exp.instance;
10206             MembersInit members;
10207
10208             init.type = listInitializer;
10209             init.list = MkList();
10210
10211             if(inst.members)
10212             {
10213                for(members = inst.members->first; members; members = members.next)
10214                {
10215                   if(members.type == dataMembersInit)
10216                   {
10217                      MemberInit member;
10218                      for(member = members.dataMembers->first; member; member = member.next)
10219                      {
10220                         ListAdd(init.list, member.initializer);
10221                         member.initializer = null;
10222                      }
10223                   }
10224                   // Discard all MembersInitMethod
10225                }
10226             }
10227             FreeExpression(exp);
10228          }
10229       case listInitializer:
10230       {
10231          Initializer i;
10232          Type initializerType = null;
10233          Class curClass = null;
10234          DataMember curMember = null;
10235          DataMember subMemberStack[256];
10236          int subMemberStackPos = 0;
10237
10238          if(type && type.kind == arrayType)
10239             initializerType = Dereference(type);
10240          else if(type && (type.kind == structType || type.kind == unionType))
10241             initializerType = type.members.first;
10242
10243          for(i = init.list->first; i; i = i.next)
10244          {
10245             if(type && type.kind == classType && type._class && type._class.registered)
10246             {
10247                // 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)
10248                FindNextDataMember(type._class.registered, &curClass, &curMember, subMemberStack, &subMemberStackPos);
10249                // TODO: Generate error on initializing a private data member this way from another module...
10250                if(curMember)
10251                {
10252                   if(!curMember.dataType)
10253                      curMember.dataType = ProcessTypeString(curMember.dataTypeString, false);
10254                   initializerType = curMember.dataType;
10255                }
10256             }
10257             ProcessInitializer(i, initializerType);
10258             if(initializerType && type && (type.kind == structType || type.kind == unionType))
10259                initializerType = initializerType.next;
10260             if(!i.isConstant)
10261                init.isConstant = false;
10262          }
10263
10264          if(type && type.kind == arrayType)
10265             FreeType(initializerType);
10266
10267          if(type && type.kind != arrayType && type.kind != structType && type.kind != unionType && (type.kind != classType || !type._class.registered || type._class.registered.type != structClass))
10268          {
10269             Compiler_Error("Assigning list initializer to non list\n");
10270          }
10271          break;
10272       }
10273    }
10274 }
10275
10276 static void ProcessSpecifier(Specifier spec, bool declareStruct)
10277 {
10278    switch(spec.type)
10279    {
10280       case baseSpecifier:
10281       {
10282          if(spec.specifier == THISCLASS)
10283          {
10284             if(thisClass)
10285             {
10286                spec.type = nameSpecifier;
10287                spec.name = ReplaceThisClass(thisClass);
10288                spec.symbol = FindClass(spec.name);
10289                ProcessSpecifier(spec, declareStruct);
10290             }
10291          }
10292          break;
10293       }
10294       case nameSpecifier:
10295       {
10296          Symbol symbol = FindType(curContext, spec.name);
10297          if(symbol)
10298             DeclareType(symbol.type, true, true);
10299          else if((symbol = spec.symbol /*FindClass(spec.name)*/) && symbol.registered && symbol.registered.type == structClass && declareStruct)
10300             DeclareStruct(spec.name, false);
10301          break;
10302       }
10303       case enumSpecifier:
10304       {
10305          Enumerator e;
10306          if(spec.list)
10307          {
10308             for(e = spec.list->first; e; e = e.next)
10309             {
10310                if(e.exp)
10311                   ProcessExpressionType(e.exp);
10312             }
10313          }
10314          break;
10315       }
10316       case structSpecifier:
10317       case unionSpecifier:
10318       {
10319          if(spec.definitions)
10320          {
10321             ClassDef def;
10322             Symbol symbol = spec.id ? FindClass(spec.id.string) : null;
10323             //if(symbol)
10324                ProcessClass(spec.definitions, symbol);
10325             /*else
10326             {
10327                for(def = spec.definitions->first; def; def = def.next)
10328                {
10329                   //if(def.type == declarationClassDef && def.decl && def.decl.type == DeclarationStruct)
10330                      ProcessDeclaration(def.decl);
10331                }
10332             }*/
10333          }
10334          break;
10335       }
10336       /*
10337       case classSpecifier:
10338       {
10339          Symbol classSym = FindClass(spec.name);
10340          if(classSym && classSym.registered && classSym.registered.type == structClass)
10341             DeclareStruct(spec.name, false);
10342          break;
10343       }
10344       */
10345    }
10346 }
10347
10348
10349 static void ProcessDeclarator(Declarator decl)
10350 {
10351    switch(decl.type)
10352    {
10353       case identifierDeclarator:
10354          if(decl.identifier.classSym /* TODO: Name Space Fix ups  || decl.identifier.nameSpace*/)
10355          {
10356             FreeSpecifier(decl.identifier._class);
10357             decl.identifier._class = null;
10358          }
10359          break;
10360       case arrayDeclarator:
10361          if(decl.array.exp)
10362             ProcessExpressionType(decl.array.exp);
10363       case structDeclarator:
10364       case bracketsDeclarator:
10365       case functionDeclarator:
10366       case pointerDeclarator:
10367       case extendedDeclarator:
10368       case extendedDeclaratorEnd:
10369          if(decl.declarator)
10370             ProcessDeclarator(decl.declarator);
10371          if(decl.type == functionDeclarator)
10372          {
10373             Identifier id = GetDeclId(decl);
10374             if(id && id._class)
10375             {
10376                TypeName param
10377                {
10378                   qualifiers = MkListOne(id._class);
10379                   declarator = null;
10380                };
10381                if(!decl.function.parameters)
10382                   decl.function.parameters = MkList();               
10383                decl.function.parameters->Insert(null, param);
10384                id._class = null;
10385             }
10386             if(decl.function.parameters)
10387             {
10388                TypeName param;
10389                
10390                for(param = decl.function.parameters->first; param; param = param.next)
10391                {
10392                   if(param.qualifiers && param.qualifiers->first)
10393                   {
10394                      Specifier spec = param.qualifiers->first;
10395                      if(spec && spec.specifier == TYPED_OBJECT)
10396                      {
10397                         Declarator d = param.declarator;
10398                         TypeName newParam
10399                         {
10400                            qualifiers = MkListOne(MkSpecifier(VOID));
10401                            declarator = MkDeclaratorPointer(MkPointer(null,null), d);
10402                         };
10403                         
10404                         FreeList(param.qualifiers, FreeSpecifier);
10405
10406                         param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
10407                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
10408
10409                         decl.function.parameters->Insert(param, newParam);
10410                         param = newParam;
10411                      }
10412                      else if(spec && spec.specifier == ANY_OBJECT)
10413                      {
10414                         Declarator d = param.declarator;
10415                         
10416                         FreeList(param.qualifiers, FreeSpecifier);
10417
10418                         param.qualifiers = MkListOne(MkSpecifier(VOID));
10419                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);                        
10420                      }
10421                      else if(spec.specifier == THISCLASS)
10422                      {
10423                         if(thisClass)
10424                         {
10425                            spec.type = nameSpecifier;
10426                            spec.name = ReplaceThisClass(thisClass);
10427                            spec.symbol = FindClass(spec.name);
10428                            ProcessSpecifier(spec, false);
10429                         }
10430                      }
10431                   }
10432
10433                   if(param.declarator)
10434                      ProcessDeclarator(param.declarator);
10435                }
10436             }
10437          }
10438          break;
10439    }
10440 }
10441
10442 static void ProcessDeclaration(Declaration decl)
10443 {
10444    yylloc = decl.loc;
10445    switch(decl.type)
10446    {
10447       case initDeclaration:
10448       {
10449          bool declareStruct = false;
10450          /*
10451          lineNum = decl.pos.line;
10452          column = decl.pos.col;
10453          */
10454
10455          if(decl.declarators)
10456          {
10457             InitDeclarator d;
10458          
10459             for(d = decl.declarators->first; d; d = d.next)
10460             {
10461                Type type, subType;
10462                ProcessDeclarator(d.declarator);
10463
10464                type = ProcessType(decl.specifiers, d.declarator);
10465
10466                if(d.initializer)
10467                {
10468                   ProcessInitializer(d.initializer, type);
10469
10470                   // Change "ColorRGB a = ColorRGB { 1,2,3 } => ColorRGB a { 1,2,3 }                  
10471                   
10472                   if(decl.declarators->count == 1 && d.initializer.type == expInitializer &&
10473                      d.initializer.exp.type == instanceExp)
10474                   {
10475                      if(type.kind == classType && type._class == 
10476                         d.initializer.exp.expType._class)
10477                      {
10478                         Instantiation inst = d.initializer.exp.instance;
10479                         inst.exp = MkExpIdentifier(CopyIdentifier(GetDeclId(d.declarator)));
10480                         
10481                         d.initializer.exp.instance = null;
10482                         if(decl.specifiers)
10483                            FreeList(decl.specifiers, FreeSpecifier);
10484                         FreeList(decl.declarators, FreeInitDeclarator);
10485
10486                         d = null;
10487
10488                         decl.type = instDeclaration;
10489                         decl.inst = inst;
10490                      }
10491                   }
10492                }
10493                for(subType = type; subType;)
10494                {
10495                   if(subType.kind == classType)
10496                   {
10497                      declareStruct = true;
10498                      break;
10499                   }
10500                   else if(subType.kind == pointerType)
10501                      break;
10502                   else if(subType.kind == arrayType)
10503                      subType = subType.arrayType;
10504                   else
10505                      break;
10506                }
10507
10508                FreeType(type);
10509                if(!d) break;
10510             }
10511          }
10512
10513          if(decl.specifiers)
10514          {
10515             Specifier s;
10516             for(s = decl.specifiers->first; s; s = s.next)
10517             {
10518                ProcessSpecifier(s, declareStruct);
10519             }
10520          }
10521          break;
10522       }
10523       case instDeclaration:
10524       {
10525          ProcessInstantiationType(decl.inst);
10526          break;
10527       }
10528       case structDeclaration:
10529       {
10530          Specifier spec;
10531          Declarator d;
10532          bool declareStruct = false;
10533
10534          if(decl.declarators)
10535          {
10536             for(d = decl.declarators->first; d; d = d.next)
10537             {
10538                Type type = ProcessType(decl.specifiers, d.declarator);
10539                Type subType;
10540                ProcessDeclarator(d);
10541                for(subType = type; subType;)
10542                {
10543                   if(subType.kind == classType)
10544                   {
10545                      declareStruct = true;
10546                      break;
10547                   }
10548                   else if(subType.kind == pointerType)
10549                      break;
10550                   else if(subType.kind == arrayType)
10551                      subType = subType.arrayType;
10552                   else
10553                      break;
10554                }
10555                FreeType(type);
10556             }
10557          }
10558          if(decl.specifiers)
10559          {
10560             for(spec = decl.specifiers->first; spec; spec = spec.next)
10561                ProcessSpecifier(spec, declareStruct);
10562          }
10563          break;
10564       }
10565    }
10566 }
10567
10568 static FunctionDefinition curFunction;
10569
10570 static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
10571 {
10572    char propName[1024], propNameM[1024];
10573    char getName[1024], setName[1024];
10574    OldList * args;
10575
10576    DeclareProperty(prop, setName, getName);
10577
10578    // eInstance_FireWatchers(object, prop);
10579    strcpy(propName, "__ecereProp_");
10580    FullClassNameCat(propName, prop._class.fullName, false);
10581    strcat(propName, "_");
10582    // strcat(propName, prop.name);
10583    FullClassNameCat(propName, prop.name, true);
10584    MangleClassName(propName);
10585
10586    strcpy(propNameM, "__ecerePropM_");
10587    FullClassNameCat(propNameM, prop._class.fullName, false);
10588    strcat(propNameM, "_");
10589    // strcat(propNameM, prop.name);
10590    FullClassNameCat(propNameM, prop.name, true);
10591    MangleClassName(propNameM);
10592
10593    if(prop.isWatchable)
10594    {
10595       args = MkList();
10596       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10597       ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10598       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10599
10600       args = MkList();
10601       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10602       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10603       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10604    }
10605
10606    
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_FireSelfWatchers")), 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_FireSelfWatchers")), args));
10617    }
10618    
10619    if(curFunction.propSet && !strcmp(curFunction.propSet.string, prop.name) && 
10620       (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
10621       curFunction.propSet.fireWatchersDone = true;
10622 }
10623
10624 static void ProcessStatement(Statement stmt)
10625 {
10626    yylloc = stmt.loc;
10627    /*
10628    lineNum = stmt.pos.line;
10629    column = stmt.pos.col;
10630    */
10631    switch(stmt.type)
10632    {
10633       case labeledStmt:
10634          ProcessStatement(stmt.labeled.stmt);
10635          break;
10636       case caseStmt:
10637          // This expression should be constant...
10638          if(stmt.caseStmt.exp)
10639          {
10640             FreeType(stmt.caseStmt.exp.destType);
10641             stmt.caseStmt.exp.destType = curSwitchType;
10642             if(curSwitchType) curSwitchType.refCount++;
10643             ProcessExpressionType(stmt.caseStmt.exp);
10644             ComputeExpression(stmt.caseStmt.exp);
10645          }
10646          if(stmt.caseStmt.stmt)
10647             ProcessStatement(stmt.caseStmt.stmt);
10648          break;
10649       case compoundStmt:
10650       {
10651          if(stmt.compound.context)
10652          {
10653             Declaration decl;
10654             Statement s;
10655
10656             Statement prevCompound = curCompound;
10657             Context prevContext = curContext;
10658
10659             if(!stmt.compound.isSwitch)
10660             {
10661                curCompound = stmt;
10662                curContext = stmt.compound.context;
10663             }
10664
10665             if(stmt.compound.declarations)
10666             {
10667                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
10668                   ProcessDeclaration(decl);
10669             }
10670             if(stmt.compound.statements)
10671             {
10672                for(s = stmt.compound.statements->first; s; s = s.next)
10673                   ProcessStatement(s);
10674             }
10675
10676             curContext = prevContext;
10677             curCompound = prevCompound;
10678          }
10679          break;
10680       }
10681       case expressionStmt:
10682       {
10683          Expression exp;
10684          if(stmt.expressions)
10685          {
10686             for(exp = stmt.expressions->first; exp; exp = exp.next)
10687                ProcessExpressionType(exp);
10688          }
10689          break;
10690       }
10691       case ifStmt:
10692       {
10693          Expression exp;
10694
10695          FreeType(((Expression)stmt.ifStmt.exp->last).destType);
10696          ((Expression)stmt.ifStmt.exp->last).destType = MkClassType("bool");
10697          ((Expression)stmt.ifStmt.exp->last).destType.truth = true;
10698          for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
10699          {
10700             ProcessExpressionType(exp);
10701          }
10702          if(stmt.ifStmt.stmt)
10703             ProcessStatement(stmt.ifStmt.stmt);
10704          if(stmt.ifStmt.elseStmt)
10705             ProcessStatement(stmt.ifStmt.elseStmt);
10706          break;
10707       }
10708       case switchStmt:
10709       {
10710          Type oldSwitchType = curSwitchType;
10711          if(stmt.switchStmt.exp)
10712          {
10713             Expression exp;
10714             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
10715             {
10716                if(!exp.next)
10717                {
10718                   /*
10719                   Type destType
10720                   {
10721                      kind = intType;
10722                      refCount = 1;
10723                   };
10724                   e.exp.destType = destType;
10725                   */
10726
10727                   ProcessExpressionType(exp);
10728                }
10729                if(!exp.next)
10730                   curSwitchType = exp.expType;
10731             }
10732          }
10733          ProcessStatement(stmt.switchStmt.stmt);
10734          curSwitchType = oldSwitchType;
10735          break;
10736       }
10737       case whileStmt:
10738       {
10739          if(stmt.whileStmt.exp)
10740          {
10741             Expression exp;
10742
10743             FreeType(((Expression)stmt.whileStmt.exp->last).destType);
10744             ((Expression)stmt.whileStmt.exp->last).destType = MkClassType("bool");
10745             ((Expression)stmt.whileStmt.exp->last).destType.truth = true;
10746             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
10747             {
10748                ProcessExpressionType(exp);
10749             }
10750          }
10751          if(stmt.whileStmt.stmt)
10752             ProcessStatement(stmt.whileStmt.stmt);
10753          break;
10754       }
10755       case doWhileStmt:
10756       {
10757          if(stmt.doWhile.exp)
10758          {
10759             Expression exp;
10760
10761             if(stmt.doWhile.exp->last)
10762             {
10763                FreeType(((Expression)stmt.doWhile.exp->last).destType);
10764                ((Expression)stmt.doWhile.exp->last).destType = MkClassType("bool");
10765                ((Expression)stmt.doWhile.exp->last).destType.truth = true;
10766             }
10767             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
10768             {
10769                ProcessExpressionType(exp);
10770             }
10771          }
10772          if(stmt.doWhile.stmt)
10773             ProcessStatement(stmt.doWhile.stmt);
10774          break;
10775       }
10776       case forStmt:
10777       {
10778          Expression exp;
10779          if(stmt.forStmt.init)
10780             ProcessStatement(stmt.forStmt.init);
10781
10782          if(stmt.forStmt.check && stmt.forStmt.check.expressions)
10783          {
10784             FreeType(((Expression)stmt.forStmt.check.expressions->last).destType);
10785             ((Expression)stmt.forStmt.check.expressions->last).destType = MkClassType("bool");
10786             ((Expression)stmt.forStmt.check.expressions->last).destType.truth = true;
10787          }
10788
10789          if(stmt.forStmt.check)
10790             ProcessStatement(stmt.forStmt.check);
10791          if(stmt.forStmt.increment)
10792          {
10793             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
10794                ProcessExpressionType(exp);
10795          }
10796
10797          if(stmt.forStmt.stmt)
10798             ProcessStatement(stmt.forStmt.stmt);
10799          break;
10800       }
10801       case forEachStmt:
10802       {
10803          Identifier id = stmt.forEachStmt.id;
10804          OldList * exp = stmt.forEachStmt.exp;
10805          OldList * filter = stmt.forEachStmt.filter;
10806          Statement block = stmt.forEachStmt.stmt;
10807          char iteratorType[1024];
10808          Type source;
10809          Expression e;
10810          bool isBuiltin = exp && exp->last && 
10811             (((Expression)exp->last).type == ExpressionType::arrayExp || 
10812               (((Expression)exp->last).type == castExp && ((Expression)exp->last).cast.exp.type == ExpressionType::arrayExp));
10813          Expression arrayExp;
10814          char * typeString = null;
10815          int builtinCount = 0;
10816
10817          for(e = exp ? exp->first : null; e; e = e.next)
10818          {
10819             if(!e.next)
10820             {
10821                FreeType(e.destType);
10822                e.destType = ProcessTypeString("Container", false);
10823             }
10824             if(!isBuiltin || e.next)
10825                ProcessExpressionType(e);
10826          }
10827
10828          source = (exp && exp->last) ? ((Expression)exp->last).expType : null;
10829          if(isBuiltin || (source && source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
10830             eClass_IsDerived(source._class.registered, containerClass)))
10831          {
10832             Class _class = source ? source._class.registered : null;
10833             Symbol symbol;
10834             Expression expIt = null;
10835             bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false, isAVLTree = false;
10836             Class arrayClass = eSystem_FindClass(privateModule, "Array");
10837             Class linkListClass = eSystem_FindClass(privateModule, "LinkList");
10838             Class customAVLTreeClass = eSystem_FindClass(privateModule, "CustomAVLTree");
10839             stmt.type = compoundStmt;
10840             
10841             stmt.compound.context = Context { };
10842             stmt.compound.context.parent = curContext;
10843             curContext = stmt.compound.context;
10844
10845             if(source && eClass_IsDerived(source._class.registered, customAVLTreeClass))
10846             {
10847                Class mapClass = eSystem_FindClass(privateModule, "Map");
10848                Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
10849                isCustomAVLTree = true;
10850                if(eClass_IsDerived(source._class.registered, avlTreeClass))
10851                   isAVLTree = true;
10852                else if(eClass_IsDerived(source._class.registered, mapClass))
10853                   isMap = true;
10854             }
10855             else if(source && eClass_IsDerived(source._class.registered, arrayClass)) isArray = true;
10856             else if(source && eClass_IsDerived(source._class.registered, linkListClass)) 
10857             {
10858                Class listClass = eSystem_FindClass(privateModule, "List");
10859                isLinkList = true;
10860                isList = eClass_IsDerived(source._class.registered, listClass);
10861             }
10862
10863             if(isArray)
10864             {
10865                Declarator decl;
10866                OldList * specs = MkList();
10867                decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
10868                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
10869                stmt.compound.declarations = MkListOne(
10870                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
10871                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
10872                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalArray")), 
10873                      MkInitializerAssignment(MkExpBrackets(exp))))));
10874             }
10875             else if(isBuiltin)
10876             {
10877                Type type = null;
10878                char typeStringBuf[1024];
10879                
10880                // TODO: Merge this code?
10881                arrayExp = (((Expression)exp->last).type == ExpressionType::arrayExp) ? (Expression)exp->last : ((Expression)exp->last).cast.exp;
10882                if(((Expression)exp->last).type == castExp)
10883                {
10884                   TypeName typeName = ((Expression)exp->last).cast.typeName;
10885                   if(typeName)
10886                      arrayExp.destType = ProcessType(typeName.qualifiers, typeName.declarator);
10887                }
10888
10889                if(arrayExp.destType && arrayExp.destType.kind == classType && arrayExp.destType._class && arrayExp.destType._class.registered &&
10890                   arrayExp.destType._class.registered != containerClass && eClass_IsDerived(arrayExp.destType._class.registered, containerClass) &&
10891                   arrayExp.destType._class.registered.templateArgs)
10892                {
10893                   Class templateClass = arrayExp.destType._class.registered;
10894                   typeString = templateClass.templateArgs[2].dataTypeString;
10895                }
10896                else if(arrayExp.list)
10897                {
10898                   // Guess type from expressions in the array
10899                   Expression e;
10900                   for(e = arrayExp.list->first; e; e = e.next)
10901                   {
10902                      ProcessExpressionType(e);
10903                      if(e.expType)
10904                      {
10905                         if(!type) { type = e.expType; type.refCount++; }
10906                         else
10907                         {
10908                            // if(!MatchType(e.expType, type, null, null, null, false, false, false))
10909                            if(!MatchTypeExpression(e, type, null, false))
10910                            {
10911                               FreeType(type);
10912                               type = e.expType;
10913                               e.expType = null;
10914                               
10915                               e = arrayExp.list->first;
10916                               ProcessExpressionType(e);
10917                               if(e.expType)
10918                               {
10919                                  //if(!MatchTypes(e.expType, type, null, null, null, false, false, false, false))
10920                                  if(!MatchTypeExpression(e, type, null, false))
10921                                  {
10922                                     FreeType(e.expType);
10923                                     e.expType = null;
10924                                     FreeType(type);
10925                                     type = null;
10926                                     break;
10927                                  }                           
10928                               }
10929                            }
10930                         }
10931                         if(e.expType)
10932                         {
10933                            FreeType(e.expType);
10934                            e.expType = null;
10935                         }
10936                      }
10937                   }
10938                   if(type)
10939                   {
10940                      typeStringBuf[0] = '\0';
10941                      PrintType(type, typeStringBuf, false, true);
10942                      typeString = typeStringBuf;
10943                      FreeType(type);
10944                   }
10945                }
10946                if(typeString)
10947                {
10948                   OldList * initializers = MkList();
10949                   Declarator decl;
10950                   OldList * specs = MkList();
10951                   if(arrayExp.list)
10952                   {
10953                      Expression e;
10954
10955                      builtinCount = arrayExp.list->count;
10956                      type = ProcessTypeString(typeString, false);
10957                      while(e = arrayExp.list->first)
10958                      {
10959                         arrayExp.list->Remove(e);
10960                         e.destType = type;
10961                         type.refCount++;
10962                         ProcessExpressionType(e);
10963                         ListAdd(initializers, MkInitializerAssignment(e));
10964                      }
10965                      FreeType(type);
10966                      delete arrayExp.list;
10967                   }
10968                   decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
10969                   stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier), 
10970                      MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
10971
10972                   ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorArray(PlugDeclarator(
10973                      /*CopyDeclarator(*/decl/*)*/, MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), null), MkInitializerList(initializers)))));
10974                   
10975                   FreeList(exp, FreeExpression);
10976                }
10977                else
10978                {
10979                   arrayExp.expType = ProcessTypeString("Container", false);
10980                   Compiler_Error("Couldn't determine type of array elements\n");
10981                }
10982
10983                /*
10984                Declarator decl;
10985                OldList * specs = MkList();
10986
10987                decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
10988                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
10989                stmt.compound.declarations = MkListOne(
10990                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
10991                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName("BuiltInContainer")),
10992                   MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), 
10993                      MkInitializerAssignment(MkExpBrackets(exp))))));
10994                */
10995             }
10996             else if(isLinkList && !isList)
10997             {
10998                Declarator decl;
10999                OldList * specs = MkList();
11000                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11001                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11002                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11003                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalLinkList")), 
11004                      MkInitializerAssignment(MkExpBrackets(exp))))));
11005             }
11006             /*else if(isCustomAVLTree)
11007             {
11008                Declarator decl;
11009                OldList * specs = MkList();
11010                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11011                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11012                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11013                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalTree")), 
11014                      MkInitializerAssignment(MkExpBrackets(exp))))));
11015             }*/
11016             else if(_class.templateArgs)
11017             {
11018                if(isMap)
11019                   sprintf(iteratorType, "MapIterator<%s, %s >", _class.templateArgs[5].dataTypeString, _class.templateArgs[6].dataTypeString);
11020                else
11021                   sprintf(iteratorType, "Iterator<%s, %s >", _class.templateArgs[2].dataTypeString, _class.templateArgs[1].dataTypeString);
11022
11023                stmt.compound.declarations = MkListOne(
11024                   MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName(iteratorType)),
11025                   MkExpIdentifier(id), MkListOne(MkMembersInitList(MkListOne(MkMemberInit(isMap ? MkListOne(MkIdentifier("map")) : null, 
11026                   MkInitializerAssignment(MkExpBrackets(exp)))))))));
11027             }
11028             symbol = FindSymbol(id.string, curContext, curContext, false, false);
11029
11030             if(block && block.type == compoundStmt && block.compound.context)
11031             {
11032                block.compound.context.parent = stmt.compound.context;
11033             }
11034             if(filter)
11035             {
11036                block = MkIfStmt(filter, block, null);
11037             }
11038             if(isArray)
11039             {
11040                stmt.compound.statements = MkListOne(MkForStmt(
11041                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
11042                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11043                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11044                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11045                   block));
11046               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11047               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11048               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11049             }
11050             else if(isBuiltin)
11051             {
11052                char count[128];
11053                //OldList * specs = MkList();
11054                // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11055
11056                sprintf(count, "%d", builtinCount);
11057
11058                stmt.compound.statements = MkListOne(MkForStmt(
11059                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
11060                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11061                      MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
11062                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11063                   block));
11064
11065                /*
11066                Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11067                stmt.compound.statements = MkListOne(MkForStmt(
11068                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
11069                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11070                      MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11071                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11072                   block));
11073               */
11074               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11075               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11076               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11077             }
11078             else if(isLinkList && !isList)
11079             {
11080                Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
11081                Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
11082                if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString && 
11083                   !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
11084                {
11085                   stmt.compound.statements = MkListOne(MkForStmt(
11086                      MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11087                      MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11088                      MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11089                      block));
11090                }
11091                else
11092                {
11093                   OldList * specs = MkList();
11094                   Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
11095                   stmt.compound.statements = MkListOne(MkForStmt(
11096                      MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11097                      MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11098                      MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
11099                         MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
11100                            MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
11101                      block));
11102                }
11103                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11104                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11105                ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11106             }
11107             /*else if(isCustomAVLTree)
11108             {
11109                stmt.compound.statements = MkListOne(MkForStmt(
11110                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
11111                      MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
11112                   MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11113                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
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
11121             {
11122                stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
11123                   MkIdentifier("Next")), null)), block));
11124             }
11125             ProcessExpressionType(expIt);
11126             if(stmt.compound.declarations->first)
11127                ProcessDeclaration(stmt.compound.declarations->first);
11128
11129             if(symbol) 
11130                symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
11131
11132             ProcessStatement(stmt);
11133             curContext = stmt.compound.context.parent;
11134             break;
11135          }
11136          else
11137          {
11138             Compiler_Error("Expression is not a container\n");
11139          }
11140          break;
11141       }
11142       case gotoStmt:
11143          break;
11144       case continueStmt:
11145          break;
11146       case breakStmt:
11147          break;
11148       case returnStmt:
11149       {
11150          Expression exp;
11151          if(stmt.expressions)
11152          {
11153             for(exp = stmt.expressions->first; exp; exp = exp.next)
11154             {
11155                if(!exp.next)
11156                {
11157                   if(curFunction && !curFunction.type)
11158                      curFunction.type = ProcessType(
11159                         curFunction.specifiers, curFunction.declarator);
11160                   FreeType(exp.destType);
11161                   exp.destType = (curFunction && curFunction.type && curFunction.type.kind == functionType) ? curFunction.type.returnType : null;
11162                   if(exp.destType) exp.destType.refCount++;
11163                }
11164                ProcessExpressionType(exp);
11165             }
11166          }
11167          break;
11168       }
11169       case badDeclarationStmt:
11170       {
11171          ProcessDeclaration(stmt.decl);
11172          break;
11173       }
11174       case asmStmt:
11175       {
11176          AsmField field;
11177          if(stmt.asmStmt.inputFields)
11178          {
11179             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
11180                if(field.expression)
11181                   ProcessExpressionType(field.expression);
11182          }
11183          if(stmt.asmStmt.outputFields)
11184          {
11185             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
11186                if(field.expression)
11187                   ProcessExpressionType(field.expression);
11188          }
11189          if(stmt.asmStmt.clobberedFields)
11190          {
11191             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
11192             {
11193                if(field.expression)
11194                   ProcessExpressionType(field.expression);
11195             }
11196          }
11197          break;
11198       }
11199       case watchStmt:
11200       {
11201          PropertyWatch propWatch;
11202          OldList * watches = stmt._watch.watches;
11203          Expression object = stmt._watch.object;
11204          Expression watcher = stmt._watch.watcher;
11205          if(watcher)
11206             ProcessExpressionType(watcher);
11207          if(object)
11208             ProcessExpressionType(object);
11209
11210          if(inCompiler)
11211          {
11212             if(watcher || thisClass)
11213             {
11214                External external = curExternal;
11215                Context context = curContext;
11216
11217                stmt.type = expressionStmt;
11218                stmt.expressions = MkList();
11219
11220                curExternal = external.prev;
11221
11222                for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11223                {
11224                   ClassFunction func;
11225                   char watcherName[1024];
11226                   Class watcherClass = watcher ? 
11227                      ((watcher.expType && watcher.expType.kind == classType && watcher.expType._class) ? watcher.expType._class.registered : null) : thisClass;
11228                   External createdExternal;
11229
11230                   // Create a declaration above
11231                   External externalDecl = MkExternalDeclaration(null);
11232                   ast->Insert(curExternal.prev, externalDecl);
11233
11234                   sprintf(watcherName,"__ecerePropertyWatcher_%d", propWatcherID++);
11235                   if(propWatch.deleteWatch)
11236                      strcat(watcherName, "_delete");
11237                   else
11238                   {
11239                      Identifier propID;
11240                      for(propID = propWatch.properties->first; propID; propID = propID.next)
11241                      {
11242                         strcat(watcherName, "_");
11243                         strcat(watcherName, propID.string);
11244                      }
11245                   }
11246
11247                   if(object && object.expType && object.expType.kind == classType && object.expType._class && object.expType._class.registered)
11248                   {
11249                      // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
11250                      func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)),
11251                         //MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null))), null);
11252                         MkListOne(MkTypeName(MkListOne(MkSpecifierName(object.expType._class.string)), MkDeclaratorIdentifier(MkIdentifier("value"))))), null);
11253                      ProcessClassFunctionBody(func, propWatch.compound);
11254                      propWatch.compound = null;
11255
11256                      //afterExternal = afterExternal ? afterExternal : curExternal;
11257
11258                      //createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal.prev);
11259                      createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal, true);
11260                      // TESTING THIS...
11261                      createdExternal.symbol.idCode = external.symbol.idCode;
11262
11263                      curExternal = createdExternal;
11264                      ProcessFunction(createdExternal.function);
11265
11266
11267                      // Create a declaration above
11268                      {
11269                         Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier), 
11270                            MkListOne(MkInitDeclarator(CopyDeclarator(createdExternal.function.declarator), null)));
11271                         externalDecl.declaration = decl;
11272                         if(decl.symbol && !decl.symbol.pointerExternal)
11273                            decl.symbol.pointerExternal = externalDecl;
11274                      }
11275
11276                      if(propWatch.deleteWatch)
11277                      {
11278                         OldList * args = MkList();
11279                         ListAdd(args, CopyExpression(object));
11280                         ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11281                         ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11282                         ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_WatchDestruction")), args));
11283                      }
11284                      else
11285                      {
11286                         Class _class = object.expType._class.registered;
11287                         Identifier propID;
11288
11289                         for(propID = propWatch.properties->first; propID; propID = propID.next)
11290                         {
11291                            char propName[1024];
11292                            Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11293                            if(prop)
11294                            {
11295                               char getName[1024], setName[1024];
11296                               OldList * args = MkList();
11297
11298                               DeclareProperty(prop, setName, getName);                              
11299                               
11300                               // eInstance_Watch(stmt.watch.object, prop, stmt.watch.watcher, callback);
11301                               strcpy(propName, "__ecereProp_");
11302                               FullClassNameCat(propName, prop._class.fullName, false);
11303                               strcat(propName, "_");
11304                               // strcat(propName, prop.name);
11305                               FullClassNameCat(propName, prop.name, true);
11306
11307                               ListAdd(args, CopyExpression(object));
11308                               ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11309                               ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11310                               ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11311
11312                               ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), args));
11313                            }
11314                            else
11315                               Compiler_Error("Property %s not found in class %s\n", prop.name, _class.fullName);
11316                         }
11317                      }
11318                   }
11319                   else
11320                      Compiler_Error("Invalid watched object\n");
11321                }
11322
11323                curExternal = external;
11324                curContext = context;
11325
11326                if(watcher)
11327                   FreeExpression(watcher);
11328                if(object)
11329                   FreeExpression(object);
11330                FreeList(watches, FreePropertyWatch);
11331             }
11332             else
11333                Compiler_Error("No observer specified and not inside a _class\n");
11334          }
11335          else
11336          {
11337             for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11338             {
11339                ProcessStatement(propWatch.compound);
11340             }
11341
11342          }
11343          break;
11344       }
11345       case fireWatchersStmt:
11346       {
11347          OldList * watches = stmt._watch.watches;
11348          Expression object = stmt._watch.object;
11349          Class _class;
11350          // DEBUGGER BUG: Why doesn't watches evaluate to null??
11351          // printf("%X\n", watches);
11352          // printf("%X\n", stmt._watch.watches);
11353          if(object)
11354             ProcessExpressionType(object);
11355
11356          if(inCompiler)
11357          {
11358             _class = object ? 
11359                   ((object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null) : thisClass;
11360
11361             if(_class)
11362             {
11363                Identifier propID;
11364
11365                stmt.type = expressionStmt;
11366                stmt.expressions = MkList();
11367
11368                // Check if we're inside a property set
11369                if(!watches && curFunction.propSet && (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
11370                {
11371                   watches = MkListOne(MkIdentifier(curFunction.propSet.string));
11372                }
11373                else if(!watches)
11374                {
11375                   //Compiler_Error("No property specified and not inside a property set\n");
11376                }
11377                if(watches)
11378                {
11379                   for(propID = watches->first; propID; propID = propID.next)
11380                   {
11381                      Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11382                      if(prop)
11383                      {
11384                         CreateFireWatcher(prop, object, stmt);
11385                      }
11386                      else
11387                         Compiler_Error("Property %s not found in class %s\n", propID.string, _class.fullName);
11388                   }
11389                }
11390                else
11391                {
11392                   // Fire all properties!
11393                   Property prop;
11394                   Class base;
11395                   for(base = _class; base; base = base.base)
11396                   {
11397                      for(prop = base.membersAndProperties.first; prop; prop = prop.next)
11398                      {
11399                         if(prop.isProperty && prop.isWatchable)
11400                         {
11401                            CreateFireWatcher(prop, object, stmt);
11402                         }
11403                      }
11404                   }
11405                }
11406
11407                if(object)
11408                   FreeExpression(object);
11409                FreeList(watches, FreeIdentifier);
11410             }
11411             else
11412                Compiler_Error("Invalid object specified and not inside a class\n");
11413          }
11414          break;
11415       }
11416       case stopWatchingStmt:
11417       {
11418          OldList * watches = stmt._watch.watches;
11419          Expression object = stmt._watch.object;
11420          Expression watcher = stmt._watch.watcher;
11421          Class _class;
11422          if(object)
11423             ProcessExpressionType(object);
11424          if(watcher)
11425             ProcessExpressionType(watcher);
11426          if(inCompiler)
11427          {
11428             _class = (object && object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null;
11429
11430             if(watcher || thisClass)
11431             {
11432                if(_class)
11433                {
11434                   Identifier propID;
11435
11436                   stmt.type = expressionStmt;
11437                   stmt.expressions = MkList();
11438
11439                   if(!watches)
11440                   {
11441                      OldList * args;
11442                      // eInstance_StopWatching(object, null, watcher); 
11443                      args = MkList();
11444                      ListAdd(args, CopyExpression(object));
11445                      ListAdd(args, MkExpConstant("0"));
11446                      ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11447                      ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11448                   }
11449                   else
11450                   {
11451                      for(propID = watches->first; propID; propID = propID.next)
11452                      {
11453                         char propName[1024];
11454                         Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11455                         if(prop)
11456                         {
11457                            char getName[1024], setName[1024];
11458                            OldList * args = MkList();
11459
11460                            DeclareProperty(prop, setName, getName);
11461          
11462                            // eInstance_StopWatching(object, prop, watcher); 
11463                            strcpy(propName, "__ecereProp_");
11464                            FullClassNameCat(propName, prop._class.fullName, false);
11465                            strcat(propName, "_");
11466                            // strcat(propName, prop.name);
11467                            FullClassNameCat(propName, prop.name, true);
11468                            MangleClassName(propName);
11469
11470                            ListAdd(args, CopyExpression(object));
11471                            ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11472                            ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11473                            ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11474                         }
11475                         else
11476                            Compiler_Error("Property %s not found in class %s\n", prop.name, _class.fullName);
11477                      }
11478                   }
11479
11480                   if(object)
11481                      FreeExpression(object);
11482                   if(watcher)
11483                      FreeExpression(watcher);
11484                   FreeList(watches, FreeIdentifier);
11485                }
11486                else
11487                   Compiler_Error("Invalid object specified and not inside a class\n");
11488             }
11489             else
11490                Compiler_Error("No observer specified and not inside a class\n");
11491          }
11492          break;
11493       }
11494    }
11495 }
11496
11497 static void ProcessFunction(FunctionDefinition function)
11498 {
11499    Identifier id = GetDeclId(function.declarator);
11500    Symbol symbol = function.declarator ? function.declarator.symbol : null;
11501    Type type = symbol ? symbol.type : null;
11502    Class oldThisClass = thisClass;
11503    Context oldTopContext = topContext;
11504
11505    yylloc = function.loc;
11506    // Process thisClass
11507    
11508    if(type && type.thisClass)
11509    {
11510       Symbol classSym = type.thisClass;
11511       Class _class = type.thisClass.registered;
11512       char className[1024];
11513       char structName[1024];
11514       Declarator funcDecl;
11515       Symbol thisSymbol;
11516
11517       bool typedObject = false;
11518
11519       if(_class && !_class.base)
11520       {
11521          _class = currentClass;
11522          if(_class && !_class.symbol)
11523             _class.symbol = FindClass(_class.fullName);
11524          classSym = _class ? _class.symbol : null;
11525          typedObject = true;
11526       }
11527
11528       thisClass = _class;
11529
11530       if(inCompiler && _class)
11531       {
11532          if(type.kind == functionType)
11533          {
11534             if(symbol.type.params.count == 1 && ((Type)symbol.type.params.first).kind == voidType)
11535             {
11536                //TypeName param = symbol.type.params.first;
11537                Type param = symbol.type.params.first;
11538                symbol.type.params.Remove(param);
11539                //FreeTypeName(param);
11540                FreeType(param);
11541             }
11542             if(type.classObjectType != classPointer)
11543             {
11544                symbol.type.params.Insert(null, MkClassType(_class.fullName));
11545                symbol.type.staticMethod = true;
11546                symbol.type.thisClass = null;
11547
11548                // HIGH DANGER: VERIFYING THIS...
11549                symbol.type.extraParam = false;
11550             }
11551          }
11552
11553          strcpy(className, "__ecereClass_");
11554          FullClassNameCat(className, _class.fullName, true);
11555
11556          MangleClassName(className);
11557
11558          structName[0] = 0;
11559          FullClassNameCat(structName, _class.fullName, false);
11560
11561          // [class] this
11562          
11563
11564          funcDecl = GetFuncDecl(function.declarator);
11565          if(funcDecl)
11566          {
11567             if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11568             {
11569                TypeName param = funcDecl.function.parameters->first;
11570                if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11571                {
11572                   funcDecl.function.parameters->Remove(param);
11573                   FreeTypeName(param);
11574                }
11575             }
11576
11577             // DANGER: Watch for this... Check if it's a Conversion?
11578             // if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11579             
11580             // WAS TRYING THIS FOR CONVERSION PROPERTIES ON NOHEAD CLASSES: if((_class.type == structClass) || function != (FunctionDefinition)symbol.externalSet)
11581             if(!function.propertyNoThis)
11582             {
11583                TypeName thisParam;
11584                
11585                if(type.classObjectType != classPointer)
11586                {
11587                   thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11588                   if(!funcDecl.function.parameters)
11589                      funcDecl.function.parameters = MkList();
11590                   funcDecl.function.parameters->Insert(null, thisParam);
11591                }
11592
11593                if(typedObject)
11594                {
11595                   if(type.classObjectType != classPointer)
11596                   {
11597                      if(type.byReference || _class.type == unitClass || _class.type == systemClass || _class.type == enumClass || _class.type == bitClass)
11598                         thisParam.declarator = MkDeclaratorPointer(MkPointer(null,null), thisParam.declarator);
11599                   }
11600
11601                   thisParam = TypeName
11602                   {
11603                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
11604                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
11605                   };
11606                   funcDecl.function.parameters->Insert(null, thisParam);
11607                }
11608             }
11609          }
11610
11611          if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11612          {
11613             InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11614             funcDecl = GetFuncDecl(initDecl.declarator);
11615             if(funcDecl)
11616             {
11617                if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11618                {
11619                   TypeName param = funcDecl.function.parameters->first;
11620                   if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11621                   {
11622                      funcDecl.function.parameters->Remove(param);
11623                      FreeTypeName(param);
11624                   }
11625                }
11626
11627                if(type.classObjectType != classPointer)
11628                {
11629                   // DANGER: Watch for this... Check if it's a Conversion?
11630                   if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11631                   {
11632                      TypeName thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11633
11634                      if(!funcDecl.function.parameters)
11635                         funcDecl.function.parameters = MkList();
11636                      funcDecl.function.parameters->Insert(null, thisParam);
11637                   }
11638                }
11639             }         
11640          }
11641       }
11642       
11643       // Add this to the context
11644       if(function.body)
11645       {
11646          if(type.classObjectType != classPointer)
11647          {
11648             thisSymbol = Symbol
11649             {
11650                string = CopyString("this");
11651                type = classSym ? MkClassType(classSym.string) : null; //_class.fullName);
11652             };
11653             function.body.compound.context.symbols.Add((BTNode)thisSymbol);
11654
11655             if(typedObject && thisSymbol.type)
11656             {
11657                thisSymbol.type.classObjectType = ClassObjectType::typedObject;
11658                thisSymbol.type.byReference = type.byReference;
11659                /*
11660                thisSymbol = Symbol { string = CopyString("class") };
11661                function.body.compound.context.symbols.Add(thisSymbol);
11662                */
11663             }
11664          }
11665       }
11666
11667       // Pointer to class data
11668       
11669       if(inCompiler && _class && (_class.type == normalClass /*|| _class.type == noHeadClass*/) && type.classObjectType != classPointer)
11670       {
11671          DataMember member = null;
11672          {
11673             Class base;
11674             for(base = _class; base && base.type != systemClass; base = base.next)
11675             {
11676                for(member = base.membersAndProperties.first; member; member = member.next)
11677                   if(!member.isProperty)
11678                      break;
11679                if(member)
11680                   break;
11681             }
11682          }
11683          for(member = _class.membersAndProperties.first; member; member = member.next)
11684             if(!member.isProperty)
11685                break;
11686          if(member)
11687          {
11688             char pointerName[1024];
11689    
11690             Declaration decl;
11691             Initializer initializer;
11692             Expression exp, bytePtr;
11693    
11694             strcpy(pointerName, "__ecerePointer_");
11695             FullClassNameCat(pointerName, _class.fullName, false);
11696             {
11697                char className[1024];
11698                strcpy(className, "__ecereClass_");
11699                FullClassNameCat(className, classSym.string, true);
11700                MangleClassName(className);
11701
11702                // Testing This
11703                DeclareClass(classSym, className);
11704             }
11705
11706             // ((byte *) this)
11707             bytePtr = QBrackets(MkExpCast(QMkType("char", QMkPtrDecl(null)), QMkExpId("this")));
11708
11709             if(_class.fixed)
11710             {
11711                char string[256];
11712                sprintf(string, "%d", _class.offset);
11713                exp = QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string)));
11714             }
11715             else
11716             {
11717                // ([bytePtr] + [className]->offset)
11718                exp = QBrackets(MkExpOp(bytePtr, '+',
11719                   MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
11720             }
11721
11722             // (this ? [exp] : 0)
11723             exp = QBrackets(QMkExpCond(QMkExpId("this"), exp, MkExpConstant("0")));
11724             exp.expType = Type
11725             {
11726                refCount = 1;
11727                kind = pointerType;
11728                type = Type { refCount = 1, kind = voidType };
11729             };
11730    
11731             if(function.body)
11732             {
11733                yylloc = function.body.loc;
11734                // ([structName] *) [exp]
11735                // initializer = MkInitializerAssignment(MkExpCast(QMkType(structName, QMkPtrDecl(null)), exp));
11736                initializer = MkInitializerAssignment(
11737                   MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), exp));
11738
11739                // [structName] * [pointerName] = [initializer];
11740                // decl = QMkDeclaration(structName, MkInitDeclarator(QMkPtrDecl(pointerName), initializer));
11741
11742                {
11743                   Context prevContext = curContext;
11744                   curContext = function.body.compound.context;
11745
11746                   decl = MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
11747                      MkListOne(MkInitDeclarator(QMkPtrDecl(pointerName), initializer)));
11748
11749                   curContext = prevContext;
11750                }
11751
11752                // WHY?
11753                decl.symbol = null;
11754
11755                if(!function.body.compound.declarations)
11756                   function.body.compound.declarations = MkList();
11757                function.body.compound.declarations->Insert(null, decl);
11758             }
11759          }
11760       }
11761       
11762
11763       // Loop through the function and replace undeclared identifiers
11764       // which are a member of the class (methods, properties or data)
11765       // by "this.[member]"
11766    }
11767    else
11768       thisClass = null;
11769
11770    if(id)
11771    {
11772       FreeSpecifier(id._class);
11773       id._class = null;
11774
11775       if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11776       {
11777          InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11778          id = GetDeclId(initDecl.declarator);
11779
11780          FreeSpecifier(id._class);
11781          id._class = null;
11782       }
11783    }
11784    if(function.body)
11785       topContext = function.body.compound.context;
11786    {
11787       FunctionDefinition oldFunction = curFunction;
11788       curFunction = function;
11789       if(function.body)
11790          ProcessStatement(function.body);
11791
11792       // If this is a property set and no firewatchers has been done yet, add one here
11793       if(inCompiler && function.propSet && !function.propSet.fireWatchersDone)
11794       {
11795          Statement prevCompound = curCompound;
11796          Context prevContext = curContext;
11797
11798          Statement fireWatchers = MkFireWatchersStmt(null, null);
11799          if(!function.body.compound.statements) function.body.compound.statements = MkList();
11800          ListAdd(function.body.compound.statements, fireWatchers);
11801
11802          curCompound = function.body;
11803          curContext = function.body.compound.context;
11804
11805          ProcessStatement(fireWatchers);
11806
11807          curContext = prevContext;
11808          curCompound = prevCompound;
11809
11810       }
11811
11812       curFunction = oldFunction;
11813    }
11814
11815    if(function.declarator)
11816    {
11817       ProcessDeclarator(function.declarator);
11818    }
11819
11820    topContext = oldTopContext;
11821    thisClass = oldThisClass;
11822 }
11823
11824 /////////// INSTANTIATIONS / DATA TYPES PASS /////////////////////////////////////////////
11825 static void ProcessClass(OldList definitions, Symbol symbol)
11826 {
11827    ClassDef def;
11828    External external = curExternal;
11829    Class regClass = symbol ? symbol.registered : null;
11830
11831    // Process all functions
11832    for(def = definitions.first; def; def = def.next)
11833    {
11834       if(def.type == functionClassDef)
11835       {
11836          if(def.function.declarator)
11837             curExternal = def.function.declarator.symbol.pointerExternal;
11838          else
11839             curExternal = external;
11840
11841          ProcessFunction((FunctionDefinition)def.function);
11842       }
11843       else if(def.type == declarationClassDef)
11844       {
11845          if(def.decl.type == instDeclaration)
11846          {
11847             thisClass = regClass;
11848             ProcessInstantiationType(def.decl.inst);
11849             thisClass = null;
11850          }
11851          // Testing this
11852          else
11853          {
11854             Class backThisClass = thisClass;
11855             if(regClass) thisClass = regClass;
11856             ProcessDeclaration(def.decl);
11857             thisClass = backThisClass;
11858          }
11859       }
11860       else if(def.type == defaultPropertiesClassDef && def.defProperties)
11861       {
11862          MemberInit defProperty;
11863
11864          // Add this to the context
11865          Symbol thisSymbol = Symbol
11866          {
11867             string = CopyString("this");
11868             type = regClass ? MkClassType(regClass.fullName) : null;
11869          };
11870          globalContext.symbols.Add((BTNode)thisSymbol);
11871          
11872          for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
11873          {
11874             thisClass = regClass;
11875             ProcessMemberInitData(defProperty, regClass, null, null, null, null);
11876             thisClass = null;
11877          }
11878
11879          globalContext.symbols.Remove((BTNode)thisSymbol);
11880          FreeSymbol(thisSymbol);
11881       }
11882       else if(def.type == propertyClassDef && def.propertyDef)
11883       {
11884          PropertyDef prop = def.propertyDef;
11885
11886          // Add this to the context
11887          /*
11888          Symbol thisSymbol = Symbol { string = CopyString("this"), type = MkClassType(regClass.fullName) };
11889          globalContext.symbols.Add(thisSymbol);
11890          */
11891          
11892          thisClass = regClass;
11893          if(prop.setStmt)
11894          {
11895             if(regClass)
11896             {
11897                Symbol thisSymbol
11898                {
11899                   string = CopyString("this");
11900                   type = MkClassType(regClass.fullName);
11901                };
11902                prop.setStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11903             }
11904
11905             curExternal = prop.symbol ? prop.symbol.externalSet : null;
11906             ProcessStatement(prop.setStmt);
11907          }
11908          if(prop.getStmt)
11909          {
11910             if(regClass)
11911             {
11912                Symbol thisSymbol
11913                {
11914                   string = CopyString("this");
11915                   type = MkClassType(regClass.fullName);
11916                };
11917                prop.getStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11918             }
11919
11920             curExternal = prop.symbol ? prop.symbol.externalGet : null;
11921             ProcessStatement(prop.getStmt);
11922          }
11923          if(prop.issetStmt)
11924          {
11925             if(regClass)
11926             {
11927                Symbol thisSymbol
11928                {
11929                   string = CopyString("this");
11930                   type = MkClassType(regClass.fullName);
11931                };
11932                prop.issetStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11933             }
11934
11935             curExternal = prop.symbol ? prop.symbol.externalIsSet : null;
11936             ProcessStatement(prop.issetStmt);
11937          }
11938
11939          thisClass = null;
11940
11941          /*
11942          globalContext.symbols.Remove(thisSymbol);
11943          FreeSymbol(thisSymbol);
11944          */
11945       }
11946       else if(def.type == propertyWatchClassDef && def.propertyWatch)
11947       {
11948          PropertyWatch propertyWatch = def.propertyWatch;
11949         
11950          thisClass = regClass;
11951          if(propertyWatch.compound)
11952          {
11953             Symbol thisSymbol
11954             {
11955                string = CopyString("this");
11956                type = MkClassType(regClass.fullName);
11957             };
11958
11959             propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
11960
11961             curExternal = null;
11962             ProcessStatement(propertyWatch.compound);
11963          }
11964          thisClass = null;
11965       }
11966    }
11967 }
11968
11969 void ComputeDataTypes()
11970 {
11971    External external;
11972    External temp { };
11973    currentClass = null;
11974
11975    containerClass = eSystem_FindClass(GetPrivateModule(), "Container");
11976
11977    temp.symbol = Symbol { id = -1000, idCode = -1000 };
11978
11979    // WHERE SHOULD THIS GO?
11980    // curExternal = ast->first;
11981    ast->Insert(null, temp);
11982
11983    curExternal = temp;
11984
11985    DeclareStruct("ecere::com::Class", false);
11986    DeclareStruct("ecere::com::Instance", false);
11987    DeclareStruct("ecere::com::Property", false);
11988    DeclareStruct("ecere::com::DataMember", false);
11989    DeclareStruct("ecere::com::Method", false);
11990    DeclareStruct("ecere::com::SerialBuffer", false);
11991    DeclareStruct("ecere::com::ClassTemplateArgument", false);
11992
11993    ast->Remove(temp);
11994
11995    for(external = ast->first; external; external = external.next)
11996    {
11997       afterExternal = curExternal = external;
11998       if(external.type == functionExternal)
11999       {
12000          currentClass = external.function._class;
12001          ProcessFunction(external.function);
12002       }
12003       // There shouldn't be any _class member access here anyways...
12004       else if(external.type == declarationExternal)
12005       {
12006          currentClass = null;
12007          ProcessDeclaration(external.declaration);
12008       }
12009       else if(external.type == classExternal)
12010       {
12011          ClassDefinition _class = external._class;
12012          currentClass = external.symbol.registered;
12013          if(_class.definitions)
12014          {
12015             ProcessClass(_class.definitions, _class.symbol);
12016          }
12017          if(inCompiler)
12018          {
12019             // Free class data...
12020             ast->Remove(external);
12021             delete external;
12022          }
12023       }
12024       else if(external.type == nameSpaceExternal)
12025       {
12026          thisNameSpace = external.id.string;
12027       }
12028    }
12029    currentClass = null;
12030    thisNameSpace = null;
12031
12032    delete temp.symbol;
12033    delete temp;
12034 }