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 NaNfix-squashed-planets
parent
2ea94244e9
commit
8632c7404d
|
@ -41,9 +41,9 @@ bool CBotExprLitNan::Execute(CBotStack* &pj)
|
||||||
CBotStack* pile = pj->AddStack(this);
|
CBotStack* pile = pj->AddStack(this);
|
||||||
|
|
||||||
if (pile->IfStep()) return false;
|
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
|
pile->SetVar(var); // put on the stack
|
||||||
return pj->Return(pile); // forward below
|
return pj->Return(pile); // forward below
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,12 +206,6 @@ bool CBotExpression::Execute(CBotStack* &pj)
|
||||||
if (m_token.GetType() != ID_ASS)
|
if (m_token.GetType() != ID_ASS)
|
||||||
{
|
{
|
||||||
pVar = pile1->GetVar(); // recovers if interrupted
|
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));
|
result = CBotVar::Create("", pVar->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,8 +217,8 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack)
|
||||||
{
|
{
|
||||||
CBotInstr* inst = new CBotExprLitNan();
|
CBotInstr* inst = new CBotExprLitNan();
|
||||||
inst->SetToken(pp);
|
inst->SetToken(pp);
|
||||||
CBotVar* var = CBotVar::Create("", CBotTypInt);
|
CBotVar* var = CBotVar::Create("", CBotTypFloat);
|
||||||
var->SetInit(CBotVar::InitType::IS_NAN);
|
var->SetValFloat(std::nanf(""));
|
||||||
pStk->SetVar(var);
|
pStk->SetVar(var);
|
||||||
return pStack->Return(inst, pStk);
|
return pStack->Return(inst, pStk);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,11 +56,6 @@ bool CBotPostIncExpr::Execute(CBotStack* &pj)
|
||||||
CBotStack* pile3 = pile2->AddStack(this);
|
CBotStack* pile3 = pile2->AddStack(this);
|
||||||
if (pile3->IfStep()) return false;
|
if (pile3->IfStep()) return false;
|
||||||
|
|
||||||
if (var1->IsNAN())
|
|
||||||
{
|
|
||||||
pile1->SetError(CBotErrNan, &m_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!var1->IsDefined())
|
if (!var1->IsDefined())
|
||||||
{
|
{
|
||||||
pile1->SetError(CBotErrNotInit, &m_token);
|
pile1->SetError(CBotErrNotInit, &m_token);
|
||||||
|
|
|
@ -55,12 +55,6 @@ bool CBotPreIncExpr::Execute(CBotStack* &pj)
|
||||||
// pile2 is modified on return
|
// pile2 is modified on return
|
||||||
if (!(static_cast<CBotExprVar*>(m_instr))->ExecuteVar(var1, pile2, nullptr, true)) return false;
|
if (!(static_cast<CBotExprVar*>(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())
|
if (!var1->IsDefined())
|
||||||
{
|
{
|
||||||
pile->SetError(CBotErrNotInit, &m_token);
|
pile->SetError(CBotErrNotInit, &m_token);
|
||||||
|
|
|
@ -305,7 +305,13 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
|
||||||
|
|
||||||
static bool VarIsNAN(const CBotVar* var)
|
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)
|
static bool IsNan(CBotVar* left, CBotVar* right, CBotError* err = nullptr)
|
||||||
|
@ -475,13 +481,13 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack)
|
||||||
break;
|
break;
|
||||||
case ID_EQ:
|
case ID_EQ:
|
||||||
if ( IsNan(left, right) )
|
if ( IsNan(left, right) )
|
||||||
result->SetValInt(left->GetInit() == right->GetInit()) ;
|
result->SetValInt(VarIsNAN(left) == VarIsNAN(right));
|
||||||
else
|
else
|
||||||
result->SetValInt(temp->Eq(left , right)); // equal
|
result->SetValInt(temp->Eq(left , right)); // equal
|
||||||
break;
|
break;
|
||||||
case ID_NE:
|
case ID_NE:
|
||||||
if ( IsNan(left, right) )
|
if ( IsNan(left, right) )
|
||||||
result->SetValInt(left ->GetInit() != right->GetInit()) ;
|
result->SetValInt(VarIsNAN(left) != VarIsNAN(right));
|
||||||
else
|
else
|
||||||
result->SetValInt(temp->Ne(left , right)); // different
|
result->SetValInt(temp->Ne(left , right)); // different
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -243,7 +243,6 @@ public:
|
||||||
UNDEF = 0, //!< the variable value is currently not defined
|
UNDEF = 0, //!< the variable value is currently not defined
|
||||||
DEF = 1, //!< the variable value is defined
|
DEF = 1, //!< the variable value is defined
|
||||||
IS_POINTER = 2, //!< the variable value is as a pointer
|
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; }
|
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; }
|
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -36,8 +36,6 @@ public:
|
||||||
{
|
{
|
||||||
if (m_binit == CBotVar::InitType::UNDEF)
|
if (m_binit == CBotVar::InitType::UNDEF)
|
||||||
return LoadString(TX_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))
|
if (0x10FFFF < m_val || (0xD7FF < m_val && m_val < 0xE000))
|
||||||
return "\xEF\xBF\xBD"; // replacement character U+FFFD
|
return "\xEF\xBF\xBD"; // replacement character U+FFFD
|
||||||
|
|
|
@ -66,8 +66,6 @@ public:
|
||||||
{
|
{
|
||||||
if (m_binit == CBotVar::InitType::UNDEF)
|
if (m_binit == CBotVar::InitType::UNDEF)
|
||||||
return LoadString(TX_UNDEF);
|
return LoadString(TX_UNDEF);
|
||||||
if (m_binit == CBotVar::InitType::IS_NAN)
|
|
||||||
return LoadString(TX_NAN);
|
|
||||||
|
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << std::boolalpha << m_val;
|
s << std::boolalpha << m_val;
|
||||||
|
|
|
@ -133,7 +133,7 @@ bool rfdestruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception
|
||||||
if (!pVar->IsDefined()) return true; // file not opened
|
if (!pVar->IsDefined()) return true; // file not opened
|
||||||
g_files.erase(pVar->GetValInt());
|
g_files.erase(pVar->GetValInt());
|
||||||
|
|
||||||
pVar->SetInit(CBotVar::InitType::IS_NAN);
|
pVar->SetInit(CBotVar::InitType::UNDEF);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ bool rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, v
|
||||||
|
|
||||||
g_files.erase(handleIter);
|
g_files.erase(handleIter);
|
||||||
|
|
||||||
pVar->SetInit(CBotVar::InitType::IS_NAN);
|
pVar->SetInit(CBotVar::InitType::UNDEF);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,37 @@ bool rTrunc(CBotVar* var, CBotVar* result, int& exception, void* user)
|
||||||
return true;
|
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
|
} // namespace
|
||||||
|
|
||||||
void InitMathFunctions()
|
void InitMathFunctions()
|
||||||
|
@ -237,6 +268,7 @@ void InitMathFunctions()
|
||||||
CBotProgram::AddFunction("ceil", rCeil, cOneFloat);
|
CBotProgram::AddFunction("ceil", rCeil, cOneFloat);
|
||||||
CBotProgram::AddFunction("round", rRound, cOneFloat);
|
CBotProgram::AddFunction("round", rRound, cOneFloat);
|
||||||
CBotProgram::AddFunction("trunc", rTrunc, cOneFloat);
|
CBotProgram::AddFunction("trunc", rTrunc, cOneFloat);
|
||||||
|
CBotProgram::AddFunction("isnan", rIsNAN, cIsNAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace CBot
|
} // namespace CBot
|
||||||
|
|
|
@ -233,7 +233,7 @@ bool rStrFind( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pResult->SetInit(CBotVar::InitType::IS_NAN);
|
pResult->SetValInt(-1);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,6 +301,7 @@ std::string GetHelpFilename(const char *token)
|
||||||
if ( strcmp(token, "ceil" ) == 0 ) helpfile = "cbot/ceil";
|
if ( strcmp(token, "ceil" ) == 0 ) helpfile = "cbot/ceil";
|
||||||
if ( strcmp(token, "round" ) == 0 ) helpfile = "cbot/round";
|
if ( strcmp(token, "round" ) == 0 ) helpfile = "cbot/round";
|
||||||
if ( strcmp(token, "trunc" ) == 0 ) helpfile = "cbot/trunc";
|
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, "retobject" ) == 0 ) helpfile = "cbot/retobj";
|
||||||
if ( strcmp(token, "errmode" ) == 0 ) helpfile = "cbot/errmode";
|
if ( strcmp(token, "errmode" ) == 0 ) helpfile = "cbot/errmode";
|
||||||
if ( strcmp(token, "isbusy" ) == 0 ) helpfile = "cbot/isbusy";
|
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, "ceil" ) == 0 ) return true;
|
||||||
if ( strcmp(token, "round" ) == 0 ) return true;
|
if ( strcmp(token, "round" ) == 0 ) return true;
|
||||||
if ( strcmp(token, "trunc" ) == 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, "retobjectbyid") == 0 ) return true;
|
||||||
if ( strcmp(token, "retobject" ) == 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, "factory" ) == 0 ) return true;
|
||||||
if ( strcmp(token, "research" ) == 0 ) return true;
|
if ( strcmp(token, "research" ) == 0 ) return true;
|
||||||
if ( strcmp(token, "takeoff" ) == 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, "ceil" ) == 0 ) return "ceil ( value );";
|
||||||
if ( strcmp(token, "round" ) == 0 ) return "round ( value );";
|
if ( strcmp(token, "round" ) == 0 ) return "round ( value );";
|
||||||
if ( strcmp(token, "trunc" ) == 0 ) return "trunc ( 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, "retobject" ) == 0 ) return "retobject ( rank );";
|
||||||
if ( strcmp(token, "retobjectbyid") == 0 ) return "retobjectbyid ( rank );";
|
if ( strcmp(token, "retobjectbyid") == 0 ) return "retobjectbyid ( rank );";
|
||||||
if ( strcmp(token, "progfunc" ) == 0 ) return "progfunc ( funcname );";
|
if ( strcmp(token, "progfunc" ) == 0 ) return "progfunc ( funcname );";
|
||||||
|
|
|
@ -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 )
|
if ( result != nullptr )
|
||||||
{
|
{
|
||||||
pSub = result->GetItemList();
|
pSub = result->GetItemList();
|
||||||
if ( pSub != nullptr )
|
if ( pSub != nullptr )
|
||||||
{
|
{
|
||||||
pSub->SetValFloat(center.x/g_unit);
|
if (success)
|
||||||
pSub = pSub->GetNext(); // "y"
|
{
|
||||||
pSub->SetValFloat(center.z/g_unit);
|
pSub->SetValFloat(center.x / g_unit);
|
||||||
pSub = pSub->GetNext(); // "z"
|
pSub = pSub->GetNext(); // "y"
|
||||||
pSub->SetValFloat(center.y/g_unit);
|
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;
|
return true;
|
||||||
|
@ -2313,7 +2325,7 @@ bool CScriptFunctions::rReceive(CBotVar* var, CBotVar* result, int& exception, v
|
||||||
if ( err != ERR_OK )
|
if ( err != ERR_OK )
|
||||||
{
|
{
|
||||||
script->m_taskExecutor->StopForegroundTask();
|
script->m_taskExecutor->StopForegroundTask();
|
||||||
result->SetInit(CBotVar::InitType::IS_NAN);
|
result->SetValFloat(std::nanf(""));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2324,7 +2336,7 @@ bool CScriptFunctions::rReceive(CBotVar* var, CBotVar* result, int& exception, v
|
||||||
|
|
||||||
if ( script->m_returnValue == boost::none )
|
if ( script->m_returnValue == boost::none )
|
||||||
{
|
{
|
||||||
result->SetInit(CBotVar::InitType::IS_NAN);
|
result->SetValFloat(std::nanf(""));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3645,11 +3657,11 @@ void CScriptFunctions::uObject(CBotVar* botThis, void* user)
|
||||||
if (IsObjectBeingTransported(object))
|
if (IsObjectBeingTransported(object))
|
||||||
{
|
{
|
||||||
pSub = pVar->GetItemList(); // "x"
|
pSub = pVar->GetItemList(); // "x"
|
||||||
pSub->SetInit(CBotVar::InitType::IS_NAN);
|
pSub->SetValFloat(std::nanf(""));
|
||||||
pSub = pSub->GetNext(); // "y"
|
pSub = pSub->GetNext(); // "y"
|
||||||
pSub->SetInit(CBotVar::InitType::IS_NAN);
|
pSub->SetValFloat(std::nanf(""));
|
||||||
pSub = pSub->GetNext(); // "z"
|
pSub = pSub->GetNext(); // "z"
|
||||||
pSub->SetInit(CBotVar::InitType::IS_NAN);
|
pSub->SetValFloat(std::nanf(""));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3750,11 +3762,11 @@ void CScriptFunctions::uObject(CBotVar* botThis, void* user)
|
||||||
if (IsObjectBeingTransported(object) || physics == nullptr)
|
if (IsObjectBeingTransported(object) || physics == nullptr)
|
||||||
{
|
{
|
||||||
pSub = pVar->GetItemList(); // "x"
|
pSub = pVar->GetItemList(); // "x"
|
||||||
pSub->SetInit(CBotVar::InitType::IS_NAN);
|
pSub->SetValFloat(std::nanf(""));
|
||||||
pSub = pSub->GetNext(); // "y"
|
pSub = pSub->GetNext(); // "y"
|
||||||
pSub->SetInit(CBotVar::InitType::IS_NAN);
|
pSub->SetValFloat(std::nanf(""));
|
||||||
pSub = pSub->GetNext(); // "z"
|
pSub = pSub->GetNext(); // "z"
|
||||||
pSub->SetInit(CBotVar::InitType::IS_NAN);
|
pSub->SetValFloat(std::nanf(""));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue