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