compiler/ecere: completed intptr/uintptr support
[sdk] / compiler / libec / src / pass2.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.h"
5
6 extern External curExternal;
7 static Statement curCompound;
8
9 static void _FixRefExp(Expression * expPtr, Expression * memberExpPtr)
10 {
11    
12    Expression memberExp = *memberExpPtr;
13    if(memberExp && memberExp.type == ExpressionType::memberExp &&
14       memberExp.member.exp && (memberExp.member.exp.type == bracketsExp || memberExp.member.exp.type == extensionExpressionExp))
15    {
16       Expression bracketExp = memberExp.member.exp;
17       Expression idExp = bracketExp.list->last;
18
19       if(idExp && idExp.type == identifierExp)
20       {
21          Expression newExp = null;
22          Expression exp = *expPtr;
23
24          // opExp ( memberExp ( bracketsExp ( identifierExp ) ) )
25          // bracketsExp ( opExp ( memberExp ( identifierExp ) ) )
26
27          *memberExpPtr = null;
28          newExp = CopyExpression(exp);
29          *(Expression *)((byte *)newExp + (uint)((byte *)memberExpPtr - (byte *)exp)) = memberExp;
30
31          memberExp.member.exp = idExp;
32       
33          exp.type = bracketsExp;
34          exp.list = bracketExp.list;
35          bracketExp.list = null;
36
37          exp.list->Remove(idExp);
38          exp.list->Add(newExp);
39          FreeExpression(bracketExp);
40
41          *expPtr = newExp; //FixRefExp(newExp);
42       }
43    }
44    else if(*expPtr && (*expPtr).type == opExp && (*expPtr).op.op == '&' && !(*expPtr).op.exp1 &&
45       memberExp && (memberExp.type == bracketsExp || memberExp.type == extensionExpressionExp) && memberExp.list && memberExp.list->count > 1)
46    {
47       Expression newExp = null;
48       Expression exp = *expPtr;
49
50       *memberExpPtr = null;
51       newExp = CopyExpression(exp);
52       *(Expression *)((byte *)newExp + (uint)((byte *)memberExpPtr - (byte *)exp)) = memberExp.list->last;
53    
54       exp.type = bracketsExp;
55       exp.list = memberExp.list;
56       memberExp.list = null;
57
58       exp.list->Remove(exp.list->last);
59       exp.list->Add(newExp);
60       FreeExpression(memberExp);
61
62       *expPtr = newExp; //FixRefExp(newExp);
63    }
64 }
65
66 static Expression FixRefExp(Expression exp)
67 {
68    if(exp.type == opExp)
69    {
70       _FixRefExp(&exp, &exp.op.exp1);
71       _FixRefExp(&exp, &exp.op.exp2);
72    }
73    else if(exp.type == indexExp)
74       _FixRefExp(&exp, &exp.index.exp);
75    else if(exp.type == memberExp)
76       _FixRefExp(&exp, &exp.member.exp);
77    return exp;
78 }
79
80 static Expression FixReference(Expression e, bool wantReference)
81 {
82    if(e.expType && e.type != constantExp)
83    {
84       Type type = e.expType;
85       bool isPointer = false;
86       /*
87       if(type.kind == TypePointer && type.type && type.type.kind == classType)
88       {
89          type = type.type;
90          isPointer = true;
91       }
92       */
93
94       if(type.kind == classType) // || type.kind == TypeInt)
95       {
96          Class _class = type._class ? type._class.registered : null;
97          // TOLOOKINTO: What was systemClass used for here? Exclude "typed_object"...
98          // TOFIX: In which case with systemClass do we actually want this to come here? Can't think of any!
99          if(_class && (_class.type == structClass || _class.type == noHeadClass || 
100            (_class.type == systemClass && _class.base && 
101            strcmp(_class.fullName, "uintptr") && 
102            strcmp(_class.fullName, "intptr") && 
103            strcmp(_class.fullName, "ecere::com::Instance") && 
104            strcmp(_class.fullName, "ecere::com::Class") && 
105            strcmp(_class.dataTypeString, "char *"))))
106          {
107             // if(wantReference != ((_class.type == systemClass) ? false : e.byReference))
108             if(wantReference != (e.byReference || isPointer))
109             {
110                Expression exp = e;
111                for(;;)
112                {
113                   if(exp.type == bracketsExp || exp.type == extensionExpressionExp)
114                   {
115                      if(exp.list)
116                      {
117                         exp.byReference = wantReference;
118                         exp = exp.list->last;
119                      }
120                      else
121                         break;
122                   }
123                   else if(exp.type == castExp)
124                   {
125                      exp.byReference = wantReference;
126                      exp = exp.cast.exp;
127                   }
128                   else if(exp.type == conditionExp)
129                   {
130                      if(exp.cond.exp->last)
131                         FixReference(exp.cond.exp->last, wantReference);
132                      FixReference(exp.cond.elseExp, wantReference);
133                      break;
134                   }
135                   else
136                   {
137                      if(wantReference != (exp.byReference || isPointer))
138                      {
139                         Expression newExp { };
140                         *newExp = *exp;
141
142                         if(exp.destType) exp.destType.refCount++;
143                         if(exp.expType) exp.expType.refCount++;
144
145                         exp.type = opExp;
146                         exp.op.exp1 = null;
147                         exp.op.exp2 = newExp;
148                         if(wantReference)
149                            exp.op.op = '&';
150                         else
151                            exp.op.op = '*';
152                        
153                         e.byReference = wantReference;
154                         exp.byReference = wantReference;
155                      }
156                      break;
157                   }
158                }
159             }
160          }
161       }
162    }
163    e = FixRefExp(e);
164    return e;
165 }
166
167 static bool FixMember(Expression exp)
168 {
169    bool byReference = false;
170    for(;exp;)
171    {
172       if(exp.type == bracketsExp || exp.type == extensionExpressionExp)
173       {
174          if(exp.list->count > 1)
175             byReference = true;
176          exp = exp.list->last;
177       }
178       else if(exp.type == castExp)
179       {
180          exp = exp.cast.exp;
181       }
182       else
183       {
184          if(byReference)
185             FixReference(exp, true);
186          else
187             byReference = exp.byReference;
188          break;
189       }
190    }
191    return byReference;
192 }
193
194 static void ProcessExpression(Expression exp)
195 {
196    Location oldyylloc = yylloc;
197 #ifdef _DEBUG
198    char debugExpString[1024] = "";
199    PrintExpression(exp, debugExpString);
200 #endif
201
202    // Testing this here
203    yylloc = exp.loc;
204
205    switch(exp.type)
206    {
207       case identifierExp:
208       {
209          if(exp.expType && exp.expType.kind == methodType)
210          {
211             Class _class = exp.expType.methodClass;
212             Method method = exp.expType.method;
213             if(method.type == virtualMethod)
214             {
215                char name[1024];
216                TypeName typeName;
217                Declarator decl;
218                OldList * specs = MkList();
219                strcpy(name, "__ecereVMethodID_");
220                FullClassNameCat(name, method._class.fullName, false);
221                strcat(name, "_");
222                strcat(name, method.name);
223
224                DeclareMethod(method, name);
225
226                // Cast function to its type
227                decl = SpecDeclFromString(method.dataTypeString, specs, MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), null)));
228                if(!method.dataType.staticMethod)
229                {
230                   Declarator funcDecl = GetFuncDecl(decl);
231
232                   if(!funcDecl.function.parameters)
233                      funcDecl.function.parameters = MkList();
234                   {
235                      TypeName firstParam = ((TypeName)funcDecl.function.parameters->first);
236                      Specifier firstSpec = firstParam ? firstParam.qualifiers->first : null;
237
238                      if(firstParam && firstSpec.type == baseSpecifier && firstSpec.specifier == VOID && !firstParam.declarator)
239                         funcDecl.function.parameters->Remove(funcDecl.function.parameters->first);
240                   }
241
242                   funcDecl.function.parameters->Insert(null, MkTypeName(MkListOne(
243                      /*MkClassName*/MkSpecifierName(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)), null));
244                }
245
246                typeName = MkTypeName(specs, decl);
247
248                if(_class)
249                {
250                   char className[1024];
251                   // Need the class itself here...
252                   strcpy(className, "__ecereClass_");
253                   FullClassNameCat(className, _class.fullName, true);
254                   MangleClassName(className);
255
256                   if(!_class.symbol)
257                      _class.symbol = FindClass(_class.fullName);
258                   DeclareClass(_class.symbol, className);
259
260                   exp.type = bracketsExp;
261                   exp.list = MkListOne(MkExpCast(typeName,
262                      MkExpIndex(MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl")),
263                      MkListOne(MkExpIdentifier(MkIdentifier(name))))));
264                }
265             }
266             else
267             {
268                char name[1024];
269                strcpy(name, "__ecereMethod_");
270                FullClassNameCat(name, method._class.fullName, false);
271                strcat(name, "_");
272                strcat(name, method.name);
273
274                delete exp.identifier.string;
275
276                exp.identifier._class = null;
277                exp.identifier.string = CopyString(name);
278                DeclareMethod(method, name);
279             }
280          }
281          /*
282          if(exp.usage & USAGE_MEMBER)
283             FixReference(exp, true);
284          */
285          break;
286       }
287       case constantExp:
288          break;
289       case stringExp:
290          break;
291       case newExp:
292       case new0Exp:
293       case renewExp:
294       case renew0Exp:
295       {
296          OldList * args = MkList();
297
298          if(exp.type == renewExp || exp.type == renew0Exp)
299             ListAdd(args, exp._renew.exp);
300
301          ListAdd(args, MkExpOp(MkExpTypeSize(exp._new.typeName), '*', MkExpBrackets(MkListOne(exp._new.size))));
302
303          switch(exp.type)
304          {
305             case newExp:   exp.call.exp = QMkExpId("ecere::com::eSystem_New"); break;
306             case new0Exp:  exp.call.exp = QMkExpId("ecere::com::eSystem_New0"); break;
307             case renewExp: exp.call.exp = QMkExpId("ecere::com::eSystem_Renew"); break;
308             case renew0Exp:exp.call.exp = QMkExpId("ecere::com::eSystem_Renew0"); break;
309          }
310          exp.call.arguments = args;
311          exp.type = callExp;
312
313          ProcessExpression(exp);
314          break;
315       }
316       case opExp:
317       {
318          Expression exp1 = exp.op.exp1;
319          Expression exp2 = exp.op.exp2;
320
321          switch(exp.op.op)
322          {
323             // Assignment Operators
324             case '=': 
325                if(exp.op.exp2)
326                   exp.op.exp2.usage.usageGet = true;
327                break;
328             case MUL_ASSIGN:
329             case DIV_ASSIGN:
330             case MOD_ASSIGN:
331             case ADD_ASSIGN:
332             case SUB_ASSIGN:
333             case LEFT_ASSIGN:
334             case RIGHT_ASSIGN:
335             case AND_ASSIGN:
336             case XOR_ASSIGN:
337             case OR_ASSIGN:
338                exp.op.exp2.usage.usageGet = true;
339                break;
340
341             case INC_OP:
342             case DEC_OP:
343
344             // Unary operators
345             case '&':
346                // Also binary
347                if(exp.op.exp1 && exp.op.exp2)
348                {
349                   exp.op.exp1.usage.usageGet = true;
350                   exp.op.exp2.usage.usageGet = true;
351                }
352                else if(exp.op.exp2)
353                {
354                   exp.op.exp2.usage.usageRef = true;
355                }
356                break;
357             case '*':
358             case '+':
359             case '-':
360                // Also binary
361                if(exp.op.exp1)
362                {
363                   exp.op.exp1.usage.usageGet = true;
364                }
365             case '~':
366             case '!':
367                if(exp.op.exp2)
368                   exp.op.exp2.usage.usageGet = true;
369                break;
370
371             // Binary only operators
372             case '/':
373             case '%':
374             case LEFT_OP:
375             case RIGHT_OP:
376             case '<':
377             case '>':
378             case LE_OP:
379             case GE_OP:
380             case EQ_OP:
381             case NE_OP:
382             case '|':
383             case '^':
384             case AND_OP:
385             case OR_OP:            
386                if(exp.op.exp1)
387                   exp.op.exp1.usage.usageGet = true;
388                if(exp.op.exp2)
389                   exp.op.exp2.usage.usageGet = true;
390                break;
391          }
392
393          if(exp.op.op == '=' || exp.op.op == MUL_ASSIGN || exp.op.op == DIV_ASSIGN || exp.op.op == ADD_ASSIGN ||
394             exp.op.op == MOD_ASSIGN || exp.op.op == SUB_ASSIGN || exp.op.op == LEFT_ASSIGN ||
395             exp.op.op == RIGHT_ASSIGN || exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN ||
396             exp.op.op == XOR_ASSIGN || exp.op.op == INC_OP || exp.op.op == DEC_OP)
397          {
398             Expression memberExp;
399             Expression parentExp = null; // Where to take memberExp out from
400
401             // TOCHECK: See note below for this if
402             if(exp.op.exp1 && exp.op.exp1.type == ExpressionType::memberExp)
403             {
404                // Extra bit of code to access deep properties...
405                Expression testExp, topExp = null;
406                Expression lastExp = exp.op.exp1, parentExp = null;
407                Property lastProperty = null;
408                Class propertyClass;
409                
410                char setName[1024], getName[1024];
411                testExp = exp.op.exp1.member.exp;
412                while(true)
413                {
414                   // Is further fixing needed to address if statement above in the same way?
415                   while(testExp)
416                   {
417                      if(testExp.type == castExp)
418                         testExp = testExp.cast.exp;
419                      else if(testExp.type == bracketsExp || testExp.type == extensionExpressionExp)
420                         testExp = testExp.list->last;
421                      else if(testExp.type == ExpressionType::memberExp)
422                         break;
423                      else
424                         testExp = null;
425                   }
426                   if(!testExp) break;
427
428                   if(testExp.member.memberType == propertyMember || 
429                      testExp.member.memberType == reverseConversionMember)
430                   {
431                      Type type = testExp.member.exp.expType;
432                      if(type)
433                      {
434                         if(type.kind == classType)
435                         {
436                            Class _class = testExp.member.member.classSym ? testExp.member.member.classSym.registered : type._class.registered;
437                            Class convertTo = null;
438                            if(testExp.member.memberType == reverseConversionMember)
439                            {
440                               convertTo = _class;
441                               _class = FindClass(testExp.member.member.string).registered;
442                               // lastProperty = eClass_FindProperty(_class, convertTo.name, privateModule);
443                               lastProperty = eClass_FindProperty(_class, convertTo.fullName, privateModule);
444                            }                              
445                            else
446                            {
447                               lastProperty = eClass_FindProperty(_class, testExp.member.member.string, privateModule);
448                            }
449                            if(lastProperty && lastProperty.Get && lastProperty.Set)
450                            {
451                               DeclareProperty(lastProperty, setName, getName);
452                               // propertyClass = convertTo ? _class : ((Symbol)lastProperty.symbol)._class;
453                               propertyClass = convertTo ? _class : 
454                                  ((((Symbol)lastProperty.symbol).type && 
455                                     ((Symbol)lastProperty.symbol).type.kind == classType) ? ((Symbol)lastProperty.symbol).type._class.registered : ((Symbol)lastProperty.symbol)._class);
456                               // TODO: Handle this kind of things with bit classes?
457                               if(propertyClass && propertyClass.type == structClass)
458                               {
459                                  topExp = testExp;
460                                  parentExp = lastExp;
461                               }
462                               else if(propertyClass && propertyClass.type == bitClass)
463                               {
464                                  topExp = testExp;
465                                  parentExp = lastExp;
466                               }
467                            }
468                            
469                         }
470                      }
471                   }
472                   lastExp = testExp;
473
474                   testExp = testExp.member.exp;
475                }
476                if(topExp)
477                {
478                   if(propertyClass.type == structClass)
479                   {
480                      Expression copy;
481                      Expression value;
482                      char className[1024];
483                      Expression tempExp;
484                   
485                      sprintf(className, "__simpleStruct%d", curContext.simpleID); //++);
486                      tempExp = QMkExpId(className);
487                      tempExp.expType = MkClassType(propertyClass.fullName);
488
489                      parentExp.member.exp = tempExp;
490
491                      value = MkExpBrackets(MkList());
492
493                      copy = CopyExpression(topExp);
494                      copy.usage.usageGet = true;
495                      copy.usage.usageDeepGet = true;
496
497                      ListAdd(value.list, copy);
498                      ListAdd(value.list, MkExpOp(exp.op.exp1, exp.op.op, exp.op.exp2));
499                      ListAdd(value.list, CopyExpression(tempExp));
500                      value.expType = tempExp.expType;
501                      tempExp.expType.refCount++;
502
503                      // Go on as usual with these new values:
504                      exp.op.exp1 = topExp;                  
505                      exp.op.exp2 = value;
506                      exp.op.op = '=';
507
508                      exp1 = exp.op.exp1;
509                      exp2 = exp.op.exp2;
510                   }
511                   else if(propertyClass.type == bitClass)
512                   {
513                      Expression copy;
514                      Expression value;
515                      char className[1024];
516                      Expression tempExp;
517                   
518                      sprintf(className, "__simpleStruct%d", curContext.simpleID); //++);
519                      tempExp = QMkExpId(className);
520                      tempExp.expType = MkClassType(propertyClass.fullName);
521
522                      parentExp.member.exp = tempExp;
523
524                      value = MkExpBrackets(MkList());
525
526                      copy = CopyExpression(topExp);
527                      copy.usage.usageGet = true;
528                      copy.usage.usageDeepGet = true;
529
530                      ListAdd(value.list, copy);
531                      ListAdd(value.list, MkExpOp(exp.op.exp1, exp.op.op, exp.op.exp2));
532                      ListAdd(value.list, CopyExpression(tempExp));
533                      value.expType = tempExp.expType;
534                      value.expType.refCount++;
535
536                      //value = MkExpOp(exp.op.exp1, exp.op.op, exp.op.exp2);
537
538                      // Go on as usual with these new values:
539                      exp.op.exp1 = topExp;                  
540                      exp.op.exp2 = value;
541                      exp.op.op = '=';
542
543                      exp1 = exp.op.exp1;
544                      exp2 = exp.op.exp2;
545                   }
546                }
547             }
548
549             memberExp = exp.op.exp1;
550
551             while(memberExp && ((memberExp.type == bracketsExp && memberExp.list->count == 1) || 
552                memberExp.type == extensionExpressionExp || memberExp.type == extensionCompoundExp))
553             {
554                parentExp = memberExp;
555                if(memberExp.type == extensionCompoundExp)
556                   memberExp = ((Statement)memberExp.compound.compound.statements->last).expressions->last;
557                else
558                   memberExp = memberExp.list->last;
559             }
560
561             if(memberExp && memberExp.type == indexExp && memberExp.index.exp && memberExp.index.exp.expType && 
562                memberExp.index.exp.expType.kind == classType && memberExp.index.exp.expType._class && memberExp.index.exp.expType._class.registered &&
563                memberExp.index.exp.expType._class.registered != containerClass && eClass_IsDerived(memberExp.index.exp.expType._class.registered, containerClass))
564             {
565                ProcessExpression(memberExp);
566
567                while(memberExp && ((memberExp.type == bracketsExp && memberExp.list->count == 1) || 
568                   memberExp.type == extensionExpressionExp || memberExp.type == extensionCompoundExp))
569                {
570                   parentExp = memberExp;
571                   if(memberExp.type == extensionCompoundExp)
572                      memberExp = ((Statement)memberExp.compound.compound.statements->last).expressions->last;
573                   else
574                      memberExp = memberExp.list->last;
575                }
576
577                if(memberExp && memberExp.type == extensionCompoundExp)
578                {
579                   parentExp = memberExp;
580                   if(memberExp.type == extensionCompoundExp)
581                   {
582                      Statement stmt = memberExp.compound.compound.statements ? memberExp.compound.compound.statements->last : null;
583                      if(stmt && stmt.type != expressionStmt) stmt = null;
584                      memberExp = (stmt && stmt.expressions) ? stmt.expressions->last : null;
585                      if(memberExp)
586                      {
587                         stmt.expressions->Remove(memberExp);
588                         stmt.expressions->Add(MkExpOp(memberExp, exp.op.op, exp.op.exp2));
589                         exp.type = bracketsExp;
590                         exp.list = MkListOne(parentExp);
591                         ProcessExpression(exp);
592                         break;
593                      }
594                   }
595                   else
596                      memberExp = memberExp.list->last;
597                }
598             }
599
600             if(memberExp && memberExp.type != ExpressionType::memberExp) memberExp = null;
601
602             if(memberExp && memberExp.type == ExpressionType::memberExp)
603             {
604                Type type = memberExp.member.exp.expType;
605                if(type)
606                {
607                   // Check if it's an instance
608                   if(type.kind == classType || type.kind == subClassType)
609                   {
610                      // TODO: SOMETHING WRONG HERE...
611                      Class _class = memberExp.member.member.classSym ? (memberExp.member.member.classSym ? memberExp.member.member.classSym.registered : null) : (type._class ? type._class.registered : null);
612
613                      if(memberExp == exp1)
614                         exp1 = null;
615                      else
616                      {
617                         if(parentExp.type == extensionCompoundExp)
618                            ((Statement)parentExp.compound.compound.statements->last).expressions->Remove(memberExp);
619                         else
620                            parentExp.list->Remove(memberExp);
621                      }
622
623                      if(_class && _class.type == bitClass && memberExp.member.memberType == dataMember)
624                      {
625                          BitMember bitMember = 
626                             (BitMember)eClass_FindDataMember(_class, 
627                               memberExp.member.member.string, privateModule, null, null);
628                          char mask[32], shift[10];
629                          OldList * specs = MkList();
630                          //Declarator decl = SpecDeclFromString(bitMember.dataTypeString, specs, null);
631                          Declarator decl = SpecDeclFromString(_class.dataTypeString, specs, null);                         
632                          TypeName type = MkTypeName(specs, decl);
633
634                          if(bitMember.mask > MAXDWORD)
635                             sprintf(mask, FORMAT64HEXLL, bitMember.mask);
636                          else
637                             sprintf(mask, FORMAT64HEX, bitMember.mask);
638                          sprintf(shift, "%d", bitMember.pos);                         
639
640                          // color = (color & ~0xFF0000) | (((unsigned char)200) << 16)
641                          exp.op.exp1 = memberExp.member.exp;
642
643                          // TESTING THIS FOR: argb.color.r = 1;
644                          //ProcessExpression(memberExp.member.exp);
645
646                          // TESTING THIS... FIX ELSEWHRE... FIX FOR OTHER OPS
647                          if(exp.op.op == XOR_ASSIGN)
648                          {
649                             exp.op.exp2 = MkExpOp(MkExpBrackets(
650                                  MkListOne(MkExpCast(type, exp.op.exp2))), LEFT_OP, MkExpConstant(shift));
651                          }
652                          else
653                          {
654                             exp.op.exp2 = MkExpOp(
655                                MkExpBrackets(MkListOne(MkExpOp(CopyExpression(memberExp.member.exp), '&', 
656                                  MkExpOp(null, '~', MkExpConstant(mask))))), '|',
657                                MkExpBrackets(MkListOne(MkExpOp(MkExpBrackets(
658                                  MkListOne(MkExpCast(type, exp.op.exp2))), LEFT_OP, MkExpConstant(shift)))));
659                          }
660
661                          memberExp.member.exp = null;
662                          FreeExpression(memberExp);
663
664                          // TESTING THIS FOR: argb.color.r = 1;
665                          ProcessExpression(exp);
666                          return;
667                      }
668                      else if(_class && _class.type == unitClass && memberExp.member.memberType == dataMember)
669                      {
670                      }
671                      else if(memberExp.member.memberType != dataMember)
672                      {
673                         Property prop;
674                         Class convertTo = null;
675                         ClassProperty classProperty = null;
676
677                         if(memberExp.member.memberType == reverseConversionMember)
678                         {
679                            convertTo = _class;
680                            _class = FindClass(memberExp.member.member.string).registered;
681                            // prop = eClass_FindProperty(_class, convertTo.name, privateModule);
682                            prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
683                         }
684                         else
685                            prop = eClass_FindProperty(_class, memberExp.member.member.string, privateModule);
686
687                         if(memberExp.member.memberType == classPropertyMember)
688                            classProperty = eClass_FindClassProperty(_class, memberExp.member.member.string);
689                         
690                         exp.tempCount = memberExp.member.exp.tempCount;
691
692                         if(classProperty)
693                         {
694                            // Only process Gets here, Set is processed in opExp's '='
695                            if(classProperty.Set)
696                            {
697                               Identifier id = memberExp.member.member;
698                               Expression classExp = memberExp.member.exp;
699                               Expression value = exp.op.exp2;
700
701                               memberExp.member.exp = null;
702                               memberExp.member.member = null;
703                               exp.op.exp2 = null;
704
705                               FreeExpContents(memberExp);
706
707                               // Class Property
708                               exp.type = callExp;
709                               exp.call.exp = MkExpIdentifier(MkIdentifier("ecere::com::eClass_SetProperty"));
710                               exp.call.arguments = MkList();
711                               ListAdd(exp.call.arguments, classExp);
712                               ListAdd(exp.call.arguments, MkExpString(QMkString(id.string)));
713                               ListAdd(exp.call.arguments, MkExpCast(MkTypeName(MkListOne(MkSpecifier(INT)), null), value));
714
715                               FreeIdentifier(id);
716
717                               ProcessExpression(exp);
718                               return;
719                            }
720                         }
721                         else if(prop)
722                         {
723                            if((!convertTo && prop.Set) || (convertTo && prop.Get))
724                            {
725                               Expression value = exp.op.exp2;
726                               char setName[1024], getName[1024];
727                               char * setToUse = convertTo ? getName : setName;
728                               char * getToUse = convertTo ? setName : getName;
729                               bool needAddress = false;
730                               int operator = exp.op.op;
731                               switch(operator)
732                               {
733                                  case MUL_ASSIGN: operator = '*'; break;
734                                  case DIV_ASSIGN: operator = '/'; break;
735                                  case MOD_ASSIGN: operator = '%'; break;
736                                  case SUB_ASSIGN: operator = '-'; break;
737                                  case ADD_ASSIGN: operator = '+'; break;
738                                  case LEFT_ASSIGN: operator = LEFT_OP; break;
739                                  case RIGHT_ASSIGN: operator = RIGHT_OP; break;
740                                  case AND_ASSIGN: operator = '&'; break;
741                                  case OR_ASSIGN: operator = '|'; break;
742                                  case XOR_ASSIGN: operator = '^'; break;
743                               }
744
745                               if(operator != '=')
746                               {
747                                  if(operator == INC_OP)
748                                     value = MkExpOp(CopyExpression(memberExp), 
749                                        '+', MkExpConstant("1"));
750                                  else if(operator == DEC_OP)
751                                     value = MkExpOp(CopyExpression(memberExp), 
752                                        '-', MkExpConstant("1"));
753                                  else
754                                  {
755                                     value = MkExpOp(CopyExpression(memberExp), 
756                                        operator, value);
757                                     exp2 = null;
758                                  }
759                                  value.expType = memberExp.expType;
760                                  memberExp.expType.refCount++;
761                                  value.usage.usageArg = true;
762                               }
763                               else if(value)
764                               {
765                                  // Dont free exp2, we're using it
766                                  exp2 = null;                              
767                               }
768                         
769                               if(value)
770                                  value.usage.usageArg = true;
771
772                               DeclareProperty(prop, setName, getName);
773
774                               if(memberExp.member.exp)
775                                  ProcessExpression(memberExp.member.exp);
776
777                               // If get flag present
778                               if(exp.usage.usageGet && 
779                                  ((!convertTo && prop.Get) || (convertTo && prop.Set)))
780                               {
781                                  OldList * list = MkList();
782                                  OldList * args;
783                                  char ecereTemp[100];
784                                  Context context = PushContext();
785                                  exp.tempCount++;
786                            
787                                  curExternal.function.tempCount = Max(curExternal.function.tempCount, exp.tempCount);
788                                  sprintf(ecereTemp, "__ecTemp%d", exp.tempCount);
789
790                                  curContext = context;
791                                  exp.type = extensionCompoundExp;
792                                  exp.compound = MkCompoundStmt(
793                                     MkListOne(MkDeclaration(MkListOne(MkSpecifier(VOID)), MkListOne(MkInitDeclarator(
794                                        MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier(ecereTemp))),
795                                           MkInitializerAssignment(QBrackets(memberExp.member.exp)))))), 
796                                     list);
797
798                                  // Add the set
799                                  args = MkList();
800                                  if(convertTo)
801                                  {
802                                     ListAdd(args, value);
803                                     ListAdd(args, QMkExpId(ecereTemp));
804                                     ListAdd(list, MkExpressionStmt(MkListOne(MkExpCall(QMkExpId(getName), args))));
805                                  }
806                                  else
807                                  {
808                                     ListAdd(args, QMkExpId(ecereTemp));
809                                     ListAdd(args, value);
810                                     ListAdd(list, MkExpressionStmt(MkListOne(MkExpCall(QMkExpId(setName), args))));
811                                  }
812                               
813                                  // Add the get
814                                  args = MkList();
815                                  if(convertTo)
816                                     ListAdd(args, QMkExpId(ecereTemp));
817                                  else
818                                     args->Insert(null, QMkExpId(ecereTemp));
819                                  ListAdd(list, MkExpressionStmt(MkListOne(MkExpCall(QMkExpId(getToUse), args))));
820
821                                  exp.compound.compound.context = context;
822                                  PopContext(context);
823                                  curContext = context.parent;
824                               }
825                               else
826                               {
827                                  Expression newExp = exp;
828
829                                  if(parentExp && parentExp.type == extensionCompoundExp)
830                                  {
831                                     newExp = Expression { };
832                                     ((Statement)parentExp.compound.compound.statements->last).expressions->Add(newExp);
833                                     FreeType(exp.expType);
834                                     FreeType(exp.destType);
835                                     exp = *parentExp;
836                                     //delete parentExp;
837                                     parentExp.type = dummyExp;
838                                     parentExp.expType = null;
839                                     parentExp.destType = null;
840                                  }
841
842                                  newExp.type = callExp;
843                                  newExp.call.exp = QMkExpId(setToUse);
844                                  newExp.call.arguments = MkList();
845                                  if(convertTo)
846                                  {
847                                     ListAdd(newExp.call.arguments, value);
848                                     ListAdd(newExp.call.arguments, FixReference(memberExp.member.exp, true));
849                                  }
850                                  else
851                                  {
852                                     ListAdd(newExp.call.arguments, FixReference(memberExp.member.exp, true));
853                                     ListAdd(newExp.call.arguments, value);
854                                  }
855                                  needAddress = true;
856                               }
857
858                               // Take it out from there
859                               memberExp.member.exp = null;
860
861                               // Don't use the temporaries used by the left side...
862                               if(value)
863                               {
864                                  value.tempCount = exp.tempCount;
865                                  ProcessExpression(value);
866                                  if(needAddress)
867                                     FixReference(value, true);
868                               }
869
870                               FreeExpression(memberExp);
871                            }
872                            else
873                            {
874                               DataMember member = eClass_FindDataMember(_class, memberExp.member.member.string, privateModule, null, null);
875                               if(member)
876                               {
877                                  memberExp.member.memberType = dataMember;
878                               }
879                               else
880                                  Compiler_Error($"no set defined for property %s of class %s\n", prop.name, prop._class.fullName);
881                            }
882                         }
883                         else
884                         {
885                            Method method = eClass_FindMethod(_class, memberExp.member.member.string, privateModule);
886                            if(method && method.type == virtualMethod && type.kind != subClassType)
887                            {
888                               Expression value = exp.op.exp2;
889                               // Don't use the temporaries used by the left side...
890                               value.tempCount = exp.tempCount;
891                               ProcessExpression(value);
892
893                               if(memberExp.member.exp)
894                                  ProcessExpression(memberExp.member.exp);
895
896                               if(exp.usage.usageGet)
897                               {
898                                  OldList * list = MkList();
899                                  OldList * args;
900                            
901                                  // Set the method
902                                  args = MkList();
903                                  ListAdd(args, memberExp.member.exp);
904                                  {
905                                     char * string = QMkString(memberExp.member.member.string);
906                                     ListAdd(args, MkExpString(string));
907                                     delete string;
908                                  }
909                                  ListAdd(args, value);
910                                  ListAdd(list, MkExpCall(QMkExpId("ecere::com::eInstance_SetMethod"), args));
911                                  ListAdd(list, CopyExpression(value));
912                                  exp.type = bracketsExp;
913                                  exp.list = list;
914                               }
915                               else
916                               {
917                                  // Set the method
918                                  exp.type = callExp;
919                                  exp.call.exp = QMkExpId("ecere::com::eInstance_SetMethod");
920                                  exp.call.arguments = MkList();
921                                  ListAdd(exp.call.arguments, memberExp.member.exp);
922                                  {
923                                     char * string = QMkString(memberExp.member.member.string);
924                                     ListAdd(exp.call.arguments, MkExpString(string));
925                                     delete string;
926                                  }
927                                  ListAdd(exp.call.arguments, value);
928                               }
929
930                               memberExp.member.exp = null;
931                               exp2 = null;
932
933                               FreeExpression(memberExp);
934                            }
935                         }
936                      }
937                      else if(memberExp.member.memberType == dataMember)
938                      {
939                         //if(exp.usage & USAGE_GET);
940                         //FixReference(value, true);
941                         if(FixMember(memberExp.member.exp))
942                         {
943                            // TESTING THIS HERE:
944                            ProcessExpression(memberExp);
945
946                            memberExp.type = pointerExp;
947                         }
948                      }
949                   }
950                }
951             }
952          }
953          else if(exp.op.op == _INCREF)
954          {
955             Expression object = exp.op.exp2;
956             exp.op.exp2 = null;
957             FreeExpContents(exp);
958             exp.expType = null;
959             exp.destType = null;
960             exp.op.op = INC_OP;
961             exp.op.exp1 = MkExpPointer(object, MkIdentifier("_refCount"));
962          }
963          else if(exp.op.op == DELETE)
964          {
965             Expression object = exp.op.exp2;
966             OldList * args = MkList();
967             
968             exp.type = bracketsExp;
969             exp.list = MkList();
970
971             object.usage.usageDelete = true;
972
973             ProcessExpression(object);
974
975             ListAdd(args, object);
976
977             // TOFIX: Same time as when we fix for = 0
978
979             if(exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && 
980                ((exp.expType._class.registered.type == normalClass && 
981                   // TODO: Improve on this, only fixed this issue here... Different String class defined in each module
982                   !eClass_IsDerived(exp.expType._class.registered, eSystem_FindClass(exp.expType._class.registered.module, "char *")) /*strcmp(exp.expType._class.string, "String")*/) ||
983                 (exp.expType._class.registered.type == systemClass && !strcmp(exp.expType._class.string, "ecere::com::Instance"))))
984             {
985                Expression decRefExp = MkExpCall(QMkExpId("ecere::com::eInstance_DecRef"), args);
986                ProcessExpressionType(decRefExp);
987                ListAdd(exp.list, decRefExp);
988             }
989             else if(exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == noHeadClass)
990             {
991                /*
992                char className[1024];
993                OldList * list = MkList();
994
995                strcpy(className, "__ecereClass_");
996                FullClassNameCat(className, exp.expType._class.string, true);
997                MangleClassName(className);
998
999                DeclareClass(exp.expType._class, className);
1000                
1001                // Call the non virtual destructor
1002                ListAdd(list, MkExpCall(MkExpPointer(QMkExpId(className), MkIdentifier("Destructor")), CopyList(args, CopyExpression)));
1003                ListAdd(list, MkExpCall(QMkExpId("ecere::com::eSystem_Delete"), args));
1004
1005                ListAdd(exp.list, MkExpBrackets(MkListOne(MkExpCondition(CopyExpression(object), MkListOne(
1006                   
1007                   MkExpBrackets(MkListOne(MkExpCondition(   
1008                   MkExpPointer(QMkExpId(className), MkIdentifier("Destructor")),
1009                   MkListOne(MkExpBrackets(list)), MkExpCall(QMkExpId("ecere::com::eSystem_Delete"), CopyList(args, CopyExpression)))))), MkExpConstant("0"))))
1010                   
1011                   );
1012                */
1013
1014                OldList * list = MkList();
1015                Class _class;
1016                for(_class = exp.expType._class.registered; _class && _class.type == noHeadClass; _class = _class.base)
1017                {
1018                   char className[1024];
1019
1020                   if(_class.templateClass) _class = _class.templateClass;
1021                   strcpy(className, "__ecereClass_");
1022                   FullClassNameCat(className, _class.fullName, false /*true*/);
1023                   MangleClassName(className);
1024
1025                   if(!_class.symbol)
1026                      _class.symbol = FindClass(_class.fullName);
1027                   DeclareClass(_class.symbol, className);
1028
1029                   // Call the non virtual destructor
1030                   ListAdd(list,
1031                      MkExpCondition(
1032                         MkExpPointer(
1033                            QMkExpId(className), 
1034                            MkIdentifier("Destructor")
1035                         ),
1036                         MkListOne(
1037                            MkExpCall(
1038                               MkExpPointer(
1039                                  QMkExpId(className), 
1040                                  MkIdentifier("Destructor")
1041                               ), 
1042                               CopyList(args, CopyExpression)
1043                            )
1044                         ),
1045                         MkExpConstant("0")
1046                      )
1047                   );
1048                }
1049                ListAdd(list, MkExpCall(QMkExpId("ecere::com::eSystem_Delete"), args));
1050                ListAdd(exp.list, 
1051                   MkExpBrackets(
1052                      MkListOne(
1053                         MkExpCondition(
1054                            CopyExpression(object), 
1055                            MkListOne(
1056                               MkExpBrackets(list)
1057                            ),
1058                            MkExpConstant("0")
1059                         )
1060                      )
1061                   )
1062                );
1063             }
1064             else if(exp.expType && exp.expType.kind == templateType)
1065             {
1066                Expression argExp = GetTemplateArgExp(exp.expType.templateParameter, thisClass, false);
1067                if(argExp)
1068                {
1069                   Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
1070                   TypeName typeName;
1071                   OldList * qualifiers = MkList();
1072                   Declarator declarator = SpecDeclFromString("void (*)(void * _class, void * data)", qualifiers, null);
1073
1074                   typeName = MkTypeName(qualifiers, declarator);
1075
1076                   ProcessExpressionType(classExp);
1077                   args->Insert(null, CopyExpression(classExp));
1078                   DeclareMethod(eClass_FindMethod(eSystem_FindClass(privateModule, "class"), "OnFree", privateModule), "__ecereVMethodID_class_OnFree");
1079                   ListAdd(exp.list, MkExpCall(
1080                      MkExpBrackets(MkListOne(MkExpCast(typeName,
1081                         MkExpIndex(MkExpPointer(classExp, MkIdentifier("_vTbl")),
1082                            MkListOne(MkExpIdentifier(MkIdentifier("__ecereVMethodID_class_OnFree"))))))), args));
1083                   //ProcessExpression(exp.list->last);                  
1084                }
1085             }
1086             else
1087                ListAdd(exp.list, MkExpCall(QMkExpId("ecere::com::eSystem_Delete"), args));
1088
1089             //ProcessExpression(object);
1090
1091             ListAdd(exp.list, MkExpOp(CopyExpression(object), '=', MkExpConstant("0")));
1092
1093             exp2 = null;
1094
1095             // TESTING THIS HERE...
1096             ProcessExpression(exp);
1097          }
1098
1099          if(exp.type == opExp)
1100          {
1101             // Handle assigment of template structures
1102             if(exp.op.op == '=' && exp.op.exp1 && exp.op.exp1.expType && exp.op.exp1.expType.kind == templateType && 
1103                (exp.op.exp1.type == indexExp || (exp.op.exp1.type == opExp && exp.op.exp1.op.op == '*' && !exp.op.exp1.op.exp1)))
1104             {
1105                Expression argExp = GetTemplateArgExp(exp.op.exp1.expType.templateParameter, thisClass, false);
1106                if(argExp)
1107                {
1108                   // memcpy((byte *)array + (count * dataTypeClass.size), dataTypeClass.type == structClass) ? value : &value, dataTypeClass.size);
1109
1110                   Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
1111                   OldList * args = MkList();
1112                   Expression derefExp = exp.op.exp1;
1113                   Expression sizeExp = MkExpCondition(MkExpBrackets(MkListOne(
1114                         MkExpOp(
1115                            MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass"))), 
1116                            OR_OP,
1117                            MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass")))))),
1118                            MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)))),
1119                            MkExpMember(CopyExpression(classExp), MkIdentifier("typeSize")));
1120    
1121                   if(exp.op.exp1.type == indexExp)
1122                   {
1123                      Expression indexExp = derefExp.index.exp;
1124                      OldList * indexExpIndex = derefExp.index.index;
1125                      
1126                      derefExp.index.index = null;
1127                      derefExp.index.exp = null;
1128                      FreeExpression(derefExp);
1129
1130                      derefExp = MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null, null), null)), indexExp), '+', 
1131                         MkExpBrackets(MkListOne(MkExpOp(MkExpBrackets(indexExpIndex), '*', MkExpBrackets(MkListOne(CopyExpression(sizeExp)))))));
1132                   }
1133                   else
1134                   {
1135                      Expression indexExp = derefExp.op.exp2;
1136                      derefExp.op.exp2 = null;
1137                      FreeExpression(derefExp);
1138                      derefExp = indexExp;
1139                   }
1140                   
1141                   args->Add(derefExp);
1142                   ProcessExpressionType(args->last);
1143                   ProcessExpression(args->last);
1144
1145                   args->Add(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null, null), null)), 
1146                      MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(MkExpMember(classExp, MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("structClass"))))), 
1147                         MkListOne(exp.op.exp2), MkExpOp(null, '&', CopyExpression(exp.op.exp2)))));
1148
1149                   thisClass = curExternal.function ? curExternal.function._class : null;
1150                   {
1151                      Symbol thisSymbol
1152                      {
1153                         string = CopyString("this");
1154                         type = MkClassType(thisClass.fullName);
1155                      };
1156                      globalContext.symbols.Add((BTNode)thisSymbol);
1157                      
1158                      ProcessExpressionType(args->last);
1159                      ProcessExpression(args->last);
1160
1161                      args->Add(sizeExp);
1162                      ProcessExpressionType(args->last);
1163                      ProcessExpression(args->last);
1164                      
1165                      exp.list = MkListOne(MkExpCall(MkExpIdentifier(MkIdentifier("memcpy")), args));
1166                      exp.type = bracketsExp;
1167                   
1168                      //globalContext.symbols.Delete((BTNode)thisSymbol);
1169                      globalContext.symbols.Remove((BTNode)thisSymbol);
1170                      FreeSymbol(thisSymbol);
1171                   }
1172                   thisClass = null;
1173                   return;
1174                }
1175             }
1176             else if(exp.op.op == '*' && !exp.op.exp1 && exp.op.exp2 && exp.op.exp2.expType && exp.op.exp2.expType.kind == pointerType && 
1177                exp.op.exp2.expType.type && exp.op.exp2.expType.type.kind == templateType)
1178             {
1179                Expression argExp = GetTemplateArgExp(exp.op.exp2.expType.type.templateParameter, thisClass, false);
1180                if(argExp)
1181                {
1182                   Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
1183                   Expression sizeExp = MkExpMember(CopyExpression(classExp), MkIdentifier("typeSize"));
1184                
1185                   exp.type = bracketsExp;
1186                   exp.list = MkListOne(
1187                      // (uint64)
1188                      MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null), 
1189
1190                      // ((class.type == structClass) ?
1191                      MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("structClass"))))),
1192                         // array
1193                         MkListOne(
1194                            MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null), CopyExpression(exp.op.exp2))))),
1195
1196                      // ((class.type == normalClass || class.type == noHeadClass) ?
1197                      MkExpCondition(MkExpBrackets(MkListOne(
1198                         MkExpOp(
1199                            MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass"))), 
1200                            OR_OP,
1201                            MkExpOp(MkExpMember(classExp, MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass")))))),
1202                         // *((void **)array)
1203                         MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null), MkExpOp(null, '*', MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, MkPointer(null, null)), null)), 
1204                            CopyExpression(exp.op.exp2))))))),
1205
1206                      // ((class.size == 1) ?
1207                      MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(CopyExpression(sizeExp), EQ_OP, MkExpConstant("1")))),
1208                         // *((byte *)array)
1209                         MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)),
1210                            CopyExpression(exp.op.exp2)))))),
1211
1212                      // ((class.size == 2) ?
1213                      MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(CopyExpression(sizeExp), EQ_OP, MkExpConstant("2")))),
1214                         // *((uint16 *)array)
1215                         MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint16")), MkDeclaratorPointer(MkPointer(null, null), null)),
1216                            CopyExpression(exp.op.exp2)))))),
1217
1218                      // ((class.size == 4) ?
1219                      MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(sizeExp, EQ_OP, MkExpConstant("4")))),
1220                         // *((uint32 *)array)
1221                         MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint32")), MkDeclaratorPointer(MkPointer(null, null), null)),
1222                            CopyExpression(exp.op.exp2)))))),
1223
1224                      // *((uint64 *)array)
1225                      MkExpOp(null, '*', MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)), 
1226                         exp.op.exp2)))))))))))))))))))));
1227                   
1228                   // Add this to the context
1229                   thisClass = curExternal.function ? curExternal.function._class : null;
1230                   {
1231                      Symbol thisSymbol
1232                      {
1233                         string = CopyString("this");
1234                         type = MkClassType(thisClass.fullName);
1235                      };
1236                      globalContext.symbols.Add((BTNode)thisSymbol);
1237                      
1238                      ProcessExpressionType(exp.list->first);
1239                      ProcessExpression(exp.list->first);
1240                      
1241                      //globalContext.symbols.Delete((BTNode)thisSymbol);
1242                      globalContext.symbols.Remove((BTNode)thisSymbol);
1243                      FreeSymbol(thisSymbol);
1244                   }
1245                   thisClass = null;
1246                   return;
1247                }
1248             }
1249             else
1250             {
1251                if(exp.op.exp1)
1252                {
1253                   if(exp.op.exp2)
1254                      // TEST: exp.op.exp1.tempCount = Max(exp.op.exp1.tempCount, exp.op.exp2.tempCount);
1255                      exp.op.exp1.tempCount = exp.op.exp2.tempCount;
1256                   ProcessExpression(exp.op.exp1);
1257
1258                   // TESTING THIS...
1259                   if(exp.op.op == '=' && exp.op.exp2 && (!exp.op.exp2.byReference || 
1260                      (exp.op.exp2.expType && exp.op.exp2.expType.kind == classType && exp.op.exp2.expType._class && 
1261                       exp.op.exp2.expType._class.registered && exp.op.exp2.expType._class.registered.type == structClass)) && 
1262                      exp.op.exp2.expType && (exp.op.exp2.expType.kind != pointerType && exp.op.exp2.expType.kind != templateType /*|| !exp.op.exp2.expType.type || exp.op.exp2.expType.type.kind != voidType*/))
1263                      FixReference(exp.op.exp1, false);
1264                   // TEST: exp.tempCount = Max(exp.op.exp1.tempCount, exp.tempCount);
1265                }
1266                if(exp.op.exp2)
1267                {
1268                   // Don't use the temporaries used by the left side...
1269                   if(exp.op.exp1)
1270                      // TEST: exp.op.exp2.tempCount = Max(exp.op.exp2.tempCount, exp.op.exp1.tempCount);
1271                      exp.op.exp2.tempCount = exp.op.exp1.tempCount;
1272                   ProcessExpression(exp.op.exp2);
1273                   if(exp.op.exp1 || (exp.op.op != '*' && exp.op.op != '&'))
1274                   {
1275                      // TESTING THIS IF:
1276                      if((!exp.op.exp1 && 
1277                         (!exp.op.exp2 || !exp.op.exp2.expType || exp.op.exp2.expType.kind != classType || !exp.op.exp2.expType._class || !exp.op.exp2.expType._class.registered || 
1278                         (exp.op.exp2.expType._class.registered.type != normalClass && 
1279                          exp.op.exp2.expType._class.registered.type != structClass && 
1280                          exp.op.exp2.expType._class.registered.type != noHeadClass))) 
1281
1282                             // TESTING THIS TEMPLATE TYPE CHECK HERE
1283                         || (exp.op.exp1 && exp.op.exp1.expType && exp.op.exp1.expType.kind != pointerType && exp.op.exp1.expType.kind != templateType))
1284                      {
1285                         FixReference(exp.op.exp2, exp.op.exp1 ? exp.op.exp1.byReference : false);
1286                         //FixReference(exp.op.exp2, false);
1287                      }
1288                   }
1289                   // TEST: exp.tempCount = Max(exp.op.exp2.tempCount, exp.tempCount);
1290                }
1291             }
1292             if(exp.op.op == '*' && !exp.op.exp1 && exp.op.exp2 && exp.op.exp2.type == opExp && exp.op.exp2.op.op == '&' && !exp.op.exp2.op.exp1)
1293             {
1294                // Preserve prev, next
1295                Expression next = exp.next, prev = exp.prev;
1296                Expression derefExp = exp.op.exp2;
1297                Expression refExp = exp.op.exp2.op.exp2;
1298                Type expType = exp.expType, destType = exp.destType;
1299
1300                derefExp.op.exp2 = null;
1301                FreeExpression(derefExp);
1302                FreeType(exp.expType);
1303                FreeType(exp.destType);
1304
1305                *exp = refExp;
1306
1307                exp.prev = prev;
1308                exp.next = next;
1309
1310                delete refExp;
1311             }
1312
1313             if(exp.op.op == '&' && !exp.op.exp1 && exp.op.exp2 && exp.op.exp2.expType && exp.op.exp2.expType.kind == templateType && !exp.op.exp2.expType.passAsTemplate)
1314             {
1315                Expression exp2 = exp.op.exp2;
1316                Expression argExp = GetTemplateArgExp(exp2.expType.templateParameter, thisClass, false);
1317                if(argExp)
1318                {
1319                   Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
1320                   Expression e;
1321                   exp.type = bracketsExp;
1322                   exp.list = MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null, null), null)), 
1323                                  MkExpOp(null, '&', exp2)), '+', 
1324                                     MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), 
1325                                        MkListOne((e = MkExpCondition(MkExpBrackets(MkListOne(
1326                               
1327                               MkExpOp(
1328                                  MkExpOp(
1329                                     MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("structClass"))), 
1330                                        OR_OP,
1331                                        MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass")))), 
1332                                        OR_OP,
1333                                        MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass"))))
1334                              )),
1335                            MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)))),
1336                            MkExpMember(classExp, MkIdentifier("typeSize"))))))));
1337
1338                   // Add this to the context
1339                   thisClass = curExternal.function ? curExternal.function._class : null;
1340                   {
1341                      /*Symbol thisSymbol
1342                      {
1343                         string = CopyString("this");
1344                         type = MkClassType(thisClass.fullName);
1345                      };*/
1346                      //globalContext.symbols.Add((BTNode)thisSymbol);
1347
1348                      ProcessExpressionType(e);
1349                      ProcessExpression(e);
1350
1351                      //globalContext.symbols.Remove((BTNode)thisSymbol);
1352                      //FreeSymbol(thisSymbol);
1353                   }
1354                   thisClass = null;
1355                }
1356             }
1357          }
1358          else
1359          {
1360             if(exp1)
1361                FreeExpression(exp1);
1362             if(exp2)
1363                FreeExpression(exp2);
1364          }
1365          break;
1366       }
1367       case bracketsExp:
1368       case extensionExpressionExp:
1369       {
1370          if(exp.list)
1371          {
1372             Expression e;
1373             for(e = exp.list->first; e; e = e.next)
1374             {
1375                if(!e.next)
1376                {
1377                   e.usage |= (exp.usage & ExpUsage { usageGet = true, usageArg = true, usageMember = true });
1378                }
1379                e.tempCount = exp.tempCount;
1380                ProcessExpression(e);
1381                if(!e.next)
1382                   exp.byReference = e.byReference;
1383                exp.tempCount = e.tempCount;
1384
1385                /*
1386                if(!e.next)
1387                   exp.expType = e.expType;
1388                */
1389             }
1390          }
1391          break;
1392       }
1393       case indexExp:
1394       {
1395          Expression e;
1396          /*bool isBuiltin = exp && exp.index.exp && 
1397             (exp.index.exp.type == ExpressionType::arrayExp || 
1398               (exp.index.exp.type == castExp && exp.index.exp.cast.exp.type == ExpressionType::arrayExp));
1399          */
1400          Expression checkedExp = exp.index.exp;
1401          bool isBuiltin = false;
1402
1403          while(checkedExp.type == extensionCompoundExp || checkedExp.type == bracketsExp || checkedExp.type == castExp)
1404          {
1405             if(checkedExp.type == extensionCompoundExp)
1406             {
1407                isBuiltin = true;
1408                break;
1409             }
1410             else if(checkedExp.type == bracketsExp)
1411                checkedExp = checkedExp.list ? checkedExp.list->last : null;
1412             else
1413                checkedExp = checkedExp.cast.exp;
1414          }
1415
1416          exp.index.exp.tempCount = exp.tempCount;
1417
1418          exp.index.exp.usage.usageGet = true;
1419          ProcessExpression(exp.index.exp);
1420
1421          if(exp.index.exp.expType && exp.index.exp.expType.kind == pointerType && 
1422             exp.index.exp.expType.type && exp.index.exp.expType.type.kind == templateType)
1423          {
1424             Expression argExp = GetTemplateArgExp(exp.index.exp.expType.type.templateParameter, thisClass, false);
1425             if(argExp)
1426             {
1427                Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
1428                Expression sizeExp = MkExpMember(CopyExpression(classExp), MkIdentifier("typeSize"));
1429             
1430                exp.type = bracketsExp;
1431                exp.list = MkListOne(
1432                   // (uint64)
1433                   MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null), 
1434
1435                   // ((class.type == structClass) ?
1436                   MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("structClass"))))),
1437                      // ((byte *)array) + (i) * class.size
1438                      MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null), MkExpBrackets(MkListOne(MkExpOp(
1439                         MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), CopyExpression(exp.index.exp)))), '+', 
1440                         MkExpOp(MkExpBrackets(CopyList(exp.index.index, CopyExpression)), '*', CopyExpression(sizeExp))))))),
1441
1442                   // ((class.type == normalClass || class.type == noHeadClass) ?
1443                   MkExpCondition(MkExpBrackets(MkListOne(
1444                      MkExpOp(
1445                         MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass"))), 
1446                         OR_OP,
1447                         MkExpOp(MkExpMember(classExp, MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass")))))),
1448                      // ((void **)array)[i]
1449                      MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), null), MkExpIndex(MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, MkPointer(null, null)), null)), 
1450                         CopyExpression(exp.index.exp)))), CopyList(exp.index.index, CopyExpression)))),
1451
1452                   // ((class.size == 1) ?
1453                   MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(CopyExpression(sizeExp), EQ_OP, MkExpConstant("1")))),
1454                      // ((byte *)array)[i]
1455                      MkListOne(MkExpIndex(MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)),
1456                         CopyExpression(exp.index.exp)))), CopyList(exp.index.index, CopyExpression))),
1457
1458                   // ((class.size == 2) ?
1459                   MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(CopyExpression(sizeExp), EQ_OP, MkExpConstant("2")))),
1460                      // ((uint16 *)array)[i]
1461                      MkListOne(MkExpIndex(MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint16")), MkDeclaratorPointer(MkPointer(null, null), null)),
1462                         CopyExpression(exp.index.exp)))), CopyList(exp.index.index, CopyExpression))),
1463
1464                   // ((class.size == 4) ?
1465                   MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(sizeExp, EQ_OP, MkExpConstant("4")))),
1466                      // ((uint32 *)array)[i]
1467                      MkListOne(MkExpIndex(MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint32")), MkDeclaratorPointer(MkPointer(null, null), null)),
1468                         CopyExpression(exp.index.exp)))), CopyList(exp.index.index, CopyExpression))),
1469
1470                   // ((uint64 *)array)[i]
1471                   MkExpIndex(MkExpBrackets(MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)), 
1472                      exp.index.exp))), exp.index.index))))))))))))))))));
1473                
1474                // Add this to the context
1475                thisClass = curExternal.function ? curExternal.function._class : null;
1476                {
1477                   Symbol thisSymbol
1478                   {
1479                      string = CopyString("this");
1480                      type = MkClassType(thisClass.fullName);
1481                   };
1482                   globalContext.symbols.Add((BTNode)thisSymbol);
1483                      
1484                   ProcessExpressionType(exp.list->first);
1485                   ProcessExpression(exp.list->first);
1486                      
1487                   //globalContext.symbols.Delete((BTNode)thisSymbol);
1488                   globalContext.symbols.Remove((BTNode)thisSymbol);
1489                   FreeSymbol(thisSymbol);
1490                }
1491                thisClass = null;
1492
1493                return;
1494             }
1495          }
1496
1497          for(e = exp.index.index->first; e; e = e.next)
1498          {
1499             if(!e.next)
1500                e.usage.usageGet = true;
1501             ProcessExpression(e);
1502          }
1503          // Ignore temps in the index for now...
1504          exp.tempCount = exp.index.exp.tempCount;
1505
1506          if(exp.index.exp.expType)
1507          {
1508             Type source = exp.index.exp.expType;
1509             if(/*isBuiltin || */source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
1510                eClass_IsDerived(source._class.registered, containerClass))
1511             {
1512                Class _class = source._class.registered;
1513                bool isArray = false;
1514                Class arrayClass = eSystem_FindClass(privateModule, "Array");
1515                if(source && eClass_IsDerived(source._class.registered, arrayClass))
1516                   isArray = true;
1517                if(isArray && _class.templateArgs)
1518                {
1519                   OldList * specs = MkList();
1520                   Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, null);
1521                   TypeName typeName = MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl);
1522                   exp.index.exp = MkExpBrackets(MkListOne(MkExpCast(typeName, MkExpMember(exp.index.exp, MkIdentifier("array")))));
1523                   ProcessExpressionType(exp.index.exp);
1524                   ProcessExpression(exp);
1525                }
1526                else if(isBuiltin && _class.templateArgs)
1527                {
1528                   OldList * specs = MkList();
1529                   Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, null);
1530                   TypeName typeName = MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl);
1531                   exp.index.exp = MkExpBrackets(MkListOne(MkExpCast(typeName, 
1532                      MkExpPointer(MkExpCast(QMkType("BuiltInContainer", QMkPtrDecl(null)), exp.index.exp), MkIdentifier("data")))));
1533                   ProcessExpressionType(exp.index.exp);
1534                   ProcessExpression(exp);
1535                }
1536                else if(_class.templateArgs)
1537                {
1538                   // __extension__({ Iterator<type> i { container }; i.Index(e, [ exp.usage.usageSet ]; i.value; });
1539
1540                   char iteratorType[1024];
1541                   OldList * declarations = MkList();
1542                   OldList * statements = MkList();
1543                   OldList * args = MkList();
1544                   OldList * instMembers = MkList();
1545                   Expression expExt;
1546                   Context context = PushContext();
1547
1548                   sprintf(iteratorType, "Iterator<%s, %s >", _class.templateArgs[2].dataTypeString, _class.templateArgs[1].dataTypeString);
1549          
1550                   ListAdd(instMembers, MkMemberInit(null, MkInitializerAssignment(exp.index.exp)));
1551                   
1552                   ListAdd(declarations, MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName(iteratorType)),
1553                      MkExpIdentifier(MkIdentifier("__internalIterator")), MkListOne(MkMembersInitList(instMembers)))));
1554
1555                   ListAdd(args, MkExpBrackets(exp.index.index));
1556                   ListAdd(args, exp.usage.usageSet ? MkExpIdentifier(MkIdentifier("true")) : MkExpIdentifier(MkIdentifier("false")));
1557                   
1558                   ListAdd(statements, MkExpressionStmt(MkListOne(MkExpCall(MkExpMember(MkExpIdentifier(MkIdentifier("__internalIterator")), 
1559                      MkIdentifier("Index")), args))));
1560
1561                   // ListAdd(statements, MkExpressionStmt(MkListOne(MkExpOp(null, '&', MkExpIdentifier(MkIdentifier("__internalIterator"))))));
1562                   ListAdd(statements, MkExpressionStmt(MkListOne(MkExpMember(MkExpIdentifier(MkIdentifier("__internalIterator")), MkIdentifier("data")))));
1563
1564                   exp.type = bracketsExp;
1565                   // exp.list = MkListOne(MkExpPointer(expExt = (MkExpExtensionCompound(MkCompoundStmt(declarations, statements))), MkIdentifier("data")));
1566                   exp.list = MkListOne(expExt = (MkExpExtensionCompound(MkCompoundStmt(declarations, statements))));
1567                   expExt.compound.compound.context = context;
1568                   PopContext(context);
1569                   expExt.usage = exp.usage;
1570                   ProcessExpressionType(exp.list->first);
1571                   ProcessExpressionInstPass(exp.list->first);
1572                   ProcessExpression(exp.list->first);
1573                }
1574             }
1575          }
1576          break;
1577       }
1578       case callExp:
1579       {
1580          Expression e;
1581          Expression memberExp;
1582          bool typedObject = false;
1583          Type ellipsisDestType = null;
1584          bool usedEllipsis = false;
1585
1586          if(exp.call.arguments)
1587          {
1588             for(e = exp.call.arguments->first; e; e = e.next)
1589             {
1590                e.usage.usageGet = true;
1591                e.usage.usageArg = true;
1592                e.tempCount = Max(e.tempCount, exp.tempCount);
1593                ProcessExpression(e);
1594                exp.tempCount = Max(exp.tempCount, e.tempCount);
1595             }
1596          }
1597          exp.call.exp.usage.usageGet = true;
1598          exp.call.exp.usage.usageCall = true;
1599          exp.call.exp.tempCount = exp.tempCount;
1600          ProcessExpression(exp.call.exp);
1601          memberExp = (exp.call.exp.type == ExpressionType::memberExp) ? exp.call.exp : null;
1602
1603          if(exp.call.exp.expType && exp.call.exp.expType.kind == methodType)
1604          {
1605             Class _class = exp.call.exp.expType.methodClass;     // For Virtual Method
1606             Class argClass = exp.call.exp.expType.methodClass;  // Class actually passed
1607             Method method = exp.call.exp.expType.method;
1608             if(method.type == virtualMethod)
1609             {
1610                char name[1024];
1611                TypeName typeName;
1612                Declarator decl;
1613                Context back;
1614                OldList * specs = MkList();
1615                strcpy(name, "__ecereVMethodID_");
1616                FullClassNameCat(name, method._class.fullName, false);
1617                strcat(name, "_");
1618                strcat(name, method.name);
1619
1620                DeclareMethod(method, name);
1621
1622                back = curContext;
1623                // THIS SpecDeclFromString HERE SHOULD WORK WITH THE METHOD TEMPLATE PARAMETERS...
1624                curContext = (method._class.symbol) ? ((Symbol)method._class.symbol).ctx : globalContext;
1625                // Cast function to its type
1626                {
1627                   Context context = SetupTemplatesContext(method._class);
1628                   
1629                   decl = SpecDeclFromString(method.dataTypeString, specs, MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), null)));
1630                   
1631                   FinishTemplatesContext(context);
1632                }
1633                curContext = back;
1634                if(method.dataType && !method.dataType.staticMethod)
1635                {
1636                   Declarator funcDecl = GetFuncDecl(decl);
1637
1638                   if(!funcDecl.function.parameters)
1639                      funcDecl.function.parameters = MkList();
1640                   {
1641                      TypeName firstParam = ((TypeName)funcDecl.function.parameters->first);
1642                      Specifier firstSpec = firstParam ? firstParam.qualifiers->first : null;
1643
1644                      if(firstParam && firstSpec && firstSpec.type == baseSpecifier && firstSpec.specifier == VOID && !firstParam.declarator)
1645                         funcDecl.function.parameters->Remove(funcDecl.function.parameters->first);
1646                   }
1647
1648                   if(method.dataType.thisClass && !strcmp(method.dataType.thisClass.string, "class"))
1649                   {
1650                      typedObject = true;
1651
1652                      funcDecl.function.parameters->Insert(null, MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null)));
1653                      // Testing this for any_object::
1654                      if(!method.dataType.extraParam)
1655                         funcDecl.function.parameters->Insert(null, MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null)), MkDeclaratorPointer(MkPointer(null,null), null)));
1656                   }
1657                   else
1658                   {
1659                      funcDecl.function.parameters->Insert(null, MkTypeName(MkListOne(
1660                         /*MkClassName*/MkSpecifierName(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)), null));
1661                   }
1662                }
1663
1664                typeName = MkTypeName(specs, decl);
1665
1666                // Added !exp.call.exp.expType.methodClass
1667                if(memberExp && memberExp.member.exp.expType)
1668                {
1669                   if(memberExp.member.exp.expType.kind == classType && memberExp.member.exp.expType._class && memberExp.member.exp.expType._class.registered)
1670                   {
1671                      ClassType type = memberExp.member.exp.expType._class.registered.type;
1672                      if(type != normalClass || (method.dataType.byReference))// TESTING THIS OUT: && !memberExp.member.exp.expType.classObjectType)
1673                         argClass = memberExp.member.exp.expType._class.registered;
1674                   }
1675                   else
1676                   {
1677                      switch(memberExp.member.exp.expType.kind)
1678                      {
1679                         case intType:
1680                         {
1681                            argClass = eSystem_FindClass(privateModule, "int");
1682                            break;
1683                         }
1684                      }
1685                   }
1686                   /*
1687                   if(!_class && argClass && strcmp(argClass.fullName, "class"))
1688                      _class = argClass;
1689                   */
1690                }
1691
1692                // *** Added !_class here
1693                if(!exp.call.exp.expType.methodClass && (!memberExp || !_class) && memberExp.member.exp.expType && memberExp.member.exp.expType.classObjectType)
1694                {
1695                   if(memberExp.member.exp.expType.kind == classType && memberExp.member.exp.expType._class &&
1696                      memberExp.member.exp.expType._class.registered && memberExp.member.exp.expType._class.registered.type == normalClass)
1697                   {
1698                      // TOCHECK: Added this if statement here for File::OnSerialize to be calling the instance's own Seek function,
1699                      // as opposed to the File class vTbl one
1700                      exp.call.exp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1701                         MkExpIndex(MkExpPointer(MkExpBrackets(MkListOne(CopyExpression(memberExp.member.exp))), MkIdentifier("_vTbl")),
1702                         MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1703                   }
1704                   else
1705                   {
1706                      exp.call.exp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1707                         MkExpIndex(MkExpPointer(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("_vTbl")),
1708                         MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1709                   }
1710                }
1711                else if(memberExp && !_class && exp.call.exp.expType._class &&
1712                      (memberExp.member.exp.expType.kind == subClassType || (memberExp.member.exp.expType.kind == classType && memberExp.member.exp.expType._class &&
1713                      memberExp.member.exp.expType._class.registered && memberExp.member.exp.expType._class.registered.type == normalClass)))
1714                {
1715                   exp.call.exp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1716                      MkExpIndex(MkExpPointer(CopyExpression(memberExp.member.exp), MkIdentifier("_vTbl")),
1717                      MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1718                }
1719                else 
1720                {
1721                   char className[1024];
1722
1723                   // TESTING: Moved this here...
1724                   if(!_class && argClass && strcmp(argClass.fullName, "class"))
1725                      _class = argClass;
1726
1727                   if(!_class)
1728                   {
1729                      // TODO: Unhandled case here, what should happen?
1730                      _class = class(int);
1731                   }
1732
1733                   // Need the class itself here...
1734                   strcpy(className, "__ecereClass_");
1735                   FullClassNameCat(className, _class.fullName, true);
1736                   MangleClassName(className);
1737
1738                   if(!_class.symbol)
1739                      _class.symbol = FindClass(_class.fullName);
1740
1741                   DeclareClass(_class.symbol, className);
1742
1743                   exp.call.exp = MkExpBrackets(MkListOne(MkExpCast(typeName,
1744                      MkExpIndex(MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl")),
1745                      MkListOne(MkExpIdentifier(MkIdentifier(name)))))));
1746                }
1747             }
1748             else
1749             {
1750                char name[1024];
1751                strcpy(name, "__ecereMethod_");
1752                FullClassNameCat(name, method._class.fullName, false);
1753                strcat(name, "_");
1754                strcat(name, method.name);
1755
1756                exp.call.exp = MkExpIdentifier(MkIdentifier(name));
1757                DeclareMethod(method, name);
1758                if(memberExp && memberExp.expType && method.dataType)
1759                {
1760                   exp.call.exp.expType = method.dataType;
1761                   method.dataType.refCount++;
1762                }
1763             }
1764             if(memberExp && (!memberExp.member.exp || !memberExp.member.exp.expType || memberExp.member.exp.expType.kind != subClassType))
1765             {
1766                if(method.dataType && !method.dataType.staticMethod && !method.dataType.extraParam)
1767                {
1768                   if(!exp.call.arguments)
1769                      exp.call.arguments = MkList();
1770
1771                   // Testing this (COMMENTED OUT TESTING, CALLING METHODS ON ENUM/UNIT ADDED & IN FRONT OF VARIABLES
1772                   /*
1773                   if(memberExp.member.exp.expType.kind != classType || 
1774                      memberExp.member.exp.expType._class.registered.type == enumClass ||
1775                      memberExp.member.exp.expType._class.registered.type == unitClass)
1776                   {
1777                      char typeString[1024] = "";
1778                      if(memberExp.member.exp.expType.kind != classType)
1779                         PrintType(memberExp.member.exp.expType, typeString, false, true);
1780                      else
1781                         strcpy(typeString, memberExp.member.exp.expType._class.registered.dataTypeString);
1782
1783                      // THIS WAS NASTY:
1784                      // memberExp.member.exp.expType.kind = classType;
1785                      // memberExp.member.exp.expType._class = FindClass(typeString);
1786                      
1787                      FreeType(memberExp.member.exp.expType);
1788                      memberExp.member.exp.expType = Type
1789                      {
1790                         kind = classType;
1791                         _class = FindClass(typeString);
1792                         refCount = 1;
1793                      };
1794
1795                      // Default to an int instead
1796                      if(!memberExp.member.exp.expType._class)
1797                      {
1798                         // TODO: Shouldn't get here...
1799                         memberExp.member.exp.expType.kind = TypeInt;
1800                      }
1801                   }
1802                   */
1803                   
1804                   if(typedObject && memberExp.member.exp && memberExp.member.exp.expType)
1805                   {
1806                      if(
1807                         (argClass && (argClass.type == enumClass || argClass.type == unitClass || argClass.type == bitClass || argClass.type == systemClass) && strcmp(argClass.fullName, "class") && strcmp(argClass.fullName, "ecere::com::Class")) || // Patched so that class isn't considered SYSTEM...
1808                         (!memberExp.member.exp.expType.classObjectType && 
1809                         (((
1810                            (memberExp.member.exp.expType.kind != pointerType && (memberExp.member.exp.expType.kind != classType || !memberExp.member.exp.expType._class || 
1811                            !memberExp.member.exp.expType._class.registered ||
1812                            memberExp.member.exp.expType._class.registered.type == structClass)))) ||
1813                            method.dataType.byReference)))      // ADDED THIS FOR OnGetDataFromString
1814                      {
1815                         if(memberExp.member.exp.type == opExp && memberExp.member.exp.op.op == '*' && !memberExp.member.exp.op.exp1)
1816                         {
1817                            exp.call.arguments->Insert(null, memberExp.member.exp.op.exp2);
1818                            memberExp.member.exp.op.exp2 = null;
1819                         }
1820                         else if(!memberExp.member.exp.byReference)
1821                         {
1822                            // TESTING THIS... REUSE THIS CODE?
1823                            Expression checkedExp = memberExp.member.exp;
1824                            Expression parentExp = null;
1825                            Expression newExp;
1826                            while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp) && checkedExp.list) || checkedExp.type == castExp)
1827                            {
1828                               parentExp = checkedExp;
1829                               if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp)
1830                                  checkedExp = checkedExp.list->last;
1831                               else if(checkedExp.type == castExp)
1832                                  checkedExp = checkedExp.cast.exp;
1833                            }
1834                            newExp = MkExpOp(null, '&', checkedExp);
1835                            if(parentExp && (parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp))
1836                            {
1837                               parentExp.list->Remove(checkedExp);
1838                               parentExp.list->Add(newExp);
1839                            }
1840                            else if(parentExp && parentExp.type == castExp)
1841                               parentExp.cast.exp = newExp;
1842
1843                            exp.call.arguments->Insert(null, parentExp ? parentExp : newExp);
1844                         }
1845                         else
1846                            exp.call.arguments->Insert(null, memberExp.member.exp);
1847                      }
1848                      else
1849                         exp.call.arguments->Insert(null, memberExp.member.exp);
1850
1851                      //if(memberExp.member.exp && memberExp.member.exp.type == identifierExp && !strcmp(memberExp.member.exp.identifier.string, "this") && FindSymbol("class", curContext, topContext, false))
1852                      if(memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.classObjectType == ClassObjectType::typedObject)
1853                      {
1854                         exp.call.arguments->Insert(null, MkExpIdentifier(MkIdentifier("class")));
1855                      }
1856                      else
1857                      {
1858                         if(memberExp && !argClass)
1859                            exp.call.arguments->Insert(null, MkExpPointer(CopyExpression(memberExp.member.exp), MkIdentifier("_class")));
1860                         else
1861                         {
1862                            char className[1024];
1863                            // Need the class itself here...
1864                            strcpy(className, "__ecereClass_");
1865                            FullClassNameCat(className, argClass.fullName, true);
1866                            MangleClassName(className);
1867
1868                            if(!argClass.symbol)
1869                               argClass.symbol = FindClass(argClass.fullName);
1870                            DeclareClass(argClass.symbol, className);
1871                            exp.call.arguments->Insert(null, MkExpIdentifier(MkIdentifier(className)));
1872                         }
1873                      }
1874                   }
1875                   else
1876                      exp.call.arguments->Insert(null, memberExp.member.exp);
1877                   memberExp.member.exp = null;
1878                }
1879                FreeExpression(memberExp);
1880             }
1881             /*else if(method->dataType)
1882             {
1883             }*/
1884          }
1885          if(exp.call.arguments)
1886          {
1887             for(e = exp.call.arguments->first; e; e = e.next)
1888             {
1889                Type destType = (e.destType && e.destType.kind == ellipsisType) ? ellipsisDestType : e.destType;
1890                //if(e.destType && e.destType.kind == classType && e.destType._class && !strcmp(e.destType._class.string, "class"))
1891                //if(e.destType && (e.destType.classObjectType == ClassObjectType::typedObject || e.destType.classObjectType == anyObject))
1892                if(destType && (destType.classObjectType == ClassObjectType::typedObject || destType.classObjectType == anyObject))
1893                {
1894                   if(e.destType && e.destType.kind == ellipsisType) usedEllipsis = true;
1895                   ellipsisDestType = destType;
1896                   if(e && e.expType)
1897                   {
1898                      Type type = e.expType;
1899                      Class _class = null;
1900                      //Type destType = e.destType;
1901
1902                      if(type.kind == classType && type._class && type._class.registered)
1903                      {
1904                         _class = type._class.registered;
1905                      }
1906                      else if(type.kind == subClassType)
1907                      {
1908                         _class = FindClass("ecere::com::Class").registered;
1909                      }
1910                      else if((type.kind == arrayType || type.kind == pointerType) && type.type && type.type.kind == charType)
1911                      {
1912                         _class = FindClass("char *").registered;
1913                      }
1914                      else
1915                      {
1916                         char string[1024] = "";
1917                         Symbol classSym;
1918
1919                         PrintType(type, string, false, true);
1920                         classSym = FindClass(string);
1921                         if(classSym) _class = classSym.registered;
1922                         // if(!class) _class = eSystem_FindClass(privateModule, "int");
1923                      }
1924
1925                      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...
1926                         (!e.expType.classObjectType && (((type.kind != pointerType && type.kind != subClassType && type.kind != arrayType && (type.kind != classType || !type._class || !type._class.registered || type._class.registered.type == structClass))) ||
1927                         destType.byReference)))
1928                      {
1929                         //if(!_class || strcmp(_class.fullName, "String"))     // TESTING THIS WITH NEW String class...
1930                         //if(!_class || strcmp(_class.fullName, "char *"))     // TESTING THIS WITH NEW String class...
1931                         // TESTING WITHOUT THE ABOVE NOW!
1932                         {
1933                            Expression checkedExp;
1934                            Expression parentExp;
1935                            Expression newExp;
1936
1937                            checkedExp = e;
1938                            parentExp = exp;
1939                            while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
1940                            {
1941                               parentExp = checkedExp;
1942                               if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
1943                               {
1944                                  if(checkedExp.type == extensionCompoundExp)
1945                                  {
1946                                     checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
1947                                  }
1948                                  else
1949                                     checkedExp = checkedExp.list->last;
1950                               }
1951                               else if(checkedExp.type == castExp)
1952                                  checkedExp = checkedExp.cast.exp;
1953                            }
1954
1955                            if(checkedExp && checkedExp.type == opExp && checkedExp.op.op == '*' && !checkedExp.op.exp1)
1956                            {
1957                               /*
1958                               Expression newExp = e.op.exp2;
1959                               exp.call.arguments->Insert(e.prev, newExp);
1960                               exp.call.arguments->Remove(e);
1961                               e.op.exp2 = null;
1962                               FreeExpContents(e);
1963                               e = newExp;
1964                               */
1965                               newExp = checkedExp.op.exp2;
1966                               checkedExp.op.exp2 = null;
1967                               FreeExpContents(checkedExp);
1968                               
1969                               if(e.expType && e.expType.passAsTemplate)
1970                               {
1971                                  char size[100];
1972                                  ComputeTypeSize(e.expType);
1973                                  sprintf(size, "%d", e.expType.size);
1974                                  newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
1975                                     MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
1976                                        MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
1977                               }
1978
1979                               if(parentExp.type == callExp)
1980                               {                              
1981                                  exp.call.arguments->Insert(e.prev, newExp);
1982                                  exp.call.arguments->Remove(e);
1983                                  e = newExp;
1984                               }
1985                               else if(parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp)
1986                               {
1987                                  parentExp.list->Remove(checkedExp);
1988                                  parentExp.list->Add(newExp);
1989                               }
1990                               else if(parentExp.type == castExp)
1991                               {
1992                                  // NEW CODE: BETTER WAY TO DO THIS? To prevent (double)(double *)
1993                                  if(parentExp.destType && parentExp.destType.kind == ellipsisType)
1994                                  {
1995                                     FreeTypeName(parentExp.cast.typeName);
1996                                     parentExp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null));
1997                                  }
1998                                  parentExp.cast.exp = newExp;
1999                               }
2000                               else if(parentExp.type == extensionCompoundExp)
2001                               {
2002                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Remove(checkedExp);
2003                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Add(newExp);
2004                               }
2005                               e.byReference = true;
2006
2007                               FreeType(checkedExp.expType);
2008                               FreeType(checkedExp.destType);
2009                               delete checkedExp;
2010                            }
2011                            else if((!e.byReference && (!e.expType || !e.expType.classObjectType) ) || (_class && _class.type == noHeadClass))     // TESTING THIS HERE...
2012                            {
2013                               Expression checkedExp;
2014                               Expression parentExp;
2015                               Expression newExp;
2016
2017                               {
2018                                  // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
2019                                  bool hasAddress =
2020                                     e.type == identifierExp ||
2021                                     (e.type == ExpressionType::memberExp && e.member.memberType == dataMember) ||
2022                                     (e.type == ExpressionType::pointerExp && e.member.memberType == dataMember) ||
2023                                     (e.type == opExp && !e.op.exp1 && e.op.op == '*') ||
2024                                     e.type == indexExp;
2025
2026                                  if(_class && _class.type != noHeadClass && _class.type != normalClass && _class.type != structClass && !hasAddress)
2027                                  {
2028                                     Context context = PushContext();
2029                                     Declarator decl;
2030                                     OldList * specs = MkList();
2031                                     char typeString[1024];
2032                                     Expression newExp { };
2033
2034                                     typeString[0] = '\0';
2035                                     *newExp = *e;
2036
2037                                     // TOCHECK: Should this read e.destType ???
2038
2039                                     if(exp.destType) exp.destType.refCount++;
2040                                     // if(exp.expType) exp.expType.refCount++;
2041                                     newExp.prev = null;
2042                                     newExp.next = null;
2043                                     newExp.expType = null;
2044
2045                                     PrintType(e.expType, typeString, false, true);
2046                                     decl = SpecDeclFromString(typeString, specs, null);
2047                                     newExp.destType = ProcessType(specs, decl);
2048
2049                                     curContext = context;
2050                                     e.type = extensionCompoundExp;
2051
2052                                     // We need a current compound for this
2053                                     if(curCompound)
2054                                     {
2055                                        char name[100];
2056                                        OldList * stmts = MkList();
2057                                        sprintf(name, "__internalValue%03X", internalValueCounter++);
2058                                        if(!curCompound.compound.declarations)
2059                                           curCompound.compound.declarations = MkList();
2060                                        curCompound.compound.declarations->Insert(null, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(name)), null))));
2061                                        ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', newExp))));
2062                                        ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier(name)))));
2063                                        e.compound = MkCompoundStmt(null, stmts);
2064                                     }
2065                                     else
2066                                        printf("libec: compiler error, curCompound is null in ApplyAnyObjectLogic\n");
2067
2068                                     /*
2069
2070                                     e.compound = MkCompoundStmt(
2071                                        MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))), 
2072                                        MkListOne(MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier("__internalValue"))))));
2073                                     */
2074                                     
2075                                     e.compound.compound.context = context;
2076                                     PopContext(context);
2077                                     curContext = context.parent;
2078                                  }
2079                               }
2080
2081                               // TODO: INTEGRATE THIS WITH VERSION ABOVE WHICH WAS ADDED TO ENCOMPASS OTHER CASE (*pointer)
2082                               checkedExp = e;
2083                               parentExp = exp;
2084                               while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
2085                               {
2086                                  parentExp = checkedExp;
2087                                  if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
2088                                  {
2089                                     if(checkedExp.type == extensionCompoundExp)
2090                                     {
2091                                        checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
2092                                     }
2093                                     else
2094                                        checkedExp = checkedExp.list->last;
2095                                  }
2096                                  else if(checkedExp.type == castExp)
2097                                     checkedExp = checkedExp.cast.exp;
2098                               }
2099                               newExp = MkExpOp(null, '&', checkedExp);
2100                               newExp.byReference = true;
2101                               if(parentExp.type == callExp)
2102                               {                              
2103                                  exp.call.arguments->Insert(e.prev, newExp);
2104                                  exp.call.arguments->Remove(e);
2105                                  e = newExp;
2106                               }
2107                               else if(parentExp.type == bracketsExp || parentExp.type == extensionExpressionExp)
2108                               {
2109                                  parentExp.list->Remove(checkedExp);
2110                                  parentExp.list->Add(newExp);
2111                               }
2112                               else if(parentExp.type == castExp)
2113                                  parentExp.cast.exp = newExp;
2114                               else if(parentExp.type == bracketsExp || parentExp.type == extensionCompoundExp)
2115                               {
2116                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Remove(checkedExp);
2117                                  ((Statement)parentExp.compound.compound.statements->last).expressions->Add(newExp);
2118                               }
2119                            }
2120                         }
2121                      }
2122                      
2123                      if(destType.classObjectType == ClassObjectType::typedObject)
2124                      {
2125                         char className[1024];
2126                         // Need the class itself here...
2127                         if(!_class && type.kind == pointerType && type.type && type.type.kind == charType)
2128                            _class = eSystem_FindClass(privateModule, "String");
2129                         if(!_class) _class = eSystem_FindClass(privateModule, "int");
2130
2131                         if(!strcmp(_class.name, "class"))
2132                         {
2133                            // Already inside a typed_object function, pass the class through
2134                            strcpy(className, "class");
2135                         }
2136                         else
2137                         {
2138                            strcpy(className, "__ecereClass_");
2139                            FullClassNameCat(className, _class.fullName, true);
2140                            MangleClassName(className);
2141
2142                            if(!_class.symbol)
2143                               _class.symbol = FindClass(_class.fullName);
2144
2145                            DeclareClass(_class.symbol, className);
2146                         }
2147                         exp.call.arguments->Insert(e.prev, MkExpIdentifier(MkIdentifier(className)));
2148                      }
2149                   }
2150                }
2151                {
2152 #ifdef _DEBUG
2153                   //char debugString[4096] = "";
2154                   //PrintExpression(e, debugString);
2155 #endif
2156                   // If expression type is a simple class, make it an address
2157                   FixReference(e, true);
2158                }
2159             }
2160             if(ellipsisDestType)
2161             {
2162                if(usedEllipsis || 
2163                   (exp.call.exp.expType && exp.call.exp.expType.kind == functionType && exp.call.exp.expType.params.last && 
2164                    ((Type)exp.call.exp.expType.params.last).kind == ellipsisType))
2165                {
2166                   exp.call.arguments->Insert(exp.call.arguments->last, MkExpConstant("0"));
2167                }
2168             }
2169          }
2170          break;
2171       }
2172       case memberExp:
2173       {
2174          bool changeToPtr = false;
2175          bool noHead = false;
2176          Type type = exp.member.exp.expType;
2177          Specifier memberClassSpecifier = exp.member.member ? exp.member.member._class : null;
2178          if(exp.member.member) exp.member.member._class = null;
2179
2180          if(type && type.kind == templateType)
2181          {
2182             Type baseType = ProcessTemplateParameterType(type.templateParameter);
2183             if(baseType) type = baseType;
2184          }
2185          if(type && exp.member.member && !type.directClassAccess)
2186          {
2187             Class _class = exp.member.member.classSym ? exp.member.member.classSym.registered : (((type.kind == classType || type.kind == subClassType) && type._class) ? type._class.registered : null);
2188             Property prop = null;
2189             ClassProperty classProperty = null;
2190             Method method = null;
2191             Class convertTo = null;
2192             DataMember member = null;
2193             bool thisPtr = exp.member.thisPtr;
2194             if(type.kind == subClassType && exp.member.exp.type == classExp)
2195                _class = eSystem_FindClass(privateModule, "ecere::com::Class");
2196
2197             // TEST: exp.member.exp.tempCount = Max(exp.tempCount, exp.member.exp.tempCount);
2198
2199             if(!_class)
2200             {
2201                // DANGER: Buffer overflow
2202                char string[2048] = "";
2203                Symbol classSym;
2204                PrintType(type, string, false, true);
2205                classSym = FindClass(string);
2206                _class = classSym ? classSym.registered : null;
2207             }
2208
2209             if(_class && exp.member.memberType == dataMember)
2210             {
2211                if(!thisPtr && !exp.member.member.classSym)
2212                   member = eClass_FindDataMember(_class, exp.member.member.string, null, null, null);
2213                if(!member)
2214                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, null, null);
2215             }
2216             else if(_class && exp.member.memberType == propertyMember)
2217             {
2218                if(!thisPtr && !exp.member.member.classSym)
2219                   prop = eClass_FindProperty(_class, exp.member.member.string, null);
2220                if(!prop)
2221                   prop = eClass_FindProperty(_class, exp.member.member.string, privateModule);
2222                if(prop && (exp.usage.usageRef || 
2223                   (exp.usage.usageGet && !prop.Get && !prop.conversion) ||
2224                   (exp.usage.usageDelete && !prop.Set && !prop.conversion)))
2225                {
2226                   member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, null, null);
2227                   if(member)
2228                   {
2229                      exp.member.memberType = dataMember;
2230                      prop = null;
2231                   }
2232                   else 
2233                   {
2234                      if(exp.usage.usageRef)
2235                         Compiler_Error($"cannot obtain address of property\n");
2236                      else if(!prop.Get)
2237                         Compiler_Error($"no get defined for property %s of class %s\n", prop.name, prop._class.fullName);
2238                      else if(exp.usage.usageDelete)
2239                         Compiler_Error($"no get defined for property %s of class %s\n", prop.name, prop._class.fullName);
2240                   }
2241                }
2242             }
2243             else if(_class && exp.member.memberType == methodMember)
2244             {
2245                if(!thisPtr)
2246                   method = eClass_FindMethod(_class, exp.member.member.string, null);
2247                if(!method)
2248                   method = eClass_FindMethod(_class, exp.member.member.string, privateModule);
2249             }
2250             else if(_class && exp.member.memberType == reverseConversionMember)
2251             {
2252                convertTo = _class;
2253                _class = FindClass(exp.member.member.string).registered;
2254                // prop = eClass_FindProperty(_class, convertTo.name, privateModule);
2255                prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
2256             }
2257             else if(_class && exp.member.memberType == classPropertyMember)
2258             {
2259                classProperty = eClass_FindClassProperty(_class, exp.member.member.string);
2260             }
2261             if(prop)
2262             {
2263                // Only process Gets here, Set is processed in opExp's '='
2264                if(exp.usage.usageGet)
2265                {
2266                   if(prop.Get)
2267                   {
2268                      char getName[1024], setName[1024];
2269                      Expression ptr = exp.member.exp;
2270                      Class propertyClass;
2271                      char * nameToUse = convertTo ? setName : getName;
2272
2273                      FreeIdentifier(exp.member.member);
2274
2275                      // Process this here since it won't be processed at the end...
2276                      exp.member.exp.usage.usageGet = true;
2277                      ProcessExpression(exp.member.exp);
2278                      // TEST: exp.tempCount = exp.member.exp.tempCount;
2279
2280                      DeclareProperty(prop, setName, getName);
2281                      //propertyClass = convertTo ? _class : ((Symbol)prop.symbol)._class;
2282                      propertyClass = convertTo ? _class : 
2283                         ((((Symbol)prop.symbol).type && ((Symbol)prop.symbol).type.kind == classType) ? ((Symbol)prop.symbol).type._class.registered : ((Symbol)prop.symbol)._class);
2284
2285
2286                      if(propertyClass && propertyClass.type == bitClass)
2287                      {
2288                         // Bit classes shouldn't have properties except for conversions...
2289                         OldList * args = MkList();
2290                         if(exp.usage.usageDeepGet)
2291                         {
2292                            char className[1024];
2293                            Declaration decl;
2294                            Declarator declarator;
2295                            OldList * specs = MkList(), * decls = MkList();
2296                            Expression tempExp;
2297
2298                            // Make a declaration in the closest compound statement
2299                            // (Do not reuse (since using address for function calls)...)
2300                            sprintf(className, "__simpleStruct%d", curContext.simpleID++);
2301                            declarator = 
2302                               SpecDeclFromString(propertyClass.dataTypeString, specs, 
2303                                  MkDeclaratorIdentifier(MkIdentifier(className)));
2304
2305                            ListAdd(decls, MkInitDeclarator(declarator, null));
2306
2307                            decl = MkDeclaration(specs, decls);
2308                            if(!curCompound.compound.declarations)
2309                               curCompound.compound.declarations = MkList();
2310                            curCompound.compound.declarations->Insert(null, decl);
2311
2312                            tempExp = QMkExpId(className);
2313                            tempExp.expType = MkClassType(propertyClass.fullName);
2314
2315                            exp.op.exp1 = tempExp;
2316                            exp.op.exp2 = MkExpCall(QMkExpId(nameToUse), args);
2317                            exp.op.op = '=';
2318                            exp.type = opExp;
2319                         }
2320                         else
2321                         {
2322                            exp.type = callExp;
2323                            exp.call.exp = QMkExpId(nameToUse);
2324                            exp.call.arguments = args;
2325                         }
2326                         ListAdd(args, FixReference(ptr, true));
2327                      }
2328                      else if(propertyClass && propertyClass.type == unitClass)
2329                      {
2330                         OldList * args = MkList();
2331                         ListAdd(args, FixReference(ptr, true));
2332                         exp.type = callExp;
2333                         exp.call.exp = QMkExpId(nameToUse);
2334                         exp.call.arguments = args;
2335                      }
2336                      else if(propertyClass && propertyClass.type == structClass)
2337                      {
2338                         OldList * args = MkList();
2339                         char className[1024];
2340                         Declaration decl;
2341                         OldList * specs = MkList(), * decls = MkList();
2342                         Expression tempExp;
2343
2344                         // Make a declaration in the closest compound statement
2345                         // (Do not reuse (since using address for function calls)...)
2346
2347                         className[0] = 0;
2348                         FullClassNameCat(className, propertyClass.fullName, false); //true);
2349
2350                         //ListAdd(specs, MkSpecifierName(className));
2351                         ListAdd(specs, MkStructOrUnion(structSpecifier, MkIdentifier(className), null));
2352
2353                         sprintf(className, "__simpleStruct%d", curContext.simpleID++);
2354
2355                         ListAdd(decls, MkInitDeclarator(
2356                            MkDeclaratorIdentifier(MkIdentifier(className)), null));
2357
2358                         decl = MkDeclaration(specs, decls);
2359                         if(curCompound)
2360                         {
2361                            if(!curCompound.compound.declarations)
2362                               curCompound.compound.declarations = MkList();
2363                            curCompound.compound.declarations->Insert(null, decl);
2364                         }
2365
2366                         tempExp = QMkExpId(className);
2367                         tempExp.expType = MkClassType(propertyClass.fullName);
2368
2369                         if(convertTo)
2370                         {
2371                            ListAdd(args, FixReference(CopyExpression(tempExp), true));
2372                            ListAdd(args, FixReference(ptr, true));
2373                         }
2374                         else
2375                         {
2376                            ListAdd(args, FixReference(ptr, true));
2377                            ListAdd(args, FixReference(CopyExpression(tempExp), true));
2378                         }
2379
2380                         if(exp.usage.usageDeepGet)
2381                         {
2382                            exp.type = callExp;
2383                            exp.call.exp = QMkExpId(nameToUse);
2384                            exp.call.arguments = args;
2385
2386                            FreeExpression(tempExp);
2387                         }
2388                         else
2389                         {
2390                            exp.type = bracketsExp;
2391                            exp.list = MkList();
2392                            ListAdd(exp.list, MkExpCall(QMkExpId(nameToUse),args));
2393                            if(exp.usage.usageMember)
2394                            {
2395                               ListAdd(exp.list, FixReference(tempExp, true));
2396                               exp.byReference = true;
2397                            }
2398                            else
2399                               ListAdd(exp.list, tempExp);
2400                         }
2401                      }
2402                      else
2403                      {
2404                         exp.type = callExp;
2405                         exp.call.exp = QMkExpId(nameToUse);
2406                         exp.call.arguments = MkList();
2407                         ListAdd(exp.call.arguments, FixReference(ptr, true));
2408                      }
2409                   }
2410                   else if(prop.conversion)
2411                   {
2412                      void * prev = exp.prev, * next = exp.next;
2413                      *exp = *exp.member.exp;
2414                      exp.prev = prev;
2415                      exp.next = next;
2416                   }
2417                }
2418             }
2419             else if(classProperty)
2420             {
2421                // Only process Gets here, Set is processed in opExp's '='
2422                if(exp.usage.usageGet)
2423                {
2424                   if(classProperty.Get)
2425                   {
2426                      Identifier id = exp.member.member;
2427                      Expression classExp = exp.member.exp;
2428
2429                      // Class Property
2430                      exp.type = callExp;
2431                      exp.call.exp = MkExpIdentifier(MkIdentifier("ecere::com::eClass_GetProperty"));
2432                      exp.call.arguments = MkList();
2433                      ListAdd(exp.call.arguments, classExp);
2434                      ListAdd(exp.call.arguments, MkExpString(QMkString(id.string)));
2435                      FreeIdentifier(id);
2436
2437                      ProcessExpression(exp);
2438                      return;
2439                   }
2440                }
2441             }
2442             else if(method)
2443             {
2444                // Get the function address if it's not called
2445                if((exp.usage.usageGet || exp.member.exp.expType.kind == subClassType) && !(exp.usage.usageCall))
2446                {
2447                   char name[1024];
2448
2449                   FreeIdentifier(exp.member.member);
2450
2451                   // Process this here since it won't be processed at the end...
2452                   exp.member.exp.usage.usageGet = true;
2453                   ProcessExpression(exp.member.exp);
2454                   // TEST: exp.tempCount = exp.member.exp.tempCount;
2455
2456                   if(method.type == virtualMethod)
2457                   {
2458                      strcpy(name, "__ecereVMethodID_");
2459                      FullClassNameCat(name, method._class.fullName, false);
2460                      strcat(name, "_");
2461                      strcat(name, method.name);
2462                      exp.type = indexExp;
2463                      if(memberClassSpecifier)
2464                      {
2465                         char className[1024];
2466                         // Need the class itself here...
2467                         strcpy(className, "__ecereClass_");
2468                         FullClassNameCat(className, _class.fullName, true);
2469                         MangleClassName(className);
2470
2471                         if(!_class.symbol)
2472                            _class.symbol = FindClass(_class.fullName);
2473                         DeclareClass(_class.symbol, className);
2474                         exp.index.exp = MkExpPointer(MkExpIdentifier(MkIdentifier(className)), MkIdentifier("_vTbl"));
2475
2476                         // WHAT HAPPENS TO exp.member.exp ?
2477                      }
2478                      else
2479                      {
2480                         if(exp.thisPtr && _class.type != normalClass)
2481                         {
2482                            FreeExpression(exp.member.exp);
2483                            exp.index.exp = MkExpPointer(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("_vTbl"));
2484                         }
2485                         else
2486                            exp.index.exp = MkExpPointer(exp.member.exp, MkIdentifier("_vTbl"));
2487                      }
2488                      exp.index.index = MkListOne(QMkExpId(name));
2489                      DeclareMethod(method, name);
2490                   }
2491                   else
2492                   {
2493                      FreeExpression(exp.member.exp);
2494                      exp.type = identifierExp;
2495                      strcpy(name, "__ecereMethod_");
2496                      FullClassNameCat(name, method._class.fullName, false);
2497                      strcat(name, "_");
2498                      strcat(name, method.name);
2499                      exp.identifier = MkIdentifier(name);
2500                      DeclareMethod(method, name);
2501                   }
2502                }
2503             }
2504             else if(member)
2505             {
2506                // Process this here since it won't be processed at the end...
2507                if(exp.usage.usageGet)
2508                {
2509                   exp.member.exp.usage.usageGet = true;   // Recently added this... is it ok?
2510                }
2511                ProcessExpression(exp.member.exp);
2512                // TEST: exp.tempCount = exp.member.exp.tempCount;
2513
2514                if(type.kind == classType)
2515                   DeclareStruct(type._class.registered.fullName, false);
2516
2517                // TESTING THIS NOHEAD STUFF...
2518                if(_class.type == noHeadClass)
2519                {
2520                   noHead = true;
2521                }
2522                else if(_class.type == structClass)
2523                {
2524                   changeToPtr = true;
2525                }
2526                else if(_class.type == bitClass)
2527                {
2528                   OldList * list = MkList();
2529                   char mask[32], shift[10];
2530                   OldList * specs = MkList();
2531                   BitMember bitMember = (BitMember) member;
2532                   Declarator decl = SpecDeclFromString(bitMember.dataTypeString, specs, null);
2533                   TypeName type = MkTypeName(specs, decl);
2534                   if(bitMember.mask > MAXDWORD)
2535                      sprintf(mask, FORMAT64HEXLL, bitMember.mask);
2536                   else
2537                      sprintf(mask, FORMAT64HEX, bitMember.mask);
2538                   sprintf(shift, "%d", bitMember.pos);
2539                   
2540                   FreeIdentifier(exp.member.member);
2541                  
2542                   // ((type) ((color & mask) >> bitPos))
2543                   ListAdd(list, MkExpCast(type, MkExpBrackets(MkListOne(MkExpOp(MkExpBrackets(MkListOne(
2544                      MkExpOp(exp.member.exp, '&', MkExpConstant(mask)))), RIGHT_OP, 
2545                         MkExpConstant(shift))))));
2546
2547                   exp.type = bracketsExp;
2548                   exp.list = list;
2549                }
2550                else if(_class.type == unitClass)
2551                {
2552                }
2553                else
2554                {
2555                   // If it's a this pointer, replace by precomputed shortcut
2556                   if(thisPtr)
2557                   {
2558                      char pointerName[1024];
2559
2560                      strcpy(pointerName, "__ecerePointer_");
2561                      FullClassNameCat(pointerName, type._class.registered.fullName, false);
2562                      FreeIdentifier(exp.member.exp.identifier);
2563                      exp.member.exp.identifier = MkIdentifier(pointerName);
2564                   }
2565                   // Otherwise, access the data the hard way
2566                   else
2567                   {
2568                      Expression bytePtr, e;
2569                      Expression classExp;
2570                      Expression checkedExp;
2571                      char structName[1024];
2572                      char className[1024];
2573                      strcpy(className, "__ecereClass_");
2574                      FullClassNameCat(className, member._class.fullName, true);
2575                      MangleClassName(className);
2576
2577                      // classExp = QMkExpId(className);
2578
2579                      if(!member._class.symbol)
2580                         member._class.symbol = FindClass(member._class.fullName);
2581
2582                      DeclareClass(member._class.symbol, className);
2583                      DeclareStruct(member._class.fullName, false);
2584
2585                      structName[0] = 0;
2586                      FullClassNameCat(structName, member._class.fullName, false);
2587
2588                      checkedExp = exp.member.exp;
2589                      while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp) && checkedExp.list && checkedExp.list->count == 1) ||
2590                            checkedExp.type == castExp)
2591                      {
2592                         if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp)
2593                            checkedExp = checkedExp.list->last;
2594                         else if(checkedExp.type == castExp)
2595                            checkedExp = checkedExp.cast.exp;
2596                      }
2597
2598                      if(checkedExp.type != identifierExp &&
2599                         checkedExp.type != constantExp &&      // Added this here... Might mess up if we need address?
2600                         checkedExp.type != memberExp && checkedExp.type != pointerExp)
2601                      {
2602                         char ecereTemp[100];
2603                         Statement compound;
2604                         OldList * list = MkList();
2605                         Context context = PushContext();
2606                         if(exp.member.exp.tempCount > exp.tempCount)
2607                            exp.tempCount = exp.member.exp.tempCount;
2608
2609                         exp.tempCount++;
2610                         curExternal.function.tempCount = Max(curExternal.function.tempCount, exp.tempCount);
2611                         sprintf(ecereTemp, "__ecTemp%d", exp.tempCount);
2612                         curContext = context;
2613                         compound = MkCompoundStmt(
2614                            MkListOne(MkDeclaration(MkListOne(MkSpecifier(CHAR)), MkListOne(MkInitDeclarator(
2615                               MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier(ecereTemp))),
2616                                  MkInitializerAssignment(QBrackets(exp.member.exp)))))), null);
2617                         if(member._class.fixed)
2618                         {
2619                            if(member._class.templateClass ? member._class.templateClass.offset : member._class.offset)
2620                            {
2621                               char string[256];
2622                               sprintf(string, "%d", member._class.templateClass ? member._class.templateClass.offset : member._class.offset);
2623                               e = QBrackets(MkExpOp(QMkExpId(ecereTemp), '+', MkExpConstant(string)));
2624                            }
2625                            else
2626                               e = QMkExpId(ecereTemp);
2627                         }
2628                         else
2629                         {
2630                            e = QBrackets(MkExpOp(QMkExpId(ecereTemp), '+', 
2631                               MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
2632                         }
2633
2634                         compound.compound.context = context;
2635                         compound.compound.statements = MkListOne(MkExpressionStmt(MkListOne(
2636                            QBrackets(MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), 
2637                               MkDeclaratorPointer(MkPointer(null, null), null)), e)))));
2638
2639                         exp.member.exp =  MkExpExtensionCompound(compound);
2640
2641                         PopContext(context);
2642                         curContext = context.parent;
2643                      }
2644                      else
2645                      {
2646                         bytePtr = MkExpCast(QMkType("char", QMkPtrDecl(null)), /*CopyExpression(*/exp.member.exp/*)*/);
2647                         // DISABLED BECAUSE PREVENTS GETTING ADDRESS OF MEMBERS WITH ADDRESS 0
2648                         /*
2649                         e = QBrackets(QMkExpCond(exp.member.exp, 
2650                            QBrackets(MkExpOp(bytePtr, '+', MkExpPointer(classExp, MkIdentifier("offset")))),
2651                            MkExpConstant("0")));
2652                         */
2653                         
2654                         // if(class.fixed)
2655                         if(member._class.fixed)
2656                         {
2657                            if(member._class.templateClass ? member._class.templateClass.offset : member._class.offset)
2658                            {
2659                               char string[256];
2660                               sprintf(string, "%d", member._class.templateClass ? member._class.templateClass.offset : member._class.offset);
2661                               e = QBrackets(QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string))));
2662                            }
2663                            else
2664                               e = bytePtr;
2665                         }
2666                         else
2667                            e = QBrackets(QBrackets(MkExpOp(bytePtr, '+', MkExpPointer(QMkExpId(className), MkIdentifier("offset")))));
2668
2669                         // exp.member.exp = QBrackets(MkExpCast(QMkType(structName, QMkPtrDecl(null)), e));
2670                         exp.member.exp = QBrackets(MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), QMkPtrDecl(null)), e));
2671                      }
2672                   }
2673                   exp.type = pointerExp;
2674                }
2675             }
2676          }
2677
2678          // Take Out Any Class Specifier (Should have been used by now)
2679          FreeSpecifier(memberClassSpecifier);
2680
2681          // Just moved this at the end... How is it?
2682          if(exp.type == memberExp || exp.type == pointerExp)
2683          {
2684             exp.member.exp.usage.usageGet = true;
2685             exp.member.exp.usage.usageMember = true;
2686             exp.member.exp.tempCount = exp.tempCount;
2687             ProcessExpression(exp.member.exp);
2688             exp.tempCount = exp.member.exp.tempCount;
2689             if((changeToPtr && exp.member.exp.byReference) || noHead)
2690                exp.type = pointerExp;
2691          }
2692          break;
2693       }
2694       case extensionCompoundExp:
2695       {
2696          ((Expression)((Statement)exp.compound.compound.statements->last).expressions->last).usage |= exp.usage & 
2697             ExpUsage { usageGet = true, usageArg = true, usageMember = true };
2698
2699          ProcessStatement(exp.compound);
2700
2701          /*if(((Expression)((Statement)checkedExp.compound.compound.statements->last).expressions->last).byReference)
2702             exp.byReference = ((Expression)((Statement)checkedExp.compound.compound.statements->last).expressions->last).byReference;*/
2703          break;
2704       }
2705       case pointerExp:
2706       {
2707          exp.member.exp.usage.usageGet = true;
2708          ProcessExpression(exp.member.exp);
2709          break;
2710       }
2711       case typeSizeExp:
2712       {
2713          Specifier spec = exp.typeName.qualifiers ? exp.typeName.qualifiers->first : null;
2714          if(spec && spec.type == templateTypeSpecifier && !exp.typeName.declarator)
2715          {
2716             Expression argExp = GetTemplateArgExp(spec.templateParameter, thisClass, false);
2717             if(argExp)
2718             {
2719                Expression classExp;
2720                
2721                FreeTypeName(exp.typeName);
2722
2723                classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
2724
2725                exp.type = bracketsExp;
2726                exp.list = MkListOne(
2727                   MkExpCondition(MkExpBrackets(MkListOne(
2728                      MkExpOp(
2729                         MkExpOp(
2730                            MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, 
2731                               MkExpIdentifier(MkIdentifier("normalClass"))), 
2732                         OR_OP,
2733                         MkExpOp(
2734                            MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, 
2735                               MkExpIdentifier(MkIdentifier("noHeadClass"))
2736                             )))),
2737                      MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)))),
2738                      MkExpMember(classExp, MkIdentifier("typeSize")))
2739                   ); 
2740
2741                ProcessExpressionType(exp);
2742                ProcessExpression(exp);
2743             }
2744          }
2745          break;
2746       }
2747       case castExp:
2748       {
2749          if(exp.cast.exp)
2750          {
2751             exp.cast.exp.usage |= exp.usage & ExpUsage { usageGet = true, usageMember = true };
2752             ProcessExpression(exp.cast.exp);
2753             // TESTING THIS
2754             if(exp.cast.exp.byReference)
2755                exp.byReference = exp.cast.exp.byReference;
2756             if(exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass &&
2757                exp.cast.exp.expType && (exp.cast.exp.expType.kind == pointerType || exp.cast.exp.expType.kind == arrayType || (
2758                   exp.cast.exp.expType.kind == classType && exp.cast.exp.expType._class && exp.cast.exp.expType._class.registered && 
2759                      !strcmp(exp.cast.exp.expType._class.registered.dataTypeString, "char *")) ) )
2760                exp.byReference = true;
2761          }
2762          // Moved this to 1.5...
2763          //exp.expType = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
2764          break;
2765       }
2766       case conditionExp:
2767       {
2768          Expression e;
2769          if(exp.usage.usageGet)
2770             exp.cond.cond.usage.usageGet = true;
2771          ProcessExpression(exp.cond.cond);
2772          for(e = exp.cond.exp->first; e; e = e.next)
2773          {
2774             if(!e.next && exp.usage.usageGet) e.usage.usageGet = true;
2775             ProcessExpression(e);
2776          }
2777          if(exp.usage.usageGet)
2778             exp.cond.elseExp.usage.usageGet = true;
2779          ProcessExpression(exp.cond.elseExp);
2780          break;
2781       }
2782       case classExp:
2783       {
2784          // Need the class itself here...
2785          if(exp._classExp.specifiers && exp._classExp.specifiers->first && ((Specifier)exp._classExp.specifiers->first).type == templateTypeSpecifier)
2786          {
2787             Specifier spec = exp._classExp.specifiers->first;
2788             Expression argExp = GetTemplateArgExp(spec.templateParameter, thisClass, true);
2789             if(argExp)
2790             {
2791                FreeList(exp._classExp.specifiers, FreeSpecifier);
2792                if(exp._classExp.decl)
2793                   FreeDeclarator(exp._classExp.decl);
2794
2795                exp.type = memberExp; //pointerExp;
2796                exp.member.exp = argExp;
2797                exp.member.member = MkIdentifier("dataTypeClass");
2798
2799                ProcessExpressionType(argExp);
2800                ProcessExpression(exp);
2801             }
2802          }
2803          else
2804          {
2805             char className[1024];
2806             char * string = StringFromSpecDecl(exp._classExp.specifiers, exp._classExp.decl);
2807             
2808             strcpy(className, "__ecereClass_");
2809             FullClassNameCat(className, string, true);      // TODO: Verify this
2810             MangleClassName(className);
2811             DeclareClass(FindClass(string), className);
2812             delete string;
2813
2814             FreeList(exp._classExp.specifiers, FreeSpecifier);
2815             if(exp._classExp.decl)
2816                FreeDeclarator(exp._classExp.decl);
2817
2818             exp.type = identifierExp;
2819             exp.identifier = MkIdentifier(className);
2820          }
2821          break;
2822       }
2823       case vaArgExp:
2824       {
2825          ProcessExpression(exp.vaArg.exp);
2826          break;
2827       }
2828       case extensionInitializerExp:
2829       {
2830          ProcessInitializer(exp.initializer.initializer);
2831          break;
2832       }
2833    }
2834    FixRefExp(exp);
2835    yylloc = oldyylloc;
2836 }
2837
2838 static void ProcessInitializer(Initializer init)
2839 {
2840    switch(init.type)
2841    {
2842       case expInitializer:
2843          init.exp.usage.usageGet = true;
2844          ProcessExpression(init.exp);
2845          if(init.exp.destType && init.exp.destType.kind == classType && init.exp.destType._class &&
2846             init.exp.destType._class.registered && init.exp.destType._class.registered.type == noHeadClass)
2847          {
2848             FixReference(init.exp, true);
2849          }
2850          else if(init.exp.destType && init.exp.destType.kind == classType)
2851             FixReference(init.exp, false);
2852          break;
2853       case listInitializer:
2854       {
2855          Initializer i;
2856          for(i = init.list->first; i; i = i.next)
2857             ProcessInitializer(i);
2858          break;
2859       }
2860    }
2861 }
2862
2863 static void ProcessDeclaration(Declaration decl)
2864 {
2865    switch(decl.type)
2866    {
2867       case initDeclaration:
2868       {
2869          if(decl.declarators)
2870          {
2871             InitDeclarator d;
2872          
2873             for(d = decl.declarators->first; d; d = d.next)
2874             {
2875                if(d.initializer)
2876                   ProcessInitializer(d.initializer);
2877             }
2878          }
2879          break;
2880       }
2881    }
2882 }
2883
2884 static void ProcessStatement(Statement stmt)
2885 {
2886    switch(stmt.type)
2887    {
2888       case labeledStmt:
2889          ProcessStatement(stmt.labeled.stmt);
2890          break;
2891       case caseStmt:
2892          if(stmt.caseStmt.exp)
2893          {
2894             stmt.caseStmt.exp.usage.usageGet = true;
2895
2896             // This expression should be constant...
2897             ProcessExpression(stmt.caseStmt.exp);
2898          }
2899          if(stmt.caseStmt.stmt)
2900             ProcessStatement(stmt.caseStmt.stmt);
2901          break;
2902       case compoundStmt:
2903       {
2904          if(stmt.compound.context)
2905          {
2906             Declaration decl;
2907             Statement s;
2908             Statement prevCompound = curCompound;
2909             Context prevContext = curContext;
2910
2911             if(!stmt.compound.isSwitch)
2912             {
2913                curCompound = stmt;
2914                curContext = stmt.compound.context;
2915             }
2916
2917             if(stmt.compound.declarations)
2918             {
2919                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
2920                   ProcessDeclaration(decl);
2921             }
2922             if(stmt.compound.statements)
2923             {
2924                for(s = stmt.compound.statements->first; s; s = s.next)
2925                   ProcessStatement(s);
2926             }
2927             curContext = prevContext;
2928             curCompound = prevCompound;
2929          }
2930          break;
2931       }
2932       case expressionStmt:
2933       {
2934          Expression exp;
2935          if(stmt.expressions)
2936          {
2937             for(exp = stmt.expressions->first; exp; exp = exp.next)
2938             {
2939                ProcessExpression(exp);
2940             }
2941          }
2942          break;
2943       }
2944       case ifStmt:
2945       {
2946          if(stmt.ifStmt.exp)
2947          {
2948             Expression exp;
2949
2950             ((Expression)stmt.ifStmt.exp->last).usage.usageGet = true;
2951             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
2952             {
2953                ProcessExpression(exp);
2954             }
2955          }
2956          if(stmt.ifStmt.stmt)
2957             ProcessStatement(stmt.ifStmt.stmt);
2958          if(stmt.ifStmt.elseStmt)
2959             ProcessStatement(stmt.ifStmt.elseStmt);
2960          break;
2961       }
2962       case switchStmt:
2963       {
2964          Expression exp;
2965          ((Expression)stmt.switchStmt.exp->last).usage.usageGet = true;
2966          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
2967          {
2968             ProcessExpression(exp);
2969          }
2970          ProcessStatement(stmt.switchStmt.stmt);
2971          break;
2972       }
2973       case whileStmt:
2974       {
2975          Expression exp;
2976          ((Expression)stmt.whileStmt.exp->last).usage.usageGet = true;
2977          for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
2978          {
2979             ProcessExpression(exp);
2980          }
2981          ProcessStatement(stmt.whileStmt.stmt);
2982          break;
2983       }
2984       case doWhileStmt:
2985       {
2986          Expression exp;
2987          if(stmt.doWhile.exp && stmt.doWhile.exp->last)
2988          {
2989             ((Expression)stmt.doWhile.exp->last).usage.usageGet = true;
2990             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
2991             {
2992                ProcessExpression(exp);
2993             }
2994          }
2995          if(stmt.doWhile.stmt)
2996             ProcessStatement(stmt.doWhile.stmt);
2997          break;
2998       }
2999       case forStmt:
3000       {
3001          Expression exp;
3002          if(stmt.forStmt.init)
3003             ProcessStatement(stmt.forStmt.init);
3004
3005          if(stmt.forStmt.check)
3006          {
3007             if(stmt.forStmt.check.expressions)
3008             {
3009                ((Expression)stmt.forStmt.check.expressions->last).usage.usageGet = true;
3010             }
3011             ProcessStatement(stmt.forStmt.check);
3012          }
3013          if(stmt.forStmt.increment)
3014          {        
3015             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
3016             {
3017                ProcessExpression(exp);
3018             }
3019          }
3020          if(stmt.forStmt.stmt)
3021             ProcessStatement(stmt.forStmt.stmt);
3022          break;
3023       }
3024       case gotoStmt:
3025          break;
3026       case continueStmt:
3027          break;
3028       case breakStmt:
3029          break;
3030       case returnStmt:
3031       {
3032          Expression exp;
3033          if(stmt.expressions)
3034          {
3035             ((Expression)stmt.expressions->last).usage.usageGet = true;
3036             for(exp = stmt.expressions->first; exp; exp = exp.next)
3037             {
3038                ProcessExpression(exp);
3039             }
3040          }
3041          break;
3042       }
3043       case badDeclarationStmt:
3044       {
3045          ProcessDeclaration(stmt.decl);
3046          break;
3047       }
3048       case asmStmt:
3049       {
3050          AsmField field;
3051          if(stmt.asmStmt.inputFields)
3052          {
3053             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
3054                if(field.expression)
3055                   ProcessExpression(field.expression);
3056          }
3057          if(stmt.asmStmt.outputFields)
3058          {
3059             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
3060                if(field.expression)
3061                   ProcessExpression(field.expression);
3062          }
3063          if(stmt.asmStmt.clobberedFields)
3064          {
3065             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
3066                if(field.expression)
3067                   ProcessExpression(field.expression);
3068          }
3069          break;
3070       }
3071    }
3072 }
3073
3074 static void ProcessFunction(FunctionDefinition function)
3075 {
3076    if(function.body)
3077    {
3078       ProcessStatement(function.body);
3079       if(function.tempCount)
3080       {
3081          Statement stmt = function.body;
3082          int c;
3083          // Declare ecereTemp here, we need it!
3084          if(!stmt.compound.declarations)
3085             stmt.compound.declarations = MkList();
3086          curContext = stmt.compound.context;
3087          for(c = 1; c<=function.tempCount; c++)
3088          {
3089             char ecereTemp[100];
3090             sprintf(ecereTemp, "__ecereTemp%d", c);
3091             stmt.compound.declarations->Insert(null,
3092                QMkDeclarationBase(VOID, MkInitDeclarator(QMkPtrDecl(ecereTemp), null)));
3093          }
3094          curContext = stmt.compound.context.parent;
3095       }
3096    }
3097 }
3098
3099 static void ProcessMemberInitData(MemberInit member)
3100 {
3101    if(member.initializer)
3102       ProcessInitializer(member.initializer);
3103 }
3104
3105 static void ProcessInstantiation(Instantiation inst)
3106 {
3107    if(inst.members)
3108    {
3109       MembersInit members;
3110       for(members = inst.members->first; members; members = members.next)
3111       {
3112          if(members.type == dataMembersInit)
3113          {
3114             if(members.dataMembers)
3115             {
3116                MemberInit member;
3117                for(member = members.dataMembers->first; member; member = member.next)
3118                   ProcessMemberInitData(member);
3119             }
3120          }
3121          else if(members.type == methodMembersInit)
3122          {
3123             ProcessFunction((FunctionDefinition)members.function);
3124          }
3125       }
3126    }
3127 }
3128
3129 /////////// MEMBER ACCESS PASS /////////////////////////////////////////////
3130 public void ProcessMemberAccess()
3131 {
3132    External external;
3133    for(external = ast->first; external; external = external.next)
3134    {
3135       curExternal = external;
3136       // There shouldn't be any class member access here anyways...
3137       if(external.type == declarationExternal)
3138       {
3139          if(external.declaration)
3140             ProcessDeclaration(external.declaration);
3141       }
3142    }
3143    
3144    for(external = ast->first; external; external = external.next)
3145    {
3146       curExternal = external;
3147       if(external.type == functionExternal)
3148       {
3149          ProcessFunction(external.function);
3150       }
3151       else if(external.type == declarationExternal)
3152       {
3153          //currentClass = external.function._class;
3154          if(external.declaration)
3155             ProcessDeclaration(external.declaration);
3156       }
3157       else if(external.type == classExternal)
3158       {
3159          ClassDefinition _class = external._class;
3160          //currentClass = external.symbol.registered;
3161          if(_class.definitions)
3162          {
3163             ClassDef def;
3164             Class regClass = _class.symbol.registered;
3165
3166             // Process all functions
3167             for(def = _class.definitions->first; def; def = def.next)
3168             {
3169                if(def.type == functionClassDef)
3170                {
3171                   curExternal = def.function.declarator.symbol.pointerExternal;
3172                   ProcessFunction((FunctionDefinition)def.function);
3173                }
3174                else if(def.type == declarationClassDef && def.decl.type == instDeclaration)
3175                {
3176                   ProcessInstantiation(def.decl.inst);
3177                }
3178                else if(def.type == defaultPropertiesClassDef && def.defProperties)
3179                {
3180                   MemberInit defProperty;
3181
3182                   // Add this to the context
3183                   Symbol thisSymbol
3184                   {
3185                      string = CopyString("this");
3186                      type = MkClassType(regClass.fullName);
3187                   };
3188                   globalContext.symbols.Add((BTNode)thisSymbol);
3189                   
3190                   for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
3191                   {
3192                      //thisClass = regClass;
3193                      ProcessMemberInitData(defProperty); //, regClass, &id);
3194                      //thisClass = null;
3195                   }
3196
3197                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3198                   globalContext.symbols.Remove((BTNode)thisSymbol);
3199                   FreeSymbol(thisSymbol);
3200                }
3201                else if(def.type == propertyClassDef && def.propertyDef)
3202                {
3203                   PropertyDef prop = def.propertyDef;
3204
3205                   // Add this to the context
3206                   Symbol thisSymbol
3207                   {
3208                      string = CopyString("this");
3209                      type = MkClassType(regClass.fullName);
3210                   };
3211                   globalContext.symbols.Add((BTNode)thisSymbol);
3212                   
3213                   //thisClass = regClass;
3214                   if(prop.setStmt)
3215                   {
3216                      curExternal = prop.symbol.externalSet;
3217                      ProcessStatement(prop.setStmt);
3218                   }
3219                   if(prop.getStmt)
3220                   {
3221                      curExternal = prop.symbol.externalGet;
3222                      ProcessStatement(prop.getStmt);
3223                   }
3224                   if(prop.issetStmt)
3225                   {
3226                      curExternal = prop.symbol.externalIsSet;
3227                      ProcessStatement(prop.issetStmt);
3228                   }
3229
3230                   //thisClass = null;
3231
3232                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3233                   globalContext.symbols.Remove((BTNode)thisSymbol);
3234                   FreeSymbol(thisSymbol);
3235                }
3236                else if(def.type == classPropertyClassDef && def.propertyDef)
3237                {
3238                   PropertyDef prop = def.propertyDef;
3239
3240                   //thisClass = regClass;
3241                   if(prop.setStmt)
3242                   {
3243                      curExternal = prop.symbol.externalSet;
3244                      ProcessStatement(prop.setStmt);
3245                   }
3246                   if(prop.getStmt)
3247                   {
3248                      curExternal = prop.symbol.externalGet;
3249                      ProcessStatement(prop.getStmt);
3250                   }
3251                   //thisClass = null;
3252                }
3253                else if(def.type == propertyWatchClassDef && def.propertyWatch)
3254                {
3255                   PropertyWatch propertyWatch = def.propertyWatch;
3256         
3257                   // Add this to the context
3258                   Symbol thisSymbol
3259                   {
3260                      string = CopyString("this");
3261                      type = MkClassType(regClass.fullName);
3262                   };
3263                   globalContext.symbols.Add((BTNode)thisSymbol);
3264                   
3265                   //thisClass = regClass;
3266                   if(propertyWatch.compound)
3267                   {
3268                      Symbol thisSymbol
3269                      {
3270                         string = CopyString("this");
3271                         type = MkClassType(regClass.fullName);
3272                      };
3273                      propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
3274                      curExternal = null;
3275                      ProcessStatement(propertyWatch.compound);
3276                   }
3277                   // thisClass = null;
3278
3279                   //globalContext.symbols.Delete((BTNode)thisSymbol);
3280                   globalContext.symbols.Remove((BTNode)thisSymbol);
3281                   FreeSymbol(thisSymbol);
3282                }
3283             }
3284          }
3285       }
3286    }
3287 }