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