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