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