compiler/libec: Improvements to units operations
authorJerome St-Louis <jerome@ecere.com>
Wed, 6 Aug 2014 22:57:14 +0000 (18:57 -0400)
committerJerome St-Louis <jerome@ecere.com>
Wed, 6 Aug 2014 22:57:14 +0000 (18:57 -0400)
- Not giving ambiguity warning when comparing related units on both side of comparison operator
- Not giving ambiguity warning on multiplication/division, giving base data type instead (powers / ratios)
- WARNING: Radians a = Pi/2; Degrees b = a * 180 / Pi; // This will now understand as Degrees the ratio of 180*a by Pi!!!
  (Degrees conversions had to be fixed in units.ec)

22 files changed:
compiler/bootstrap/ecp/bootstrap/ecp.c
compiler/bootstrap/libec/bootstrap/ast.c
compiler/bootstrap/libec/bootstrap/copy.c
compiler/bootstrap/libec/bootstrap/dbpass.c
compiler/bootstrap/libec/bootstrap/ecdefs.c
compiler/bootstrap/libec/bootstrap/expression.c
compiler/bootstrap/libec/bootstrap/firstPass.c
compiler/bootstrap/libec/bootstrap/freeAst.c
compiler/bootstrap/libec/bootstrap/grammar.c
compiler/bootstrap/libec/bootstrap/loadSymbols.c
compiler/bootstrap/libec/bootstrap/output.c
compiler/bootstrap/libec/bootstrap/pass0.c
compiler/bootstrap/libec/bootstrap/pass1.c
compiler/bootstrap/libec/bootstrap/pass15.c
compiler/bootstrap/libec/bootstrap/pass16.c
compiler/bootstrap/libec/bootstrap/pass2.c
compiler/bootstrap/libec/bootstrap/pass3.c
compiler/bootstrap/libec/bootstrap/type.c
compiler/libec/src/copy.ec
compiler/libec/src/ecdefs.ec
compiler/libec/src/pass15.ec
ecere/src/sys/units.ec

index b49ea26..7012b1c 100644 (file)
@@ -1465,6 +1465,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index 71e8294..b4ceb23 100644 (file)
@@ -1426,6 +1426,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index 0fd2dcf..18dede6 100644 (file)
@@ -882,6 +882,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
@@ -1545,7 +1548,9 @@ result->loc = exp->loc;
 result->isConstant = exp->isConstant;
 result->byReference = exp->byReference;
 result->opDestType = exp->opDestType;
+result->usedInComparison = exp->usedInComparison;
 result->needTemplateCast = exp->needTemplateCast;
+result->parentOpDestType = exp->parentOpDestType;
 }
 return result;
 }
index fe13ab9..5ef6aa8 100644 (file)
@@ -909,6 +909,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index 9bde309..80d393b 100644 (file)
@@ -2074,6 +2074,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
@@ -2101,6 +2104,8 @@ this->addedThis = 0;
 this->needCast = 0;
 this->thisPtr = 0;
 this->opDestType = 0;
+this->parentOpDestType = 0;
+this->usedInComparison = 0;
 this->needTemplateCast = 0;
 }
 
@@ -2871,6 +2876,9 @@ __ecereNameSpace__ecere__com__eClass_AddDataMember(class, "addedThis", "bool", 4
 __ecereNameSpace__ecere__com__eClass_AddDataMember(class, "needCast", "bool", 4, 4, 1);
 __ecereNameSpace__ecere__com__eClass_AddDataMember(class, "thisPtr", "bool", 4, 4, 1);
 __ecereNameSpace__ecere__com__eClass_AddDataMember(class, "opDestType", "bool", 4, 4, 1);
+__ecereNameSpace__ecere__com__eClass_AddDataMember(class, "usedInComparison", "bool", 4, 4, 1);
+__ecereNameSpace__ecere__com__eClass_AddDataMember(class, "ambiguousUnits", "bool", 4, 4, 1);
+__ecereNameSpace__ecere__com__eClass_AddDataMember(class, "parentOpDestType", "bool", 4, 4, 1);
 __ecereNameSpace__ecere__com__eClass_AddDataMember(class, "needTemplateCast", "uint", 4, 4, 1);
 class = __ecereNameSpace__ecere__com__eSystem_RegisterClass(5, "Enumerator", 0, sizeof(struct Enumerator), 0, (void *)0, (void *)0, module, 1, 1);
 if(((struct __ecereNameSpace__ecere__com__Module *)(((char *)module + sizeof(struct __ecereNameSpace__ecere__com__Instance))))->application == ((struct __ecereNameSpace__ecere__com__Module *)(((char *)__thisModule + sizeof(struct __ecereNameSpace__ecere__com__Instance))))->application && class)
index 8a564ea..50f571e 100644 (file)
@@ -955,6 +955,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index 5347196..72f169c 100644 (file)
@@ -747,6 +747,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index a1c375e..f3be115 100644 (file)
@@ -1523,6 +1523,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index 7274800..c3487ae 100644 (file)
@@ -899,6 +899,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index ad9e318..36654ba 100644 (file)
@@ -477,6 +477,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index dc806f2..817e1f0 100644 (file)
@@ -908,6 +908,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index 6f6d609..458870c 100644 (file)
@@ -1100,6 +1100,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index e3420d9..3b1cfa4 100644 (file)
@@ -994,6 +994,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index 3bc7da5..5ad2d97 100644 (file)
@@ -1400,6 +1400,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
@@ -7935,6 +7938,15 @@ break;
 }
 }
 
+unsigned int RelatedUnits(struct __ecereNameSpace__ecere__com__Class * c1, struct __ecereNameSpace__ecere__com__Class * c2)
+{
+if(c1->base->type == 3)
+c1 = c1->base;
+if(c2->base->type == 3)
+c2 = c2->base;
+return c1 == c2;
+}
+
 extern char *  __ecereNameSpace__ecere__com__PrintString(struct __ecereNameSpace__ecere__com__Class * class, const void * object, ...);
 
 extern struct __ecereNameSpace__ecere__com__Class * __ecereClass___ecereNameSpace__ecere__sys__TempFile;
@@ -13194,6 +13206,12 @@ struct __ecereNameSpace__ecere__sys__OldList * list = exp->__anon1.list;
 struct Expression * prev = exp->prev;
 struct Expression * next = exp->next;
 
+if(exp->expType && exp->expType->kind == 8 && (!e->expType || e->expType->kind != 8))
+{
+FreeType(e->expType);
+e->expType = exp->expType;
+e->expType->refCount++;
+}
 ComputeExpression(e);
 FreeType(exp->expType);
 FreeType(exp->destType);
@@ -16202,6 +16220,8 @@ unsigned int useDestType = 0, useSideType = 0;
 struct Location oldyylloc = yylloc;
 unsigned int useSideUnit = 0;
 struct __ecereNameSpace__ecere__com__Class * destClass = (exp->destType && exp->destType->kind == 8 && exp->destType->__anon1._class) ? exp->destType->__anon1._class->__anon1.registered : (((void *)0));
+unsigned int powerOp = 0, relationOp = 0;
+struct __ecereNameSpace__ecere__com__Class * c1 = (((void *)0)), * c2 = (((void *)0));
 struct Type * dummy = (dummy = __ecereNameSpace__ecere__com__eInstance_New(__ecereClass_Type), dummy->count = 1, dummy->refCount = 1, dummy);
 
 switch(exp->__anon1.op.op)
@@ -16234,6 +16254,7 @@ case GE_OP:
 case NE_OP:
 boolResult = 1;
 useSideType = 1;
+relationOp = 1;
 break;
 case '+':
 case '-':
@@ -16253,6 +16274,8 @@ case '/':
 case '%':
 useSideType = 1;
 useDestType = 1;
+if(exp->__anon1.op.op == '/')
+powerOp = 1;
 break;
 case '&':
 case '*':
@@ -16260,6 +16283,8 @@ if(exp->__anon1.op.exp1)
 {
 useSideType = 1;
 useDestType = 1;
+if(exp->__anon1.op.op == '*')
+powerOp = 1;
 }
 break;
 }
@@ -16303,6 +16328,17 @@ if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
 exp->__anon1.op.exp1->destType = dummy;
 dummy->refCount++;
+if(powerOp)
+exp->__anon1.op.exp1->opDestType = 1;
+if(relationOp)
+exp->__anon1.op.exp1->usedInComparison = 1;
+}
+if(exp->__anon1.op.op == '+' || exp->__anon1.op.op == '-')
+{
+if(exp->opDestType)
+exp->__anon1.op.exp1->parentOpDestType = 1;
+if(exp->usedInComparison)
+exp->__anon1.op.exp1->usedInComparison = 1;
 }
 if(exp->__anon1.op.exp1->destType && exp->__anon1.op.op != '=')
 exp->__anon1.op.exp1->destType->count++;
@@ -16310,6 +16346,7 @@ ProcessExpressionType(exp->__anon1.op.exp1);
 if(exp->__anon1.op.exp1->destType && exp->__anon1.op.op != '=')
 exp->__anon1.op.exp1->destType->count--;
 exp->__anon1.op.exp1->opDestType = 0;
+exp->__anon1.op.exp1->usedInComparison = 0;
 if(!exp->__anon1.op.exp2 && (exp->__anon1.op.op == INC_OP || exp->__anon1.op.op == DEC_OP) && exp->__anon1.op.exp1->expType && exp->__anon1.op.exp1->expType->kind == 8 && exp->__anon1.op.exp1->expType->__anon1._class && exp->__anon1.op.exp1->expType->__anon1._class->__anon1.registered && exp->__anon1.op.exp1->expType->__anon1._class->__anon1.registered->type == 3)
 {
 exp->__anon1.op.exp2 = MkExpConstant("1");
@@ -16408,6 +16445,10 @@ if(exp->__anon1.op.exp2->destType)
 FreeType(exp->__anon1.op.exp2->destType);
 exp->__anon1.op.exp2->destType = dummy;
 dummy->refCount++;
+if(powerOp)
+exp->__anon1.op.exp2->opDestType = 1;
+if(relationOp)
+exp->__anon1.op.exp2->usedInComparison = 1;
 }
 if(type1 && boolResult && useSideType && type1->kind == 8 && type1->__anon1._class && type1->__anon1._class->__anon1.registered && (type1->__anon1._class->__anon1.registered->type == 2 || type1->__anon1._class->__anon1.registered->type == 4))
 {
@@ -16434,8 +16475,16 @@ e = (*e->__anon1.list).last;
 if(e->type == 11 && e->__anon1.cast.exp)
 e->__anon1.cast.exp->needCast = 1;
 }
+if(exp->__anon1.op.op == '+' || exp->__anon1.op.op == '-')
+{
+if(exp->opDestType)
+exp->__anon1.op.exp2->parentOpDestType = 1;
+if(exp->usedInComparison)
+exp->__anon1.op.exp2->usedInComparison = 1;
+}
 ProcessExpressionType(exp->__anon1.op.exp2);
 exp->__anon1.op.exp2->opDestType = 0;
+exp->__anon1.op.exp2->usedInComparison = 0;
 if(exp->__anon1.op.exp2->destType && exp->__anon1.op.op != '=')
 exp->__anon1.op.exp2->destType->count--;
 if(!assign && (exp->__anon1.op.exp1 || exp->__anon1.op.op == '~'))
@@ -16507,6 +16556,17 @@ if(type2)
 type2->refCount++;
 }
 }
+c1 = type1 && type1->kind == 8 && type1->__anon1._class ? type1->__anon1._class->__anon1.registered : (((void *)0));
+c2 = type2 && type2->kind == 8 && type2->__anon1._class ? type2->__anon1._class->__anon1.registered : (((void *)0));
+if(relationOp && ((exp->__anon1.op.exp1 && exp->__anon1.op.exp1->ambiguousUnits && (!c2 || c2->type != 3)) || (exp->__anon1.op.exp2 && exp->__anon1.op.exp2->ambiguousUnits && (!c1 || c1->type != 3))))
+Compiler_Warning(__ecereNameSpace__ecere__GetTranslatedString("ec", "ambiguous units in relation operation\n", (((void *)0))));
+if(!relationOp && ((exp->__anon1.op.exp1 && exp->__anon1.op.exp1->ambiguousUnits) || (exp->__anon1.op.exp2 && exp->__anon1.op.exp2->ambiguousUnits)) && (!powerOp || !c1 || c1->type != 3 || !c2 || c2->type != 3 || !RelatedUnits(c1, c2)))
+{
+if(exp->opDestType || exp->usedInComparison)
+exp->ambiguousUnits = 1;
+else
+Compiler_Warning(__ecereNameSpace__ecere__GetTranslatedString("ec", "ambiguous units\n", (((void *)0))));
+}
 dummy->kind = 0;
 if(exp->__anon1.op.op == SIZEOF)
 {
@@ -16535,6 +16595,10 @@ exp->expType->refCount++;
 }
 else if(!assign)
 {
+if(c1 && !c1->dataType)
+c1->dataType = ProcessTypeString(c1->dataTypeString, 0);
+if(c2 && !c2->dataType)
+c2->dataType = ProcessTypeString(c2->dataTypeString, 0);
 if(boolOps)
 {
 if(exp->__anon1.op.exp1)
@@ -16566,19 +16630,36 @@ exp->__anon1.op.exp2->expType = MkClassType("bool");
 exp->__anon1.op.exp2->expType->truth = 1;
 }
 }
+else if(powerOp && exp->__anon1.op.exp1 && exp->__anon1.op.exp2 && ((c1 && c1->type == 3) || (c2 && c2->type == 3)))
+{
+if(c1 && c1->type == 3 && c2 && c2->type == 3)
+{
+if(c1->dataType->kind == 7)
+exp->expType = c1->dataType;
+else if(c2->dataType->kind == 7)
+exp->expType = c2->dataType;
+else if(c1->dataType->kind == 6)
+exp->expType = c1->dataType;
+else if(c2->dataType->kind == 6)
+exp->expType = c2->dataType;
+else
+exp->expType = c1->dataType;
+}
+else if((c1 && c1->type == 3) || exp->__anon1.op.op == '/')
+exp->expType = type1;
+else
+exp->expType = type2;
+if(exp->expType)
+exp->expType->refCount++;
+}
 else if(exp->__anon1.op.exp1 && exp->__anon1.op.exp2 && ((useSideType) || ((!type1 || type1->kind != 8 || !strcmp(type1->__anon1._class->string, "String")) && (!type2 || type2->kind != 8 || !strcmp(type2->__anon1._class->string, "String")))))
 {
 if(type1 && type2 && ((type1->kind == 8 && type1->__anon1._class && strcmp(type1->__anon1._class->string, "String")) == (type2->kind == 8 && type2->__anon1._class && strcmp(type2->__anon1._class->string, "String"))))
 {
-if(exp->__anon1.op.op == '-' && ((type1->kind == 8 && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 4) || (type2->kind == 8 && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 4)))
+if(exp->__anon1.op.op == '-' && ((c1 && c1->type == 4) || (c2 && c2->type == 4)))
 {
-struct Type * intType;
+struct Type * intType = ProcessTypeString((c1 && c1->dataType->kind == 4) || (c2 && c2->dataType->kind == 4) ? "int64" : "int", 0);
 
-if(!type1->__anon1._class->__anon1.registered->dataType)
-type1->__anon1._class->__anon1.registered->dataType = ProcessTypeString(type1->__anon1._class->__anon1.registered->dataTypeString, 0);
-if(!type2->__anon1._class->__anon1.registered->dataType)
-type2->__anon1._class->__anon1.registered->dataType = ProcessTypeString(type2->__anon1._class->__anon1.registered->dataTypeString, 0);
-intType = ProcessTypeString((type1->__anon1._class->__anon1.registered->dataType->kind == 4 || type2->__anon1._class->__anon1.registered->dataType->kind == 4) ? "int64" : "int", 0);
 if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
 if(exp->__anon1.op.exp2->destType)
@@ -16598,8 +16679,13 @@ FreeType(exp->__anon1.op.exp1->destType);
 exp->__anon1.op.exp1->destType = type2;
 type2->refCount++;
 }
-if(!boolResult && type1->kind == 8 && (!exp->destType || exp->destType->kind != 8) && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 3 && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 3 && type1->__anon1._class->__anon1.registered != type2->__anon1._class->__anon1.registered)
+if(!boolResult && !exp->opDestType && (!exp->destType || exp->destType->kind != 8) && c1 && c1->type == 3 && c2 && c2->type == 3 && c1 != c2)
+{
+if(exp->usedInComparison || exp->parentOpDestType)
+exp->ambiguousUnits = 1;
+else
 Compiler_Warning(__ecereNameSpace__ecere__GetTranslatedString("ec", "operating on %s and %s with an untyped result, assuming %s\n", (((void *)0))), type1->__anon1._class->string, type2->__anon1._class->string, type1->__anon1._class->string);
+}
 if(type1->kind == 13 && type1->__anon1.type->kind == 20 && type2->kind != 13)
 {
 struct Expression * argExp = GetTemplateArgExp(type1->__anon1.type->__anon1.templateParameter, thisClass, 1);
@@ -16619,6 +16705,7 @@ if(!exp->__anon1.op.exp2->expType)
 if(type2)
 FreeType(type2);
 type2 = exp->__anon1.op.exp2->expType = ProcessTypeString("int", 0);
+c2 = (((void *)0));
 type2->refCount++;
 }
 ProcessExpressionType(exp->__anon1.op.exp2);
@@ -16748,7 +16835,7 @@ Compiler_Warning(__ecereNameSpace__ecere__GetTranslatedString("ec", "incompatibl
 }
 }
 }
-else if(!boolResult && (!useSideUnit) && type2 && type1 && type2->kind == 8 && type1->kind != 8 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 3)
+else if(!boolResult && !useSideUnit && c2 && c2->type == 3 && type1 && type1->kind != 8)
 {
 if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
@@ -16760,7 +16847,7 @@ exp->expType = type2;
 if(type2)
 type2->refCount++;
 }
-else if(!boolResult && (!useSideUnit) && type1 && type2 && type1->kind == 8 && type2->kind != 8 && type1->__anon1._class && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 3)
+else if(!boolResult && !useSideUnit && c1 && c1->type == 3 && type2 && type2->kind != 8)
 {
 if(exp->__anon1.op.exp2->destType)
 FreeType(exp->__anon1.op.exp2->destType);
@@ -16776,40 +16863,38 @@ else if(type1)
 {
 unsigned int valid = 0;
 
-if(!boolResult && useSideUnit && type1 && type1->kind == 8 && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 3 && type2 && type2->kind != 8)
+if(!boolResult && useSideUnit && c1 && c1->type == 3 && type2 && type2->kind != 8)
 {
 if(exp->__anon1.op.exp2->destType)
 FreeType(exp->__anon1.op.exp2->destType);
-if(!type1->__anon1._class->__anon1.registered->dataType)
-type1->__anon1._class->__anon1.registered->dataType = ProcessTypeString(type1->__anon1._class->__anon1.registered->dataTypeString, 0);
-exp->__anon1.op.exp2->destType = type1->__anon1._class->__anon1.registered->dataType;
+exp->__anon1.op.exp2->destType = c1->dataType;
 exp->__anon1.op.exp2->destType->refCount++;
 CheckExpressionType(exp->__anon1.op.exp2, exp->__anon1.op.exp2->destType, 0, 0);
 if(type2)
 FreeType(type2);
 type2 = exp->__anon1.op.exp2->destType;
+c2 = type2 && type2->kind == 8 && type2->__anon1._class ? type2->__anon1._class->__anon1.registered : (((void *)0));
 if(type2)
 type2->refCount++;
 exp->expType = type2;
 type2->refCount++;
 }
-if(!boolResult && useSideUnit && type2 && type2->kind == 8 && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 3 && type1 && type1->kind != 8)
+if(!boolResult && useSideUnit && c2 && c2->type == 3 && type1 && type1->kind != 8)
 {
 if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
-if(!type2->__anon1._class->__anon1.registered->dataType)
-type2->__anon1._class->__anon1.registered->dataType = ProcessTypeString(type2->__anon1._class->__anon1.registered->dataTypeString, 0);
-exp->__anon1.op.exp1->destType = type2->__anon1._class->__anon1.registered->dataType;
+exp->__anon1.op.exp1->destType = c2->dataType;
 exp->__anon1.op.exp1->destType->refCount++;
 CheckExpressionType(exp->__anon1.op.exp1, exp->__anon1.op.exp1->destType, 0, 0);
 type1 = exp->__anon1.op.exp1->destType;
+c1 = type1 && type1->kind == 8 && type1->__anon1._class ? type1->__anon1._class->__anon1.registered : (((void *)0));
 exp->expType = type1;
 type1->refCount++;
 }
 if(!boolResult || exp->__anon1.op.op == '>' || exp->__anon1.op.op == '<' || exp->__anon1.op.op == GE_OP || exp->__anon1.op.op == LE_OP)
 {
-unsigned int op1IsEnum = type1 && type1->kind == 8 && type1->__anon1._class && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 4;
-unsigned int op2IsEnum = type2 && type2->kind == 8 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 4;
+unsigned int op1IsEnum = c1 && c1->type == 4;
+unsigned int op2IsEnum = c2 && c2->type == 4;
 
 if(exp->__anon1.op.op == '*' || exp->__anon1.op.op == '/' || exp->__anon1.op.op == '-' || exp->__anon1.op.op == '|' || exp->__anon1.op.op == '^')
 {
@@ -16868,7 +16953,7 @@ valid = 1;
 }
 if(!valid)
 {
-if(type2 && type2->kind == 8 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 3 && (type1->kind != 8 || !type1->__anon1._class || !type1->__anon1._class->__anon1.registered || type1->__anon1._class->__anon1.registered->type != 3))
+if(c2 && c2->type == 3 && (!c1 || c1->type != 3))
 {
 if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
@@ -16918,13 +17003,13 @@ PrintType(exp->__anon1.op.exp1->expType, type1String, 0, 1);
 PrintType(exp->__anon1.op.exp2->expType, type2String, 0, 1);
 }
 Compiler_Warning(__ecereNameSpace__ecere__GetTranslatedString("ec", "incompatible expressions %s (%s) and %s (%s)\n", (((void *)0))), expString1, type1String, expString2, type2String);
-if(type1->kind == 8 && type1->__anon1._class && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 4)
+if(c1 && c1->type == 4)
 {
 exp->expType = exp->__anon1.op.exp1->expType;
 if(exp->__anon1.op.exp1->expType)
 exp->__anon1.op.exp1->expType->refCount++;
 }
-else if(type2->kind == 8 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 4)
+else if(c2 && c2->type == 4)
 {
 exp->expType = exp->__anon1.op.exp2->expType;
 if(exp->__anon1.op.exp2->expType)
@@ -16936,7 +17021,7 @@ exp->__anon1.op.exp2->expType->refCount++;
 }
 else if(type2)
 {
-if(type2->kind == 8 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 4)
+if(c2 && c2->type == 4)
 {
 struct Type * oldType = exp->__anon1.op.exp1->expType;
 
@@ -16962,7 +17047,7 @@ exp->__anon1.op.exp1->destType->refCount++;
 }
 else if(type2 && (!type1 || (type2->kind == 8 && type1->kind != 8)))
 {
-if(type1 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 3)
+if(type1 && c2 && c2->type == 3)
 {
 if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
@@ -16985,7 +17070,7 @@ type2->refCount++;
 }
 else if(type1 && (!type2 || (type1->kind == 8 && type2->kind != 8)))
 {
-if(type2 && type1->__anon1._class && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 3)
+if(c2 && c2->type == 3)
 {
 if(exp->__anon1.op.exp2->destType)
 FreeType(exp->__anon1.op.exp2->destType);
@@ -17058,6 +17143,8 @@ if(!e->next)
 {
 FreeType(e->destType);
 e->opDestType = exp->opDestType;
+e->usedInComparison = exp->usedInComparison;
+e->parentOpDestType = exp->parentOpDestType;
 e->destType = exp->destType;
 if(e->destType)
 {
@@ -17065,6 +17152,8 @@ exp->destType->refCount++;
 }
 }
 ProcessExpressionType(e);
+if(e->ambiguousUnits)
+exp->ambiguousUnits = 1;
 if(!exp->expType && !e->next)
 {
 exp->expType = e->expType;
@@ -19543,6 +19632,7 @@ __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ParseExpressionString",
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ReplaceExpContents", "void ReplaceExpContents(Expression checkedExp, Expression newExp)", ReplaceExpContents, module, 1);
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ApplyAnyObjectLogic", "void ApplyAnyObjectLogic(Expression e)", ApplyAnyObjectLogic, module, 1);
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ApplyLocation", "void ApplyLocation(Expression exp, Location loc)", ApplyLocation, module, 1);
+__ecereNameSpace__ecere__com__eSystem_RegisterFunction("RelatedUnits", "bool RelatedUnits(ecere::com::Class c1, ecere::com::Class c2)", RelatedUnits, module, 1);
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ProcessExpressionType", "void ProcessExpressionType(Expression exp)", ProcessExpressionType, module, 1);
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("DeclareFunctionUtil", "void DeclareFunctionUtil(External neededBy, const String s)", DeclareFunctionUtil, module, 1);
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ComputeDataTypes", "void ComputeDataTypes(void)", ComputeDataTypes, module, 1);
index 6601c54..0fb0248 100644 (file)
@@ -827,6 +827,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index fefd9b1..b8960f0 100644 (file)
@@ -724,6 +724,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index 3d65dea..2fcd642 100644 (file)
@@ -1545,6 +1545,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index e05e624..f2c1f0c 100644 (file)
@@ -1072,6 +1072,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
index aaf451f..9b27ac7 100644 (file)
@@ -226,7 +226,9 @@ Expression MoveExpContents(Expression exp)
       result.isConstant = exp.isConstant;
       result.byReference = exp.byReference;
       result.opDestType = exp.opDestType;
+      result.usedInComparison = exp.usedInComparison;
       result.needTemplateCast = exp.needTemplateCast;
+      result.parentOpDestType = exp.parentOpDestType;
    }
 
    return result;
index dfbfa59..7a3ea19 100644 (file)
@@ -672,6 +672,9 @@ public:
    bool needCast;
    bool thisPtr;
    bool opDestType;
+   bool usedInComparison;
+   bool ambiguousUnits;
+   bool parentOpDestType;
    uint needTemplateCast;
 
    void Clear()
@@ -692,6 +695,8 @@ public:
       needCast = false;
       thisPtr = false;
       opDestType = false;
+      parentOpDestType = false;
+      usedInComparison = false;
       needTemplateCast = 0;
    }
 };
index edb9e63..c19a875 100644 (file)
@@ -5725,6 +5725,14 @@ void ComputeExpression(Expression exp)
                OldList * list = exp.list;
                Expression prev = exp.prev;
                Expression next = exp.next;
+
+               // For operations which set the exp type on brackets exp after the inner exp was processed...
+               if(exp.expType && exp.expType.kind == classType && (!e.expType || e.expType.kind != classType))
+               {
+                  FreeType(e.expType);
+                  e.expType = exp.expType;
+                  e.expType.refCount++;
+               }
                ComputeExpression(e);
                //FreeExpContents(exp);
                FreeType(exp.expType);
@@ -7768,6 +7776,13 @@ void ApplyLocation(Expression exp, Location loc)
    }
 }
 
+bool RelatedUnits(Class c1, Class c2)
+{
+   if(c1.base.type == unitClass) c1 = c1.base;
+   if(c2.base.type == unitClass) c2 = c2.base;
+   return c1 == c2;
+}
+
 void ProcessExpressionType(Expression exp)
 {
    bool unresolved = false;
@@ -8260,6 +8275,8 @@ void ProcessExpressionType(Expression exp)
          Location oldyylloc = yylloc;
          bool useSideUnit = false;
          Class destClass = (exp.destType && exp.destType.kind == classType && exp.destType._class) ? exp.destType._class.registered : null;
+         bool powerOp = false, relationOp = false;
+         Class c1 = null, c2 = null;
 
          // Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
          Type dummy
@@ -8306,6 +8323,7 @@ void ProcessExpressionType(Expression exp)
                // Gives boolean result
                boolResult = true;
                useSideType = true;
+               relationOp = true;
                break;
             case '+':
             case '-':
@@ -8330,6 +8348,7 @@ void ProcessExpressionType(Expression exp)
             case '%':
                useSideType = true;
                useDestType = true;
+               if(exp.op.op == '/') powerOp = true;
                break;
             case '&':
             case '*':
@@ -8338,6 +8357,7 @@ void ProcessExpressionType(Expression exp)
                   // For & operator, useDestType nicely ensures the result will fit in a bool (TODO: Fix for generic enum)
                   useSideType = true;
                   useDestType = true;
+                  if(exp.op.op == '*') powerOp = true;
                }
                break;
 
@@ -8395,6 +8415,17 @@ void ProcessExpressionType(Expression exp)
                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                exp.op.exp1.destType = dummy;
                dummy.refCount++;
+               if(powerOp)
+                  exp.op.exp1.opDestType = true;
+               if(relationOp)
+                  exp.op.exp1.usedInComparison = true;
+            }
+            if(exp.op.op == '+' || exp.op.op == '-')
+            {
+               if(exp.opDestType)
+                  exp.op.exp1.parentOpDestType = true;
+               if(exp.usedInComparison)
+                  exp.op.exp1.usedInComparison = true;
             }
 
             // TESTING THIS HERE...
@@ -8403,6 +8434,7 @@ void ProcessExpressionType(Expression exp)
             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count--;
 
             exp.op.exp1.opDestType = false;
+            exp.op.exp1.usedInComparison = false;
 
             // Fix for unit and ++ / --
             if(!exp.op.exp2 && (exp.op.op == INC_OP || exp.op.op == DEC_OP) && exp.op.exp1.expType && exp.op.exp1.expType.kind == classType &&
@@ -8506,6 +8538,10 @@ void ProcessExpressionType(Expression exp)
                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                exp.op.exp2.destType = dummy;
                dummy.refCount++;
+               if(powerOp)
+                  exp.op.exp2.opDestType = true;
+               if(relationOp)
+                  exp.op.exp2.usedInComparison = true;
             }
 
             // TESTING THIS HERE... (DANGEROUS)
@@ -8534,8 +8570,16 @@ void ProcessExpressionType(Expression exp)
                if(e.type == castExp && e.cast.exp)
                   e.cast.exp.needCast = true;
             }
+            if(exp.op.op == '+' || exp.op.op == '-')
+            {
+               if(exp.opDestType)
+                  exp.op.exp2.parentOpDestType = true;
+               if(exp.usedInComparison)
+                  exp.op.exp2.usedInComparison = true;
+            }
             ProcessExpressionType(exp.op.exp2);
             exp.op.exp2.opDestType = false;
+            exp.op.exp2.usedInComparison = false;
             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
 
             if(!assign && (exp.op.exp1 || exp.op.op == '~'))
@@ -8609,6 +8653,24 @@ void ProcessExpressionType(Expression exp)
                if(type2) type2.refCount++;
             }
          }
+         c1 = type1 && type1.kind == classType && type1._class ? type1._class.registered : null;
+         c2 = type2 && type2.kind == classType && type2._class ? type2._class.registered : null;
+
+         if(relationOp &&
+            ( (exp.op.exp1 && exp.op.exp1.ambiguousUnits && (!c2 || c2.type != unitClass)) ||
+               (exp.op.exp2 && exp.op.exp2.ambiguousUnits && (!c1 || c1.type != unitClass))) )
+            Compiler_Warning($"ambiguous units in relation operation\n");
+
+         if(!relationOp &&
+            ((exp.op.exp1 && exp.op.exp1.ambiguousUnits) ||
+             (exp.op.exp2 && exp.op.exp2.ambiguousUnits)) &&
+             (!powerOp || !c1 || c1.type != unitClass || !c2 || c2.type != unitClass || !RelatedUnits(c1, c2)))
+         {
+            if(exp.opDestType || exp.usedInComparison)
+               exp.ambiguousUnits = true;
+            else
+               Compiler_Warning($"ambiguous units\n");
+         }
 
          dummy.kind = voidType;
 
@@ -8640,6 +8702,11 @@ void ProcessExpressionType(Expression exp)
          }
          else if(!assign)
          {
+            if(c1 && !c1.dataType)
+               c1.dataType = ProcessTypeString(c1.dataTypeString, false);
+            if(c2 && !c2.dataType)
+               c2.dataType = ProcessTypeString(c2.dataTypeString, false);
+
             if(boolOps)
             {
                if(exp.op.exp1)
@@ -8669,11 +8736,33 @@ void ProcessExpressionType(Expression exp)
                   exp.op.exp2.expType.truth = true;
                }
             }
+            else if(powerOp && exp.op.exp1 && exp.op.exp2 && ((c1 && c1.type == unitClass) || (c2 && c2.type == unitClass)))
+            {
+               // * or / with at least one unit operand
+               if(c1 && c1.type == unitClass && c2 && c2.type == unitClass)
+               {
+                  // This is where we'd handle unit powers e.g. square meters or meters/seconds
+                  // For now using base types
+                  if(c1.dataType.kind == doubleType)        exp.expType = c1.dataType;
+                  else if(c2.dataType.kind == doubleType)   exp.expType = c2.dataType;
+                  else if(c1.dataType.kind == floatType)    exp.expType = c1.dataType;
+                  else if(c2.dataType.kind == floatType)    exp.expType = c2.dataType;
+                  else
+                     exp.expType = c1.dataType;
+               }
+               else if((c1 && c1.type == unitClass) || exp.op.op == '/')   // 1/units should not be typed with unit
+                  exp.expType = type1;
+               else
+                  exp.expType = type2;
+
+               if(exp.expType)
+                  exp.expType.refCount++;
+            }
             else if(exp.op.exp1 && exp.op.exp2 &&
                ((useSideType /*&&
                      (useSideUnit ||
-                        ((!type1 || type1.kind != classType || type1._class.registered.type != unitClass) &&
-                         (!type2 || type2.kind != classType || type2._class.registered.type != unitClass)))*/) ||
+                        ((!c1 || c1.type != unitClass) &&
+                         (!c2 || c2.type != unitClass)))*/) ||
                   ((!type1 || type1.kind != classType || !strcmp(type1._class.string, "String")) &&
                   (!type2 || type2.kind != classType || !strcmp(type2._class.string, "String")))))
             {
@@ -8682,18 +8771,9 @@ void ProcessExpressionType(Expression exp)
                   ((type1.kind == classType && type1._class && strcmp(type1._class.string, "String")) == (type2.kind == classType && type2._class && strcmp(type2._class.string, "String"))))
                {
                   // 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)) )
+                  if(exp.op.op == '-' && ((c1 && c1.type == enumClass) || (c2 && c2.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);
+                     Type intType = ProcessTypeString((c1 && c1.dataType.kind == int64Type) || (c2 && c2.dataType.kind == int64Type) ? "int64" : "int", false);
 
                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
@@ -8712,12 +8792,17 @@ void ProcessExpressionType(Expression exp)
                   }
 
                   // Warning here for adding Radians + Degrees with no destination type
-                  if(!boolResult && type1.kind == classType && (!exp.destType || exp.destType.kind != classType) &&
-                     type1._class.registered && type1._class.registered.type == unitClass &&
-                     type2._class.registered && type2._class.registered.type == unitClass &&
-                     type1._class.registered != type2._class.registered)
-                     Compiler_Warning($"operating on %s and %s with an untyped result, assuming %s\n",
-                        type1._class.string, type2._class.string, type1._class.string);
+                  if(!boolResult && !exp.opDestType && (!exp.destType || exp.destType.kind != classType) &&
+                     c1 && c1.type == unitClass &&
+                     c2 && c2.type == unitClass &&
+                     c1 != c2)
+                  {
+                     if(exp.usedInComparison || exp.parentOpDestType)
+                        exp.ambiguousUnits = true;
+                     else
+                        Compiler_Warning($"operating on %s and %s with an untyped result, assuming %s\n",
+                           type1._class.string, type2._class.string, type1._class.string);
+                  }
 
                   if(type1.kind == pointerType && type1.type.kind == templateType && type2.kind != pointerType)
                   {
@@ -8742,7 +8827,7 @@ void ProcessExpressionType(Expression exp)
                            {
                               if(type2)
                                  FreeType(type2);
-                              type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
+                              type2 = exp.op.exp2.expType = ProcessTypeString("int", false); c2 = null;
                               type2.refCount++;
                            }
 
@@ -8875,7 +8960,7 @@ void ProcessExpressionType(Expression exp)
                   }
                }
                // ADDED THESE TWO FROM OUTSIDE useSideType CHECK
-               else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type2 && type1 && type2.kind == classType && type1.kind != classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
+               else if(!boolResult && !useSideUnit && c2 && c2.type == unitClass && type1 && type1.kind != classType)
                {
                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                   // Convert e.g. / 4 into / 4.0
@@ -8886,7 +8971,7 @@ void ProcessExpressionType(Expression exp)
                   exp.expType = type2;
                   if(type2) type2.refCount++;
                }
-               else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type1 && type2 && type1.kind == classType && type2.kind != classType && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
+               else if(!boolResult && !useSideUnit && c1 && c1.type == unitClass && type2 && type2.kind != classType)
                {
                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                   // Convert e.g. / 4 into / 4.0
@@ -8901,36 +8986,34 @@ void ProcessExpressionType(Expression exp)
                {
                   bool valid = false;
 
-                  if(!boolResult && useSideUnit && type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
+                  if(!boolResult && useSideUnit && c1 && c1.type == unitClass && type2 && type2.kind != classType)
                   {
                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
 
-                     if(!type1._class.registered.dataType)
-                        type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
-                     exp.op.exp2.destType = type1._class.registered.dataType;
+                     exp.op.exp2.destType = c1.dataType;
                      exp.op.exp2.destType.refCount++;
 
                      CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
                      if(type2)
                         FreeType(type2);
                      type2 = exp.op.exp2.destType;
+                     c2 = type2 && type2.kind == classType && type2._class ? type2._class.registered : null;
                      if(type2) type2.refCount++;
 
                      exp.expType = type2;
                      type2.refCount++;
                   }
 
-                  if(!boolResult && useSideUnit && type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
+                  if(!boolResult && useSideUnit && c2 && c2.type == unitClass && type1 && type1.kind != classType)
                   {
                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
 
-                     if(!type2._class.registered.dataType)
-                        type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
-                     exp.op.exp1.destType = type2._class.registered.dataType;
+                     exp.op.exp1.destType = c2.dataType;
                      exp.op.exp1.destType.refCount++;
 
                      CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
                      type1 = exp.op.exp1.destType;
+                     c1 = type1 && type1.kind == classType && type1._class ? type1._class.registered : null;
                      exp.expType = type1;
                      type1.refCount++;
                   }
@@ -8938,8 +9021,8 @@ void ProcessExpressionType(Expression exp)
                   // TESTING THIS NEW CODE
                   if(!boolResult || exp.op.op == '>' || exp.op.op == '<' || exp.op.op == GE_OP || exp.op.op == LE_OP)
                   {
-                     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;
+                     bool op1IsEnum = c1 && c1.type == enumClass;
+                     bool op2IsEnum = c2 && c2.type == enumClass;
                      if(exp.op.op == '*' || exp.op.op == '/' || exp.op.op == '-' || exp.op.op == '|' || exp.op.op == '^')
                      {
                         // Convert the enum to an int instead for these operators
@@ -8992,8 +9075,7 @@ void ProcessExpressionType(Expression exp)
                   if(!valid)
                   {
                      // 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(c2 && c2.type == unitClass && (!c1 || c1.type != unitClass))
                      {
                         if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                         exp.op.exp1.destType = type2;
@@ -9080,12 +9162,12 @@ void ProcessExpressionType(Expression exp)
 
                            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)
+                           if(c1 && c1.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)
+                           else if(c2 && c2.type == enumClass)
                            {
                               exp.expType = exp.op.exp2.expType;
                               if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
@@ -9097,7 +9179,7 @@ void ProcessExpressionType(Expression exp)
                else if(type2)
                {
                   // Maybe this was meant to be an enum...
-                  if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
+                  if(c2 && c2.type == enumClass)
                   {
                      Type oldType = exp.op.exp1.expType;
                      exp.op.exp1.expType = null;
@@ -9140,7 +9222,7 @@ void ProcessExpressionType(Expression exp)
             }
             else if(type2 && (!type1 || (type2.kind == classType && type1.kind != classType)))
             {
-               if(type1 && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
+               if(type1 && c2 && c2.type == unitClass)
                {
                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                   // Convert e.g. / 4 into / 4.0
@@ -9162,7 +9244,7 @@ void ProcessExpressionType(Expression exp)
             }
             else if(type1 && (!type2 || (type1.kind == classType && type2.kind != classType)))
             {
-               if(type2 && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
+               if(c2 && c2.type == unitClass)
                {
                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                   // Convert e.g. / 4 into / 4.0
@@ -9240,10 +9322,14 @@ void ProcessExpressionType(Expression exp)
             {
                FreeType(e.destType);
                e.opDestType = exp.opDestType;
+               e.usedInComparison = exp.usedInComparison;
+               e.parentOpDestType = exp.parentOpDestType;
                e.destType = exp.destType;
                if(e.destType) { exp.destType.refCount++; /*e.destType.count++; inced = true;*/ }
             }
             ProcessExpressionType(e);
+            if(e.ambiguousUnits)
+               exp.ambiguousUnits = true;
             /*if(inced)
                exp.destType.count--;*/
             if(!exp.expType && !e.next)
index ad01f5b..f9999ab 100644 (file)
@@ -119,7 +119,7 @@ public class Degrees : Angle
       //get { return (Angle)this * Pi / 180; }
       //set { return (Angle)(value * 180 / Pi); }
       get { return this * (double)Pi / 180; }
-      set { return (double)value * 180 / Pi; }
+      set { return Angle { value * 180 / Pi }; }
    }
 }