From 8632c7404df91077ea826fe298138e1447dae696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Kapu=C5=9Bci=C5=84ski?= Date: Mon, 15 Aug 2022 00:04:54 +0200 Subject: [PATCH] Refactored NaN implementation strfind() now returns -1 instead of NaN when substring can't be found added isnan() as an alternative way of checking if a value is NaN --- src/CBot/CBotInstr/CBotExprLitNan.cpp | 4 +-- src/CBot/CBotInstr/CBotExpression.cpp | 6 ---- src/CBot/CBotInstr/CBotParExpr.cpp | 4 +-- src/CBot/CBotInstr/CBotPostIncExpr.cpp | 5 ---- src/CBot/CBotInstr/CBotPreIncExpr.cpp | 6 ---- src/CBot/CBotInstr/CBotTwoOpExpr.cpp | 12 ++++++-- src/CBot/CBotVar/CBotVar.h | 7 ----- src/CBot/CBotVar/CBotVarChar.h | 2 -- src/CBot/CBotVar/CBotVarValue.h | 2 -- src/CBot/stdlib/FileFunctions.cpp | 4 +-- src/CBot/stdlib/MathFunctions.cpp | 32 +++++++++++++++++++++ src/CBot/stdlib/StringFunctions.cpp | 2 +- src/script/cbottoken.cpp | 5 +++- src/script/scriptfunc.cpp | 40 +++++++++++++++++--------- 14 files changed, 78 insertions(+), 53 deletions(-) diff --git a/src/CBot/CBotInstr/CBotExprLitNan.cpp b/src/CBot/CBotInstr/CBotExprLitNan.cpp index 52e30d5f..60f73e8e 100644 --- a/src/CBot/CBotInstr/CBotExprLitNan.cpp +++ b/src/CBot/CBotInstr/CBotExprLitNan.cpp @@ -41,9 +41,9 @@ bool CBotExprLitNan::Execute(CBotStack* &pj) CBotStack* pile = pj->AddStack(this); if (pile->IfStep()) return false; - CBotVar* var = CBotVar::Create("", CBotTypInt); + CBotVar* var = CBotVar::Create("", CBotTypFloat); - var->SetInit(CBotVar::InitType::IS_NAN); // nan + var->SetValFloat(std::nanf("")); pile->SetVar(var); // put on the stack return pj->Return(pile); // forward below } diff --git a/src/CBot/CBotInstr/CBotExpression.cpp b/src/CBot/CBotInstr/CBotExpression.cpp index 2374a2a6..8a9e91de 100644 --- a/src/CBot/CBotInstr/CBotExpression.cpp +++ b/src/CBot/CBotInstr/CBotExpression.cpp @@ -206,12 +206,6 @@ bool CBotExpression::Execute(CBotStack* &pj) if (m_token.GetType() != ID_ASS) { pVar = pile1->GetVar(); // recovers if interrupted - initKind = pVar->GetInit(); - if (initKind == CBotVar::InitType::IS_NAN) - { - pile2->SetError(CBotErrNan, m_leftop->GetToken()); - return pj->Return(pile2); - } result = CBotVar::Create("", pVar->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC)); } diff --git a/src/CBot/CBotInstr/CBotParExpr.cpp b/src/CBot/CBotInstr/CBotParExpr.cpp index 46f72818..fe33c82d 100644 --- a/src/CBot/CBotInstr/CBotParExpr.cpp +++ b/src/CBot/CBotInstr/CBotParExpr.cpp @@ -217,8 +217,8 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack) { CBotInstr* inst = new CBotExprLitNan(); inst->SetToken(pp); - CBotVar* var = CBotVar::Create("", CBotTypInt); - var->SetInit(CBotVar::InitType::IS_NAN); + CBotVar* var = CBotVar::Create("", CBotTypFloat); + var->SetValFloat(std::nanf("")); pStk->SetVar(var); return pStack->Return(inst, pStk); } diff --git a/src/CBot/CBotInstr/CBotPostIncExpr.cpp b/src/CBot/CBotInstr/CBotPostIncExpr.cpp index fac31e2c..5ce6284d 100644 --- a/src/CBot/CBotInstr/CBotPostIncExpr.cpp +++ b/src/CBot/CBotInstr/CBotPostIncExpr.cpp @@ -56,11 +56,6 @@ bool CBotPostIncExpr::Execute(CBotStack* &pj) CBotStack* pile3 = pile2->AddStack(this); if (pile3->IfStep()) return false; - if (var1->IsNAN()) - { - pile1->SetError(CBotErrNan, &m_token); - } - if (!var1->IsDefined()) { pile1->SetError(CBotErrNotInit, &m_token); diff --git a/src/CBot/CBotInstr/CBotPreIncExpr.cpp b/src/CBot/CBotInstr/CBotPreIncExpr.cpp index afb2b65c..6416215b 100644 --- a/src/CBot/CBotInstr/CBotPreIncExpr.cpp +++ b/src/CBot/CBotInstr/CBotPreIncExpr.cpp @@ -55,12 +55,6 @@ bool CBotPreIncExpr::Execute(CBotStack* &pj) // pile2 is modified on return if (!(static_cast(m_instr))->ExecuteVar(var1, pile2, nullptr, true)) return false; - if (var1->IsNAN()) - { - pile->SetError(CBotErrNan, &m_token); - return pj->Return(pile); // operation performed - } - if (!var1->IsDefined()) { pile->SetError(CBotErrNotInit, &m_token); diff --git a/src/CBot/CBotInstr/CBotTwoOpExpr.cpp b/src/CBot/CBotInstr/CBotTwoOpExpr.cpp index ad09f221..52b78372 100644 --- a/src/CBot/CBotInstr/CBotTwoOpExpr.cpp +++ b/src/CBot/CBotInstr/CBotTwoOpExpr.cpp @@ -305,7 +305,13 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera static bool VarIsNAN(const CBotVar* var) { - return var->GetInit() > CBotVar::InitType::DEF; + if (var->GetType() == CBotTypFloat) + return std::isnan(var->GetValFloat()); + + if (var->GetType() == CBotTypDouble) + return std::isnan(var->GetValDouble()); + + return false; } static bool IsNan(CBotVar* left, CBotVar* right, CBotError* err = nullptr) @@ -475,13 +481,13 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack) break; case ID_EQ: if ( IsNan(left, right) ) - result->SetValInt(left->GetInit() == right->GetInit()) ; + result->SetValInt(VarIsNAN(left) == VarIsNAN(right)); else result->SetValInt(temp->Eq(left , right)); // equal break; case ID_NE: if ( IsNan(left, right) ) - result->SetValInt(left ->GetInit() != right->GetInit()) ; + result->SetValInt(VarIsNAN(left) != VarIsNAN(right)); else result->SetValInt(temp->Ne(left , right)); // different break; diff --git a/src/CBot/CBotVar/CBotVar.h b/src/CBot/CBotVar/CBotVar.h index d1d336cf..c9739e3f 100644 --- a/src/CBot/CBotVar/CBotVar.h +++ b/src/CBot/CBotVar/CBotVar.h @@ -243,7 +243,6 @@ public: UNDEF = 0, //!< the variable value is currently not defined DEF = 1, //!< the variable value is defined IS_POINTER = 2, //!< the variable value is as a pointer - IS_NAN = 999 //!< the variable value is NAN }; /** @@ -269,12 +268,6 @@ public: */ bool IsDefined() const { return GetInit() == InitType::DEF; } - /** - * \brief Checks if the variable is currently NAN - * \return InitType::NAN - */ - bool IsNAN() const { return GetInit() == InitType::IS_NAN; } - //@} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/CBot/CBotVar/CBotVarChar.h b/src/CBot/CBotVar/CBotVarChar.h index 6bbfb9c1..168604f6 100644 --- a/src/CBot/CBotVar/CBotVarChar.h +++ b/src/CBot/CBotVar/CBotVarChar.h @@ -36,8 +36,6 @@ public: { if (m_binit == CBotVar::InitType::UNDEF) return LoadString(TX_UNDEF); - if (m_binit == CBotVar::InitType::IS_NAN) - return LoadString(TX_NAN); if (0x10FFFF < m_val || (0xD7FF < m_val && m_val < 0xE000)) return "\xEF\xBF\xBD"; // replacement character U+FFFD diff --git a/src/CBot/CBotVar/CBotVarValue.h b/src/CBot/CBotVar/CBotVarValue.h index 9d1e6f4a..fddb6bfe 100644 --- a/src/CBot/CBotVar/CBotVarValue.h +++ b/src/CBot/CBotVar/CBotVarValue.h @@ -66,8 +66,6 @@ public: { if (m_binit == CBotVar::InitType::UNDEF) return LoadString(TX_UNDEF); - if (m_binit == CBotVar::InitType::IS_NAN) - return LoadString(TX_NAN); std::ostringstream s; s << std::boolalpha << m_val; diff --git a/src/CBot/stdlib/FileFunctions.cpp b/src/CBot/stdlib/FileFunctions.cpp index 04e54ac1..bb48268d 100644 --- a/src/CBot/stdlib/FileFunctions.cpp +++ b/src/CBot/stdlib/FileFunctions.cpp @@ -133,7 +133,7 @@ bool rfdestruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception if (!pVar->IsDefined()) return true; // file not opened g_files.erase(pVar->GetValInt()); - pVar->SetInit(CBotVar::InitType::IS_NAN); + pVar->SetInit(CBotVar::InitType::UNDEF); return true; } @@ -203,7 +203,7 @@ bool rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, v g_files.erase(handleIter); - pVar->SetInit(CBotVar::InitType::IS_NAN); + pVar->SetInit(CBotVar::InitType::UNDEF); return true; } diff --git a/src/CBot/stdlib/MathFunctions.cpp b/src/CBot/stdlib/MathFunctions.cpp index 5353f80d..105f805a 100644 --- a/src/CBot/stdlib/MathFunctions.cpp +++ b/src/CBot/stdlib/MathFunctions.cpp @@ -218,6 +218,37 @@ bool rTrunc(CBotVar* var, CBotVar* result, int& exception, void* user) return true; } +// Instruction "isnan()" + +CBotTypResult cIsNAN(CBotVar*& var, void* user) +{ + if (var == nullptr) return CBotTypResult(CBotErrLowParam); + + if (var->GetType() > CBotTypDouble) return CBotTypResult(CBotErrBadNum); + + var = var->GetNext(); + if (var != nullptr) return CBotTypResult(CBotErrOverParam); + + return CBotTypResult(CBotTypBoolean); +} + +bool rIsNAN(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + bool isnan = false; + + if (var->GetType() == CBotTypFloat) + { + if (std::isnan(var->GetValFloat())) isnan = true; + } + else if (var->GetType() == CBotTypDouble) + { + if (std::isnan(var->GetValDouble())) isnan = true; + } + + result->SetValInt(isnan); + return true; +} + } // namespace void InitMathFunctions() @@ -237,6 +268,7 @@ void InitMathFunctions() CBotProgram::AddFunction("ceil", rCeil, cOneFloat); CBotProgram::AddFunction("round", rRound, cOneFloat); CBotProgram::AddFunction("trunc", rTrunc, cOneFloat); + CBotProgram::AddFunction("isnan", rIsNAN, cIsNAN); } } // namespace CBot diff --git a/src/CBot/stdlib/StringFunctions.cpp b/src/CBot/stdlib/StringFunctions.cpp index c543df7f..a9d61b81 100644 --- a/src/CBot/stdlib/StringFunctions.cpp +++ b/src/CBot/stdlib/StringFunctions.cpp @@ -233,7 +233,7 @@ bool rStrFind( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser ) } else { - pResult->SetInit(CBotVar::InitType::IS_NAN); + pResult->SetValInt(-1); } return true; } diff --git a/src/script/cbottoken.cpp b/src/script/cbottoken.cpp index 911b985d..d14a7068 100644 --- a/src/script/cbottoken.cpp +++ b/src/script/cbottoken.cpp @@ -301,6 +301,7 @@ std::string GetHelpFilename(const char *token) if ( strcmp(token, "ceil" ) == 0 ) helpfile = "cbot/ceil"; if ( strcmp(token, "round" ) == 0 ) helpfile = "cbot/round"; if ( strcmp(token, "trunc" ) == 0 ) helpfile = "cbot/trunc"; + if ( strcmp(token, "isnan" ) == 0 ) helpfile = "cbot/isnan"; if ( strcmp(token, "retobject" ) == 0 ) helpfile = "cbot/retobj"; if ( strcmp(token, "errmode" ) == 0 ) helpfile = "cbot/errmode"; if ( strcmp(token, "isbusy" ) == 0 ) helpfile = "cbot/isbusy"; @@ -463,9 +464,10 @@ bool IsFunction(const char *token) if ( strcmp(token, "ceil" ) == 0 ) return true; if ( strcmp(token, "round" ) == 0 ) return true; if ( strcmp(token, "trunc" ) == 0 ) return true; + if ( strcmp(token, "isnan" ) == 0 ) return true; if ( strcmp(token, "retobjectbyid") == 0 ) return true; if ( strcmp(token, "retobject" ) == 0 ) return true; - if ( strcmp(token, "isbusy" ) == 0 ) return true; + if ( strcmp(token, "isbusy" ) == 0 ) return true; if ( strcmp(token, "factory" ) == 0 ) return true; if ( strcmp(token, "research" ) == 0 ) return true; if ( strcmp(token, "takeoff" ) == 0 ) return true; @@ -571,6 +573,7 @@ const char* GetHelpText(const char *token) if ( strcmp(token, "ceil" ) == 0 ) return "ceil ( value );"; if ( strcmp(token, "round" ) == 0 ) return "round ( value );"; if ( strcmp(token, "trunc" ) == 0 ) return "trunc ( value );"; + if ( strcmp(token, "isnan" ) == 0 ) return "isnan ( value );"; if ( strcmp(token, "retobject" ) == 0 ) return "retobject ( rank );"; if ( strcmp(token, "retobjectbyid") == 0 ) return "retobjectbyid ( rank );"; if ( strcmp(token, "progfunc" ) == 0 ) return "progfunc ( funcname );"; diff --git a/src/script/scriptfunc.cpp b/src/script/scriptfunc.cpp index 323bea85..bd782618 100644 --- a/src/script/scriptfunc.cpp +++ b/src/script/scriptfunc.cpp @@ -1836,18 +1836,30 @@ bool CScriptFunctions::rSpace(CBotVar* var, CBotVar* result, int& exception, voi } } } - script->m_main->FreeSpace(center, rMin, rMax, dist, pThis); + + bool success = script->m_main->FreeSpace(center, rMin, rMax, dist, pThis); if ( result != nullptr ) { pSub = result->GetItemList(); if ( pSub != nullptr ) { - pSub->SetValFloat(center.x/g_unit); - pSub = pSub->GetNext(); // "y" - pSub->SetValFloat(center.z/g_unit); - pSub = pSub->GetNext(); // "z" - pSub->SetValFloat(center.y/g_unit); + if (success) + { + pSub->SetValFloat(center.x / g_unit); + pSub = pSub->GetNext(); // "y" + pSub->SetValFloat(center.z / g_unit); + pSub = pSub->GetNext(); // "z" + pSub->SetValFloat(center.y / g_unit); + } + else + { + pSub->SetValFloat(center.x); + pSub = pSub->GetNext(); // "y" + pSub->SetValFloat(center.y); + pSub = pSub->GetNext(); // "z" + pSub->SetValFloat(center.z); + } } } return true; @@ -2313,7 +2325,7 @@ bool CScriptFunctions::rReceive(CBotVar* var, CBotVar* result, int& exception, v if ( err != ERR_OK ) { script->m_taskExecutor->StopForegroundTask(); - result->SetInit(CBotVar::InitType::IS_NAN); + result->SetValFloat(std::nanf("")); return true; } @@ -2324,7 +2336,7 @@ bool CScriptFunctions::rReceive(CBotVar* var, CBotVar* result, int& exception, v if ( script->m_returnValue == boost::none ) { - result->SetInit(CBotVar::InitType::IS_NAN); + result->SetValFloat(std::nanf("")); } else { @@ -3645,11 +3657,11 @@ void CScriptFunctions::uObject(CBotVar* botThis, void* user) if (IsObjectBeingTransported(object)) { pSub = pVar->GetItemList(); // "x" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(std::nanf("")); pSub = pSub->GetNext(); // "y" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(std::nanf("")); pSub = pSub->GetNext(); // "z" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(std::nanf("")); } else { @@ -3750,11 +3762,11 @@ void CScriptFunctions::uObject(CBotVar* botThis, void* user) if (IsObjectBeingTransported(object) || physics == nullptr) { pSub = pVar->GetItemList(); // "x" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(std::nanf("")); pSub = pSub->GetNext(); // "y" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(std::nanf("")); pSub = pSub->GetNext(); // "z" - pSub->SetInit(CBotVar::InitType::IS_NAN); + pSub->SetValFloat(std::nanf("")); } else {