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