samples/audio; Installer: Added SineTone sample
[sdk] / compiler / libec / src / pass15.ec
index 6e1bcc4..4d4d489 100644 (file)
@@ -1,9 +1,5 @@
 import "ecdefs"
 
-#define uint _uint
-#include <stdlib.h>  // For strtoll
-#undef uint
-
 // UNTIL IMPLEMENTED IN GRAMMAR
 #define ACCESS_CLASSDATA(_class, baseClass) \
    (_class ? ((void *)(((char *)_class.data) + baseClass.offsetClass)) : null)
@@ -47,6 +43,8 @@ Time findSymbolTotalTime;
    {
       TempFile f { };
       int count;
+      bool backOutputLineNumbers = outputLineNumbers;
+      outputLineNumbers = false;
 
       if(exp)
          OutputExpression(exp, f);
@@ -55,6 +53,8 @@ Time findSymbolTotalTime;
       count += f.Read(string + count, 1, 1023);
       string[count] = '\0';
       delete f;
+
+      outputLineNumbers = backOutputLineNumbers;
    }
 }
 
@@ -84,10 +84,11 @@ bool NeedCast(Type type1, Type type2)
       return false;
    }
 
-   if(type1.kind == type2.kind)
+   if(type1.kind == type2.kind && type1.isLong == type2.isLong)
    {
       switch(type1.kind)
       {
+         case _BoolType:
          case charType:
          case shortType:
          case intType:
@@ -100,7 +101,7 @@ bool NeedCast(Type type1, Type type2)
          case classType:
             return type1._class != type2._class;
          case pointerType:
-            return NeedCast(type1.type, type2.type);
+            return (type1.type && type2.type && type1.type.constant != type2.type.constant) || NeedCast(type1.type, type2.type);
          default:
             return true; //false; ????
       }
@@ -120,6 +121,7 @@ static void ReplaceClassMembers(Expression exp, Class _class)
          // First, check if the identifier is declared inside the function
          for(ctx = curContext; ctx != topContext.parent && !symbol; ctx = ctx.parent)
          {
+            if(!ctx) break;   // This happened opening old mapTileCache.ec from archives?
             symbol = (Symbol)ctx.symbols.FindString(id.string);
             if(symbol) break;
          }
@@ -200,10 +202,12 @@ static void ReplaceClassMembers(Expression exp, Class _class)
 public char * PrintInt(int64 result)
 {
    char temp[100];
-   if(result > MAXINT64)
-      sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
+   if(result > MAXINT)
+      sprintf(temp, FORMAT64HEX /*"0x%I64XLL"*/, result);
    else
-      sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
+      sprintf(temp, FORMAT64D /*"%I64d"*/, result);
+   if(result > MAXINT || result < MININT)
+      strcat(temp, "LL");
    return CopyString(temp);
 }
 
@@ -211,7 +215,7 @@ public char * PrintUInt(uint64 result)
 {
    char temp[100];
    if(result > MAXDWORD)
-      sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
+      sprintf(temp, FORMAT64HEXLL /*"0x%I64X"*/, result);
    else if(result > MAXINT)
       sprintf(temp, FORMAT64HEX /*"0x%I64X"*/, result);
    else
@@ -219,20 +223,25 @@ public char * PrintUInt(uint64 result)
    return CopyString(temp);
 }
 
-public char * PrintInt64(int64 result)
+public char *  PrintInt64(int64 result)
 {
    char temp[100];
-   sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
+   if(result > MAXINT || result < MININT)
+      sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
+   else
+      sprintf(temp, FORMAT64D /*"%I64d"*/, result);
    return CopyString(temp);
 }
 
 public char * PrintUInt64(uint64 result)
 {
    char temp[100];
-   if(result > MAXINT64)
+   if(result > MAXDWORD)
       sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
+   else if(result > MAXINT)
+      sprintf(temp, FORMAT64HEX /*"0x%I64XLL"*/, result);
    else
-      sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
+      sprintf(temp, FORMAT64D /*"%I64d"*/, result);
    return CopyString(temp);
 }
 
@@ -240,9 +249,11 @@ public char * PrintHexUInt(uint64 result)
 {
    char temp[100];
    if(result > MAXDWORD)
-      sprintf(temp, FORMAT64HEXLL /*"0x%I64xLL"*/, result);
+      sprintf(temp, FORMAT64HEX /*"0x%I64xLL"*/, result);
    else
       sprintf(temp, FORMAT64HEX /*"0x%I64x"*/, result);
+   if(result > MAXDWORD)
+      strcat(temp, "LL");
    return CopyString(temp);
 }
 
@@ -296,14 +307,44 @@ public char * PrintUChar(unsigned char result)
 public char * PrintFloat(float result)
 {
    char temp[350];
-   sprintf(temp, "%.16ff", result);
+   if(result.isInf)
+   {
+      if(result.signBit)
+         strcpy(temp, "-inf");
+      else
+         strcpy(temp, "inf");
+   }
+   else if(result.isNan)
+   {
+      if(result.signBit)
+         strcpy(temp, "-nan");
+      else
+         strcpy(temp, "nan");
+   }
+   else
+      sprintf(temp, "%.16ff", result);
    return CopyString(temp);
 }
 
 public char * PrintDouble(double result)
 {
    char temp[350];
-   sprintf(temp, "%.16f", result);
+   if(result.isInf)
+   {
+      if(result.signBit)
+         strcpy(temp, "-inf");
+      else
+         strcpy(temp, "inf");
+   }
+   else if(result.isNan)
+   {
+      if(result.signBit)
+         strcpy(temp, "-nan");
+      else
+         strcpy(temp, "nan");
+   }
+   else
+      sprintf(temp, "%.16f", result);
    return CopyString(temp);
 }
 
@@ -313,9 +354,8 @@ public char * PrintDouble(double result)
 //public Operand GetOperand(Expression exp);
 
 #define GETVALUE(name, t) \
-   public bool Get##name(Expression exp, t * value2) \
+   public bool GetOp##name(Operand op2, t * value2) \
    {                                                        \
-      Operand op2 = GetOperand(exp);                        \
       if(op2.kind == intType && op2.type.isSigned) *value2 = (t) op2.i; \
       else if(op2.kind == intType) *value2 = (t) op2.ui;                 \
       else if(op2.kind == int64Type && op2.type.isSigned) *value2 = (t) op2.i64; \
@@ -327,16 +367,21 @@ public char * PrintDouble(double result)
       else if(op2.kind == shortType && op2.type.isSigned) *value2 = (t) op2.s;   \
       else if(op2.kind == shortType) *value2 = (t) op2.us;                        \
       else if(op2.kind == charType && op2.type.isSigned) *value2 = (t) op2.c;    \
-      else if(op2.kind == charType) *value2 = (t) op2.uc;                         \
+      else if(op2.kind == _BoolType || op2.kind == charType) *value2 = (t) op2.uc; \
       else if(op2.kind == floatType) *value2 = (t) op2.f;                         \
       else if(op2.kind == doubleType) *value2 = (t) op2.d;                        \
       else if(op2.kind == pointerType) *value2 = (t) op2.ui64;                    \
       else                                                                          \
          return false;                                                              \
       return true;                                                                  \
+   } \
+   public bool Get##name(Expression exp, t * value2) \
+   {                                                        \
+      Operand op2 = GetOperand(exp);                        \
+      return GetOp##name(op2, value2); \
    }
 
-// To help the deubugger currently not preprocessing...
+// To help the debugger currently not preprocessing...
 #define HELP(x) x
 
 GETVALUE(Int, HELP(int));
@@ -360,10 +405,9 @@ void ComputeClassMembers(Class _class, bool isMember)
 {
    DataMember member = isMember ? (DataMember) _class : null;
    Context context = isMember ? null : SetupTemplatesContext(_class);
-   if(member || ((_class.type == bitClass || _class.type == normalClass || _class.type == structClass || _class.type == noHeadClass) && 
+   if(member || ((_class.type == bitClass || _class.type == normalClass || _class.type == structClass || _class.type == noHeadClass) &&
                  (_class.type == bitClass || (!_class.structSize || _class.structSize == _class.offset)) && _class.computeSize))
    {
-      int c;
       int unionMemberOffset = 0;
       int bitFields = 0;
 
@@ -440,7 +484,7 @@ void ComputeClassMembers(Class _class, bool isMember)
                   int alignment = 0;
 
                   // Prevent infinite recursion
-                  if(dataMember.dataType.kind != classType || 
+                  if(dataMember.dataType.kind != classType ||
                      ((!dataMember.dataType._class || !dataMember.dataType._class.registered || dataMember.dataType._class.registered != _class ||
                      _class.type != structClass)))
                      ComputeTypeSize(dataMember.dataType);
@@ -607,7 +651,7 @@ void ComputeClassMembers(Class _class, bool isMember)
       {
          member.memberOffset = unionMemberOffset;
       }
-      
+
       if(!isMember)
       {
          /*if(_class.type == structClass)
@@ -623,7 +667,9 @@ void ComputeClassMembers(Class _class, bool isMember)
                if(_class.memberOffset % _class.structAlignment)
                   extra += _class.structAlignment - (_class.memberOffset % _class.structAlignment);
             }
-            _class.structSize = (_class.base ? (_class.base.templateClass ? _class.base.templateClass.structSize : _class.base.structSize) : 0) + _class.memberOffset + extra;
+            _class.structSize = (_class.base ? (_class.base.templateClass ?
+               (_class.base.type == noHeadClass ? _class.base.templateClass.memberOffset : _class.base.templateClass.structSize) :
+                  (_class.base.type == noHeadClass ? _class.base.memberOffset : _class.base.structSize) ) : 0) + _class.memberOffset + extra;
             if(!member)
             {
                Property prop;
@@ -647,7 +693,7 @@ void ComputeClassMembers(Class _class, bool isMember)
                   if(deriv.computeSize)
                   {
                      // TESTING THIS NEW CODE HERE... TRYING TO FIX ScrollBar MEMBERS DEBUGGING
-                     deriv.offset = /*_class.offset + */_class.structSize;
+                     deriv.offset = /*_class.offset + */(_class.type == noHeadClass ? _class.memberOffset : _class.structSize);
                      deriv.memberOffset = 0;
                      // ----------------------
 
@@ -668,7 +714,7 @@ public void ComputeModuleClasses(Module module)
 {
    Class _class;
    OldLink subModule;
-   
+
    for(subModule = module.modules.first; subModule; subModule = subModule.next)
       ComputeModuleClasses(subModule.data);
    for(_class = module.classes.first; _class; _class = _class.next)
@@ -684,11 +730,12 @@ public int ComputeTypeSize(Type type)
       type.computing = true;
       switch(type.kind)
       {
+         case _BoolType: type.alignment = size = sizeof(char); break;   // Assuming 1 byte _Bool
          case charType: type.alignment = size = sizeof(char); break;
          case intType: type.alignment = size = sizeof(int); break;
          case int64Type: type.alignment = size = sizeof(int64); break;
-         case intPtrType: type.alignment = size = targetBits / 8; break;
-         case intSizeType: type.alignment = size = targetBits / 8; break;
+         case intPtrType: type.alignment = size = targetBits / 8; type.pointerAlignment = true; break;
+         case intSizeType: type.alignment = size = targetBits / 8; type.pointerAlignment = true; break;
          case longType: type.alignment = size = sizeof(long); break;
          case shortType: type.alignment = size = sizeof(short); break;
          case floatType: type.alignment = size = sizeof(float); break;
@@ -702,13 +749,14 @@ public int ComputeTypeSize(Type type)
                // Ensure all members are properly registered
                ComputeClassMembers(_class, false);
                type.alignment = _class.structAlignment;
+               type.pointerAlignment = (bool)_class.pointerAlignment;
                size = _class.structSize;
                if(type.alignment && size % type.alignment)
                   size += type.alignment - (size % type.alignment);
 
             }
-            else if(_class && (_class.type == unitClass || 
-                   _class.type == enumClass || 
+            else if(_class && (_class.type == unitClass ||
+                   _class.type == enumClass ||
                    _class.type == bitClass))
             {
                if(!_class.dataType)
@@ -716,16 +764,26 @@ public int ComputeTypeSize(Type type)
                size = type.alignment = ComputeTypeSize(_class.dataType);
             }
             else
+            {
                size = type.alignment = targetBits / 8; // sizeof(Instance *);
+               type.pointerAlignment = true;
+            }
             break;
          }
-         case pointerType: case subClassType: size = type.alignment = targetBits / 8; /*sizeof(void *); */break;
-         case arrayType: 
+         case pointerType: case subClassType: size = type.alignment = targetBits / 8; /*sizeof(void *); */ type.pointerAlignment = true; break;
+         case arrayType:
             if(type.arraySizeExp)
             {
                ProcessExpressionType(type.arraySizeExp);
                ComputeExpression(type.arraySizeExp);
-               if(!type.arraySizeExp.isConstant || (type.arraySizeExp.expType.kind != intType && type.arraySizeExp.expType.kind != enumType && 
+               if(!type.arraySizeExp.isConstant || (type.arraySizeExp.expType.kind != intType &&
+                  type.arraySizeExp.expType.kind != shortType &&
+                  type.arraySizeExp.expType.kind != charType &&
+                  type.arraySizeExp.expType.kind != longType &&
+                  type.arraySizeExp.expType.kind != int64Type &&
+                  type.arraySizeExp.expType.kind != intSizeType &&
+                  type.arraySizeExp.expType.kind != intPtrType &&
+                  type.arraySizeExp.expType.kind != enumType &&
                   (type.arraySizeExp.expType.kind != classType || !type.arraySizeExp.expType._class.registered || type.arraySizeExp.expType._class.registered.type != enumClass)))
                {
                   Location oldLoc = yylloc;
@@ -758,45 +816,84 @@ public int ComputeTypeSize(Type type)
 
             size = ComputeTypeSize(type.type) * type.arraySize;
             if(type.type)
+            {
                type.alignment = type.type.alignment;
-            
+               type.pointerAlignment = type.type.pointerAlignment;
+            }
+
             break;
          case structType:
          {
-            Type member;
-            for(member = type.members.first; member; member = member.next)
+            if(!type.members.first && type.enumName)
+            {
+               Symbol symbol = FindStruct(curContext, type.enumName);
+               if(symbol && symbol.type)
+               {
+                  ComputeTypeSize(symbol.type);
+                  size = symbol.type.size;
+               }
+            }
+            else
             {
-               uint addSize = ComputeTypeSize(member);
+               Type member;
+               for(member = type.members.first; member; member = member.next)
+               {
+                  uint addSize = ComputeTypeSize(member);
 
-               member.offset = size;
-               if(member.alignment && size % member.alignment)
-                  member.offset += member.alignment - (size % member.alignment);
-               size = member.offset;
+                  member.offset = size;
+                  if(member.alignment && size % member.alignment)
+                     member.offset += member.alignment - (size % member.alignment);
+                  size = member.offset;
 
-               type.alignment = Max(type.alignment, member.alignment);
-               size += addSize;
+                  if(member.pointerAlignment && type.size <= 4)
+                     type.pointerAlignment = true;
+                  else if(!member.pointerAlignment && member.alignment >= 8)
+                     type.pointerAlignment = false;
+
+                  type.alignment = Max(type.alignment, member.alignment);
+                  size += addSize;
+               }
+               if(type.alignment && size % type.alignment)
+                  size += type.alignment - (size % type.alignment);
             }
-            if(type.alignment && size % type.alignment)
-               size += type.alignment - (size % type.alignment);
             break;
          }
          case unionType:
          {
-            Type member;
-            for(member = type.members.first; member; member = member.next)
+            if(!type.members.first && type.enumName)
             {
-               uint addSize = ComputeTypeSize(member);
-               
-               member.offset = size;
-               if(member.alignment && size % member.alignment)
-                  member.offset += member.alignment - (size % member.alignment);
-               size = member.offset;
+               Symbol symbol = FindStruct(curContext, type.enumName);
+               if(symbol && symbol.type)
+               {
+                  ComputeTypeSize(symbol.type);
+                  size = symbol.type.size;
+                  type.alignment = symbol.type.alignment;
+               }
+            }
+            else
+            {
+               Type member;
+               for(member = type.members.first; member; member = member.next)
+               {
+                  uint addSize = ComputeTypeSize(member);
+
+                  member.offset = size;
+                  if(member.alignment && size % member.alignment)
+                     member.offset += member.alignment - (size % member.alignment);
+                  size = member.offset;
+
+                  if(member.pointerAlignment && type.size <= 4)
+                     type.pointerAlignment = true;
+                  else if(!member.pointerAlignment && member.alignment >= 8)
+                     type.pointerAlignment = false;
 
-               type.alignment = Max(type.alignment, member.alignment);
-               size = Max(size, addSize);
+                  type.alignment = Max(type.alignment, member.alignment);
+
+                  size = Max(size, addSize);
+               }
+               if(type.alignment && size % type.alignment)
+                  size += type.alignment - (size % type.alignment);
             }
-            if(type.alignment && size % type.alignment)
-               size += type.alignment - (size % type.alignment);
             break;
          }
          case templateType:
@@ -807,6 +904,7 @@ public int ComputeTypeSize(Type type)
             {
                size = ComputeTypeSize(baseType);
                type.alignment = baseType.alignment;
+               type.pointerAlignment = baseType.pointerAlignment;
             }
             else
                type.alignment = size = sizeof(uint64);
@@ -820,6 +918,7 @@ public int ComputeTypeSize(Type type)
          case thisClassType:
          {
             type.alignment = size = targetBits / 8; //sizeof(void *);
+            type.pointerAlignment = true;
             break;
          }
       }
@@ -830,14 +929,16 @@ public int ComputeTypeSize(Type type)
 }
 
 
-/*static */int AddMembers(OldList * declarations, Class _class, bool isMember, uint * retSize, Class topClass, bool *addedPadding)
+/*static */int AddMembers(External neededBy, OldList * declarations, Class _class, bool isMember, uint * retSize, Class topClass, bool *addedPadding)
 {
    // This function is in need of a major review when implementing private members etc.
    DataMember topMember = isMember ? (DataMember) _class : null;
    uint totalSize = 0;
    uint maxSize = 0;
-   int alignment, size;
+   int alignment;
+   uint size;
    DataMember member;
+   int anonID = 1;
    Context context = isMember ? null : SetupTemplatesContext(_class);
    if(addedPadding)
       *addedPadding = false;
@@ -849,7 +950,7 @@ public int ComputeTypeSize(Type type)
       {
          // DANGER: Testing this noHeadClass here...
          if(_class.type == structClass || _class.type == noHeadClass)
-            /*totalSize = */AddMembers(declarations, _class.base, false, &totalSize, topClass, null);
+            /*totalSize = */AddMembers(neededBy, declarations, _class.base, false, &totalSize, topClass, null);
          else
          {
             uint baseSize = _class.base.templateClass ? _class.base.templateClass.structSize : _class.base.structSize;
@@ -874,7 +975,7 @@ public int ComputeTypeSize(Type type)
                   OldList * specs = MkList(), * decls = MkList();
                   Declarator decl;
 
-                  decl = SpecDeclFromString(member.dataTypeString, specs, 
+                  decl = SpecDeclFromString(member.dataTypeString, specs,
                      MkDeclaratorIdentifier(MkIdentifier(member.name)));
                   ListAdd(decls, MkStructDeclarator(decl, null));
                   ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, decls, null)));
@@ -886,7 +987,7 @@ public int ComputeTypeSize(Type type)
 
                   {
                      Type type = ProcessType(specs, decl);
-                     DeclareType(member.dataType, false, false);
+                     DeclareType(neededBy, member.dataType, true, false);
                      FreeType(type);
                   }
                   /*
@@ -912,12 +1013,14 @@ public int ComputeTypeSize(Type type)
             case structMember:
             {
                OldList * specs = MkList(), * list = MkList();
-               
+               char id[100];
+               sprintf(id, "__anon%d", anonID++);
+
                size = 0;
-               AddMembers(list, (Class)member, true, &size, topClass, null);
-               ListAdd(specs, 
+               AddMembers(neededBy, list, (Class)member, true, &size, topClass, null);
+               ListAdd(specs,
                   MkStructOrUnion((member.type == unionMember)?unionSpecifier:structSpecifier, null, list));
-               ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, null, null)));
+               ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, MkListOne(MkDeclaratorIdentifier(MkIdentifier(id))),null)));
                alignment = member.structAlignment;
 
                if(alignment)
@@ -947,8 +1050,8 @@ public int ComputeTypeSize(Type type)
       {
          char sizeString[50];
          sprintf(sizeString, "%d", maxSize - totalSize);
-         ListAdd(declarations, 
-            MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(CHAR)), 
+         ListAdd(declarations,
+            MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(CHAR)),
             MkListOne(MkDeclaratorArray(MkDeclaratorIdentifier(MkIdentifier("__ecere_padding")), MkExpConstant(sizeString))), null)));
          if(addedPadding)
             *addedPadding = true;
@@ -959,15 +1062,14 @@ public int ComputeTypeSize(Type type)
    return topMember ? topMember.memberID : _class.memberID;
 }
 
-static int DeclareMembers(Class _class, bool isMember)
+static int DeclareMembers(External neededBy, Class _class, bool isMember)
 {
    DataMember topMember = isMember ? (DataMember) _class : null;
-   uint totalSize = 0;
    DataMember member;
    Context context = isMember ? null : SetupTemplatesContext(_class);
-   
+
    if(!isMember && (_class.type == structClass || _class.type == noHeadClass) && _class.base.type != systemClass)
-      DeclareMembers(_class.base, false);
+      DeclareMembers(neededBy, _class.base, false);
 
    for(member = isMember ? topMember.members.first : _class.membersAndProperties.first; member; member = member.next)
    {
@@ -977,21 +1079,16 @@ static int DeclareMembers(Class _class, bool isMember)
          {
             case normalMember:
             {
-               /*
-               if(member.dataType && member.dataType.kind == classType && member.dataType._class &&
-                  member.dataType._class.registered && member.dataType._class.registered.type == structClass)
-                  DeclareStruct(member.dataType._class.string, false);
-                  */
                if(!member.dataType && member.dataTypeString)
                   member.dataType = ProcessTypeString(member.dataTypeString, false);
                if(member.dataType)
-                  DeclareType(member.dataType, false, false);
+                  DeclareType(neededBy, member.dataType, true, false);
                break;
             }
             case unionMember:
             case structMember:
             {
-               DeclareMembers((Class)member, true);
+               DeclareMembers(neededBy, (Class)member, true);
                break;
             }
          }
@@ -1003,488 +1100,526 @@ static int DeclareMembers(Class _class, bool isMember)
    return topMember ? topMember.memberID : _class.memberID;
 }
 
-void DeclareStruct(char * name, bool skipNoHead)
+static void IdentifyAnonStructs(OldList/*<ClassDef>*/ *  definitions)
+{
+   ClassDef def;
+   int anonID = 1;
+   for(def = definitions->first; def; def = def.next)
+   {
+      if(def.type == declarationClassDef)
+      {
+         Declaration decl = def.decl;
+         if(decl && decl.specifiers)
+         {
+            Specifier spec;
+            bool isStruct = false;
+            for(spec = decl.specifiers->first; spec; spec = spec.next)
+            {
+               if(spec.type == structSpecifier || spec.type == unionSpecifier)
+               {
+                  if(spec.definitions)
+                     IdentifyAnonStructs(spec.definitions);
+                  isStruct = true;
+               }
+            }
+            if(isStruct)
+            {
+               Declarator d = null;
+               if(decl.declarators)
+               {
+                  for(d = decl.declarators->first; d; d = d.next)
+                  {
+                     Identifier idDecl = GetDeclId(d);
+                     if(idDecl)
+                        break;
+                  }
+               }
+               if(!d)
+               {
+                  char id[100];
+                  sprintf(id, "__anon%d", anonID++);
+                  if(!decl.declarators)
+                     decl.declarators = MkList();
+                  ListAdd(decl.declarators, MkDeclaratorIdentifier(MkIdentifier(id)));
+               }
+            }
+         }
+      }
+   }
+}
+
+External DeclareStruct(External neededBy, const char * name, bool skipNoHead, bool needDereference)
+{
+   return _DeclareStruct(neededBy, name, skipNoHead, needDereference, false);
+}
+
+External _DeclareStruct(External neededBy, const char * name, bool skipNoHead, bool needDereference, bool fwdDecl)
 {
    External external = null;
    Symbol classSym = FindClass(name);
+   OldList * curDeclarations = null;
 
-   if(!inCompiler || !classSym) return;
+   if(!inCompiler || !classSym) return null;
 
    // We don't need any declaration for bit classes...
-   if(classSym.registered && 
+   if(classSym.registered &&
       (classSym.registered.type == bitClass || classSym.registered.type == unitClass || classSym.registered.type == enumClass))
-      return;
+      return null;
 
-   /*if(classSym.registered.templateClass)
-      return DeclareStruct(classSym.registered.templateClass.fullName, skipNoHead);
-   */
+   if(!classSym.registered || (classSym.registered.type == normalClass && classSym.registered.structSize && classSym.registered.base && classSym.registered.base.base))
+      _DeclareStruct(neededBy, "ecere::com::Instance", false, true, fwdDecl);
 
-   if(classSym.registered && classSym.imported && !classSym.declaredStructSym)
+   external = classSym.structExternal;
+
+   if(external && external.declaration)
+   {
+      Specifier spec;
+      for(spec = external.declaration.specifiers ? external.declaration.specifiers->first : null; spec; spec = spec.next)
+         if(spec.type == structSpecifier || spec.type == unionSpecifier)
+         {
+            curDeclarations = spec.definitions;
+            break;
+         }
+   }
+
+   if(classSym.registered && !classSym.declaring && classSym.imported && (!classSym.declaredStructSym || (classSym.registered.type == noHeadClass && !skipNoHead && external && !curDeclarations)))
    {
-      // Add typedef struct
-      Declaration decl;
       OldList * specifiers, * declarators;
       OldList * declarations = null;
       char structName[1024];
-      external = (classSym.registered && classSym.registered.type == structClass) ? 
-         classSym.pointerExternal : classSym.structExternal;
-
-      // TEMPORARY HACK: Pass 3 will move up struct declarations without moving members
-      // Moved this one up because DeclareClass done later will need it
+      bool addedPadding = false;
+      Specifier curSpec = null;
 
       classSym.declaring++;
 
       if(strchr(classSym.string, '<'))
       {
          if(classSym.registered.templateClass)
-         {
-            DeclareStruct(classSym.registered.templateClass.fullName, skipNoHead);
-            classSym.declaring--;
-         }
-         return;
+            external = _DeclareStruct(neededBy, classSym.registered.templateClass.fullName, skipNoHead, needDereference, fwdDecl);
+         classSym.declaring--;
+         return external;
       }
-      
-      //if(!skipNoHead)
-         DeclareMembers(classSym.registered, false);
 
       structName[0] = 0;
       FullClassNameCat(structName, name, false);
 
-      /*if(!external)      
-         external = MkExternalDeclaration(null);*/
-
-      if(!skipNoHead)
+      classSym.declaredStructSym = true;
+      if(!external || (classSym.registered.type == noHeadClass && !skipNoHead && !curDeclarations))
       {
-         bool addedPadding = false;
-         classSym.declaredStructSym = true;
+         bool add = false;
+         if(!external)
+         {
+            external = MkExternalDeclaration(null);
+            classSym.structExternal = external;
+            external.symbol = classSym;
 
-         declarations = MkList();
+            add = true;
+         }
 
-         AddMembers(declarations, classSym.registered, false, null, classSym.registered, &addedPadding);
+         if(!skipNoHead)
+         {
+            declarations = MkList();
+            AddMembers(external, declarations, classSym.registered, false, null, classSym.registered, &addedPadding);
+         }
 
-         //ListAdd(specifiers, MkSpecifier(TYPEDEF));
-         //ListAdd(specifiers, MkStructOrUnion(structSpecifier, null, declarations));
+         if(external.declaration)
+         {
+            Specifier spec;
+            for(spec = external.declaration.specifiers ? external.declaration.specifiers->first : null; spec; spec = spec.next)
+               if(spec.type == structSpecifier || spec.type == unionSpecifier)
+               {
+                  curSpec = spec;
+                  curDeclarations = spec.definitions;
+                  break;
+               }
+         }
 
-         if(!declarations->count || (declarations->count == 1 && addedPadding))
+         if(declarations && (!declarations->count || (declarations->count == 1 && addedPadding)))
          {
             FreeList(declarations, FreeClassDef);
             declarations = null;
          }
-      }
-      if(skipNoHead || declarations)
-      {
-         if(external && external.declaration)
-         {
-            ((Specifier)external.declaration.specifiers->first).definitions = declarations;
-
-            if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
-            {
-               // TODO: Fix this
-               //ast->Move(classSym.structExternal ? classSym.structExternal : classSym.pointerExternal, curExternal.prev);
-
-               // DANGER
-               if(classSym.structExternal)
-                  ast->Move(classSym.structExternal, curExternal.prev);
-               ast->Move(classSym.pointerExternal, curExternal.prev);
 
-               classSym.id = curExternal.symbol.idCode;
-               classSym.idCode = curExternal.symbol.idCode;
-               // external = classSym.pointerExternal;
-               //external = classSym.structExternal ? classSym.structExternal : classSym.pointerExternal;
-            }
+         if(classSym.registered.type != noHeadClass && !declarations)
+         {
+            FreeExternal(external);
+            external = null;
+            classSym.structExternal = null;
          }
          else
          {
-            if(!external)      
-               external = MkExternalDeclaration(null);
-
-            specifiers = MkList();
-            declarators = MkList();
-            ListAdd(specifiers, MkStructOrUnion(structSpecifier, MkIdentifier(structName), declarations));
-
-            /*
-            d = MkDeclaratorIdentifier(MkIdentifier(structName));
-            ListAdd(declarators, MkInitDeclarator(d, null));
-            */
-            external.declaration = decl = MkDeclaration(specifiers, declarators);
-            if(decl.symbol && !decl.symbol.pointerExternal)
-               decl.symbol.pointerExternal = external;
-
-            // For simple classes, keep the declaration as the external to move around
-            if(classSym.registered && classSym.registered.type == structClass)
-            {
-               char className[1024];
-               strcpy(className, "__ecereClass_");
-               FullClassNameCat(className, classSym.string, true);
-               MangleClassName(className);
-
-               // Testing This
-               DeclareClass(classSym, className);
-
-               external.symbol = classSym;
-               classSym.pointerExternal = external;
-               classSym.id = (curExternal && curExternal.symbol) ? curExternal.symbol.idCode : 0;
-               classSym.idCode = (curExternal && curExternal.symbol) ? curExternal.symbol.idCode : 0;
-            }
+            if(curSpec)
+               curSpec.definitions = declarations;
             else
             {
-               char className[1024];
-               strcpy(className, "__ecereClass_");
-               FullClassNameCat(className, classSym.string, true);
-               MangleClassName(className);
-
-               // TOFIX: TESTING THIS...
-               classSym.structExternal = external;
-               DeclareClass(classSym, className);
-               external.symbol = classSym;
+               specifiers = MkList();
+               declarators = MkList();
+               ListAdd(specifiers, MkStructOrUnion(structSpecifier, MkIdentifier(structName), declarations));
+               external.declaration = MkDeclaration(specifiers, declarators);
             }
-
-            //if(curExternal)
-               ast->Insert(curExternal ? curExternal.prev : null, external);
+            if(add)
+               ast->Add(external);
          }
       }
-
       classSym.declaring--;
    }
-   else if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
+   else if(!classSym.declaredStructSym && classSym.structExternal)
    {
-      // TEMPORARY HACK: Pass 3 will move up struct declarations without moving members
-      // Moved this one up because DeclareClass done later will need it
+      classSym.declaredStructSym = true;
 
-      // TESTING THIS:
-      classSym.declaring++;
+      if(classSym.registered)
+         DeclareMembers(classSym.structExternal, classSym.registered, false);
 
-      //if(!skipNoHead)
+      if(classSym.structExternal.declaration && classSym.structExternal.declaration.specifiers)
       {
-         if(classSym.registered)
-            DeclareMembers(classSym.registered, false);
+         Specifier spec;
+         for(spec = classSym.structExternal.declaration.specifiers->first; spec; spec = spec.next)
+         {
+            if(spec.definitions)
+               IdentifyAnonStructs(spec.definitions);
+         }
       }
-
-      if(classSym.registered && (classSym.registered.type == structClass || classSym.registered.type == noHeadClass))
+   }
+   if(inCompiler && neededBy && (external || !classSym.imported))
+   {
+      if(!external)
       {
-         // TODO: Fix this
-         //ast->Move(classSym.structExternal ? classSym.structExternal : classSym.pointerExternal, curExternal.prev);
-
-         // DANGER
-         if(classSym.structExternal)
-            ast->Move(classSym.structExternal, curExternal.prev);
-         ast->Move(classSym.pointerExternal, curExternal.prev);
-
-         classSym.id = curExternal.symbol.idCode;
-         classSym.idCode = curExternal.symbol.idCode;
-         // external = classSym.pointerExternal;
-         // external = classSym.structExternal ? classSym.structExternal : classSym.pointerExternal;
+         classSym.structExternal = external = MkExternalDeclaration(null);
+         external.symbol = classSym;
+         ast->Add(external);
       }
-
-      classSym.declaring--;
+      if(reachedPass15 && !external.declaration && classSym.registered && classSym.registered.type == noHeadClass)
+      {
+         // Declare nohead classes without definitions here (e.g. IteratorPointer)
+         char structName[1024];
+         OldList * specifiers, * declarators;
+         structName[0] = 0;
+         FullClassNameCat(structName, name, false);
+         specifiers = MkList();
+         declarators = MkList();
+         ListAdd(specifiers, MkStructOrUnion(structSpecifier, MkIdentifier(structName), null));
+         external.declaration = MkDeclaration(specifiers, declarators);
+      }
+      if(fwdDecl)
+      {
+         External e = external.fwdDecl ? external.fwdDecl : external;
+         if(e.incoming.count)
+            neededBy.CreateUniqueEdge(e, !needDereference && !external.fwdDecl);
+      }
+      else
+         neededBy.CreateUniqueEdge(external, !needDereference);
    }
-   //return external;
+   return external;
 }
 
-void DeclareProperty(Property prop, char * setName, char * getName)
+void DeclareProperty(External neededBy, Property prop, char * setName, char * getName)
 {
    Symbol symbol = prop.symbol;
-   char propName[1024];
+   bool imported = false;
+   bool dllImport = false;
+   External structExternal = null;
+   External instExternal = null;
 
    strcpy(setName, "__ecereProp_");
    FullClassNameCat(setName, prop._class.fullName, false);
    strcat(setName, "_Set_");
-   // strcat(setName, prop.name);
    FullClassNameCat(setName, prop.name, true);
 
    strcpy(getName, "__ecereProp_");
    FullClassNameCat(getName, prop._class.fullName, false);
    strcat(getName, "_Get_");
    FullClassNameCat(getName, prop.name, true);
-   // strcat(getName, prop.name);
-
-   strcpy(propName, "__ecereProp_");
-   FullClassNameCat(propName, prop._class.fullName, false);
-   strcat(propName, "_");
-   FullClassNameCat(propName, prop.name, true);
-   // strcat(propName, prop.name);
 
-   // To support "char *" property
-   MangleClassName(getName);
-   MangleClassName(setName);
-   MangleClassName(propName);
-
-   if(prop._class.type == structClass)
-      DeclareStruct(prop._class.fullName, false);
-
-   if(!symbol || curExternal.symbol.idCode < symbol.id)
+   if(!symbol || symbol._import)
    {
-      bool imported = false;
-      bool dllImport = false;
-      if(!symbol || symbol._import)
+      if(!symbol)
       {
-         if(!symbol)
+         Symbol classSym;
+
+         if(!prop._class.symbol)
+            prop._class.symbol = FindClass(prop._class.fullName);
+         classSym = prop._class.symbol;
+         if(classSym && !classSym._import)
          {
-            Symbol classSym;
-            if(!prop._class.symbol)
-               prop._class.symbol = FindClass(prop._class.fullName);
-            classSym = prop._class.symbol;
-            if(classSym && !classSym._import)
-            {
-               ModuleImport module;
+            ModuleImport module;
 
-               if(prop._class.module)
-                  module = FindModule(prop._class.module);
-               else
-                  module = mainModule;
+            if(prop._class.module)
+               module = FindModule(prop._class.module);
+            else
+               module = mainModule;
 
-               classSym._import = ClassImport
-               {
-                  name = CopyString(prop._class.fullName);
-                  isRemote = prop._class.isRemote;
-               };
-               module.classes.Add(classSym._import);
-            }
-            symbol = prop.symbol = Symbol { };
-            symbol._import = (ClassImport)PropertyImport
+            classSym._import = ClassImport
             {
-               name = CopyString(prop.name);
-               isVirtual = false; //prop.isVirtual;
-               hasSet = prop.Set ? true : false;
-               hasGet = prop.Get ? true : false;
+               name = CopyString(prop._class.fullName);
+               isRemote = prop._class.isRemote;
             };
-            if(classSym)
-               classSym._import.properties.Add(symbol._import);
+            module.classes.Add(classSym._import);
          }
-         imported = true;
-         if(prop._class.module != privateModule && prop._class.module.importType != staticImport)
-            dllImport = true;
-      }
+         symbol = prop.symbol = Symbol { };
+         symbol._import = (ClassImport)PropertyImport
+         {
+            name = CopyString(prop.name);
+            isVirtual = false; //prop.isVirtual;
+            hasSet = prop.Set ? true : false;
+            hasGet = prop.Get ? true : false;
+         };
+         if(classSym)
+            classSym._import.properties.Add(symbol._import);
+      }
+      imported = true;
+      // Ugly work around for isNan properties declared within float/double classes which are initialized with ecereCOM
+      if((prop._class.module != privateModule || !strcmp(prop._class.name, "float") || !strcmp(prop._class.name, "double")) &&
+         prop._class.module.importType != staticImport)
+         dllImport = true;
+   }
+
+   if(!symbol.type)
+   {
+      Context context = SetupTemplatesContext(prop._class);
+      symbol.type = ProcessTypeString(prop.dataTypeString, false);
+      FinishTemplatesContext(context);
+   }
+
+   if((prop.Get && !symbol.externalGet) || (prop.Set && !symbol.externalSet))
+   {
+      if(prop._class.type == normalClass && prop._class.structSize)
+         instExternal = DeclareStruct(null, "ecere::com::Instance", false, true);
+      structExternal = DeclareStruct(null, prop._class.fullName, prop._class.type != structClass /*true*/, false);
+   }
+
+   // Get
+   if(prop.Get && !symbol.externalGet)
+   {
+      Declaration decl;
+      OldList * specifiers, * declarators;
+      Declarator d;
+      OldList * params;
+      Specifier spec = null;
+      External external;
+      Declarator typeDecl;
+      bool simple = false;
+      bool needReference;
+
+      specifiers = MkList();
+      declarators = MkList();
+      params = MkList();
+
+      ListAdd(params, MkTypeName(MkListOne(MkSpecifierName(prop._class.fullName)),
+         MkDeclaratorIdentifier(MkIdentifier("this"))));
+
+      d = MkDeclaratorIdentifier(MkIdentifier(getName));
+      //if(imported)
+      if(dllImport)
+         d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
 
-      if(!symbol.type)
       {
          Context context = SetupTemplatesContext(prop._class);
-         symbol.type = ProcessTypeString(prop.dataTypeString, false);
+         typeDecl = SpecDeclFromString(prop.dataTypeString, specifiers, null);
          FinishTemplatesContext(context);
       }
 
-      // Get
-      if(prop.Get)
+      // Make sure the simple _class's type is declared
+      needReference = !typeDecl || typeDecl.type == identifierDeclarator;
+      for(spec = specifiers->first; spec; spec = spec.next)
       {
-         if(!symbol.externalGet || symbol.externalGet.type == functionExternal)
+         if(spec.type == nameSpecifier)
          {
-            Declaration decl;
-            OldList * specifiers, * declarators;
-            Declarator d;
-            OldList * params;
-            Specifier spec;
-            External external;
-            Declarator typeDecl;
-            bool simple = false;
+            Symbol classSym = spec.symbol;
+            if(needReference)
+            {
+               symbol._class = classSym.registered;
+               if(classSym.registered && classSym.registered.type == structClass)
+                  simple = true;
+            }
+            break;
+         }
+      }
 
-            specifiers = MkList();
-            declarators = MkList();
-            params = MkList();
+      if(!simple)
+         d = PlugDeclarator(typeDecl, d);
+      else
+      {
+         ListAdd(params, MkTypeName(specifiers,
+            PlugDeclarator(typeDecl, MkDeclaratorIdentifier(MkIdentifier("value")))));
+         specifiers = MkList();
+      }
 
-            ListAdd(params, MkTypeName(MkListOne(MkSpecifierName /*MkClassName*/(prop._class.fullName)), 
-               MkDeclaratorIdentifier(MkIdentifier("this"))));
+      d = MkDeclaratorFunction(d, params);
 
-            d = MkDeclaratorIdentifier(MkIdentifier(getName));
-            //if(imported)
-            if(dllImport)
-               d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
+      //if(imported)
+      if(dllImport)
+         specifiers->Insert(null, MkSpecifier(EXTERN));
+      else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
+         specifiers->Insert(null, MkSpecifier(STATIC));
+      if(simple)
+         ListAdd(specifiers, MkSpecifier(VOID));
 
-            {
-               Context context = SetupTemplatesContext(prop._class);
-               typeDecl = SpecDeclFromString(prop.dataTypeString, specifiers, null);
-               FinishTemplatesContext(context);
-            }
+      ListAdd(declarators, MkInitDeclarator(d, null));
 
-            // Make sure the simple _class's type is declared
-            for(spec = specifiers->first; spec; spec = spec.next)
-            {
-               if(spec.type == nameSpecifier /*SpecifierClass*/)
-               {
-                  if((!typeDecl || typeDecl.type == identifierDeclarator))
-                  {
-                     Symbol classSym = spec.symbol; // FindClass(spec.name);
-                     symbol._class = classSym.registered;
-                     if(classSym.registered && classSym.registered.type == structClass)
-                     {
-                        DeclareStruct(spec.name, false);
-                        simple = true;
-                     }
-                  }
-               }
-            }
+      decl = MkDeclaration(specifiers, declarators);
 
-            if(!simple)
-               d = PlugDeclarator(typeDecl, d);
-            else
-            {
-               ListAdd(params, MkTypeName(specifiers, 
-                  PlugDeclarator(typeDecl, MkDeclaratorIdentifier(MkIdentifier("value")))));
-               specifiers = MkList();
-            }
+      external = MkExternalDeclaration(decl);
 
-            d = MkDeclaratorFunction(d, params);
-            //if(imported)
-            if(dllImport)
-               specifiers->Insert(null, MkSpecifier(EXTERN));
-            else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
-               specifiers->Insert(null, MkSpecifier(STATIC));
-            if(simple)
-               ListAdd(specifiers, MkSpecifier(VOID));
+      if(structExternal)
+         external.CreateEdge(structExternal, false);
+      if(instExternal)
+         external.CreateEdge(instExternal, false);
 
-            ListAdd(declarators, MkInitDeclarator(d, null));
+      if(spec)
+         DeclareStruct(external, spec.name, false, needReference);
 
-            decl = MkDeclaration(specifiers, declarators);
+      ast->Add(external);
+      external.symbol = symbol;
+      symbol.externalGet = external;
 
-            external = MkExternalDeclaration(decl);
-            ast->Insert(curExternal.prev, external);
-            external.symbol = symbol;
-            symbol.externalGet = external;
+      ReplaceThisClassSpecifiers(specifiers, prop._class);
 
-            ReplaceThisClassSpecifiers(specifiers, prop._class);
+      if(typeDecl)
+         FreeDeclarator(typeDecl);
+   }
 
-            if(typeDecl)
-               FreeDeclarator(typeDecl);
-         }
-         else
-         {
-            // Move declaration higher...
-            ast->Move(symbol.externalGet, curExternal.prev);
-         }
+   // Set
+   if(prop.Set && !symbol.externalSet)
+   {
+      Declaration decl;
+      OldList * specifiers, * declarators;
+      Declarator d;
+      OldList * params;
+      Specifier spec = null;
+      External external;
+      Declarator typeDecl;
+      bool needReference;
+
+      declarators = MkList();
+      params = MkList();
+
+      if(!prop.conversion || prop._class.type == structClass)
+      {
+         ListAdd(params, MkTypeName(MkListOne(MkSpecifierName(prop._class.fullName)),
+            MkDeclaratorIdentifier(MkIdentifier("this"))));
       }
 
-      // Set
-      if(prop.Set)
+      specifiers = MkList();
+
       {
-         if(!symbol.externalSet || symbol.externalSet.type == functionExternal)
-         {
-            Declaration decl;
-            OldList * specifiers, * declarators;
-            Declarator d;
-            OldList * params;
-            Specifier spec;
-            External external;
-            Declarator typeDecl;
+         Context context = SetupTemplatesContext(prop._class);
+         typeDecl = d = SpecDeclFromString(prop.dataTypeString, specifiers,
+            MkDeclaratorIdentifier(MkIdentifier("value")));
+         FinishTemplatesContext(context);
+      }
+      if(!strcmp(prop._class.base.fullName, "eda::Row") || !strcmp(prop._class.base.fullName, "eda::Id"))
+         specifiers->Insert(null, MkSpecifier(CONST));
 
-            declarators = MkList();
-            params = MkList();
+      ListAdd(params, MkTypeName(specifiers, d));
 
-            // TESTING COMMENTING THIS FIRST LINE OUT, what was the problem? Trying to add noHeadClass here ...
-            if(!prop.conversion || prop._class.type == structClass)
-            {
-               ListAdd(params, MkTypeName(MkListOne(MkSpecifierName/*MkClassName*/(prop._class.fullName)), 
-                  MkDeclaratorIdentifier(MkIdentifier("this"))));
-            }
+      d = MkDeclaratorIdentifier(MkIdentifier(setName));
+      if(dllImport)
+         d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
+      d = MkDeclaratorFunction(d, params);
 
-            specifiers = MkList();
+      // Make sure the simple _class's type is declared
+      needReference = !typeDecl || typeDecl.type == identifierDeclarator;
+      for(spec = specifiers->first; spec; spec = spec.next)
+      {
+         if(spec.type == nameSpecifier)
+         {
+            Symbol classSym = spec.symbol;
+            if(needReference)
+               symbol._class = classSym.registered;
+            break;
+         }
+      }
 
-            {
-               Context context = SetupTemplatesContext(prop._class);
-               typeDecl = d = SpecDeclFromString(prop.dataTypeString, specifiers,
-                  MkDeclaratorIdentifier(MkIdentifier("value")));
-               FinishTemplatesContext(context);
-            }
-            ListAdd(params, MkTypeName(specifiers, d));
+      ListAdd(declarators, MkInitDeclarator(d, null));
 
-            d = MkDeclaratorIdentifier(MkIdentifier(setName));
-            //if(imported)
-            if(dllImport)
-               d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
-            d = MkDeclaratorFunction(d, params);
+      specifiers = MkList();
+      if(dllImport)
+         specifiers->Insert(null, MkSpecifier(EXTERN));
+      else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
+         specifiers->Insert(null, MkSpecifier(STATIC));
 
-            // Make sure the simple _class's type is declared
-            for(spec = specifiers->first; spec; spec = spec.next)
-            {
-               if(spec.type == nameSpecifier /*SpecifierClass*/)
-               {
-                  if((!typeDecl || typeDecl.type == identifierDeclarator))
-                  {
-                     Symbol classSym = spec.symbol; // FindClass(spec.name);
-                     symbol._class = classSym.registered;
-                     if(classSym.registered && classSym.registered.type == structClass)
-                        DeclareStruct(spec.name, false);
-                  }
-               }
-            }
+      if(!prop.conversion || prop._class.type == structClass)
+         ListAdd(specifiers, MkSpecifier(VOID));
+      else
+         ListAdd(specifiers, MkSpecifierName(prop._class.fullName));
 
-            ListAdd(declarators, MkInitDeclarator(d, null));
+      decl = MkDeclaration(specifiers, declarators);
 
-            specifiers = MkList();
-            //if(imported)
-            if(dllImport)
-               specifiers->Insert(null, MkSpecifier(EXTERN));
-            else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
-               specifiers->Insert(null, MkSpecifier(STATIC));
+      external = MkExternalDeclaration(decl);
 
-            // TESTING COMMENTING THIS FIRST LINE OUT, what was the problem? Trying to add noHeadClass here ...
-            if(!prop.conversion || prop._class.type == structClass)
-               ListAdd(specifiers, MkSpecifier(VOID));
-            else
-               ListAdd(specifiers, MkSpecifierName/*MkClassName*/(prop._class.fullName));
+      if(structExternal)
+         external.CreateEdge(structExternal, false);
+      if(instExternal)
+         external.CreateEdge(instExternal, false);
 
-            decl = MkDeclaration(specifiers, declarators);
+      if(spec)
+         DeclareStruct(external, spec.name, false, needReference);
 
-            external = MkExternalDeclaration(decl);
-            ast->Insert(curExternal.prev, external);
-            external.symbol = symbol;
-            symbol.externalSet = external;
+      ast->Add(external);
+      external.symbol = symbol;
+      symbol.externalSet = external;
 
-            ReplaceThisClassSpecifiers(specifiers, prop._class);
-         }
-         else
-         {
-            // Move declaration higher...
-            ast->Move(symbol.externalSet, curExternal.prev);
-         }
-      }
+      ReplaceThisClassSpecifiers(specifiers, prop._class);
+   }
+
+   // Property (for Watchers)
+   if(!symbol.externalPtr)
+   {
+      Declaration decl;
+      External external;
+      OldList * specifiers = MkList();
+      char propName[1024];
 
-      // Property (for Watchers)
-      if(!symbol.externalPtr)
+      if(imported)
+         specifiers->Insert(null, MkSpecifier(EXTERN));
+      else
       {
-         Declaration decl;
-         External external;
-         OldList * specifiers = MkList();
+         specifiers->Insert(null, MkSpecifier(STATIC));
+         specifiers->Add(MkSpecifierExtended(MkExtDeclAttrib(MkAttrib(ATTRIB, MkListOne(MkAttribute(CopyString("unused"), null))))));
+      }
 
-         if(imported)
-            specifiers->Insert(null, MkSpecifier(EXTERN));
-         else
-            specifiers->Insert(null, MkSpecifier(STATIC));
+      ListAdd(specifiers, MkSpecifierName("Property"));
 
-         ListAdd(specifiers, MkSpecifierName("Property"));
+      strcpy(propName, "__ecereProp_");
+      FullClassNameCat(propName, prop._class.fullName, false);
+      strcat(propName, "_");
+      FullClassNameCat(propName, prop.name, true);
+
+      {
+         OldList * list = MkList();
+         ListAdd(list, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(propName)), null));
 
+         if(!imported)
          {
-            OldList * list = MkList();
-            ListAdd(list, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), 
-                  MkDeclaratorIdentifier(MkIdentifier(propName))), null));
+            strcpy(propName, "__ecerePropM_");
+            FullClassNameCat(propName, prop._class.fullName, false);
+            strcat(propName, "_");
+            FullClassNameCat(propName, prop.name, true);
 
-            if(!imported)
-            {
-               strcpy(propName, "__ecerePropM_");
-               FullClassNameCat(propName, prop._class.fullName, false);
-               strcat(propName, "_");
-               // strcat(propName, prop.name);
-               FullClassNameCat(propName, prop.name, true);
+            ListAdd(list, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(propName)), null));
+         }
+         decl = MkDeclaration(specifiers, list);
+      }
 
-               MangleClassName(propName);
+      external = MkExternalDeclaration(decl);
+      ast->Insert(curExternal.prev, external);
+      external.symbol = symbol;
+      symbol.externalPtr = external;
+   }
 
-               ListAdd(list, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), 
-                     MkDeclaratorIdentifier(MkIdentifier(propName))), null));
-            }
-            decl = MkDeclaration(specifiers, list);
-         }
+   if(inCompiler && neededBy)
+   {
+      // Could improve this to create edge on only what is needed...
+      if(symbol.externalPtr)
+         neededBy.CreateUniqueEdge(symbol.externalPtr, false);
 
-         external = MkExternalDeclaration(decl);
-         ast->Insert(curExternal.prev, external);
-         external.symbol = symbol;
-         symbol.externalPtr = external;
-      }
-      else
-      {
-         // Move declaration higher...
-         ast->Move(symbol.externalPtr, curExternal.prev);
-      }
+      if(symbol.externalGet)
+         neededBy.CreateUniqueEdge(symbol.externalGet, symbol.externalGet.type == functionExternal);
 
-      symbol.id = curExternal.symbol.idCode;
+      if(symbol.externalSet)
+         neededBy.CreateUniqueEdge(symbol.externalSet, symbol.externalSet.type == functionExternal);
+
+      // IsSet ?
    }
 }
 
@@ -1671,8 +1806,16 @@ void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, Da
             ClassTemplateArgument arg = _class.templateArgs[id];
             if(arg.dataTypeString)
             {
+               bool constant = type.constant;
                // FreeType(type);
                type = ProcessTypeString(arg.dataTypeString, false);
+               if(type.kind == classType && constant) type.constant = true;
+               else if(type.kind == pointerType)
+               {
+                  Type t = type.type;
+                  while(t.kind == pointerType) t = t.type;
+                  if(constant) t.constant = constant;
+               }
                freeType = true;
                if(type && _class.templateClass)
                   type.passAsTemplate = true;
@@ -1692,10 +1835,9 @@ void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, Da
       {
          Class expClass = type._class.registered;
          Class cClass = null;
-         int c;
          int paramCount = 0;
          int lastParam = -1;
-         
+
          char templateString[1024];
          ClassTemplateParameter param;
          sprintf(templateString, "%s<", expClass.templateClass.fullName);
@@ -1708,7 +1850,7 @@ void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, Da
                int id = p;
                Class sClass;
                ClassTemplateArgument arg;
-               for(sClass = cClass.base; sClass; sClass = sClass.base) 
+               for(sClass = cClass.base; sClass; sClass = sClass.base)
                {
                   if(sClass.templateClass) sClass = sClass.templateClass;
                   id += sClass.templateParams.count;
@@ -1723,12 +1865,12 @@ void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, Da
                   Class nextClass;
                   if(sClass.templateClass) sClass = sClass.templateClass;
 
-                  for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) 
+                  for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
                   {
                      if(nextClass.templateClass) nextClass = nextClass.templateClass;
                      p += nextClass.templateParams.count;
                   }
-                  
+
                   for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
                   {
                      if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
@@ -1762,6 +1904,7 @@ void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, Da
                         Expression exp;
                         char * string = PrintHexUInt64(arg.expression.ui64);
                         exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
+                        delete string;
 
                         ProcessExpressionType(exp);
                         ComputeExpression(exp);
@@ -1797,7 +1940,7 @@ void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, Da
                      lastParam = p;
                   }
                   p++;
-               }               
+               }
             }
          }
          {
@@ -1836,7 +1979,7 @@ void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, Da
             }
          }
          //else if(!MatchTypes(member.exp.expType, type, null, _class, null, true, true, false, false))
-         else if(!MatchTypes(member.initializer.exp.expType, type, null, null, _class, true, true, false, false))
+         else if(!MatchTypes(member.initializer.exp.expType, type, null, null, _class, true, true, false, false, true))
          {
             Compiler_Error($"incompatible instance method %s\n", ident.string);
          }
@@ -1903,17 +2046,14 @@ void ProcessInstantiationType(Instantiation inst)
    if(inst._class)
    {
       MembersInit members;
-      Symbol classSym; // = inst._class.symbol; // FindClass(inst._class.name);
+      Symbol classSym;
       Class _class;
-      
-      /*if(!inst._class.symbol)
-         inst._class.symbol = FindClass(inst._class.name);*/
+
       classSym = inst._class.symbol;
       _class = classSym ? classSym.registered : null;
 
-      // DANGER: Patch for mutex not declaring its struct when not needed
       if(!_class || _class.type != noHeadClass)
-         DeclareStruct(inst._class.name, false); //_class && _class.type == noHeadClass);
+         DeclareStruct(curExternal, inst._class.name, false, true);
 
       afterExternal = afterExternal ? afterExternal : curExternal;
 
@@ -1947,14 +2087,13 @@ void ProcessInstantiationType(Instantiation inst)
                   if(inCompiler)
                   {
                      char number[16];
-                     //members.function.dontMangle = true;
                      strcpy(name, "__ecereInstMeth_");
                      FullClassNameCat(name, _class ? _class.fullName : "_UNKNOWNCLASS", false);
                      strcat(name, "_");
                      strcat(name, nameID.string);
                      strcat(name, "_");
                      sprintf(number, "_%08d", instMethodID++);
-                     strcat(name, number);                     
+                     strcat(name, number);
                      nameID.string = CopyString(name);
                   }
 
@@ -1963,7 +2102,7 @@ void ProcessInstantiationType(Instantiation inst)
                   {
                      Symbol symbol = declarator.symbol;
                      Method method = eClass_FindMethod(_class, unmangled, privateModule);
-                                    
+
                      if(method && method.type == virtualMethod)
                      {
                         symbol.method = method;
@@ -1971,7 +2110,7 @@ void ProcessInstantiationType(Instantiation inst)
 
                         if(!symbol.type.thisClass)
                         {
-                           if(method.dataType.thisClass && currentClass && 
+                           if(method.dataType.thisClass && currentClass &&
                               eClass_IsDerived(currentClass, method.dataType.thisClass.registered))
                            {
                               if(!currentClass.symbol)
@@ -1985,8 +2124,7 @@ void ProcessInstantiationType(Instantiation inst)
                               symbol.type.thisClass = _class.symbol;
                            }
                         }
-                        // TESTING THIS HERE:
-                        DeclareType(symbol.type, true, true);
+                        DeclareType(curExternal, symbol.type, true, true);
 
                      }
                      else if(classSym)
@@ -1996,7 +2134,6 @@ void ProcessInstantiationType(Instantiation inst)
                      }
                   }
 
-                  //declarator.symbol.id = declarator.symbol.idCode = curExternal.symbol.idCode;
                   createdExternal = ProcessClassFunction(classSym ? classSym.registered : null, members.function, ast, afterExternal, true);
 
                   if(nameID)
@@ -2005,88 +2142,11 @@ void ProcessInstantiationType(Instantiation inst)
                      nameID._class = null;
                   }
 
+                  curExternal = createdExternal;
                   if(inCompiler)
                   {
-
-                     Type type = declarator.symbol.type;
-                     External oldExternal = curExternal;
-
-                     // *** Commented this out... Any negative impact? Yes: makes double prototypes declarations... Why was it commented out?
-                     // *** It was commented out for problems such as
-                     /*
-                           class VirtualDesktop : Window
-                           {
-                              clientSize = Size { };
-                              Timer timer
-                              {
-                                 bool DelayExpired()
-                                 {
-                                    clientSize.w;
-                                    return true;
-                                 }
-                              };
-                           }
-                     */
-                     // Commented Out: Good for bet.ec in Poker (Otherwise: obj\bet.c:187: error: `currentBet' undeclared (first use in this function))
-
-                     declarator.symbol.id = declarator.symbol.idCode = curExternal.symbol.idCode;
-
-                     /*
-                     if(strcmp(declarator.symbol.string, name))
-                     {
-                        printf("TOCHECK: Look out for this\n");
-                        delete declarator.symbol.string;
-                        declarator.symbol.string = CopyString(name);
-                     }
-                     
-                     if(!declarator.symbol.parent && globalContext.symbols.root != (BTNode)declarator.symbol)
-                     {
-                        printf("TOCHECK: Will this ever be in a list? Yes.\n");
-                        excludedSymbols->Remove(declarator.symbol);
-                        globalContext.symbols.Add((BTNode)declarator.symbol);
-                        if(strstr(declarator.symbol.string), "::")
-                           globalContext.hasNameSpace = true;
-
-                     }
-                     */
-                  
-                     //curExternal = curExternal.prev;
-                     //afterExternal = afterExternal->next;
-
-                     //ProcessFunction(afterExternal->function);
-
-                     //curExternal = afterExternal;
-                     {
-                        External externalDecl;
-                        externalDecl = MkExternalDeclaration(null);
-                        ast->Insert(oldExternal.prev, externalDecl);
-
-                        // Which function does this process?
-                        if(createdExternal.function)
-                        {
-                           ProcessFunction(createdExternal.function);
-
-                           //curExternal = oldExternal;
-
-                           {
-                              //Declaration decl = MkDeclaration(members.function.specifiers, MkListOne(MkInitDeclarator(CopyDeclarator(declarator), null)));
-
-                              Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier), 
-                                 MkListOne(MkInitDeclarator(CopyDeclarator(declarator), null)));
-                     
-                              //externalDecl = MkExternalDeclaration(decl);
-                        
-                              //***** ast->Insert(external.prev, externalDecl);
-                              //ast->Insert(curExternal.prev, externalDecl);
-                              externalDecl.declaration = decl;
-                              if(decl.symbol && !decl.symbol.pointerExternal)
-                                 decl.symbol.pointerExternal = externalDecl;
-
-                              // Trying this out...
-                              declarator.symbol.pointerExternal = externalDecl;
-                           }
-                        }
-                     }
+                     if(createdExternal.function)
+                        ProcessFunction(createdExternal.function);
                   }
                   else if(declarator)
                   {
@@ -2131,36 +2191,42 @@ void ProcessInstantiationType(Instantiation inst)
    }
 }
 
-static void DeclareType(Type type, bool declarePointers, bool declareParams)
+void DeclareType(External neededFor, Type type, bool needDereference, bool forFunctionDef)
+{
+   _DeclareType(neededFor, type, needDereference, forFunctionDef, false);
+}
+
+void DeclareTypeForwardDeclare(External neededFor, Type type, bool needDereference, bool forFunctionDef)
+{
+   _DeclareType(neededFor, type, needDereference, forFunctionDef, true);
+}
+
+static void _DeclareType(External neededFor, Type type, bool needDereference, bool forFunctionDef, bool fwdDecl)
 {
-   // OPTIMIZATIONS: TESTING THIS...
    if(inCompiler)
    {
       if(type.kind == functionType)
       {
          Type param;
-         if(declareParams)
-         {
-            for(param = type.params.first; param; param = param.next)
-               DeclareType(param, declarePointers, true);
-         }
-         DeclareType(type.returnType, declarePointers, true);
+         for(param = type.params.first; param; param = param.next)
+            _DeclareType(neededFor, param, forFunctionDef, false, fwdDecl);
+         _DeclareType(neededFor, type.returnType, forFunctionDef, false, fwdDecl);
       }
-      else if(type.kind == pointerType && declarePointers)
-         DeclareType(type.type, declarePointers, false);
+      else if(type.kind == pointerType)
+         _DeclareType(neededFor, type.type, false, false, fwdDecl);
       else if(type.kind == classType)
       {
-         if(type._class.registered && (type._class.registered.type == structClass || type._class.registered.type == noHeadClass) && !type._class.declaring)
-            DeclareStruct(type._class.registered.fullName, type._class.registered.type == noHeadClass);
+         Class c = type._class.registered;
+         _DeclareStruct(neededFor, c ? c.fullName : "ecere::com::Instance", c ? c.type == noHeadClass : false, needDereference && c && c.type == structClass, fwdDecl);
       }
       else if(type.kind == structType || type.kind == unionType)
       {
          Type member;
          for(member = type.members.first; member; member = member.next)
-            DeclareType(member, false, false);
+            _DeclareType(neededFor, member, needDereference, forFunctionDef, fwdDecl);
       }
       else if(type.kind == arrayType)
-         DeclareType(type.arrayType, declarePointers, false);
+         _DeclareType(neededFor, type.arrayType, true, false, fwdDecl);
    }
 }
 
@@ -2234,7 +2300,7 @@ public Context SetupTemplatesContext(Class _class)
                   // ADD DATA TYPE HERE...
                   p.param = param = TemplateParameter
                   {
-                     identifier = MkIdentifier(p.name), type = p.type, 
+                     identifier = MkIdentifier(p.name), type = p.type,
                      dataTypeString = p.dataTypeString /*, dataType = { specs, decl }*/
                   };
                }
@@ -2338,18 +2404,17 @@ public void ProcessPropertyType(Property prop)
    }
 }
 
-public void DeclareMethod(Method method, char * name)
+public void DeclareMethod(External neededFor, Method method, const char * name)
 {
    Symbol symbol = method.symbol;
-   if(!symbol || (!symbol.pointerExternal && method.type == virtualMethod) || symbol.id > (curExternal ? curExternal.symbol.idCode : -1))
+   if(!symbol || (!symbol.pointerExternal && (!symbol.methodCodeExternal || method.type == virtualMethod)))
    {
-      bool imported = false;
       bool dllImport = false;
 
       if(!method.dataType)
          method.dataType = ProcessTypeString(method.dataTypeString, false);
 
-      if(!symbol || symbol._import || method.type == virtualMethod)
+      //if(!symbol || symbol._import || method.type == virtualMethod)
       {
          if(!symbol || method.type == virtualMethod)
          {
@@ -2360,7 +2425,7 @@ public void DeclareMethod(Method method, char * name)
             if(!classSym._import)
             {
                ModuleImport module;
-               
+
                if(method._class.module && method._class.module.name)
                   module = FindModule(method._class.module);
                else
@@ -2387,45 +2452,18 @@ public void DeclareMethod(Method method, char * name)
             }
             if(!symbol)
             {
-               // Set the symbol type
-               /*
-               if(!type.thisClass)
-               {
-                  type.thisClass = method._class.symbol; // FindClass(method._class.fullName);
-               }
-               else if(type.thisClass == (void *)-1)
-               {
-                  type.thisClass = null;
-               }
-               */
-               // symbol.type = ProcessTypeString(method.dataTypeString, false);
                symbol.type = method.dataType;
                if(symbol.type) symbol.type.refCount++;
             }
-            /*
-            if(!method.thisClass || strcmp(method.thisClass, "void"))
-               symbol.type.params.Insert(null, 
-                  MkClassType(method.thisClass ? method.thisClass : method._class.fullName));
-            */
          }
          if(!method.dataType.dllExport)
          {
-            imported = true;
-            if(method._class.module != privateModule && method._class.module.importType != staticImport)
+            if((method._class.module != privateModule || !strcmp(method._class.name, "float") || !strcmp(method._class.name, "double")) && method._class.module.importType != staticImport)
                dllImport = true;
          }
       }
 
-      /* MOVING THIS UP
-      if(!method.dataType)
-         method.dataType = ((Symbol)method.symbol).type;
-         //ProcessMethodType(method);
-      */
-
-      if(method.type != virtualMethod && method.dataType)
-         DeclareType(method.dataType, true, true);
-
-      if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
+      if(inCompiler)
       {
          // We need a declaration here :)
          Declaration decl;
@@ -2437,7 +2475,6 @@ public void DeclareMethod(Method method, char * name)
          specifiers = MkList();
          declarators = MkList();
 
-         //if(imported)
          if(dllImport)
             ListAdd(specifiers, MkSpecifier(EXTERN));
          else if(method._class.symbol && ((Symbol)method._class.symbol).isStatic)
@@ -2451,7 +2488,6 @@ public void DeclareMethod(Method method, char * name)
          else
          {
             d = MkDeclaratorIdentifier(MkIdentifier(name));
-            //if(imported)
             if(dllImport)
                d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
             {
@@ -2482,7 +2518,7 @@ public void DeclareMethod(Method method, char * name)
                {
                   Class _class = method.dataType.thisClass ? method.dataType.thisClass.registered : method._class;
                   TypeName thisParam = MkTypeName(MkListOne(
-                     MkSpecifierName/*MkClassName*/(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)), 
+                     MkSpecifierName(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)),
                      (_class && _class.type == systemClass) ? MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("this"))) : MkDeclaratorIdentifier(MkIdentifier("this")));
                   TypeName firstParam = ((TypeName)funcDecl.function.parameters->first);
                   Specifier firstSpec = firstParam.qualifiers ? firstParam.qualifiers->first : null;
@@ -2499,17 +2535,8 @@ public void DeclareMethod(Method method, char * name)
                   funcDecl.function.parameters->Insert(null, thisParam);
                }
             }
-            // Make sure we don't have empty parameter declarations for static methods...
-            /*
-            else if(!funcDecl.function.parameters)
-            {
-               funcDecl.function.parameters = MkList();
-               funcDecl.function.parameters->Insert(null, 
-                  MkTypeName(MkListOne(MkSpecifier(VOID)),null));
-            }*/
          }
-         // TESTING THIS:
-         ProcessDeclarator(d);
+         ProcessDeclarator(d, true);
 
          ListAdd(declarators, MkInitDeclarator(d, null));
 
@@ -2517,35 +2544,19 @@ public void DeclareMethod(Method method, char * name)
 
          ReplaceThisClassSpecifiers(specifiers, method._class);
 
-         // Keep a different symbol for the function definition than the declaration...
-         if(symbol.pointerExternal)
-         {
-            Symbol functionSymbol { };
-
-            // Copy symbol
-            {
-               *functionSymbol = *symbol;
-               functionSymbol.string = CopyString(symbol.string);
-               if(functionSymbol.type)
-                  functionSymbol.type.refCount++;
-            }
-
-            excludedSymbols->Add(functionSymbol);
-            symbol.pointerExternal.symbol = functionSymbol;
-         }
          external = MkExternalDeclaration(decl);
-         if(curExternal)
-            ast->Insert(curExternal ? curExternal.prev : null, external);
          external.symbol = symbol;
          symbol.pointerExternal = external;
+         ast->Add(external);
+         DeclareStruct(external, method._class.fullName, true, true);
+         if(method.dataType)
+            DeclareType(external, method.dataType, true, true);
       }
-      else if(ast)
-      {
-         // Move declaration higher...
-         ast->Move(symbol.pointerExternal, curExternal.prev);
-      }
-
-      symbol.id = curExternal ? curExternal.symbol.idCode : MAXINT;
+   }
+   if(inCompiler && neededFor)
+   {
+      External external = symbol.pointerExternal ? symbol.pointerExternal : symbol.methodCodeExternal;
+      neededFor.CreateUniqueEdge(external, external.type == functionExternal);
    }
 }
 
@@ -2557,7 +2568,7 @@ char * ReplaceThisClass(Class _class)
       int p = 0;
       ClassTemplateParameter param;
       int lastParam = -1;
-      
+
       char className[1024];
       strcpy(className, _class.fullName);
       for(param = _class.templateParams.first; param; param = param.next)
@@ -2587,11 +2598,12 @@ char * ReplaceThisClass(Class _class)
       return CopyString(className);
    }
    else
-      return CopyString(_class.fullName);   
+      return CopyString(_class.fullName);
 }
 
 Type ReplaceThisClassType(Class _class)
 {
+   Type type;
    if(thisClassParams && _class.templateParams.count && !_class.templateClass)
    {
       bool first = true;
@@ -2600,7 +2612,7 @@ Type ReplaceThisClassType(Class _class)
       int lastParam = -1;
       char className[1024];
       strcpy(className, _class.fullName);
-      
+
       for(param = _class.templateParams.first; param; param = param.next)
       {
          // if((!param.defaultArg.dataTypeString && !param.defaultArg.expression.ui64))
@@ -2625,14 +2637,16 @@ Type ReplaceThisClassType(Class _class)
          className[len++] = '>';
          className[len++] = '\0';
       }
-      return MkClassType(className);
-      //return ProcessTypeString(className, false);
+      type = MkClassType(className);
+      //type = ProcessTypeString(className, false);
    }
    else
    {
-      return MkClassType(_class.fullName);
-      //return ProcessTypeString(_class.fullName, false);
+      type = MkClassType(_class.fullName);
+      //type = ProcessTypeString(_class.fullName, false);
    }
+   //type.wasThisClass = true;
+   return type;
 }
 
 void ReplaceThisClassSpecifiers(OldList specs, Class _class)
@@ -2653,10 +2667,11 @@ void ReplaceThisClassSpecifiers(OldList specs, Class _class)
 }
 
 // Returns imported or not
-bool DeclareFunction(GlobalFunction function, char * name)
+bool DeclareFunction(External neededFor, GlobalFunction function, char * name)
 {
    Symbol symbol = function.symbol;
-   if(curExternal && (!symbol || symbol.id > curExternal.symbol.idCode))
+   // TOCHECK: Might get rid of the pointerExternal check in favor of marking the edge as breakable
+   if(!symbol || !symbol.pointerExternal)
    {
       bool imported = false;
       bool dllImport = false;
@@ -2696,11 +2711,10 @@ bool DeclareFunction(GlobalFunction function, char * name)
             dllImport = true;
       }
 
-      DeclareType(function.dataType, true, true);
-
       if(inCompiler)
       {
-         if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
+         // TOCHECK: What's with the functionExternal check here? Is it Edge breaking / forward declaration?
+         //if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
          {
             // We need a declaration here :)
             Declaration decl;
@@ -2712,15 +2726,9 @@ bool DeclareFunction(GlobalFunction function, char * name)
             specifiers = MkList();
             declarators = MkList();
 
-            //if(imported)
-               ListAdd(specifiers, MkSpecifier(EXTERN));
-            /*
-            else
-               ListAdd(specifiers, MkSpecifier(STATIC));
-            */
+            ListAdd(specifiers, MkSpecifier(EXTERN));
 
             d = MkDeclaratorIdentifier(MkIdentifier(imported ? name : function.name));
-            //if(imported)
             if(dllImport)
                d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
 
@@ -2744,7 +2752,7 @@ bool DeclareFunction(GlobalFunction function, char * name)
             if(funcDecl && !funcDecl.function.parameters)
             {
                funcDecl.function.parameters = MkList();
-               funcDecl.function.parameters->Insert(null, 
+               funcDecl.function.parameters->Insert(null,
                   MkTypeName(MkListOne(MkSpecifier(VOID)),null));
             }
 
@@ -2758,7 +2766,8 @@ bool DeclareFunction(GlobalFunction function, char * name)
             }
 
             // Keep a different symbol for the function definition than the declaration...
-            if(symbol.pointerExternal)
+            /* Note: This should be handled by the edge breaking...
+            if(symbol.pointerExternal && symbol.pointerExternal.type == functionExternal)
             {
                Symbol functionSymbol { };
                // Copy symbol
@@ -2773,29 +2782,26 @@ bool DeclareFunction(GlobalFunction function, char * name)
 
                symbol.pointerExternal.symbol = functionSymbol;
             }
+            */
             external = MkExternalDeclaration(decl);
-            if(curExternal)
-               ast->Insert(curExternal.prev, external);
+            ast->Add(external);
             external.symbol = symbol;
             symbol.pointerExternal = external;
-         }
-         else
-         {
-            // Move declaration higher...
-            ast->Move(symbol.pointerExternal, curExternal.prev);
-         }
 
-         if(curExternal)
-            symbol.id = curExternal.symbol.idCode;
+            DeclareType(external, function.dataType, true, true);
+         }
       }
    }
+   if(inCompiler && neededFor && symbol && symbol.pointerExternal)
+      neededFor.CreateUniqueEdge(symbol.pointerExternal, symbol.pointerExternal.type == functionExternal);
    return (symbol && symbol._import && function.module != privateModule && function.module.importType != staticImport) ? true : false;
 }
 
-void DeclareGlobalData(GlobalData data)
+void DeclareGlobalData(External neededFor, GlobalData data)
 {
    Symbol symbol = data.symbol;
-   if(curExternal && (!symbol || symbol.id > curExternal.symbol.idCode))
+   // TOCHECK: Might get rid of the pointerExternal check in favor of marking the edge as breakable
+   if(!symbol || !symbol.pointerExternal)
    {
       if(inCompiler)
       {
@@ -2804,43 +2810,36 @@ void DeclareGlobalData(GlobalData data)
       }
       if(!data.dataType)
          data.dataType = ProcessTypeString(data.dataTypeString, false);
-      DeclareType(data.dataType, true, true);
+
       if(inCompiler)
       {
-         if(!symbol.pointerExternal)
-         {
-            // We need a declaration here :)
-            Declaration decl;
-            OldList * specifiers, * declarators;
-            Declarator d;
-            External external;
-
-            specifiers = MkList();
-            declarators = MkList();
+         // We need a declaration here :)
+         Declaration decl;
+         OldList * specifiers, * declarators;
+         Declarator d;
+         External external;
 
-            ListAdd(specifiers, MkSpecifier(EXTERN));
-            d = MkDeclaratorIdentifier(MkIdentifier(data.fullName));
-            d = SpecDeclFromString(data.dataTypeString, specifiers, d);
+         specifiers = MkList();
+         declarators = MkList();
 
-            ListAdd(declarators, MkInitDeclarator(d, null));
+         ListAdd(specifiers, MkSpecifier(EXTERN));
+         d = MkDeclaratorIdentifier(MkIdentifier(data.fullName));
+         d = SpecDeclFromString(data.dataTypeString, specifiers, d);
 
-            decl = MkDeclaration(specifiers, declarators);
-            external = MkExternalDeclaration(decl);
-            if(curExternal)
-               ast->Insert(curExternal.prev, external);
-            external.symbol = symbol;
-            symbol.pointerExternal = external;
-         }
-         else
-         {
-            // Move declaration higher...
-            ast->Move(symbol.pointerExternal, curExternal.prev);
-         }
+         ListAdd(declarators, MkInitDeclarator(d, null));
 
+         decl = MkDeclaration(specifiers, declarators);
+         external = MkExternalDeclaration(decl);
          if(curExternal)
-            symbol.id = curExternal.symbol.idCode;
+            ast->Insert(curExternal.prev, external);
+         external.symbol = symbol;
+         symbol.pointerExternal = external;
+
+         DeclareType(external, data.dataType, true, true);
       }
    }
+   if(inCompiler && neededFor && symbol && symbol.pointerExternal)
+      neededFor.CreateUniqueEdge(symbol.pointerExternal, false);
 }
 
 class Conversion : struct
@@ -2851,10 +2850,38 @@ class Conversion : struct
    Type resultType;
 };
 
-public bool MatchTypes(Type source, Type dest, OldList conversions, Class owningClassSource, Class owningClassDest, bool doConversion, bool enumBaseType, bool acceptReversedParams, bool isConversionExploration)
+static bool CheckConstCompatibility(Type source, Type dest, bool warn)
+{
+   bool status = true;
+   if(((source.kind == classType && source._class && source._class.registered) || source.kind == arrayType || source.kind == pointerType) &&
+      ((dest.kind == classType && dest._class && dest._class.registered) || /*dest.kind == arrayType || */dest.kind == pointerType))
+   {
+      Class sourceClass = source.kind == classType ? source._class.registered : null;
+      Class destClass = dest.kind == classType ? dest._class.registered : null;
+      if((!sourceClass || (sourceClass && sourceClass.type == normalClass && !sourceClass.structSize)) &&
+         (!destClass || (destClass && destClass.type == normalClass && !destClass.structSize)))
+      {
+         Type sourceType = source, destType = dest;
+         while((sourceType.kind == pointerType || sourceType.kind == arrayType) && sourceType.type) sourceType = sourceType.type;
+         while((destType.kind == pointerType || destType.kind == arrayType) && destType.type) destType = destType.type;
+         if(!destType.constant && sourceType.constant)
+         {
+            status = false;
+            if(warn)
+               Compiler_Warning($"discarding const qualifier\n");
+         }
+      }
+   }
+   return status;
+}
+
+public bool MatchTypes(Type source, Type dest, OldList conversions, Class owningClassSource, Class owningClassDest, bool doConversion, bool enumBaseType, bool acceptReversedParams,
+                       bool isConversionExploration, bool warnConst)
 {
    if(source && dest)
    {
+      if(warnConst)
+         CheckConstCompatibility(source, dest, true);
       // Property convert;
 
       if(source.kind == templateType && dest.kind != templateType)
@@ -2869,7 +2896,7 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
          if(type) dest = type;
       }
 
-      if(dest.classObjectType == typedObject)
+      if(dest.classObjectType == typedObject && dest.kind != functionType)
       {
          if(source.classObjectType != anyObject)
             return true;
@@ -2884,12 +2911,12 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
       }
       else
       {
-         if(source.classObjectType == anyObject)
+         if(source.kind != functionType && source.classObjectType == anyObject)
             return true;
-         if(dest.classObjectType == anyObject && source.classObjectType != typedObject)
+         if(dest.kind != functionType && dest.classObjectType == anyObject && source.classObjectType != typedObject)
             return true;
       }
-      
+
       if((dest.kind == structType && source.kind == structType) ||
          (dest.kind == unionType && source.kind == unionType))
       {
@@ -2906,13 +2933,12 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
          || source.kind == subClassType || source.kind == pointerType || source.kind == arrayType || source.kind == functionType || source.kind == thisClassType)
 
          /*source.kind != voidType && source.kind != structType && source.kind != unionType  */
-      
+
          /*&& (source.kind != classType /-*|| source._class.registered.type != structClass)*/)
          return true;
       if(!isConversionExploration && source.kind == pointerType && source.type.kind == voidType &&
          ((dest.kind == classType && (!dest._class || !dest._class.registered || dest._class.registered.type == structClass || dest._class.registered.type == normalClass || dest._class.registered.type == noHeadClass || dest._class.registered.type == systemClass))
          || dest.kind == subClassType || dest.kind == pointerType || dest.kind == arrayType || dest.kind == functionType || dest.kind == thisClassType)
-
          /* dest.kind != voidType && dest.kind != structType && dest.kind != unionType  */
 
          /*&& (dest.kind != classType || dest._class.registered.type != structClass)*/)
@@ -2939,16 +2965,18 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
          // Don't match enum inheriting from other enum if resolving enumeration values
          // TESTING: !dest.classObjectType
          else if(source._class && dest._class && (dest.classObjectType == source.classObjectType || !dest.classObjectType) &&
-            (enumBaseType || 
-               (!source._class.registered || source._class.registered.type != enumClass) || 
+            (enumBaseType ||
+               (!source._class.registered || source._class.registered.type != enumClass) ||
                (!dest._class.registered || dest._class.registered.type != enumClass)) && eClass_IsDerived(source._class.registered, dest._class.registered))
             return true;
          else
          {
             // Added this so that DefinedColor = Color doesn't go through ColorRGB property
-            if(enumBaseType && 
-               dest._class && dest._class.registered && dest._class.registered.type == enumClass &&
-               ((source._class && source._class.registered && source._class.registered.type != enumClass) || source.kind == classType)) // Added this here for a base enum to be acceptable for a derived enum (#139)
+            if(dest._class && dest._class.registered && source._class && source._class.registered &&
+               (dest.casted || (enumBaseType && dest._class.registered.type == enumClass &&
+                  (source.kind == classType ||  // Added this here for a base enum to be acceptable for a derived enum (#139)
+                   source._class.registered.type != enumClass)
+                ) ) )
             {
                if(eClass_IsDerived(dest._class.registered, source._class.registered))
                {
@@ -2979,14 +3007,18 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
 
                      if(!convert.dataType)
                         convert.dataType = ProcessTypeString(convert.dataTypeString, false);
-                     if(MatchTypes(convert.dataType, dest, conversions, null, null, false, true, false, true))
+                     // Only go ahead with this conversion flow while processing an existing conversion if the conversion data type is a class
+                     if((!isConversionExploration || convert.dataType.kind == classType || !strcmp(_class.name, "String")) &&
+                        MatchTypes(convert.dataType, dest, conversions, null, null,
+                           (convert.dataType.kind == classType && !strcmp(convert.dataTypeString, "String")) ? true : false,
+                              convert.dataType.kind == classType, false, true, warnConst))
                      {
                         if(!conversions && !convert.Get)
                            return true;
                         else if(conversions != null)
                         {
-                           if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class && 
-                              convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base && 
+                           if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
+                              convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
                               (dest.kind != classType || dest._class.registered != _class.base))
                               return true;
                            else
@@ -2994,6 +3026,7 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                               Conversion conv { convert = convert, isGet = true };
                               // conversions.Add(conv);
                               conversions.Insert(after, conv);
+
                               return true;
                            }
                         }
@@ -3015,38 +3048,53 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                {
                   if(convert.memberAccess == publicAccess || _class.module == privateModule)
                   {
+                     Type constType = null;
+                     bool success = false;
                      // Conversion after = (conversions != null) ? conversions.last : null;
 
-                     if(!convert.dataType)
-                        convert.dataType = ProcessTypeString(convert.dataTypeString, false);
+                     if(!convert.dataType)
+                        convert.dataType = ProcessTypeString(convert.dataTypeString, false);
+
+                     if(warnConst && convert.dataType.kind == pointerType && convert.dataType.type && dest.constant)
+                     {
+                        Type ptrType { };
+                        constType = { kind = pointerType, refCount = 1, type = ptrType };
+                        CopyTypeInto(ptrType, convert.dataType.type);
+                        ptrType.constant = true;
+                     }
+
                      // Just added this equality check to prevent recursion.... Make it safer?
                      // Changed enumBaseType to false here to prevent all int-compatible enums to show up in AnchorValues
-                     if(convert.dataType != dest && MatchTypes(source, convert.dataType, conversions, null, null, true, false /*true*/, false, true))
+                     if((constType || convert.dataType != dest) && MatchTypes(source, constType ? constType : convert.dataType, conversions, null, null, true, false /*true*/, false, true, warnConst))
                      {
                         if(!conversions && !convert.Set)
-                           return true;
+                           success = true;
                         else if(conversions != null)
                         {
-                           if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class && 
-                              convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base && 
+                           if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
+                              convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
                               (source.kind != classType || source._class.registered != _class.base))
-                              return true;
+                              success = true;
                            else
                            {
                               // *** Testing this! ***
                               Conversion conv { convert = convert };
                               conversions.Add(conv);
                               //conversions.Insert(after, conv);
-                              return true;
+                              success = true;
                            }
                         }
                      }
+                     if(constType)
+                        FreeType(constType);
+                     if(success)
+                        return true;
                   }
                }
             }
             /*if(dest._class.registered && !strcmp(dest._class.registered.name, "bool"))
             {
-               if(source.kind != voidType && source.kind != structType && source.kind != unionType && 
+               if(source.kind != voidType && source.kind != structType && source.kind != unionType &&
                   (source.kind != classType || source._class.registered.type != structClass))
                   return true;
             }*/
@@ -3060,7 +3108,7 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                if(dest._class.registered.dataType.kind == classType || source.truth || dest.truth/* ||
                   !strcmp(dest._class.registered.name, "bool") || (source.kind == classType && !strcmp(source._class.string, "bool"))*/)
                {
-                  if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
+                  if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, dest._class.registered.dataType.kind == classType, false, false, warnConst))
                   {
                      return true;
                   }
@@ -3083,14 +3131,16 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
 
                      if(!convert.dataType)
                         convert.dataType = ProcessTypeString(convert.dataTypeString, false);
-                     if(convert.dataType != source && MatchTypes(convert.dataType, dest, conversions, null, null, true, true, false, true))
+                     if(convert.dataType != source &&
+                        (!isConversionExploration || convert.dataType.kind == classType || !strcmp(_class.name, "String")) &&
+                        MatchTypes(convert.dataType, dest, conversions, null, null, convert.dataType.kind == classType, convert.dataType.kind == classType, false, true, warnConst))
                      {
                         if(!conversions && !convert.Get)
                            return true;
                         else if(conversions != null)
                         {
-                           if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class && 
-                              convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base && 
+                           if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
+                              convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
                               (dest.kind != classType || dest._class.registered != _class.base))
                               return true;
                            else
@@ -3112,9 +3162,13 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
             {
                if(!source._class.registered.dataType)
                   source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
-               if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, true, false, false))
+               if(!isConversionExploration || source._class.registered.dataType.kind == classType || !strcmp(source._class.registered.name, "String"))
                {
-                  return true;
+                  if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, source._class.registered.dataType.kind == classType, source._class.registered.dataType.kind == classType, false, false, warnConst))
+                     return true;
+                  // For bool to be accepted by byte, short, etc.
+                  else if(MatchTypes(dest, source._class.registered.dataType, null, null, null, false, false, false, false, warnConst))
+                     return true;
                }
             }
          }
@@ -3122,44 +3176,44 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
 
       if(source.kind == classType || source.kind == subClassType)
          ;
-      else if(dest.kind == source.kind && 
+      else if(dest.kind == source.kind &&
          (dest.kind != structType && dest.kind != unionType &&
           dest.kind != functionType && dest.kind != arrayType && dest.kind != pointerType && dest.kind != methodType))
           return true;
       // RECENTLY ADDED THESE
       else if(dest.kind == doubleType && source.kind == floatType)
          return true;
-      else if(dest.kind == shortType && source.kind == charType)
+      else if(dest.kind == shortType && (source.kind == charType || source.kind == _BoolType))
          return true;
-      else if(dest.kind == intType && (source.kind == shortType || source.kind == charType || source.kind == intSizeType /* Exception here for size_t */))
+      else if(dest.kind == intType && (source.kind == shortType || source.kind == charType || source.kind == _BoolType || source.kind == intSizeType /* Exception here for size_t */))
          return true;
-      else if(dest.kind == int64Type && (source.kind == shortType || source.kind == charType || source.kind == intType || source.kind == intPtrType || source.kind == intSizeType))
+      else if(dest.kind == int64Type && (source.kind == shortType || source.kind == charType || source.kind == _BoolType || source.kind == intType || source.kind == intPtrType || source.kind == intSizeType))
          return true;
-      else if(dest.kind == intPtrType && (source.kind == shortType || source.kind == charType || source.kind == intType || source.kind == intSizeType || source.kind == int64Type))
+      else if(dest.kind == intPtrType && (source.kind == shortType || source.kind == charType || source.kind == _BoolType || source.kind == intType || source.kind == intSizeType || source.kind == int64Type))
          return true;
-      else if(dest.kind == intSizeType && (source.kind == shortType || source.kind == charType || source.kind == intType || source.kind == int64Type || source.kind == intPtrType))
+      else if(dest.kind == intSizeType && (source.kind == shortType || source.kind == charType || source.kind == _BoolType || source.kind == intType || source.kind == int64Type || source.kind == intPtrType))
          return true;
       else if(source.kind == enumType &&
-         (dest.kind == intType || dest.kind == shortType || dest.kind == charType || dest.kind == longType || dest.kind == int64Type || dest.kind == intPtrType || dest.kind == intSizeType))
+         (dest.kind == intType || dest.kind == shortType || dest.kind == charType || source.kind == _BoolType || dest.kind == longType || dest.kind == int64Type || dest.kind == intPtrType || dest.kind == intSizeType))
           return true;
-      else if(dest.kind == enumType &&
-         (source.kind == intType || source.kind == shortType || source.kind == charType || source.kind == longType || source.kind == int64Type || source.kind == intPtrType || source.kind == intSizeType))
+      else if(dest.kind == enumType && !isConversionExploration &&
+         (source.kind == intType || source.kind == shortType || source.kind == charType || source.kind == _BoolType || source.kind == longType || source.kind == int64Type || source.kind == intPtrType || source.kind == intSizeType))
           return true;
-      else if((dest.kind == functionType || (dest.kind == pointerType && dest.type.kind == functionType) || dest.kind == methodType) && 
+      else if((dest.kind == functionType || (dest.kind == pointerType && dest.type.kind == functionType) || dest.kind == methodType) &&
               ((source.kind == functionType || (source.kind == pointerType && source.type.kind == functionType) || source.kind == methodType)))
       {
          Type paramSource, paramDest;
 
-         if(dest.kind == methodType)     
+         if(dest.kind == methodType)
             owningClassDest = dest.methodClass ? dest.methodClass : dest.method._class;
-         if(source.kind == methodType)   
+         if(source.kind == methodType)
             owningClassSource = source.methodClass ? source.methodClass : source.method._class;
 
          if(dest.kind == pointerType && dest.type.kind == functionType) dest = dest.type;
          if(source.kind == pointerType && source.type.kind == functionType) source = source.type;
-         if(dest.kind == methodType) 
+         if(dest.kind == methodType)
             dest = dest.method.dataType;
-         if(source.kind == methodType) 
+         if(source.kind == methodType)
             source = source.method.dataType;
 
          paramSource = source.params.first;
@@ -3167,8 +3221,8 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
          paramDest = dest.params.first;
          if(paramDest && paramDest.kind == voidType) paramDest = null;
 
-     
-         if((dest.staticMethod || (!dest.thisClass && !owningClassDest)) && 
+
+         if((dest.staticMethod || (!dest.thisClass && !owningClassDest)) &&
             !(source.staticMethod || (!source.thisClass && !owningClassSource)))
          {
             // Source thisClass must be derived from destination thisClass
@@ -3204,7 +3258,7 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                      if(owningClassDest)
                        Compiler_Error($"%s expected to be derived from method class\n", owningClassDest.fullName);
                      else
-                        Compiler_Error($"overriding class expected to be derived from method class\n");      
+                        Compiler_Error($"overriding class expected to be derived from method class\n");
                      return false;
                   }
                }
@@ -3230,7 +3284,7 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                      //if(owningClass)
                         Compiler_Error($"%s expected to be derived from method class\n", /*owningClass.name*/ source.thisClass.registered.fullName);
                      //else
-                        //Compiler_Error($"overriding class expected to be derived from method class\n");      
+                        //Compiler_Error($"overriding class expected to be derived from method class\n");
                      return false;
                   }
                }
@@ -3239,14 +3293,17 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
 
 
          // Source return type must be derived from destination return type
-         if(!MatchTypes(source.returnType, dest.returnType, null, null, null, true, true, false, false))
+         if(!MatchTypes(source.returnType, dest.returnType, null, null, null, true, true, false, false, warnConst))
          {
             Compiler_Warning($"incompatible return type for function\n");
             return false;
          }
+         // The const check is backwards from the MatchTypes above (for derivative classes checks)
+         else
+            CheckConstCompatibility(dest.returnType, source.returnType, true);
 
          // Check parameters
-      
+
          for(; paramDest; paramDest = paramDest.next)
          {
             if(!paramSource)
@@ -3295,14 +3352,14 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                }
 
                // paramDest must be derived from paramSource
-               if(!MatchTypes(paramDestType, paramSourceType, null, null, null, true, true, false, false) && 
-                  (!acceptReversedParams || !MatchTypes(paramSourceType, paramDestType, null, null, null, true, true, false, false)))
+               if(!MatchTypes(paramDestType, paramSourceType, null, null, null, true, true, false, false, warnConst) &&
+                  (!acceptReversedParams || !MatchTypes(paramSourceType, paramDestType, null, null, null, true, true, false, false, warnConst)))
                {
                   char type[1024];
                   type[0] = 0;
                   PrintType(paramDest, type, false, true);
                   Compiler_Warning($"incompatible parameter %s (expected %s)\n", paramSource.name, type);
-                  
+
                   if(paramDestType != paramDest)
                      FreeType(paramDestType);
                   return false;
@@ -3310,7 +3367,7 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                if(paramDestType != paramDest)
                   FreeType(paramDestType);
             }
-         
+
             paramSource = paramSource.next;
          }
          if(paramSource)
@@ -3324,11 +3381,18 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
       {
          return true;
       }
-      else if((dest.kind == pointerType || dest.kind == arrayType) && 
+      else if((dest.kind == pointerType || dest.kind == arrayType) &&
          (source.kind == arrayType || source.kind == pointerType))
       {
-         if(MatchTypes(source.type, dest.type, null, null, null, true, true, false, false))
-            return true;
+         // Pointers to pointer is incompatible with non normal/nohead classes
+         if(!(dest.type && dest.type.kind == pointerType && source.type.kind == classType && source.type._class &&
+            source.type._class.registered && (source.type._class.registered.type != normalClass && source.type._class.registered.type != noHeadClass) && !source.type.byReference))
+         {
+            ComputeTypeSize(source.type);
+            ComputeTypeSize(dest.type);
+            if(source.type.size == dest.type.size && MatchTypes(source.type, dest.type, null, null, null, true, true, false, false, warnConst))
+               return true;
+         }
       }
    }
    return false;
@@ -3340,7 +3404,7 @@ static void FreeConvert(Conversion convert)
       FreeType(convert.resultType);
 }
 
-bool MatchWithEnums_NameSpace(NameSpace nameSpace, Expression sourceExp, Type dest, 
+bool MatchWithEnums_NameSpace(NameSpace nameSpace, Expression sourceExp, Type dest,
                               char * string, OldList conversions)
 {
    BTNamedLink link;
@@ -3358,9 +3422,10 @@ bool MatchWithEnums_NameSpace(NameSpace nameSpace, Expression sourceExp, Type de
             _class.symbol = FindClass(_class.fullName);
          type._class = _class.symbol;
 
-         if(MatchTypes(type, dest, &converts, null, null, true, false, false, false))
+         if(MatchTypes(type, dest, &converts, null, null, dest.kind != classType || !dest._class || strcmp(dest._class.string, "bool"),
+               false, false, false, false))
          {
-            NamedLink value;
+            NamedLink64 value;
             Class enumClass = eSystem_FindClass(privateModule, "enum");
             if(enumClass)
             {
@@ -3375,23 +3440,24 @@ bool MatchWithEnums_NameSpace(NameSpace nameSpace, Expression sourceExp, Type de
                   }
                   if(value)
                   {
-                     FreeExpContents(sourceExp);
                      FreeType(sourceExp.expType);
 
                      sourceExp.isConstant = true;
                      sourceExp.expType = MkClassType(baseClass.fullName);
-                     //if(inCompiler)
+                     if(inCompiler || inPreCompiler || inDebugger)
                      {
                         char constant[256];
+                        FreeExpContents(sourceExp);
+
                         sourceExp.type = constantExp;
-                        if(!strcmp(baseClass.dataTypeString, "int"))
-                           sprintf(constant, "%d",(int)value.data);
+                        if(!strcmp(baseClass.dataTypeString, "int") || !strcmp(baseClass.dataTypeString, "int64") || !strcmp(baseClass.dataTypeString, "short") || !strcmp(baseClass.dataTypeString, "char"))
+                           sprintf(constant, FORMAT64D, value.data);
                         else
-                           sprintf(constant, "0x%X",(int)value.data);
+                           sprintf(constant, FORMAT64HEXLL, value.data);
                         sourceExp.constant = CopyString(constant);
                         //for(;baseClass.base && baseClass.base.type != systemClass; baseClass = baseClass.base);
                      }
-                  
+
                      while(converts.first)
                      {
                         Conversion convert = converts.first;
@@ -3418,7 +3484,7 @@ bool MatchWithEnums_NameSpace(NameSpace nameSpace, Expression sourceExp, Type de
 public bool ModuleVisibility(Module searchIn, Module searchFor)
 {
    SubModule subModule;
-   
+
    if(searchFor == searchIn)
       return true;
 
@@ -3452,30 +3518,58 @@ bool MatchWithEnums_Module(Module mainModule, Expression sourceExp, Type dest, c
    return false;
 }
 
-bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, bool skipUnitBla)
+bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, bool skipUnitBla, bool warnConst)
 {
-   Type source = sourceExp.expType;
+   Type source;
    Type realDest = dest;
    Type backupSourceExpType = null;
+   Expression nbExp = GetNonBracketsExp(sourceExp);
+   Expression computedExp = nbExp;
+   dest.refCount++;
+
+   if(sourceExp.isConstant && sourceExp.type != constantExp && sourceExp.type != identifierExp && sourceExp.type != castExp &&
+      dest.kind == classType && dest._class && dest._class.registered && dest._class.registered.type == enumClass)
+   {
+      computedExp = CopyExpression(nbExp);        // Keep the original expression, but compute for checking enum ranges
+      ComputeExpression(computedExp /*sourceExp*/);
+   }
+
+   source = sourceExp.expType;
 
    if(dest.kind == pointerType && sourceExp.type == constantExp && !strtoul(sourceExp.constant, null, 0))
+   {
+      if(computedExp != nbExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = nbExp;
+      }
+      FreeType(dest);
       return true;
+   }
 
    if(!skipUnitBla && source && dest && source.kind == classType && dest.kind == classType)
    {
        if(source._class && source._class.registered && source._class.registered.type == unitClass)
        {
           Class sourceBase, destBase;
-          for(sourceBase = source._class.registered; 
+          for(sourceBase = source._class.registered;
               sourceBase && sourceBase.base && sourceBase.base.type != systemClass;
               sourceBase = sourceBase.base);
-          for(destBase = dest._class.registered; 
+          for(destBase = dest._class.registered;
               destBase && destBase.base && destBase.base.type != systemClass;
               destBase = destBase.base);
           //if(source._class.registered == dest._class.registered)
           if(sourceBase == destBase)
-             return true;
-       }
+          {
+            if(computedExp != nbExp)
+            {
+               FreeExpression(computedExp);
+               computedExp = nbExp;
+            }
+            FreeType(dest);
+            return true;
+         }
+      }
    }
 
    if(source)
@@ -3485,25 +3579,29 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
       int64 value = MAXINT;
 
       source.refCount++;
-      dest.refCount++;
 
-      if(sourceExp.type == constantExp)
+      if(computedExp.type == constantExp)
       {
          if(source.isSigned)
-            value = strtoll(sourceExp.constant, null, 0);
+            value = strtoll(computedExp.constant, null, 0);
          else
-            value = strtoull(sourceExp.constant, null, 0);
+            value = strtoull(computedExp.constant, null, 0);
       }
-      else if(sourceExp.type == opExp && sourceExp.op.op == '-' && !sourceExp.op.exp1 && sourceExp.op.exp2 && sourceExp.op.exp2.type == constantExp)
+      else if(computedExp.type == opExp && computedExp.op.op == '-' && !computedExp.op.exp1 && computedExp.op.exp2 && computedExp.op.exp2.type == constantExp)
       {
          if(source.isSigned)
-            value = -strtoll(sourceExp.op.exp2.constant, null, 0);
+            value = -strtoll(computedExp.op.exp2.constant, null, 0);
          else
-            value = -strtoull(sourceExp.op.exp2.constant, null, 0);
+            value = -strtoull(computedExp.op.exp2.constant, null, 0);
+      }
+      if(computedExp != nbExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = nbExp;
       }
 
-      if(dest.kind != classType && source.kind == classType && source._class && source._class.registered && 
-         !strcmp(source._class.registered.fullName, "ecere::com::unichar"))
+      if(dest.kind != classType && source.kind == classType && source._class && source._class.registered &&
+         !strcmp(source._class.registered.fullName, "unichar" /*"ecere::com::unichar"*/))
       {
          FreeType(source);
          source = Type { kind = intType, isSigned = false, refCount = 1 };
@@ -3531,13 +3629,24 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                tempType._class = _class.symbol;
                tempType.truth = dest.truth;
                if(tempType._class)
-                  MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
+                  MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false, warnConst);
 
                // NOTE: To handle bad warnings on int64 vs 32 bit eda::Id incompatibilities
                backupSourceExpType = sourceExp.expType;
-               sourceExp.expType = dest; dest.refCount++;
+               if(dest.passAsTemplate)
+               {
+                  // Don't carry passAsTemplate
+                  sourceExp.expType = { };
+                  CopyTypeInto(sourceExp.expType, dest);
+                  sourceExp.expType.passAsTemplate = false;
+               }
+               else
+               {
+                  sourceExp.expType = dest;
+                  dest.refCount++;
+               }
                //sourceExp.expType = MkClassType(_class.fullName);
-               flag = true;            
+               flag = true;
 
                delete tempType;
             }
@@ -3549,13 +3658,13 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
          {
             if(!dest._class.registered.dataType)
                dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
-            if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
+            if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false, warnConst))
             {
                FreeType(source);
                FreeType(sourceExp.expType);
                source = sourceExp.expType = MkClassType(dest._class.string);
                source.refCount++;
-               
+
                //source.kind = classType;
                //source._class = dest._class;
             }
@@ -3575,7 +3684,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                FreeType(source);
                source = sourceExp.expType = MkClassType(dest._class.string);
                source.refCount++;
-               
+
                //source.kind = classType;
                //source._class = dest._class;
             }
@@ -3609,7 +3718,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
       {
          Class _class = source._class ? source._class.registered : null;
 
-         if(_class && (_class.type == unitClass || !strcmp(_class.fullName, "bool") || /*_class.type == enumClass || */_class.type == bitClass ))  // TOCHECK: enumClass, bitClass is new here...
+         if(_class && (_class.type == unitClass || /*!strcmp(_class.fullName, "bool") || _class.type == enumClass || */_class.type == bitClass ))  // TOCHECK: enumClass, bitClass is new here...
          {
             /*
             if(dest.kind != classType)
@@ -3617,14 +3726,14 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                // Testing this simpler piece of code... (Broke Units Conversion to no unit Logic)
                if(!source._class.registered.dataType)
                   source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
-               
+
                FreeType(dest);
                dest = MkClassType(source._class.string);
                //if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, false, false))
                //   dest = MkClassType(source._class.string);
             }
             */
-            
+
             if(dest.kind != classType)
             {
                Type tempType { };
@@ -3642,15 +3751,15 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                tempType.classObjectType = source.classObjectType;
 
                if(tempType._class)
-                  MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
-               
+                  MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false, warnConst);
+
                // PUT THIS BACK TESTING UNITS?
-               if(conversions.last)
+               if(conversions && conversions.last)
                {
                   ((Conversion)(conversions.last)).resultType = dest;
                   dest.refCount++;
                }
-               
+
                FreeType(sourceExp.expType);
                sourceExp.expType = MkClassType(_class.fullName);
                sourceExp.expType.truth = source.truth;
@@ -3676,7 +3785,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                dest = MkClassType(source._class.string);
                dest.truth = source.truth;
                dest.classObjectType = source.classObjectType;
-               
+
                FreeType(source);
                source = _class.dataType;
                source.refCount++;
@@ -3688,7 +3797,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
 
       if(!flag)
       {
-         if(MatchTypes(source, dest, conversions, null, null, true, true, false, false))
+         if(MatchTypes(source, dest, conversions, null, null, true, true, false, false, warnConst))
          {
             FreeType(source);
             FreeType(dest);
@@ -3712,7 +3821,16 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
       if(dest.kind == classType)
       {
          Class _class = dest._class ? dest._class.registered : null;
-         if(_class && !dest.truth && (_class.type == unitClass || !strcmp(_class.fullName, "bool") || 
+         bool fittingValue = false;
+         if(_class && _class.type == enumClass)
+         {
+            Class enumClass = eSystem_FindClass(privateModule, "enum");
+            EnumClassData c = ACCESS_CLASSDATA(_class, enumClass);
+            if(c && value >= 0 && value <= c.largest)
+               fittingValue = true;
+         }
+
+         if(_class && !dest.truth && (_class.type == unitClass || fittingValue ||
             (/*_class.type == enumClass*/_class.type != structClass && !value && source.kind == intType) || _class.type == bitClass))   // TOCHECK: enumClass, bitClass is new here...
          {
             if(_class.type == normalClass || _class.type == noHeadClass)
@@ -3750,40 +3868,40 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
          }
 
          // Accept lower precision types for units, since we want to keep the unit type
-         if(dest.kind == doubleType && 
+         if(dest.kind == doubleType &&
             (source.kind == doubleType || source.kind == floatType || dest.kind == int64Type || source.kind == intType || source.kind == shortType ||
-             source.kind == charType))
+             source.kind == charType || source.kind == _BoolType))
          {
             specs = MkListOne(MkSpecifier(DOUBLE));
          }
-         else if(dest.kind == floatType && 
+         else if(dest.kind == floatType &&
             (source.kind == floatType || dest.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType ||
-            source.kind == doubleType))
+            source.kind == _BoolType || source.kind == doubleType))
          {
             specs = MkListOne(MkSpecifier(FLOAT));
          }
          else if(dest.kind == int64Type && (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType ||
-            source.kind == floatType || source.kind == doubleType))
+            source.kind == _BoolType || source.kind == floatType || source.kind == doubleType))
          {
             specs = MkList();
             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
             ListAdd(specs, MkSpecifier(INT64));
          }
          else if(dest.kind == intType && (source.kind == intType || source.kind == shortType || source.kind == charType ||
-            source.kind == floatType || source.kind == doubleType))
+            source.kind == _BoolType || source.kind == floatType || source.kind == doubleType))
          {
             specs = MkList();
             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
             ListAdd(specs, MkSpecifier(INT));
          }
-         else if(dest.kind == shortType && (source.kind == shortType || source.kind == charType || source.kind == intType ||
+         else if(dest.kind == shortType && (source.kind == shortType || source.kind == charType || source.kind == _BoolType || source.kind == intType ||
             source.kind == floatType || source.kind == doubleType))
          {
             specs = MkList();
             if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
             ListAdd(specs, MkSpecifier(SHORT));
          }
-         else if(dest.kind == charType && (source.kind == charType || source.kind == shortType || source.kind == intType ||
+         else if(dest.kind == charType && (source.kind == charType || source.kind == _BoolType || source.kind == shortType || source.kind == intType ||
             source.kind == floatType || source.kind == doubleType))
          {
             specs = MkList();
@@ -3803,45 +3921,71 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
             return false;
          }
       }
-      else if(dest.kind == doubleType && 
+      else if(dest.kind == doubleType &&
          (source.kind == doubleType || source.kind == floatType || source.kind == int64Type || source.kind == intType || source.kind == enumType || source.kind == shortType ||
-          source.kind == charType))
+          source.kind == _BoolType || source.kind == charType))
       {
          specs = MkListOne(MkSpecifier(DOUBLE));
       }
-      else if(dest.kind == floatType && 
-         (source.kind == floatType || source.kind == enumType || source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType))
+      else if(dest.kind == floatType &&
+         (source.kind == floatType || source.kind == enumType || source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == _BoolType || source.kind == charType))
       {
          specs = MkListOne(MkSpecifier(FLOAT));
       }
-      else if(dest.kind == charType && (source.kind == charType || source.kind == enumType || source.kind == shortType || source.kind == intType) && 
-         (dest.isSigned ? (value >= -128 && value <= 127) : (value >= 0 && value <= 255)))
+      else if(dest.kind == _BoolType && (source.kind == _BoolType || source.kind == charType || source.kind == enumType || source.kind == shortType || source.kind == intType) &&
+         (value == 1 || value == 0))
       {
          specs = MkList();
-         if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
-         ListAdd(specs, MkSpecifier(CHAR));
+         ListAdd(specs, MkSpecifier(BOOL));
+      }
+      else if(dest.kind == charType && (source.kind == _BoolType || source.kind == charType || source.kind == enumType || source.kind == shortType || source.kind == intType) &&
+         (dest.isSigned ? (value >= -128 && value <= 127) : (value >= 0 && value <= 255)))
+      {
+         if(source.kind == intType)
+         {
+            FreeType(dest);
+            FreeType(source);
+            if(backupSourceExpType) FreeType(backupSourceExpType);
+            return true;
+         }
+         else
+         {
+            specs = MkList();
+            if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
+            ListAdd(specs, MkSpecifier(CHAR));
+         }
       }
-      else if(dest.kind == shortType && (source.kind == enumType || source.kind == charType || source.kind == shortType || 
+      else if(dest.kind == shortType && (source.kind == enumType || source.kind == _BoolType || source.kind == charType || source.kind == shortType ||
          (source.kind == intType && (dest.isSigned ? (value >= -32768 && value <= 32767) : (value >= 0 && value <= 65535)))))
       {
-         specs = MkList();
-         if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
-         ListAdd(specs, MkSpecifier(SHORT));
+         if(source.kind == intType)
+         {
+            FreeType(dest);
+            FreeType(source);
+            if(backupSourceExpType) FreeType(backupSourceExpType);
+            return true;
+         }
+         else
+         {
+            specs = MkList();
+            if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
+            ListAdd(specs, MkSpecifier(SHORT));
+         }
       }
-      else if(dest.kind == intType && (source.kind == enumType || source.kind == shortType || source.kind == charType || source.kind == intType))
+      else if(dest.kind == intType && (source.kind == enumType || source.kind == shortType || source.kind == _BoolType || source.kind == charType || source.kind == intType))
       {
          specs = MkList();
          if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
          ListAdd(specs, MkSpecifier(INT));
       }
-      else if(dest.kind == int64Type && (source.kind == enumType || source.kind == shortType || source.kind == charType || source.kind == intType || source.kind == int64Type))
+      else if(dest.kind == int64Type && (source.kind == enumType || source.kind == shortType || source.kind == _BoolType || source.kind == charType || source.kind == intType || source.kind == int64Type))
       {
          specs = MkList();
          if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
          ListAdd(specs, MkSpecifier(INT64));
       }
-      else if(dest.kind == enumType && 
-         (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType))
+      else if(dest.kind == enumType &&
+         (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == _BoolType || source.kind == charType))
       {
          specs = MkListOne(MkEnum(MkIdentifier(dest.enumName), null));
       }
@@ -3858,7 +4002,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
          return false;
       }
 
-      if(!flag)
+      if(!flag && !sourceExp.opDestType)
       {
          Expression newExp { };
          *newExp = *sourceExp;
@@ -3881,7 +4025,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
          }
          else
             sourceExp.cast.exp = newExp;
-         
+
          FreeType(sourceExp.expType);
          sourceExp.expType = null;
          ProcessExpressionType(sourceExp);
@@ -3897,6 +4041,12 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
    }
    else
    {
+      if(computedExp != nbExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = nbExp;
+      }
+
       while((sourceExp.type == bracketsExp || sourceExp.type == extensionExpressionExp) && sourceExp.list) sourceExp = sourceExp.list->last;
       if(sourceExp.type == identifierExp)
       {
@@ -3911,7 +4061,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                {
                   for( ; _class && _class.type == ClassType::enumClass; _class = _class.base)
                   {
-                     NamedLink value;
+                     NamedLink64 value;
                      EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
                      for(value = e.values.first; value; value = value.next)
                      {
@@ -3920,22 +4070,22 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                      }
                      if(value)
                      {
-                        FreeExpContents(sourceExp);
                         FreeType(sourceExp.expType);
 
                         sourceExp.isConstant = true;
                         sourceExp.expType = MkClassType(_class.fullName);
-                        //if(inCompiler)
+                        if(inCompiler || inPreCompiler || inDebugger)
                         {
-                           char constant[256];
+                           FreeExpContents(sourceExp);
+
                            sourceExp.type = constantExp;
-                           if(/*_class && */_class.dataTypeString && !strcmp(_class.dataTypeString, "int")) // _class cannot be null here!
-                              sprintf(constant, "%d", (int) value.data);
+                           if(_class.dataTypeString && (!strcmp(_class.dataTypeString, "int") || !strcmp(_class.dataTypeString, "int64") || !strcmp(_class.dataTypeString, "short") || !strcmp(_class.dataTypeString, "char"))) // _class cannot be null here!
+                              sourceExp.constant = PrintInt64(value.data);
                            else
-                              sprintf(constant, "0x%X", (int) value.data);
-                           sourceExp.constant = CopyString(constant);
+                              sourceExp.constant = PrintUInt64(value.data);
                            //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
                         }
+                        FreeType(dest);
                         return true;
                      }
                   }
@@ -3945,8 +4095,12 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
 
          // Loop through all enum classes
          if(dest.classObjectType != typedObject && dest.kind == classType /*!= ellipsisType */&& MatchWithEnums_Module(privateModule, sourceExp, dest, id.string, conversions))
+         {
+            FreeType(dest);
             return true;
+         }
       }
+      FreeType(dest);
    }
    return false;
 }
@@ -3966,18 +4120,29 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
    {                                                              \
       t value2 = op2.m;                                           \
       exp.type = constantExp;                                    \
-      exp.string = p(op1.m o value2);                     \
+      exp.string = p((t)(op1.m o value2));                     \
+      if(!exp.expType) \
+         { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
+      return true;                                                \
+   }
+
+#define BINARY_DIVIDEINT(o, name, m, t, p) \
+   static bool name(Expression exp, Operand op1, Operand op2)   \
+   {                                                              \
+      t value2 = op2.m;                                           \
+      exp.type = constantExp;                                    \
+      exp.string = p(value2 ? ((t)(op1.m o value2)) : 0);             \
       if(!exp.expType) \
          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
       return true;                                                \
    }
 
-#define BINARY_DIVIDE(o, name, m, t, p) \
+#define BINARY_DIVIDEREAL(o, name, m, t, p) \
    static bool name(Expression exp, Operand op1, Operand op2)   \
    {                                                              \
       t value2 = op2.m;                                           \
       exp.type = constantExp;                                    \
-      exp.string = p(value2 ? (op1.m o value2) : 0);             \
+      exp.string = p((t)(op1.m o value2));             \
       if(!exp.expType) \
          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
       return true;                                                \
@@ -3996,6 +4161,8 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
 #define OPERATOR_ALL(macro, o, name) \
    macro(o, Int##name, i, int, PrintInt) \
    macro(o, UInt##name, ui, unsigned int, PrintUInt) \
+   macro(o, Int64##name, i64, int64, PrintInt64) \
+   macro(o, UInt64##name, ui64, uint64, PrintUInt64) \
    macro(o, Short##name, s, short, PrintShort) \
    macro(o, UShort##name, us, unsigned short, PrintUShort) \
    macro(o, Char##name, c, char, PrintChar) \
@@ -4006,18 +4173,24 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
 #define OPERATOR_INTTYPES(macro, o, name) \
    macro(o, Int##name, i, int, PrintInt) \
    macro(o, UInt##name, ui, unsigned int, PrintUInt) \
+   macro(o, Int64##name, i64, int64, PrintInt64) \
+   macro(o, UInt64##name, ui64, uint64, PrintUInt64) \
    macro(o, Short##name, s, short, PrintShort) \
    macro(o, UShort##name, us, unsigned short, PrintUShort) \
    macro(o, Char##name, c, char, PrintChar) \
    macro(o, UChar##name, uc, unsigned char, PrintUChar)
 
+#define OPERATOR_REALTYPES(macro, o, name) \
+   macro(o, Float##name, f, float, PrintFloat) \
+   macro(o, Double##name, d, double, PrintDouble)
 
 // binary arithmetic
 OPERATOR_ALL(BINARY, +, Add)
 OPERATOR_ALL(BINARY, -, Sub)
 OPERATOR_ALL(BINARY, *, Mul)
-OPERATOR_ALL(BINARY_DIVIDE, /, Div)
-OPERATOR_INTTYPES(BINARY_DIVIDE, %, Mod)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, /, Div)
+OPERATOR_REALTYPES(BINARY_DIVIDEREAL, /, Div)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, %, Mod)
 
 // unary arithmetic
 OPERATOR_ALL(UNARY, -, Neg)
@@ -4031,8 +4204,9 @@ OPERATOR_ALL(BINARY, =, Asign)
 OPERATOR_ALL(BINARY, +=, AddAsign)
 OPERATOR_ALL(BINARY, -=, SubAsign)
 OPERATOR_ALL(BINARY, *=, MulAsign)
-OPERATOR_ALL(BINARY_DIVIDE, /=, DivAsign)
-OPERATOR_INTTYPES(BINARY_DIVIDE, %=, ModAsign)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, /=, DivAsign)
+OPERATOR_REALTYPES(BINARY_DIVIDEREAL, /=, DivAsign)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, %=, ModAsign)
 
 // binary bitwise
 OPERATOR_INTTYPES(BINARY, &, BitAnd)
@@ -4069,7 +4243,7 @@ OPERATOR_ALL(BINARY, >=, GrtEqu)
 OPERATOR_ALL(BINARY, <=, SmaEqu)
 
 // tertiary condition operator
-OPERATOR_ALL(TERTIARY, ?, Cond)
+OPERATOR_INTTYPES(TERTIARY, ?, Cond)
 
 //Add, Sub, Mul, Div, Mod,     , Neg,     Inc, Dec,    Asign, AddAsign, SubAsign, MulAsign, DivAsign, ModAsign,     BitAnd, BitOr, BitXor, LShift, RShift, BitNot,     AndAsign, OrAsign, XorAsign, LShiftAsign, RShiftAsign,     Not,     Equ, Nqu,     And, Or,     Grt, Sma, GrtEqu, SmaEqu
 #define OPERATOR_TABLE_ALL(name, type) \
@@ -4102,6 +4276,8 @@ OPERATOR_ALL(TERTIARY, ?, Cond)
 
 OPERATOR_TABLE_ALL(int, Int)
 OPERATOR_TABLE_ALL(uint, UInt)
+OPERATOR_TABLE_ALL(int64, Int64)
+OPERATOR_TABLE_ALL(uint64, UInt64)
 OPERATOR_TABLE_ALL(short, Short)
 OPERATOR_TABLE_ALL(ushort, UShort)
 OPERATOR_TABLE_INTTYPES(float, Float)
@@ -4139,15 +4315,15 @@ public void ReadString(char * output,  char * string)
             case 'v': output[d] = '\v'; break;
             case '\\': output[d] = '\\'; break;
             case '\"': output[d] = '\"'; break;
-            default: output[d++] = '\\'; output[d] = ch;
-            //default: output[d] = ch;
+            case '\'': output[d] = '\''; break;
+            default: output[d] = ch;
          }
          d++;
          escaped = false;
       }
-      else 
+      else
       {
-         if(ch == '\"') 
+         if(ch == '\"')
             quoted ^= true;
          else if(quoted)
          {
@@ -4161,30 +4337,90 @@ public void ReadString(char * output,  char * string)
    output[d] = '\0';
 }
 
+// String Unescape Copy
+
+// TOFIX: THIS DOESN'T HANDLE NUMERIC ESCAPE CODES (OCTAL/HEXADECIMAL...)?
+// This is the same as ReadString above (which also misses numeric escape codes) except it doesn't handle external quotes
+public int UnescapeString(char * d, char * s, int len)
+{
+   int j = 0, k = 0;
+   char ch;
+   while(j < len && (ch = s[j]))
+   {
+      switch(ch)
+      {
+         case '\\':
+            switch((ch = s[++j]))
+            {
+               case 'n': d[k] = '\n'; break;
+               case 't': d[k] = '\t'; break;
+               case 'a': d[k] = '\a'; break;
+               case 'b': d[k] = '\b'; break;
+               case 'f': d[k] = '\f'; break;
+               case 'r': d[k] = '\r'; break;
+               case 'v': d[k] = '\v'; break;
+               case '\\': d[k] = '\\'; break;
+               case '\"': d[k] = '\"'; break;
+               case '\'': d[k] = '\''; break;
+               default: d[k] = '\\'; d[k] = ch;
+            }
+            break;
+         default:
+            d[k] = ch;
+      }
+      j++, k++;
+   }
+   d[k] = '\0';
+   return k;
+}
+
+public char * OffsetEscapedString(char * s, int len, int offset)
+{
+   char ch;
+   int j = 0, k = 0;
+   while(j < len && k < offset && (ch = s[j]))
+   {
+      if(ch == '\\') ++j;
+      j++, k++;
+   }
+   return (k == offset) ? s + j : null;
+}
+
 public Operand GetOperand(Expression exp)
 {
    Operand op { };
    Type type = exp.expType;
    if(type)
    {
-      while(type.kind == classType && 
+      while(type.kind == classType && type._class &&
          type._class.registered && (type._class.registered.type == bitClass || type._class.registered.type == unitClass || type._class.registered.type == enumClass))
       {
          if(!type._class.registered.dataType)
             type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
          type = type._class.registered.dataType;
-         
+
+      }
+      if(exp.type == stringExp && op.kind == pointerType)
+      {
+         op.ui64 = (uint64)(uintptr)exp.string;
+         op.kind = pointerType;
+         op.ops = uint64Ops;
       }
-      op.kind = type.kind;
-      op.type = exp.expType;
-      if(exp.isConstant && exp.type == constantExp)
+      else if(exp.isConstant && exp.type == constantExp)
       {
+         op.kind = type.kind;
+         op.type = type;
+
          switch(op.kind)
          {
+            case _BoolType:
             case charType:
             {
                if(exp.constant[0] == '\'')
+               {
                   op.c = exp.constant[1];
+                  op.ops = charOps;
+               }
                else if(type.isSigned)
                {
                   op.c = (char)strtol(exp.constant, null, 0);
@@ -4198,7 +4434,12 @@ public Operand GetOperand(Expression exp)
                break;
             }
             case shortType:
-               if(type.isSigned)
+               if(exp.constant[0] == '\'')
+               {
+                  op.s = exp.constant[1];
+                  op.ops = shortOps;
+               }
+               else if(type.isSigned)
                {
                   op.s = (short)strtol(exp.constant, null, 0);
                   op.ops = shortOps;
@@ -4211,7 +4452,12 @@ public Operand GetOperand(Expression exp)
                break;
             case intType:
             case longType:
-               if(type.isSigned)
+               if(exp.constant[0] == '\'')
+               {
+                  op.i = exp.constant[1];
+                  op.ops = intOps;
+               }
+               else if(type.isSigned)
                {
                   op.i = (int)strtol(exp.constant, null, 0);
                   op.ops = intOps;
@@ -4227,47 +4473,57 @@ public Operand GetOperand(Expression exp)
                if(type.isSigned)
                {
                   op.i64 = (int64)_strtoi64(exp.constant, null, 0);
-                  op.ops = intOps;
+                  op.ops = int64Ops;
                }
                else
                {
                   op.ui64 = (uint64)_strtoui64(exp.constant, null, 0);
-                  op.ops = uintOps;
+                  op.ops = uint64Ops;
                }
-               op.kind = intType;
+               op.kind = int64Type;
                break;
             case intPtrType:
                if(type.isSigned)
                {
                   op.i64 = (int64)_strtoi64(exp.constant, null, 0);
-                  op.ops = intOps;
+                  op.ops = int64Ops;
                }
                else
                {
                   op.ui64 = (uint64)_strtoui64(exp.constant, null, 0);
-                  op.ops = uintOps;
+                  op.ops = uint64Ops;
                }
-               op.kind = intType;
+               op.kind = int64Type;
                break;
             case intSizeType:
                if(type.isSigned)
                {
                   op.i64 = (int64)_strtoi64(exp.constant, null, 0);
-                  op.ops = intOps;
+                  op.ops = int64Ops;
                }
                else
                {
                   op.ui64 = (uint64)_strtoui64(exp.constant, null, 0);
-                  op.ops = uintOps;
+                  op.ops = uint64Ops;
                }
-               op.kind = intType;
+               op.kind = int64Type;
                break;
             case floatType:
-               op.f = (float)strtod(exp.constant, null);
+               if(!strcmp(exp.constant, "inf")) op.f = float::inf();
+               else if(!strcmp(exp.constant, "-inf")) op.f = -float::inf();
+               else if(!strcmp(exp.constant, "nan")) op.f = float::nan();
+               else if(!strcmp(exp.constant, "-nan")) op.f = -float::nan();
+               else
+                  op.f = (float)strtod(exp.constant, null);
                op.ops = floatOps;
                break;
             case doubleType:
-               op.d = (double)strtod(exp.constant, null);
+               if(!strcmp(exp.constant, "inf")) op.d = double::inf();
+               else if(!strcmp(exp.constant, "-inf")) op.d = -double::inf();
+               else if(!strcmp(exp.constant, "nan")) op.d = double::nan();
+               else if(!strcmp(exp.constant, "-nan")) op.d = -double::nan();
+               else
+                  op.d = (double)strtod(exp.constant, null);
                op.ops = doubleOps;
                break;
             //case classType:    For when we have operator overloading...
@@ -4278,8 +4534,8 @@ public Operand GetOperand(Expression exp)
             case classType:
                op.ui64 = _strtoui64(exp.constant, null, 0);
                op.kind = pointerType;
-               op.ops = uintOps;
-               // op.ptrSize = 
+               op.ops = uint64Ops;
+               // op.ptrSize =
                break;
          }
       }
@@ -4287,7 +4543,40 @@ public Operand GetOperand(Expression exp)
    return op;
 }
 
-static void UnusedFunction()
+static int64 GetEnumValue(Class _class, void * ptr)
+{
+   int64 v = 0;
+   switch(_class.typeSize)
+   {
+      case 8:
+         if(!strcmp(_class.dataTypeString, "uint64"))
+            v = (int64)*(uint64 *)ptr;
+         else
+            v = (int64)*(int64 *)ptr;
+         break;
+      case 4:
+         if(!strcmp(_class.dataTypeString, "uint"))
+            v = (int64)*(uint *)ptr;
+         else
+            v = (int64)*(int *)ptr;
+         break;
+      case 2:
+         if(!strcmp(_class.dataTypeString, "uint16"))
+            v = (int64)*(uint16 *)ptr;
+         else
+            v = (int64)*(short *)ptr;
+         break;
+      case 1:
+         if(!strcmp(_class.dataTypeString, "byte"))
+            v = (int64)*(byte *)ptr;
+         else
+            v = (int64)*(char *)ptr;
+         break;
+   }
+   return v;
+}
+
+static __attribute__((unused)) void UnusedFunction()
 {
    int a;
    a.OnGetString(0,0,0);
@@ -4325,10 +4614,10 @@ static void PopulateInstanceProcessMember(Instantiation inst, OldList * memberLi
                if(enumClass)
                {
                   EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
-                  NamedLink item;
+                  NamedLink64 item;
                   for(item = e.values.first; item; item = item.next)
                   {
-                     if((int)item.data == *(int *)ptr)
+                     if(item.data == GetEnumValue(_class, ptr))
                      {
                         result = item.name;
                         break;
@@ -4398,7 +4687,7 @@ static void PopulateInstanceProcessMember(Instantiation inst, OldList * memberLi
                {
                   FreeExpContents(exp);
                   // TODO: This should probably use proper type
-                  exp.constant = PrintInt64((int64)*(intptr*)ptr);
+                  exp.constant = PrintInt64((int64)*(intsize*)ptr);
                   exp.type = constantExp;
                   break;
                }
@@ -4454,10 +4743,10 @@ void PopulateInstance(Instantiation inst)
                   if(enumClass)
                   {
                      EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
-                     NamedLink item;
+                     NamedLink64 item;
                      for(item = e.values.first; item; item = item.next)
                      {
-                        if((int)item.data == *(int *)ptr)
+                        if(item.data == GetEnumValue(_class, ptr))
                         {
                            result = item.name;
                            break;
@@ -4470,7 +4759,7 @@ void PopulateInstance(Instantiation inst)
                      exp.type = identifierExp;
                      exp.destType = MkClassType(_class.fullName);
                      ProcessExpressionType(exp);
-                  }                     
+                  }
                }
                if(_class.type == enumClass || _class.type == unitClass || _class.type == bitClass)
                {
@@ -4537,13 +4826,17 @@ void ComputeInstantiation(Expression exp)
 
    if(_class && (_class.type == structClass || _class.type == normalClass || _class.type == noHeadClass ))
    {
-      // Don't recompute the instantiation... 
+      // Don't recompute the instantiation...
       // Non Simple classes will have become constants by now
-      if(inst.data) 
+      if(inst.data)
          return;
 
       if(_class.type == normalClass || _class.type == noHeadClass)
+      {
          inst.data = (byte *)eInstance_New(_class);
+         if(_class.type == normalClass)
+            ((Instance)inst.data)._refCount++;
+      }
       else
          inst.data = new0 byte[_class.structSize];
    }
@@ -4566,7 +4859,6 @@ void ComputeInstantiation(Expression exp)
 
                      Property prop = null;
                      DataMember dataMember = null;
-                     Method method = null;
                      uint dataMemberOffset;
 
                      if(!ident)
@@ -4579,7 +4871,7 @@ void ComputeInstantiation(Expression exp)
                            else
                            {
                               dataMember = curMember;
-                              
+
                               // CHANGED THIS HERE
                               eClass_FindDataMemberAndOffset(_class, dataMember.name, &dataMemberOffset, privateModule, null, null);
 
@@ -4638,7 +4930,7 @@ void ComputeInstantiation(Expression exp)
                         {
                            if(!dataMember.dataType)
                               dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
-                           
+
                            type = dataMember.dataType;
                         }
 
@@ -4657,7 +4949,7 @@ void ComputeInstantiation(Expression exp)
                                     type = prop.dataType;
                                  else
                                  {
-                                    dataMember = eClass_FindDataMemberAndOffset(type._class.registered, 
+                                    dataMember = eClass_FindDataMemberAndOffset(type._class.registered,
                                        ident.string, &dataMemberOffset, privateModule, null, null);
                                     if(dataMember)
                                        type = dataMember.dataType;
@@ -4689,8 +4981,7 @@ void ComputeInstantiation(Expression exp)
                            if(type.kind == classType)
                            {
                               Class _class = type._class.registered;
-                              if(_class.type == bitClass || _class.type == unitClass ||
-                                 _class.type == enumClass)
+                              if(_class && (_class.type == bitClass || _class.type == unitClass || _class.type == enumClass))
                               {
                                  if(!_class.dataType)
                                     _class.dataType = ProcessTypeString(_class.dataTypeString, false);
@@ -4701,7 +4992,7 @@ void ComputeInstantiation(Expression exp)
                            if(dataMember)
                            {
                               void * ptr = inst.data + dataMemberOffset;
-                              
+
                               if(value.type == constantExp)
                               {
                                  switch(type.kind)
@@ -4752,7 +5043,7 @@ void ComputeInstantiation(Expression exp)
                                  }
                               }
                            }
-                           else if(prop)
+                           else if(prop && prop.Set != (void *)(intptr)1)
                            {
                               if(value.type == instanceExp && value.instance.data)
                               {
@@ -4876,69 +5167,29 @@ void ComputeInstantiation(Expression exp)
                            {
                               BitMember bitMember = (BitMember) dataMember;
                               Type type;
-                              int part = 0;
-                              GetInt(value, &part);
+                              uint64 part = 0;
                               bits = (bits & ~bitMember.mask);
                               if(!bitMember.dataType)
                                  bitMember.dataType = ProcessTypeString(bitMember.dataTypeString, false);
-
                               type = bitMember.dataType;
-
                               if(type.kind == classType && type._class && type._class.registered)
                               {
                                  if(!type._class.registered.dataType)
-                                    type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);                                    
+                                    type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
                                  type = type._class.registered.dataType;
                               }
-
                               switch(type.kind)
                               {
-                                 case charType:
-                                    if(type.isSigned)
-                                       bits |= ((char)part << bitMember.pos);
-                                    else
-                                       bits |= ((unsigned char)part << bitMember.pos);
-                                    break;
-                                 case shortType:
-                                    if(type.isSigned)
-                                       bits |= ((short)part << bitMember.pos);
-                                    else
-                                       bits |= ((unsigned short)part << bitMember.pos);
-                                    break;
+                                 case _BoolType:
+                                 case charType:       { byte v; type.isSigned ? GetChar(value, (char *)&v) : GetUChar(value, &v); part = (uint64)v; break; }
+                                 case shortType:      { uint16 v; type.isSigned ? GetShort(value, (short *)&v) : GetUShort(value, &v); part = (uint64)v; break; }
                                  case intType:
-                                 case longType:
-                                    if(type.isSigned)
-                                       bits |= ((int)part << bitMember.pos);
-                                    else
-                                       bits |= ((unsigned int)part << bitMember.pos);
-                                    break;
-                                 case int64Type:
-                                    if(type.isSigned)
-                                       bits |= ((int64)part << bitMember.pos);
-                                    else
-                                       bits |= ((uint64)part << bitMember.pos);
-                                    break;
-                                 case intPtrType:
-                                    if(type.isSigned)
-                                    {
-                                       bits |= ((intptr)part << bitMember.pos);
-                                    }
-                                    else
-                                    {
-                                       bits |= ((uintptr)part << bitMember.pos);
-                                    }
-                                    break;
-                                 case intSizeType:
-                                    if(type.isSigned)
-                                    {
-                                       bits |= ((ssize_t)(intsize)part << bitMember.pos);
-                                    }
-                                    else
-                                    {
-                                       bits |= ((size_t) (uintsize)part << bitMember.pos);
-                                    }
-                                    break;
+                                 case longType:       { uint v; type.isSigned ? GetInt(value, (int *)&v) : GetUInt(value, &v); part = (uint64)v; break; }
+                                 case int64Type:      { uint64 v; type.isSigned ? GetInt64(value, (int64 *)&v) : GetUInt64(value, &v); part = (uint64)v; break; }
+                                 case intPtrType:     { uintptr v; type.isSigned ? GetIntPtr(value, (intptr *)&v) : GetUIntPtr(value, &v); part = (uint64)v; break; }
+                                 case intSizeType:    { uintsize v; type.isSigned ? GetIntSize(value, (intsize *)&v) : GetUIntSize(value, &v); part = (uint64)v; break; }
                               }
+                              bits |= part << bitMember.pos;
                            }
                         }
                      }
@@ -4949,7 +5200,7 @@ void ComputeInstantiation(Expression exp)
                            ComputeExpression(member.initializer.exp);
                            exp.constant = member.initializer.exp.constant;
                            exp.type = constantExp;
-                           
+
                            member.initializer.exp.constant = null;
                         }
                      }
@@ -4971,6 +5222,57 @@ void ComputeInstantiation(Expression exp)
    }
 }
 
+static bool Promote(Operand op, TypeKind kind, bool isSigned)
+{
+   bool result = false;
+   switch(kind)
+   {
+      case shortType:
+         if(op.kind == charType || op.kind == enumType || op.kind == _BoolType)
+            result = isSigned ? GetOpShort(op, &op.s) : GetOpUShort(op, &op.us);
+         break;
+      case intType:
+      case longType:
+         if(op.kind == charType || op.kind == shortType || op.kind == enumType || op.kind == _BoolType)
+            result = isSigned ? GetOpInt(op, &op.i) : GetOpUInt(op, &op.ui);
+         break;
+      case int64Type:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType || op.kind == doubleType ||
+            op.kind == pointerType || op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+            result = isSigned ? GetOpInt64(op, &op.i64) : GetOpUInt64(op, &op.ui64);
+         break;
+      case floatType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType ||
+            op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+            result = GetOpFloat(op, &op.f);
+         break;
+      case doubleType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType ||
+            op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+            result = GetOpDouble(op, &op.d);
+         break;
+      case pointerType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType || op.kind == doubleType ||
+            op.kind == pointerType || op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+            result = GetOpUInt64 /*GetOpUIntPtr*/(op, &op.ui64);
+         break;
+      case enumType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType || op.kind == doubleType ||
+            op.kind == pointerType || op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+            result = isSigned ? GetOpInt(op, &op.i) : GetOpUInt(op, &op.ui);
+         break;
+      case intPtrType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == longType || op.kind == enumType || op.kind == _BoolType)
+            result = isSigned ? GetOpInt64 /*GetOpIntPtr*/(op, &op.i64) : GetOpUInt64 /*GetOpUIntPtr*/(op, &op.ui64);
+         break;
+      case intSizeType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == longType || op.kind == enumType || op.kind == _BoolType)
+            result = isSigned ? GetOpInt64 /*GetOpIntSize*/(op, &op.i64) : GetOpUInt64 /*GetOpUIntSize*/(op, &op.ui64);
+         break;
+   }
+   return result;
+}
+
 void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1, Operand op2)
 {
    if(exp.op.op == SIZEOF)
@@ -5016,6 +5318,13 @@ void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1,
       }
       else
       {
+         if(op1 && op2 && op1.type && op2.type && op1.kind != op2.kind)
+         {
+            if(Promote(op2, op1.kind, op1.type.isSigned))
+               op2.kind = op1.kind, op2.ops = op1.ops;
+            else if(Promote(op1, op2.kind, op2.type.isSigned))
+               op1.kind = op2.kind, op1.ops = op2.ops;
+         }
          switch(exp.op.op)
          {
             // binary arithmetic
@@ -5100,14 +5409,44 @@ void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1,
 
 void ComputeExpression(Expression exp)
 {
+#ifdef _DEBUG
    char expString[10240];
    expString[0] = '\0';
-#ifdef _DEBUG
    PrintExpression(exp, expString);
 #endif
 
    switch(exp.type)
    {
+      case identifierExp:
+      {
+         Identifier id = exp.identifier;
+         if(id && exp.isConstant && !inCompiler && !inPreCompiler && !inDebugger)
+         {
+            Class c = (exp.expType && exp.expType.kind == classType && exp.expType._class) ? exp.expType._class.registered : null;
+            if(c && c.type == enumClass)
+            {
+               Class enumClass = eSystem_FindClass(privateModule, "enum");
+               if(enumClass)
+               {
+                  NamedLink64 value;
+                  EnumClassData e = ACCESS_CLASSDATA(c, enumClass);
+                  for(value = e.values.first; value; value = value.next)
+                  {
+                     if(!strcmp(value.name, id.string))
+                        break;
+                  }
+                  if(value)
+                  {
+                     const String dts = c.dataTypeString;
+                     FreeExpContents(exp);
+                     exp.type = constantExp;
+                     exp.constant = (dts && (!strcmp(dts, "int") || !strcmp(dts, "int64") || !strcmp(dts, "short") || !strcmp(dts, "char"))) ? PrintInt64(value.data) : PrintUInt64(value.data);
+                  }
+               }
+            }
+         }
+         break;
+      }
       case instanceExp:
       {
          ComputeInstantiation(exp);
@@ -5125,7 +5464,46 @@ void ComputeExpression(Expression exp)
 
          // We don't care about operations with only exp2 (INC_OP, DEC_OP...)
          if(exp.op.exp2)
-            ComputeExpression(exp.op.exp2);
+         {
+            Expression e = exp.op.exp2;
+
+            while((e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp) && e.list)
+            {
+               if(e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp)
+               {
+                  if(e.type == extensionCompoundExp)
+                     e = ((Statement)e.compound.compound.statements->last).expressions->last;
+                  else
+                     e = e.list->last;
+               }
+            }
+            if(exp.op.op == TokenType::sizeOf && e && e.expType)
+            {
+               if(e.type == stringExp && e.string)
+               {
+                  char * string = e.string;
+                  int len = strlen(string);
+                  char * tmp = new char[len-2+1];
+                  len = UnescapeString(tmp, string + 1, len - 2);
+                  delete tmp;
+                  FreeExpContents(exp);
+                  exp.type = constantExp;
+                  exp.constant = PrintUInt(len + 1);
+               }
+               else
+               {
+                  Type type = e.expType;
+                  type.refCount++;
+                  FreeExpContents(exp);
+                  exp.type = constantExp;
+                  exp.constant = PrintUInt(ComputeTypeSize(type));
+                  FreeType(type);
+               }
+               break;
+            }
+            else
+               ComputeExpression(exp.op.exp2);
+         }
          if(exp.op.exp1)
          {
             ComputeExpression(exp.op.exp1);
@@ -5139,7 +5517,7 @@ void ComputeExpression(Expression exp)
                if(op2.type) op2.type.refCount++;
             }
          }
-         else 
+         else
          {
             exp1 = exp.op.exp2;
             op1 = GetOperand(exp1);
@@ -5198,7 +5576,7 @@ void ComputeExpression(Expression exp)
             case '-':
                if(exp.op.exp1)
                {
-                  if(op1.ops.Sub) 
+                  if(op1.ops.Sub)
                   {
                      FreeExpContents(exp);
                      op1.ops.Sub(exp, op1, op2);
@@ -5206,7 +5584,7 @@ void ComputeExpression(Expression exp)
                }
                else
                {
-                  if(op1.ops.Neg) 
+                  if(op1.ops.Neg)
                   {
                      FreeExpContents(exp);
                      op1.ops.Neg(exp, op1);
@@ -5229,7 +5607,7 @@ void ComputeExpression(Expression exp)
                break;
             // Binary only operators
             case '/':
-               if(op1.ops.Div) 
+               if(op1.ops.Div)
                {
                   FreeExpContents(exp);
                   op1.ops.Div(exp, op1, op2);
@@ -5307,14 +5685,14 @@ void ComputeExpression(Expression exp)
                }
                break;
             case '|':
-               if(op1.ops.BitOr) 
+               if(op1.ops.BitOr)
                {
                   FreeExpContents(exp);
                   op1.ops.BitOr(exp, op1, op2);
                }
                break;
             case '^':
-               if(op1.ops.BitXor) 
+               if(op1.ops.BitXor)
                {
                   FreeExpContents(exp);
                   op1.ops.BitXor(exp, op1, op2);
@@ -5345,11 +5723,23 @@ void ComputeExpression(Expression exp)
             if(!n)
             {
                OldList * list = exp.list;
+               Expression prev = exp.prev;
+               Expression next = exp.next;
+
+               // For operations which set the exp type on brackets exp after the inner exp was processed...
+               if(exp.expType && exp.expType.kind == classType && (!e.expType || e.expType.kind != classType))
+               {
+                  FreeType(e.expType);
+                  e.expType = exp.expType;
+                  e.expType.refCount++;
+               }
                ComputeExpression(e);
                //FreeExpContents(exp);
                FreeType(exp.expType);
                FreeType(exp.destType);
                *exp = *e;
+               exp.prev = prev;
+               exp.next = next;
                delete e;
                delete list;
             }
@@ -5425,7 +5815,7 @@ void ComputeExpression(Expression exp)
                _class = classSym ? classSym.registered : null;
                prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
             }
-      
+
             if(prop)
             {
                if(prop.compiled)
@@ -5460,7 +5850,7 @@ void ComputeExpression(Expression exp)
                            double value;
                            double (*Get)(double);
                            GetDouble(exp.member.exp, &value);
-                     
+
                            if(convertTo)
                               Get = (void *)prop.Set;
                            else
@@ -5497,7 +5887,7 @@ void ComputeExpression(Expression exp)
                                     void (*Set)(void *, void *) = (void *)prop.Set;
                                     exp.instance = Instantiation { };
                                     exp.instance.data = new0 byte[_class.structSize];
-                                    exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                    exp.instance._class = MkSpecifierName(_class.fullName);
                                     exp.instance.loc = exp.loc;
                                     exp.type = instanceExp;
                                     Set(exp.instance.data, value.instance.data);
@@ -5512,10 +5902,10 @@ void ComputeExpression(Expression exp)
 
                                  exp.instance = Instantiation { };
                                  exp.instance.data = new0 byte[_class.structSize];
-                                 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                 exp.instance._class = MkSpecifierName(_class.fullName);
                                  exp.instance.loc = exp.loc;
                                  exp.type = instanceExp;
-                              
+
                                  GetInt(value, &intValue);
 
                                  Set(exp.instance.data, intValue);
@@ -5532,7 +5922,7 @@ void ComputeExpression(Expression exp)
                                  exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
                                  exp.instance.loc = exp.loc;
                                  exp.type = instanceExp;
-                              
+
                                  GetInt64(value, &intValue);
 
                                  Set(exp.instance.data, intValue);
@@ -5547,10 +5937,10 @@ void ComputeExpression(Expression exp)
 
                                  exp.instance = Instantiation { };
                                  exp.instance.data = new0 byte[_class.structSize];
-                                 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                 exp.instance._class = MkSpecifierName(_class.fullName);
                                  exp.instance.loc = exp.loc;
                                  exp.type = instanceExp;
-                              
+
                                  GetIntPtr(value, &intValue);
 
                                  Set(exp.instance.data, intValue);
@@ -5565,7 +5955,7 @@ void ComputeExpression(Expression exp)
 
                                  exp.instance = Instantiation { };
                                  exp.instance.data = new0 byte[_class.structSize];
-                                 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                 exp.instance._class = MkSpecifierName(_class.fullName);
                                  exp.instance.loc = exp.loc;
                                  exp.type = instanceExp;
 
@@ -5575,6 +5965,23 @@ void ComputeExpression(Expression exp)
                                  PopulateInstance(exp.instance);
                                  break;
                               }
+                              case floatType:
+                              {
+                                 float floatValue;
+                                 void (*Set)(void *, float) = (void *)prop.Set;
+
+                                 exp.instance = Instantiation { };
+                                 exp.instance.data = new0 byte[_class.structSize];
+                                 exp.instance._class = MkSpecifierName(_class.fullName);
+                                 exp.instance.loc = exp.loc;
+                                 exp.type = instanceExp;
+
+                                 GetFloat(value, &floatValue);
+
+                                 Set(exp.instance.data, floatValue);
+                                 PopulateInstance(exp.instance);
+                                 break;
+                              }
                               case doubleType:
                               {
                                  double doubleValue;
@@ -5582,10 +5989,10 @@ void ComputeExpression(Expression exp)
 
                                  exp.instance = Instantiation { };
                                  exp.instance.data = new0 byte[_class.structSize];
-                                 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                 exp.instance._class = MkSpecifierName(_class.fullName);
                                  exp.instance.loc = exp.loc;
                                  exp.type = instanceExp;
-                              
+
                                  GetDouble(value, &doubleValue);
 
                                  Set(exp.instance.data, doubleValue);
@@ -5642,7 +6049,7 @@ void ComputeExpression(Expression exp)
 
                                     exp.instance = Instantiation { };
                                     exp.instance.data = new0 byte[_class.structSize];
-                                    exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                    exp.instance._class = MkSpecifierName(_class.fullName);
                                     exp.instance.loc = exp.loc;
                                     //exp.instance.fullSet = true;
                                     exp.type = instanceExp;
@@ -5662,7 +6069,7 @@ void ComputeExpression(Expression exp)
                         }
                         else if(_class.type == structClass)
                         {
-                           char * value = (exp.member.exp.type == instanceExp ) ? exp.member.exp.instance.data : null;
+                           byte * value = (exp.member.exp.type == instanceExp ) ? exp.member.exp.instance.data : null;
                            switch(type.kind)
                            {
                               case classType:
@@ -5674,7 +6081,7 @@ void ComputeExpression(Expression exp)
 
                                     exp.instance = Instantiation { };
                                     exp.instance.data = new0 byte[_class.structSize];
-                                    exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                    exp.instance._class = MkSpecifierName(_class.fullName);
                                     exp.instance.loc = exp.loc;
                                     //exp.instance.fullSet = true;
                                     exp.type = instanceExp;
@@ -5732,7 +6139,7 @@ void ComputeExpression(Expression exp)
          Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
          FreeExpContents(exp);
          exp.constant = PrintUInt(ComputeTypeSize(type));
-         exp.type = constantExp;         
+         exp.type = constantExp;
          FreeType(type);
          break;
       }
@@ -5752,9 +6159,8 @@ void ComputeExpression(Expression exp)
                char className[1024];
                strcpy(className, "__ecereClass_");
                FullClassNameCat(className, classSym.string, true);
-               MangleClassName(className);
 
-               DeclareClass(classSym, className);
+               DeclareClass(curExternal, classSym, className);
 
                FreeExpContents(exp);
                exp.type = pointerExp;
@@ -5791,133 +6197,162 @@ void ComputeExpression(Expression exp)
                   type = _class.dataType;
                }
             }
-            
+
             switch(type.kind)
             {
+               case _BoolType:
                case charType:
                   if(type.isSigned)
                   {
-                     char value;
-                     GetChar(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintChar(value);
-                     exp.type = constantExp;
+                     char value = 0;
+                     if(GetChar(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintChar(value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     unsigned char value;
-                     GetUChar(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUChar(value);
-                     exp.type = constantExp;
+                     unsigned char value = 0;
+                     if(GetUChar(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUChar(value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case shortType:
                   if(type.isSigned)
                   {
-                     short value;
-                     GetShort(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintShort(value);
-                     exp.type = constantExp;
+                     short value = 0;
+                     if(GetShort(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintShort(value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     unsigned short value;
-                     GetUShort(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUShort(value);
-                     exp.type = constantExp;
+                     unsigned short value = 0;
+                     if(GetUShort(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUShort(value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case intType:
                   if(type.isSigned)
                   {
-                     int value;
-                     GetInt(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintInt(value);
-                     exp.type = constantExp;
+                     int value = 0;
+                     if(GetInt(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintInt(value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     unsigned int value;
-                     GetUInt(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUInt(value);
-                     exp.type = constantExp;
+                     unsigned int value = 0;
+                     if(GetUInt(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUInt(value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case int64Type:
                   if(type.isSigned)
                   {
-                     int64 value;
-                     GetInt64(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintInt64(value);
-                     exp.type = constantExp;
+                     int64 value = 0;
+                     if(GetInt64(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintInt64(value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     uint64 value;
-                     GetUInt64(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUInt64(value);
-                     exp.type = constantExp;
+                     uint64 value = 0;
+                     if(GetUInt64(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUInt64(value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case intPtrType:
                   if(type.isSigned)
                   {
-                     intptr value;
-                     GetIntPtr(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintInt64((int64)value);
-                     exp.type = constantExp;
+                     intptr value = 0;
+                     if(GetIntPtr(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintInt64((int64)value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     uintptr value;
-                     GetUIntPtr(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUInt64((uint64)value);
-                     exp.type = constantExp;
+                     uintptr value = 0;
+                     if(GetUIntPtr(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUInt64((uint64)value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case intSizeType:
                   if(type.isSigned)
                   {
-                     intsize value;
-                     GetIntSize(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintInt64((int64)value);
-                     exp.type = constantExp;
+                     intsize value = 0;
+                     if(GetIntSize(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintInt64((int64)value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     uintsize value;
-                     GetUIntSize(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUInt64((uint64)value);
-                     exp.type = constantExp;
+                     uintsize value = 0;
+                     if(GetUIntSize(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUInt64((uint64)value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case floatType:
                {
-                  float value;
-                  GetFloat(e, &value);
-                  FreeExpContents(exp);
-                  exp.constant = PrintFloat(value);
-                  exp.type = constantExp;
+                  float value = 0;
+                  if(GetFloat(e, &value))
+                  {
+                     FreeExpContents(exp);
+                     exp.constant = PrintFloat(value);
+                     exp.type = constantExp;
+                  }
                   break;
                }
                case doubleType:
-               {  
-                  double value;
-                  GetDouble(e, &value);
-                  FreeExpContents(exp);
-                  exp.constant = PrintDouble(value);
-                  exp.type = constantExp;
+               {
+                  double value = 0;
+                  if(GetDouble(e, &value))
+                  {
+                     FreeExpContents(exp);
+                     exp.constant = PrintDouble(value);
+                     exp.type = constantExp;
+                  }
                   break;
                }
             }
@@ -5950,11 +6385,11 @@ void ComputeExpression(Expression exp)
          if(op2.type) FreeType(op2.type);
          if(op3.type) FreeType(op3.type);
          break;
-      }  
+      }
    }
 }
 
-static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
+static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla, bool warnConst)
 {
    bool result = true;
    if(destType)
@@ -5965,7 +6400,7 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
       if(destType.kind == voidType)
          return false;
 
-      if(!MatchTypeExpression(exp, destType, &converts, skipUnitBla))
+      if(!MatchTypeExpression(exp, destType, &converts, skipUnitBla, warnConst))
          result = false;
       if(converts.count)
       {
@@ -5980,6 +6415,8 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
 
                // TODO: Check this...
                *newExp = *exp;
+               newExp.prev = null;
+               newExp.next = null;
                newExp.destType = null;
 
                if(convert.isGet)
@@ -6002,7 +6439,7 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
                }
                else
                {
-               
+
                   /*if(exp.isConstant)
                   {
                      // Color { ColorRGB = [exp] };
@@ -6054,13 +6491,15 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
                if(convert.isGet)
                {
                   exp.expType = convert.resultType ? convert.resultType : convert.convert.dataType;
-                  exp.needCast = true;
+                  if(exp.destType.casted)
+                     exp.needCast = true;
                   if(exp.expType) exp.expType.refCount++;
                }
                else
                {
                   exp.expType = convert.resultType ? convert.resultType : MkClassType(convert.convert._class.fullName);
-                  exp.needCast = true;
+                  if(exp.destType.casted)
+                     exp.needCast = true;
                   if(convert.resultType)
                      convert.resultType.refCount++;
                }
@@ -6074,13 +6513,13 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
 
       if(!result && exp.expType && converts.count)      // TO TEST: Added converts.count here to avoid a double warning with function type
       {
-         result = MatchTypes(exp.expType, exp.destType, null, null, null, true, true, false, false);
+         result = MatchTypes(exp.expType, exp.destType, null, null, null, true, true, false, false, warnConst);
       }
       if(!result && exp.expType && exp.destType)
       {
-         if((exp.destType.kind == classType && exp.expType.kind == pointerType && 
+         if((exp.destType.kind == classType && exp.expType.kind == pointerType &&
              exp.expType.type.kind == classType && exp.expType.type._class == exp.destType._class && exp.destType._class.registered && exp.destType._class.registered.type == structClass) ||
-            (exp.expType.kind == classType && exp.destType.kind == pointerType && 
+            (exp.expType.kind == classType && exp.destType.kind == pointerType &&
             exp.destType.type.kind == classType && exp.destType.type._class == exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass))
             result = true;
       }
@@ -6091,18 +6530,35 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
 
 void CheckTemplateTypes(Expression exp)
 {
-   if(exp.destType && exp.destType.passAsTemplate && exp.expType && exp.expType.kind != templateType && !exp.expType.passAsTemplate)
+   /*
+   bool et = exp.expType ? exp.expType.passAsTemplate : false;
+   bool dt = exp.destType ? exp.destType.passAsTemplate : false;
+   */
+   Expression nbExp = GetNonBracketsExp(exp);
+   if(exp.destType && exp.destType.passAsTemplate && exp.expType && exp.expType.kind != templateType && !exp.expType.passAsTemplate &&
+      (nbExp == exp || nbExp.type != castExp))
    {
       Expression newExp { };
-      Statement compound;
       Context context;
+      TypeKind kind = exp.expType.kind;
       *newExp = *exp;
       if(exp.destType) exp.destType.refCount++;
       if(exp.expType)  exp.expType.refCount++;
       newExp.prev = null;
       newExp.next = null;
 
-      switch(exp.expType.kind)
+      if(exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered)
+      {
+         Class c = exp.expType._class.registered;
+         if(c.type == bitClass || c.type == enumClass || c.type == unitClass)
+         {
+            if(!c.dataType)
+               c.dataType = ProcessTypeString(c.dataTypeString, false);
+            kind = c.dataType.kind;
+         }
+      }
+
+      switch(kind)
       {
          case doubleType:
             if(exp.destType.classObjectType)
@@ -6120,7 +6576,7 @@ void CheckTemplateTypes(Expression exp)
                OldList * unionDefs = MkList();
                OldList * statements = MkList();
                context = PushContext();
-               ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(DOUBLE)), MkListOne(MkDeclaratorIdentifier(MkIdentifier("d"))), null))); 
+               ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(DOUBLE)), MkListOne(MkDeclaratorIdentifier(MkIdentifier("d"))), null)));
                ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifierName("uint64")), MkListOne(MkDeclaratorIdentifier(MkIdentifier("i"))), null)));
                specs = MkListOne(MkStructOrUnion(unionSpecifier, null, unionDefs ));
                exp.type = extensionCompoundExp;
@@ -6134,22 +6590,37 @@ void CheckTemplateTypes(Expression exp)
          default:
             exp.type = castExp;
             exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
-            exp.cast.exp = MkExpBrackets(MkListOne(newExp));
+            if((exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass) || exp.expType.isPointerType)
+               exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), MkExpBrackets(MkListOne(newExp)));
+            else
+               exp.cast.exp = MkExpBrackets(MkListOne(newExp));
+            exp.needCast = true;
             break;
       }
    }
    else if(exp.expType && exp.expType.passAsTemplate && exp.destType && exp.usage.usageGet && exp.destType.kind != templateType && !exp.destType.passAsTemplate)
    {
       Expression newExp { };
-      Statement compound;
       Context context;
+      TypeKind kind = exp.expType.kind;
       *newExp = *exp;
       if(exp.destType) exp.destType.refCount++;
       if(exp.expType)  exp.expType.refCount++;
       newExp.prev = null;
       newExp.next = null;
 
-      switch(exp.expType.kind)
+      if(exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered)
+      {
+         Class c = exp.expType._class.registered;
+         if(c.type == bitClass || c.type == enumClass || c.type == unitClass)
+         {
+            if(!c.dataType)
+               c.dataType = ProcessTypeString(c.dataTypeString, false);
+            kind = c.dataType.kind;
+         }
+      }
+
+      switch(kind)
       {
          case doubleType:
             if(exp.destType.classObjectType)
@@ -6167,7 +6638,7 @@ void CheckTemplateTypes(Expression exp)
                OldList * unionDefs = MkList();
                OldList * statements = MkList();
                context = PushContext();
-               ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(DOUBLE)), MkListOne(MkDeclaratorIdentifier(MkIdentifier("d"))), null))); 
+               ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(DOUBLE)), MkListOne(MkDeclaratorIdentifier(MkIdentifier("d"))), null)));
                ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifierName("uint64")), MkListOne(MkDeclaratorIdentifier(MkIdentifier("i"))), null)));
                specs = MkListOne(MkStructOrUnion(unionSpecifier, null, unionDefs ));
                exp.type = extensionCompoundExp;
@@ -6183,6 +6654,8 @@ void CheckTemplateTypes(Expression exp)
             if(exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass)
             {
                exp.type = bracketsExp;
+
+               newExp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), newExp);
                exp.list = MkListOne(MkExpOp(null, '*', MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)),
                   MkDeclaratorPointer(MkPointer(null, null), null)), newExp)));
                ProcessExpressionType(exp.list->first);
@@ -6191,8 +6664,18 @@ void CheckTemplateTypes(Expression exp)
             else
             {
                exp.type = bracketsExp;
+               if(exp.expType.isPointerType)
+               {
+                  exp.needTemplateCast = 2;
+                  newExp.needCast = true;
+                  newExp.needTemplateCast = 2;
+                  newExp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), newExp);
+               }
+
                exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)), null), newExp));
+               exp.needTemplateCast = 2;
                newExp.needCast = true;
+               newExp.needTemplateCast = 2;
                ProcessExpressionType(exp.list->first);
                break;
             }
@@ -6210,15 +6693,16 @@ void CheckTemplateTypes(Expression exp)
                   break;
                }
             }
-            if(newExp.type == memberExp && newExp.member.memberType == dataMember)
+            /*if(newExp.type == memberExp && newExp.member.memberType == dataMember)
             {
+               // When was this required?    Removed to address using templated values to pass to printf()
                exp.type = opExp;
                exp.op.op = '*';
                exp.op.exp1 = null;
                exp.op.exp2 = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)),
                   MkExpBrackets(MkListOne(MkExpOp(null, '&', newExp))));
             }
-            else
+            else*/
             {
                char typeString[1024];
                Declarator decl;
@@ -6226,12 +6710,14 @@ void CheckTemplateTypes(Expression exp)
                typeString[0] = '\0';
                PrintType(exp.expType, typeString, false, false);
                decl = SpecDeclFromString(typeString, specs, null);
-               
+
                exp.type = castExp;
                //exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
                exp.cast.typeName = MkTypeName(specs, decl);
                exp.cast.exp = MkExpBrackets(MkListOne(newExp));
                exp.cast.exp.needCast = true;
+               exp.needTemplateCast = 2;
+               newExp.needTemplateCast = 2;
             }
             break;
          }
@@ -6243,7 +6729,7 @@ void CheckTemplateTypes(Expression exp)
 //    - Tree of all symbols within (stored without namespace)
 //    - Tree of sub-namespaces
 
-static Symbol ScanWithNameSpace(BinaryTree tree, char * nameSpace, char * name)
+static Symbol ScanWithNameSpace(BinaryTree tree, const char * nameSpace, const char * name)
 {
    int nsLen = strlen(nameSpace);
    Symbol symbol;
@@ -6273,11 +6759,11 @@ static Symbol ScanWithNameSpace(BinaryTree tree, char * nameSpace, char * name)
    return null;
 }
 
-static Symbol FindWithNameSpace(BinaryTree tree, char * name)
+static Symbol FindWithNameSpace(BinaryTree tree, const char * name)
 {
    int c;
    char nameSpace[1024];
-   char * namePart;
+   const char * namePart;
    bool gotColon = false;
 
    nameSpace[0] = '\0';
@@ -6320,9 +6806,7 @@ static Symbol FindWithNameSpace(BinaryTree tree, char * name)
    return null;
 }
 
-static void ProcessDeclaration(Declaration decl);
-
-/*static */Symbol FindSymbol(char * name, Context startContext, Context endContext, bool isStruct, bool globalNameSpace)
+/*static */Symbol FindSymbol(const char * name, Context startContext, Context endContext, bool isStruct, bool globalNameSpace)
 {
 #ifdef _DEBUG
    //Time startTime = GetTime();
@@ -6330,6 +6814,7 @@ static void ProcessDeclaration(Declaration decl);
    // Optimize this later? Do this before/less?
    Context ctx;
    Symbol symbol = null;
+
    // First, check if the identifier is declared inside the function
    //for(ctx = curContext; ctx /*!= topContext.parent */&& !symbol; ctx = ctx.parent)
 
@@ -6355,34 +6840,8 @@ static void ProcessDeclaration(Declaration decl);
 
       if(symbol || ctx == endContext) break;
    }
-   if(inCompiler && curExternal && symbol && ctx == globalContext && curExternal.symbol && symbol.id > curExternal.symbol.idCode && symbol.pointerExternal)
-   {
-      if(symbol.pointerExternal.type == functionExternal)
-      {
-         FunctionDefinition function = symbol.pointerExternal.function;
-
-         // Modified this recently...
-         Context tmpContext = curContext;
-         curContext = null;         
-         symbol.pointerExternal = MkExternalDeclaration(MkDeclaration(CopyList(function.specifiers, CopySpecifier), MkListOne(MkInitDeclarator(CopyDeclarator(function.declarator), null))));
-         curContext = tmpContext;
-
-         symbol.pointerExternal.symbol = symbol;
-
-         // TESTING THIS:
-         DeclareType(symbol.type, true, true);
-
-         ast->Insert(curExternal.prev, symbol.pointerExternal);
-
-         symbol.id = curExternal.symbol.idCode;
-
-      }
-      else if(symbol.pointerExternal.type == declarationExternal && curExternal.symbol.idCode < symbol.pointerExternal.symbol.id) // Added id comparison because Global Function prototypes were broken
-      {
-         ast->Move(symbol.pointerExternal, curExternal.prev);
-         symbol.id = curExternal.symbol.idCode;
-      }
-   }
+   if(inCompiler && symbol && ctx == globalContext && symbol.pointerExternal && curExternal && symbol.pointerExternal != curExternal)
+      curExternal.CreateUniqueEdge(symbol.pointerExternal, symbol.pointerExternal.type == functionExternal);
 #ifdef _DEBUG
    //findSymbolTotalTime += GetTime() - startTime;
 #endif
@@ -6394,7 +6853,7 @@ static void GetTypeSpecs(Type type, OldList * specs)
    if(!type.isSigned && type.kind != intPtrType && type.kind != intSizeType) ListAdd(specs, MkSpecifier(UNSIGNED));
    switch(type.kind)
    {
-      case classType: 
+      case classType:
       {
          if(type._class.registered)
          {
@@ -6407,11 +6866,12 @@ static void GetTypeSpecs(Type type, OldList * specs)
       case doubleType: ListAdd(specs, MkSpecifier(DOUBLE)); break;
       case floatType: ListAdd(specs, MkSpecifier(FLOAT)); break;
       case charType: ListAdd(specs, MkSpecifier(CHAR)); break;
+      case _BoolType: ListAdd(specs, MkSpecifier(_BOOL)); break;
       case shortType: ListAdd(specs, MkSpecifier(SHORT)); break;
       case int64Type: ListAdd(specs, MkSpecifier(INT64)); break;
       case intPtrType: ListAdd(specs, MkSpecifierName(type.isSigned ? "intptr" : "uintptr")); break;
       case intSizeType: ListAdd(specs, MkSpecifierName(type.isSigned ? "intsize" : "uintsize")); break;
-      case intType: 
+      case intType:
       default:
          ListAdd(specs, MkSpecifier(INT)); break;
    }
@@ -6442,11 +6902,12 @@ static void PrintTypeSpecs(Type type, char * string, bool fullName, bool printCo
          case classType:
          {
             Symbol c = type._class;
+            bool isObjectBaseClass = !c || !c.string || !strcmp(c.string, "class");
             // TODO: typed_object does not fully qualify the type, as it may have taken up an actual class (Stored in _class) from overriding
             //       look into merging with thisclass ?
-            if(type.classObjectType == typedObject)
+            if(type.classObjectType == typedObject && isObjectBaseClass)
                strcat(string, "typed_object");
-            else if(type.classObjectType == anyObject)
+            else if(type.classObjectType == anyObject && isObjectBaseClass)
                strcat(string, "any_object");
             else
             {
@@ -6463,6 +6924,7 @@ static void PrintTypeSpecs(Type type, char * string, bool fullName, bool printCo
          case intPtrType:  strcat(string, type.isSigned ? "intptr" : "uintptr"); break;
          case intSizeType:  strcat(string, type.isSigned ? "intsize" : "uintsize"); break;
          case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
+         case _BoolType: strcat(string, "_Bool"); break;
          case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
          case floatType: strcat(string, "float"); break;
          case doubleType: strcat(string, "double"); break;
@@ -6517,7 +6979,7 @@ static void PrintTypeSpecs(Type type, char * string, bool fullName, bool printCo
          case subClassType:
             strcat(string, "subclass(");
             strcat(string, type._class ? type._class.string : "int");
-            strcat(string, ")");                  
+            strcat(string, ")");
             break;
          case templateType:
             strcat(string, type.templateParameter.identifier.string);
@@ -6560,7 +7022,6 @@ static void PrePrintType(Type type, char * string, bool fullName, Type parentTyp
 {
    if(type.kind == arrayType || type.kind == pointerType || type.kind == functionType || type.kind == methodType)
    {
-      Type attrType = null;
       if((type.kind == functionType || type.kind == methodType) && (!parentType || parentType.kind != pointerType))
          PrintAttribs(type, string);
       if(printConst && type.constant && (type.kind == functionType || type.kind == methodType))
@@ -6703,8 +7164,12 @@ Type FindMemberAndOffset(Type type, char * string, uint * offset)
    return null;
 }
 
+public bool GetParseError() { return parseError; }
+
 Expression ParseExpressionString(char * expression)
 {
+   parseError = false;
+
    fileInput = TempFile { };
    fileInput.Write(expression, 1, strlen(expression));
    fileInput.Seek(0, start);
@@ -6728,7 +7193,7 @@ static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassChe
 
    if(_class && _class.type == enumClass)
    {
-      NamedLink value = null;
+      NamedLink64 value = null;
       Class enumClass = eSystem_FindClass(privateModule, "enum");
       if(enumClass)
       {
@@ -6743,17 +7208,19 @@ static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassChe
             }
             if(value)
             {
-               char constant[256];
-
-               FreeExpContents(exp);
-
-               exp.type = constantExp;
                exp.isConstant = true;
-               if(!strcmp(baseClass.dataTypeString, "int"))
-                  sprintf(constant, "%d",(int)value.data);
-               else
-                  sprintf(constant, "0x%X",(int)value.data);
-               exp.constant = CopyString(constant);
+               if(inCompiler || inPreCompiler || inDebugger)
+               {
+                  char constant[256];
+                  FreeExpContents(exp);
+
+                  exp.type = constantExp;
+                  if(!strcmp(baseClass.dataTypeString, "int") || !strcmp(baseClass.dataTypeString, "int64") || !strcmp(baseClass.dataTypeString, "char") || !strcmp(baseClass.dataTypeString, "short"))
+                     sprintf(constant, FORMAT64D, value.data);
+                  else
+                     sprintf(constant, FORMAT64HEX, value.data);
+                  exp.constant = CopyString(constant);
+               }
                //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
                exp.expType = MkClassType(baseClass.fullName);
                break;
@@ -6809,7 +7276,7 @@ static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassChe
          {
             //char constant[256];
             exp.type = stringExp;
-            exp.constant = QMkString((char *)classProp.Get(_class));
+            exp.constant = QMkString((char *)(uintptr)classProp.Get(_class));
          }
          else
          {
@@ -6962,12 +7429,12 @@ void ApplyAnyObjectLogic(Expression e)
                   newExp = checkedExp.op.exp2;
                   checkedExp.op.exp2 = null;
                   FreeExpContents(checkedExp);
-                  
+
                   if(e.expType && e.expType.passAsTemplate)
                   {
                      char size[100];
                      ComputeTypeSize(e.expType);
-                     sprintf(size, "%d", e.expType.size);
+                     sprintf(size, "%d", e.expType.size);   // Potential 32/64 Bootstrap issue
                      newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
                         MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
                            MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
@@ -6978,7 +7445,7 @@ void ApplyAnyObjectLogic(Expression e)
                }
                else if(!e.byReference || (_class && _class.type == noHeadClass))     // TESTING THIS HERE...
                {
-                  Expression checkedExp, newExp;
+                  Expression checkedExp; //, newExp;
 
                   {
                      // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
@@ -7032,11 +7499,11 @@ void ApplyAnyObjectLogic(Expression e)
                         /*
                         e.compound = MkCompoundStmt(
                            MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(
-                              MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))), 
+                              MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))),
 
                            MkListOne(MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier("__internalValue"))))));
                         */
-                        
+
                         {
                            Type type = e.destType;
                            e.destType = { };
@@ -7071,9 +7538,11 @@ void ApplyAnyObjectLogic(Expression e)
                   {
                      Expression operand { };
                      operand = *checkedExp;
-                     checkedExp.destType = null;
-                     checkedExp.expType = null;
                      checkedExp.Clear();
+                     checkedExp.destType = ProcessTypeString("void *", false);
+                     checkedExp.expType = checkedExp.destType;
+                     checkedExp.destType.refCount++;
+
                      checkedExp.type = opExp;
                      checkedExp.op.op = '&';
                      checkedExp.op.exp1 = null;
@@ -7092,7 +7561,7 @@ void ApplyAnyObjectLogic(Expression e)
       // FixReference(e, true);
    }
 //#if 0
-   if((!destType || destType.kind == ellipsisType || destType.kind == voidType) && e.expType && (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) && 
+   if((!destType || destType.kind == ellipsisType || destType.kind == voidType) && e.expType && (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) &&
       (e.expType.byReference || (e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
          (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass ) )))
    {
@@ -7137,11 +7606,11 @@ void ApplyAnyObjectLogic(Expression e)
 // TOFIX: Try this for a nice IDE crash!
 //#endif
    // The other way around
-   else 
+   else
 //#endif
-   if(destType && e.expType && 
+   if(destType && e.expType &&
          //e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class") &&
-         (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) && 
+         (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) &&
          !destType.classObjectType && /*(destType.kind != pointerType || !destType.type || destType.type.kind != voidType) &&*/ destType.kind != voidType)
    {
       if(destType.kind == ellipsisType)
@@ -7162,7 +7631,7 @@ void ApplyAnyObjectLogic(Expression e)
          if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && strcmp(e.expType._class.registered.name, "class"))
             type = e.expType;
          else
-            type = destType;            
+            type = destType;
 
          backupClassObjectType = type.classObjectType;
          backupByReference = type.byReference;
@@ -7182,19 +7651,42 @@ void ApplyAnyObjectLogic(Expression e)
          thisExp.next = null;
          e.Clear();
 
-         if( ( type.kind == classType && type._class && type._class.registered && 
-                   (type._class.registered.type == systemClass || type._class.registered.type == bitClass || 
+         if( ( type.kind == classType && type._class && type._class.registered &&
+                   (type._class.registered.type == systemClass || type._class.registered.type == bitClass ||
                     type._class.registered.type == enumClass || type._class.registered.type == unitClass) ) ||
              (type.kind != pointerType && type.kind != intPtrType && type.kind != arrayType && type.kind != classType) ||
              (!destType.byReference && byReference && (destType.kind != pointerType || type.kind != pointerType)))
          {
+            bool passAsTemplate = thisExp.destType.passAsTemplate;
+            Type t;
+
+            destType.refCount++;
+
             e.type = opExp;
             e.op.op = '*';
             e.op.exp1 = null;
             e.op.exp2 = MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), thisExp);
 
+            t = { };
+            CopyTypeInto(t, thisExp.destType);
+            t.passAsTemplate = false;
+            FreeType(thisExp.destType);
+            thisExp.destType = t;
+
+            t = { };
+            CopyTypeInto(t, destType);
+            t.passAsTemplate = passAsTemplate;
+            FreeType(destType);
+            destType = t;
+            destType.refCount = 0;
+
             e.expType = { };
             CopyTypeInto(e.expType, type);
+            if(type.passAsTemplate)
+            {
+               e.expType.classObjectType = none;
+               e.expType.passAsTemplate = false;
+            }
             e.expType.byReference = false;
             e.expType.refCount = 1;
          }
@@ -7207,27 +7699,105 @@ void ApplyAnyObjectLogic(Expression e)
             e.expType = type;
             type.refCount++;
          }
+
+         if(e.destType)
+            FreeType(e.destType);
+
          e.destType = destType;
          destType.refCount++;
       }
    }
 }
 
+void ApplyLocation(Expression exp, Location loc)
+{
+   exp.loc = loc;
+   switch(exp.type)
+   {
+      case opExp:
+         if(exp.op.exp1) ApplyLocation(exp.op.exp1, loc);
+         if(exp.op.exp2) ApplyLocation(exp.op.exp2, loc);
+         break;
+      case bracketsExp:
+         if(exp.list)
+         {
+            Expression e;
+            for(e = exp.list->first; e; e = e.next)
+               ApplyLocation(e, loc);
+         }
+         break;
+      case indexExp:
+         if(exp.index.index)
+         {
+            Expression e;
+            for(e = exp.index.index->first; e; e = e.next)
+               ApplyLocation(e, loc);
+         }
+         if(exp.index.exp)
+            ApplyLocation(exp.index.exp, loc);
+         break;
+      case callExp:
+         if(exp.call.arguments)
+         {
+            Expression arg;
+            for(arg = exp.call.arguments->first; arg; arg = arg.next)
+               ApplyLocation(arg, loc);
+         }
+         if(exp.call.exp)
+            ApplyLocation(exp.call.exp, loc);
+         break;
+      case memberExp:
+      case pointerExp:
+         if(exp.member.exp)
+            ApplyLocation(exp.member.exp, loc);
+         break;
+      case castExp:
+         if(exp.cast.exp)
+            ApplyLocation(exp.cast.exp, loc);
+         break;
+      case conditionExp:
+         if(exp.cond.exp)
+         {
+            Expression e;
+            for(e = exp.cond.exp->first; e; e = e.next)
+               ApplyLocation(e, loc);
+         }
+         if(exp.cond.cond)
+            ApplyLocation(exp.cond.cond, loc);
+         if(exp.cond.elseExp)
+            ApplyLocation(exp.cond.elseExp, loc);
+         break;
+      case vaArgExp:
+         if(exp.vaArg.exp)
+            ApplyLocation(exp.vaArg.exp, loc);
+         break;
+      default:
+         break;
+   }
+}
+
+bool RelatedUnits(Class c1, Class c2)
+{
+   if(c1.base.type == unitClass) c1 = c1.base;
+   if(c2.base.type == unitClass) c2 = c2.base;
+   return c1 == c2;
+}
+
 void ProcessExpressionType(Expression exp)
 {
    bool unresolved = false;
    Location oldyylloc = yylloc;
    bool notByReference = false;
-#ifdef _DEBUG   
+#ifdef _DEBUG
    char debugExpString[4096];
    debugExpString[0] = '\0';
    PrintExpression(exp, debugExpString);
 #endif
-   if(!exp || exp.expType) 
+   if(!exp || exp.expType)
       return;
 
    //eSystem_Logf("%s\n", expString);
-   
+
    // Testing this here
    yylloc = exp.loc;
    switch(exp.type)
@@ -7235,7 +7805,7 @@ void ProcessExpressionType(Expression exp)
       case identifierExp:
       {
          Identifier id = exp.identifier;
-         if(!id) return;
+         if(!id || !topContext) return;
 
          // DOING THIS LATER NOW...
          if(id._class && id._class.name)
@@ -7252,7 +7822,13 @@ void ProcessExpressionType(Expression exp)
             exp.expType = ProcessTypeString("Module", true);
             break;
          }
-         else */if(strstr(id.string, "__ecereClass") == id.string)
+         else */
+         if(!strcmp(id.string, "__runtimePlatform"))
+         {
+            exp.expType = ProcessTypeString("ecere::com::Platform", true);
+            break;
+         }
+         else if(strstr(id.string, "__ecereClass") == id.string)
          {
             exp.expType = ProcessTypeString("ecere::com::Class", true);
             break;
@@ -7272,11 +7848,17 @@ void ProcessExpressionType(Expression exp)
          }
          else
          {
-            Symbol symbol = FindSymbol(id.string, curContext, topContext /*exp.destType ? topContext : globalContext*/, false, id._class && id._class.name == null);
+            Symbol symbol = null;
+            bool findInGlobal = false;
+            if(!topContext.parent && exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered && exp.destType._class.registered.type == enumClass)
+               findInGlobal = true;  // In global context, look at enum values first
+            else
+               symbol = FindSymbol(id.string, curContext, topContext /*exp.destType ? topContext : globalContext*/, false, id._class && id._class.name == null);
+
             // Enums should be resolved here (Special pass in opExp to fix identifiers not seen as enum on the first pass)
             if(!symbol/* && exp.destType*/)
             {
-               if(exp.destType && CheckExpressionType(exp, exp.destType, false))
+               if(exp.destType && CheckExpressionType(exp, exp.destType, false, false))
                   break;
                else
                {
@@ -7298,6 +7880,8 @@ void ProcessExpressionType(Expression exp)
                   symbol = FindSymbol(id.string, topContext.parent, globalContext, false, id._class && id._class.name == null);
                }
             }
+            if(findInGlobal)
+               symbol = FindSymbol(id.string, curContext, topContext, false, id._class && id._class.name == null);
 
             // If we manage to resolve this symbol
             if(symbol)
@@ -7322,7 +7906,10 @@ void ProcessExpressionType(Expression exp)
                exp.expType = type;
                if(type)
                   type.refCount++;
-               if(type && (type.kind == enumType || (_class && _class.type == enumClass)))
+
+                                                // Commented this out, it was making non-constant enum parameters seen as constant
+                                                // enums should have been resolved by ResolveIdWithClass, changed to constantExp and marked as constant
+               if(type && (type.kind == enumType /*|| (_class && _class.type == enumClass)*/))
                   // Add missing cases here... enum Classes...
                   exp.isConstant = true;
 
@@ -7331,10 +7918,10 @@ void ProcessExpressionType(Expression exp)
                {
                   if(_class && _class.type == structClass && !type.declaredWithStruct)
                      exp.byReference = true;
-                  
+
                   //TESTING COMMENTING THIS OUT IN FAVOR OF ApplyAnyObjectLogic
-                  /*if(type && _class && (type.classObjectType == typedObject || type.classObjectType == anyObject) && 
-                     ((_class.type == unitClass || _class.type == enumClass || _class.type == bitClass) || 
+                  /*if(type && _class && (type.classObjectType == typedObject || type.classObjectType == anyObject) &&
+                     ((_class.type == unitClass || _class.type == enumClass || _class.type == bitClass) ||
                      (type.byReference && (_class.type == normalClass || _class.type == noHeadClass))))
                   {
                      Identifier id = exp.identifier;
@@ -7351,7 +7938,7 @@ void ProcessExpressionType(Expression exp)
                      exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(exp.identifier)));
                      ((Expression)exp.list->first).op.exp2.expType = exp.expType;
                      exp.expType = null;
-                     ProcessExpressionType(exp);                     
+                     ProcessExpressionType(exp);
                   }
                   else if(symbol.isIterator != 4)
                   {
@@ -7390,7 +7977,9 @@ void ProcessExpressionType(Expression exp)
                   if(c == definedExpStackPos && c < sizeof(definedExpStack) / sizeof(void *))
                   {
                      Location backupYylloc = yylloc;
+                     File backInput = fileInput;
                      definedExpStack[definedExpStackPos++] = definedExp;
+
                      fileInput = TempFile { };
                      fileInput.Write(definedExp.value, 1, strlen(definedExp.value));
                      fileInput.Seek(0, start);
@@ -7400,6 +7989,8 @@ void ProcessExpressionType(Expression exp)
                      resetScanner();
                      expression_yyparse();
                      delete fileInput;
+                     if(backInput)
+                        fileInput = backInput;
 
                      yylloc = backupYylloc;
 
@@ -7408,7 +7999,7 @@ void ProcessExpressionType(Expression exp)
                         FreeIdentifier(id);
                         exp.type = bracketsExp;
                         exp.list = MkListOne(parsedExpression);
-                        parsedExpression.loc = yylloc;
+                        ApplyLocation(parsedExpression, yylloc);
                         ProcessExpressionType(exp);
                         definedExpStackPos--;
                         return;
@@ -7438,7 +8029,7 @@ void ProcessExpressionType(Expression exp)
                      data = FindGlobalData(id.string);
                   if(data)
                   {
-                     DeclareGlobalData(data);
+                     DeclareGlobalData(curExternal, data);
                      exp.expType = data.dataType;
                      if(data.dataType) data.dataType.refCount++;
 
@@ -7472,7 +8063,7 @@ void ProcessExpressionType(Expression exp)
                         if(function.module.importType != staticImport && (!function.dataType || !function.dataType.dllExport))
                            strcpy(name, "__ecereFunction_");
                         FullClassNameCat(name, id.string, false); // Why is this using FullClassNameCat ?
-                        if(DeclareFunction(function, name))
+                        if(DeclareFunction(curExternal, function, name))
                         {
                            delete id.string;
                            id.string = CopyString(name);
@@ -7494,7 +8085,7 @@ void ProcessExpressionType(Expression exp)
       }
       case instanceExp:
       {
-         Class _class;
+         // Class _class;
          // Symbol classSym;
 
          if(!exp.instance._class)
@@ -7509,6 +8100,7 @@ void ProcessExpressionType(Expression exp)
          //_class = classSym ? classSym.registered : null;
 
          ProcessInstantiationType(exp.instance);
+
          exp.isConstant = exp.instance.isConstant;
 
          /*
@@ -7529,16 +8121,17 @@ void ProcessExpressionType(Expression exp)
          if(exp.instance._class)
          {
             exp.expType = MkClassType(exp.instance._class.name);
-            /*if(exp.expType._class && exp.expType._class.registered && 
+            /*if(exp.expType._class && exp.expType._class.registered &&
                (exp.expType._class.registered.type == normalClass || exp.expType._class.registered.type == noHeadClass))
                exp.expType.byReference = true;*/
-         }         
+         }
          break;
       }
       case constantExp:
       {
          if(!exp.expType)
          {
+            char * constant = exp.constant;
             Type type
             {
                refCount = 1;
@@ -7546,14 +8139,14 @@ void ProcessExpressionType(Expression exp)
             };
             exp.expType = type;
 
-            if(exp.constant[0] == '\'')
+            if(constant[0] == '\'')
             {
-               if((int)((byte *)exp.constant)[1] > 127)
+               if((int)((byte *)constant)[1] > 127)
                {
                   int nb;
-                  unichar ch = UTF8GetChar(exp.constant + 1, &nb);
-                  if(nb < 2) ch = exp.constant[1];
-                  delete exp.constant;
+                  unichar ch = UTF8GetChar(constant + 1, &nb);
+                  if(nb < 2) ch = constant[1];
+                  delete constant;
                   exp.constant = PrintUInt(ch);
                   // type.kind = (ch > 0xFFFF) ? intType : shortType;
                   type.kind = classType; //(ch > 0xFFFF) ? intType : shortType;
@@ -7567,26 +8160,62 @@ void ProcessExpressionType(Expression exp)
                   type.isSigned = true;
                }
             }
-            else if(strchr(exp.constant, '.'))
-            {
-               char ch = exp.constant[strlen(exp.constant)-1];
-               if(ch == 'f')
-                  type.kind = floatType;
-               else
-                  type.kind = doubleType;
-               type.isSigned = true;
-            }
             else
             {
-               if(exp.constant[0] == '0' && exp.constant[1])
-                  type.isSigned = false;
-               else if(strchr(exp.constant, 'L') || strchr(exp.constant, 'l'))
-                  type.isSigned = false;
-               else if(strtoll(exp.constant, null, 0) > MAXINT)
-                  type.isSigned = false;
+               char * dot = strchr(constant, '.');
+               bool isHex = (constant[0] == '0' && (constant[1] == 'x' || constant[1] == 'X'));
+               char * exponent;
+               if(isHex)
+               {
+                  exponent = strchr(constant, 'p');
+                  if(!exponent) exponent = strchr(constant, 'P');
+               }
                else
+               {
+                  exponent = strchr(constant, 'e');
+                  if(!exponent) exponent = strchr(constant, 'E');
+               }
+
+               if(dot || exponent)
+               {
+                  if(strchr(constant, 'f') || strchr(constant, 'F'))
+                     type.kind = floatType;
+                  else
+                     type.kind = doubleType;
                   type.isSigned = true;
-               type.kind = intType;
+               }
+               else
+               {
+                  bool isSigned = constant[0] == '-';
+                  char * endP = null;
+                  int64 i64 = strtoll(constant, &endP, 0);
+                  uint64 ui64 = strtoull(constant, &endP, 0);
+                  bool is64Bit = endP && (!strcmp(endP, "LL") || !strcmp(endP, "ll") || !strcmp(endP, "LLU") || !strcmp(endP, "llu") || !strcmp(endP, "ull") || !strcmp(endP, "ULL"));
+                  bool forceUnsigned = endP && (!strcmp(endP, "U") || !strcmp(endP, "u") || !strcmp(endP, "LLU") || !strcmp(endP, "llu") || !strcmp(endP, "ull") || !strcmp(endP, "ULL"));
+                  if(isSigned)
+                  {
+                     if(i64 < MININT)
+                        is64Bit = true;
+                  }
+                  else
+                  {
+                     if(ui64 > MAXINT)
+                     {
+                        if(ui64 > MAXDWORD)
+                        {
+                           is64Bit = true;
+                           if(ui64 <= MAXINT64 && (constant[0] != '0' || !constant[1]))
+                              isSigned = true;
+                        }
+                     }
+                     else if(constant[0] != '0' || !constant[1])
+                        isSigned = true;
+                  }
+                  if(forceUnsigned)
+                     isSigned = false;
+                  type.kind = is64Bit ? int64Type : intType;
+                  type.isSigned = isSigned;
+               }
             }
             exp.isConstant = true;
             if(exp.destType && exp.destType.kind == doubleType)
@@ -7608,8 +8237,9 @@ void ProcessExpressionType(Expression exp)
             type = Type
             {
                refCount = 1;
-               kind = charType;
+               kind = exp.wideString ? shortType : charType;
                constant = true;
+               isSigned = exp.wideString ? false : true;
             }
          };
          break;
@@ -7623,7 +8253,7 @@ void ProcessExpressionType(Expression exp)
             kind = pointerType;
             type = ProcessType(exp._new.typeName.qualifiers, exp._new.typeName.declarator);
          };
-         DeclareType(exp.expType.type, false, false);
+         DeclareType(curExternal, exp.expType.type, true, false);
          break;
       case renewExp:
       case renew0Exp:
@@ -7635,7 +8265,7 @@ void ProcessExpressionType(Expression exp)
             kind = pointerType;
             type = ProcessType(exp._renew.typeName.qualifiers, exp._renew.typeName.declarator);
          };
-         DeclareType(exp.expType.type, false, false);
+         DeclareType(curExternal, exp.expType.type, true, false);
          break;
       case opExp:
       {
@@ -7644,6 +8274,9 @@ void ProcessExpressionType(Expression exp)
          bool useDestType = false, useSideType = false;
          Location oldyylloc = yylloc;
          bool useSideUnit = false;
+         Class destClass = (exp.destType && exp.destType.kind == classType && exp.destType._class) ? exp.destType._class.registered : null;
+         bool powerOp = false, relationOp = false;
+         Class c1 = null, c2 = null;
 
          // Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
          Type dummy
@@ -7655,7 +8288,7 @@ void ProcessExpressionType(Expression exp)
          switch(exp.op.op)
          {
             // Assignment Operators
-            case '=': 
+            case '=':
             case MUL_ASSIGN:
             case DIV_ASSIGN:
             case MOD_ASSIGN:
@@ -7690,25 +8323,41 @@ void ProcessExpressionType(Expression exp)
                // Gives boolean result
                boolResult = true;
                useSideType = true;
+               relationOp = true;
                break;
             case '+':
             case '-':
                useSideUnit = true;
+               useSideType = true;
+               useDestType = true;
+               break;
+
+            case LEFT_OP:
+            case RIGHT_OP:
+               // useSideType = true;
+               // useDestType = true;
+               break;
 
-               // Just added these... testing
             case '|':
-            case '&':
             case '^':
+               useSideType = true;
+               useDestType = true;
+               break;
 
-            // DANGER: Verify units
             case '/':
             case '%':
+               useSideType = true;
+               useDestType = true;
+               if(exp.op.op == '/') powerOp = true;
+               break;
+            case '&':
             case '*':
-               
-               if(exp.op.op != '*' || exp.op.exp1)
+               if(exp.op.exp1)
                {
+                  // For & operator, useDestType nicely ensures the result will fit in a bool (TODO: Fix for generic enum)
                   useSideType = true;
                   useDestType = true;
+                  if(exp.op.op == '*') powerOp = true;
                }
                break;
 
@@ -7742,21 +8391,22 @@ void ProcessExpressionType(Expression exp)
          }
 
          //dummy.kind = TypeDummy;
-
          if(exp.op.exp1)
          {
-            if(exp.destType && exp.destType.kind == classType &&
-               exp.destType._class && exp.destType._class.registered && useDestType &&
-               
-              ((exp.destType._class.registered.type == unitClass && useSideUnit) || 
-               exp.destType._class.registered.type == enumClass ||
-               exp.destType._class.registered.type == bitClass
-               )) 
+            // Added this check here to use the dest type only for units derived from the base unit
+            // So that untyped units will use the side unit as opposed to the untyped destination unit
+            // This fixes (#771) sin(Degrees { 5 } + 5) to be equivalent to sin(Degrees { 10 }), since sin expects a generic Angle
+            if(exp.op.exp2 && useSideUnit && useDestType && destClass && destClass.type == unitClass && destClass.base.type != unitClass)
+               useDestType = false;
+
+            if(destClass && useDestType &&
+              ((destClass.type == unitClass && useSideUnit) || destClass.type == enumClass || destClass.type == bitClass))
 
               //(exp.destType._class.registered.type == unitClass || exp.destType._class.registered.type == enumClass) && useDestType)
             {
                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                exp.op.exp1.destType = exp.destType;
+               exp.op.exp1.opDestType = true;
                if(exp.destType)
                   exp.destType.refCount++;
             }
@@ -7764,19 +8414,53 @@ void ProcessExpressionType(Expression exp)
             {
                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                exp.op.exp1.destType = dummy;
-               dummy.refCount++;               
+               dummy.refCount++;
+               if(powerOp)
+                  exp.op.exp1.opDestType = true;
+               if(relationOp)
+                  exp.op.exp1.usedInComparison = true;
+            }
+            if(exp.op.op == '+' || exp.op.op == '-')
+            {
+               if(exp.opDestType)
+                  exp.op.exp1.parentOpDestType = true;
+               if(exp.usedInComparison)
+                  exp.op.exp1.usedInComparison = true;
             }
 
             // TESTING THIS HERE...
             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count++;
-            ProcessExpressionType(exp.op.exp1);
+               ProcessExpressionType(exp.op.exp1);
             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count--;
 
+            exp.op.exp1.opDestType = false;
+            exp.op.exp1.usedInComparison = false;
+
+            // Fix for unit and ++ / --
+            if(!exp.op.exp2 && (exp.op.op == INC_OP || exp.op.op == DEC_OP) && exp.op.exp1.expType && exp.op.exp1.expType.kind == classType &&
+               exp.op.exp1.expType._class && exp.op.exp1.expType._class.registered && exp.op.exp1.expType._class.registered.type == unitClass)
+            {
+               exp.op.exp2 = MkExpConstant("1");
+               exp.op.op = exp.op.op == INC_OP ? ADD_ASSIGN : SUB_ASSIGN;
+               assign = true;
+            }
+
             if(exp.op.exp1.destType == dummy)
             {
                FreeType(dummy);
                exp.op.exp1.destType = null;
             }
+
+            if(exp.op.exp2)
+            {
+               if(!assign && exp.op.exp1.expType && (exp.op.exp1.expType.kind == charType || exp.op.exp1.expType.kind == shortType))
+               {
+                  Type type { kind = intType, isSigned = true, refCount = 1, signedBeforePromotion = exp.op.exp1.expType.isSigned, bitMemberSize = exp.op.exp1.expType.bitMemberSize, promotedFrom = exp.op.exp1.expType.kind };
+                  FreeType(exp.op.exp1.expType);
+                  exp.op.exp1.expType = type;
+               }
+            }
+
             type1 = exp.op.exp1.expType;
          }
 
@@ -7795,6 +8479,8 @@ void ProcessExpressionType(Expression exp)
                else
                {
                   exp.op.exp2.destType = exp.destType;
+                  if(!exp.op.exp1 || (exp.op.op != '&' && exp.op.op != '^'))
+                     exp.op.exp2.opDestType = true;
                   if(exp.destType)
                      exp.destType.refCount++;
                }
@@ -7822,7 +8508,7 @@ void ProcessExpressionType(Expression exp)
                }
                else
                {
-                  // Don't convert to the type for those... (e.g.: Degrees a; a /= 2;) 
+                  // Don't convert to the type for those... (e.g.: Degrees a; a /= 2;)
                   if(exp.op.op == MUL_ASSIGN || exp.op.op == DIV_ASSIGN ||exp.op.op == MOD_ASSIGN ||exp.op.op == LEFT_ASSIGN ||exp.op.op == RIGHT_ASSIGN/* ||
                      exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN*/);
                   else
@@ -7836,15 +8522,14 @@ void ProcessExpressionType(Expression exp)
                if(type1) type1.refCount++;
                exp.expType = type1;
             }
-            else if(exp.destType && exp.destType.kind == classType &&
-               exp.destType._class && exp.destType._class.registered && 
-               
-                  ((exp.destType._class.registered.type == unitClass && useDestType && useSideUnit) || 
-                  (exp.destType._class.registered.type == enumClass && useDestType)) 
-                  )
+            else if(destClass &&
+                  ((destClass.type == unitClass && useDestType && useSideUnit) ||
+                  (destClass.type == enumClass && useDestType)))
             {
                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                exp.op.exp2.destType = exp.destType;
+               if(exp.op.op != '&' && exp.op.op != '^')
+                  exp.op.exp2.opDestType = true;
                if(exp.destType)
                   exp.destType.refCount++;
             }
@@ -7853,10 +8538,14 @@ void ProcessExpressionType(Expression exp)
                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                exp.op.exp2.destType = dummy;
                dummy.refCount++;
+               if(powerOp)
+                  exp.op.exp2.opDestType = true;
+               if(relationOp)
+                  exp.op.exp2.usedInComparison = true;
             }
 
             // TESTING THIS HERE... (DANGEROUS)
-            if(type1 && boolResult && useSideType && type1.kind == classType && type1._class && type1._class.registered && 
+            if(type1 && boolResult && useSideType && type1.kind == classType && type1._class && type1._class.registered &&
                (type1._class.registered.type == bitClass || type1._class.registered.type == enumClass))
             {
                FreeType(exp.op.exp2.destType);
@@ -7864,30 +8553,66 @@ void ProcessExpressionType(Expression exp)
                type1.refCount++;
             }
             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count++;
+            // Cannot lose the cast on a sizeof
+            if(exp.op.op == SIZEOF)
+            {
+               Expression e = exp.op.exp2;
+               while((e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp) && e.list)
+               {
+                  if(e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp)
+                  {
+                     if(e.type == extensionCompoundExp)
+                        e = ((Statement)e.compound.compound.statements->last).expressions->last;
+                     else
+                        e = e.list->last;
+                  }
+               }
+               if(e.type == castExp && e.cast.exp)
+                  e.cast.exp.needCast = true;
+            }
+            if(exp.op.op == '+' || exp.op.op == '-')
+            {
+               if(exp.opDestType)
+                  exp.op.exp2.parentOpDestType = true;
+               if(exp.usedInComparison)
+                  exp.op.exp2.usedInComparison = true;
+            }
             ProcessExpressionType(exp.op.exp2);
+            exp.op.exp2.opDestType = false;
+            exp.op.exp2.usedInComparison = false;
             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
 
+            if(!assign && (exp.op.exp1 || exp.op.op == '~'))
+            {
+               if(exp.op.exp2.expType && (exp.op.exp2.expType.kind == charType || exp.op.exp2.expType.kind == shortType))
+               {
+                  Type type { kind = intType, isSigned = true, refCount = 1, signedBeforePromotion = exp.op.exp2.expType.isSigned, bitMemberSize = exp.op.exp2.expType.bitMemberSize, promotedFrom = exp.op.exp2.expType.kind };
+                  FreeType(exp.op.exp2.expType);
+                  exp.op.exp2.expType = type;
+               }
+            }
+
             if(assign && type1 && type1.kind == pointerType && exp.op.exp2.expType)
             {
                if(exp.op.exp2.expType.kind == intSizeType || exp.op.exp2.expType.kind == intPtrType || exp.op.exp2.expType.kind == int64Type || exp.op.exp2.expType.kind == intType || exp.op.exp2.expType.kind == shortType || exp.op.exp2.expType.kind == charType)
                {
-                  if(exp.op.op != '=' && type1.type.kind == voidType) 
+                  if(exp.op.op != '=' && type1.type.kind == voidType)
                      Compiler_Error($"void *: unknown size\n");
                }
-               else if(exp.op.exp2.expType.kind == pointerType || exp.op.exp2.expType.kind == arrayType || exp.op.exp2.expType.kind == functionType || exp.op.exp2.expType.kind == methodType|| 
+               else if(exp.op.exp2.expType.kind == pointerType || exp.op.exp2.expType.kind == arrayType || exp.op.exp2.expType.kind == functionType || exp.op.exp2.expType.kind == methodType||
                            (type1.type.kind == voidType && exp.op.exp2.expType.kind == classType && exp.op.exp2.expType._class.registered &&
-                              (exp.op.exp2.expType._class.registered.type == normalClass || 
+                              (exp.op.exp2.expType._class.registered.type == normalClass ||
                               exp.op.exp2.expType._class.registered.type == structClass ||
                               exp.op.exp2.expType._class.registered.type == noHeadClass)))
                {
                   if(exp.op.op == ADD_ASSIGN)
-                     Compiler_Error($"cannot add two pointers\n");                   
+                     Compiler_Error($"cannot add two pointers\n");
                }
-               else if((exp.op.exp2.expType.kind == classType && type1.kind == pointerType && type1.type.kind == classType && 
+               else if((exp.op.exp2.expType.kind == classType && type1.kind == pointerType && type1.type.kind == classType &&
                   type1.type._class == exp.op.exp2.expType._class && exp.op.exp2.expType._class.registered && exp.op.exp2.expType._class.registered.type == structClass))
                {
                   if(exp.op.op == ADD_ASSIGN)
-                     Compiler_Error($"cannot add two pointers\n");                   
+                     Compiler_Error($"cannot add two pointers\n");
                }
                else if(inCompiler)
                {
@@ -7895,7 +8620,7 @@ void ProcessExpressionType(Expression exp)
                   char type2String[1024];
                   type1String[0] = '\0';
                   type2String[0] = '\0';
-                  
+
                   PrintType(exp.op.exp2.expType, type1String, false, true);
                   PrintType(type1, type2String, false, true);
                   ChangeCh(expString, '\n', ' ');
@@ -7923,7 +8648,28 @@ void ProcessExpressionType(Expression exp)
                type2.isSigned = true;
             }
             else
+            {
                type2 = exp.op.exp2.expType;
+               if(type2) type2.refCount++;
+            }
+         }
+         c1 = type1 && type1.kind == classType && type1._class ? type1._class.registered : null;
+         c2 = type2 && type2.kind == classType && type2._class ? type2._class.registered : null;
+
+         if(relationOp &&
+            ( (exp.op.exp1 && exp.op.exp1.ambiguousUnits && (!c2 || c2.type != unitClass)) ||
+               (exp.op.exp2 && exp.op.exp2.ambiguousUnits && (!c1 || c1.type != unitClass))) )
+            Compiler_Warning($"ambiguous units in relational operation\n");
+
+         if(!relationOp &&
+            ((exp.op.exp1 && exp.op.exp1.ambiguousUnits) ||
+             (exp.op.exp2 && exp.op.exp2.ambiguousUnits)) &&
+             (!powerOp || !c1 || c1.type != unitClass || !c2 || c2.type != unitClass || !RelatedUnits(c1, c2)))
+         {
+            if(exp.opDestType || exp.usedInComparison)
+               exp.ambiguousUnits = true;
+            else
+               Compiler_Warning($"ambiguous units\n");
          }
 
          dummy.kind = voidType;
@@ -7933,7 +8679,7 @@ void ProcessExpressionType(Expression exp)
             exp.expType = Type
             {
                refCount = 1;
-               kind = intType;
+               kind = intSizeType;
             };
             exp.isConstant = true;
          }
@@ -7946,11 +8692,24 @@ void ProcessExpressionType(Expression exp)
          }
          else if(exp.op.op == '&' && !exp.op.exp1)
             exp.expType = Reference(type2);
+         else if(exp.op.op == LEFT_OP || exp.op.op == RIGHT_OP)
+         {
+            if(exp.op.exp1.expType)
+            {
+               exp.expType = exp.op.exp1.expType;
+               exp.expType.refCount++;
+            }
+         }
          else if(!assign)
          {
+            if(c1 && !c1.dataType)
+               c1.dataType = ProcessTypeString(c1.dataTypeString, false);
+            if(c2 && !c2.dataType)
+               c2.dataType = ProcessTypeString(c2.dataTypeString, false);
+
             if(boolOps)
             {
-               if(exp.op.exp1) 
+               if(exp.op.exp1)
                {
                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                   exp.op.exp1.destType = MkClassType("bool");
@@ -7958,12 +8717,12 @@ void ProcessExpressionType(Expression exp)
                   if(!exp.op.exp1.expType)
                      ProcessExpressionType(exp.op.exp1);
                   else
-                     CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+                     CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
                   FreeType(exp.op.exp1.expType);
                   exp.op.exp1.expType = MkClassType("bool");
                   exp.op.exp1.expType.truth = true;
                }
-               if(exp.op.exp2) 
+               if(exp.op.exp2)
                {
                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                   exp.op.exp2.destType = MkClassType("bool");
@@ -7971,37 +8730,79 @@ void ProcessExpressionType(Expression exp)
                   if(!exp.op.exp2.expType)
                      ProcessExpressionType(exp.op.exp2);
                   else
-                     CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+                     CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
                   FreeType(exp.op.exp2.expType);
                   exp.op.exp2.expType = MkClassType("bool");
                   exp.op.exp2.expType.truth = true;
                }
             }
-            else if(exp.op.exp1 && exp.op.exp2 && 
-               ((useSideType /*&& 
-                     (useSideUnit || 
-                        ((!type1 || type1.kind != classType || type1._class.registered.type != unitClass) &&
-                         (!type2 || type2.kind != classType || type2._class.registered.type != unitClass)))*/) ||
-                  ((!type1 || type1.kind != classType || !strcmp(type1._class.string, "String")) && 
+            else if(powerOp && exp.op.exp1 && exp.op.exp2 && ((c1 && c1.type == unitClass) || (c2 && c2.type == unitClass)))
+            {
+               // * or / with at least one unit operand
+               if(c1 && c1.type == unitClass && c2 && c2.type == unitClass)
+               {
+                  // This is where we'd handle unit powers e.g. square meters or meters/seconds
+                  // For now using base types
+                  if(c1.dataType.kind == doubleType)        exp.expType = c1.dataType;
+                  else if(c2.dataType.kind == doubleType)   exp.expType = c2.dataType;
+                  else if(c1.dataType.kind == floatType)    exp.expType = c1.dataType;
+                  else if(c2.dataType.kind == floatType)    exp.expType = c2.dataType;
+                  else
+                     exp.expType = c1.dataType;
+               }
+               else if((c1 && c1.type == unitClass) || exp.op.op == '/')   // 1/units should not be typed with unit
+                  exp.expType = type1;
+               else
+                  exp.expType = type2;
+
+               if(exp.expType)
+                  exp.expType.refCount++;
+            }
+            else if(exp.op.exp1 && exp.op.exp2 &&
+               ((useSideType /*&&
+                     (useSideUnit ||
+                        ((!c1 || c1.type != unitClass) &&
+                         (!c2 || c2.type != unitClass)))*/) ||
+                  ((!type1 || type1.kind != classType || !strcmp(type1._class.string, "String")) &&
                   (!type2 || type2.kind != classType || !strcmp(type2._class.string, "String")))))
             {
                if(type1 && type2 &&
                   // If either both are class or both are not class
                   ((type1.kind == classType && type1._class && strcmp(type1._class.string, "String")) == (type2.kind == classType && type2._class && strcmp(type2._class.string, "String"))))
                {
-                  if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
-                  exp.op.exp2.destType = type1;
-                  type1.refCount++;
-                  if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
-                  exp.op.exp1.destType = type2;
-                  type2.refCount++;
+                  // Added this check for enum subtraction to result in an int type:
+                  if(exp.op.op == '-' && ((c1 && c1.type == enumClass) || (c2 && c2.type == enumClass)) )
+                  {
+                     Type intType = ProcessTypeString((c1 && c1.dataType.kind == int64Type) || (c2 && c2.dataType.kind == int64Type) ? "int64" : "int", false);
+
+                     if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
+                     if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
+                     exp.op.exp1.destType = intType;
+                     exp.op.exp2.destType = intType;
+                     intType.refCount++;
+                  }
+                  else
+                  {
+                     if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
+                     exp.op.exp2.destType = type1;
+                     type1.refCount++;
+                     if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
+                     exp.op.exp1.destType = type2;
+                     type2.refCount++;
+                  }
+
                   // Warning here for adding Radians + Degrees with no destination type
-                  if(!boolResult && type1.kind == classType && (!exp.destType || exp.destType.kind != classType) && 
-                     type1._class.registered && type1._class.registered.type == unitClass && 
-                     type2._class.registered && type2._class.registered.type == unitClass && 
-                     type1._class.registered != type2._class.registered)
-                     Compiler_Warning($"operating on %s and %s with an untyped result, assuming %s\n",
-                        type1._class.string, type2._class.string, type1._class.string);
+                  if(!boolResult && !exp.opDestType && (!exp.destType || exp.destType.kind != classType) &&
+                     c1 && c1.type == unitClass &&
+                     c2 && c2.type == unitClass &&
+                     c1 != c2)
+                  {
+                     if(exp.usedInComparison || exp.parentOpDestType)
+                        exp.ambiguousUnits = true;
+                     else
+                        Compiler_Warning($"operating on %s and %s with an untyped result, assuming %s\n",
+                           type1._class.string, type2._class.string, type1._class.string);
+                  }
 
                   if(type1.kind == pointerType && type1.type.kind == templateType && type2.kind != pointerType)
                   {
@@ -8011,7 +8812,7 @@ void ProcessExpressionType(Expression exp)
                         Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
 
                         exp.op.exp1 = MkExpBrackets(MkListOne(MkExpCast(
-                           MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), 
+                           MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)),
                            exp.op.exp1)));
 
                         ProcessExpressionType(exp.op.exp1);
@@ -8020,36 +8821,31 @@ void ProcessExpressionType(Expression exp)
                         {
                            ProcessExpressionType(classExp);
 
-                           exp.op.exp2 = MkExpBrackets(MkListOne(MkExpOp(exp.op.exp2, '*', 
-                              // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
-                              MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
-                                 // noHeadClass
-                                 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("5")),
-                                    OR_OP, 
-                                 // normalClass
-                                 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("0"))))),
-                                    MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
-                                       MkPointer(null, null), null)))),                                  
-                                       MkExpMember(classExp, MkIdentifier("typeSize"))))))));
+                           exp.op.exp2 = MkExpBrackets(MkListOne(MkExpOp(exp.op.exp2, '*', MkExpMember(classExp, MkIdentifier("typeSize")) )));
 
                            if(!exp.op.exp2.expType)
-                              type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
+                           {
+                              if(type2)
+                                 FreeType(type2);
+                              type2 = exp.op.exp2.expType = ProcessTypeString("int", false); c2 = null;
+                              type2.refCount++;
+                           }
 
                            ProcessExpressionType(exp.op.exp2);
                         }
                      }
                   }
-                  
+
                   if(!boolResult && ((type1.kind == pointerType || type1.kind == arrayType || (type1.kind == classType && !strcmp(type1._class.string, "String"))) && (type2.kind == intSizeType || type2.kind == intPtrType || type2.kind == int64Type || type2.kind == intType || type2.kind == shortType || type2.kind == charType)))
                   {
-                     if(type1.kind != classType && type1.type.kind == voidType) 
+                     if(type1.kind != classType && type1.type.kind == voidType)
                         Compiler_Error($"void *: unknown size\n");
                      exp.expType = type1;
                      if(type1) type1.refCount++;
                   }
                   else if(!boolResult && ((type2.kind == pointerType || type2.kind == arrayType || (type2.kind == classType && !strcmp(type2._class.string, "String"))) && (type1.kind == intSizeType || type1.kind == intPtrType || type1.kind == int64Type || type1.kind == intType || type1.kind == shortType || type1.kind == charType)))
                   {
-                     if(type2.kind != classType && type2.type.kind == voidType) 
+                     if(type2.kind != classType && type2.type.kind == voidType)
                         Compiler_Error($"void *: unknown size\n");
                      exp.expType = type2;
                      if(type2) type2.refCount++;
@@ -8059,7 +8855,7 @@ void ProcessExpressionType(Expression exp)
                   {
                      Compiler_Warning($"different levels of indirection\n");
                   }
-                  else 
+                  else
                   {
                      bool success = false;
                      if(type1.kind == pointerType && type2.kind == pointerType)
@@ -8069,7 +8865,7 @@ void ProcessExpressionType(Expression exp)
                         else if(exp.op.op == '-')
                         {
                            // Pointer Subtraction gives integer
-                           if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false))
+                           if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false, false))
                            {
                               exp.expType = Type
                               {
@@ -8091,28 +8887,13 @@ void ProcessExpressionType(Expression exp)
                                     exp.list = MkListOne(MkExpOp(
                                        MkExpBrackets(MkListOne(MkExpOp(
                                              MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp1)))
-                                             , exp.op.op, 
-                                             MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp2)))))), '/', 
-                                          
-                                             //MkExpMember(classExp, MkIdentifier("typeSize"))
-
-                                             // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
-                                             MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
-                                                // noHeadClass
-                                                MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass"))),
-                                                   OR_OP, 
-                                                // normalClass
-                                                MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass")))))),
-                                                   MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
-                                                      MkPointer(null, null), null)))),                                  
-                                                      MkExpMember(classExp, MkIdentifier("typeSize")))))
-
-                                             
-                                             ));
-                                    
+                                             , exp.op.op,
+                                             MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp2)))))), '/',
+                                             MkExpMember(classExp, MkIdentifier("typeSize"))));
+
                                     ProcessExpressionType(((Expression)exp.list->first).op.exp2);
                                     FreeType(dummy);
-                                    return;                                       
+                                    return;
                                  }
                               }
                            }
@@ -8122,14 +8903,14 @@ void ProcessExpressionType(Expression exp)
                      if(!success && exp.op.exp1.type == constantExp)
                      {
                         // If first expression is constant, try to match that first
-                        if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+                        if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
                         {
                            if(exp.expType) FreeType(exp.expType);
                            exp.expType = exp.op.exp1.destType;
                            if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
                            success = true;
                         }
-                        else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
+                        else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false))
                         {
                            if(exp.expType) FreeType(exp.expType);
                            exp.expType = exp.op.exp2.destType;
@@ -8139,14 +8920,14 @@ void ProcessExpressionType(Expression exp)
                      }
                      else if(!success)
                      {
-                        if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
+                        if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false))
                         {
                            if(exp.expType) FreeType(exp.expType);
                            exp.expType = exp.op.exp2.destType;
                            if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
                            success = true;
                         }
-                        else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+                        else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
                         {
                            if(exp.expType) FreeType(exp.expType);
                            exp.expType = exp.op.exp1.destType;
@@ -8179,25 +8960,25 @@ void ProcessExpressionType(Expression exp)
                   }
                }
                // ADDED THESE TWO FROM OUTSIDE useSideType CHECK
-               else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type2 && type1 && type2.kind == classType && type1.kind != classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
+               else if(!boolResult && !useSideUnit && c2 && c2.type == unitClass && type1 && type1.kind != classType)
                {
                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                   // Convert e.g. / 4 into / 4.0
                   exp.op.exp1.destType = type2._class.registered.dataType;
                   if(type2._class.registered.dataType)
                      type2._class.registered.dataType.refCount++;
-                  CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+                  CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
                   exp.expType = type2;
                   if(type2) type2.refCount++;
                }
-               else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type1 && type2 && type1.kind == classType && type2.kind != classType && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
+               else if(!boolResult && !useSideUnit && c1 && c1.type == unitClass && type2 && type2.kind != classType)
                {
                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                   // Convert e.g. / 4 into / 4.0
                   exp.op.exp2.destType = type1._class.registered.dataType;
                   if(type1._class.registered.dataType)
                      type1._class.registered.dataType.refCount++;
-                  CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+                  CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
                   exp.expType = type1;
                   if(type1) type1.refCount++;
                }
@@ -8205,68 +8986,113 @@ void ProcessExpressionType(Expression exp)
                {
                   bool valid = false;
 
-                  if(!boolResult && useSideUnit && type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
+                  if(!boolResult && useSideUnit && c1 && c1.type == unitClass && type2 && type2.kind != classType)
                   {
                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
 
-                     if(!type1._class.registered.dataType)
-                        type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
-                     exp.op.exp2.destType = type1._class.registered.dataType;
+                     exp.op.exp2.destType = c1.dataType;
                      exp.op.exp2.destType.refCount++;
 
-                     CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+                     CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
+                     if(type2)
+                        FreeType(type2);
                      type2 = exp.op.exp2.destType;
+                     c2 = type2 && type2.kind == classType && type2._class ? type2._class.registered : null;
+                     if(type2) type2.refCount++;
 
                      exp.expType = type2;
                      type2.refCount++;
                   }
-                  
-                  if(!boolResult && useSideUnit && type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
+
+                  if(!boolResult && useSideUnit && c2 && c2.type == unitClass && type1 && type1.kind != classType)
                   {
                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
 
-                     if(!type2._class.registered.dataType)
-                        type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
-                     exp.op.exp1.destType = type2._class.registered.dataType;
+                     exp.op.exp1.destType = c2.dataType;
                      exp.op.exp1.destType.refCount++;
 
-                     CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+                     CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
                      type1 = exp.op.exp1.destType;
+                     c1 = type1 && type1.kind == classType && type1._class ? type1._class.registered : null;
                      exp.expType = type1;
                      type1.refCount++;
                   }
 
                   // TESTING THIS NEW CODE
-                  if(!boolResult || exp.op.op == '>' || exp.op.op == '<')
+                  if(!boolResult || exp.op.op == '>' || exp.op.op == '<' || exp.op.op == GE_OP || exp.op.op == LE_OP)
                   {
-                     if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass && exp.op.exp2.expType)
+                     bool op1IsEnum = c1 && c1.type == enumClass;
+                     bool op2IsEnum = c2 && c2.type == enumClass;
+                     if(exp.op.op == '*' || exp.op.op == '/' || exp.op.op == '-' || exp.op.op == '|' || exp.op.op == '^')
                      {
-                        if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false))
+                        // Convert the enum to an int instead for these operators
+                        if(op1IsEnum && exp.op.exp2.expType)
                         {
-                           if(exp.expType) FreeType(exp.expType);
-                           exp.expType = exp.op.exp1.expType;
-                           if(exp.op.exp2.expType) exp.op.exp1.expType.refCount++;
-                           valid = true;
+                           if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false, false))
+                           {
+                              if(exp.expType) FreeType(exp.expType);
+                              exp.expType = exp.op.exp2.expType;
+                              if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+                              valid = true;
+                           }
+                        }
+                        else if(op2IsEnum && exp.op.exp1.expType)
+                        {
+                           if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false, false))
+                           {
+                              if(exp.expType) FreeType(exp.expType);
+                              exp.expType = exp.op.exp1.expType;
+                              if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
+                              valid = true;
+                           }
                         }
                      }
-
-                     else if(type2 && (type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass && exp.op.exp1.expType))
+                     else
                      {
-                        if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false))
+                        if(op1IsEnum && exp.op.exp2.expType)
                         {
-                           if(exp.expType) FreeType(exp.expType);
-                           exp.expType = exp.op.exp2.expType;
-                           if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
-                           valid = true;
+                           if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false, false))
+                           {
+                              if(exp.expType) FreeType(exp.expType);
+                              exp.expType = exp.op.exp1.expType;
+                              if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
+                              valid = true;
+                           }
+                        }
+                        else if(op2IsEnum && exp.op.exp1.expType)
+                        {
+                           if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false, false))
+                           {
+                              if(exp.expType) FreeType(exp.expType);
+                              exp.expType = exp.op.exp2.expType;
+                              if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+                              valid = true;
+                           }
                         }
                      }
                   }
 
                   if(!valid)
                   {
-                     if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
-                     exp.op.exp2.destType = type1;
-                     type1.refCount++;
+                     // Added this first part of the if here to handle  5 + Degrees { 5 } with either a base unit dest or not a unit dest type
+                     if(c2 && c2.type == unitClass && (!c1 || c1.type != unitClass))
+                     {
+                        if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
+                        exp.op.exp1.destType = type2;
+                        type2.refCount++;
+
+                        if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
+                        {
+                           if(exp.expType) FreeType(exp.expType);
+                           exp.expType = exp.op.exp1.destType;
+                           if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
+                        }
+                     }
+                     else
+                     {
+                        if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
+                        exp.op.exp2.destType = type1;
+                        type1.refCount++;
 
                      /*
                      // Maybe this was meant to be an enum...
@@ -8290,7 +9116,7 @@ void ProcessExpressionType(Expression exp)
                         if(type2._class.registered.dataType)
                            type2._class.registered.dataType.refCount++;
                         CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
-                        
+
                         //exp.expType = type2._class.registered.dataType; //type2;
                         //if(type2) type2.refCount++;
                      }
@@ -8308,43 +9134,44 @@ void ProcessExpressionType(Expression exp)
                      }
                      */
 
-                     if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
-                     {
-                        if(exp.expType) FreeType(exp.expType);
-                        exp.expType = exp.op.exp2.destType;
-                        if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
-                     }
-                     else if(type1 && type2)
-                     {
-                        char expString1[10240];
-                        char expString2[10240];
-                        char type1String[1024];
-                        char type2String[1024];
-                        expString1[0] = '\0';
-                        expString2[0] = '\0';
-                        type1String[0] = '\0';
-                        type2String[0] = '\0';
-                        if(inCompiler)
+                        if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false))
                         {
-                           PrintExpression(exp.op.exp1, expString1);
-                           ChangeCh(expString1, '\n', ' ');
-                           PrintExpression(exp.op.exp2, expString2);
-                           ChangeCh(expString2, '\n', ' ');
-                           PrintType(exp.op.exp1.expType, type1String, false, true);
-                           PrintType(exp.op.exp2.expType, type2String, false, true);
+                           if(exp.expType) FreeType(exp.expType);
+                           exp.expType = exp.op.exp2.destType;
+                           if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
                         }
+                        else if(type1 && type2)
+                        {
+                           char expString1[10240];
+                           char expString2[10240];
+                           char type1String[1024];
+                           char type2String[1024];
+                           expString1[0] = '\0';
+                           expString2[0] = '\0';
+                           type1String[0] = '\0';
+                           type2String[0] = '\0';
+                           if(inCompiler)
+                           {
+                              PrintExpression(exp.op.exp1, expString1);
+                              ChangeCh(expString1, '\n', ' ');
+                              PrintExpression(exp.op.exp2, expString2);
+                              ChangeCh(expString2, '\n', ' ');
+                              PrintType(exp.op.exp1.expType, type1String, false, true);
+                              PrintType(exp.op.exp2.expType, type2String, false, true);
+                           }
 
-                        Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
+                           Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
 
-                        if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
-                        {
-                           exp.expType = exp.op.exp1.expType;
-                           if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
-                        }
-                        else if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
-                        {
-                           exp.expType = exp.op.exp2.expType;
-                           if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+                           if(c1 && c1.type == enumClass)
+                           {
+                              exp.expType = exp.op.exp1.expType;
+                              if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
+                           }
+                           else if(c2 && c2.type == enumClass)
+                           {
+                              exp.expType = exp.op.exp2.expType;
+                              if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+                           }
                         }
                      }
                   }
@@ -8352,11 +9179,11 @@ void ProcessExpressionType(Expression exp)
                else if(type2)
                {
                   // Maybe this was meant to be an enum...
-                  if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
+                  if(c2 && c2.type == enumClass)
                   {
                      Type oldType = exp.op.exp1.expType;
                      exp.op.exp1.expType = null;
-                     if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+                     if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
                         FreeType(oldType);
                      else
                         exp.op.exp1.expType = oldType;
@@ -8385,7 +9212,7 @@ void ProcessExpressionType(Expression exp)
                   }
                   */
 
-                  if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+                  if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
                   {
                      if(exp.expType) FreeType(exp.expType);
                      exp.expType = exp.op.exp1.destType;
@@ -8395,14 +9222,14 @@ void ProcessExpressionType(Expression exp)
             }
             else if(type2 && (!type1 || (type2.kind == classType && type1.kind != classType)))
             {
-               if(type1 && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
+               if(type1 && c2 && c2.type == unitClass)
                {
                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                   // Convert e.g. / 4 into / 4.0
                   exp.op.exp1.destType = type2._class.registered.dataType;
                   if(type2._class.registered.dataType)
                      type2._class.registered.dataType.refCount++;
-                  CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+                  CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
                }
                if(exp.op.op == '!')
                {
@@ -8417,20 +9244,20 @@ void ProcessExpressionType(Expression exp)
             }
             else if(type1 && (!type2 || (type1.kind == classType && type2.kind != classType)))
             {
-               if(type2 && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
+               if(c2 && c2.type == unitClass)
                {
                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                   // Convert e.g. / 4 into / 4.0
                   exp.op.exp2.destType = type1._class.registered.dataType;
                   if(type1._class.registered.dataType)
                      type1._class.registered.dataType.refCount++;
-                  CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+                  CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
                }
                exp.expType = type1;
                if(type1) type1.refCount++;
             }
          }
-         
+
          yylloc = exp.loc;
          if(exp.op.exp1 && !exp.op.exp1.expType)
          {
@@ -8470,12 +9297,17 @@ void ProcessExpressionType(Expression exp)
 
          if(exp.op.op == SIZEOF && exp.op.exp2.expType)
          {
-            DeclareType(exp.op.exp2.expType, false, false);
+            DeclareType(curExternal, exp.op.exp2.expType, true, false);
          }
 
+         if(exp.op.op == DELETE && exp.op.exp2 && exp.op.exp2.expType && exp.op.exp2.expType.specConst)
+            Compiler_Warning($"deleting const qualified object\n");
+
          yylloc = oldyylloc;
 
          FreeType(dummy);
+         if(type2)
+            FreeType(type2);
          break;
       }
       case bracketsExp:
@@ -8485,20 +9317,26 @@ void ProcessExpressionType(Expression exp)
          exp.isConstant = true;
          for(e = exp.list->first; e; e = e.next)
          {
-            bool inced = false;
+            //bool inced = false;
             if(!e.next)
             {
                FreeType(e.destType);
+               e.opDestType = exp.opDestType;
+               e.usedInComparison = exp.usedInComparison;
+               e.parentOpDestType = exp.parentOpDestType;
                e.destType = exp.destType;
-               if(e.destType) { exp.destType.refCount++; e.destType.count++; inced = true; }
+               if(e.destType) { exp.destType.refCount++; /*e.destType.count++; inced = true;*/ }
             }
             ProcessExpressionType(e);
-            if(inced)
-               exp.destType.count--;
+            if(e.ambiguousUnits)
+               exp.ambiguousUnits = true;
+            /*if(inced)
+               exp.destType.count--;*/
             if(!exp.expType && !e.next)
             {
                exp.expType = e.expType;
                if(e.expType) e.expType.refCount++;
+               exp.needCast = e.needCast;
             }
             if(!e.isConstant)
                exp.isConstant = false;
@@ -8515,7 +9353,7 @@ void ProcessExpressionType(Expression exp)
             FreeType(exp.expType);
             FreeType(exp.destType);
             delete exp.list;
-            
+
             *exp = *e;
 
             exp.prev = prev;
@@ -8549,7 +9387,17 @@ void ProcessExpressionType(Expression exp)
 
                   if(exp.index.index && exp.index.index->last)
                   {
-                     ((Expression)exp.index.index->last).destType = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
+                     Type type = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
+
+                     if(type.kind == classType) type.constant = true;
+                     else if(type.kind == pointerType)
+                     {
+                        Type t = type;
+                        while(t.kind == pointerType) t = t.type;
+                        t.constant = true;
+                     }
+
+                     ((Expression)exp.index.index->last).destType = type;
                   }
                }
             }
@@ -8574,7 +9422,7 @@ void ProcessExpressionType(Expression exp)
          if(!exp.expType)
             exp.expType = Dereference(exp.index.exp.expType);
          if(exp.expType)
-            DeclareType(exp.expType, false, false);
+            DeclareType(curExternal, exp.expType, true, false);
          break;
       }
       case callExp:
@@ -8633,7 +9481,7 @@ void ProcessExpressionType(Expression exp)
                   a = exp.call.arguments->first;
                   tempExp1 = a;
                }
-               
+
                if(a)
                {
                   exp.call.arguments->Clear();
@@ -8681,7 +9529,7 @@ void ProcessExpressionType(Expression exp)
                               if(b.expType)
                                  b.expType.refCount++;
                               ListAdd(exp.list, MkExpOp(CopyExpression(tempExp2), '=', b));
-                           }                        
+                           }
 
                            decl = MkDeclaration(specs, decls);
                            if(!curCompound.compound.declarations)
@@ -8694,7 +9542,7 @@ void ProcessExpressionType(Expression exp)
                   if(!strcmp(id.string, "Max") || !strcmp(id.string, "Min"))
                   {
                      int op = (!strcmp(id.string, "Max")) ? '>' : '<';
-                     ListAdd(exp.list, 
+                     ListAdd(exp.list,
                         MkExpCondition(MkExpBrackets(MkListOne(
                            MkExpOp(CopyExpression(tempExp1), op, CopyExpression(tempExp2)))),
                            MkListOne(CopyExpression(tempExp1)), CopyExpression(tempExp2)));
@@ -8704,7 +9552,7 @@ void ProcessExpressionType(Expression exp)
                   }
                   else if(!strcmp(id.string, "Abs"))
                   {
-                     ListAdd(exp.list, 
+                     ListAdd(exp.list,
                         MkExpCondition(MkExpBrackets(MkListOne(
                            MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
                            MkListOne(MkExpOp(null, '-', CopyExpression(tempExp1))), CopyExpression(tempExp1)));
@@ -8715,7 +9563,7 @@ void ProcessExpressionType(Expression exp)
                   else if(!strcmp(id.string, "Sgn"))
                   {
                      // ((!(a))?(0):(((a)<0)?(-1):(1)))
-                     ListAdd(exp.list, 
+                     ListAdd(exp.list,
                         MkExpCondition(MkExpBrackets(MkListOne(
                            MkExpOp(null, '!', CopyExpression(tempExp1)))), MkListOne(MkExpConstant("0")),
                               MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(
@@ -8760,7 +9608,7 @@ void ProcessExpressionType(Expression exp)
          {
             methodType = functionType;
             functionType = methodType.method.dataType;
-            
+
             //if(functionType.returnType && functionType.returnType.kind == thisClassType)
             // TOCHECK: Instead of doing this here could this be done per param?
             if(exp.call.exp.expType.usedClass)
@@ -8782,17 +9630,17 @@ void ProcessExpressionType(Expression exp)
                      Context context = SetupTemplatesContext(exp.call.exp.expType.usedClass);
 
                      decl = SpecDeclFromString(typeString, specs, null);
-                     
+
                      // SET THIS TO FALSE WHEN PROCESSING THISCLASS OUTSIDE THE CLASS
                      if(thisClass != (exp.call.exp.expType.usedClass.templateClass ? exp.call.exp.expType.usedClass.templateClass :
                         exp.call.exp.expType.usedClass))
                         thisClassParams = false;
-                     
+
                      ReplaceThisClassSpecifiers(specs, exp.call.exp.expType.usedClass);
                      {
                         Class backupThisClass = thisClass;
                         thisClass = exp.call.exp.expType.usedClass;
-                        ProcessDeclarator(decl);
+                        ProcessDeclarator(decl, true);
                         thisClass = backupThisClass;
                      }
 
@@ -8801,6 +9649,22 @@ void ProcessExpressionType(Expression exp)
                      functionType = ProcessType(specs, decl);
                      functionType.refCount = 0;
                      FinishTemplatesContext(context);
+
+                     // Mark parameters that were 'thisclass'
+                     {
+                        Type p, op;
+                        for(p = functionType.params.first, op = methodType.method.dataType.params.first; p && op; p = p.next, op = op.next)
+                        {
+                           //p.wasThisClass = op.kind == thisClassType;
+                           if(op.kind == thisClassType)
+                              p.thisClassFrom = methodType.method._class;
+                        }
+                     }
+                     if(methodType.method.dataType.returnType.kind == thisClassType)
+                     {
+                        // functionType.returnType.wasThisClass = true;
+                        functionType.returnType.thisClassFrom = methodType.method._class;
+                     }
                   }
 
                   FreeList(specs, FreeSpecifier);
@@ -8845,7 +9709,7 @@ void ProcessExpressionType(Expression exp)
             // Fixed #141 by adding '&& !functionType.extraParam'
             if(!functionType.staticMethod && !functionType.extraParam)
             {
-               if(memberExp && memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.kind == subClassType && 
+               if(memberExp && memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.kind == subClassType &&
                   memberExp.member.exp.expType._class)
                {
                   type = MkClassType(memberExp.member.exp.expType._class.string);
@@ -8866,7 +9730,7 @@ void ProcessExpressionType(Expression exp)
                   if(e)
                   {
                      // Allow manually passing a class for typed object
-                     if(type.kind == classType && (functionType && functionType.thisClass) && functionType.classObjectType == typedObject)
+                     if(e.next && type.kind == classType && (functionType && functionType.thisClass) && functionType.classObjectType == typedObject)
                         e = e.next;
                      e.destType = type;
                      e = e.next;
@@ -8933,15 +9797,25 @@ void ProcessExpressionType(Expression exp)
                   }
                   if(curParam && _class.templateArgs[id].dataTypeString)
                   {
+                     bool constant = type.constant;
                      ClassTemplateArgument arg = _class.templateArgs[id];
                      {
                         Context context = SetupTemplatesContext(_class);
-                     
+
                         /*if(!arg.dataType)
                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
                         templatedType = ProcessTypeString(arg.dataTypeString, false);
                         FinishTemplatesContext(context);
                      }
+
+                     if(templatedType.kind == classType && constant) templatedType.constant = true;
+                     else if(templatedType.kind == pointerType)
+                     {
+                        Type t = templatedType.type;
+                        while(t.kind == pointerType) t = t.type;
+                        if(constant) t.constant = constant;
+                     }
+
                      e.destType = templatedType;
                      if(templatedType)
                      {
@@ -9057,10 +9931,7 @@ void ProcessExpressionType(Expression exp)
          if(exp.call.arguments)
          {
             for(e = exp.call.arguments->first; e; e = e.next)
-            {
-               Type destType = e.destType;
                ProcessExpressionType(e);
-            }
          }
          break;
       }
@@ -9094,7 +9965,7 @@ void ProcessExpressionType(Expression exp)
          }
 
          ProcessExpressionType(exp.member.exp);
-         if(exp.member.exp.expType && exp.member.exp.expType.kind == classType && exp.member.exp.expType._class && 
+         if(exp.member.exp.expType && exp.member.exp.expType.kind == classType && exp.member.exp.expType._class &&
             exp.member.exp.expType._class.registered && exp.member.exp.expType._class.registered.type == normalClass)
          {
             exp.isConstant = false;
@@ -9135,9 +10006,6 @@ void ProcessExpressionType(Expression exp)
                      char * colon = strstr(param.defaultArg.memberString, "::");
                      if(colon)
                      {
-                        char className[1024];
-                        Class sClass;
-
                         memcpy(thisClassTypeString, param.defaultArg.memberString, colon - param.defaultArg.memberString);
                         thisClassTypeString[colon - param.defaultArg.memberString] = '\0';
                      }
@@ -9152,10 +10020,9 @@ void ProcessExpressionType(Expression exp)
                   {
                      Class expClass = exp.expType._class.registered;
                      Class cClass = null;
-                     int c;
                      int paramCount = 0;
                      int lastParam = -1;
-                     
+
                      char templateString[1024];
                      ClassTemplateParameter param;
                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
@@ -9177,7 +10044,7 @@ void ProcessExpressionType(Expression exp)
                               int p = 0;
                               Class nextClass;
                               for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
-                              
+
                               for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
                               {
                                  if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
@@ -9211,6 +10078,7 @@ void ProcessExpressionType(Expression exp)
                                     Expression exp;
                                     char * string = PrintHexUInt64(arg.expression.ui64);
                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
+                                    delete string;
 
                                     ProcessExpressionType(exp);
                                     ComputeExpression(exp);
@@ -9251,7 +10119,7 @@ void ProcessExpressionType(Expression exp)
                                  lastParam = p;
                               }
                               p++;
-                           }               
+                           }
                         }
                      }
                      {
@@ -9265,10 +10133,12 @@ void ProcessExpressionType(Expression exp)
                         FreeType(exp.expType);
                         exp.expType = ProcessTypeString(templateString, false);
                         FinishTemplatesContext(context);
-                     }                     
+                     }
                   }
 
-                  // *([expType] *)(((byte *)[exp.member.exp]) + [argExp].member.offset)
+                  if(!expMember.expType.isPointerType)
+                     expMember = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), expMember);
+                  // *([expType] *)(((byte *)(uintptr)[exp.member.exp]) + [argExp].member.offset)
                   exp.type = bracketsExp;
                   exp.list = MkListOne(MkExpOp(null, '*',
                   /*opExp;
@@ -9277,16 +10147,17 @@ void ProcessExpressionType(Expression exp)
                   exp.op.exp2 = */
                   MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpBrackets(MkListOne(MkExpOp(
                      MkExpBrackets(MkListOne(
-                        MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), expMember))),
-                           '+',  
-                           MkExpOp(MkExpMember(MkExpMember(argExp, MkIdentifier("member")), MkIdentifier("offset")), 
-                           '+',
-                           MkExpMember(MkExpMember(MkExpMember(CopyExpression(argExp), MkIdentifier("member")), MkIdentifier("_class")), MkIdentifier("offset")))))))
-                           
+                        MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)),
+                           expMember))),
+                              '+',
+                              MkExpOp(MkExpMember(MkExpMember(argExp, MkIdentifier("member")), MkIdentifier("offset")),
+                              '+',
+                              MkExpMember(MkExpMember(MkExpMember(CopyExpression(argExp), MkIdentifier("member")), MkIdentifier("_class")), MkIdentifier("offset")))))))
+
                            ));
                }
             }
-            else if(type.templateParameter && type.templateParameter.type == TemplateParameterType::type && 
+            else if(type.templateParameter && type.templateParameter.type == TemplateParameterType::type &&
                (type.templateParameter.dataType || type.templateParameter.dataTypeString))
             {
                type = ProcessTemplateParameterType(type.templateParameter);
@@ -9295,7 +10166,7 @@ void ProcessExpressionType(Expression exp)
          // TODO: *** This seems to be where we should add method support for all basic types ***
          if(type && (type.kind == templateType));
          else if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType ||
-                          type.kind == int64Type || type.kind == shortType || type.kind == longType || type.kind == charType ||
+                          type.kind == int64Type || type.kind == shortType || type.kind == longType || type.kind == charType || type.kind == _BoolType ||
                           type.kind == intPtrType || type.kind == intSizeType || type.kind == floatType || type.kind == doubleType ||
                           (type.kind == pointerType && type.type.kind == charType)))
          {
@@ -9342,8 +10213,8 @@ void ProcessExpressionType(Expression exp)
 
             if(_class && id)
             {
-               /*bool thisPtr = 
-                  (exp.member.exp.type == identifierExp && 
+               /*bool thisPtr =
+                  (exp.member.exp.type == identifierExp &&
                   !strcmp(exp.member.exp.identifier.string, "this"));*/
                Property prop = null;
                Method method = null;
@@ -9378,28 +10249,39 @@ void ProcessExpressionType(Expression exp)
                   // Prioritize properties over data members otherwise
                   else
                   {
+                     bool useMemberForNonConst = false;
                      // First look for Public Members (Unless class specifier is provided, which skips public priority)
                      if(!id.classSym)
                      {
                         prop = eClass_FindProperty(_class, id.string, null);
-                        if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
+
+                        useMemberForNonConst = prop && exp.destType &&
+                           ( (exp.destType.kind == classType && !exp.destType.constant) || ((exp.destType.kind == pointerType || exp.destType.kind == arrayType) && exp.destType.type && !exp.destType.type.constant) ) &&
+                              !strncmp(prop.dataTypeString, "const ", 6);
+
+                        if(useMemberForNonConst || !id._class || !id._class.name || strcmp(id._class.name, "property"))
                            member = eClass_FindDataMember(_class, id.string, null, null, null);
                      }
 
-                     if(!prop && !member)
+                     if((!prop || useMemberForNonConst) && !member)
                      {
-                        method = eClass_FindMethod(_class, id.string, null);
+                        method = useMemberForNonConst ? null : eClass_FindMethod(_class, id.string, null);
                         if(!method)
                         {
                            prop = eClass_FindProperty(_class, id.string, privateModule);
-                           if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
+
+                           useMemberForNonConst |= prop && exp.destType &&
+                              ( (exp.destType.kind == classType && !exp.destType.constant) || ((exp.destType.kind == pointerType || exp.destType.kind == arrayType) && exp.destType.type && !exp.destType.type.constant) ) &&
+                                 !strncmp(prop.dataTypeString, "const ", 6);
+
+                           if(useMemberForNonConst || !id._class || !id._class.name || strcmp(id._class.name, "property"))
                               member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
                         }
                      }
 
                      if(member && prop)
                      {
-                        if(member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class))
+                        if(useMemberForNonConst || (member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class)))
                            prop = null;
                         else
                            member = null;
@@ -9428,16 +10310,16 @@ void ProcessExpressionType(Expression exp)
 
                         FreeType(classExp.expType);
                         classExp.expType = ProcessTypeString("ecere::com::Class", false);
-                     
+
                         strcpy(structName, "__ecereClassData_");
                         FullClassNameCat(structName, type._class.string, false);
                         exp.type = pointerExp;
                         exp.member.member = id;
 
                         exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
-                           MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), 
+                           MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)),
                               MkExpBrackets(MkListOne(MkExpOp(
-                                 MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)), 
+                                 MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)),
                                     MkExpMember(classExp, MkIdentifier("data"))), '+',
                                        MkExpMember(MkExpClass(MkListOne(MkSpecifierName(type._class.string)), null), MkIdentifier("offsetClass")))))
                                  )));
@@ -9462,14 +10344,42 @@ void ProcessExpressionType(Expression exp)
                      }
                   }
                }
-      
+
+               //if(!exp.member.exp.destType)
+               if(exp.member.exp.destType)
+                  FreeType(exp.member.exp.destType);
+               {
+                  if(method && !method._class.symbol)
+                     method._class.symbol = FindClass(method._class.fullName);
+                  if(prop && !prop._class.symbol)
+                     prop._class.symbol = FindClass(prop._class.fullName);
+
+                  exp.member.exp.destType = Type
+                  {
+                     refCount = 1;
+                     kind = classType;
+                     _class = prop ? prop._class.symbol : method ? method._class.symbol : _class.symbol;
+                     // wasThisClass = type ? type.wasThisClass : false;
+                     thisClassFrom = type ? type.thisClassFrom : null;
+                  };
+               }
+
                if(prop)
                {
                   exp.member.memberType = propertyMember;
                   if(!prop.dataType)
                      ProcessPropertyType(prop);
-                  exp.expType = prop.dataType;                     
-                  if(prop.dataType) prop.dataType.refCount++;
+                  exp.expType = prop.dataType;
+                  if(!strcmp(_class.base.fullName, "eda::Row") && !exp.expType.constant && !exp.destType)
+                  {
+                     Type type { };
+                     CopyTypeInto(type, exp.expType);
+                     type.refCount = 1;
+                     type.constant = true;
+                     exp.expType = type;
+                  }
+                  else if(prop.dataType)
+                     prop.dataType.refCount++;
                }
                else if(member)
                {
@@ -9483,13 +10393,18 @@ void ProcessExpressionType(Expression exp)
                   }
 
                   exp.member.memberType = dataMember;
-                  DeclareStruct(_class.fullName, false);
+                  DeclareStruct(curExternal, _class.fullName, false, true);
+                  if(member._class != _class)
+                     DeclareStruct(curExternal, member._class.fullName, false, true);
+
                   if(!member.dataType)
                   {
                      Context context = SetupTemplatesContext(_class);
                      member.dataType = ProcessTypeString(member.dataTypeString, false);
                      FinishTemplatesContext(context);
                   }
+                  if(exp.member.exp.expType.kind == classType && exp.member.exp.expType._class && exp.member.exp.expType._class.registered && exp.member.exp.expType._class.registered.type == bitClass)
+                     member.dataType.bitMemberSize = ((BitMember)member).size;
                   exp.expType = member.dataType;
                   if(member.dataType) member.dataType.refCount++;
                }
@@ -9537,7 +10452,8 @@ void ProcessExpressionType(Expression exp)
                      FreeExpContents(exp);
                      exp.type = identifierExp;
                      exp.identifier = MkIdentifier("class");
-                     ProcessExpressionType(exp);
+                     FreeType(exp.expType);
+                     exp.expType = MkClassType("ecere::com::Class");
                      return;
                   }
                   yylloc = exp.member.member.loc;
@@ -9550,7 +10466,7 @@ void ProcessExpressionType(Expression exp)
                {
                   Class tClass;
 
-                  tClass = _class;
+                  tClass = type._class && type._class.registered ? type._class.registered : _class;
                   while(tClass && !tClass.templateClass) tClass = tClass.base;
 
                   if(tClass && exp.expType.kind == templateType && exp.expType.templateParameter.type == TemplateParameterType::type)
@@ -9580,10 +10496,34 @@ void ProcessExpressionType(Expression exp)
                      {
                         ClassTemplateArgument arg = tClass.templateArgs[id];
                         Context context = SetupTemplatesContext(tClass);
+                        bool constant = exp.expType.constant;
+                        bool passAsTemplate = false;
+                        Class thisClassFrom = null;
+                        Type t = ProcessTypeString(exp.expType.templateParameter.dataTypeString, false);
+                        if(t && t.kind == classType && t._class)
+                           thisClassFrom = t._class.registered;
+                        else
+                           // Mark that 'thisClassFrom' was set to something
+                           thisClassFrom = eSystem_FindClass(GetPrivateModule(), "class");
+
+                        FreeType(t);
+
+                        passAsTemplate = tClass.templateClass && (exp.expType.kind != templateType ||
+                           (!exp.expType.templateParameter || (!exp.expType.templateParameter.dataTypeString && !exp.expType.templateParameter.dataType)));
+
                         /*if(!arg.dataType)
                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
                         FreeType(exp.expType);
+
                         exp.expType = ProcessTypeString(arg.dataTypeString, false);
+                        exp.expType.thisClassFrom = thisClassFrom;
+                        if(exp.expType.kind == classType && constant) exp.expType.constant = true;
+                        else if(exp.expType.kind == pointerType)
+                        {
+                           Type t = exp.expType.type;
+                           while(t.kind == pointerType) t = t.type;
+                           if(constant) t.constant = constant;
+                        }
                         if(exp.expType)
                         {
                            if(exp.expType.kind == thisClassType)
@@ -9592,12 +10532,20 @@ void ProcessExpressionType(Expression exp)
                               exp.expType = ReplaceThisClassType(_class);
                            }
 
-                           if(tClass.templateClass)
+                           if(passAsTemplate)
                               exp.expType.passAsTemplate = true;
                            //exp.expType.refCount++;
                            if(!exp.destType)
                            {
                               exp.destType = ProcessTypeString(arg.dataTypeString, false);
+                              if(exp.destType.kind == classType && constant) exp.destType.constant = true;
+                              else if(exp.destType.kind == pointerType)
+                              {
+                                 Type t = exp.destType.type;
+                                 while(t.kind == pointerType) t = t.type;
+                                 if(constant) t.constant = constant;
+                              }
+
                               //exp.destType.refCount++;
 
                               if(exp.destType.kind == thisClassType)
@@ -9623,7 +10571,7 @@ void ProcessExpressionType(Expression exp)
                         if(sClass.templateClass) sClass = sClass.templateClass;
                         for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
                         {
-                           if(curParam.type == TemplateParameterType::type && 
+                           if(curParam.type == TemplateParameterType::type &&
                               !strcmp(exp.expType.type.templateParameter.identifier.string, curParam.name))
                            {
                               for(sClass = sClass.base; sClass; sClass = sClass.base)
@@ -9642,7 +10590,7 @@ void ProcessExpressionType(Expression exp)
                         Type basicType;
                         /*if(!arg.dataType)
                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
-                        
+
                         basicType = ProcessTypeString(arg.dataTypeString, false);
                         if(basicType)
                         {
@@ -9656,7 +10604,7 @@ void ProcessExpressionType(Expression exp)
                            if(tClass.templateClass)
                               basicType.passAsTemplate = true;
                            */
-                           
+
                            FreeType(exp.expType);
 
                            exp.expType = Type { refCount = 1, kind = pointerType, type = basicType };
@@ -9692,7 +10640,6 @@ void ProcessExpressionType(Expression exp)
                      if(expClass)
                      {
                         Class cClass = null;
-                        int c;
                         int p = 0;
                         int paramCount = 0;
                         int lastParam = -1;
@@ -9708,7 +10655,6 @@ void ProcessExpressionType(Expression exp)
                            for(param = cClass.templateParams.first; param; param = param.next)
                            {
                               Class cClassCur = null;
-                              int c;
                               int cp = 0;
                               ClassTemplateParameter paramCur = null;
                               ClassTemplateArgument arg;
@@ -9722,7 +10668,7 @@ void ProcessExpressionType(Expression exp)
                                  {
                                     if(!strcmp(paramCur.name, param.name))
                                     {
-                                       
+
                                        break;
                                     }
                                     cp++;
@@ -9752,6 +10698,7 @@ void ProcessExpressionType(Expression exp)
                                        Expression exp;
                                        char * string = PrintHexUInt64(arg.expression.ui64);
                                        exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
+                                       delete string;
 
                                        ProcessExpressionType(exp);
                                        ComputeExpression(exp);
@@ -9781,7 +10728,7 @@ void ProcessExpressionType(Expression exp)
                                     {
                                        strcat(templateString, param.name);
                                        strcat(templateString, " = ");
-                                    }                                       
+                                    }
                                     strcat(templateString, argument);
                                     paramCount++;
                                     lastParam = p;
@@ -9820,7 +10767,7 @@ void ProcessExpressionType(Expression exp)
                   memberType.refCount++;
             }
          }
-         else 
+         else
          {
             char expString[10240];
             expString[0] = '\0';
@@ -9840,7 +10787,7 @@ void ProcessExpressionType(Expression exp)
                   exp.expType = ReplaceThisClassType(_class);
                }
             }
-         }         
+         }
          yylloc = oldyylloc;
          break;
       }
@@ -9875,19 +10822,54 @@ void ProcessExpressionType(Expression exp)
          Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
          if(classSym && classSym.registered)
          {
-            if(classSym.registered.type == noHeadClass)
+            if(classSym.registered.type == noHeadClass || (classSym.registered.fixed && classSym.registered.structSize))
             {
                char name[1024];
+               Class b = classSym.registered;
                name[0] = '\0';
-               DeclareStruct(classSym.string, false);
+               DeclareStruct(curExternal, classSym.string, false, true);
                FreeSpecifier(exp._class);
-               exp.type = typeSizeExp;
                FullClassNameCat(name, classSym.string, false);
-               exp.typeName = MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null);
+
+               if(b.offset == 0)
+               {
+                  exp.type = typeSizeExp;
+                  exp.typeName = MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null);
+               }
+               else
+               {
+                  Expression e;
+                  exp.type = opExp;
+                  if(b.structSize == b.offset)
+                     exp.op.exp1 = MkExpConstant("0");
+                  else
+                     exp.op.exp1 = MkExpTypeSize(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null));
+                  exp.op.op = '+';
+                  e = exp;
+                  while(b.offset != 0)
+                  {
+                     Symbol sym;
+                     Expression typeSize;
+
+                     b = b.base;
+                     sym = FindClass(b.fullName);
+
+                     name[0] = '\0';
+                     DeclareStruct(curExternal, sym.string, false, true);
+                     FullClassNameCat(name, sym.string, false);
+
+                     if(b.structSize == b.offset)
+                        typeSize = MkExpConstant("0");
+                     else
+                        typeSize = MkExpTypeSize(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null));
+                     e.op.exp2 = b.offset ? MkExpOp(typeSize, '+', null) : typeSize;
+                     e = e.op.exp2;
+                  }
+               }
             }
             else
             {
-               if(classSym.registered.fixed)
+               if(classSym.registered.fixed && !classSym.registered.structSize)
                {
                   FreeSpecifier(exp._class);
                   exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
@@ -9898,9 +10880,8 @@ void ProcessExpressionType(Expression exp)
                   char className[1024];
                   strcpy(className, "__ecereClass_");
                   FullClassNameCat(className, classSym.string, true);
-                  MangleClassName(className);
 
-                  DeclareClass(classSym, className);
+                  DeclareClass(curExternal, classSym, className);
 
                   FreeExpContents(exp);
                   exp.type = pointerExp;
@@ -9913,7 +10894,7 @@ void ProcessExpressionType(Expression exp)
          exp.expType = Type
          {
             refCount = 1;
-            kind = intType;
+            kind = intSizeType;
          };
          // exp.isConstant = true;
          break;
@@ -9925,11 +10906,11 @@ void ProcessExpressionType(Expression exp)
          exp.expType = Type
          {
             refCount = 1;
-            kind = intType;
+            kind = intSizeType;
          };
          exp.isConstant = true;
 
-         DeclareType(type, false, false);
+         DeclareType(curExternal, type, true, false);
          FreeType(type);
          break;
       }
@@ -9940,11 +10921,13 @@ void ProcessExpressionType(Expression exp)
          FreeType(exp.cast.exp.destType);
          exp.cast.exp.destType = type;
          type.refCount++;
+         type.casted = true;
          ProcessExpressionType(exp.cast.exp);
+         type.casted = false;
          type.count = 0;
          exp.expType = type;
          //type.refCount++;
-         
+
          // if(!NeedCast(exp.cast.exp.expType, exp.cast.exp.destType))
          if(!exp.cast.exp.needCast && !NeedCast(exp.cast.exp.expType, type))
          {
@@ -9958,7 +10941,7 @@ void ProcessExpressionType(Expression exp)
             //FreeType(exp.destType);
             FreeType(exp.expType);
             FreeTypeName(exp.cast.typeName);
-            
+
             *exp = *castExp;
             FreeType(exp.expType);
             FreeType(exp.destType);
@@ -9997,6 +10980,16 @@ void ProcessExpressionType(Expression exp)
       case conditionExp:
       {
          Expression e;
+         Type t = exp.destType;
+         if(t && !exp.destType.casted)
+         {
+            t = { };
+            CopyTypeInto(t, exp.destType);
+            t.count = 0;
+         }
+         else if(t)
+            t.refCount++;
+
          exp.isConstant = true;
 
          FreeType(exp.cond.cond.destType);
@@ -10010,7 +11003,7 @@ void ProcessExpressionType(Expression exp)
             if(!e.next)
             {
                FreeType(e.destType);
-               e.destType = exp.destType;
+               e.destType = t;
                if(e.destType) e.destType.refCount++;
             }
             ProcessExpressionType(e);
@@ -10028,7 +11021,7 @@ void ProcessExpressionType(Expression exp)
          // exp.cond.elseExp.destType = exp.expType ? exp.expType : exp.destType;
 
          // Reversed it...
-         exp.cond.elseExp.destType = exp.destType ? exp.destType : exp.expType;
+         exp.cond.elseExp.destType = t ? t : exp.expType;
 
          if(exp.cond.elseExp.destType)
             exp.cond.elseExp.destType.refCount++;
@@ -10037,6 +11030,8 @@ void ProcessExpressionType(Expression exp)
          // FIXED THIS: Was done before calling process on elseExp
          if(!exp.cond.elseExp.isConstant)
             exp.isConstant = false;
+
+         FreeType(t);
          break;
       }
       case extensionCompoundExp:
@@ -10091,9 +11086,9 @@ void ProcessExpressionType(Expression exp)
                classExp = MkExpIdentifier(MkIdentifier("class"));
 
             exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
-               MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), 
+               MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)),
                   MkExpBrackets(MkListOne(MkExpOp(
-                     MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)), 
+                     MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)),
                         MkExpMember(classExp, MkIdentifier("data"))), '+',
                            MkExpMember(MkExpClass(MkListOne(MkSpecifierName(_class.fullName)), null), MkIdentifier("offsetClass")))))
                      )));
@@ -10106,7 +11101,7 @@ void ProcessExpressionType(Expression exp)
       case arrayExp:
       {
          Type type = null;
-         char * typeString = null;
+         const char * typeString = null;
          char typeStringBuf[1024];
          if(exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
             exp.destType._class.registered != containerClass && eClass_IsDerived(exp.destType._class.registered, containerClass))
@@ -10127,25 +11122,25 @@ void ProcessExpressionType(Expression exp)
                   else
                   {
                      // if(!MatchType(e.expType, type, null, null, null, false, false, false))
-                     if(!MatchTypeExpression(e, type, null, false))
+                     if(!MatchTypeExpression(e, type, null, false, true))
                      {
                         FreeType(type);
                         type = e.expType;
                         e.expType = null;
-                        
+
                         e = exp.list->first;
                         ProcessExpressionType(e);
                         if(e.expType)
                         {
                            //if(!MatchTypes(e.expType, type, null, null, null, false, false, false))
-                           if(!MatchTypeExpression(e, type, null, false))
+                           if(!MatchTypeExpression(e, type, null, false, true))
                            {
                               FreeType(e.expType);
                               e.expType = null;
                               FreeType(type);
                               type = null;
                               break;
-                           }                           
+                           }
                         }
                      }
                   }
@@ -10190,7 +11185,7 @@ void ProcessExpressionType(Expression exp)
             {
                Expression e;
                type = ProcessTypeString(typeString, false);
-               while(e = exp.list->first)
+               while((e = exp.list->first))
                {
                   exp.list->Remove(e);
                   e.destType = type;
@@ -10201,8 +11196,8 @@ void ProcessExpressionType(Expression exp)
                FreeType(type);
                delete exp.list;
             }
-            
-            DeclareStruct("ecere::com::BuiltInContainer", false);
+
+            DeclareStruct(curExternal, "ecere::com::BuiltInContainer", false, true);
 
             ListAdd(structInitializers, /*MkIdentifier("_vTbl")*/    MkInitializerAssignment(MkExpMember(MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null), MkIdentifier("_vTbl"))));
                ProcessExpressionType(((Initializer)structInitializers->last).exp);
@@ -10268,23 +11263,48 @@ void ProcessExpressionType(Expression exp)
          }
          else
          {
-            NamedLink member;
+            NamedLink64 member;
             for(member = symbol.type.members.first; member; member = member.next)
             {
-               NamedLink value { name = CopyString(member.name) };
+               NamedLink64 value { name = CopyString(member.name) };
                exp.expType.members.Add(value);
             }
          }
       }
    }
 
+   // Trying to do this here before conversion properties kick in and this becomes a new expression... (Fixing Class c; const char * a = c;)
+   // Mark nohead classes as by reference, unless we're casting them to an integral type
+   if(!notByReference && exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
+      exp.expType._class.registered.type == noHeadClass && (!exp.destType ||
+         (exp.destType.kind != intType && exp.destType.kind != int64Type && exp.destType.kind != intPtrType && exp.destType.kind != intSizeType &&
+          exp.destType.kind != longType && exp.destType.kind != shortType && exp.destType.kind != charType && exp.destType.kind != _BoolType)))
+   {
+      exp.byReference = true;
+   }
+
    yylloc = exp.loc;
-   if(exp.destType && (exp.destType.kind == voidType || exp.destType.kind == dummyType) );
+   if(exp.destType && (/*exp.destType.kind == voidType || */exp.destType.kind == dummyType) );
    else if(exp.destType && !exp.destType.keepCast)
    {
-      if(!CheckExpressionType(exp, exp.destType, false))
+      if(!exp.needTemplateCast && exp.expType && (exp.expType.kind == templateType || exp.expType.passAsTemplate)) // && exp.destType && !exp.destType.passAsTemplate)
+         exp.needTemplateCast = 1;
+
+      if(exp.destType.kind == voidType);
+      else if(!CheckExpressionType(exp, exp.destType, false, !exp.destType.casted))
       {
-         if(!exp.destType.count || unresolved)
+         // Warn for casting unrelated types to/from struct classes
+         bool invalidCast = false;
+         if(inCompiler && exp.destType.count && exp.expType)
+         {
+            Class c1 = (exp.expType.kind == classType && exp.expType._class) ? exp.expType._class.registered : null;
+            Class c2 = (exp.destType.kind == classType && exp.destType._class) ? exp.destType._class.registered : null;
+            if(c1 && c1.type != structClass) c1 = null;
+            if(c2 && c2.type != structClass) c2 = null;
+            if((c1 && !exp.expType.byReference && !c2 && !exp.destType.isPointerType) || (c2 && !exp.destType.byReference && !c1 && !exp.expType.isPointerType))
+               invalidCast = true;
+         }
+         if(!exp.destType.count || unresolved || invalidCast)
          {
             if(!exp.expType)
             {
@@ -10333,51 +11353,147 @@ void ProcessExpressionType(Expression exp)
 
                //CheckExpressionType(exp, exp.destType, false);
 
-               if(exp.destType.truth && exp.destType._class && exp.destType._class.registered && !strcmp(exp.destType._class.registered.name, "bool") &&
-                  exp.expType.kind != voidType && exp.expType.kind != structType && exp.expType.kind != unionType && 
-                  (exp.expType.kind != classType || exp.expType.classObjectType || (exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type != structClass)));
-               else
-               {
-                  char expString[10240];
-                  expString[0] = '\0';
-                  if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
+               if(exp.destType.truth && exp.destType._class && exp.destType._class.registered && !strcmp(exp.destType._class.registered.name, "bool") &&
+                  exp.expType.kind != voidType && exp.expType.kind != structType && exp.expType.kind != unionType &&
+                  (exp.expType.kind != classType || exp.expType.classObjectType || (exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type != structClass)));
+               else
+               {
+                  Expression nbExp = GetNonBracketsExp(exp);
+                  bool skipWarning = false;
+                  TypeKind kind = exp.destType.kind;
+                  if(nbExp.type == conditionExp && nbExp.destType && !nbExp.destType.casted && nbExp.destType.kind == exp.destType.kind)
+                     // The if/else operands have already been checked / warned about
+                     skipWarning = true;
+                  if((kind == charType || kind == shortType) && exp.destType.isSigned == exp.expType.signedBeforePromotion && nbExp.type == opExp && nbExp.op.exp1 && nbExp.op.exp2)
+                  {
+                     int op = nbExp.op.op;
+                     Expression nbExp1, nbExp2;
+                     TypeKind from;
+
+                     switch(op)
+                     {
+                        case '%': case '/':
+                           nbExp1 = GetNonBracketsExp(nbExp.op.exp1);
+                           from = nbExp1.expType.promotedFrom;
+                           // Division and Modulo will not take more room than type before promotion
+                           if(from == charType || (kind == shortType && from == shortType))
+                              skipWarning = true;
+                           break;
+                        // Left shift
+                        case LEFT_OP: case RIGHT_OP:
+                           nbExp1 = GetNonBracketsExp(nbExp.op.exp1);
+                           nbExp2 = GetNonBracketsExp(nbExp.op.exp2);
+                           from = nbExp1.expType.promotedFrom;
+                           // Right shift will not take more room than type before promotion
+                           if(op == RIGHT_OP && (from == charType || (kind == shortType && from == shortType)))
+                              skipWarning = true;
+                           else if(nbExp2.isConstant && nbExp2.type == constantExp && (nbExp.op.op == RIGHT_OP || nbExp1.expType.bitMemberSize))
+                           {
+                              int n = (int)strtol(nbExp2.constant, null, 0);
+                              int s = from == charType ? 8 : 16;
+                              // Left shifting a bit member constrained in size may still fit in type before promotion
+                              if(nbExp1.expType.bitMemberSize && nbExp1.expType.bitMemberSize < s)
+                                 s = nbExp1.expType.bitMemberSize;
+
+                              // If right shifted enough things will fit in smaller type
+                              if(nbExp.op.op == RIGHT_OP)
+                                 s -= n;
+                              else
+                                 s += n;
+                              if(s <= (kind == charType ? 8 : 16))
+                                 skipWarning = true;
+                           }
+                           break;
+                        case '-':
+                           if(!exp.destType.isSigned)
+                           {
+                              nbExp1 = GetNonBracketsExp(nbExp.op.exp1);
+                              nbExp2 = GetNonBracketsExp(nbExp.op.exp2);
+                              from = nbExp2.expType.promotedFrom;
+                              // Max value of unsigned type before promotion minus the same will always fit
+                              if((from == charType || from == shortType) && nbExp1.isConstant && nbExp1.type == constantExp)
+                              {
+                                 int n = (int)strtol(nbExp1.constant, null, 0);
+                                 if(n == (from == charType ? 255 : 65535))
+                                    skipWarning = true;
+                              }
+                           }
+                           break;
+                        case '|':
+                        {
+                           TypeKind kind1, kind2;
+                           nbExp1 = GetNonBracketsExp(nbExp.op.exp1);
+                           nbExp2 = GetNonBracketsExp(nbExp.op.exp2);
+                           kind1 = nbExp1.expType.promotedFrom ? nbExp1.expType.promotedFrom : nbExp1.expType.kind;
+                           kind2 = nbExp2.expType.promotedFrom ? nbExp2.expType.promotedFrom : nbExp2.expType.kind;
+                           if(((kind1 == charType || (kind1 == shortType && kind == shortType)) || MatchTypeExpression(nbExp1, exp.destType, null, false, false)) &&
+                              ((kind2 == charType || (kind2 == shortType && kind == shortType)) || MatchTypeExpression(nbExp2, exp.destType, null, false, false)))
+                              skipWarning = true;
+                           break;
+                        }
+                        case '&':
+                        {
+                           TypeKind kind1, kind2;
+                           nbExp1 = GetNonBracketsExp(nbExp.op.exp1);
+                           nbExp2 = GetNonBracketsExp(nbExp.op.exp2);
+                           kind1 = nbExp1.expType.promotedFrom ? nbExp1.expType.promotedFrom : nbExp1.expType.kind;
+                           kind2 = nbExp2.expType.promotedFrom ? nbExp2.expType.promotedFrom : nbExp2.expType.kind;
+                           if(((kind1 == charType || (kind1 == shortType && kind == shortType)) || MatchTypeExpression(nbExp1, exp.destType, null, false, false)) ||
+                              ((kind2 == charType || (kind2 == shortType && kind == shortType)) || MatchTypeExpression(nbExp2, exp.destType, null, false, false)))
+                              skipWarning = true;
+                           break;
+                        }
+                     }
+                  }
+
+                  if(!skipWarning)
+                  {
+                     char expString[10240];
+                     expString[0] = '\0';
+                     if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
 
 #ifdef _DEBUG
-                  CheckExpressionType(exp, exp.destType, false);
+                     CheckExpressionType(exp, exp.destType, false, true);
 #endif
-                  // Flex & Bison generate code that triggers this, so we ignore it for a quiet sdk build:
-                  if(!sourceFile || (strcmp(sourceFile, "src\\lexer.ec") && strcmp(sourceFile, "src/lexer.ec") && strcmp(sourceFile, "src\\grammar.ec") && strcmp(sourceFile, "src/grammar.ec")))
-                     Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
+
+                     // Flex & Bison generate code that triggers this, so we ignore it for a quiet sdk build:
+                     if(!sourceFile || (!strstr(sourceFile, "src\\lexer.ec") && !strstr(sourceFile, "src/lexer.ec") &&
+                                        !strstr(sourceFile, "src\\grammar.ec") && !strstr(sourceFile, "src/grammar.ec") &&
+                                        !strstr(sourceFile, "src\\type.ec") && !strstr(sourceFile, "src/type.ec") &&
+                                        !strstr(sourceFile, "src\\expression.ec") && !strstr(sourceFile, "src/expression.ec")))
+                     {
+                        if(invalidCast)
+                           Compiler_Error($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
+                        else
+                           Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
+                     }
+                  }
 
                   // TO CHECK: FORCING HERE TO HELP DEBUGGER
-                  FreeType(exp.expType);
-                  exp.destType.refCount++;
-                  exp.expType = exp.destType;
+                  if(!inCompiler)
+                  {
+                     FreeType(exp.expType);
+                     exp.destType.refCount++;
+                     exp.expType = exp.destType;
+                  }
                }
             }
          }
       }
-      else if(exp.destType && exp.destType.kind == ellipsisType && exp.expType && exp.expType.passAsTemplate)
+      // Cast function pointers to void * as eC already checked compatibility
+      else if(exp.destType && exp.destType.kind == pointerType && exp.destType.type && exp.destType.type.kind == functionType &&
+              exp.expType && (exp.expType.kind == functionType || exp.expType.kind == methodType))
       {
-         Expression newExp { };
-         char typeString[1024];
-         OldList * specs = MkList();
-         Declarator decl;
-
-         typeString[0] = '\0';
-
-         *newExp = *exp;
-
-         if(exp.expType)  exp.expType.refCount++;
-         if(exp.expType)  exp.expType.refCount++;
-         exp.type = castExp;
-         newExp.destType = exp.expType;
-
-         PrintType(exp.expType, typeString, false, false);
-         decl = SpecDeclFromString(typeString, specs, null);
-         
-         exp.cast.typeName = MkTypeName(specs, decl);
-         exp.cast.exp = newExp;
+         Expression nbExp = GetNonBracketsExp(exp);
+         if(nbExp.type != castExp || !IsVoidPtrCast(nbExp.cast.typeName))
+         {
+            Expression e = MoveExpContents(exp);
+            exp.cast.exp = MkExpBrackets(MkListOne(e));
+            exp.type = castExp;
+            exp.cast.exp.destType = exp.destType;
+            if(exp.destType) exp.destType.refCount++;
+            exp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null));
+         }
       }
    }
    else if(unresolved)
@@ -10401,9 +11517,9 @@ void ProcessExpressionType(Expression exp)
 
    // Mark nohead classes as by reference, unless we're casting them to an integral type
    if(!notByReference && exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
-      exp.expType._class.registered.type == noHeadClass && (!exp.destType || 
-         (exp.destType.kind != intType && exp.destType.kind != int64Type && exp.destType.kind != intPtrType && exp.destType.kind != intSizeType && 
-          exp.destType.kind != longType && exp.destType.kind != shortType && exp.destType.kind != charType)))
+      exp.expType._class.registered.type == noHeadClass && (!exp.destType ||
+         (exp.destType.kind != intType && exp.destType.kind != int64Type && exp.destType.kind != intPtrType && exp.destType.kind != intSizeType &&
+          exp.destType.kind != longType && exp.destType.kind != shortType && exp.destType.kind != charType && exp.destType.kind != _BoolType)))
    {
       exp.byReference = true;
    }
@@ -10413,7 +11529,7 @@ void ProcessExpressionType(Expression exp)
 static void FindNextDataMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
 {
    // THIS CODE WILL FIND NEXT MEMBER...
-   if(*curMember) 
+   if(*curMember)
    {
       *curMember = (*curMember).next;
 
@@ -10435,7 +11551,7 @@ static void FindNextDataMember(Class _class, Class * curClass, DataMember * curM
 
             *curMember = (*curMember).members.first;
             while(*curMember && (*curMember).isProperty)
-               *curMember = (*curMember).next;                     
+               *curMember = (*curMember).next;
          }
       }
    }
@@ -10468,7 +11584,7 @@ static void FindNextDataMember(Class _class, Class * curClass, DataMember * curM
 
                *curMember = (*curMember).members.first;
                while(*curMember && (*curMember).isProperty)
-                  *curMember = (*curMember).next;                     
+                  *curMember = (*curMember).next;
             }
          }
       }
@@ -10571,7 +11687,7 @@ static void ProcessInitializer(Initializer init, Type type)
    }
 }
 
-static void ProcessSpecifier(Specifier spec, bool declareStruct)
+static void ProcessSpecifier(Specifier spec, bool declareStruct, bool warnClasses)
 {
    switch(spec.type)
    {
@@ -10584,7 +11700,7 @@ static void ProcessSpecifier(Specifier spec, bool declareStruct)
                spec.type = nameSpecifier;
                spec.name = ReplaceThisClass(thisClass);
                spec.symbol = FindClass(spec.name);
-               ProcessSpecifier(spec, declareStruct);
+               ProcessSpecifier(spec, declareStruct, false);
             }
          }
          break;
@@ -10593,9 +11709,14 @@ static void ProcessSpecifier(Specifier spec, bool declareStruct)
       {
          Symbol symbol = FindType(curContext, spec.name);
          if(symbol)
-            DeclareType(symbol.type, true, true);
-         else if((symbol = spec.symbol /*FindClass(spec.name)*/) && symbol.registered && symbol.registered.type == structClass && declareStruct)
-            DeclareStruct(spec.name, false);
+            DeclareType(curExternal, symbol.type, true, true);
+         else if(spec.symbol /*&& declareStruct*/)
+         {
+            Class c = spec.symbol.registered;
+            if(warnClasses && !c)
+               Compiler_Warning("Undeclared class %s\n", spec.name);
+            DeclareStruct(curExternal, spec.name, c && c.type == noHeadClass, declareStruct && c && c.type == structClass);
+         }
          break;
       }
       case enumSpecifier:
@@ -10609,14 +11730,16 @@ static void ProcessSpecifier(Specifier spec, bool declareStruct)
                   ProcessExpressionType(e.exp);
             }
          }
-         break;
+         // Fall through for IDE type processing
+         if(inCompiler)
+            break;
       }
       case structSpecifier:
       case unionSpecifier:
       {
          if(spec.definitions)
          {
-            ClassDef def;
+            //ClassDef def;
             Symbol symbol = spec.id ? FindClass(spec.id.string) : null;
             //if(symbol)
                ProcessClass(spec.definitions, symbol);
@@ -10636,7 +11759,7 @@ static void ProcessSpecifier(Specifier spec, bool declareStruct)
       {
          Symbol classSym = FindClass(spec.name);
          if(classSym && classSym.registered && classSym.registered.type == structClass)
-            DeclareStruct(spec.name, false);
+            DeclareStruct(spec.name, false, true);
          break;
       }
       */
@@ -10644,7 +11767,7 @@ static void ProcessSpecifier(Specifier spec, bool declareStruct)
 }
 
 
-static void ProcessDeclarator(Declarator decl)
+static void ProcessDeclarator(Declarator decl, bool isFunction)
 {
    switch(decl.type)
    {
@@ -10664,80 +11787,116 @@ static void ProcessDeclarator(Declarator decl)
       case pointerDeclarator:
       case extendedDeclarator:
       case extendedDeclaratorEnd:
-         if(decl.declarator)
-            ProcessDeclarator(decl.declarator);
+      {
+         Identifier id = null;
+         Specifier classSpec = null;
          if(decl.type == functionDeclarator)
          {
-            Identifier id = GetDeclId(decl);
+            id = GetDeclId(decl);
             if(id && id._class)
             {
+               classSpec = id._class;
+               id._class = null;
+            }
+         }
+         if(decl.declarator)
+            ProcessDeclarator(decl.declarator, isFunction);
+         if(decl.type == functionDeclarator)
+         {
+            if(classSpec)
+            {
                TypeName param
                {
-                  qualifiers = MkListOne(id._class);
+                  qualifiers = MkListOne(classSpec);
                   declarator = null;
                };
                if(!decl.function.parameters)
-                  decl.function.parameters = MkList();               
+                  decl.function.parameters = MkList();
                decl.function.parameters->Insert(null, param);
-               id._class = null;
             }
             if(decl.function.parameters)
             {
                TypeName param;
-               
+
                for(param = decl.function.parameters->first; param; param = param.next)
                {
-                  if(param.qualifiers && param.qualifiers->first)
+                  if(param.qualifiers)
                   {
-                     Specifier spec = param.qualifiers->first;
-                     if(spec && spec.specifier == TYPED_OBJECT)
+                     Specifier spec;
+                     for(spec = param.qualifiers->first; spec; spec = spec.next)
                      {
-                        Declarator d = param.declarator;
-                        TypeName newParam
+                        if(spec.type == baseSpecifier)
                         {
-                           qualifiers = MkListOne(MkSpecifier(VOID));
-                           declarator = MkDeclaratorPointer(MkPointer(null,null), d);
-                        };
-                        
-                        FreeList(param.qualifiers, FreeSpecifier);
+                           if(spec.specifier == TYPED_OBJECT)
+                           {
+                              Declarator d = param.declarator;
+                              TypeName newParam
+                              {
+                                 qualifiers = MkListOne(MkSpecifier(VOID));
+                                 declarator = MkDeclaratorPointer(MkPointer(null,null), d);
+                              };
+                              if(!d || d.type != pointerDeclarator)
+                                 newParam.qualifiers->Insert(null, MkSpecifier(CONST));
 
-                        param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
-                        param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
+                              FreeList(param.qualifiers, FreeSpecifier);
 
-                        decl.function.parameters->Insert(param, newParam);
-                        param = newParam;
-                     }
-                     else if(spec && spec.specifier == ANY_OBJECT)
-                     {
-                        Declarator d = param.declarator;
-                        
-                        FreeList(param.qualifiers, FreeSpecifier);
+                              param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
+                              param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
 
-                        param.qualifiers = MkListOne(MkSpecifier(VOID));
-                        param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);                        
-                     }
-                     else if(spec.specifier == THISCLASS)
-                     {
-                        if(thisClass)
+                              DeclareStruct(curExternal, "ecere::com::Class", false, true);
+
+                              decl.function.parameters->Insert(param, newParam);
+                              param = newParam;
+                              break;
+                           }
+                           else if(spec.specifier == ANY_OBJECT)
+                           {
+                              Declarator d = param.declarator;
+
+                              FreeList(param.qualifiers, FreeSpecifier);
+
+                              param.qualifiers = MkListOne(MkSpecifier(VOID));
+                              if(!d || d.type != pointerDeclarator)
+                                 param.qualifiers->Insert(null, MkSpecifier(CONST));
+                              param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);
+                              break;
+                           }
+                           else if(spec.specifier == THISCLASS)
+                           {
+                              if(thisClass)
+                              {
+                                 spec.type = nameSpecifier;
+                                 spec.name = ReplaceThisClass(thisClass);
+                                 spec.symbol = FindClass(spec.name);
+                                 ProcessSpecifier(spec, false, false);
+                              }
+                              break;
+                           }
+                        }
+                        else if(spec.type == nameSpecifier)
+                        {
+                           ProcessSpecifier(spec, isFunction, true);
+                        }
+                        else if((spec.type == structSpecifier || spec.type == unionSpecifier) && !spec.definitions && spec.id && spec.id.string)
                         {
-                           spec.type = nameSpecifier;
-                           spec.name = ReplaceThisClass(thisClass);
-                           spec.symbol = FindClass(spec.name);
-                           ProcessSpecifier(spec, false);
+                           Declarator d = param.declarator;
+                           if(!d || d.type != pointerDeclarator)
+                              DeclareStruct(curExternal, spec.id.string, false, true);
                         }
                      }
                   }
 
                   if(param.declarator)
-                     ProcessDeclarator(param.declarator);
+                     ProcessDeclarator(param.declarator, false);
                }
             }
          }
          break;
+      }
    }
 }
 
-static void ProcessDeclaration(Declaration decl)
+static void ProcessDeclaration(Declaration decl, bool warnClasses)
 {
    yylloc = decl.loc;
    switch(decl.type)
@@ -10753,11 +11912,11 @@ static void ProcessDeclaration(Declaration decl)
          if(decl.declarators)
          {
             InitDeclarator d;
-         
+
             for(d = decl.declarators->first; d; d = d.next)
             {
                Type type, subType;
-               ProcessDeclarator(d.declarator);
+               ProcessDeclarator(d.declarator, false);
 
                type = ProcessType(decl.specifiers, d.declarator);
 
@@ -10765,17 +11924,17 @@ static void ProcessDeclaration(Declaration decl)
                {
                   ProcessInitializer(d.initializer, type);
 
-                  // Change "ColorRGB a = ColorRGB { 1,2,3 } => ColorRGB a { 1,2,3 }                  
-                  
+                  // Change "ColorRGB a = ColorRGB { 1,2,3 } => ColorRGB a { 1,2,3 }
+
                   if(decl.declarators->count == 1 && d.initializer.type == expInitializer &&
                      d.initializer.exp.type == instanceExp)
                   {
-                     if(type.kind == classType && type._class == 
+                     if(type.kind == classType && type._class ==
                         d.initializer.exp.expType._class)
                      {
                         Instantiation inst = d.initializer.exp.instance;
                         inst.exp = MkExpIdentifier(CopyIdentifier(GetDeclId(d.declarator)));
-                        
+
                         d.initializer.exp.instance = null;
                         if(decl.specifiers)
                            FreeList(decl.specifiers, FreeSpecifier);
@@ -10813,7 +11972,7 @@ static void ProcessDeclaration(Declaration decl)
             Specifier s;
             for(s = decl.specifiers->first; s; s = s.next)
             {
-               ProcessSpecifier(s, declareStruct);
+               ProcessSpecifier(s, declareStruct, true);
             }
          }
          break;
@@ -10835,7 +11994,7 @@ static void ProcessDeclaration(Declaration decl)
             {
                Type type = ProcessType(decl.specifiers, d.declarator);
                Type subType;
-               ProcessDeclarator(d);
+               ProcessDeclarator(d, false);
                for(subType = type; subType;)
                {
                   if(subType.kind == classType)
@@ -10856,7 +12015,7 @@ static void ProcessDeclaration(Declaration decl)
          if(decl.specifiers)
          {
             for(spec = decl.specifiers->first; spec; spec = spec.next)
-               ProcessSpecifier(spec, declareStruct);
+               ProcessSpecifier(spec, declareStruct, warnClasses);
          }
          break;
       }
@@ -10871,22 +12030,18 @@ static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
    char getName[1024], setName[1024];
    OldList * args;
 
-   DeclareProperty(prop, setName, getName);
+   DeclareProperty(curExternal, prop, setName, getName);
 
    // eInstance_FireWatchers(object, prop);
    strcpy(propName, "__ecereProp_");
    FullClassNameCat(propName, prop._class.fullName, false);
    strcat(propName, "_");
-   // strcat(propName, prop.name);
    FullClassNameCat(propName, prop.name, true);
-   MangleClassName(propName);
 
    strcpy(propNameM, "__ecerePropM_");
    FullClassNameCat(propNameM, prop._class.fullName, false);
    strcat(propNameM, "_");
-   // strcat(propNameM, prop.name);
    FullClassNameCat(propNameM, prop.name, true);
-   MangleClassName(propNameM);
 
    if(prop.isWatchable)
    {
@@ -10899,9 +12054,10 @@ static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
+
+      DeclareFunctionUtil(curExternal, "eInstance_FireWatchers");
    }
 
-   
    {
       args = MkList();
       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
@@ -10912,9 +12068,11 @@ static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
+
+      DeclareFunctionUtil(curExternal, "eInstance_FireSelfWatchers");
    }
-   
-   if(curFunction.propSet && !strcmp(curFunction.propSet.string, prop.name) && 
+
+   if(curFunction.propSet && !strcmp(curFunction.propSet.string, prop.name) &&
       (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
       curFunction.propSet.fireWatchersDone = true;
 }
@@ -10955,15 +12113,13 @@ static void ProcessStatement(Statement stmt)
             Context prevContext = curContext;
 
             if(!stmt.compound.isSwitch)
-            {
                curCompound = stmt;
-               curContext = stmt.compound.context;
-            }
+            curContext = stmt.compound.context;
 
             if(stmt.compound.declarations)
             {
                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
-                  ProcessDeclaration(decl);
+                  ProcessDeclaration(decl, true);
             }
             if(stmt.compound.statements)
             {
@@ -11105,11 +12261,11 @@ static void ProcessStatement(Statement stmt)
          char iteratorType[1024];
          Type source;
          Expression e;
-         bool isBuiltin = exp && exp->last && 
-            (((Expression)exp->last).type == ExpressionType::arrayExp || 
+         bool isBuiltin = exp && exp->last &&
+            (((Expression)exp->last).type == ExpressionType::arrayExp ||
               (((Expression)exp->last).type == castExp && ((Expression)exp->last).cast.exp.type == ExpressionType::arrayExp));
          Expression arrayExp;
-         char * typeString = null;
+         const char * typeString = null;
          int builtinCount = 0;
 
          for(e = exp ? exp->first : null; e; e = e.next)
@@ -11130,51 +12286,55 @@ static void ProcessStatement(Statement stmt)
             Class _class = source ? source._class.registered : null;
             Symbol symbol;
             Expression expIt = null;
-            bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false, isAVLTree = false;
+            bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false; //, isAVLTree = false;
             Class arrayClass = eSystem_FindClass(privateModule, "Array");
             Class linkListClass = eSystem_FindClass(privateModule, "LinkList");
             Class customAVLTreeClass = eSystem_FindClass(privateModule, "CustomAVLTree");
-            stmt.type = compoundStmt;
-            
-            stmt.compound.context = Context { };
-            stmt.compound.context.parent = curContext;
-            curContext = stmt.compound.context;
+
+            if(inCompiler)
+            {
+               stmt.type = compoundStmt;
+
+               stmt.compound.context = Context { };
+               stmt.compound.context.parent = curContext;
+               curContext = stmt.compound.context;
+            }
 
             if(source && eClass_IsDerived(source._class.registered, customAVLTreeClass))
             {
                Class mapClass = eSystem_FindClass(privateModule, "Map");
-               Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
+               //Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
                isCustomAVLTree = true;
-               if(eClass_IsDerived(source._class.registered, avlTreeClass))
+               /*if(eClass_IsDerived(source._class.registered, avlTreeClass))
                   isAVLTree = true;
-               else if(eClass_IsDerived(source._class.registered, mapClass))
+               else */if(eClass_IsDerived(source._class.registered, mapClass))
                   isMap = true;
             }
             else if(source && eClass_IsDerived(source._class.registered, arrayClass)) isArray = true;
-            else if(source && eClass_IsDerived(source._class.registered, linkListClass)) 
+            else if(source && eClass_IsDerived(source._class.registered, linkListClass))
             {
                Class listClass = eSystem_FindClass(privateModule, "List");
                isLinkList = true;
                isList = eClass_IsDerived(source._class.registered, listClass);
             }
 
-            if(isArray)
+            if(inCompiler && isArray)
             {
                Declarator decl;
                OldList * specs = MkList();
-               decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
+               decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs,
                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
                stmt.compound.declarations = MkListOne(
                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
-                  MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalArray")), 
+                  MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalArray")),
                      MkInitializerAssignment(MkExpBrackets(exp))))));
             }
             else if(isBuiltin)
             {
                Type type = null;
                char typeStringBuf[1024];
-               
+
                // TODO: Merge this code?
                arrayExp = (((Expression)exp->last).type == ExpressionType::arrayExp) ? (Expression)exp->last : ((Expression)exp->last).cast.exp;
                if(((Expression)exp->last).type == castExp)
@@ -11204,25 +12364,25 @@ static void ProcessStatement(Statement stmt)
                         else
                         {
                            // if(!MatchType(e.expType, type, null, null, null, false, false, false))
-                           if(!MatchTypeExpression(e, type, null, false))
+                           if(!MatchTypeExpression(e, type, null, false, true))
                            {
                               FreeType(type);
                               type = e.expType;
                               e.expType = null;
-                              
+
                               e = arrayExp.list->first;
                               ProcessExpressionType(e);
                               if(e.expType)
                               {
                                  //if(!MatchTypes(e.expType, type, null, null, null, false, false, false, false))
-                                 if(!MatchTypeExpression(e, type, null, false))
+                                 if(!MatchTypeExpression(e, type, null, false, true))
                                  {
                                     FreeType(e.expType);
                                     e.expType = null;
                                     FreeType(type);
                                     type = null;
                                     break;
-                                 }                           
+                                 }
                               }
                            }
                         }
@@ -11243,35 +12403,52 @@ static void ProcessStatement(Statement stmt)
                }
                if(typeString)
                {
-                  OldList * initializers = MkList();
-                  Declarator decl;
-                  OldList * specs = MkList();
-                  if(arrayExp.list)
+                  if(inCompiler)
                   {
-                     Expression e;
+                     OldList * initializers = MkList();
+                     Declarator decl;
+                     OldList * specs = MkList();
+                     if(arrayExp.list)
+                     {
+                        Expression e;
+
+                        builtinCount = arrayExp.list->count;
+                        type = ProcessTypeString(typeString, false);
+                        while((e = arrayExp.list->first))
+                        {
+                           arrayExp.list->Remove(e);
+                           e.destType = type;
+                           type.refCount++;
+                           ProcessExpressionType(e);
+                           if(inCompiler)
+                              ListAdd(initializers, MkInitializerAssignment(e));
+                        }
+                        FreeType(type);
+                        delete arrayExp.list;
+                     }
+                     decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
 
-                     builtinCount = arrayExp.list->count;
+                     stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier),
+                        MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
+
+                     ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(
+                        PlugDeclarator(
+                           /*CopyDeclarator(*/decl/*)*/, MkDeclaratorArray(MkDeclaratorIdentifier(MkIdentifier("__internalArray")), null)
+                           ), MkInitializerList(initializers)))));
+                     FreeList(exp, FreeExpression);
+                  }
+                  else if(arrayExp.list)
+                  {
+                     Expression e;
                      type = ProcessTypeString(typeString, false);
-                     while(e = arrayExp.list->first)
+                     for(e = arrayExp.list->first; e; e = e.next)
                      {
-                        arrayExp.list->Remove(e);
                         e.destType = type;
                         type.refCount++;
                         ProcessExpressionType(e);
-                        ListAdd(initializers, MkInitializerAssignment(e));
                      }
                      FreeType(type);
-                     delete arrayExp.list;
                   }
-                  decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
-                  stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier), 
-                     MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
-
-                  ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(
-                     PlugDeclarator(
-                        /*CopyDeclarator(*/decl/*)*/, MkDeclaratorArray(MkDeclaratorIdentifier(MkIdentifier("__internalArray")), null)
-                        ), MkInitializerList(initializers)))));
-                  FreeList(exp, FreeExpression);
                }
                else
                {
@@ -11283,23 +12460,23 @@ static void ProcessStatement(Statement stmt)
                Declarator decl;
                OldList * specs = MkList();
 
-               decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, 
+               decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs,
                   MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
                stmt.compound.declarations = MkListOne(
                   MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName("BuiltInContainer")),
-                  MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), 
+                  MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("__internalArray"))),
                      MkInitializerAssignment(MkExpBrackets(exp))))));
                */
             }
-            else if(isLinkList && !isList)
+            else if(inCompiler && isLinkList && !isList)
             {
                Declarator decl;
                OldList * specs = MkList();
                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
-                  MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalLinkList")), 
+                  MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalLinkList")),
                      MkInitializerAssignment(MkExpBrackets(exp))))));
             }
             /*else if(isCustomAVLTree)
@@ -11309,10 +12486,10 @@ static void ProcessStatement(Statement stmt)
                decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
                stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
                ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
-                  MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalTree")), 
+                  MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalTree")),
                      MkInitializerAssignment(MkExpBrackets(exp))))));
             }*/
-            else if(_class.templateArgs)
+            else if(inCompiler && _class.templateArgs)
             {
                if(isMap)
                   sprintf(iteratorType, "MapIterator<%s, %s >", _class.templateArgs[5].dataTypeString, _class.templateArgs[6].dataTypeString);
@@ -11321,115 +12498,169 @@ static void ProcessStatement(Statement stmt)
 
                stmt.compound.declarations = MkListOne(
                   MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName(iteratorType)),
-                  MkExpIdentifier(id), MkListOne(MkMembersInitList(MkListOne(MkMemberInit(isMap ? MkListOne(MkIdentifier("map")) : null, 
+                  MkExpIdentifier(id), MkListOne(MkMembersInitList(MkListOne(MkMemberInit(isMap ? MkListOne(MkIdentifier("map")) : null,
                   MkInitializerAssignment(MkExpBrackets(exp)))))))));
             }
-            symbol = FindSymbol(id.string, curContext, curContext, false, false);
-
-            if(block && block.type == compoundStmt && block.compound.context)
-            {
-               block.compound.context.parent = stmt.compound.context;
-            }
-            if(filter)
-            {
-               block = MkIfStmt(filter, block, null);
-            }
-            if(isArray)
-            {
-               stmt.compound.statements = MkListOne(MkForStmt(
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
-                     MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
-                  MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
-                  block));
-              ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
-              ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
-              ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
-            }
-            else if(isBuiltin)
+            if(inCompiler)
             {
-               char count[128];
-               //OldList * specs = MkList();
-               // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
+               symbol = FindSymbol(id.string, curContext, curContext, false, false);
 
-               sprintf(count, "%d", builtinCount);
-
-               stmt.compound.statements = MkListOne(MkForStmt(
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
-                     MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
-                  MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
-                  block));
+               if(block)
+               {
+                  // Reparent sub-contexts in this statement
+                  switch(block.type)
+                  {
+                     case compoundStmt:
+                        if(block.compound.context)
+                           block.compound.context.parent = stmt.compound.context;
+                        break;
+                     case ifStmt:
+                        if(block.ifStmt.stmt && block.ifStmt.stmt.type == compoundStmt && block.ifStmt.stmt.compound.context)
+                           block.ifStmt.stmt.compound.context.parent = stmt.compound.context;
+                        if(block.ifStmt.elseStmt && block.ifStmt.elseStmt.type == compoundStmt && block.ifStmt.elseStmt.compound.context)
+                           block.ifStmt.elseStmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     case switchStmt:
+                        if(block.switchStmt.stmt && block.switchStmt.stmt.type == compoundStmt && block.switchStmt.stmt.compound.context)
+                           block.switchStmt.stmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     case whileStmt:
+                        if(block.whileStmt.stmt && block.whileStmt.stmt.type == compoundStmt && block.whileStmt.stmt.compound.context)
+                           block.whileStmt.stmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     case doWhileStmt:
+                        if(block.doWhile.stmt && block.doWhile.stmt.type == compoundStmt && block.doWhile.stmt.compound.context)
+                           block.doWhile.stmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     case forStmt:
+                        if(block.forStmt.stmt && block.forStmt.stmt.type == compoundStmt && block.forStmt.stmt.compound.context)
+                           block.forStmt.stmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     case forEachStmt:
+                        if(block.forEachStmt.stmt && block.forEachStmt.stmt.type == compoundStmt && block.forEachStmt.stmt.compound.context)
+                           block.forEachStmt.stmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     /* Only handle those with compound blocks for now... (Potential limitation on compound statements within expressions)
+                     case labeledStmt:
+                     case caseStmt
+                     case expressionStmt:
+                     case gotoStmt:
+                     case continueStmt:
+                     case breakStmt
+                     case returnStmt:
+                     case asmStmt:
+                     case badDeclarationStmt:
+                     case fireWatchersStmt:
+                     case stopWatchingStmt:
+                     case watchStmt:
+                     */
+                  }
+               }
 
-               /*
-               Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
-               stmt.compound.statements = MkListOne(MkForStmt(
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<', 
-                     MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
-                  MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
-                  block));
-              */
-              ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
-              ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
-              ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
-            }
-            else if(isLinkList && !isList)
-            {
-               Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
-               Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
-               if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString && 
-                  !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
+               if(filter)
+               {
+                  block = MkIfStmt(filter, block, null);
+               }
+               if(isArray)
                {
                   stmt.compound.statements = MkListOne(MkForStmt(
-                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
-                     MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
-                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
+                        MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
+                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
                      block));
+                 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
+                 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
+                 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
                }
-               else
+               else if(isBuiltin)
                {
-                  OldList * specs = MkList();
-                  Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
+                  char count[128];
+                  //OldList * specs = MkList();
+                  // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
+
+                  sprintf(count, "%d", builtinCount);
+
                   stmt.compound.statements = MkListOne(MkForStmt(
-                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
-                     MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
-                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
-                        MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
-                           MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
+                        MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
+                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
+                     block));
+
+                  /*
+                  Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
+                  stmt.compound.statements = MkListOne(MkForStmt(
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
+                        MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
+                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
                      block));
+                 */
+                 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
+                 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
+                 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
                }
-               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
-               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
-               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
-            }
-            /*else if(isCustomAVLTree)
-            {
-               stmt.compound.statements = MkListOne(MkForStmt(
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
-                     MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
-                  MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
-                  MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
-                  block));
+               else if(isLinkList && !isList)
+               {
+                  Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
+                  Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
+                  if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString &&
+                     !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
+                  {
+                     stmt.compound.statements = MkListOne(MkForStmt(
+                        MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
+                        MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
+                        MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
+                        block));
+                  }
+                  else
+                  {
+                     OldList * specs = MkList();
+                     Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
+                     stmt.compound.statements = MkListOne(MkForStmt(
+                        MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
+                        MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
+                        MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
+                           MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
+                              MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
+                        block));
+                  }
+                  ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
+                  ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
+                  ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
+               }
+               /*else if(isCustomAVLTree)
+               {
+                  stmt.compound.statements = MkListOne(MkForStmt(
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
+                        MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
+                     MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
+                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
+                     block));
 
-               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
-               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
-               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
-            }*/
-            else
-            {
-               stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
-                  MkIdentifier("Next")), null)), block));
-            }
-            ProcessExpressionType(expIt);
-            if(stmt.compound.declarations->first)
-               ProcessDeclaration(stmt.compound.declarations->first);
+                  ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
+                  ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
+                  ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
+               }*/
+               else
+               {
+                  stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
+                     MkIdentifier("Next")), null)), block));
+               }
+               ProcessExpressionType(expIt);
+               if(stmt.compound.declarations->first)
+                  ProcessDeclaration(stmt.compound.declarations->first, true);
 
-            if(symbol) 
-               symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
+               if(symbol)
+                  symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
 
-            ProcessStatement(stmt);
-            curContext = stmt.compound.context.parent;
+               ProcessStatement(stmt);
+            }
+            else
+               ProcessStatement(stmt.forEachStmt.stmt);
+            if(inCompiler)
+               curContext = stmt.compound.context.parent;
             break;
          }
          else
@@ -11457,6 +12688,7 @@ static void ProcessStatement(Statement stmt)
                      curFunction.type = ProcessType(
                         curFunction.specifiers, curFunction.declarator);
                   FreeType(exp.destType);
+                  // TODO: current property if not compiling
                   exp.destType = (curFunction && curFunction.type && curFunction.type.kind == functionType) ? curFunction.type.returnType : null;
                   if(exp.destType) exp.destType.refCount++;
                }
@@ -11467,7 +12699,7 @@ static void ProcessStatement(Statement stmt)
       }
       case badDeclarationStmt:
       {
-         ProcessDeclaration(stmt.decl);
+         ProcessDeclaration(stmt.decl, true);
          break;
       }
       case asmStmt:
@@ -11516,20 +12748,14 @@ static void ProcessStatement(Statement stmt)
                stmt.type = expressionStmt;
                stmt.expressions = MkList();
 
-               curExternal = external.prev;
-
                for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
                {
                   ClassFunction func;
                   char watcherName[1024];
-                  Class watcherClass = watcher ? 
+                  Class watcherClass = watcher ?
                      ((watcher.expType && watcher.expType.kind == classType && watcher.expType._class) ? watcher.expType._class.registered : null) : thisClass;
                   External createdExternal;
 
-                  // Create a declaration above
-                  External externalDecl = MkExternalDeclaration(null);
-                  ast->Insert(curExternal.prev, externalDecl);
-
                   sprintf(watcherName,"__ecerePropertyWatcher_%d", propWatcherID++);
                   if(propWatch.deleteWatch)
                      strcat(watcherName, "_delete");
@@ -11545,33 +12771,18 @@ static void ProcessStatement(Statement stmt)
 
                   if(object && object.expType && object.expType.kind == classType && object.expType._class && object.expType._class.registered)
                   {
-                     // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
                      func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)),
-                        //MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null))), null);
                         MkListOne(MkTypeName(MkListOne(MkSpecifierName(object.expType._class.string)), MkDeclaratorIdentifier(MkIdentifier("value"))))), null);
                      ProcessClassFunctionBody(func, propWatch.compound);
                      propWatch.compound = null;
 
-                     //afterExternal = afterExternal ? afterExternal : curExternal;
-
-                     //createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal.prev);
                      createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal, true);
-                     // TESTING THIS...
-                     createdExternal.symbol.idCode = external.symbol.idCode;
+
+                     FreeClassFunction(func);
 
                      curExternal = createdExternal;
                      ProcessFunction(createdExternal.function);
 
-
-                     // Create a declaration above
-                     {
-                        Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier), 
-                           MkListOne(MkInitDeclarator(CopyDeclarator(createdExternal.function.declarator), null)));
-                        externalDecl.declaration = decl;
-                        if(decl.symbol && !decl.symbol.pointerExternal)
-                           decl.symbol.pointerExternal = externalDecl;
-                     }
-
                      if(propWatch.deleteWatch)
                      {
                         OldList * args = MkList();
@@ -11594,24 +12805,25 @@ static void ProcessStatement(Statement stmt)
                               char getName[1024], setName[1024];
                               OldList * args = MkList();
 
-                              DeclareProperty(prop, setName, getName);                              
-                              
+                              DeclareProperty(createdExternal, prop, setName, getName);
+
                               // eInstance_Watch(stmt.watch.object, prop, stmt.watch.watcher, callback);
                               strcpy(propName, "__ecereProp_");
                               FullClassNameCat(propName, prop._class.fullName, false);
                               strcat(propName, "_");
-                              // strcat(propName, prop.name);
                               FullClassNameCat(propName, prop.name, true);
 
                               ListAdd(args, CopyExpression(object));
                               ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
                               ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
-                              ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
+                              ListAdd(args, MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpIdentifier(MkIdentifier(watcherName))));
 
                               ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), args));
+
+                              external.CreateUniqueEdge(createdExternal, true);
                            }
                            else
-                              Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
+                              Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
                         }
                      }
                   }
@@ -11629,7 +12841,7 @@ static void ProcessStatement(Statement stmt)
                FreeList(watches, FreePropertyWatch);
             }
             else
-               Compiler_Error($"No observer specified and not inside a _class\n");
+               Compiler_Error($"No observer specified and not inside a class\n");
          }
          else
          {
@@ -11654,7 +12866,7 @@ static void ProcessStatement(Statement stmt)
 
          if(inCompiler)
          {
-            _class = object ? 
+            _class = object ?
                   ((object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null) : thisClass;
 
             if(_class)
@@ -11738,7 +12950,7 @@ static void ProcessStatement(Statement stmt)
                   if(!watches)
                   {
                      OldList * args;
-                     // eInstance_StopWatching(object, null, watcher); 
+                     // eInstance_StopWatching(object, null, watcher);
                      args = MkList();
                      ListAdd(args, CopyExpression(object));
                      ListAdd(args, MkExpConstant("0"));
@@ -11756,15 +12968,13 @@ static void ProcessStatement(Statement stmt)
                            char getName[1024], setName[1024];
                            OldList * args = MkList();
 
-                           DeclareProperty(prop, setName, getName);
-         
-                           // eInstance_StopWatching(object, prop, watcher); 
+                           DeclareProperty(curExternal, prop, setName, getName);
+
+                           // eInstance_StopWatching(object, prop, watcher);
                            strcpy(propName, "__ecereProp_");
                            FullClassNameCat(propName, prop._class.fullName, false);
                            strcat(propName, "_");
-                           // strcat(propName, prop.name);
                            FullClassNameCat(propName, prop.name, true);
-                           MangleClassName(propName);
 
                            ListAdd(args, CopyExpression(object));
                            ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
@@ -11772,7 +12982,7 @@ static void ProcessStatement(Statement stmt)
                            ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
                         }
                         else
-                           Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
+                           Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
                      }
                   }
 
@@ -11803,7 +13013,7 @@ static void ProcessFunction(FunctionDefinition function)
 
    yylloc = function.loc;
    // Process thisClass
-   
+
    if(type && type.thisClass)
    {
       Symbol classSym = type.thisClass;
@@ -11852,14 +13062,10 @@ static void ProcessFunction(FunctionDefinition function)
          strcpy(className, "__ecereClass_");
          FullClassNameCat(className, _class.fullName, true);
 
-         MangleClassName(className);
-
          structName[0] = 0;
          FullClassNameCat(structName, _class.fullName, false);
 
          // [class] this
-         
-
          funcDecl = GetFuncDecl(function.declarator);
          if(funcDecl)
          {
@@ -11873,14 +13079,10 @@ static void ProcessFunction(FunctionDefinition function)
                }
             }
 
-            // DANGER: Watch for this... Check if it's a Conversion?
-            // if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
-            
-            // WAS TRYING THIS FOR CONVERSION PROPERTIES ON NOHEAD CLASSES: if((_class.type == structClass) || function != (FunctionDefinition)symbol.externalSet)
             if(!function.propertyNoThis)
             {
-               TypeName thisParam;
-               
+               TypeName thisParam = null;
+
                if(type.classObjectType != classPointer)
                {
                   thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
@@ -11902,6 +13104,7 @@ static void ProcessFunction(FunctionDefinition function)
                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
                   };
+                  DeclareStruct(curExternal, "ecere::com::Class", false, true);
                   funcDecl.function.parameters->Insert(null, thisParam);
                }
             }
@@ -11925,7 +13128,6 @@ static void ProcessFunction(FunctionDefinition function)
 
                if(type.classObjectType != classPointer)
                {
-                  // DANGER: Watch for this... Check if it's a Conversion?
                   if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
                   {
                      TypeName thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
@@ -11935,10 +13137,10 @@ static void ProcessFunction(FunctionDefinition function)
                      funcDecl.function.parameters->Insert(null, thisParam);
                   }
                }
-            }         
+            }
          }
       }
-      
+
       // Add this to the context
       if(function.body)
       {
@@ -11947,7 +13149,7 @@ static void ProcessFunction(FunctionDefinition function)
             thisSymbol = Symbol
             {
                string = CopyString("this");
-               type = classSym ? MkClassType(classSym.string) : null; //_class.fullName);
+               type = classSym ? MkClassType(classSym.string) : null;
             };
             function.body.compound.context.symbols.Add((BTNode)thisSymbol);
 
@@ -11956,17 +13158,12 @@ static void ProcessFunction(FunctionDefinition function)
                thisSymbol.type.classObjectType = ClassObjectType::typedObject;
                thisSymbol.type.byReference = type.byReference;
                thisSymbol.type.typedByReference = type.byReference;
-               /*
-               thisSymbol = Symbol { string = CopyString("class") };
-               function.body.compound.context.symbols.Add(thisSymbol);
-               */
             }
          }
       }
 
       // Pointer to class data
-      
-      if(inCompiler && _class && (_class.type == normalClass /*|| _class.type == noHeadClass*/) && type.classObjectType != classPointer)
+      if(inCompiler && _class && _class.type == normalClass && type.classObjectType != classPointer)
       {
          DataMember member = null;
          {
@@ -11986,21 +13183,19 @@ static void ProcessFunction(FunctionDefinition function)
          if(member)
          {
             char pointerName[1024];
-   
+
             Declaration decl;
             Initializer initializer;
             Expression exp, bytePtr;
-   
+
             strcpy(pointerName, "__ecerePointer_");
             FullClassNameCat(pointerName, _class.fullName, false);
             {
                char className[1024];
                strcpy(className, "__ecereClass_");
                FullClassNameCat(className, classSym.string, true);
-               MangleClassName(className);
 
-               // Testing This
-               DeclareClass(classSym, className);
+               DeclareClass(curExternal, classSym, className);
             }
 
             // ((byte *) this)
@@ -12008,9 +13203,19 @@ static void ProcessFunction(FunctionDefinition function)
 
             if(_class.fixed)
             {
-               char string[256];
-               sprintf(string, "%d", _class.offset);
-               exp = QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string)));
+               Expression e;
+               if(_class.offset && _class.offset == (_class.base.type == noHeadClass ? _class.base.memberOffset : _class.base.structSize))
+               {
+                  e = MkExpClassSize(MkSpecifierName(_class.base.fullName));
+                  ProcessExpressionType(e);
+               }
+               else
+               {
+                  char string[256];
+                  sprintf(string, "%d", _class.offset);  // Need Bootstrap Fix
+                  e = MkExpConstant(string);
+               }
+               exp = QBrackets(MkExpOp(bytePtr, '+', e));
             }
             else
             {
@@ -12027,7 +13232,7 @@ static void ProcessFunction(FunctionDefinition function)
                kind = pointerType;
                type = Type { refCount = 1, kind = voidType };
             };
-   
+
             if(function.body)
             {
                yylloc = function.body.loc;
@@ -12041,10 +13246,12 @@ static void ProcessFunction(FunctionDefinition function)
 
                {
                   Context prevContext = curContext;
+                  OldList * list;
                   curContext = function.body.compound.context;
 
-                  decl = MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
+                  decl = MkDeclaration((list = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null))),
                      MkListOne(MkInitDeclarator(QMkPtrDecl(pointerName), initializer)));
+                  list->Insert(null, MkSpecifierExtended(MkExtDeclAttrib(MkAttrib(ATTRIB, MkListOne(MkAttribute(CopyString("unused"), null))))));
 
                   curContext = prevContext;
                }
@@ -12058,7 +13265,7 @@ static void ProcessFunction(FunctionDefinition function)
             }
          }
       }
-      
+
 
       // Loop through the function and replace undeclared identifiers
       // which are a member of the class (methods, properties or data)
@@ -12114,7 +13321,7 @@ static void ProcessFunction(FunctionDefinition function)
 
    if(function.declarator)
    {
-      ProcessDeclarator(function.declarator);
+      ProcessDeclarator(function.declarator, true);
    }
 
    topContext = oldTopContext;
@@ -12153,7 +13360,7 @@ static void ProcessClass(OldList definitions, Symbol symbol)
          {
             Class backThisClass = thisClass;
             if(regClass) thisClass = regClass;
-            ProcessDeclaration(def.decl);
+            ProcessDeclaration(def.decl, symbol ? true : false);
             thisClass = backThisClass;
          }
       }
@@ -12168,7 +13375,7 @@ static void ProcessClass(OldList definitions, Symbol symbol)
             type = regClass ? MkClassType(regClass.fullName) : null;
          };
          globalContext.symbols.Add((BTNode)thisSymbol);
-         
+
          for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
          {
             thisClass = regClass;
@@ -12184,11 +13391,6 @@ static void ProcessClass(OldList definitions, Symbol symbol)
          PropertyDef prop = def.propertyDef;
 
          // Add this to the context
-         /*
-         Symbol thisSymbol = Symbol { string = CopyString("this"), type = MkClassType(regClass.fullName) };
-         globalContext.symbols.Add(thisSymbol);
-         */
-         
          thisClass = regClass;
          if(prop.setStmt)
          {
@@ -12237,16 +13439,11 @@ static void ProcessClass(OldList definitions, Symbol symbol)
          }
 
          thisClass = null;
-
-         /*
-         globalContext.symbols.Remove(thisSymbol);
-         FreeSymbol(thisSymbol);
-         */
       }
       else if(def.type == propertyWatchClassDef && def.propertyWatch)
       {
          PropertyWatch propertyWatch = def.propertyWatch;
-        
+
          thisClass = regClass;
          if(propertyWatch.compound)
          {
@@ -12266,7 +13463,7 @@ static void ProcessClass(OldList definitions, Symbol symbol)
    }
 }
 
-void DeclareFunctionUtil(String s)
+void DeclareFunctionUtil(External neededBy, const String s)
 {
    GlobalFunction function = eSystem_FindFunction(privateModule, s);
    if(function)
@@ -12276,90 +13473,81 @@ void DeclareFunctionUtil(String s)
       if(function.module.importType != staticImport && (!function.dataType || !function.dataType.dllExport))
          strcpy(name, "__ecereFunction_");
       FullClassNameCat(name, s, false); // Why is this using FullClassNameCat ?
-      DeclareFunction(function, name);
+      DeclareFunction(neededBy, function, name);
    }
+   else if(neededBy)
+      FindSymbol(s, globalContext, globalContext, false, false);
 }
 
+bool reachedPass15;
+
 void ComputeDataTypes()
 {
    External external;
-   External temp { };
-   External after = null;
 
    currentClass = null;
 
    containerClass = eSystem_FindClass(GetPrivateModule(), "Container");
 
-   for(external = ast->first; external; external = external.next)
-   {
-      if(external.type == declarationExternal)
-      {
-         Declaration decl = external.declaration;
-         if(decl)
-         {
-            OldList * decls = decl.declarators;
-            if(decls)
-            {
-               InitDeclarator initDecl = decls->first;
-               if(initDecl)
-               {
-                  Declarator declarator = initDecl.declarator;
-                  if(declarator && declarator.type == identifierDeclarator)
-                  {
-                     Identifier id = declarator.identifier;
-                     if(id && id.string)
-                     {
-                        if(!strcmp(id.string, "uintptr_t") || !strcmp(id.string, "intptr_t") || !strcmp(id.string, "size_t") || !strcmp(id.string, "ssize_t"))
-                        {
-                           external.symbol.id = -1001, external.symbol.idCode = -1001;
-                           after = external;
-                        }
-                     }
-                  }
-               }
-            }
-         }
-       }
-   }
-
-   temp.symbol = Symbol { id = -1000, idCode = -1000 };
-   ast->Insert(after, temp);
-   curExternal = temp;
-
-   DeclareFunctionUtil("eSystem_New");
-   DeclareFunctionUtil("eSystem_New0");
-   DeclareFunctionUtil("eSystem_Renew");
-   DeclareFunctionUtil("eSystem_Renew0");
-   DeclareFunctionUtil("eClass_GetProperty");
-
-   DeclareStruct("ecere::com::Class", false);
-   DeclareStruct("ecere::com::Instance", false);
-   DeclareStruct("ecere::com::Property", false);
-   DeclareStruct("ecere::com::DataMember", false);
-   DeclareStruct("ecere::com::Method", false);
-   DeclareStruct("ecere::com::SerialBuffer", false);
-   DeclareStruct("ecere::com::ClassTemplateArgument", false);
-
-   ast->Remove(temp);
+   DeclareStruct(null, "ecere::com::Class", false, true);
+   DeclareStruct(null, "ecere::com::Instance", false, true);
+   DeclareStruct(null, "ecere::com::Property", false, true);
+   DeclareStruct(null, "ecere::com::DataMember", false, true);
+   DeclareStruct(null, "ecere::com::Method", false, true);
+   DeclareStruct(null, "ecere::com::SerialBuffer", false, true);
+   DeclareStruct(null, "ecere::com::ClassTemplateArgument", false, true);
+
+   DeclareFunctionUtil(null, "eSystem_New");
+   DeclareFunctionUtil(null, "eSystem_New0");
+   DeclareFunctionUtil(null, "eSystem_Renew");
+   DeclareFunctionUtil(null, "eSystem_Renew0");
+   DeclareFunctionUtil(null, "eSystem_Delete");
+   DeclareFunctionUtil(null, "eClass_GetProperty");
+   DeclareFunctionUtil(null, "eClass_SetProperty");
+   DeclareFunctionUtil(null, "eInstance_FireSelfWatchers");
+   DeclareFunctionUtil(null, "eInstance_SetMethod");
+   DeclareFunctionUtil(null, "eInstance_IncRef");
+   DeclareFunctionUtil(null, "eInstance_StopWatching");
+   DeclareFunctionUtil(null, "eInstance_Watch");
+   DeclareFunctionUtil(null, "eInstance_FireWatchers");
+   reachedPass15 = true;
 
    for(external = ast->first; external; external = external.next)
    {
       afterExternal = curExternal = external;
       if(external.type == functionExternal)
       {
+         if(memoryGuard)
+         {
+            DeclareFunctionUtil(external, "MemoryGuard_PushLoc");
+            DeclareFunctionUtil(external, "MemoryGuard_PopLoc");
+         }
+
          currentClass = external.function._class;
          ProcessFunction(external.function);
       }
       // There shouldn't be any _class member access here anyways...
       else if(external.type == declarationExternal)
       {
+         if(memoryGuard && external.declaration && external.declaration.type == instDeclaration)
+         {
+            DeclareFunctionUtil(external, "MemoryGuard_PushLoc");
+            DeclareFunctionUtil(external, "MemoryGuard_PopLoc");
+         }
+
          currentClass = null;
-         ProcessDeclaration(external.declaration);
+         if(external.declaration)
+            ProcessDeclaration(external.declaration, true);
       }
       else if(external.type == classExternal)
       {
          ClassDefinition _class = external._class;
          currentClass = external.symbol.registered;
+         if(memoryGuard)
+         {
+            DeclareFunctionUtil(external, "MemoryGuard_PushLoc");
+            DeclareFunctionUtil(external, "MemoryGuard_PopLoc");
+         }
          if(_class.definitions)
          {
             ProcessClass(_class.definitions, _class.symbol);
@@ -12378,7 +13566,5 @@ void ComputeDataTypes()
    }
    currentClass = null;
    thisNameSpace = null;
-
-   delete temp.symbol;
-   delete temp;
+   curExternal = null;
 }