- 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)
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
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;
}
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
this->needCast = 0;
this->thisPtr = 0;
this->opDestType = 0;
+this->parentOpDestType = 0;
+this->usedInComparison = 0;
this->needTemplateCast = 0;
}
__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)
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
}
}
+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;
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);
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)
case NE_OP:
boolResult = 1;
useSideType = 1;
+relationOp = 1;
break;
case '+':
case '-':
case '%':
useSideType = 1;
useDestType = 1;
+if(exp->__anon1.op.op == '/')
+powerOp = 1;
break;
case '&':
case '*':
{
useSideType = 1;
useDestType = 1;
+if(exp->__anon1.op.op == '*')
+powerOp = 1;
}
break;
}
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++;
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");
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))
{
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 == '~'))
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)
{
}
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)
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)
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);
if(type2)
FreeType(type2);
type2 = exp->__anon1.op.exp2->expType = ProcessTypeString("int", 0);
+c2 = (((void *)0));
type2->refCount++;
}
ProcessExpressionType(exp->__anon1.op.exp2);
}
}
}
-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);
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);
{
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 == '^')
{
}
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);
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)
}
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;
}
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);
}
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);
{
FreeType(e->destType);
e->opDestType = exp->opDestType;
+e->usedInComparison = exp->usedInComparison;
+e->parentOpDestType = exp->parentOpDestType;
e->destType = exp->destType;
if(e->destType)
{
}
}
ProcessExpressionType(e);
+if(e->ambiguousUnits)
+exp->ambiguousUnits = 1;
if(!exp->expType && !e->next)
{
exp->expType = e->expType;
__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);
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
unsigned int needCast;
unsigned int thisPtr;
unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
unsigned int needTemplateCast;
} ecere_gcc_struct;
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;
bool needCast;
bool thisPtr;
bool opDestType;
+ bool usedInComparison;
+ bool ambiguousUnits;
+ bool parentOpDestType;
uint needTemplateCast;
void Clear()
needCast = false;
thisPtr = false;
opDestType = false;
+ parentOpDestType = false;
+ usedInComparison = false;
needTemplateCast = 0;
}
};
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);
}
}
+bool RelatedUnits(Class c1, Class c2)
+{
+ if(c1.base.type == unitClass) c1 = c1.base;
+ if(c2.base.type == unitClass) c2 = c2.base;
+ return c1 == c2;
+}
+
void ProcessExpressionType(Expression exp)
{
bool unresolved = false;
Location oldyylloc = yylloc;
bool 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
// Gives boolean result
boolResult = true;
useSideType = true;
+ relationOp = true;
break;
case '+':
case '-':
case '%':
useSideType = true;
useDestType = true;
+ if(exp.op.op == '/') powerOp = true;
break;
case '&':
case '*':
// 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;
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...
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 &&
if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
exp.op.exp2.destType = dummy;
dummy.refCount++;
+ if(powerOp)
+ exp.op.exp2.opDestType = true;
+ if(relationOp)
+ exp.op.exp2.usedInComparison = true;
}
// TESTING THIS HERE... (DANGEROUS)
if(e.type == castExp && e.cast.exp)
e.cast.exp.needCast = true;
}
+ if(exp.op.op == '+' || exp.op.op == '-')
+ {
+ if(exp.opDestType)
+ exp.op.exp2.parentOpDestType = true;
+ if(exp.usedInComparison)
+ exp.op.exp2.usedInComparison = true;
+ }
ProcessExpressionType(exp.op.exp2);
exp.op.exp2.opDestType = false;
+ exp.op.exp2.usedInComparison = false;
if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
if(!assign && (exp.op.exp1 || exp.op.op == '~'))
if(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;
}
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)
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")))))
{
((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);
}
// 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)
{
{
if(type2)
FreeType(type2);
- type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
+ type2 = exp.op.exp2.expType = ProcessTypeString("int", false); c2 = null;
type2.refCount++;
}
}
}
// ADDED THESE TWO FROM OUTSIDE useSideType CHECK
- else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type2 && type1 && type2.kind == classType && type1.kind != classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
+ else if(!boolResult && !useSideUnit && c2 && c2.type == unitClass && type1 && type1.kind != classType)
{
if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
// Convert e.g. / 4 into / 4.0
exp.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
{
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++;
}
// 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
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;
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++;
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;
}
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
}
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
{
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)
//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 }; }
}
}