compiler/libec: Fixed parsing memory leaks
[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                            if(exp.expType) FreeType(exp.expType);
7920                            exp.expType = exp.op.exp1.destType;
7921                            if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
7922                            success = true;
7923                         }
7924                         else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
7925                         {
7926                            if(exp.expType) FreeType(exp.expType);
7927                            exp.expType = exp.op.exp2.destType;
7928                            if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
7929                            success = true;
7930                         }
7931                      }
7932                      else if(!success)
7933                      {
7934                         if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
7935                         {
7936                            if(exp.expType) FreeType(exp.expType);
7937                            exp.expType = exp.op.exp2.destType;
7938                            if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
7939                            success = true;
7940                         }
7941                         else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
7942                         {
7943                            if(exp.expType) FreeType(exp.expType);
7944                            exp.expType = exp.op.exp1.destType;
7945                            if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
7946                            success = true;
7947                         }
7948                      }
7949                      if(!success)
7950                      {
7951                         char expString1[10240];
7952                         char expString2[10240];
7953                         char type1[1024];
7954                         char type2[1024];
7955                         expString1[0] = '\0';
7956                         expString2[0] = '\0';
7957                         type1[0] = '\0';
7958                         type2[0] = '\0';
7959                         if(inCompiler)
7960                         {
7961                            PrintExpression(exp.op.exp1, expString1);
7962                            ChangeCh(expString1, '\n', ' ');
7963                            PrintExpression(exp.op.exp2, expString2);
7964                            ChangeCh(expString2, '\n', ' ');
7965                            PrintType(exp.op.exp1.expType, type1, false, true);
7966                            PrintType(exp.op.exp2.expType, type2, false, true);
7967                         }
7968
7969                         Compiler_Warning("incompatible expressions %s (%s) and %s (%s)\n", expString1, type1, expString2, type2);
7970                      }
7971                   }
7972                }
7973                // ADDED THESE TWO FROM OUTSIDE useSideType CHECK
7974                else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type2 && type1 && type2.kind == classType && type1.kind != classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
7975                {
7976                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7977                   // Convert e.g. / 4 into / 4.0
7978                   exp.op.exp1.destType = type2._class.registered.dataType;
7979                   if(type2._class.registered.dataType)
7980                      type2._class.registered.dataType.refCount++;
7981                   CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
7982                   exp.expType = type2;
7983                   if(type2) type2.refCount++;
7984                }
7985                else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type1 && type2 && type1.kind == classType && type2.kind != classType && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
7986                {
7987                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7988                   // Convert e.g. / 4 into / 4.0
7989                   exp.op.exp2.destType = type1._class.registered.dataType;
7990                   if(type1._class.registered.dataType)
7991                      type1._class.registered.dataType.refCount++;
7992                   CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
7993                   exp.expType = type1;
7994                   if(type1) type1.refCount++;
7995                }
7996                else if(type1)
7997                {
7998                   bool valid = false;
7999
8000                   if(!boolResult && useSideUnit && type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8001                   {
8002                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8003
8004                      if(!type1._class.registered.dataType)
8005                         type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
8006                      exp.op.exp2.destType = type1._class.registered.dataType;
8007                      exp.op.exp2.destType.refCount++;
8008
8009                      CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8010                      type2 = exp.op.exp2.destType;
8011
8012                      exp.expType = type2;
8013                      type2.refCount++;
8014                   }
8015                   
8016                   if(!boolResult && useSideUnit && type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8017                   {
8018                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8019
8020                      if(!type2._class.registered.dataType)
8021                         type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
8022                      exp.op.exp1.destType = type2._class.registered.dataType;
8023                      exp.op.exp1.destType.refCount++;
8024
8025                      CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8026                      type1 = exp.op.exp1.destType;
8027                      exp.expType = type1;
8028                      type1.refCount++;
8029                   }
8030
8031                   // TESTING THIS NEW CODE
8032                   if(!boolResult || exp.op.op == '>' || exp.op.op == '<')
8033                   {
8034                      if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass && exp.op.exp2.expType)
8035                      {
8036                         if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false))
8037                         {
8038                            if(exp.expType) FreeType(exp.expType);
8039                            exp.expType = exp.op.exp1.expType;
8040                            if(exp.op.exp2.expType) exp.op.exp1.expType.refCount++;
8041                            valid = true;
8042                         }
8043                      }
8044
8045                      else if(type2 && (type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass && exp.op.exp1.expType))
8046                      {
8047                         if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false))
8048                         {
8049                            if(exp.expType) FreeType(exp.expType);
8050                            exp.expType = exp.op.exp2.expType;
8051                            if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8052                            valid = true;
8053                         }
8054                      }
8055                   }
8056
8057                   if(!valid)
8058                   {
8059                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8060                      exp.op.exp2.destType = type1;
8061                      type1.refCount++;
8062
8063                      /*
8064                      // Maybe this was meant to be an enum...
8065                      if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8066                      {
8067                         Type oldType = exp.op.exp2.expType;
8068                         exp.op.exp2.expType = null;
8069                         if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8070                            FreeType(oldType);
8071                         else
8072                            exp.op.exp2.expType = oldType;
8073                      }
8074                      */
8075
8076                      /*
8077                      // TESTING THIS HERE... LATEST ADDITION
8078                      if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8079                      {
8080                         if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8081                         exp.op.exp2.destType = type2._class.registered.dataType;
8082                         if(type2._class.registered.dataType)
8083                            type2._class.registered.dataType.refCount++;
8084                         CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8085                         
8086                         //exp.expType = type2._class.registered.dataType; //type2;
8087                         //if(type2) type2.refCount++;
8088                      }
8089
8090                      // TESTING THIS HERE... LATEST ADDITION
8091                      if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8092                      {
8093                         if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8094                         exp.op.exp1.destType = type1._class.registered.dataType;
8095                         if(type1._class.registered.dataType)
8096                            type1._class.registered.dataType.refCount++;
8097                         CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8098                         exp.expType = type1._class.registered.dataType; //type1;
8099                         if(type1) type1.refCount++;
8100                      }
8101                      */
8102
8103                      if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8104                      {
8105                         if(exp.expType) FreeType(exp.expType);
8106                         exp.expType = exp.op.exp2.destType;
8107                         if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8108                      }
8109                      else if(type1 && type2)
8110                      {
8111                         char expString1[10240];
8112                         char expString2[10240];
8113                         char type1String[1024];
8114                         char type2String[1024];
8115                         expString1[0] = '\0';
8116                         expString2[0] = '\0';
8117                         type1String[0] = '\0';
8118                         type2String[0] = '\0';
8119                         if(inCompiler)
8120                         {
8121                            PrintExpression(exp.op.exp1, expString1);
8122                            ChangeCh(expString1, '\n', ' ');
8123                            PrintExpression(exp.op.exp2, expString2);
8124                            ChangeCh(expString2, '\n', ' ');
8125                            PrintType(exp.op.exp1.expType, type1String, false, true);
8126                            PrintType(exp.op.exp2.expType, type2String, false, true);
8127                         }
8128
8129                         Compiler_Warning("incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
8130
8131                         if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8132                         {
8133                            exp.expType = exp.op.exp1.expType;
8134                            if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
8135                         }
8136                         else if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8137                         {
8138                            exp.expType = exp.op.exp2.expType;
8139                            if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8140                         }
8141                      }
8142                   }
8143                }
8144                else if(type2)
8145                {
8146                   // Maybe this was meant to be an enum...
8147                   if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8148                   {
8149                      Type oldType = exp.op.exp1.expType;
8150                      exp.op.exp1.expType = null;
8151                      if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8152                         FreeType(oldType);
8153                      else
8154                         exp.op.exp1.expType = oldType;
8155                   }
8156
8157                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8158                   exp.op.exp1.destType = type2;
8159                   type2.refCount++;
8160                   /*
8161                   // TESTING THIS HERE... LATEST ADDITION
8162                   if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8163                   {
8164                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8165                      exp.op.exp1.destType = type1._class.registered.dataType;
8166                      if(type1._class.registered.dataType)
8167                         type1._class.registered.dataType.refCount++;
8168                   }
8169
8170                   // TESTING THIS HERE... LATEST ADDITION
8171                   if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8172                   {
8173                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8174                      exp.op.exp2.destType = type2._class.registered.dataType;
8175                      if(type2._class.registered.dataType)
8176                         type2._class.registered.dataType.refCount++;
8177                   }
8178                   */
8179
8180                   if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8181                   {
8182                      if(exp.expType) FreeType(exp.expType);
8183                      exp.expType = exp.op.exp1.destType;
8184                      if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8185                   }
8186                }
8187             }
8188             else if(type2 && (!type1 || (type2.kind == classType && type1.kind != classType)))
8189             {
8190                if(type1 && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
8191                {
8192                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8193                   // Convert e.g. / 4 into / 4.0
8194                   exp.op.exp1.destType = type2._class.registered.dataType;
8195                   if(type2._class.registered.dataType)
8196                      type2._class.registered.dataType.refCount++;
8197                   CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8198                }
8199                if(exp.op.op == '!')
8200                {
8201                   exp.expType = MkClassType("bool");
8202                   exp.expType.truth = true;
8203                }
8204                else
8205                {
8206                   exp.expType = type2;
8207                   if(type2) type2.refCount++;
8208                }
8209             }
8210             else if(type1 && (!type2 || (type1.kind == classType && type2.kind != classType)))
8211             {
8212                if(type2 && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
8213                {
8214                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8215                   // Convert e.g. / 4 into / 4.0
8216                   exp.op.exp2.destType = type1._class.registered.dataType;
8217                   if(type1._class.registered.dataType)
8218                      type1._class.registered.dataType.refCount++;
8219                   CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8220                }
8221                exp.expType = type1;
8222                if(type1) type1.refCount++;
8223             }
8224          }
8225          
8226          yylloc = exp.loc;
8227          if(exp.op.exp1 && !exp.op.exp1.expType)
8228          {
8229             char expString[10000];
8230             expString[0] = '\0';
8231             if(inCompiler)
8232             {
8233                PrintExpression(exp.op.exp1, expString);
8234                ChangeCh(expString, '\n', ' ');
8235             }
8236             if(expString[0])
8237                Compiler_Error("couldn't determine type of %s\n", expString);
8238          }
8239          if(exp.op.exp2 && !exp.op.exp2.expType)
8240          {
8241             char expString[10240];
8242             expString[0] = '\0';
8243             if(inCompiler)
8244             {
8245                PrintExpression(exp.op.exp2, expString);
8246                ChangeCh(expString, '\n', ' ');
8247             }
8248             if(expString[0])
8249                Compiler_Error("couldn't determine type of %s\n", expString);
8250          }
8251
8252          if(boolResult)
8253          {
8254             FreeType(exp.expType);
8255             exp.expType = MkClassType("bool");
8256             exp.expType.truth = true;
8257          }
8258
8259          if(exp.op.op != SIZEOF)
8260             exp.isConstant = (!exp.op.exp1 || exp.op.exp1.isConstant) &&
8261                (!exp.op.exp2 || exp.op.exp2.isConstant);
8262
8263          if(exp.op.op == SIZEOF && exp.op.exp2.expType)
8264          {
8265             DeclareType(exp.op.exp2.expType, false, false);
8266          }
8267
8268          yylloc = oldyylloc;
8269
8270          FreeType(dummy);
8271          break;
8272       }
8273       case bracketsExp:
8274       case extensionExpressionExp:
8275       {
8276          Expression e;
8277          exp.isConstant = true;
8278          for(e = exp.list->first; e; e = e.next)
8279          {
8280             bool inced = false;
8281             if(!e.next)
8282             {
8283                FreeType(e.destType);
8284                e.destType = exp.destType;
8285                if(e.destType) { exp.destType.refCount++; e.destType.count++; inced = true; }
8286             }
8287             ProcessExpressionType(e);
8288             if(inced)
8289                exp.destType.count--;
8290             if(!exp.expType && !e.next)
8291             {
8292                exp.expType = e.expType;
8293                if(e.expType) e.expType.refCount++;
8294             }
8295             if(!e.isConstant)
8296                exp.isConstant = false;
8297          }
8298
8299          // In case a cast became a member...
8300          e = exp.list->first;
8301          if(!e.next && e.type == memberExp)
8302          {
8303             // Preserve prev, next
8304             Expression next = exp.next, prev = exp.prev;
8305
8306
8307             FreeType(exp.expType);
8308             FreeType(exp.destType);
8309             delete exp.list;
8310             
8311             *exp = *e;
8312
8313             exp.prev = prev;
8314             exp.next = next;
8315
8316             delete e;
8317
8318             ProcessExpressionType(exp);
8319          }
8320          break;
8321       }
8322       case indexExp:
8323       {
8324          Expression e;
8325          exp.isConstant = true;
8326
8327          ProcessExpressionType(exp.index.exp);
8328          if(!exp.index.exp.isConstant)
8329             exp.isConstant = false;
8330
8331          if(exp.index.exp.expType)
8332          {
8333             Type source = exp.index.exp.expType;
8334             if(source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
8335                eClass_IsDerived(source._class.registered, containerClass) && 
8336                source._class.registered.templateArgs)
8337             {
8338                Class _class = source._class.registered;
8339                exp.expType = ProcessTypeString(_class.templateArgs[2].dataTypeString, false);
8340
8341                if(exp.index.index && exp.index.index->last)
8342                {
8343                   ((Expression)exp.index.index->last).destType = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
8344                }
8345             }
8346          }
8347
8348          for(e = exp.index.index->first; e; e = e.next)
8349          {
8350             if(!e.next && exp.index.exp.expType && exp.index.exp.expType.kind == arrayType && exp.index.exp.expType.enumClass)
8351             {
8352                if(e.destType) FreeType(e.destType);
8353                e.destType = MkClassType(exp.index.exp.expType.enumClass.string);
8354             }
8355             ProcessExpressionType(e);
8356             if(!e.next)
8357             {
8358                // Check if this type is int
8359             }
8360             if(!e.isConstant)
8361                exp.isConstant = false;
8362          }
8363
8364          if(!exp.expType)
8365             exp.expType = Dereference(exp.index.exp.expType);
8366          if(exp.expType)
8367             DeclareType(exp.expType, false, false);
8368          break;
8369       }
8370       case callExp:
8371       {
8372          Expression e;
8373          Type functionType;
8374          Type methodType = null;
8375          char name[1024];
8376          name[0] = '\0';
8377
8378          if(inCompiler)
8379          {
8380             PrintExpression(exp.call.exp,  name);
8381             if(exp.call.exp.expType && !exp.call.exp.expType.returnType)
8382             {
8383                //exp.call.exp.expType = null;
8384                PrintExpression(exp.call.exp,  name);
8385             }
8386          }
8387          if(exp.call.exp.type == identifierExp)
8388          {
8389             Expression idExp = exp.call.exp;
8390             Identifier id = idExp.identifier;
8391             if(!strcmp(id.string, "__ENDIAN_PAD"))
8392             {
8393                exp.expType = ProcessTypeString("int", true);
8394                if(exp.call.arguments && exp.call.arguments->first)
8395                   ProcessExpressionType(exp.call.arguments->first);
8396                break;
8397             }
8398             else if(!strcmp(id.string, "Max") ||
8399                !strcmp(id.string, "Min") ||
8400                !strcmp(id.string, "Sgn") ||
8401                !strcmp(id.string, "Abs"))
8402             {
8403                Expression a = null;
8404                Expression b = null;
8405                Expression tempExp1 = null, tempExp2 = null;
8406                if((!strcmp(id.string, "Max") ||
8407                   !strcmp(id.string, "Min")) && exp.call.arguments->count == 2)
8408                {
8409                   a = exp.call.arguments->first;
8410                   b = exp.call.arguments->last;
8411                   tempExp1 = a;
8412                   tempExp2 = b;
8413                }
8414                else if(exp.call.arguments->count == 1)
8415                {
8416                   a = exp.call.arguments->first;
8417                   tempExp1 = a;
8418                }
8419                
8420                if(a)
8421                {
8422                   exp.call.arguments->Clear();
8423                   idExp.identifier = null;
8424
8425                   FreeExpContents(exp);
8426
8427                   ProcessExpressionType(a);
8428                   if(b)
8429                      ProcessExpressionType(b);
8430
8431                   exp.type = bracketsExp;
8432                   exp.list = MkList();
8433
8434                   if(a.expType && (!b || b.expType))
8435                   {
8436                      if((!a.isConstant && a.type != identifierExp) || (b && !b.isConstant && b.type != identifierExp))
8437                      {
8438                         // Use the simpleStruct name/ids for now...
8439                         if(inCompiler)
8440                         {
8441                            OldList * specs = MkList();
8442                            OldList * decls = MkList();
8443                            Declaration decl;
8444                            char temp1[1024], temp2[1024];
8445
8446                            GetTypeSpecs(a.expType, specs);
8447
8448                            if(a && !a.isConstant && a.type != identifierExp)
8449                            {
8450                               sprintf(temp1, "__simpleStruct%d", curContext.simpleID++);
8451                               ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp1)), null));
8452                               tempExp1 = QMkExpId(temp1);
8453                               tempExp1.expType = a.expType;
8454                               if(a.expType)
8455                                  a.expType.refCount++;
8456                               ListAdd(exp.list, MkExpOp(CopyExpression(tempExp1), '=', a));
8457                            }
8458                            if(b && !b.isConstant && b.type != identifierExp)
8459                            {
8460                               sprintf(temp2, "__simpleStruct%d", curContext.simpleID++);
8461                               ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp2)), null));
8462                               tempExp2 = QMkExpId(temp2);
8463                               tempExp2.expType = b.expType;
8464                               if(b.expType)
8465                                  b.expType.refCount++;
8466                               ListAdd(exp.list, MkExpOp(CopyExpression(tempExp2), '=', b));
8467                            }                        
8468
8469                            decl = MkDeclaration(specs, decls);
8470                            if(!curCompound.compound.declarations)
8471                               curCompound.compound.declarations = MkList();
8472                            curCompound.compound.declarations->Insert(null, decl);
8473                         }
8474                      }
8475                   }
8476
8477                   if(!strcmp(id.string, "Max") || !strcmp(id.string, "Min"))
8478                   {
8479                      int op = (!strcmp(id.string, "Max")) ? '>' : '<';
8480                      ListAdd(exp.list, 
8481                         MkExpCondition(MkExpBrackets(MkListOne(
8482                            MkExpOp(CopyExpression(tempExp1), op, CopyExpression(tempExp2)))),
8483                            MkListOne(CopyExpression(tempExp1)), CopyExpression(tempExp2)));
8484                      exp.expType = a.expType;
8485                      if(a.expType)
8486                         a.expType.refCount++;
8487                   }
8488                   else if(!strcmp(id.string, "Abs"))
8489                   {
8490                      ListAdd(exp.list, 
8491                         MkExpCondition(MkExpBrackets(MkListOne(
8492                            MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8493                            MkListOne(MkExpOp(null, '-', CopyExpression(tempExp1))), CopyExpression(tempExp1)));
8494                      exp.expType = a.expType;
8495                      if(a.expType)
8496                         a.expType.refCount++;
8497                   }
8498                   else if(!strcmp(id.string, "Sgn"))
8499                   {
8500                      // ((!(a))?(0):(((a)<0)?(-1):(1)))
8501                      ListAdd(exp.list, 
8502                         MkExpCondition(MkExpBrackets(MkListOne(
8503                            MkExpOp(null, '!', CopyExpression(tempExp1)))), MkListOne(MkExpConstant("0")),
8504                               MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(
8505                                  MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8506                                  MkListOne(MkExpConstant("-1")), MkExpConstant("1"))))));
8507                      exp.expType = ProcessTypeString("int", false);
8508                   }
8509
8510                   FreeExpression(tempExp1);
8511                   if(tempExp2) FreeExpression(tempExp2);
8512
8513                   FreeIdentifier(id);
8514                   break;
8515                }
8516             }
8517          }
8518
8519          {
8520             Type dummy
8521             {
8522                count = 1;
8523                refCount = 1;
8524             };
8525             if(!exp.call.exp.destType)
8526             {
8527                exp.call.exp.destType = dummy;
8528                dummy.refCount++;
8529             }
8530             ProcessExpressionType(exp.call.exp);
8531             if(exp.call.exp.destType == dummy)
8532             {
8533                FreeType(dummy);
8534                exp.call.exp.destType = null;
8535             }
8536             FreeType(dummy);
8537          }
8538
8539          // Check argument types against parameter types
8540          functionType = exp.call.exp.expType;
8541
8542          if(functionType && functionType.kind == TypeKind::methodType)
8543          {
8544             methodType = functionType;
8545             functionType = methodType.method.dataType;
8546             
8547             //if(functionType.returnType && functionType.returnType.kind == thisClassType)
8548             // TOCHECK: Instead of doing this here could this be done per param?
8549             if(exp.call.exp.expType.usedClass)
8550             {
8551                char typeString[1024];
8552                typeString[0] = '\0';
8553                PrintType(functionType, typeString, true, true);
8554                if(strstr(typeString, "thisclass"))
8555                {
8556                   OldList * specs = MkList();
8557                   Declarator decl;
8558                   {
8559                      Context context = SetupTemplatesContext(exp.call.exp.expType.usedClass);
8560
8561                      decl = SpecDeclFromString(typeString, specs, null);
8562                      
8563                      // SET THIS TO FALSE WHEN PROCESSING THISCLASS OUTSIDE THE CLASS
8564                      if(thisClass != (exp.call.exp.expType.usedClass.templateClass ? exp.call.exp.expType.usedClass.templateClass :
8565                         exp.call.exp.expType.usedClass))
8566                         thisClassParams = false;
8567                      
8568                      ReplaceThisClassSpecifiers(specs, exp.call.exp.expType.usedClass);
8569                      {
8570                         Class backupThisClass = thisClass;
8571                         thisClass = exp.call.exp.expType.usedClass;
8572                         ProcessDeclarator(decl);
8573                         thisClass = backupThisClass;
8574                      }
8575
8576                      thisClassParams = true;
8577
8578                      functionType = ProcessType(specs, decl);
8579                      functionType.refCount = 0;
8580                      FinishTemplatesContext(context);
8581                   }
8582
8583                   FreeList(specs, FreeSpecifier);
8584                   FreeDeclarator(decl);
8585                 }
8586             }
8587          }
8588          if(functionType && functionType.kind == pointerType && functionType.type && functionType.type.kind == TypeKind::functionType)
8589          {
8590             Type type = functionType.type;
8591             if(!functionType.refCount)
8592             {
8593                functionType.type = null;
8594                FreeType(functionType);
8595             }
8596             //methodType = functionType;
8597             functionType = type;
8598          }
8599          if(functionType && functionType.kind != TypeKind::functionType)
8600          {
8601             Compiler_Error("called object %s is not a function\n", name);
8602          }
8603          else if(functionType)
8604          {
8605             bool emptyParams = false, noParams = false;
8606             Expression e = exp.call.arguments ? exp.call.arguments->first : null;
8607             Type type = functionType.params.first;
8608             Expression memberExp = (exp.call.exp.type == ExpressionType::memberExp) ? exp.call.exp : null;
8609             int extra = 0;
8610             Location oldyylloc = yylloc;
8611
8612             if(!type) emptyParams = true;
8613
8614             // WORKING ON THIS:
8615             if(functionType.extraParam && e)
8616             {
8617                e.destType = MkClassType(functionType.thisClass.string);
8618                e = e.next;
8619             }
8620
8621             // WHY WAS THIS COMMENTED OUT ? Broke DisplaySystem::FontExtent(this ? displaySystem : null, font, text, len, width, height);
8622             if(!functionType.staticMethod)
8623             {
8624                if(memberExp && memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.kind == subClassType && 
8625                   memberExp.member.exp.expType._class)
8626                {
8627                   type = MkClassType(memberExp.member.exp.expType._class.string);
8628                   if(e)
8629                   {
8630                      e.destType = type;
8631                      e = e.next;
8632                      type = functionType.params.first;
8633                   }
8634                   else
8635                      type.refCount = 0;
8636                }
8637                else if(!memberExp && (functionType.thisClass || (methodType && methodType.methodClass)))
8638                {
8639                   type = MkClassType(functionType.thisClass ? functionType.thisClass.string : (methodType ? methodType.methodClass.fullName : null));
8640                   if(e)
8641                   {
8642                      e.destType = type;
8643                      e = e.next;
8644                      type = functionType.params.first;
8645                   }
8646                   else
8647                      type.refCount = 0;
8648                   //extra = 1;
8649                }
8650             }
8651
8652             if(type && type.kind == voidType)
8653             {
8654                noParams = true;
8655                if(!type.refCount) FreeType(type);
8656                type = null;
8657             }
8658
8659             for( ; e; e = e.next)
8660             {
8661                if(!type && !emptyParams)
8662                {
8663                   yylloc = e.loc;
8664                   if(methodType && methodType.methodClass)
8665                      Compiler_Error("too many arguments for method %s::%s (%d given, expected %d)\n",
8666                         methodType.methodClass.fullName, methodType.method.name, exp.call.arguments->count,
8667                         noParams ? 0 : functionType.params.count);
8668                   else
8669                      Compiler_Error("too many arguments for function %s (%d given, expected %d)\n",
8670                         name /*exp.call.exp.identifier.string*/, exp.call.arguments->count,
8671                         noParams ? 0 : functionType.params.count);
8672                   break;
8673                }
8674
8675                if(methodType && type && type.kind == templateType && type.templateParameter.type == TemplateParameterType::type)
8676                {
8677                   Type templatedType = null;
8678                   Class _class = methodType.usedClass;
8679                   ClassTemplateParameter curParam = null;
8680                   int id = 0;
8681                   if(_class && _class.templateArgs /*&& _class.templateClass*/)
8682                   {
8683                      Class sClass;
8684                      for(sClass = _class; sClass; sClass = sClass.base)
8685                      {
8686                         if(sClass.templateClass) sClass = sClass.templateClass;
8687                         id = 0;
8688                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
8689                         {
8690                            if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
8691                            {
8692                               Class nextClass;
8693                               for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
8694                               {
8695                                  if(nextClass.templateClass) nextClass = nextClass.templateClass;
8696                                  id += nextClass.templateParams.count;
8697                               }
8698                               break;
8699                            }
8700                            id++;
8701                         }
8702                         if(curParam) break;
8703                      }
8704                   }
8705                   if(curParam && _class.templateArgs[id].dataTypeString)
8706                   {
8707                      ClassTemplateArgument arg = _class.templateArgs[id];
8708                      {
8709                         Context context = SetupTemplatesContext(_class);
8710                      
8711                         /*if(!arg.dataType)
8712                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
8713                         templatedType = ProcessTypeString(arg.dataTypeString, false);
8714                         FinishTemplatesContext(context);
8715                      }
8716                      e.destType = templatedType;
8717                      if(templatedType)
8718                      {
8719                         templatedType.passAsTemplate = true;
8720                         // templatedType.refCount++;
8721                      }
8722                   }
8723                   else
8724                   {
8725                      e.destType = type;
8726                      if(type) type.refCount++;
8727                   }
8728                }
8729                else
8730                {
8731                   e.destType = type;
8732                   if(type) type.refCount++;
8733                }
8734                // Don't reach the end for the ellipsis
8735                if(type && type.kind != ellipsisType)
8736                {
8737                   Type next = type.next;
8738                   if(!type.refCount) FreeType(type);
8739                   type = next;
8740                }
8741             }
8742
8743             if(type && type.kind != ellipsisType)
8744             {
8745                if(methodType && methodType.methodClass)
8746                   Compiler_Warning("not enough arguments for method %s::%s (%d given, expected %d)\n",
8747                      methodType.methodClass.fullName, methodType.method.name, exp.call.arguments ? exp.call.arguments->count : 0,
8748                      functionType.params.count + extra);
8749                else
8750                   Compiler_Warning("not enough arguments for function %s (%d given, expected %d)\n",
8751                      name /*exp.call.exp.identifier.string*/, exp.call.arguments ? exp.call.arguments->count : 0,
8752                      functionType.params.count + extra);
8753             }
8754             yylloc = oldyylloc;
8755             if(type && !type.refCount) FreeType(type);
8756          }
8757          else
8758          {
8759             functionType = Type
8760             {
8761                refCount = 0;
8762                kind = TypeKind::functionType;
8763             };
8764
8765             if(exp.call.exp.type == identifierExp)
8766             {
8767                char * string = exp.call.exp.identifier.string;
8768                if(inCompiler)
8769                {
8770                   Symbol symbol;
8771                   Location oldyylloc = yylloc;
8772
8773                   yylloc = exp.call.exp.identifier.loc;
8774                   if(strstr(string, "__builtin_") == string);
8775                   else
8776                      Compiler_Warning("%s undefined; assuming extern returning int\n", string);
8777                   symbol = Symbol { string = CopyString(string), type = ProcessTypeString("int()", true) };
8778                   globalContext.symbols.Add((BTNode)symbol);
8779
8780                   yylloc = oldyylloc;
8781                }
8782             }
8783             else if(exp.call.exp.type == memberExp)
8784             {
8785                /*Compiler_Warning("%s undefined; assuming returning int\n",
8786                   exp.call.exp.member.member.string);*/
8787             }
8788             else
8789                Compiler_Warning("callable object undefined; extern assuming returning int\n");
8790
8791             if(!functionType.returnType)
8792             {
8793                functionType.returnType = Type
8794                {
8795                   refCount = 1;
8796                   kind = intType;
8797                };
8798             }
8799          }
8800          if(functionType && functionType.kind == TypeKind::functionType)
8801          {
8802             exp.expType = functionType.returnType;
8803
8804             if(functionType.returnType)
8805                functionType.returnType.refCount++;
8806
8807             if(!functionType.refCount)
8808                FreeType(functionType);
8809          }
8810
8811          if(exp.call.arguments)
8812          {
8813             for(e = exp.call.arguments->first; e; e = e.next)
8814             {
8815                Type destType = e.destType;
8816                ProcessExpressionType(e);
8817             }
8818          }
8819          break;
8820       }
8821       case memberExp:
8822       {
8823          Type type;
8824          Location oldyylloc = yylloc;
8825          bool thisPtr = (exp.member.exp && exp.member.exp.type == identifierExp && !strcmp(exp.member.exp.identifier.string, "this"));
8826          exp.thisPtr = thisPtr;
8827
8828          // DOING THIS LATER NOW...
8829          if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
8830          {
8831             exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
8832             /* TODO: Name Space Fix ups
8833             if(!exp.member.member.classSym)
8834                exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.fullName);
8835             */
8836          }
8837
8838          ProcessExpressionType(exp.member.exp);
8839          if(exp.member.exp.expType && exp.member.exp.expType.kind == classType && exp.member.exp.expType._class && 
8840             exp.member.exp.expType._class.registered && exp.member.exp.expType._class.registered.type == normalClass)
8841          {
8842             exp.isConstant = false;
8843          }
8844          else
8845             exp.isConstant = exp.member.exp.isConstant;
8846          type = exp.member.exp.expType;
8847
8848          yylloc = exp.loc;
8849
8850          if(type && (type.kind == templateType))
8851          {
8852             Class _class = thisClass ? thisClass : currentClass;
8853             ClassTemplateParameter param = null;
8854             if(_class)
8855             {
8856                for(param = _class.templateParams.first; param; param = param.next)
8857                {
8858                   if(param.type == identifier && !strcmp(param.name, exp.member.member.string))
8859                      break;
8860                }
8861             }
8862             if(param && param.defaultArg.member)
8863             {
8864                Expression argExp = GetTemplateArgExpByName(param.name, thisClass, TemplateParameterType::identifier);
8865                if(argExp)
8866                {
8867                   Expression expMember = exp.member.exp;
8868                   Declarator decl;
8869                   OldList * specs = MkList();
8870                   char thisClassTypeString[1024];
8871
8872                   FreeIdentifier(exp.member.member);
8873
8874                   ProcessExpressionType(argExp);
8875
8876                   {
8877                      char * colon = strstr(param.defaultArg.memberString, "::");
8878                      if(colon)
8879                      {
8880                         char className[1024];
8881                         Class sClass;
8882
8883                         memcpy(thisClassTypeString, param.defaultArg.memberString, colon - param.defaultArg.memberString);
8884                         thisClassTypeString[colon - param.defaultArg.memberString] = '\0';
8885                      }
8886                      else
8887                         strcpy(thisClassTypeString, _class.fullName);
8888                   }
8889
8890                   decl = SpecDeclFromString(param.defaultArg.member.dataTypeString, specs, null);
8891
8892                   exp.expType = ProcessType(specs, decl);
8893                   if(exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.templateClass)
8894                   {
8895                      Class expClass = exp.expType._class.registered;
8896                      Class cClass = null;
8897                      int c;
8898                      int paramCount = 0;
8899                      int lastParam = -1;
8900                      
8901                      char templateString[1024];
8902                      ClassTemplateParameter param;
8903                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
8904                      for(cClass = expClass; cClass; cClass = cClass.base)
8905                      {
8906                         int p = 0;
8907                         for(param = cClass.templateParams.first; param; param = param.next)
8908                         {
8909                            int id = p;
8910                            Class sClass;
8911                            ClassTemplateArgument arg;
8912                            for(sClass = cClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
8913                            arg = expClass.templateArgs[id];
8914
8915                            for(sClass = _class /*expClass*/; sClass; sClass = sClass.base)
8916                            {
8917                               ClassTemplateParameter cParam;
8918                               //int p = numParams - sClass.templateParams.count;
8919                               int p = 0;
8920                               Class nextClass;
8921                               for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
8922                               
8923                               for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
8924                               {
8925                                  if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
8926                                  {
8927                                     if(_class.templateArgs && arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
8928                                     {
8929                                        arg.dataTypeString = _class.templateArgs[p].dataTypeString;
8930                                        arg.dataTypeClass = _class.templateArgs[p].dataTypeClass;
8931                                        break;
8932                                     }
8933                                  }
8934                               }
8935                            }
8936
8937                            {
8938                               char argument[256];
8939                               argument[0] = '\0';
8940                               /*if(arg.name)
8941                               {
8942                                  strcat(argument, arg.name.string);
8943                                  strcat(argument, " = ");
8944                               }*/
8945                               switch(param.type)
8946                               {
8947                                  case expression:
8948                                  {
8949                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
8950                                     char expString[1024];
8951                                     OldList * specs = MkList();
8952                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
8953                                     Expression exp;
8954                                     char * string = PrintHexUInt64(arg.expression.ui64);
8955                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
8956
8957                                     ProcessExpressionType(exp);
8958                                     ComputeExpression(exp);
8959                                     expString[0] = '\0';
8960                                     PrintExpression(exp, expString);
8961                                     strcat(argument, expString);
8962                                     // delete exp;
8963                                     FreeExpression(exp);
8964                                     break;
8965                                  }
8966                                  case identifier:
8967                                  {
8968                                     strcat(argument, arg.member.name);
8969                                     break;
8970                                  }
8971                                  case TemplateParameterType::type:
8972                                  {
8973                                     if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
8974                                     {
8975                                        if(!strcmp(arg.dataTypeString, "thisclass"))
8976                                           strcat(argument, thisClassTypeString);
8977                                        else
8978                                           strcat(argument, arg.dataTypeString);
8979                                     }
8980                                     break;
8981                                  }
8982                               }
8983                               if(argument[0])
8984                               {
8985                                  if(paramCount) strcat(templateString, ", ");
8986                                  if(lastParam != p - 1)
8987                                  {
8988                                     strcat(templateString, param.name);
8989                                     strcat(templateString, " = ");
8990                                  }
8991                                  strcat(templateString, argument);
8992                                  paramCount++;
8993                                  lastParam = p;
8994                               }
8995                               p++;
8996                            }               
8997                         }
8998                      }
8999                      {
9000                         int len = strlen(templateString);
9001                         if(templateString[len-1] == '>') templateString[len++] = ' ';
9002                         templateString[len++] = '>';
9003                         templateString[len++] = '\0';
9004                      }
9005                      {
9006                         Context context = SetupTemplatesContext(_class);
9007                         FreeType(exp.expType);
9008                         exp.expType = ProcessTypeString(templateString, false);
9009                         FinishTemplatesContext(context);
9010                      }                     
9011                   }
9012
9013                   // *([expType] *)(((byte *)[exp.member.exp]) + [argExp].member.offset)
9014                   exp.type = bracketsExp;
9015                   exp.list = MkListOne(MkExpOp(null, '*',
9016                   /*opExp;
9017                   exp.op.op = '*';
9018                   exp.op.exp1 = null;
9019                   exp.op.exp2 = */
9020                   MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpBrackets(MkListOne(MkExpOp(
9021                      MkExpBrackets(MkListOne(
9022                         MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), expMember))),
9023                            '+',  
9024                            MkExpOp(MkExpMember(MkExpMember(argExp, MkIdentifier("member")), MkIdentifier("offset")), 
9025                            '+',
9026                            MkExpMember(MkExpMember(MkExpMember(CopyExpression(argExp), MkIdentifier("member")), MkIdentifier("_class")), MkIdentifier("offset")))))))
9027                            
9028                            ));
9029                }
9030             }
9031             else if(type.templateParameter && type.templateParameter.type == TemplateParameterType::type && 
9032                (type.templateParameter.dataType || type.templateParameter.dataTypeString))
9033             {
9034                type = ProcessTemplateParameterType(type.templateParameter);
9035             }
9036          }
9037
9038          if(type && (type.kind == templateType));
9039          else if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9040          {
9041             Identifier id = exp.member.member;
9042             TypeKind typeKind = type.kind;
9043             Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9044             if(typeKind == subClassType && exp.member.exp.type == classExp)
9045             {
9046                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
9047                typeKind = classType;
9048             }
9049
9050             if(id && (typeKind == intType || typeKind == enumType))
9051                _class = eSystem_FindClass(privateModule, "int");
9052
9053             if(_class && id)
9054             {
9055                /*bool thisPtr = 
9056                   (exp.member.exp.type == identifierExp && 
9057                   !strcmp(exp.member.exp.identifier.string, "this"));*/
9058                Property prop = null;
9059                Method method = null;
9060                DataMember member = null;
9061                Property revConvert = null;
9062                ClassProperty classProp = null;
9063
9064                if(id && id._class && id._class.name && !strcmp(id._class.name, "property"))
9065                   exp.member.memberType = propertyMember;
9066
9067                if(id && id._class && type._class && !eClass_IsDerived(type._class.registered, _class))
9068                   Compiler_Error("invalid class specifier %s for object of class %s\n", _class.fullName, type._class.string);
9069
9070                if(typeKind != subClassType)
9071                {
9072                   // Prioritize data members over properties for "this"
9073                   if((exp.member.memberType == unresolvedMember && thisPtr) || exp.member.memberType == dataMember)
9074                   {
9075                      member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9076                      if(member && member._class != (_class.templateClass ? _class.templateClass : _class) && exp.member.memberType != dataMember)
9077                      {
9078                         prop = eClass_FindProperty(_class, id.string, privateModule);
9079                         if(prop)
9080                            member = null;
9081                      }
9082                      if(!member && !prop)
9083                         prop = eClass_FindProperty(_class, id.string, privateModule);
9084                      if((member && member._class == (_class.templateClass ? _class.templateClass : _class)) ||
9085                         (prop && prop._class == (_class.templateClass ? _class.templateClass : _class)))
9086                         exp.member.thisPtr = true;
9087                   }
9088                   // Prioritize properties over data members otherwise
9089                   else
9090                   {
9091                      // First look for Public Members (Unless class specifier is provided, which skips public priority)
9092                      if(!id.classSym)
9093                      {
9094                         prop = eClass_FindProperty(_class, id.string, null);
9095                         if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9096                            member = eClass_FindDataMember(_class, id.string, null, null, null);
9097                      }
9098
9099                      if(!prop && !member)
9100                      {
9101                         method = eClass_FindMethod(_class, id.string, null);
9102                         if(!method)
9103                         {
9104                            prop = eClass_FindProperty(_class, id.string, privateModule);
9105                            if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9106                               member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9107                         }
9108                      }
9109
9110                      if(member && prop)
9111                      {
9112                         if(member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class))
9113                            prop = null;
9114                         else
9115                            member = null;
9116                      }
9117                   }
9118                }
9119                if(!prop && !member)
9120                   method = eClass_FindMethod(_class, id.string, privateModule);
9121                if(!prop && !member && !method)
9122                {
9123                   if(typeKind == subClassType)
9124                   {
9125                      classProp = eClass_FindClassProperty(type._class.registered, exp.member.member.string);
9126                      if(classProp)
9127                      {
9128                         exp.member.memberType = classPropertyMember;
9129                         exp.expType = ProcessTypeString(classProp.dataTypeString, false);
9130                      }
9131                      else
9132                      {
9133                         // Assume this is a class_data member
9134                         char structName[1024];
9135                         Identifier id = exp.member.member;
9136                         Expression classExp = exp.member.exp;
9137                         type.refCount++;
9138
9139                         FreeType(classExp.expType);
9140                         classExp.expType = ProcessTypeString("ecere::com::Class", false);
9141                      
9142                         strcpy(structName, "__ecereClassData_");
9143                         FullClassNameCat(structName, type._class.string, false);
9144                         exp.type = pointerExp;
9145                         exp.member.member = id;
9146
9147                         exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9148                            MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), 
9149                               MkExpBrackets(MkListOne(MkExpOp(
9150                                  MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)), 
9151                                     MkExpMember(classExp, MkIdentifier("data"))), '+',
9152                                        MkExpMember(MkExpClass(MkListOne(MkSpecifierName(type._class.string)), null), MkIdentifier("offsetClass")))))
9153                                  )));
9154
9155                         FreeType(type);
9156
9157                         ProcessExpressionType(exp);
9158                         return;
9159                      }
9160                   }
9161                   else
9162                   {
9163                      // Check for reverse conversion
9164                      // (Convert in an instantiation later, so that we can use
9165                      //  deep properties system)
9166                      Symbol classSym = FindClass(id.string);
9167                      if(classSym)
9168                      {
9169                         Class convertClass = classSym.registered;
9170                         if(convertClass)
9171                            revConvert = eClass_FindProperty(convertClass, _class.fullName, privateModule);
9172                      }
9173                   }
9174                }
9175       
9176                if(prop)
9177                {
9178                   exp.member.memberType = propertyMember;
9179                   if(!prop.dataType)
9180                      ProcessPropertyType(prop);
9181                   exp.expType = prop.dataType;                     
9182                   if(prop.dataType) prop.dataType.refCount++;
9183                }
9184                else if(member)
9185                {
9186                   if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9187                   {
9188                      FreeExpContents(exp);
9189                      exp.type = identifierExp;
9190                      exp.identifier = MkIdentifier("class");
9191                      ProcessExpressionType(exp);
9192                      return;
9193                   }
9194
9195                   exp.member.memberType = dataMember;
9196                   DeclareStruct(_class.fullName, false);
9197                   if(!member.dataType)
9198                   {
9199                      Context context = SetupTemplatesContext(_class);
9200                      member.dataType = ProcessTypeString(member.dataTypeString, false);
9201                      FinishTemplatesContext(context);
9202                   }
9203                   exp.expType = member.dataType;
9204                   if(member.dataType) member.dataType.refCount++;
9205                }
9206                else if(revConvert)
9207                {
9208                   exp.member.memberType = reverseConversionMember;
9209                   exp.expType = MkClassType(revConvert._class.fullName);
9210                }
9211                else if(method)
9212                {
9213                   if(inCompiler)
9214                   {
9215                      /*if(id._class)
9216                      {
9217                         exp.type = identifierExp;
9218                         exp.identifier = exp.member.member;
9219                      }
9220                      else*/
9221                         exp.member.memberType = methodMember;
9222                   }
9223                   if(!method.dataType)
9224                      ProcessMethodType(method);
9225                   exp.expType = Type
9226                   {
9227                      refCount = 1;
9228                      kind = methodType;
9229                      method = method;
9230                   };
9231
9232                   // Tricky spot here... To use instance versus class virtual table
9233                   // Put it back to what it was... What did we break?
9234
9235                   // Had to put it back for overriding Main of Thread global instance
9236
9237                   //exp.expType.methodClass = _class;
9238                   exp.expType.methodClass = (id && id._class) ? _class : null;
9239
9240                   // Need the actual class used for templated classes
9241                   exp.expType.usedClass = _class;
9242                }
9243                else if(!classProp)
9244                {
9245                   if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9246                   {
9247                      FreeExpContents(exp);
9248                      exp.type = identifierExp;
9249                      exp.identifier = MkIdentifier("class");
9250                      ProcessExpressionType(exp);
9251                      return;
9252                   }
9253                   yylloc = exp.member.member.loc;
9254                   Compiler_Error("couldn't find member %s in class %s\n", id.string, _class.fullName);
9255                   if(inCompiler)
9256                      eClass_AddDataMember(_class, id.string, "int", 0, 0, publicAccess);
9257                }
9258
9259                if(_class && /*(_class.templateClass || _class.templateArgs) && */exp.expType)
9260                {
9261                   Class tClass;
9262
9263                   tClass = _class;
9264                   while(tClass && !tClass.templateClass) tClass = tClass.base;
9265
9266                   if(tClass && exp.expType.kind == templateType && exp.expType.templateParameter.type == TemplateParameterType::type)
9267                   {
9268                      int id = 0;
9269                      ClassTemplateParameter curParam;
9270                      Class sClass;
9271
9272                      for(sClass = tClass; sClass; sClass = sClass.base)
9273                      {
9274                         id = 0;
9275                         if(sClass.templateClass) sClass = sClass.templateClass;
9276                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9277                         {
9278                            if(curParam.type == TemplateParameterType::type && !strcmp(exp.expType.templateParameter.identifier.string, curParam.name))
9279                            {
9280                               for(sClass = sClass.base; sClass; sClass = sClass.base)
9281                                  id += sClass.templateParams.count;
9282                               break;
9283                            }
9284                            id++;
9285                         }
9286                         if(curParam) break;
9287                      }
9288
9289                      if(curParam && tClass.templateArgs[id].dataTypeString)
9290                      {
9291                         ClassTemplateArgument arg = tClass.templateArgs[id];
9292                         Context context = SetupTemplatesContext(tClass);
9293                         /*if(!arg.dataType)
9294                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9295                         FreeType(exp.expType);
9296                         exp.expType = ProcessTypeString(arg.dataTypeString, false);
9297                         if(exp.expType)
9298                         {
9299                            if(exp.expType.kind == thisClassType)
9300                            {
9301                               FreeType(exp.expType);
9302                               exp.expType = ReplaceThisClassType(_class);
9303                            }
9304
9305                            if(tClass.templateClass)
9306                               exp.expType.passAsTemplate = true;
9307                            //exp.expType.refCount++;
9308                            if(!exp.destType)
9309                            {
9310                               exp.destType = ProcessTypeString(arg.dataTypeString, false);
9311                               //exp.destType.refCount++;
9312
9313                               if(exp.destType.kind == thisClassType)
9314                               {
9315                                  FreeType(exp.destType);
9316                                  exp.destType = ReplaceThisClassType(_class);
9317                               }
9318                            }
9319                         }
9320                         FinishTemplatesContext(context);
9321                      }
9322                   }
9323                   // TODO: MORE GENERIC SUPPORT FOR DEEPER TYPES
9324                   else if(tClass && exp.expType.kind == pointerType && exp.expType.type && exp.expType.type.kind == templateType && exp.expType.type.templateParameter.type == TemplateParameterType::type)
9325                   {
9326                      int id = 0;
9327                      ClassTemplateParameter curParam;
9328                      Class sClass;
9329
9330                      for(sClass = tClass; sClass; sClass = sClass.base)
9331                      {
9332                         id = 0;
9333                         if(sClass.templateClass) sClass = sClass.templateClass;
9334                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9335                         {
9336                            if(curParam.type == TemplateParameterType::type && 
9337                               !strcmp(exp.expType.type.templateParameter.identifier.string, curParam.name))
9338                            {
9339                               for(sClass = sClass.base; sClass; sClass = sClass.base)
9340                                  id += sClass.templateParams.count;
9341                               break;
9342                            }
9343                            id++;
9344                         }
9345                         if(curParam) break;
9346                      }
9347
9348                      if(curParam)
9349                      {
9350                         ClassTemplateArgument arg = tClass.templateArgs[id];
9351                         Context context = SetupTemplatesContext(tClass);
9352                         Type basicType;
9353                         /*if(!arg.dataType)
9354                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9355                         
9356                         basicType = ProcessTypeString(arg.dataTypeString, false);
9357                         if(basicType)
9358                         {
9359                            if(basicType.kind == thisClassType)
9360                            {
9361                               FreeType(basicType);
9362                               basicType = ReplaceThisClassType(_class);
9363                            }
9364
9365                            /*    DO WE REALLY WANT THIS HERE? IT SEEMS TO BE ONLY USED WITH Array::array which was causing bug 135
9366                            if(tClass.templateClass)
9367                               basicType.passAsTemplate = true;
9368                            */
9369                            
9370                            FreeType(exp.expType);
9371
9372                            exp.expType = Type { refCount = 1, kind = pointerType, type = basicType };
9373                            //exp.expType.refCount++;
9374                            if(!exp.destType)
9375                            {
9376                               exp.destType = exp.expType;
9377                               exp.destType.refCount++;
9378                            }
9379
9380                            {
9381                               Expression newExp { };
9382                               OldList * specs = MkList();
9383                               Declarator decl;
9384                               decl = SpecDeclFromString(arg.dataTypeString, specs, null);
9385                               *newExp = *exp;
9386                               if(exp.destType) exp.destType.refCount++;
9387                               if(exp.expType)  exp.expType.refCount++;
9388                               exp.type = castExp;
9389                               exp.cast.typeName = MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl));
9390                               exp.cast.exp = newExp;
9391                               //FreeType(exp.expType);
9392                               //exp.expType = null;
9393                               //ProcessExpressionType(sourceExp);
9394                            }
9395                         }
9396                         FinishTemplatesContext(context);
9397                      }
9398                   }
9399                   else if(tClass && exp.expType.kind == classType && exp.expType._class && strchr(exp.expType._class.string, '<'))
9400                   {
9401                      Class expClass = exp.expType._class.registered;
9402                      if(expClass)
9403                      {
9404                         Class cClass = null;
9405                         int c;
9406                         int p = 0;
9407                         int paramCount = 0;
9408                         int lastParam = -1;
9409                         char templateString[1024];
9410                         ClassTemplateParameter param;
9411                         sprintf(templateString, "%s<", expClass.templateClass.fullName);
9412                         while(cClass != expClass)
9413                         {
9414                            Class sClass;
9415                            for(sClass = expClass; sClass && sClass.base != cClass; sClass = sClass.base);
9416                            cClass = sClass;
9417
9418                            for(param = cClass.templateParams.first; param; param = param.next)
9419                            {
9420                               Class cClassCur = null;
9421                               int c;
9422                               int cp = 0;
9423                               ClassTemplateParameter paramCur = null;
9424                               ClassTemplateArgument arg;
9425                               while(cClassCur != tClass && !paramCur)
9426                               {
9427                                  Class sClassCur;
9428                                  for(sClassCur = tClass; sClassCur && sClassCur.base != cClassCur; sClassCur = sClassCur.base);
9429                                  cClassCur = sClassCur;
9430
9431                                  for(paramCur = cClassCur.templateParams.first; paramCur; paramCur = paramCur.next)
9432                                  {
9433                                     if(!strcmp(paramCur.name, param.name))
9434                                     {
9435                                        
9436                                        break;
9437                                     }
9438                                     cp++;
9439                                  }
9440                               }
9441                               if(paramCur && paramCur.type == TemplateParameterType::type)
9442                                  arg = tClass.templateArgs[cp];
9443                               else
9444                                  arg = expClass.templateArgs[p];
9445
9446                               {
9447                                  char argument[256];
9448                                  argument[0] = '\0';
9449                                  /*if(arg.name)
9450                                  {
9451                                     strcat(argument, arg.name.string);
9452                                     strcat(argument, " = ");
9453                                  }*/
9454                                  switch(param.type)
9455                                  {
9456                                     case expression:
9457                                     {
9458                                        // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
9459                                        char expString[1024];
9460                                        OldList * specs = MkList();
9461                                        Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
9462                                        Expression exp;
9463                                        char * string = PrintHexUInt64(arg.expression.ui64);
9464                                        exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
9465
9466                                        ProcessExpressionType(exp);
9467                                        ComputeExpression(exp);
9468                                        expString[0] = '\0';
9469                                        PrintExpression(exp, expString);
9470                                        strcat(argument, expString);
9471                                        // delete exp;
9472                                        FreeExpression(exp);
9473                                        break;
9474                                     }
9475                                     case identifier:
9476                                     {
9477                                        strcat(argument, arg.member.name);
9478                                        break;
9479                                     }
9480                                     case TemplateParameterType::type:
9481                                     {
9482                                        if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9483                                           strcat(argument, arg.dataTypeString);
9484                                        break;
9485                                     }
9486                                  }
9487                                  if(argument[0])
9488                                  {
9489                                     if(paramCount) strcat(templateString, ", ");
9490                                     if(lastParam != p - 1)
9491                                     {
9492                                        strcat(templateString, param.name);
9493                                        strcat(templateString, " = ");
9494                                     }                                       
9495                                     strcat(templateString, argument);
9496                                     paramCount++;
9497                                     lastParam = p;
9498                                  }
9499                               }
9500                               p++;
9501                            }
9502                         }
9503                         {
9504                            int len = strlen(templateString);
9505                            if(templateString[len-1] == '>') templateString[len++] = ' ';
9506                            templateString[len++] = '>';
9507                            templateString[len++] = '\0';
9508                         }
9509
9510                         FreeType(exp.expType);
9511                         {
9512                            Context context = SetupTemplatesContext(tClass);
9513                            exp.expType = ProcessTypeString(templateString, false);
9514                            FinishTemplatesContext(context);
9515                         }
9516                      }
9517                   }
9518                }
9519             }
9520             else
9521                Compiler_Error("undefined class %s\n", (id && (!id._class || id._class.name))? (id.classSym ? id.classSym.string : (type._class ? type._class.string : null)) : "(null)");
9522          }
9523          else if(type && (type.kind == structType || type.kind == unionType))
9524          {
9525             Type memberType = exp.member.member ? FindMember(type, exp.member.member.string) : null;
9526             if(memberType)
9527             {
9528                exp.expType = memberType;
9529                if(memberType)
9530                   memberType.refCount++;
9531             }
9532          }
9533          else 
9534          {
9535             char expString[10240];
9536             expString[0] = '\0';
9537             if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
9538             Compiler_Error("member operator on non-structure type expression %s\n", expString);
9539          }
9540
9541          if(exp.expType && exp.expType.kind == thisClassType && (!exp.destType || exp.destType.kind != thisClassType))
9542          {
9543             if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9544             {
9545                Identifier id = exp.member.member;
9546                Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9547                if(_class)
9548                {
9549                   FreeType(exp.expType);
9550                   exp.expType = ReplaceThisClassType(_class);
9551                }
9552             }
9553          }         
9554          yylloc = oldyylloc;
9555          break;
9556       }
9557       // Convert x->y into (*x).y
9558       case pointerExp:
9559       {
9560          Type destType = exp.destType;
9561
9562          // DOING THIS LATER NOW...
9563          if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
9564          {
9565             exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
9566             /* TODO: Name Space Fix ups
9567             if(!exp.member.member.classSym)
9568                exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.name);
9569             */
9570          }
9571
9572          exp.member.exp = MkExpBrackets(MkListOne(MkExpOp(null, '*', exp.member.exp)));
9573          exp.type = memberExp;
9574          if(destType)
9575             destType.count++;
9576          ProcessExpressionType(exp);
9577          if(destType)
9578             destType.count--;
9579          break;
9580       }
9581       case classSizeExp:
9582       {
9583          //ComputeExpression(exp);
9584
9585          Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
9586          if(classSym && classSym.registered)
9587          {
9588             if(classSym.registered.type == noHeadClass)
9589             {
9590                char name[1024];
9591                name[0] = '\0';
9592                DeclareStruct(classSym.string, false);
9593                FreeSpecifier(exp._class);
9594                exp.type = typeSizeExp;
9595                FullClassNameCat(name, classSym.string, false);
9596                exp.typeName = MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null);
9597             }
9598             else
9599             {
9600                if(classSym.registered.fixed)
9601                {
9602                   FreeSpecifier(exp._class);
9603                   exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
9604                   exp.type = constantExp;
9605                }
9606                else
9607                {
9608                   char className[1024];
9609                   strcpy(className, "__ecereClass_");
9610                   FullClassNameCat(className, classSym.string, true);
9611                   MangleClassName(className);
9612
9613                   DeclareClass(classSym, className);
9614
9615                   FreeExpContents(exp);
9616                   exp.type = pointerExp;
9617                   exp.member.exp = MkExpIdentifier(MkIdentifier(className));
9618                   exp.member.member = MkIdentifier("structSize");
9619                }
9620             }
9621          }
9622
9623          exp.expType = Type
9624          {
9625             refCount = 1;
9626             kind = intType;
9627          };
9628          // exp.isConstant = true;
9629          break;
9630       }
9631       case typeSizeExp:
9632       {
9633          Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
9634
9635          exp.expType = Type
9636          {
9637             refCount = 1;
9638             kind = intType;
9639          };
9640          exp.isConstant = true;
9641
9642          DeclareType(type, false, false);
9643          FreeType(type);
9644          break;
9645       }
9646       case castExp:
9647       {
9648          Type type = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
9649          type.count = 1;
9650          FreeType(exp.cast.exp.destType);
9651          exp.cast.exp.destType = type;
9652          type.refCount++;
9653          ProcessExpressionType(exp.cast.exp);
9654          type.count = 0;
9655          exp.expType = type;
9656          //type.refCount++;
9657          
9658          // if(!NeedCast(exp.cast.exp.expType, exp.cast.exp.destType))
9659          if(!exp.cast.exp.needCast && !NeedCast(exp.cast.exp.expType, type))
9660          {
9661             void * prev = exp.prev, * next = exp.next;
9662             Type expType = exp.cast.exp.destType;
9663             Expression castExp = exp.cast.exp;
9664             Type destType = exp.destType;
9665
9666             if(expType) expType.refCount++;
9667
9668             //FreeType(exp.destType);
9669             FreeType(exp.expType);
9670             FreeTypeName(exp.cast.typeName);
9671             
9672             *exp = *castExp;
9673             FreeType(exp.expType);
9674             FreeType(exp.destType);
9675
9676             exp.expType = expType;
9677             exp.destType = destType;
9678
9679             delete castExp;
9680
9681             exp.prev = prev;
9682             exp.next = next;
9683
9684          }
9685          else
9686          {
9687             exp.isConstant = exp.cast.exp.isConstant;
9688          }
9689          //FreeType(type);
9690          break;
9691       }
9692       case extensionInitializerExp:
9693       {
9694          Type type = ProcessType(exp.initializer.typeName.qualifiers, exp.initializer.typeName.declarator);
9695          type.refCount++;
9696          // ProcessInitializer(exp.initializer.initializer, type);
9697          exp.expType = type;
9698          break;
9699       }
9700       case vaArgExp:
9701       {
9702          Type type = ProcessType(exp.vaArg.typeName.qualifiers, exp.vaArg.typeName.declarator);
9703          ProcessExpressionType(exp.vaArg.exp);
9704          type.refCount++;
9705          exp.expType = type;
9706          break;
9707       }
9708       case conditionExp:
9709       {
9710          Expression e;
9711          exp.isConstant = true;
9712
9713          FreeType(exp.cond.cond.destType);
9714          exp.cond.cond.destType = MkClassType("bool");
9715          exp.cond.cond.destType.truth = true;
9716          ProcessExpressionType(exp.cond.cond);
9717          if(!exp.cond.cond.isConstant)
9718             exp.isConstant = false;
9719          for(e = exp.cond.exp->first; e; e = e.next)
9720          {
9721             if(!e.next)
9722             {
9723                FreeType(e.destType);
9724                e.destType = exp.destType;
9725                if(e.destType) e.destType.refCount++;
9726             }
9727             ProcessExpressionType(e);
9728             if(!e.next)
9729             {
9730                exp.expType = e.expType;
9731                if(e.expType) e.expType.refCount++;
9732             }
9733             if(!e.isConstant)
9734                exp.isConstant = false;
9735          }
9736
9737          FreeType(exp.cond.elseExp.destType);
9738          // Added this check if we failed to find an expType
9739          // exp.cond.elseExp.destType = exp.expType ? exp.expType : exp.destType;
9740
9741          // Reversed it...
9742          exp.cond.elseExp.destType = exp.destType ? exp.destType : exp.expType;
9743
9744          if(exp.cond.elseExp.destType)
9745             exp.cond.elseExp.destType.refCount++;
9746          ProcessExpressionType(exp.cond.elseExp);
9747
9748          // FIXED THIS: Was done before calling process on elseExp
9749          if(!exp.cond.elseExp.isConstant)
9750             exp.isConstant = false;
9751          break;
9752       }
9753       case extensionCompoundExp:
9754       {
9755          if(exp.compound && exp.compound.compound.statements && exp.compound.compound.statements->last)
9756          {
9757             Statement last = exp.compound.compound.statements->last;
9758             if(last.type == expressionStmt && last.expressions && last.expressions->last)
9759             {
9760                ((Expression)last.expressions->last).destType = exp.destType;
9761                if(exp.destType)
9762                   exp.destType.refCount++;
9763             }
9764             ProcessStatement(exp.compound);
9765             exp.expType = ((Expression)last.expressions->last).expType;
9766             if(((Expression)last.expressions->last).expType)
9767                exp.expType.refCount++;
9768          }
9769          break;
9770       }
9771       case classExp:
9772       {
9773          Specifier spec = exp._classExp.specifiers->first;
9774          if(spec && spec.type == nameSpecifier)
9775          {
9776             exp.expType = MkClassType(spec.name);
9777             exp.expType.kind = subClassType;
9778             exp.byReference = true;
9779          }
9780          else
9781          {
9782             exp.expType = MkClassType("ecere::com::Class");
9783             exp.byReference = true;
9784          }
9785          break;
9786       }
9787       case classDataExp:
9788       {
9789          Class _class = thisClass ? thisClass : currentClass;
9790          if(_class)
9791          {
9792             Identifier id = exp.classData.id;
9793             char structName[1024];
9794             Expression classExp;
9795             strcpy(structName, "__ecereClassData_");
9796             FullClassNameCat(structName, _class.fullName, false);
9797             exp.type = pointerExp;
9798             exp.member.member = id;
9799             if(curCompound && FindSymbol("this", curContext, curCompound.compound.context, false, false))
9800                classExp = MkExpMember(MkExpIdentifier(MkIdentifier("this")), MkIdentifier("_class"));
9801             else
9802                classExp = MkExpIdentifier(MkIdentifier("class"));
9803
9804             exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9805                MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), 
9806                   MkExpBrackets(MkListOne(MkExpOp(
9807                      MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)), 
9808                         MkExpMember(classExp, MkIdentifier("data"))), '+',
9809                            MkExpMember(MkExpClass(MkListOne(MkSpecifierName(_class.fullName)), null), MkIdentifier("offsetClass")))))
9810                      )));
9811
9812             ProcessExpressionType(exp);
9813             return;
9814          }
9815          break;
9816       }
9817       case arrayExp:
9818       {
9819          Type type = null;
9820          char * typeString = null;
9821          char typeStringBuf[1024];
9822          if(exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
9823             exp.destType._class.registered != containerClass && eClass_IsDerived(exp.destType._class.registered, containerClass))
9824          {
9825             Class templateClass = exp.destType._class.registered;
9826             typeString = templateClass.templateArgs[2].dataTypeString;
9827          }
9828          else if(exp.list)
9829          {
9830             // Guess type from expressions in the array
9831             Expression e;
9832             for(e = exp.list->first; e; e = e.next)
9833             {
9834                ProcessExpressionType(e);
9835                if(e.expType)
9836                {
9837                   if(!type) { type = e.expType; type.refCount++; }
9838                   else
9839                   {
9840                      // if(!MatchType(e.expType, type, null, null, null, false, false, false))
9841                      if(!MatchTypeExpression(e, type, null, false))
9842                      {
9843                         FreeType(type);
9844                         type = e.expType;
9845                         e.expType = null;
9846                         
9847                         e = exp.list->first;
9848                         ProcessExpressionType(e);
9849                         if(e.expType)
9850                         {
9851                            //if(!MatchTypes(e.expType, type, null, null, null, false, false, false))
9852                            if(!MatchTypeExpression(e, type, null, false))
9853                            {
9854                               FreeType(e.expType);
9855                               e.expType = null;
9856                               FreeType(type);
9857                               type = null;
9858                               break;
9859                            }                           
9860                         }
9861                      }
9862                   }
9863                   if(e.expType)
9864                   {
9865                      FreeType(e.expType);
9866                      e.expType = null;
9867                   }
9868                }
9869             }
9870             if(type)
9871             {
9872                typeStringBuf[0] = '\0';
9873                PrintType(type, typeStringBuf, false, true);
9874                typeString = typeStringBuf;
9875                FreeType(type);
9876                type = null;
9877             }
9878          }
9879          if(typeString)
9880          {
9881             /*
9882             (Container)(__extension__( { 
9883                int __arrayMembers[] = { 1, 7, 3, 4, 5 };
9884                BuiltInContainer __baseContainer
9885                {
9886                   data = __arrayMembers,
9887                   count = 5,
9888                   type = class(int),
9889                   _vTbl = class(BuiltInContainer)._vTbl,
9890                   _class = class(BuiltInContainer) };
9891                &__baseContainer;
9892              }))
9893             */
9894             
9895             char templateString[1024];
9896             OldList * declarations = MkList();
9897             OldList * instMembers = MkList();
9898             OldList * specs = MkList();
9899             OldList * initializers = MkList();
9900             char count[128];
9901             Expression e;
9902             Expression expExt;
9903             Declarator decl = SpecDeclFromString(typeString, specs, null);
9904             Context context = PushContext();
9905
9906             // sprintf(templateString, "Container<%s >", typeString);
9907             sprintf(templateString, "Container<%s>", typeString);
9908    
9909             ListAdd(instMembers, MkMemberInit(MkListOne(MkIdentifier("data")), MkInitializerAssignment(MkExpIdentifier(MkIdentifier("__internalList")))));
9910
9911             sprintf(count, "%d", exp.list->count);
9912             ListAdd(instMembers, MkMemberInit(MkListOne(MkIdentifier("count")), MkInitializerAssignment(MkExpConstant(count))));
9913
9914             ListAdd(instMembers, MkMemberInit(MkListOne(MkIdentifier("type")), MkInitializerAssignment(MkExpClass(CopyList(specs, CopySpecifier), 
9915                CopyDeclarator(decl)))));
9916
9917             ListAdd(instMembers, MkMemberInit(MkListOne(MkIdentifier("_vTbl")), MkInitializerAssignment(MkExpMember(
9918                MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null), MkIdentifier("_vTbl")))));
9919
9920             ListAdd(instMembers, MkMemberInit(MkListOne(MkIdentifier("_class")), MkInitializerAssignment(
9921                MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null))));
9922
9923             if(exp.list)
9924             {
9925                type = ProcessTypeString(typeString, false);
9926                while(e = exp.list->first)
9927                {
9928                   exp.list->Remove(e);
9929                   e.destType = type;
9930                   type.refCount++;
9931                   ProcessExpressionType(e);
9932                   ListAdd(initializers, MkInitializerAssignment(e));
9933                }
9934                FreeType(type);
9935                delete exp.list;
9936             }
9937             
9938             ListAdd(declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorArray(PlugDeclarator(decl, 
9939                MkDeclaratorIdentifier(MkIdentifier("__internalList"))), null),
9940                MkInitializerList(initializers)))));
9941             ListAdd(declarations, MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName("BuiltInContainer")),
9942                MkExpIdentifier(MkIdentifier("__internalContainer")), MkListOne(MkMembersInitList(instMembers)))));
9943
9944             exp.expType = ProcessTypeString(templateString, false);
9945             exp.type = bracketsExp;
9946             exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(templateString)), null),
9947                (expExt = MkExpExtensionCompound(MkCompoundStmt(
9948                   declarations, MkListOne(MkExpressionStmt(MkListOne(MkExpOp(null, '&', MkExpIdentifier(MkIdentifier("__internalContainer")))))))))));
9949             expExt.compound.compound.context = context;
9950             PopContext(context);
9951             ProcessExpressionType(expExt);
9952          }
9953          else
9954          {
9955             exp.expType = ProcessTypeString("Container", false);
9956             Compiler_Error("Couldn't determine type of array elements\n");
9957          }
9958          break;
9959       }
9960    }
9961
9962    if(exp.expType && exp.expType.kind == thisClassType && thisClass && (!exp.destType || exp.destType.kind != thisClassType))
9963    {
9964       FreeType(exp.expType);
9965       exp.expType = ReplaceThisClassType(thisClass);
9966    }
9967
9968    // Resolve structures here
9969    if(exp.expType && (exp.expType.kind == structType || exp.expType.kind == unionType || exp.expType.kind == enumType) && !exp.expType.members.first && exp.expType.enumName)
9970    {
9971       Symbol symbol = FindSymbol(exp.expType.enumName, curContext, globalContext, true, false);
9972       // TODO: Fix members reference...
9973       if(symbol)
9974       {
9975          if(exp.expType.kind != enumType)
9976          {
9977             Type member;
9978             exp.expType.members = symbol.type.members;
9979             for(member = symbol.type.members.first; member; member = member.next)
9980                member.refCount++;
9981          }
9982          else
9983          {
9984             NamedLink member;
9985             for(member = symbol.type.members.first; member; member = member.next)
9986             {
9987                NamedLink value { name = CopyString(member.name) };
9988                exp.expType.members.Add(value);
9989             }
9990          }
9991       }
9992    }
9993
9994    yylloc = exp.loc;
9995    if(exp.destType && (exp.destType.kind == voidType || exp.destType.kind == dummyType) );
9996    else if(exp.destType && !exp.destType.keepCast)
9997    {
9998       if(!CheckExpressionType(exp, exp.destType, false))
9999       {
10000          if(!exp.destType.count || unresolved)
10001          {
10002             if(!exp.expType)
10003             {
10004                yylloc = exp.loc;
10005                if(exp.destType.kind != ellipsisType)
10006                {
10007                   char type2[1024];
10008                   type2[0] = '\0';
10009                   if(inCompiler)
10010                   {
10011                      char expString[10240];
10012                      expString[0] = '\0';
10013
10014                      PrintType(exp.destType, type2, false, true);
10015
10016                      if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10017                      if(unresolved)
10018                         Compiler_Error("unresolved identifier %s; expected %s\n", expString, type2);
10019                      else if(exp.type != dummyExp)
10020                         Compiler_Error("couldn't determine type of %s; expected %s\n", expString, type2);
10021                   }
10022                }
10023                else
10024                {
10025                   char expString[10240] ;
10026                   expString[0] = '\0';
10027                   if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10028
10029                   if(unresolved)
10030                      Compiler_Error("unresolved identifier %s\n", expString);
10031                   else if(exp.type != dummyExp)
10032                      Compiler_Error("couldn't determine type of %s\n", expString);
10033                }
10034             }
10035             else
10036             {
10037                char type1[1024];
10038                char type2[1024];
10039                type1[0] = '\0';
10040                type2[0] = '\0';
10041                if(inCompiler)
10042                {
10043                   PrintType(exp.expType, type1, false, true);
10044                   PrintType(exp.destType, type2, false, true);
10045                }
10046
10047                //CheckExpressionType(exp, exp.destType, false);
10048
10049                if(exp.destType.truth && exp.destType._class && exp.destType._class.registered && !strcmp(exp.destType._class.registered.name, "bool") &&
10050                   exp.expType.kind != voidType && exp.expType.kind != structType && exp.expType.kind != unionType && 
10051                   (exp.expType.kind != classType || exp.expType.classObjectType || (exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type != structClass)));
10052                else
10053                {
10054                   char expString[10240];
10055                   expString[0] = '\0';
10056                   if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10057
10058 #ifdef _DEBUG
10059                   CheckExpressionType(exp, exp.destType, false);
10060 #endif
10061                   Compiler_Warning("incompatible expression %s (%s); expected %s\n", expString, type1, type2);
10062
10063                   // TO CHECK: FORCING HERE TO HELP DEBUGGER
10064                   FreeType(exp.expType);
10065                   exp.destType.refCount++;
10066                   exp.expType = exp.destType;
10067                }
10068             }
10069          }
10070       }
10071       else if(exp.destType && exp.destType.kind == ellipsisType && exp.expType && exp.expType.passAsTemplate)
10072       {
10073          Expression newExp { };
10074          char typeString[1024];
10075          OldList * specs = MkList();
10076          Declarator decl;
10077
10078          typeString[0] = '\0';
10079
10080          *newExp = *exp;
10081
10082          if(exp.expType)  exp.expType.refCount++;
10083          if(exp.expType)  exp.expType.refCount++;
10084          exp.type = castExp;
10085          newExp.destType = exp.expType;
10086
10087          PrintType(exp.expType, typeString, false, false);
10088          decl = SpecDeclFromString(typeString, specs, null);
10089          
10090          exp.cast.typeName = MkTypeName(specs, decl);
10091          exp.cast.exp = newExp;
10092       }
10093    }
10094    else if(unresolved)
10095    {
10096       if(exp.identifier._class && exp.identifier._class.name)
10097          Compiler_Error("unresolved identifier %s::%s\n", exp.identifier._class.name, exp.identifier.string);
10098       else if(exp.identifier.string && exp.identifier.string[0])
10099          Compiler_Error("unresolved identifier %s\n", exp.identifier.string);
10100    }
10101    else if(!exp.expType && exp.type != dummyExp)
10102    {
10103       char expString[10240];
10104       expString[0] = '\0';
10105       if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10106       Compiler_Error("couldn't determine type of %s\n", expString);
10107    }
10108
10109    // Let's try to support any_object & typed_object here:
10110    ApplyAnyObjectLogic(exp);
10111
10112    if(!notByReference && exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
10113       exp.expType._class.registered.type == noHeadClass)
10114    {
10115       exp.byReference = true;
10116    }
10117    /*else if(!notByReference && exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
10118       exp.destType._class.registered.type == noHeadClass)
10119    {
10120       exp.byReference = true;
10121    }*/
10122    yylloc = oldyylloc;
10123 }
10124
10125 static void FindNextDataMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
10126 {
10127    // THIS CODE WILL FIND NEXT MEMBER...
10128    if(*curMember) 
10129    {
10130       *curMember = (*curMember).next;
10131
10132       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
10133       {
10134          *curMember = subMemberStack[--(*subMemberStackPos)];
10135          *curMember = (*curMember).next;
10136       }
10137
10138       // SKIP ALL PROPERTIES HERE...
10139       while((*curMember) && (*curMember).isProperty)
10140          *curMember = (*curMember).next;
10141
10142       if(subMemberStackPos)
10143       {
10144          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10145          {
10146             subMemberStack[(*subMemberStackPos)++] = *curMember;
10147
10148             *curMember = (*curMember).members.first;
10149             while(*curMember && (*curMember).isProperty)
10150                *curMember = (*curMember).next;                     
10151          }
10152       }
10153    }
10154    while(!*curMember)
10155    {
10156       if(!*curMember)
10157       {
10158          if(subMemberStackPos && *subMemberStackPos)
10159          {
10160             *curMember = subMemberStack[--(*subMemberStackPos)];
10161             *curMember = (*curMember).next;
10162          }
10163          else
10164          {
10165             Class lastCurClass = *curClass;
10166
10167             if(*curClass == _class) break;     // REACHED THE END
10168
10169             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass; *curClass = (*curClass).base);
10170             *curMember = (*curClass).membersAndProperties.first;
10171          }
10172
10173          while((*curMember) && (*curMember).isProperty)
10174             *curMember = (*curMember).next;
10175          if(subMemberStackPos)
10176          {
10177             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10178             {
10179                subMemberStack[(*subMemberStackPos)++] = *curMember;
10180
10181                *curMember = (*curMember).members.first;
10182                while(*curMember && (*curMember).isProperty)
10183                   *curMember = (*curMember).next;                     
10184             }
10185          }
10186       }
10187    }
10188 }
10189
10190
10191 static void ProcessInitializer(Initializer init, Type type)
10192 {
10193    switch(init.type)
10194    {
10195       case expInitializer:
10196          if(!init.exp || init.exp.type != instanceExp || !init.exp.instance || init.exp.instance._class || !type || type.kind == classType)
10197          {
10198             // TESTING THIS FOR SHUTTING = 0 WARNING
10199             if(init.exp && !init.exp.destType)
10200             {
10201                FreeType(init.exp.destType);
10202                init.exp.destType = type;
10203                if(type) type.refCount++;
10204             }
10205             if(init.exp)
10206             {
10207                ProcessExpressionType(init.exp);
10208                init.isConstant = init.exp.isConstant;
10209             }
10210             break;
10211          }
10212          else
10213          {
10214             Expression exp = init.exp;
10215             Instantiation inst = exp.instance;
10216             MembersInit members;
10217
10218             init.type = listInitializer;
10219             init.list = MkList();
10220
10221             if(inst.members)
10222             {
10223                for(members = inst.members->first; members; members = members.next)
10224                {
10225                   if(members.type == dataMembersInit)
10226                   {
10227                      MemberInit member;
10228                      for(member = members.dataMembers->first; member; member = member.next)
10229                      {
10230                         ListAdd(init.list, member.initializer);
10231                         member.initializer = null;
10232                      }
10233                   }
10234                   // Discard all MembersInitMethod
10235                }
10236             }
10237             FreeExpression(exp);
10238          }
10239       case listInitializer:
10240       {
10241          Initializer i;
10242          Type initializerType = null;
10243          Class curClass = null;
10244          DataMember curMember = null;
10245          DataMember subMemberStack[256];
10246          int subMemberStackPos = 0;
10247
10248          if(type && type.kind == arrayType)
10249             initializerType = Dereference(type);
10250          else if(type && (type.kind == structType || type.kind == unionType))
10251             initializerType = type.members.first;
10252
10253          for(i = init.list->first; i; i = i.next)
10254          {
10255             if(type && type.kind == classType && type._class && type._class.registered)
10256             {
10257                // 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)
10258                FindNextDataMember(type._class.registered, &curClass, &curMember, subMemberStack, &subMemberStackPos);
10259                // TODO: Generate error on initializing a private data member this way from another module...
10260                if(curMember)
10261                {
10262                   if(!curMember.dataType)
10263                      curMember.dataType = ProcessTypeString(curMember.dataTypeString, false);
10264                   initializerType = curMember.dataType;
10265                }
10266             }
10267             ProcessInitializer(i, initializerType);
10268             if(initializerType && type && (type.kind == structType || type.kind == unionType))
10269                initializerType = initializerType.next;
10270             if(!i.isConstant)
10271                init.isConstant = false;
10272          }
10273
10274          if(type && type.kind == arrayType)
10275             FreeType(initializerType);
10276
10277          if(type && type.kind != arrayType && type.kind != structType && type.kind != unionType && (type.kind != classType || !type._class.registered || type._class.registered.type != structClass))
10278          {
10279             Compiler_Error("Assigning list initializer to non list\n");
10280          }
10281          break;
10282       }
10283    }
10284 }
10285
10286 static void ProcessSpecifier(Specifier spec, bool declareStruct)
10287 {
10288    switch(spec.type)
10289    {
10290       case baseSpecifier:
10291       {
10292          if(spec.specifier == THISCLASS)
10293          {
10294             if(thisClass)
10295             {
10296                spec.type = nameSpecifier;
10297                spec.name = ReplaceThisClass(thisClass);
10298                spec.symbol = FindClass(spec.name);
10299                ProcessSpecifier(spec, declareStruct);
10300             }
10301          }
10302          break;
10303       }
10304       case nameSpecifier:
10305       {
10306          Symbol symbol = FindType(curContext, spec.name);
10307          if(symbol)
10308             DeclareType(symbol.type, true, true);
10309          else if((symbol = spec.symbol /*FindClass(spec.name)*/) && symbol.registered && symbol.registered.type == structClass && declareStruct)
10310             DeclareStruct(spec.name, false);
10311          break;
10312       }
10313       case enumSpecifier:
10314       {
10315          Enumerator e;
10316          if(spec.list)
10317          {
10318             for(e = spec.list->first; e; e = e.next)
10319             {
10320                if(e.exp)
10321                   ProcessExpressionType(e.exp);
10322             }
10323          }
10324          break;
10325       }
10326       case structSpecifier:
10327       case unionSpecifier:
10328       {
10329          if(spec.definitions)
10330          {
10331             ClassDef def;
10332             Symbol symbol = spec.id ? FindClass(spec.id.string) : null;
10333             //if(symbol)
10334                ProcessClass(spec.definitions, symbol);
10335             /*else
10336             {
10337                for(def = spec.definitions->first; def; def = def.next)
10338                {
10339                   //if(def.type == declarationClassDef && def.decl && def.decl.type == DeclarationStruct)
10340                      ProcessDeclaration(def.decl);
10341                }
10342             }*/
10343          }
10344          break;
10345       }
10346       /*
10347       case classSpecifier:
10348       {
10349          Symbol classSym = FindClass(spec.name);
10350          if(classSym && classSym.registered && classSym.registered.type == structClass)
10351             DeclareStruct(spec.name, false);
10352          break;
10353       }
10354       */
10355    }
10356 }
10357
10358
10359 static void ProcessDeclarator(Declarator decl)
10360 {
10361    switch(decl.type)
10362    {
10363       case identifierDeclarator:
10364          if(decl.identifier.classSym /* TODO: Name Space Fix ups  || decl.identifier.nameSpace*/)
10365          {
10366             FreeSpecifier(decl.identifier._class);
10367             decl.identifier._class = null;
10368          }
10369          break;
10370       case arrayDeclarator:
10371          if(decl.array.exp)
10372             ProcessExpressionType(decl.array.exp);
10373       case structDeclarator:
10374       case bracketsDeclarator:
10375       case functionDeclarator:
10376       case pointerDeclarator:
10377       case extendedDeclarator:
10378       case extendedDeclaratorEnd:
10379          if(decl.declarator)
10380             ProcessDeclarator(decl.declarator);
10381          if(decl.type == functionDeclarator)
10382          {
10383             Identifier id = GetDeclId(decl);
10384             if(id && id._class)
10385             {
10386                TypeName param
10387                {
10388                   qualifiers = MkListOne(id._class);
10389                   declarator = null;
10390                };
10391                if(!decl.function.parameters)
10392                   decl.function.parameters = MkList();               
10393                decl.function.parameters->Insert(null, param);
10394                id._class = null;
10395             }
10396             if(decl.function.parameters)
10397             {
10398                TypeName param;
10399                
10400                for(param = decl.function.parameters->first; param; param = param.next)
10401                {
10402                   if(param.qualifiers && param.qualifiers->first)
10403                   {
10404                      Specifier spec = param.qualifiers->first;
10405                      if(spec && spec.specifier == TYPED_OBJECT)
10406                      {
10407                         Declarator d = param.declarator;
10408                         TypeName newParam
10409                         {
10410                            qualifiers = MkListOne(MkSpecifier(VOID));
10411                            declarator = MkDeclaratorPointer(MkPointer(null,null), d);
10412                         };
10413                         
10414                         FreeList(param.qualifiers, FreeSpecifier);
10415
10416                         param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
10417                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
10418
10419                         decl.function.parameters->Insert(param, newParam);
10420                         param = newParam;
10421                      }
10422                      else if(spec && spec.specifier == ANY_OBJECT)
10423                      {
10424                         Declarator d = param.declarator;
10425                         
10426                         FreeList(param.qualifiers, FreeSpecifier);
10427
10428                         param.qualifiers = MkListOne(MkSpecifier(VOID));
10429                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);                        
10430                      }
10431                      else if(spec.specifier == THISCLASS)
10432                      {
10433                         if(thisClass)
10434                         {
10435                            spec.type = nameSpecifier;
10436                            spec.name = ReplaceThisClass(thisClass);
10437                            spec.symbol = FindClass(spec.name);
10438                            ProcessSpecifier(spec, false);
10439                         }
10440                      }
10441                   }
10442
10443                   if(param.declarator)
10444                      ProcessDeclarator(param.declarator);
10445                }
10446             }
10447          }
10448          break;
10449    }
10450 }
10451
10452 static void ProcessDeclaration(Declaration decl)
10453 {
10454    yylloc = decl.loc;
10455    switch(decl.type)
10456    {
10457       case initDeclaration:
10458       {
10459          bool declareStruct = false;
10460          /*
10461          lineNum = decl.pos.line;
10462          column = decl.pos.col;
10463          */
10464
10465          if(decl.declarators)
10466          {
10467             InitDeclarator d;
10468          
10469             for(d = decl.declarators->first; d; d = d.next)
10470             {
10471                Type type, subType;
10472                ProcessDeclarator(d.declarator);
10473
10474                type = ProcessType(decl.specifiers, d.declarator);
10475
10476                if(d.initializer)
10477                {
10478                   ProcessInitializer(d.initializer, type);
10479
10480                   // Change "ColorRGB a = ColorRGB { 1,2,3 } => ColorRGB a { 1,2,3 }                  
10481                   
10482                   if(decl.declarators->count == 1 && d.initializer.type == expInitializer &&
10483                      d.initializer.exp.type == instanceExp)
10484                   {
10485                      if(type.kind == classType && type._class == 
10486                         d.initializer.exp.expType._class)
10487                      {
10488                         Instantiation inst = d.initializer.exp.instance;
10489                         inst.exp = MkExpIdentifier(CopyIdentifier(GetDeclId(d.declarator)));
10490                         
10491                         d.initializer.exp.instance = null;
10492                         if(decl.specifiers)
10493                            FreeList(decl.specifiers, FreeSpecifier);
10494                         FreeList(decl.declarators, FreeInitDeclarator);
10495
10496                         d = null;
10497
10498                         decl.type = instDeclaration;
10499                         decl.inst = inst;
10500                      }
10501                   }
10502                }
10503                for(subType = type; subType;)
10504                {
10505                   if(subType.kind == classType)
10506                   {
10507                      declareStruct = true;
10508                      break;
10509                   }
10510                   else if(subType.kind == pointerType)
10511                      break;
10512                   else if(subType.kind == arrayType)
10513                      subType = subType.arrayType;
10514                   else
10515                      break;
10516                }
10517
10518                FreeType(type);
10519                if(!d) break;
10520             }
10521          }
10522
10523          if(decl.specifiers)
10524          {
10525             Specifier s;
10526             for(s = decl.specifiers->first; s; s = s.next)
10527             {
10528                ProcessSpecifier(s, declareStruct);
10529             }
10530          }
10531          break;
10532       }
10533       case instDeclaration:
10534       {
10535          ProcessInstantiationType(decl.inst);
10536          break;
10537       }
10538       case structDeclaration:
10539       {
10540          Specifier spec;
10541          Declarator d;
10542          bool declareStruct = false;
10543
10544          if(decl.declarators)
10545          {
10546             for(d = decl.declarators->first; d; d = d.next)
10547             {
10548                Type type = ProcessType(decl.specifiers, d.declarator);
10549                Type subType;
10550                ProcessDeclarator(d);
10551                for(subType = type; subType;)
10552                {
10553                   if(subType.kind == classType)
10554                   {
10555                      declareStruct = true;
10556                      break;
10557                   }
10558                   else if(subType.kind == pointerType)
10559                      break;
10560                   else if(subType.kind == arrayType)
10561                      subType = subType.arrayType;
10562                   else
10563                      break;
10564                }
10565                FreeType(type);
10566             }
10567          }
10568          if(decl.specifiers)
10569          {
10570             for(spec = decl.specifiers->first; spec; spec = spec.next)
10571                ProcessSpecifier(spec, declareStruct);
10572          }
10573          break;
10574       }
10575    }
10576 }
10577
10578 static FunctionDefinition curFunction;
10579
10580 static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
10581 {
10582    char propName[1024], propNameM[1024];
10583    char getName[1024], setName[1024];
10584    OldList * args;
10585
10586    DeclareProperty(prop, setName, getName);
10587
10588    // eInstance_FireWatchers(object, prop);
10589    strcpy(propName, "__ecereProp_");
10590    FullClassNameCat(propName, prop._class.fullName, false);
10591    strcat(propName, "_");
10592    // strcat(propName, prop.name);
10593    FullClassNameCat(propName, prop.name, true);
10594    MangleClassName(propName);
10595
10596    strcpy(propNameM, "__ecerePropM_");
10597    FullClassNameCat(propNameM, prop._class.fullName, false);
10598    strcat(propNameM, "_");
10599    // strcat(propNameM, prop.name);
10600    FullClassNameCat(propNameM, prop.name, true);
10601    MangleClassName(propNameM);
10602
10603    if(prop.isWatchable)
10604    {
10605       args = MkList();
10606       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10607       ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10608       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10609
10610       args = MkList();
10611       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10612       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10613       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10614    }
10615
10616    
10617    {
10618       args = MkList();
10619       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10620       ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10621       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10622
10623       args = MkList();
10624       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10625       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10626       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10627    }
10628    
10629    if(curFunction.propSet && !strcmp(curFunction.propSet.string, prop.name) && 
10630       (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
10631       curFunction.propSet.fireWatchersDone = true;
10632 }
10633
10634 static void ProcessStatement(Statement stmt)
10635 {
10636    yylloc = stmt.loc;
10637    /*
10638    lineNum = stmt.pos.line;
10639    column = stmt.pos.col;
10640    */
10641    switch(stmt.type)
10642    {
10643       case labeledStmt:
10644          ProcessStatement(stmt.labeled.stmt);
10645          break;
10646       case caseStmt:
10647          // This expression should be constant...
10648          if(stmt.caseStmt.exp)
10649          {
10650             FreeType(stmt.caseStmt.exp.destType);
10651             stmt.caseStmt.exp.destType = curSwitchType;
10652             if(curSwitchType) curSwitchType.refCount++;
10653             ProcessExpressionType(stmt.caseStmt.exp);
10654             ComputeExpression(stmt.caseStmt.exp);
10655          }
10656          if(stmt.caseStmt.stmt)
10657             ProcessStatement(stmt.caseStmt.stmt);
10658          break;
10659       case compoundStmt:
10660       {
10661          if(stmt.compound.context)
10662          {
10663             Declaration decl;
10664             Statement s;
10665
10666             Statement prevCompound = curCompound;
10667             Context prevContext = curContext;
10668
10669             if(!stmt.compound.isSwitch)
10670             {
10671                curCompound = stmt;
10672                curContext = stmt.compound.context;
10673             }
10674
10675             if(stmt.compound.declarations)
10676             {
10677                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
10678                   ProcessDeclaration(decl);
10679             }
10680             if(stmt.compound.statements)
10681             {
10682                for(s = stmt.compound.statements->first; s; s = s.next)
10683                   ProcessStatement(s);
10684             }
10685
10686             curContext = prevContext;
10687             curCompound = prevCompound;
10688          }
10689          break;
10690       }
10691       case expressionStmt:
10692       {
10693          Expression exp;
10694          if(stmt.expressions)
10695          {
10696             for(exp = stmt.expressions->first; exp; exp = exp.next)
10697                ProcessExpressionType(exp);
10698          }
10699          break;
10700       }
10701       case ifStmt:
10702       {
10703          Expression exp;
10704
10705          FreeType(((Expression)stmt.ifStmt.exp->last).destType);
10706          ((Expression)stmt.ifStmt.exp->last).destType = MkClassType("bool");
10707          ((Expression)stmt.ifStmt.exp->last).destType.truth = true;
10708          for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
10709          {
10710             ProcessExpressionType(exp);
10711          }
10712          if(stmt.ifStmt.stmt)
10713             ProcessStatement(stmt.ifStmt.stmt);
10714          if(stmt.ifStmt.elseStmt)
10715             ProcessStatement(stmt.ifStmt.elseStmt);
10716          break;
10717       }
10718       case switchStmt:
10719       {
10720          Type oldSwitchType = curSwitchType;
10721          if(stmt.switchStmt.exp)
10722          {
10723             Expression exp;
10724             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
10725             {
10726                if(!exp.next)
10727                {
10728                   /*
10729                   Type destType
10730                   {
10731                      kind = intType;
10732                      refCount = 1;
10733                   };
10734                   e.exp.destType = destType;
10735                   */
10736
10737                   ProcessExpressionType(exp);
10738                }
10739                if(!exp.next)
10740                   curSwitchType = exp.expType;
10741             }
10742          }
10743          ProcessStatement(stmt.switchStmt.stmt);
10744          curSwitchType = oldSwitchType;
10745          break;
10746       }
10747       case whileStmt:
10748       {
10749          if(stmt.whileStmt.exp)
10750          {
10751             Expression exp;
10752
10753             FreeType(((Expression)stmt.whileStmt.exp->last).destType);
10754             ((Expression)stmt.whileStmt.exp->last).destType = MkClassType("bool");
10755             ((Expression)stmt.whileStmt.exp->last).destType.truth = true;
10756             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
10757             {
10758                ProcessExpressionType(exp);
10759             }
10760          }
10761          if(stmt.whileStmt.stmt)
10762             ProcessStatement(stmt.whileStmt.stmt);
10763          break;
10764       }
10765       case doWhileStmt:
10766       {
10767          if(stmt.doWhile.exp)
10768          {
10769             Expression exp;
10770
10771             if(stmt.doWhile.exp->last)
10772             {
10773                FreeType(((Expression)stmt.doWhile.exp->last).destType);
10774                ((Expression)stmt.doWhile.exp->last).destType = MkClassType("bool");
10775                ((Expression)stmt.doWhile.exp->last).destType.truth = true;
10776             }
10777             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
10778             {
10779                ProcessExpressionType(exp);
10780             }
10781          }
10782          if(stmt.doWhile.stmt)
10783             ProcessStatement(stmt.doWhile.stmt);
10784          break;
10785       }
10786       case forStmt:
10787       {
10788          Expression exp;
10789          if(stmt.forStmt.init)
10790             ProcessStatement(stmt.forStmt.init);
10791
10792          if(stmt.forStmt.check && stmt.forStmt.check.expressions)
10793          {
10794             FreeType(((Expression)stmt.forStmt.check.expressions->last).destType);
10795             ((Expression)stmt.forStmt.check.expressions->last).destType = MkClassType("bool");
10796             ((Expression)stmt.forStmt.check.expressions->last).destType.truth = true;
10797          }
10798
10799          if(stmt.forStmt.check)
10800             ProcessStatement(stmt.forStmt.check);
10801          if(stmt.forStmt.increment)
10802          {
10803             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
10804                ProcessExpressionType(exp);
10805          }
10806
10807          if(stmt.forStmt.stmt)
10808             ProcessStatement(stmt.forStmt.stmt);
10809          break;
10810       }
10811       case forEachStmt:
10812       {
10813          Identifier id = stmt.forEachStmt.id;
10814          OldList * exp = stmt.forEachStmt.exp;
10815          OldList * filter = stmt.forEachStmt.filter;
10816          Statement block = stmt.forEachStmt.stmt;
10817          char iteratorType[1024];
10818          Type source;
10819          Expression e;
10820          bool isBuiltin = exp && exp->last && 
10821             (((Expression)exp->last).type == ExpressionType::arrayExp || 
10822               (((Expression)exp->last).type == castExp && ((Expression)exp->last).cast.exp.type == ExpressionType::arrayExp));
10823          Expression arrayExp;
10824          char * typeString = null;
10825          int builtinCount = 0;
10826
10827          for(e = exp ? exp->first : null; e; e = e.next)
10828          {
10829             if(!e.next)
10830             {
10831                FreeType(e.destType);
10832                e.destType = ProcessTypeString("Container", false);
10833             }
10834             if(!isBuiltin || e.next)
10835                ProcessExpressionType(e);
10836          }
10837
10838          source = (exp && exp->last) ? ((Expression)exp->last).expType : null;
10839          if(isBuiltin || (source && source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
10840             eClass_IsDerived(source._class.registered, containerClass)))
10841          {
10842             Class _class = source ? source._class.registered : null;
10843             Symbol symbol;
10844             Expression expIt = null;
10845             bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false, isAVLTree = false;
10846             Class arrayClass = eSystem_FindClass(privateModule, "Array");
10847             Class linkListClass = eSystem_FindClass(privateModule, "LinkList");
10848             Class customAVLTreeClass = eSystem_FindClass(privateModule, "CustomAVLTree");
10849             stmt.type = compoundStmt;
10850             
10851             stmt.compound.context = Context { };
10852             stmt.compound.context.parent = curContext;
10853             curContext = stmt.compound.context;
10854
10855             if(source && eClass_IsDerived(source._class.registered, customAVLTreeClass))
10856             {
10857                Class mapClass = eSystem_FindClass(privateModule, "Map");
10858                Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
10859                isCustomAVLTree = true;
10860                if(eClass_IsDerived(source._class.registered, avlTreeClass))
10861                   isAVLTree = true;
10862                else if(eClass_IsDerived(source._class.registered, mapClass))
10863                   isMap = true;
10864             }
10865             else if(source && eClass_IsDerived(source._class.registered, arrayClass)) isArray = true;
10866             else if(source && eClass_IsDerived(source._class.registered, linkListClass)) 
10867             {
10868                Class listClass = eSystem_FindClass(privateModule, "List");
10869                isLinkList = true;
10870                isList = eClass_IsDerived(source._class.registered, listClass);
10871             }
10872
10873             if(isArray)
10874             {
10875                Declarator decl;
10876                OldList * specs = MkList();
10877                decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
10878                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
10879                stmt.compound.declarations = MkListOne(
10880                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
10881                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
10882                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalArray")), 
10883                      MkInitializerAssignment(MkExpBrackets(exp))))));
10884             }
10885             else if(isBuiltin)
10886             {
10887                Type type = null;
10888                char typeStringBuf[1024];
10889                
10890                // TODO: Merge this code?
10891                arrayExp = (((Expression)exp->last).type == ExpressionType::arrayExp) ? (Expression)exp->last : ((Expression)exp->last).cast.exp;
10892                if(((Expression)exp->last).type == castExp)
10893                {
10894                   TypeName typeName = ((Expression)exp->last).cast.typeName;
10895                   if(typeName)
10896                      arrayExp.destType = ProcessType(typeName.qualifiers, typeName.declarator);
10897                }
10898
10899                if(arrayExp.destType && arrayExp.destType.kind == classType && arrayExp.destType._class && arrayExp.destType._class.registered &&
10900                   arrayExp.destType._class.registered != containerClass && eClass_IsDerived(arrayExp.destType._class.registered, containerClass) &&
10901                   arrayExp.destType._class.registered.templateArgs)
10902                {
10903                   Class templateClass = arrayExp.destType._class.registered;
10904                   typeString = templateClass.templateArgs[2].dataTypeString;
10905                }
10906                else if(arrayExp.list)
10907                {
10908                   // Guess type from expressions in the array
10909                   Expression e;
10910                   for(e = arrayExp.list->first; e; e = e.next)
10911                   {
10912                      ProcessExpressionType(e);
10913                      if(e.expType)
10914                      {
10915                         if(!type) { type = e.expType; type.refCount++; }
10916                         else
10917                         {
10918                            // if(!MatchType(e.expType, type, null, null, null, false, false, false))
10919                            if(!MatchTypeExpression(e, type, null, false))
10920                            {
10921                               FreeType(type);
10922                               type = e.expType;
10923                               e.expType = null;
10924                               
10925                               e = arrayExp.list->first;
10926                               ProcessExpressionType(e);
10927                               if(e.expType)
10928                               {
10929                                  //if(!MatchTypes(e.expType, type, null, null, null, false, false, false, false))
10930                                  if(!MatchTypeExpression(e, type, null, false))
10931                                  {
10932                                     FreeType(e.expType);
10933                                     e.expType = null;
10934                                     FreeType(type);
10935                                     type = null;
10936                                     break;
10937                                  }                           
10938                               }
10939                            }
10940                         }
10941                         if(e.expType)
10942                         {
10943                            FreeType(e.expType);
10944                            e.expType = null;
10945                         }
10946                      }
10947                   }
10948                   if(type)
10949                   {
10950                      typeStringBuf[0] = '\0';
10951                      PrintType(type, typeStringBuf, false, true);
10952                      typeString = typeStringBuf;
10953                      FreeType(type);
10954                   }
10955                }
10956                if(typeString)
10957                {
10958                   OldList * initializers = MkList();
10959                   Declarator decl;
10960                   OldList * specs = MkList();
10961                   if(arrayExp.list)
10962                   {
10963                      Expression e;
10964
10965                      builtinCount = arrayExp.list->count;
10966                      type = ProcessTypeString(typeString, false);
10967                      while(e = arrayExp.list->first)
10968                      {
10969                         arrayExp.list->Remove(e);
10970                         e.destType = type;
10971                         type.refCount++;
10972                         ProcessExpressionType(e);
10973                         ListAdd(initializers, MkInitializerAssignment(e));
10974                      }
10975                      FreeType(type);
10976                      delete arrayExp.list;
10977                   }
10978                   decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
10979                   stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier), 
10980                      MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
10981
10982                   ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorArray(PlugDeclarator(
10983                      /*CopyDeclarator(*/decl/*)*/, MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), null), MkInitializerList(initializers)))));
10984                   
10985                   FreeList(exp, FreeExpression);
10986                }
10987                else
10988                {
10989                   arrayExp.expType = ProcessTypeString("Container", false);
10990                   Compiler_Error("Couldn't determine type of array elements\n");
10991                }
10992
10993                /*
10994                Declarator decl;
10995                OldList * specs = MkList();
10996
10997                decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
10998                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
10999                stmt.compound.declarations = MkListOne(
11000                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11001                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName("BuiltInContainer")),
11002                   MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), 
11003                      MkInitializerAssignment(MkExpBrackets(exp))))));
11004                */
11005             }
11006             else if(isLinkList && !isList)
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("__internalLinkList")), 
11014                      MkInitializerAssignment(MkExpBrackets(exp))))));
11015             }
11016             /*else if(isCustomAVLTree)
11017             {
11018                Declarator decl;
11019                OldList * specs = MkList();
11020                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11021                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11022                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11023                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalTree")), 
11024                      MkInitializerAssignment(MkExpBrackets(exp))))));
11025             }*/
11026             else if(_class.templateArgs)
11027             {
11028                if(isMap)
11029                   sprintf(iteratorType, "MapIterator<%s, %s >", _class.templateArgs[5].dataTypeString, _class.templateArgs[6].dataTypeString);
11030                else
11031                   sprintf(iteratorType, "Iterator<%s, %s >", _class.templateArgs[2].dataTypeString, _class.templateArgs[1].dataTypeString);
11032
11033                stmt.compound.declarations = MkListOne(
11034                   MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName(iteratorType)),
11035                   MkExpIdentifier(id), MkListOne(MkMembersInitList(MkListOne(MkMemberInit(isMap ? MkListOne(MkIdentifier("map")) : null, 
11036                   MkInitializerAssignment(MkExpBrackets(exp)))))))));
11037             }
11038             symbol = FindSymbol(id.string, curContext, curContext, false, false);
11039
11040             if(block && block.type == compoundStmt && block.compound.context)
11041             {
11042                block.compound.context.parent = stmt.compound.context;
11043             }
11044             if(filter)
11045             {
11046                block = MkIfStmt(filter, block, null);
11047             }
11048             if(isArray)
11049             {
11050                stmt.compound.statements = MkListOne(MkForStmt(
11051                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
11052                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11053                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11054                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11055                   block));
11056               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11057               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11058               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11059             }
11060             else if(isBuiltin)
11061             {
11062                char count[128];
11063                //OldList * specs = MkList();
11064                // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11065
11066                sprintf(count, "%d", builtinCount);
11067
11068                stmt.compound.statements = MkListOne(MkForStmt(
11069                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
11070                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11071                      MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
11072                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11073                   block));
11074
11075                /*
11076                Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11077                stmt.compound.statements = MkListOne(MkForStmt(
11078                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
11079                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
11080                      MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11081                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11082                   block));
11083               */
11084               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11085               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11086               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11087             }
11088             else if(isLinkList && !isList)
11089             {
11090                Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
11091                Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
11092                if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString && 
11093                   !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
11094                {
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)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11099                      block));
11100                }
11101                else
11102                {
11103                   OldList * specs = MkList();
11104                   Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
11105                   stmt.compound.statements = MkListOne(MkForStmt(
11106                      MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11107                      MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11108                      MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
11109                         MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
11110                            MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
11111                      block));
11112                }
11113                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11114                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11115                ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11116             }
11117             /*else if(isCustomAVLTree)
11118             {
11119                stmt.compound.statements = MkListOne(MkForStmt(
11120                   MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
11121                      MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
11122                   MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11123                   MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11124                   block));
11125
11126                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11127                ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11128                ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11129             }*/
11130             else
11131             {
11132                stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
11133                   MkIdentifier("Next")), null)), block));
11134             }
11135             ProcessExpressionType(expIt);
11136             if(stmt.compound.declarations->first)
11137                ProcessDeclaration(stmt.compound.declarations->first);
11138
11139             if(symbol) 
11140                symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
11141
11142             ProcessStatement(stmt);
11143             curContext = stmt.compound.context.parent;
11144             break;
11145          }
11146          else
11147          {
11148             Compiler_Error("Expression is not a container\n");
11149          }
11150          break;
11151       }
11152       case gotoStmt:
11153          break;
11154       case continueStmt:
11155          break;
11156       case breakStmt:
11157          break;
11158       case returnStmt:
11159       {
11160          Expression exp;
11161          if(stmt.expressions)
11162          {
11163             for(exp = stmt.expressions->first; exp; exp = exp.next)
11164             {
11165                if(!exp.next)
11166                {
11167                   if(curFunction && !curFunction.type)
11168                      curFunction.type = ProcessType(
11169                         curFunction.specifiers, curFunction.declarator);
11170                   FreeType(exp.destType);
11171                   exp.destType = (curFunction && curFunction.type && curFunction.type.kind == functionType) ? curFunction.type.returnType : null;
11172                   if(exp.destType) exp.destType.refCount++;
11173                }
11174                ProcessExpressionType(exp);
11175             }
11176          }
11177          break;
11178       }
11179       case badDeclarationStmt:
11180       {
11181          ProcessDeclaration(stmt.decl);
11182          break;
11183       }
11184       case asmStmt:
11185       {
11186          AsmField field;
11187          if(stmt.asmStmt.inputFields)
11188          {
11189             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
11190                if(field.expression)
11191                   ProcessExpressionType(field.expression);
11192          }
11193          if(stmt.asmStmt.outputFields)
11194          {
11195             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
11196                if(field.expression)
11197                   ProcessExpressionType(field.expression);
11198          }
11199          if(stmt.asmStmt.clobberedFields)
11200          {
11201             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
11202             {
11203                if(field.expression)
11204                   ProcessExpressionType(field.expression);
11205             }
11206          }
11207          break;
11208       }
11209       case watchStmt:
11210       {
11211          PropertyWatch propWatch;
11212          OldList * watches = stmt._watch.watches;
11213          Expression object = stmt._watch.object;
11214          Expression watcher = stmt._watch.watcher;
11215          if(watcher)
11216             ProcessExpressionType(watcher);
11217          if(object)
11218             ProcessExpressionType(object);
11219
11220          if(inCompiler)
11221          {
11222             if(watcher || thisClass)
11223             {
11224                External external = curExternal;
11225                Context context = curContext;
11226
11227                stmt.type = expressionStmt;
11228                stmt.expressions = MkList();
11229
11230                curExternal = external.prev;
11231
11232                for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11233                {
11234                   ClassFunction func;
11235                   char watcherName[1024];
11236                   Class watcherClass = watcher ? 
11237                      ((watcher.expType && watcher.expType.kind == classType && watcher.expType._class) ? watcher.expType._class.registered : null) : thisClass;
11238                   External createdExternal;
11239
11240                   // Create a declaration above
11241                   External externalDecl = MkExternalDeclaration(null);
11242                   ast->Insert(curExternal.prev, externalDecl);
11243
11244                   sprintf(watcherName,"__ecerePropertyWatcher_%d", propWatcherID++);
11245                   if(propWatch.deleteWatch)
11246                      strcat(watcherName, "_delete");
11247                   else
11248                   {
11249                      Identifier propID;
11250                      for(propID = propWatch.properties->first; propID; propID = propID.next)
11251                      {
11252                         strcat(watcherName, "_");
11253                         strcat(watcherName, propID.string);
11254                      }
11255                   }
11256
11257                   if(object && object.expType && object.expType.kind == classType && object.expType._class && object.expType._class.registered)
11258                   {
11259                      // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
11260                      func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)),
11261                         //MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null))), null);
11262                         MkListOne(MkTypeName(MkListOne(MkSpecifierName(object.expType._class.string)), MkDeclaratorIdentifier(MkIdentifier("value"))))), null);
11263                      ProcessClassFunctionBody(func, propWatch.compound);
11264                      propWatch.compound = null;
11265
11266                      //afterExternal = afterExternal ? afterExternal : curExternal;
11267
11268                      //createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal.prev);
11269                      createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal, true);
11270                      // TESTING THIS...
11271                      createdExternal.symbol.idCode = external.symbol.idCode;
11272
11273                      curExternal = createdExternal;
11274                      ProcessFunction(createdExternal.function);
11275
11276
11277                      // Create a declaration above
11278                      {
11279                         Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier), 
11280                            MkListOne(MkInitDeclarator(CopyDeclarator(createdExternal.function.declarator), null)));
11281                         externalDecl.declaration = decl;
11282                         if(decl.symbol && !decl.symbol.pointerExternal)
11283                            decl.symbol.pointerExternal = externalDecl;
11284                      }
11285
11286                      if(propWatch.deleteWatch)
11287                      {
11288                         OldList * args = MkList();
11289                         ListAdd(args, CopyExpression(object));
11290                         ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11291                         ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11292                         ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_WatchDestruction")), args));
11293                      }
11294                      else
11295                      {
11296                         Class _class = object.expType._class.registered;
11297                         Identifier propID;
11298
11299                         for(propID = propWatch.properties->first; propID; propID = propID.next)
11300                         {
11301                            char propName[1024];
11302                            Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11303                            if(prop)
11304                            {
11305                               char getName[1024], setName[1024];
11306                               OldList * args = MkList();
11307
11308                               DeclareProperty(prop, setName, getName);                              
11309                               
11310                               // eInstance_Watch(stmt.watch.object, prop, stmt.watch.watcher, callback);
11311                               strcpy(propName, "__ecereProp_");
11312                               FullClassNameCat(propName, prop._class.fullName, false);
11313                               strcat(propName, "_");
11314                               // strcat(propName, prop.name);
11315                               FullClassNameCat(propName, prop.name, true);
11316
11317                               ListAdd(args, CopyExpression(object));
11318                               ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11319                               ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11320                               ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11321
11322                               ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), args));
11323                            }
11324                            else
11325                               Compiler_Error("Property %s not found in class %s\n", prop.name, _class.fullName);
11326                         }
11327                      }
11328                   }
11329                   else
11330                      Compiler_Error("Invalid watched object\n");
11331                }
11332
11333                curExternal = external;
11334                curContext = context;
11335
11336                if(watcher)
11337                   FreeExpression(watcher);
11338                if(object)
11339                   FreeExpression(object);
11340                FreeList(watches, FreePropertyWatch);
11341             }
11342             else
11343                Compiler_Error("No observer specified and not inside a _class\n");
11344          }
11345          else
11346          {
11347             for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11348             {
11349                ProcessStatement(propWatch.compound);
11350             }
11351
11352          }
11353          break;
11354       }
11355       case fireWatchersStmt:
11356       {
11357          OldList * watches = stmt._watch.watches;
11358          Expression object = stmt._watch.object;
11359          Class _class;
11360          // DEBUGGER BUG: Why doesn't watches evaluate to null??
11361          // printf("%X\n", watches);
11362          // printf("%X\n", stmt._watch.watches);
11363          if(object)
11364             ProcessExpressionType(object);
11365
11366          if(inCompiler)
11367          {
11368             _class = object ? 
11369                   ((object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null) : thisClass;
11370
11371             if(_class)
11372             {
11373                Identifier propID;
11374
11375                stmt.type = expressionStmt;
11376                stmt.expressions = MkList();
11377
11378                // Check if we're inside a property set
11379                if(!watches && curFunction.propSet && (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
11380                {
11381                   watches = MkListOne(MkIdentifier(curFunction.propSet.string));
11382                }
11383                else if(!watches)
11384                {
11385                   //Compiler_Error("No property specified and not inside a property set\n");
11386                }
11387                if(watches)
11388                {
11389                   for(propID = watches->first; propID; propID = propID.next)
11390                   {
11391                      Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11392                      if(prop)
11393                      {
11394                         CreateFireWatcher(prop, object, stmt);
11395                      }
11396                      else
11397                         Compiler_Error("Property %s not found in class %s\n", propID.string, _class.fullName);
11398                   }
11399                }
11400                else
11401                {
11402                   // Fire all properties!
11403                   Property prop;
11404                   Class base;
11405                   for(base = _class; base; base = base.base)
11406                   {
11407                      for(prop = base.membersAndProperties.first; prop; prop = prop.next)
11408                      {
11409                         if(prop.isProperty && prop.isWatchable)
11410                         {
11411                            CreateFireWatcher(prop, object, stmt);
11412                         }
11413                      }
11414                   }
11415                }
11416
11417                if(object)
11418                   FreeExpression(object);
11419                FreeList(watches, FreeIdentifier);
11420             }
11421             else
11422                Compiler_Error("Invalid object specified and not inside a class\n");
11423          }
11424          break;
11425       }
11426       case stopWatchingStmt:
11427       {
11428          OldList * watches = stmt._watch.watches;
11429          Expression object = stmt._watch.object;
11430          Expression watcher = stmt._watch.watcher;
11431          Class _class;
11432          if(object)
11433             ProcessExpressionType(object);
11434          if(watcher)
11435             ProcessExpressionType(watcher);
11436          if(inCompiler)
11437          {
11438             _class = (object && object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null;
11439
11440             if(watcher || thisClass)
11441             {
11442                if(_class)
11443                {
11444                   Identifier propID;
11445
11446                   stmt.type = expressionStmt;
11447                   stmt.expressions = MkList();
11448
11449                   if(!watches)
11450                   {
11451                      OldList * args;
11452                      // eInstance_StopWatching(object, null, watcher); 
11453                      args = MkList();
11454                      ListAdd(args, CopyExpression(object));
11455                      ListAdd(args, MkExpConstant("0"));
11456                      ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11457                      ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11458                   }
11459                   else
11460                   {
11461                      for(propID = watches->first; propID; propID = propID.next)
11462                      {
11463                         char propName[1024];
11464                         Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11465                         if(prop)
11466                         {
11467                            char getName[1024], setName[1024];
11468                            OldList * args = MkList();
11469
11470                            DeclareProperty(prop, setName, getName);
11471          
11472                            // eInstance_StopWatching(object, prop, watcher); 
11473                            strcpy(propName, "__ecereProp_");
11474                            FullClassNameCat(propName, prop._class.fullName, false);
11475                            strcat(propName, "_");
11476                            // strcat(propName, prop.name);
11477                            FullClassNameCat(propName, prop.name, true);
11478                            MangleClassName(propName);
11479
11480                            ListAdd(args, CopyExpression(object));
11481                            ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11482                            ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11483                            ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11484                         }
11485                         else
11486                            Compiler_Error("Property %s not found in class %s\n", prop.name, _class.fullName);
11487                      }
11488                   }
11489
11490                   if(object)
11491                      FreeExpression(object);
11492                   if(watcher)
11493                      FreeExpression(watcher);
11494                   FreeList(watches, FreeIdentifier);
11495                }
11496                else
11497                   Compiler_Error("Invalid object specified and not inside a class\n");
11498             }
11499             else
11500                Compiler_Error("No observer specified and not inside a class\n");
11501          }
11502          break;
11503       }
11504    }
11505 }
11506
11507 static void ProcessFunction(FunctionDefinition function)
11508 {
11509    Identifier id = GetDeclId(function.declarator);
11510    Symbol symbol = function.declarator ? function.declarator.symbol : null;
11511    Type type = symbol ? symbol.type : null;
11512    Class oldThisClass = thisClass;
11513    Context oldTopContext = topContext;
11514
11515    yylloc = function.loc;
11516    // Process thisClass
11517    
11518    if(type && type.thisClass)
11519    {
11520       Symbol classSym = type.thisClass;
11521       Class _class = type.thisClass.registered;
11522       char className[1024];
11523       char structName[1024];
11524       Declarator funcDecl;
11525       Symbol thisSymbol;
11526
11527       bool typedObject = false;
11528
11529       if(_class && !_class.base)
11530       {
11531          _class = currentClass;
11532          if(_class && !_class.symbol)
11533             _class.symbol = FindClass(_class.fullName);
11534          classSym = _class ? _class.symbol : null;
11535          typedObject = true;
11536       }
11537
11538       thisClass = _class;
11539
11540       if(inCompiler && _class)
11541       {
11542          if(type.kind == functionType)
11543          {
11544             if(symbol.type.params.count == 1 && ((Type)symbol.type.params.first).kind == voidType)
11545             {
11546                //TypeName param = symbol.type.params.first;
11547                Type param = symbol.type.params.first;
11548                symbol.type.params.Remove(param);
11549                //FreeTypeName(param);
11550                FreeType(param);
11551             }
11552             if(type.classObjectType != classPointer)
11553             {
11554                symbol.type.params.Insert(null, MkClassType(_class.fullName));
11555                symbol.type.staticMethod = true;
11556                symbol.type.thisClass = null;
11557
11558                // HIGH DANGER: VERIFYING THIS...
11559                symbol.type.extraParam = false;
11560             }
11561          }
11562
11563          strcpy(className, "__ecereClass_");
11564          FullClassNameCat(className, _class.fullName, true);
11565
11566          MangleClassName(className);
11567
11568          structName[0] = 0;
11569          FullClassNameCat(structName, _class.fullName, false);
11570
11571          // [class] this
11572          
11573
11574          funcDecl = GetFuncDecl(function.declarator);
11575          if(funcDecl)
11576          {
11577             if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11578             {
11579                TypeName param = funcDecl.function.parameters->first;
11580                if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11581                {
11582                   funcDecl.function.parameters->Remove(param);
11583                   FreeTypeName(param);
11584                }
11585             }
11586
11587             // DANGER: Watch for this... Check if it's a Conversion?
11588             // if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11589             
11590             // WAS TRYING THIS FOR CONVERSION PROPERTIES ON NOHEAD CLASSES: if((_class.type == structClass) || function != (FunctionDefinition)symbol.externalSet)
11591             if(!function.propertyNoThis)
11592             {
11593                TypeName thisParam;
11594                
11595                if(type.classObjectType != classPointer)
11596                {
11597                   thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11598                   if(!funcDecl.function.parameters)
11599                      funcDecl.function.parameters = MkList();
11600                   funcDecl.function.parameters->Insert(null, thisParam);
11601                }
11602
11603                if(typedObject)
11604                {
11605                   if(type.classObjectType != classPointer)
11606                   {
11607                      if(type.byReference || _class.type == unitClass || _class.type == systemClass || _class.type == enumClass || _class.type == bitClass)
11608                         thisParam.declarator = MkDeclaratorPointer(MkPointer(null,null), thisParam.declarator);
11609                   }
11610
11611                   thisParam = TypeName
11612                   {
11613                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
11614                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
11615                   };
11616                   funcDecl.function.parameters->Insert(null, thisParam);
11617                }
11618             }
11619          }
11620
11621          if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11622          {
11623             InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11624             funcDecl = GetFuncDecl(initDecl.declarator);
11625             if(funcDecl)
11626             {
11627                if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11628                {
11629                   TypeName param = funcDecl.function.parameters->first;
11630                   if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11631                   {
11632                      funcDecl.function.parameters->Remove(param);
11633                      FreeTypeName(param);
11634                   }
11635                }
11636
11637                if(type.classObjectType != classPointer)
11638                {
11639                   // DANGER: Watch for this... Check if it's a Conversion?
11640                   if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11641                   {
11642                      TypeName thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11643
11644                      if(!funcDecl.function.parameters)
11645                         funcDecl.function.parameters = MkList();
11646                      funcDecl.function.parameters->Insert(null, thisParam);
11647                   }
11648                }
11649             }         
11650          }
11651       }
11652       
11653       // Add this to the context
11654       if(function.body)
11655       {
11656          if(type.classObjectType != classPointer)
11657          {
11658             thisSymbol = Symbol
11659             {
11660                string = CopyString("this");
11661                type = classSym ? MkClassType(classSym.string) : null; //_class.fullName);
11662             };
11663             function.body.compound.context.symbols.Add((BTNode)thisSymbol);
11664
11665             if(typedObject && thisSymbol.type)
11666             {
11667                thisSymbol.type.classObjectType = ClassObjectType::typedObject;
11668                thisSymbol.type.byReference = type.byReference;
11669                /*
11670                thisSymbol = Symbol { string = CopyString("class") };
11671                function.body.compound.context.symbols.Add(thisSymbol);
11672                */
11673             }
11674          }
11675       }
11676
11677       // Pointer to class data
11678       
11679       if(inCompiler && _class && (_class.type == normalClass /*|| _class.type == noHeadClass*/) && type.classObjectType != classPointer)
11680       {
11681          DataMember member = null;
11682          {
11683             Class base;
11684             for(base = _class; base && base.type != systemClass; base = base.next)
11685             {
11686                for(member = base.membersAndProperties.first; member; member = member.next)
11687                   if(!member.isProperty)
11688                      break;
11689                if(member)
11690                   break;
11691             }
11692          }
11693          for(member = _class.membersAndProperties.first; member; member = member.next)
11694             if(!member.isProperty)
11695                break;
11696          if(member)
11697          {
11698             char pointerName[1024];
11699    
11700             Declaration decl;
11701             Initializer initializer;
11702             Expression exp, bytePtr;
11703    
11704             strcpy(pointerName, "__ecerePointer_");
11705             FullClassNameCat(pointerName, _class.fullName, false);
11706             {
11707                char className[1024];
11708                strcpy(className, "__ecereClass_");
11709                FullClassNameCat(className, classSym.string, true);
11710                MangleClassName(className);
11711
11712                // Testing This
11713                DeclareClass(classSym, className);
11714             }
11715
11716             // ((byte *) this)
11717             bytePtr = QBrackets(MkExpCast(QMkType("char", QMkPtrDecl(null)), QMkExpId("this")));
11718
11719             if(_class.fixed)
11720             {
11721                char string[256];
11722                sprintf(string, "%d", _class.offset);
11723                exp = QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string)));
11724             }
11725             else
11726             {
11727                // ([bytePtr] + [className]->offset)
11728                exp = QBrackets(MkExpOp(bytePtr, '+',
11729                   MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
11730             }
11731
11732             // (this ? [exp] : 0)
11733             exp = QBrackets(QMkExpCond(QMkExpId("this"), exp, MkExpConstant("0")));
11734             exp.expType = Type
11735             {
11736                refCount = 1;
11737                kind = pointerType;
11738                type = Type { refCount = 1, kind = voidType };
11739             };
11740    
11741             if(function.body)
11742             {
11743                yylloc = function.body.loc;
11744                // ([structName] *) [exp]
11745                // initializer = MkInitializerAssignment(MkExpCast(QMkType(structName, QMkPtrDecl(null)), exp));
11746                initializer = MkInitializerAssignment(
11747                   MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), exp));
11748
11749                // [structName] * [pointerName] = [initializer];
11750                // decl = QMkDeclaration(structName, MkInitDeclarator(QMkPtrDecl(pointerName), initializer));
11751
11752                {
11753                   Context prevContext = curContext;
11754                   curContext = function.body.compound.context;
11755
11756                   decl = MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
11757                      MkListOne(MkInitDeclarator(QMkPtrDecl(pointerName), initializer)));
11758
11759                   curContext = prevContext;
11760                }
11761
11762                // WHY?
11763                decl.symbol = null;
11764
11765                if(!function.body.compound.declarations)
11766                   function.body.compound.declarations = MkList();
11767                function.body.compound.declarations->Insert(null, decl);
11768             }
11769          }
11770       }
11771       
11772
11773       // Loop through the function and replace undeclared identifiers
11774       // which are a member of the class (methods, properties or data)
11775       // by "this.[member]"
11776    }
11777    else
11778       thisClass = null;
11779
11780    if(id)
11781    {
11782       FreeSpecifier(id._class);
11783       id._class = null;
11784
11785       if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11786       {
11787          InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11788          id = GetDeclId(initDecl.declarator);
11789
11790          FreeSpecifier(id._class);
11791          id._class = null;
11792       }
11793    }
11794    if(function.body)
11795       topContext = function.body.compound.context;
11796    {
11797       FunctionDefinition oldFunction = curFunction;
11798       curFunction = function;
11799       if(function.body)
11800          ProcessStatement(function.body);
11801
11802       // If this is a property set and no firewatchers has been done yet, add one here
11803       if(inCompiler && function.propSet && !function.propSet.fireWatchersDone)
11804       {
11805          Statement prevCompound = curCompound;
11806          Context prevContext = curContext;
11807
11808          Statement fireWatchers = MkFireWatchersStmt(null, null);
11809          if(!function.body.compound.statements) function.body.compound.statements = MkList();
11810          ListAdd(function.body.compound.statements, fireWatchers);
11811
11812          curCompound = function.body;
11813          curContext = function.body.compound.context;
11814
11815          ProcessStatement(fireWatchers);
11816
11817          curContext = prevContext;
11818          curCompound = prevCompound;
11819
11820       }
11821
11822       curFunction = oldFunction;
11823    }
11824
11825    if(function.declarator)
11826    {
11827       ProcessDeclarator(function.declarator);
11828    }
11829
11830    topContext = oldTopContext;
11831    thisClass = oldThisClass;
11832 }
11833
11834 /////////// INSTANTIATIONS / DATA TYPES PASS /////////////////////////////////////////////
11835 static void ProcessClass(OldList definitions, Symbol symbol)
11836 {
11837    ClassDef def;
11838    External external = curExternal;
11839    Class regClass = symbol ? symbol.registered : null;
11840
11841    // Process all functions
11842    for(def = definitions.first; def; def = def.next)
11843    {
11844       if(def.type == functionClassDef)
11845       {
11846          if(def.function.declarator)
11847             curExternal = def.function.declarator.symbol.pointerExternal;
11848          else
11849             curExternal = external;
11850
11851          ProcessFunction((FunctionDefinition)def.function);
11852       }
11853       else if(def.type == declarationClassDef)
11854       {
11855          if(def.decl.type == instDeclaration)
11856          {
11857             thisClass = regClass;
11858             ProcessInstantiationType(def.decl.inst);
11859             thisClass = null;
11860          }
11861          // Testing this
11862          else
11863          {
11864             Class backThisClass = thisClass;
11865             if(regClass) thisClass = regClass;
11866             ProcessDeclaration(def.decl);
11867             thisClass = backThisClass;
11868          }
11869       }
11870       else if(def.type == defaultPropertiesClassDef && def.defProperties)
11871       {
11872          MemberInit defProperty;
11873
11874          // Add this to the context
11875          Symbol thisSymbol = Symbol
11876          {
11877             string = CopyString("this");
11878             type = regClass ? MkClassType(regClass.fullName) : null;
11879          };
11880          globalContext.symbols.Add((BTNode)thisSymbol);
11881          
11882          for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
11883          {
11884             thisClass = regClass;
11885             ProcessMemberInitData(defProperty, regClass, null, null, null, null);
11886             thisClass = null;
11887          }
11888
11889          globalContext.symbols.Remove((BTNode)thisSymbol);
11890          FreeSymbol(thisSymbol);
11891       }
11892       else if(def.type == propertyClassDef && def.propertyDef)
11893       {
11894          PropertyDef prop = def.propertyDef;
11895
11896          // Add this to the context
11897          /*
11898          Symbol thisSymbol = Symbol { string = CopyString("this"), type = MkClassType(regClass.fullName) };
11899          globalContext.symbols.Add(thisSymbol);
11900          */
11901          
11902          thisClass = regClass;
11903          if(prop.setStmt)
11904          {
11905             if(regClass)
11906             {
11907                Symbol thisSymbol
11908                {
11909                   string = CopyString("this");
11910                   type = MkClassType(regClass.fullName);
11911                };
11912                prop.setStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11913             }
11914
11915             curExternal = prop.symbol ? prop.symbol.externalSet : null;
11916             ProcessStatement(prop.setStmt);
11917          }
11918          if(prop.getStmt)
11919          {
11920             if(regClass)
11921             {
11922                Symbol thisSymbol
11923                {
11924                   string = CopyString("this");
11925                   type = MkClassType(regClass.fullName);
11926                };
11927                prop.getStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11928             }
11929
11930             curExternal = prop.symbol ? prop.symbol.externalGet : null;
11931             ProcessStatement(prop.getStmt);
11932          }
11933          if(prop.issetStmt)
11934          {
11935             if(regClass)
11936             {
11937                Symbol thisSymbol
11938                {
11939                   string = CopyString("this");
11940                   type = MkClassType(regClass.fullName);
11941                };
11942                prop.issetStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11943             }
11944
11945             curExternal = prop.symbol ? prop.symbol.externalIsSet : null;
11946             ProcessStatement(prop.issetStmt);
11947          }
11948
11949          thisClass = null;
11950
11951          /*
11952          globalContext.symbols.Remove(thisSymbol);
11953          FreeSymbol(thisSymbol);
11954          */
11955       }
11956       else if(def.type == propertyWatchClassDef && def.propertyWatch)
11957       {
11958          PropertyWatch propertyWatch = def.propertyWatch;
11959         
11960          thisClass = regClass;
11961          if(propertyWatch.compound)
11962          {
11963             Symbol thisSymbol
11964             {
11965                string = CopyString("this");
11966                type = regClass ? MkClassType(regClass.fullName) : null;
11967             };
11968
11969             propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
11970
11971             curExternal = null;
11972             ProcessStatement(propertyWatch.compound);
11973          }
11974          thisClass = null;
11975       }
11976    }
11977 }
11978
11979 void ComputeDataTypes()
11980 {
11981    External external;
11982    External temp { };
11983    currentClass = null;
11984
11985    containerClass = eSystem_FindClass(GetPrivateModule(), "Container");
11986
11987    temp.symbol = Symbol { id = -1000, idCode = -1000 };
11988
11989    // WHERE SHOULD THIS GO?
11990    // curExternal = ast->first;
11991    ast->Insert(null, temp);
11992
11993    curExternal = temp;
11994
11995    DeclareStruct("ecere::com::Class", false);
11996    DeclareStruct("ecere::com::Instance", false);
11997    DeclareStruct("ecere::com::Property", false);
11998    DeclareStruct("ecere::com::DataMember", false);
11999    DeclareStruct("ecere::com::Method", false);
12000    DeclareStruct("ecere::com::SerialBuffer", false);
12001    DeclareStruct("ecere::com::ClassTemplateArgument", false);
12002
12003    ast->Remove(temp);
12004
12005    for(external = ast->first; external; external = external.next)
12006    {
12007       afterExternal = curExternal = external;
12008       if(external.type == functionExternal)
12009       {
12010          currentClass = external.function._class;
12011          ProcessFunction(external.function);
12012       }
12013       // There shouldn't be any _class member access here anyways...
12014       else if(external.type == declarationExternal)
12015       {
12016          currentClass = null;
12017          ProcessDeclaration(external.declaration);
12018       }
12019       else if(external.type == classExternal)
12020       {
12021          ClassDefinition _class = external._class;
12022          currentClass = external.symbol.registered;
12023          if(_class.definitions)
12024          {
12025             ProcessClass(_class.definitions, _class.symbol);
12026          }
12027          if(inCompiler)
12028          {
12029             // Free class data...
12030             ast->Remove(external);
12031             delete external;
12032          }
12033       }
12034       else if(external.type == nameSpaceExternal)
12035       {
12036          thisNameSpace = external.id.string;
12037       }
12038    }
12039    currentClass = null;
12040    thisNameSpace = null;
12041
12042    delete temp.symbol;
12043    delete temp;
12044 }