Made CBotExternalCallList combatible with class calls

dev-time-step
krzys-h 2015-12-24 12:57:37 +01:00
parent ae544c71ae
commit ff081aff49
4 changed files with 99 additions and 21 deletions

View File

@ -351,7 +351,7 @@ CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nId
nIdent = 0; nIdent = 0;
CBotTypResult val(-1); CBotTypResult val(-1);
val = m_prog->GetExternalCalls()->CompileCall(p, ppVars, this); val = m_prog->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this);
if (val.GetType() < 0) if (val.GetType() < 0)
{ {
val = m_prog->GetFunctions()->CompileCall(p->GetString(), ppVars, nIdent); val = m_prog->GetFunctions()->CompileCall(p->GetString(), ppVars, nIdent);

View File

@ -37,7 +37,7 @@ bool CBotExternalCallList::AddFunction(const std::string& name, std::unique_ptr<
return true; return true;
} }
CBotTypResult CBotExternalCallList::CompileCall(CBotToken*& p, CBotVar** ppVar, CBotCStack* pStack) CBotTypResult CBotExternalCallList::CompileCall(CBotToken*& p, CBotVar* thisVar, CBotVar** ppVar, CBotCStack* pStack)
{ {
if (m_list.count(p->GetString()) == 0) if (m_list.count(p->GetString()) == 0)
return -1; return -1;
@ -45,7 +45,7 @@ CBotTypResult CBotExternalCallList::CompileCall(CBotToken*& p, CBotVar** ppVar,
CBotExternalCall* pt = m_list[p->GetString()].get(); CBotExternalCall* pt = m_list[p->GetString()].get();
std::unique_ptr<CBotVar> args = std::unique_ptr<CBotVar>(MakeListVars(ppVar)); std::unique_ptr<CBotVar> args = std::unique_ptr<CBotVar>(MakeListVars(ppVar));
CBotTypResult r = pt->Compile(args.get(), m_user); CBotTypResult r = pt->Compile(thisVar, args.get(), m_user);
// if a class is returned, it is actually a pointer // if a class is returned, it is actually a pointer
if (r.GetType() == CBotTypClass) r.SetType(CBotTypPointer); if (r.GetType() == CBotTypClass) r.SetType(CBotTypPointer);
@ -68,7 +68,7 @@ bool CBotExternalCallList::CheckCall(const std::string& name)
return m_list.count(name) > 0; return m_list.count(name) > 0;
} }
int CBotExternalCallList::DoCall(CBotToken* token, CBotVar** ppVar, CBotStack* pStack, const CBotTypResult& rettype) int CBotExternalCallList::DoCall(CBotToken* token, CBotVar* thisVar, CBotVar** ppVar, CBotStack* pStack, const CBotTypResult& rettype)
{ {
if (token == nullptr) if (token == nullptr)
return -1; return -1;
@ -93,10 +93,10 @@ int CBotExternalCallList::DoCall(CBotToken* token, CBotVar** ppVar, CBotStack* p
pile2->SetVar(pResult); pile2->SetVar(pResult);
pile->SetError(CBotNoErr, token); // save token for the position in case of error pile->SetError(CBotNoErr, token); // save token for the position in case of error
return pt->Run(pStack); return pt->Run(thisVar, pStack);
} }
bool CBotExternalCallList::RestoreCall(CBotToken* token, CBotVar** ppVar, CBotStack* pStack) bool CBotExternalCallList::RestoreCall(CBotToken* token, CBotVar* thisVar, CBotVar** ppVar, CBotStack* pStack)
{ {
if (m_list.count(token->GetString()) == 0) if (m_list.count(token->GetString()) == 0)
return false; return false;
@ -123,7 +123,6 @@ CBotExternalCall::~CBotExternalCall()
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CBotExternalCallDefault::CBotExternalCallDefault(RuntimeFunc rExec, CompileFunc rCompile) CBotExternalCallDefault::CBotExternalCallDefault(RuntimeFunc rExec, CompileFunc rCompile)
: CBotExternalCall()
{ {
m_rExec = rExec; m_rExec = rExec;
m_rComp = rCompile; m_rComp = rCompile;
@ -133,12 +132,12 @@ CBotExternalCallDefault::~CBotExternalCallDefault()
{ {
} }
CBotTypResult CBotExternalCallDefault::Compile(CBotVar* args, void* user) CBotTypResult CBotExternalCallDefault::Compile(CBotVar* thisVar, CBotVar* args, void* user)
{ {
return m_rComp(args, user); return m_rComp(args, user);
} }
bool CBotExternalCallDefault::Run(CBotStack* pStack) bool CBotExternalCallDefault::Run(CBotVar* thisVar, CBotStack* pStack)
{ {
CBotStack* pile = pStack->AddStackEOX(this); CBotStack* pile = pStack->AddStackEOX(this);
if ( pile == EOX ) return true; if ( pile == EOX ) return true;
@ -164,3 +163,47 @@ bool CBotExternalCallDefault::Run(CBotStack* pStack)
return true; return true;
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CBotExternalCallDefaultClass::CBotExternalCallDefaultClass(RuntimeFunc rExec, CompileFunc rCompile)
{
m_rExec = rExec;
m_rComp = rCompile;
}
CBotExternalCallDefaultClass::~CBotExternalCallDefaultClass()
{
}
CBotTypResult CBotExternalCallDefaultClass::Compile(CBotVar* thisVar, CBotVar* args, void* user)
{
return m_rComp(nullptr, args);
}
// TODO: Figure out why classes do pStack->SetVar while normal calls do pStack->SetCopyVar
bool CBotExternalCallDefaultClass::Run(CBotVar* thisVar, CBotStack* pStack)
{
CBotStack* pile = pStack->AddStackEOX(this);
if ( pile == EOX ) return true;
CBotVar* args = pile->GetVar();
CBotStack* pile2 = pile->AddStack();
CBotVar* result = pile2->GetVar();
int exception = CBotNoErr; // TODO: Change to CBotError
bool res = m_rExec(thisVar, args, result, exception, pStack->GetPUser());
pStack->SetVar(result);
if (!res)
{
if (exception != CBotNoErr)
{
pStack->SetError(static_cast<CBotError>(exception));
}
return false;
}
return true;
}

View File

@ -56,18 +56,20 @@ public:
/** /**
* \brief Compile the function * \brief Compile the function
* *
* \param "this" variable for class calls, nullptr for normal calls
* \param Arguments (only types!) passed to the function * \param Arguments (only types!) passed to the function
* \param User pointer provided to CBotProgram::Compile() * \param User pointer provided to CBotProgram::Compile()
*/ */
virtual CBotTypResult Compile(CBotVar* args, void* user) = 0; virtual CBotTypResult Compile(CBotVar* thisVar, CBotVar* args, void* user) = 0;
/** /**
* \brief Execute the function * \brief Execute the function
* *
* \param thisVar "this" variable for class calls, nullptr for normal calls
* \param pStack Stack to execute the function on * \param pStack Stack to execute the function on
* \return false to request program interruption, true otherwise * \return false to request program interruption, true otherwise
*/ */
virtual bool Run(CBotStack* pStack) = 0; virtual bool Run(CBotVar* thisVar, CBotStack* pStack) = 0;
}; };
/** /**
@ -92,8 +94,38 @@ public:
*/ */
virtual ~CBotExternalCallDefault(); virtual ~CBotExternalCallDefault();
virtual CBotTypResult Compile(CBotVar* args, void* user); virtual CBotTypResult Compile(CBotVar* thisVar, CBotVar* args, void* user);
virtual bool Run(CBotStack* pStack); virtual bool Run(CBotVar* thisVar, CBotStack* pStack);
private:
RuntimeFunc m_rExec;
CompileFunc m_rComp;
};
/**
* \brief Default implementation of CBot external class call, using compilation and runtime functions
*/
class CBotExternalCallDefaultClass : public CBotExternalCall
{
public:
typedef bool (*RuntimeFunc)(CBotVar* thisVar, CBotVar* args, CBotVar* result, int& exception, void* user);
typedef CBotTypResult (*CompileFunc)(CBotVar* thisVar, CBotVar*& args); // TODO: Add user pointer
/**
* \brief Constructor
* \param rExec Runtime function
* \param rCompile Compilation function
* \see CBotClass::AddFunction()
*/
CBotExternalCallDefaultClass(RuntimeFunc rExec, CompileFunc rCompile);
/**
* \brief Destructor
*/
virtual ~CBotExternalCallDefaultClass();
virtual CBotTypResult Compile(CBotVar* thisVar, CBotVar* args, void* user);
virtual bool Run(CBotVar* thisVar, CBotStack* pStack);
private: private:
RuntimeFunc m_rExec; RuntimeFunc m_rExec;
@ -124,10 +156,11 @@ public:
* *
* \param p Token representing the function name * \param p Token representing the function name
* \param ppVars List of arguments (only types!) * \param ppVars List of arguments (only types!)
* \param thisVar "this" variable for class calls, nullptr for normal calls
* \param pStack Compilation stack * \param pStack Compilation stack
* \return CBotTypResult representing the return type of the function (::CBotTypVar), or an error (::CBotError) * \return CBotTypResult representing the return type of the function (::CBotTypVar), or an error (::CBotError)
*/ */
CBotTypResult CompileCall(CBotToken*& p, CBotVar** ppVars, CBotCStack* pStack); CBotTypResult CompileCall(CBotToken*& p, CBotVar* thisVar, CBotVar** ppVars, CBotCStack* pStack);
/** /**
* \brief Check if function with given name has been defined * \brief Check if function with given name has been defined
@ -142,22 +175,24 @@ public:
* This function sets an error in runtime stack in case of failure * This function sets an error in runtime stack in case of failure
* *
* \param token Token representing the function name * \param token Token representing the function name
* \param thisVar "this" variable for class calls, nullptr for normal calls
* \param ppVars List of arguments * \param ppVars List of arguments
* \param pStack Runtime stack * \param pStack Runtime stack
* \param rettype Return type of the function, as returned by CompileCall() * \param rettype Return type of the function, as returned by CompileCall()
* \return -1 if call failed (no such function), 0 if function requested interruption, 1 on success * \return -1 if call failed (no such function), 0 if function requested interruption, 1 on success
*/ */
int DoCall(CBotToken* token, CBotVar** ppVars, CBotStack* pStack, const CBotTypResult& rettype); int DoCall(CBotToken* token, CBotVar* thisVar, CBotVar** ppVars, CBotStack* pStack, const CBotTypResult& rettype);
/** /**
* \brief Restore execution status after loading saved state * \brief Restore execution status after loading saved state
* *
* \param token Token representing the function name * \param token Token representing the function name
* \param ppVar List of arguments (TODO: unused) * \param "this" variable for class calls, nullptr for normal calls
* \param ppVar List of arguments
* \param pStack Runtime stack * \param pStack Runtime stack
* \return false on failure (e.g. function doesn't exist) * \return false on failure (e.g. function doesn't exist)
*/ */
bool RestoreCall(CBotToken* token, CBotVar** ppVar, CBotStack* pStack); bool RestoreCall(CBotToken* token, CBotVar* thisVar, CBotVar** ppVar, CBotStack* pStack);
/** /**
* \brief Set user pointer to pass to compile functions * \brief Set user pointer to pass to compile functions

View File

@ -637,7 +637,7 @@ bool CBotStack::Execute()
if ( instr == nullptr ) return true; // normal execution request if ( instr == nullptr ) return true; // normal execution request
if (!instr->Run(pile)) return false; // \TODO exécution à partir de là if (!instr->Run(nullptr, pile)) return false; // \TODO exécution à partir de là
#if STACKMEM #if STACKMEM
pile->m_next->Delete(); pile->m_next->Delete();
@ -744,7 +744,7 @@ bool CBotStack::ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBo
// first looks by the identifier // first looks by the identifier
res = m_prog->GetExternalCalls()->DoCall(nullptr, ppVar, this, rettype); res = m_prog->GetExternalCalls()->DoCall(nullptr, nullptr, ppVar, this, rettype);
if (res.GetType() >= 0) return res.GetType(); if (res.GetType() >= 0) return res.GetType();
res = m_prog->GetFunctions()->DoCall(nIdent, "", ppVar, this, token ); res = m_prog->GetFunctions()->DoCall(nIdent, "", ppVar, this, token );
@ -753,7 +753,7 @@ bool CBotStack::ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBo
// if not found (recompile?) seeks by name // if not found (recompile?) seeks by name
nIdent = 0; nIdent = 0;
res = m_prog->GetExternalCalls()->DoCall(token, ppVar, this, rettype); res = m_prog->GetExternalCalls()->DoCall(token, nullptr, ppVar, this, rettype);
if (res.GetType() >= 0) return res.GetType(); if (res.GetType() >= 0) return res.GetType();
res = m_prog->GetFunctions()->DoCall(nIdent, token->GetString(), ppVar, this, token ); res = m_prog->GetFunctions()->DoCall(nIdent, token->GetString(), ppVar, this, token );
@ -768,7 +768,7 @@ void CBotStack::RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar)
{ {
if (m_next == nullptr) return; if (m_next == nullptr) return;
if (m_prog->GetExternalCalls()->RestoreCall(token, ppVar, this)) if (m_prog->GetExternalCalls()->RestoreCall(token, nullptr, ppVar, this))
return; return;
m_prog->GetFunctions()->RestoreCall(nIdent, token->GetString(), ppVar, this); m_prog->GetFunctions()->RestoreCall(nIdent, token->GetString(), ppVar, this);