Be type-strict checking on equality checks

After a short discussion with @reduz and @karroffel we decided to make
all non number/number comparisons return type errors on comparisons.

Now bool == bool is allowed but Vector2 == Vector3 is a type error and
no longer 'not equal'. The same has been done for the != operators.

In addition I forgot to add some failures to some Object operators
meaning that there was a potential for a crasher.
This commit is contained in:
Hein-Pieter van Braam 2017-09-18 13:09:06 +02:00
parent 33e1716f13
commit 85641c545b

View file

@ -421,11 +421,12 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
if (p_b.type == NIL) _RETURN(true); if (p_b.type == NIL) _RETURN(true);
if (p_b.type == OBJECT) if (p_b.type == OBJECT)
_RETURN(p_b._get_obj().obj == NULL); _RETURN(p_b._get_obj().obj == NULL);
_RETURN(false); _RETURN_FAIL;
} }
CASE_TYPE(math, OP_EQUAL, BOOL) { CASE_TYPE(math, OP_EQUAL, BOOL) {
if (p_b.type != BOOL) _RETURN(false); if (p_b.type != BOOL)
_RETURN_FAIL;
_RETURN(p_a._data._bool == p_b._data._bool); _RETURN(p_a._data._bool == p_b._data._bool);
} }
@ -434,11 +435,12 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
_RETURN((p_a._get_obj().obj == p_b._get_obj().obj)); _RETURN((p_a._get_obj().obj == p_b._get_obj().obj));
if (p_b.type == NIL) if (p_b.type == NIL)
_RETURN(p_a._get_obj().obj == NULL); _RETURN(p_a._get_obj().obj == NULL);
_RETURN_FAIL;
} }
CASE_TYPE(math, OP_EQUAL, DICTIONARY) { CASE_TYPE(math, OP_EQUAL, DICTIONARY) {
if (p_b.type != DICTIONARY) if (p_b.type != DICTIONARY)
_RETURN(false); _RETURN_FAIL;
const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem);
const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem);
@ -448,7 +450,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_EQUAL, ARRAY) { CASE_TYPE(math, OP_EQUAL, ARRAY) {
if (p_b.type != ARRAY) if (p_b.type != ARRAY)
_RETURN(false); _RETURN_FAIL;
const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
@ -495,11 +497,12 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
if (p_b.type == NIL) _RETURN(false); if (p_b.type == NIL) _RETURN(false);
if (p_b.type == OBJECT) if (p_b.type == OBJECT)
_RETURN(p_b._get_obj().obj != NULL); _RETURN(p_b._get_obj().obj != NULL);
_RETURN(true); _RETURN_FAIL;
} }
CASE_TYPE(math, OP_NOT_EQUAL, BOOL) { CASE_TYPE(math, OP_NOT_EQUAL, BOOL) {
if (p_b.type != BOOL) _RETURN(true); if (p_b.type != BOOL)
_RETURN_FAIL;
_RETURN(p_a._data._bool != p_b._data._bool); _RETURN(p_a._data._bool != p_b._data._bool);
} }
@ -508,11 +511,12 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
_RETURN((p_a._get_obj().obj != p_b._get_obj().obj)); _RETURN((p_a._get_obj().obj != p_b._get_obj().obj));
if (p_b.type == NIL) if (p_b.type == NIL)
_RETURN(p_a._get_obj().obj != NULL); _RETURN(p_a._get_obj().obj != NULL);
_RETURN_FAIL;
} }
CASE_TYPE(math, OP_NOT_EQUAL, DICTIONARY) { CASE_TYPE(math, OP_NOT_EQUAL, DICTIONARY) {
if (p_b.type != DICTIONARY) if (p_b.type != DICTIONARY)
_RETURN(true); _RETURN_FAIL;
const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem);
const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem);
@ -522,7 +526,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_NOT_EQUAL, ARRAY) { CASE_TYPE(math, OP_NOT_EQUAL, ARRAY) {
if (p_b.type != ARRAY) if (p_b.type != ARRAY)
_RETURN(true); _RETURN_FAIL;
const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
@ -580,13 +584,14 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
} }
CASE_TYPE(math, OP_LESS, OBJECT) { CASE_TYPE(math, OP_LESS, OBJECT) {
if (p_b.type == OBJECT) if (p_b.type != OBJECT)
_RETURN_FAIL;
_RETURN((p_a._get_obj().obj < p_b._get_obj().obj)); _RETURN((p_a._get_obj().obj < p_b._get_obj().obj));
} }
CASE_TYPE(math, OP_LESS, ARRAY) { CASE_TYPE(math, OP_LESS, ARRAY) {
if (p_b.type != ARRAY) if (p_b.type != ARRAY)
_RETURN(false); _RETURN_FAIL;
const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
@ -633,7 +638,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
SWITCH_OP(math, OP_LESS_EQUAL, p_a.type) { SWITCH_OP(math, OP_LESS_EQUAL, p_a.type) {
CASE_TYPE(math, OP_LESS_EQUAL, OBJECT) { CASE_TYPE(math, OP_LESS_EQUAL, OBJECT) {
if (p_b.type == OBJECT) if (p_b.type != OBJECT)
_RETURN_FAIL;
_RETURN((p_a._get_obj().obj <= p_b._get_obj().obj)); _RETURN((p_a._get_obj().obj <= p_b._get_obj().obj));
} }
@ -682,13 +688,14 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
} }
CASE_TYPE(math, OP_GREATER, OBJECT) { CASE_TYPE(math, OP_GREATER, OBJECT) {
if (p_b.type == OBJECT) if (p_b.type != OBJECT)
_RETURN_FAIL;
_RETURN((p_a._get_obj().obj > p_b._get_obj().obj)); _RETURN((p_a._get_obj().obj > p_b._get_obj().obj));
} }
CASE_TYPE(math, OP_GREATER, ARRAY) { CASE_TYPE(math, OP_GREATER, ARRAY) {
if (p_b.type != ARRAY) if (p_b.type != ARRAY)
_RETURN(false); _RETURN_FAIL;
const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
@ -735,7 +742,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
SWITCH_OP(math, OP_GREATER_EQUAL, p_a.type) { SWITCH_OP(math, OP_GREATER_EQUAL, p_a.type) {
CASE_TYPE(math, OP_GREATER_EQUAL, OBJECT) { CASE_TYPE(math, OP_GREATER_EQUAL, OBJECT) {
if (p_b.type == OBJECT) if (p_b.type != OBJECT)
_RETURN_FAIL;
_RETURN((p_a._get_obj().obj >= p_b._get_obj().obj)); _RETURN((p_a._get_obj().obj >= p_b._get_obj().obj));
} }
@ -771,10 +779,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
SWITCH_OP(math, OP_ADD, p_a.type) { SWITCH_OP(math, OP_ADD, p_a.type) {
CASE_TYPE(math, OP_ADD, ARRAY) { CASE_TYPE(math, OP_ADD, ARRAY) {
if (p_a.type != p_b.type) { if (p_a.type != p_b.type)
r_valid = false; _RETURN_FAIL;
return;
}
const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem); const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem);
const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem); const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem);
Array sum; Array sum;
@ -853,65 +860,54 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
SWITCH_OP(math, OP_MULTIPLY, p_a.type) { SWITCH_OP(math, OP_MULTIPLY, p_a.type) {
CASE_TYPE(math, OP_MULTIPLY, TRANSFORM2D) { CASE_TYPE(math, OP_MULTIPLY, TRANSFORM2D) {
if (p_b.type == TRANSFORM2D) { switch (p_b.type) {
case TRANSFORM2D: {
_RETURN(*p_a._data._transform2d * *p_b._data._transform2d); _RETURN(*p_a._data._transform2d * *p_b._data._transform2d);
}; }
if (p_b.type == VECTOR2) { case VECTOR2: {
_RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem)); _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem));
}; }
r_valid = false; default: _RETURN_FAIL;
return; }
} }
CASE_TYPE(math, OP_MULTIPLY, QUAT) { CASE_TYPE(math, OP_MULTIPLY, QUAT) {
switch (p_b.type) { switch (p_b.type) {
case VECTOR3: { case VECTOR3: {
_RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem)); _RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem));
} break; }
case QUAT: { case QUAT: {
_RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem)); _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem));
} break; }
case REAL: { case REAL: {
_RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._real); _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._real);
} break; }
default: {} default: _RETURN_FAIL;
}; }
r_valid = false;
return;
} }
CASE_TYPE(math, OP_MULTIPLY, BASIS) { CASE_TYPE(math, OP_MULTIPLY, BASIS) {
switch (p_b.type) { switch (p_b.type) {
case VECTOR3: { case VECTOR3: {
_RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem)); _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem));
}; }
case BASIS: { case BASIS: {
_RETURN(*p_a._data._basis * *p_b._data._basis); _RETURN(*p_a._data._basis * *p_b._data._basis);
}; }
default: {} default: _RETURN_FAIL;
}; }
r_valid = false;
return;
} }
CASE_TYPE(math, OP_MULTIPLY, TRANSFORM) { CASE_TYPE(math, OP_MULTIPLY, TRANSFORM) {
switch (p_b.type) { switch (p_b.type) {
case VECTOR3: { case VECTOR3: {
_RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem)); _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem));
}; }
case TRANSFORM: { case TRANSFORM: {
_RETURN(*p_a._data._transform * *p_b._data._transform); _RETURN(*p_a._data._transform * *p_b._data._transform);
}; }
default: {} default: _RETURN_FAIL;
}; }
r_valid = false;
return;
} }
DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, INT, *, _int); DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, INT, *, _int);
@ -943,18 +939,15 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
SWITCH_OP(math, OP_DIVIDE, p_a.type) { SWITCH_OP(math, OP_DIVIDE, p_a.type) {
CASE_TYPE(math, OP_DIVIDE, QUAT) { CASE_TYPE(math, OP_DIVIDE, QUAT) {
if (p_b.type != REAL) { if (p_b.type != REAL)
r_valid = false; _RETURN_FAIL;
return;
}
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (p_b._data._real == 0) { if (p_b._data._real == 0) {
r_valid = false; r_valid = false;
_RETURN("Division By Zero"); _RETURN("Division By Zero");
} }
#endif #endif
_RETURN( _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._real);
*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._real);
} }
DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, INT, _int); DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, INT, _int);
@ -1054,9 +1047,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
SWITCH_OP(math, OP_MODULE, p_a.type) { SWITCH_OP(math, OP_MODULE, p_a.type) {
CASE_TYPE(math, OP_MODULE, INT) { CASE_TYPE(math, OP_MODULE, INT) {
if (p_b.type != INT) { if (p_b.type != INT)
_RETURN_FAIL; _RETURN_FAIL;
}
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (p_b._data._int == 0) { if (p_b._data._int == 0) {
r_valid = false; r_valid = false;
@ -1067,15 +1059,13 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
} }
CASE_TYPE(math, OP_MODULE, STRING) { CASE_TYPE(math, OP_MODULE, STRING) {
const String *format = const String *format = reinterpret_cast<const String *>(p_a._data._mem);
reinterpret_cast<const String *>(p_a._data._mem);
String result; String result;
bool error; bool error;
if (p_b.type == ARRAY) { if (p_b.type == ARRAY) {
// e.g. "frog %s %d" % ["fish", 12] // e.g. "frog %s %d" % ["fish", 12]
const Array *args = const Array *args = reinterpret_cast<const Array *>(p_b._data._mem);
reinterpret_cast<const Array *>(p_b._data._mem);
result = format->sprintf(*args, &error); result = format->sprintf(*args, &error);
} else { } else {
// e.g. "frog %d" % 12 // e.g. "frog %d" % 12
@ -1127,6 +1117,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
_RETURN_FAIL; _RETURN_FAIL;
_RETURN(p_a._data._int << p_b._data._int); _RETURN(p_a._data._int << p_b._data._int);
} }
CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_LEFT) CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_LEFT)
_RETURN_FAIL; _RETURN_FAIL;
} }
@ -1137,6 +1128,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
_RETURN_FAIL; _RETURN_FAIL;
_RETURN(p_a._data._int >> p_b._data._int); _RETURN(p_a._data._int >> p_b._data._int);
} }
CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_RIGHT) CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_RIGHT)
_RETURN_FAIL; _RETURN_FAIL;
} }
@ -1147,6 +1139,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
_RETURN_FAIL; _RETURN_FAIL;
_RETURN(p_a._data._int & p_b._data._int); _RETURN(p_a._data._int & p_b._data._int);
} }
CASE_TYPE_ALL_BUT_INT(math, OP_BIT_AND) CASE_TYPE_ALL_BUT_INT(math, OP_BIT_AND)
_RETURN_FAIL; _RETURN_FAIL;
} }
@ -1157,6 +1150,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
_RETURN_FAIL; _RETURN_FAIL;
_RETURN(p_a._data._int | p_b._data._int); _RETURN(p_a._data._int | p_b._data._int);
} }
CASE_TYPE_ALL_BUT_INT(math, OP_BIT_OR) CASE_TYPE_ALL_BUT_INT(math, OP_BIT_OR)
_RETURN_FAIL; _RETURN_FAIL;
} }
@ -1167,6 +1161,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
_RETURN_FAIL; _RETURN_FAIL;
_RETURN(p_a._data._int ^ p_b._data._int); _RETURN(p_a._data._int ^ p_b._data._int);
} }
CASE_TYPE_ALL_BUT_INT(math, OP_BIT_XOR) CASE_TYPE_ALL_BUT_INT(math, OP_BIT_XOR)
_RETURN_FAIL; _RETURN_FAIL;
} }
@ -1175,6 +1170,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
CASE_TYPE(math, OP_BIT_NEGATE, INT) { CASE_TYPE(math, OP_BIT_NEGATE, INT) {
_RETURN(~p_a._data._int); _RETURN(~p_a._data._int);
} }
CASE_TYPE_ALL_BUT_INT(math, OP_BIT_NEGATE) CASE_TYPE_ALL_BUT_INT(math, OP_BIT_NEGATE)
_RETURN_FAIL; _RETURN_FAIL;
} }