compiler/libec: (#341, #351, #644, #771) Improved enum type matching and type handlin...
[sdk] / compiler / libec / src / pass15.ec
index c9e718c..fda2c99 100644 (file)
@@ -47,6 +47,8 @@ Time findSymbolTotalTime;
    {
       TempFile f { };
       int count;
+      bool backOutputLineNumbers = outputLineNumbers;
+      outputLineNumbers = false;
 
       if(exp)
          OutputExpression(exp, f);
@@ -55,6 +57,8 @@ Time findSymbolTotalTime;
       count += f.Read(string + count, 1, 1023);
       string[count] = '\0';
       delete f;
+
+      outputLineNumbers = backOutputLineNumbers;
    }
 }
 
@@ -88,6 +92,7 @@ bool NeedCast(Type type1, Type type2)
    {
       switch(type1.kind)
       {
+         case _BoolType:
          case charType:
          case shortType:
          case intType:
@@ -200,10 +205,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);
 }
 
@@ -240,9 +247,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 +305,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 +352,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,13 +365,18 @@ 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...
@@ -684,6 +727,7 @@ 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;
@@ -1026,6 +1070,7 @@ void DeclareStruct(char * name, bool skipNoHead)
       OldList * specifiers, * declarators;
       OldList * declarations = null;
       char structName[1024];
+      Specifier spec = null;
       external = (classSym.registered && classSym.registered.type == structClass) ?
          classSym.pointerExternal : classSym.structExternal;
 
@@ -1050,10 +1095,19 @@ void DeclareStruct(char * name, bool skipNoHead)
       structName[0] = 0;
       FullClassNameCat(structName, name, false);
 
+      if(external && external.declaration && external.declaration.specifiers)
+      {
+         for(spec = external.declaration.specifiers->first; spec; spec = spec.next)
+         {
+            if(spec.type == structSpecifier || spec.type == unionSpecifier)
+               break;
+         }
+      }
+
       /*if(!external)
          external = MkExternalDeclaration(null);*/
 
-      if(!skipNoHead)
+      if(!skipNoHead && (!spec || !spec.definitions))
       {
          bool addedPadding = false;
          classSym.declaredStructSym = true;
@@ -1073,9 +1127,10 @@ void DeclareStruct(char * name, bool skipNoHead)
       }
       if(skipNoHead || declarations)
       {
-         if(external && external.declaration)
+         if(spec)
          {
-            ((Specifier)external.declaration.specifiers->first).definitions = declarations;
+            if(declarations)
+               spec.definitions = declarations;
 
             if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
             {
@@ -1252,7 +1307,9 @@ void DeclareProperty(Property prop, char * setName, char * getName)
                classSym._import.properties.Add(symbol._import);
          }
          imported = true;
-         if(prop._class.module != privateModule && prop._class.module.importType != staticImport)
+         // 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;
       }
 
@@ -1762,6 +1819,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);
@@ -2411,7 +2469,7 @@ public void DeclareMethod(Method method, char * name)
          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;
          }
       }
@@ -2979,7 +3037,11 @@ 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))
                      {
                         if(!conversions && !convert.Get)
                            return true;
@@ -3060,7 +3122,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))
                   {
                      return true;
                   }
@@ -3083,7 +3145,9 @@ 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))
                      {
                         if(!conversions && !convert.Get)
                            return true;
@@ -3112,9 +3176,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))
+                     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))
+                     return true;
                }
             }
          }
@@ -3129,21 +3197,21 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
       // 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) &&
               ((source.kind == functionType || (source.kind == pointerType && source.type.kind == functionType) || source.kind == methodType)))
@@ -3454,12 +3522,31 @@ bool MatchWithEnums_Module(Module mainModule, Expression sourceExp, Type dest, c
 
 bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, bool skipUnitBla)
 {
-   Type source = sourceExp.expType;
+   Type source;
    Type realDest = dest;
    Type backupSourceExpType = null;
+   Expression computedExp = sourceExp;
+   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(sourceExp);        // 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 != sourceExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = sourceExp;
+      }
+      FreeType(dest);
       return true;
+   }
 
    if(!skipUnitBla && source && dest && source.kind == classType && dest.kind == classType)
    {
@@ -3474,8 +3561,16 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
               destBase = destBase.base);
           //if(source._class.registered == dest._class.registered)
           if(sourceBase == destBase)
-             return true;
-       }
+          {
+            if(computedExp != sourceExp)
+            {
+               FreeExpression(computedExp);
+               computedExp = sourceExp;
+            }
+            FreeType(dest);
+            return true;
+         }
+      }
    }
 
    if(source)
@@ -3485,21 +3580,25 @@ 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 && sourceExp.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 != sourceExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = sourceExp;
       }
 
       if(dest.kind != classType && source.kind == classType && source._class && source._class.registered &&
@@ -3609,7 +3708,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)
@@ -3712,7 +3811,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)
@@ -3752,38 +3860,38 @@ 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 &&
             (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 &&
             (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();
@@ -3805,43 +3913,49 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
       }
       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))
+         (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) &&
+      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();
+         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)))
       {
          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));
       }
-      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))
+         (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == _BoolType || source.kind == charType))
       {
          specs = MkListOne(MkEnum(MkIdentifier(dest.enumName), null));
       }
@@ -3858,7 +3972,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
          return false;
       }
 
-      if(!flag)
+      if(!flag && !sourceExp.opDestType)
       {
          Expression newExp { };
          *newExp = *sourceExp;
@@ -3897,6 +4011,12 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
    }
    else
    {
+      if(computedExp != sourceExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = sourceExp;
+      }
+
       while((sourceExp.type == bracketsExp || sourceExp.type == extensionExpressionExp) && sourceExp.list) sourceExp = sourceExp.list->last;
       if(sourceExp.type == identifierExp)
       {
@@ -3936,6 +4056,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                            sourceExp.constant = CopyString(constant);
                            //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
                         }
+                        FreeType(dest);
                         return true;
                      }
                   }
@@ -3945,8 +4066,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,13 +4091,13 @@ 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_DIVIDE(o, name, m, t, p) \
+#define BINARY_DIVIDEINT(o, name, m, t, p) \
    static bool name(Expression exp, Operand op1, Operand op2)   \
    {                                                              \
       t value2 = op2.m;                                           \
@@ -3983,6 +4108,17 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
       return true;                                                \
    }
 
+#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(op1.m o value2);             \
+      if(!exp.expType) \
+         { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
+      return true;                                                \
+   }
+
 #define UNARY(o, name, m, t, p) \
    static bool name(Expression exp, Operand op1)                \
    {                                                              \
@@ -3996,6 +4132,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 +4144,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 +4175,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 +4214,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 +4247,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,8 +4286,8 @@ 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;
@@ -4161,6 +4308,55 @@ 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 { };
@@ -4175,16 +4371,27 @@ public Operand GetOperand(Expression exp)
          type = type._class.registered.dataType;
 
       }
-      op.kind = type.kind;
-      op.type = exp.expType;
-      if(exp.isConstant && exp.type == constantExp)
+      if(exp.type == stringExp && op.kind == pointerType)
+      {
+         op.ui64 = (uint64)exp.string;
+         op.kind = pointerType;
+         op.ops = uint64Ops;
+      }
+      else if(exp.isConstant && exp.type == constantExp)
       {
+         op.kind = type.kind;
+         op.type = exp.expType;
+
          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);
@@ -4227,47 +4434,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,7 +4495,7 @@ public Operand GetOperand(Expression exp)
             case classType:
                op.ui64 = _strtoui64(exp.constant, null, 0);
                op.kind = pointerType;
-               op.ops = uintOps;
+               op.ops = uint64Ops;
                // op.ptrSize =
                break;
          }
@@ -4880,69 +5097,29 @@ void ComputeInstantiation(Expression exp)
                            {
                               BitMember bitMember = (BitMember) dataMember;
                               Type type;
-                              int part = 0;
-                              GetInt(value, &part);
+                              uint64 part;
                               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 = 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, &v) : GetUChar(value, &v); part = (uint64)v; break; }
+                                 case shortType:      { uint16 v; type.isSigned ? GetShort(value, &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, &v) : GetUInt(value, &v); part = (uint64)v; break; }
+                                 case int64Type:      { uint64 v; type.isSigned ? GetInt64(value, &v) : GetUInt64(value, &v); part = (uint64)v; break; }
+                                 case intPtrType:     { intptr v; type.isSigned ? GetIntPtr(value, &v) : GetUIntPtr(value, &v); part = (uint64)v; break; }
+                                 case intSizeType:    { intsize v; type.isSigned ? GetIntSize(value, &v) : GetUIntSize(value, &v); part = (uint64)v; break; }
                               }
+                              bits += part << bitMember.pos;
                            }
                         }
                      }
@@ -4975,6 +5152,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 = 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 ? GetOpIntPtr(op, &op.i64) : GetOpUIntPtr(op, &op.i64);
+         break;
+      case intSizeType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == longType || op.kind == enumType || op.kind == _BoolType)
+            result = isSigned ? GetOpIntSize(op, &op.ui64) : GetOpUIntSize(op, &op.ui64);
+         break;
+   }
+   return result;
+}
+
 void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1, Operand op2)
 {
    if(exp.op.op == SIZEOF)
@@ -5020,6 +5248,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
@@ -5129,7 +5364,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);
@@ -5349,11 +5623,15 @@ void ComputeExpression(Expression exp)
             if(!n)
             {
                OldList * list = exp.list;
+               Expression prev = exp.prev;
+               Expression next = exp.next;
                ComputeExpression(e);
                //FreeExpContents(exp);
                FreeType(exp.expType);
                FreeType(exp.destType);
                *exp = *e;
+               exp.prev = prev;
+               exp.next = next;
                delete e;
                delete list;
             }
@@ -5501,7 +5779,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);
@@ -5516,7 +5794,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;
 
@@ -5551,7 +5829,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;
 
@@ -5569,7 +5847,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;
 
@@ -5579,6 +5857,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;
@@ -5586,7 +5881,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;
 
@@ -5646,7 +5941,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;
@@ -5678,7 +5973,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;
@@ -5798,130 +6093,159 @@ void ComputeExpression(Expression exp)
 
             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;
                }
             }
@@ -5984,6 +6308,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)
@@ -6411,6 +6737,7 @@ 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;
@@ -6467,6 +6794,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;
@@ -6707,8 +7035,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);
@@ -7239,7 +7571,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)
@@ -7326,7 +7658,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;
 
@@ -7394,7 +7729,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);
@@ -7404,6 +7741,8 @@ void ProcessExpressionType(Expression exp)
                      resetScanner();
                      expression_yyparse();
                      delete fileInput;
+                     if(backInput)
+                        fileInput = backInput;
 
                      yylloc = backupYylloc;
 
@@ -7543,6 +7882,7 @@ void ProcessExpressionType(Expression exp)
       {
          if(!exp.expType)
          {
+            char * constant = exp.constant;
             Type type
             {
                refCount = 1;
@@ -7550,14 +7890,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;
@@ -7571,26 +7911,59 @@ 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"));
+                  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;
+                  }
+                  type.kind = is64Bit ? int64Type : intType;
+                  type.isSigned = isSigned;
+               }
             }
             exp.isConstant = true;
             if(exp.destType && exp.destType.kind == doubleType)
@@ -7649,6 +8022,7 @@ 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;
 
          // Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
          Type dummy
@@ -7699,19 +8073,32 @@ void ProcessExpressionType(Expression exp)
             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;
+               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;
                }
@@ -7747,21 +8134,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 &&
+            // 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;
 
-              ((exp.destType._class.registered.type == unitClass && useSideUnit) ||
-               exp.destType._class.registered.type == enumClass ||
-               exp.destType._class.registered.type == bitClass
-               ))
+            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++;
             }
@@ -7777,6 +8165,17 @@ void ProcessExpressionType(Expression exp)
             ProcessExpressionType(exp.op.exp1);
             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count--;
 
+            exp.op.exp1.opDestType = 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);
@@ -7800,6 +8199,8 @@ void ProcessExpressionType(Expression exp)
                else
                {
                   exp.op.exp2.destType = exp.destType;
+                  if(!exp.op.exp1 || exp.op.op != '&')
+                     exp.op.exp2.opDestType = true;
                   if(exp.destType)
                      exp.destType.refCount++;
                }
@@ -7841,15 +8242,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.exp2.opDestType = true;
                if(exp.destType)
                   exp.destType.refCount++;
             }
@@ -7869,7 +8269,25 @@ 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;
+            }
             ProcessExpressionType(exp.op.exp2);
+            exp.op.exp2.opDestType = false;
             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
 
             if(assign && type1 && type1.kind == pointerType && exp.op.exp2.expType)
@@ -7928,7 +8346,10 @@ void ProcessExpressionType(Expression exp)
                type2.isSigned = true;
             }
             else
+            {
                type2 = exp.op.exp2.expType;
+               if(type2) type2.refCount++;
+            }
          }
 
          dummy.kind = voidType;
@@ -7994,12 +8415,36 @@ void ProcessExpressionType(Expression exp)
                   // 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 == '-' &&
+                     ((type1.kind == classType && type1._class.registered && type1._class.registered.type == enumClass) ||
+                      (type2.kind == classType && type2._class.registered && type2._class.registered.type == enumClass)) )
+                  {
+                     Type intType;
+                     if(!type1._class.registered.dataType)
+                        type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
+                     if(!type2._class.registered.dataType)
+                        type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
+
+                     intType = ProcessTypeString(
+                        (type1._class.registered.dataType.kind == int64Type || type2._class.registered.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 &&
@@ -8038,7 +8483,12 @@ void ProcessExpressionType(Expression exp)
                                        MkExpMember(classExp, MkIdentifier("typeSize"))))))));
 
                            if(!exp.op.exp2.expType)
+                           {
+                              if(type2)
+                                 FreeType(type2);
                               type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
+                              type2.refCount++;
+                           }
 
                            ProcessExpressionType(exp.op.exp2);
                         }
@@ -8220,7 +8670,10 @@ void ProcessExpressionType(Expression exp)
                      exp.op.exp2.destType.refCount++;
 
                      CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+                     if(type2)
+                        FreeType(type2);
                      type2 = exp.op.exp2.destType;
+                     if(type2) type2.refCount++;
 
                      exp.expType = type2;
                      type2.refCount++;
@@ -8242,36 +8695,81 @@ void ProcessExpressionType(Expression exp)
                   }
 
                   // 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 = type1 && type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass;
+                     bool op2IsEnum = type2 && type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.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))
+                           {
+                              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))
+                           {
+                              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))
+                           {
+                              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))
+                           {
+                              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(type2 && type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass &&
+                        (type1.kind != classType || !type1._class || !type1._class.registered || type1._class.registered.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))
+                        {
+                           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...
@@ -8313,43 +8811,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))
                         {
-                           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(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++;
+                           }
                         }
                      }
                   }
@@ -8481,6 +8980,8 @@ void ProcessExpressionType(Expression exp)
          yylloc = oldyylloc;
 
          FreeType(dummy);
+         if(type2)
+            FreeType(type2);
          break;
       }
       case bracketsExp:
@@ -8494,6 +8995,7 @@ void ProcessExpressionType(Expression exp)
             if(!e.next)
             {
                FreeType(e.destType);
+               e.opDestType = exp.opDestType;
                e.destType = exp.destType;
                if(e.destType) { exp.destType.refCount++; e.destType.count++; inced = true; }
             }
@@ -9216,6 +9718,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);
@@ -9300,7 +9803,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)))
          {
@@ -9542,7 +10045,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;
@@ -9757,6 +10261,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);
@@ -10408,7 +10913,7 @@ void ProcessExpressionType(Expression exp)
    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 != longType && exp.destType.kind != shortType && exp.destType.kind != charType && exp.destType.kind != _BoolType)))
    {
       exp.byReference = true;
    }
@@ -10960,10 +11465,8 @@ 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)
             {
@@ -11331,9 +11834,56 @@ static void ProcessStatement(Statement stmt)
             }
             symbol = FindSymbol(id.string, curContext, curContext, false, false);
 
-            if(block && block.type == compoundStmt && block.compound.context)
+            if(block)
             {
-               block.compound.context.parent = stmt.compound.context;
+               // 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:
+                  */
+               }
             }
             if(filter)
             {
@@ -11616,7 +12166,7 @@ static void ProcessStatement(Statement stmt)
                               ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), 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);
                         }
                      }
                   }
@@ -11777,7 +12327,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);
                      }
                   }
 
@@ -12335,7 +12885,9 @@ void ComputeDataTypes()
    DeclareFunctionUtil("eSystem_New0");
    DeclareFunctionUtil("eSystem_Renew");
    DeclareFunctionUtil("eSystem_Renew0");
+   DeclareFunctionUtil("eSystem_Delete");
    DeclareFunctionUtil("eClass_GetProperty");
+   DeclareFunctionUtil("eInstance_FireSelfWatchers");
 
    DeclareStruct("ecere::com::Class", false);
    DeclareStruct("ecere::com::Instance", false);
@@ -12359,7 +12911,8 @@ void ComputeDataTypes()
       else if(external.type == declarationExternal)
       {
          currentClass = null;
-         ProcessDeclaration(external.declaration);
+         if(external.declaration)
+            ProcessDeclaration(external.declaration);
       }
       else if(external.type == classExternal)
       {
@@ -12383,6 +12936,7 @@ void ComputeDataTypes()
    }
    currentClass = null;
    thisNameSpace = null;
+   curExternal = null;
 
    delete temp.symbol;
    delete temp;