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