Fix arithmetic operations with integers (#993)
Also fixed unsigned right shift operator ">>>"blender-script
parent
a66b3d0672
commit
250ea57e8b
|
@ -129,6 +129,13 @@ bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (op == ID_ASR || op == ID_SR || op == ID_SL ||
|
||||||
|
op == ID_ASSOR || op == ID_ASSSL || op == ID_ASSSR ||
|
||||||
|
op == ID_ASSAND || op == ID_ASSXOR || op == ID_ASSASR)
|
||||||
|
{
|
||||||
|
if (max > CBotTypLong) return false;
|
||||||
|
}
|
||||||
|
|
||||||
type1.SetType(max);
|
type1.SetType(max);
|
||||||
type2.SetType(max);
|
type2.SetType(max);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -103,7 +103,7 @@ static const boost::bimap<TokenId, std::string> KEYWORDS = makeBimap<TokenId, st
|
||||||
{ID_ASSSR, ">>>="},
|
{ID_ASSSR, ">>>="},
|
||||||
{ID_ASSASR, ">>="},
|
{ID_ASSASR, ">>="},
|
||||||
{ID_SL, "<<"},
|
{ID_SL, "<<"},
|
||||||
{ID_SR, ">>"},
|
{ID_SR, ">>>"},
|
||||||
{ID_ASR, ">>"},
|
{ID_ASR, ">>"},
|
||||||
{ID_INC, "++"},
|
{ID_INC, "++"},
|
||||||
{ID_DEC, "--"},
|
{ID_DEC, "--"},
|
||||||
|
|
|
@ -752,6 +752,11 @@ CBotClass* CBotVar::GetClass()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBotVar::operator bool()
|
||||||
|
{
|
||||||
|
return static_cast<bool>(GetValInt());
|
||||||
|
}
|
||||||
|
|
||||||
CBotVar::operator int()
|
CBotVar::operator int()
|
||||||
{
|
{
|
||||||
return GetValInt();
|
return GetValInt();
|
||||||
|
|
|
@ -444,6 +444,7 @@ public:
|
||||||
*/
|
*/
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
operator bool();
|
||||||
operator int();
|
operator int();
|
||||||
operator float();
|
operator float();
|
||||||
operator std::string();
|
operator std::string();
|
||||||
|
|
|
@ -58,33 +58,9 @@ void CBotVarInt::Dec()
|
||||||
m_defnum.clear();
|
m_defnum.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBotVarInt::XOr(CBotVar* left, CBotVar* right)
|
|
||||||
{
|
|
||||||
SetValInt(left->GetValInt() ^ right->GetValInt());
|
|
||||||
}
|
|
||||||
void CBotVarInt::And(CBotVar* left, CBotVar* right)
|
|
||||||
{
|
|
||||||
SetValInt(left->GetValInt() & right->GetValInt());
|
|
||||||
}
|
|
||||||
void CBotVarInt::Or(CBotVar* left, CBotVar* right)
|
|
||||||
{
|
|
||||||
SetValInt(left->GetValInt() | right->GetValInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBotVarInt::SL(CBotVar* left, CBotVar* right)
|
|
||||||
{
|
|
||||||
SetValInt(left->GetValInt() << right->GetValInt());
|
|
||||||
}
|
|
||||||
void CBotVarInt::ASR(CBotVar* left, CBotVar* right)
|
|
||||||
{
|
|
||||||
SetValInt(left->GetValInt() >> right->GetValInt());
|
|
||||||
}
|
|
||||||
void CBotVarInt::SR(CBotVar* left, CBotVar* right)
|
void CBotVarInt::SR(CBotVar* left, CBotVar* right)
|
||||||
{
|
{
|
||||||
int source = left->GetValInt();
|
SetValInt(static_cast<unsigned>(left->GetValInt()) >> right->GetValInt());
|
||||||
int shift = right->GetValInt();
|
|
||||||
if (shift >= 1) source &= 0x7fffffff;
|
|
||||||
SetValInt(source >> shift);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBotVarInt::Not()
|
void CBotVarInt::Not()
|
||||||
|
|
|
@ -27,10 +27,10 @@ namespace CBot
|
||||||
/**
|
/**
|
||||||
* \brief CBotVar subclass for managing integer values (::CBotTypInt)
|
* \brief CBotVar subclass for managing integer values (::CBotTypInt)
|
||||||
*/
|
*/
|
||||||
class CBotVarInt : public CBotVarNumber<int, CBotTypInt>
|
class CBotVarInt : public CBotVarInteger<int, CBotTypInt>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CBotVarInt(const CBotToken &name) : CBotVarNumber(name) {}
|
CBotVarInt(const CBotToken &name) : CBotVarInteger(name) {}
|
||||||
|
|
||||||
void SetValInt(int val, const std::string& s = "") override;
|
void SetValInt(int val, const std::string& s = "") override;
|
||||||
std::string GetValString() override;
|
std::string GetValString() override;
|
||||||
|
@ -40,19 +40,21 @@ public:
|
||||||
void Neg() override;
|
void Neg() override;
|
||||||
void Inc() override;
|
void Inc() override;
|
||||||
void Dec() override;
|
void Dec() override;
|
||||||
|
|
||||||
void XOr(CBotVar* left, CBotVar* right) override;
|
|
||||||
void Or(CBotVar* left, CBotVar* right) override;
|
|
||||||
void And(CBotVar* left, CBotVar* right) override;
|
|
||||||
void Not() override;
|
void Not() override;
|
||||||
|
|
||||||
void SL(CBotVar* left, CBotVar* right) override;
|
|
||||||
void SR(CBotVar* left, CBotVar* right) override;
|
void SR(CBotVar* left, CBotVar* right) override;
|
||||||
void ASR(CBotVar* left, CBotVar* right) override;
|
|
||||||
|
|
||||||
bool Save0State(std::ostream &ostr) override;
|
bool Save0State(std::ostream &ostr) override;
|
||||||
bool Save1State(std::ostream &ostr) override;
|
bool Save1State(std::ostream &ostr) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void SetValue(int val) override
|
||||||
|
{
|
||||||
|
CBotVarNumberBase::SetValue(val);
|
||||||
|
m_defnum.clear();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! The name if given by DefineNum.
|
//! The name if given by DefineNum.
|
||||||
std::string m_defnum;
|
std::string m_defnum;
|
||||||
|
|
|
@ -74,6 +74,13 @@ public:
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void SetValue(T val)
|
||||||
|
{
|
||||||
|
this->m_val = val;
|
||||||
|
this->m_binit = CBotVar::InitType::DEF;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! The value
|
//! The value
|
||||||
T m_val;
|
T m_val;
|
||||||
|
@ -93,14 +100,12 @@ public:
|
||||||
|
|
||||||
void SetValInt(int val, const std::string &s = "") override
|
void SetValInt(int val, const std::string &s = "") override
|
||||||
{
|
{
|
||||||
this->m_val = static_cast<T>(val);
|
this->SetValue(static_cast<T>(val));
|
||||||
this->m_binit = CBotVar::InitType::DEF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetValFloat(float val) override
|
void SetValFloat(float val) override
|
||||||
{
|
{
|
||||||
this->m_val = static_cast<T>(val);
|
this->SetValue(static_cast<T>(val));
|
||||||
this->m_binit = CBotVar::InitType::DEF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetValInt() override
|
int GetValInt() override
|
||||||
|
@ -116,11 +121,11 @@ public:
|
||||||
|
|
||||||
bool Eq(CBotVar* left, CBotVar* right) override
|
bool Eq(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
return left->GetValFloat() == right->GetValFloat();
|
return static_cast<T>(*left) == static_cast<T>(*right);
|
||||||
}
|
}
|
||||||
bool Ne(CBotVar* left, CBotVar* right) override
|
bool Ne(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
return left->GetValFloat() != right->GetValFloat();
|
return static_cast<T>(*left) != static_cast<T>(*right);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -135,33 +140,33 @@ public:
|
||||||
|
|
||||||
void Mul(CBotVar* left, CBotVar* right) override
|
void Mul(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
this->SetValFloat(left->GetValFloat() * right->GetValFloat());
|
this->SetValue(static_cast<T>(*left) * static_cast<T>(*right));
|
||||||
}
|
}
|
||||||
void Power(CBotVar* left, CBotVar* right) override
|
void Power(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
this->SetValFloat(pow(left->GetValFloat(), right->GetValFloat()));
|
this->SetValue(pow(static_cast<T>(*left), static_cast<T>(*right)));
|
||||||
}
|
}
|
||||||
CBotError Div(CBotVar* left, CBotVar* right) override
|
CBotError Div(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
float r = right->GetValFloat();
|
T r = static_cast<T>(*right);
|
||||||
if (r == 0) return CBotErrZeroDiv;
|
if ( r == static_cast<T>(0) ) return CBotErrZeroDiv;
|
||||||
this->SetValFloat(left->GetValFloat() / r);
|
this->SetValue(static_cast<T>(*left) / r);
|
||||||
return CBotNoErr;
|
return CBotNoErr;
|
||||||
}
|
}
|
||||||
CBotError Modulo(CBotVar* left, CBotVar* right) override
|
CBotError Modulo(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
float r = right->GetValFloat();
|
T r = static_cast<T>(*right);
|
||||||
if (r == 0) return CBotErrZeroDiv;
|
if ( r == static_cast<T>(0) ) return CBotErrZeroDiv;
|
||||||
this->SetValFloat(fmod(left->GetValFloat(), r));
|
this->SetValue(fmod(static_cast<T>(*left), r));
|
||||||
return CBotNoErr;
|
return CBotNoErr;
|
||||||
}
|
}
|
||||||
void Add(CBotVar* left, CBotVar* right) override
|
void Add(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
this->SetValFloat(left->GetValFloat() + right->GetValFloat());
|
this->SetValue(static_cast<T>(*left) + static_cast<T>(*right));
|
||||||
}
|
}
|
||||||
void Sub(CBotVar* left, CBotVar* right) override
|
void Sub(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
this->SetValFloat(left->GetValFloat() - right->GetValFloat());
|
this->SetValue(static_cast<T>(*left) - static_cast<T>(*right));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Neg() override
|
void Neg() override
|
||||||
|
@ -179,21 +184,65 @@ public:
|
||||||
|
|
||||||
bool Lo(CBotVar* left, CBotVar* right) override
|
bool Lo(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
return left->GetValFloat() < right->GetValFloat();
|
return static_cast<T>(*left) < static_cast<T>(*right);
|
||||||
}
|
}
|
||||||
bool Hi(CBotVar* left, CBotVar* right) override
|
bool Hi(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
return left->GetValFloat() > right->GetValFloat();
|
return static_cast<T>(*left) > static_cast<T>(*right);
|
||||||
}
|
}
|
||||||
bool Ls(CBotVar* left, CBotVar* right) override
|
bool Ls(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
return left->GetValFloat() <= right->GetValFloat();
|
return static_cast<T>(*left) <= static_cast<T>(*right);
|
||||||
}
|
}
|
||||||
bool Hs(CBotVar* left, CBotVar* right) override
|
bool Hs(CBotVar* left, CBotVar* right) override
|
||||||
{
|
{
|
||||||
return left->GetValFloat() >= right->GetValFloat();
|
return static_cast<T>(*left) >= static_cast<T>(*right);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* \brief An integer variable (byte, short, char, int, long)
|
||||||
|
*/
|
||||||
|
template <typename T, CBotType type>
|
||||||
|
class CBotVarInteger : public CBotVarNumber<T, type>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CBotVarInteger(const CBotToken &name) : CBotVarNumber<T, type>(name) {}
|
||||||
|
|
||||||
|
CBotError Modulo(CBotVar* left, CBotVar* right) override
|
||||||
|
{
|
||||||
|
T r = static_cast<T>(*right);
|
||||||
|
if ( r == static_cast<T>(0) ) return CBotErrZeroDiv;
|
||||||
|
this->SetValue(static_cast<T>(*left) % r);
|
||||||
|
return CBotNoErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XOr(CBotVar* left, CBotVar* right) override
|
||||||
|
{
|
||||||
|
this->SetValue(static_cast<T>(*left) ^ static_cast<T>(*right));
|
||||||
|
}
|
||||||
|
void And(CBotVar* left, CBotVar* right) override
|
||||||
|
{
|
||||||
|
this->SetValue(static_cast<T>(*left) & static_cast<T>(*right));
|
||||||
|
}
|
||||||
|
void Or(CBotVar* left, CBotVar* right) override
|
||||||
|
{
|
||||||
|
this->SetValue(static_cast<T>(*left) | static_cast<T>(*right));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SL(CBotVar* left, CBotVar* right) override
|
||||||
|
{
|
||||||
|
this->SetValue(static_cast<T>(*left) << right->GetValInt());
|
||||||
|
}
|
||||||
|
void ASR(CBotVar* left, CBotVar* right) override
|
||||||
|
{
|
||||||
|
this->SetValue(static_cast<T>(*left) >> right->GetValInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Not() override
|
||||||
|
{
|
||||||
|
this->m_val = ~(this->m_val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace CBot
|
||||||
|
|
|
@ -605,6 +605,20 @@ TEST_F(CBotUT, VarImplicitCast)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CBotUT, IntegerMathNearLimits_Issue993)
|
||||||
|
{
|
||||||
|
ExecuteTest(
|
||||||
|
"extern void Test_Issue993() {\n"
|
||||||
|
" ASSERT(-2147483600 * 1 == -2147483600);\n"
|
||||||
|
" ASSERT( 2147483600 * 1 == 2147483600);\n"
|
||||||
|
" ASSERT( 2147483646 * 1 == 2147483646);\n"
|
||||||
|
" ASSERT( 2147483646 * -1 == -2147483646);\n"
|
||||||
|
" ASSERT( 2147483000 * -1 == -2147483000);\n"
|
||||||
|
" ASSERT( 2147483000 * 1 == 2147483000);\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(CBotUT, ToString)
|
TEST_F(CBotUT, ToString)
|
||||||
{
|
{
|
||||||
ExecuteTest(
|
ExecuteTest(
|
||||||
|
|
Loading…
Reference in New Issue