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;
CBotTypResult val(-1);
val = m_prog->GetExternalCalls()->CompileCall(p, ppVars, this);
val = m_prog->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this);
if (val.GetType() < 0)
{
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;
}
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)
return -1;
@ -45,7 +45,7 @@ CBotTypResult CBotExternalCallList::CompileCall(CBotToken*& p, CBotVar** ppVar,
CBotExternalCall* pt = m_list[p->GetString()].get();
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 (r.GetType() == CBotTypClass) r.SetType(CBotTypPointer);
@ -68,7 +68,7 @@ bool CBotExternalCallList::CheckCall(const std::string& name)
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)
return -1;
@ -93,10 +93,10 @@ int CBotExternalCallList::DoCall(CBotToken* token, CBotVar** ppVar, CBotStack* p
pile2->SetVar(pResult);
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)
return false;
@ -123,7 +123,6 @@ CBotExternalCall::~CBotExternalCall()
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CBotExternalCallDefault::CBotExternalCallDefault(RuntimeFunc rExec, CompileFunc rCompile)
: CBotExternalCall()
{
m_rExec = rExec;
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);
}
bool CBotExternalCallDefault::Run(CBotStack* pStack)
bool CBotExternalCallDefault::Run(CBotVar* thisVar, CBotStack* pStack)
{
CBotStack* pile = pStack->AddStackEOX(this);
if ( pile == EOX ) return true;
@ -164,3 +163,47 @@ bool CBotExternalCallDefault::Run(CBotStack* pStack)
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
*
* \param "this" variable for class calls, nullptr for normal calls
* \param Arguments (only types!) passed to the function
* \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
*
* \param thisVar "this" variable for class calls, nullptr for normal calls
* \param pStack Stack to execute the function on
* \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 CBotTypResult Compile(CBotVar* args, void* user);
virtual bool Run(CBotStack* pStack);
virtual CBotTypResult Compile(CBotVar* thisVar, CBotVar* args, void* user);
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:
RuntimeFunc m_rExec;
@ -124,10 +156,11 @@ public:
*
* \param p Token representing the function name
* \param ppVars List of arguments (only types!)
* \param thisVar "this" variable for class calls, nullptr for normal calls
* \param pStack Compilation stack
* \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
@ -142,22 +175,24 @@ public:
* This function sets an error in runtime stack in case of failure
*
* \param token Token representing the function name
* \param thisVar "this" variable for class calls, nullptr for normal calls
* \param ppVars List of arguments
* \param pStack Runtime stack
* \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
*/
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
*
* \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
* \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

View File

@ -637,7 +637,7 @@ bool CBotStack::Execute()
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
pile->m_next->Delete();
@ -744,7 +744,7 @@ bool CBotStack::ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBo
// 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();
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
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();
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_prog->GetExternalCalls()->RestoreCall(token, ppVar, this))
if (m_prog->GetExternalCalls()->RestoreCall(token, nullptr, ppVar, this))
return;
m_prog->GetFunctions()->RestoreCall(nIdent, token->GetString(), ppVar, this);