More extensible external call interface
parent
3170395576
commit
8e01a208c1
|
@ -22,7 +22,7 @@
|
|||
#include "CBot/CBotCStack.h"
|
||||
|
||||
#include "CBot/CBotToken.h"
|
||||
#include "CBot/CBotCall.h"
|
||||
#include "CBotExternalCall.h"
|
||||
|
||||
#include "CBot/CBotVar/CBotVar.h"
|
||||
|
||||
|
@ -351,7 +351,7 @@ CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nId
|
|||
nIdent = 0;
|
||||
CBotTypResult val(-1);
|
||||
|
||||
val = CBotCall::CompileCall(p, ppVars, this, nIdent);
|
||||
val = CBotExternalCallList::CompileCall(p, ppVars, this);
|
||||
if (val.GetType() < 0)
|
||||
{
|
||||
val = m_prog->GetFunctions()->CompileCall(p->GetString(), ppVars, nIdent);
|
||||
|
@ -371,7 +371,7 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
|
|||
{
|
||||
std::string name = pToken->GetString();
|
||||
|
||||
if ( CBotCall::CheckCall(name) ) return true;
|
||||
if ( CBotExternalCallList::CheckCall(name) ) return true;
|
||||
|
||||
CBotFunction* pp = m_prog->GetFunctions();
|
||||
while ( pp != nullptr )
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Colobot: Gold Edition source code
|
||||
* Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://gnu.org/licenses
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CBot/CBotUtils.h"
|
||||
#include "CBot/CBotEnums.h"
|
||||
#include "CBot/CBotDefines.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class CBotStack;
|
||||
class CBotCStack;
|
||||
class CBotVar;
|
||||
class CBotTypResult;
|
||||
class CBotToken;
|
||||
|
||||
/**
|
||||
* \brief Class used for external calls
|
||||
*
|
||||
* \see CBotProgram::AddFunction() for information on how to add your functions to this list
|
||||
*/
|
||||
class CBotCall : public CBotLinkedList<CBotCall>
|
||||
{
|
||||
public:
|
||||
typedef bool (*RuntimeFunc)(CBotVar* args, CBotVar* result, int& exception, void* user);
|
||||
typedef CBotTypResult (*CompileFunc)(CBotVar*& args, void* user);
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param name Function name
|
||||
* \param rExec Runtime function
|
||||
* \param rCompile Compilation function
|
||||
* \see CBotProgram::AddFunction()
|
||||
*/
|
||||
CBotCall(const std::string& name, RuntimeFunc rExec, CompileFunc rCompile);
|
||||
|
||||
/**
|
||||
* \brief Destructor
|
||||
*/
|
||||
~CBotCall();
|
||||
|
||||
/**
|
||||
* \brief Add a new function to the list
|
||||
* \param name Function name
|
||||
* \param rExec Runtime function
|
||||
* \param rCompile Compilation function
|
||||
* \return true
|
||||
*/
|
||||
static bool AddFunction(const std::string& name, RuntimeFunc rExec, CompileFunc rCompile);
|
||||
|
||||
/**
|
||||
* \brief Find and call compile function
|
||||
*
|
||||
* \todo Document
|
||||
*/
|
||||
static CBotTypResult CompileCall(CBotToken* &p, CBotVar** ppVars, CBotCStack* pStack, long& nIdent);
|
||||
|
||||
/**
|
||||
* \brief Check if function with given name has been defined
|
||||
* \param name Name to check
|
||||
* \return true if function was defined
|
||||
*/
|
||||
static bool CheckCall(const std::string& name);
|
||||
|
||||
/**
|
||||
* \brief Find and call runtime function
|
||||
*
|
||||
* \todo Document
|
||||
*/
|
||||
static int DoCall(long& nIdent, CBotToken* token, CBotVar** ppVars, CBotStack* pStack, CBotTypResult& rettype);
|
||||
|
||||
/**
|
||||
* \brief Execute the runtime function
|
||||
* \param pStack Stack to execute the function on
|
||||
* \return false if function requested interruption, true otherwise
|
||||
*/
|
||||
bool Run(CBotStack* pStack);
|
||||
|
||||
/**
|
||||
* \brief Restore execution status after loading saved state
|
||||
*
|
||||
* \todo Document
|
||||
*/
|
||||
static bool RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack);
|
||||
|
||||
/**
|
||||
* \brief Set user pointer to pass to compile/runtime functions
|
||||
* \param pUser User pointer
|
||||
*/
|
||||
static void SetUserPtr(void* pUser);
|
||||
|
||||
/**
|
||||
* \brief Reset the list of registered functions
|
||||
*/
|
||||
static void Clear();
|
||||
|
||||
private:
|
||||
static std::map<std::string, std::unique_ptr<CBotCall>> m_list;
|
||||
static void* m_user;
|
||||
|
||||
long m_ident;
|
||||
std::string m_name;
|
||||
RuntimeFunc m_rExec;
|
||||
CompileFunc m_rComp;
|
||||
};
|
|
@ -39,7 +39,6 @@ CBotCallMethode::CBotCallMethode(const std::string& name,
|
|||
m_name = name;
|
||||
m_rExec = rExec;
|
||||
m_rComp = rCompile;
|
||||
m_nFuncIdent = CBotVar::NextUniqNum();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -48,14 +47,10 @@ CBotCallMethode::~CBotCallMethode()
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotTypResult CBotCallMethode::CompileCall(const std::string& name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppVar,
|
||||
CBotCStack* pStack,
|
||||
long& nIdent)
|
||||
CBotTypResult CBotCallMethode::CompileCall(const std::string& name, CBotVar* pThis, CBotVar** ppVar,
|
||||
CBotCStack* pStack)
|
||||
{
|
||||
CBotCallMethode* pt = this;
|
||||
nIdent = 0;
|
||||
|
||||
while ( pt != nullptr )
|
||||
{
|
||||
|
@ -70,7 +65,6 @@ CBotTypResult CBotCallMethode::CompileCall(const std::string& name,
|
|||
if (pVar2) pStack->SetError(static_cast<CBotError>(ret), pVar2->GetToken());
|
||||
}
|
||||
delete pVar;
|
||||
nIdent = pt->m_nFuncIdent;
|
||||
return r;
|
||||
}
|
||||
pt = pt->m_next;
|
||||
|
@ -79,55 +73,11 @@ CBotTypResult CBotCallMethode::CompileCall(const std::string& name,
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string CBotCallMethode::GetName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CBotCallMethode::DoCall(long& nIdent,
|
||||
const std::string& name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppVars,
|
||||
CBotVar*& pResult,
|
||||
CBotStack* pStack,
|
||||
CBotToken* pToken)
|
||||
int CBotCallMethode::DoCall(const std::string& name, CBotVar* pThis, CBotVar** ppVars, CBotVar*& pResult,
|
||||
CBotStack* pStack, CBotToken* pToken)
|
||||
{
|
||||
CBotCallMethode* pt = this;
|
||||
|
||||
// search by the identifier
|
||||
|
||||
if ( nIdent ) while ( pt != nullptr )
|
||||
{
|
||||
if ( pt->m_nFuncIdent == nIdent )
|
||||
{
|
||||
// lists the parameters depending on the contents of the stack (pStackVar)
|
||||
|
||||
CBotVar* pVar = MakeListVars(ppVars, true);
|
||||
CBotVar* pVarToDelete = pVar;
|
||||
|
||||
// then calls the routine external to the module
|
||||
|
||||
int Exception = 0; // TODO: Change this to CBotError
|
||||
int res = pt->m_rExec(pThis, pVar, pResult, Exception, pStack->GetPUser());
|
||||
pStack->SetVar(pResult);
|
||||
|
||||
if (res == false)
|
||||
{
|
||||
if (Exception!=0)
|
||||
{
|
||||
// pStack->SetError(Exception, pVar->GetToken());
|
||||
pStack->SetError(static_cast<CBotError>(Exception), pToken);
|
||||
}
|
||||
delete pVarToDelete;
|
||||
return false;
|
||||
}
|
||||
delete pVarToDelete;
|
||||
return true;
|
||||
}
|
||||
pt = pt->m_next;
|
||||
}
|
||||
|
||||
// search by name
|
||||
|
||||
while ( pt != nullptr )
|
||||
|
@ -154,7 +104,6 @@ int CBotCallMethode::DoCall(long& nIdent,
|
|||
return false;
|
||||
}
|
||||
delete pVarToDelete;
|
||||
nIdent = pt->m_nFuncIdent;
|
||||
return true;
|
||||
}
|
||||
pt = pt->m_next;
|
||||
|
|
|
@ -60,11 +60,8 @@ public:
|
|||
* \param nIdent
|
||||
* \return
|
||||
*/
|
||||
CBotTypResult CompileCall(const std::string& name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppVars,
|
||||
CBotCStack* pStack,
|
||||
long& nIdent);
|
||||
CBotTypResult CompileCall(const std::string& name, CBotVar* pThis, CBotVar** ppVars,
|
||||
CBotCStack* pStack);
|
||||
|
||||
/*!
|
||||
* \brief DoCall
|
||||
|
@ -77,26 +74,13 @@ public:
|
|||
* \param pFunc
|
||||
* \return
|
||||
*/
|
||||
int DoCall(long& nIdent,
|
||||
const std::string& name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppVars,
|
||||
CBotVar*& pResult,
|
||||
CBotStack* pStack,
|
||||
CBotToken* pFunc);
|
||||
|
||||
/*!
|
||||
* \brief GetName
|
||||
* \return
|
||||
*/
|
||||
std::string GetName();
|
||||
int DoCall(const std::string& name, CBotVar* pThis, CBotVar** ppVars, CBotVar*& pResult,
|
||||
CBotStack* pStack, CBotToken* pFunc);
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
bool (*m_rExec) (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user);
|
||||
CBotTypResult (*m_rComp) (CBotVar* pThis, CBotVar* &pVar);
|
||||
friend class CBotClass;
|
||||
long m_nFuncIdent;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "CBot/CBotInstr/CBotListArray.h"
|
||||
#include "CBot/CBotInstr/CBotEmpty.h"
|
||||
|
||||
#include "CBot/CBotCall.h"
|
||||
#include "CBotExternalCall.h"
|
||||
#include "CBot/CBotStack.h"
|
||||
#include "CBot/CBotCStack.h"
|
||||
#include "CBot/CBotUtils.h"
|
||||
|
@ -337,7 +337,7 @@ bool CBotClass::AddFunction(const std::string& name,
|
|||
|
||||
while ( p != nullptr )
|
||||
{
|
||||
if ( name == p->GetName() )
|
||||
if ( name == p->m_name )
|
||||
{
|
||||
if ( pp == nullptr ) m_pCalls = p->m_next;
|
||||
else pp->m_next = p->m_next;
|
||||
|
@ -374,7 +374,7 @@ CBotTypResult CBotClass::CompileMethode(const std::string& name,
|
|||
|
||||
// find the methods declared by AddFunction
|
||||
|
||||
CBotTypResult r = m_pCalls->CompileCall(name, pThis, ppParams, pStack, nIdent);
|
||||
CBotTypResult r = m_pCalls->CompileCall(name, pThis, ppParams, pStack);
|
||||
if ( r.GetType() >= 0) return r;
|
||||
|
||||
// find the methods declared by user
|
||||
|
@ -394,7 +394,7 @@ bool CBotClass::ExecuteMethode(long& nIdent,
|
|||
CBotStack*& pStack,
|
||||
CBotToken* pToken)
|
||||
{
|
||||
int ret = m_pCalls->DoCall(nIdent, name, pThis, ppParams, pResult, pStack, pToken);
|
||||
int ret = m_pCalls->DoCall(name, pThis, ppParams, pResult, pStack, pToken);
|
||||
if (ret>=0) return ret;
|
||||
|
||||
ret = m_pMethod->DoCall(nIdent, name, pThis, ppParams, pStack, pToken, this);
|
||||
|
@ -402,7 +402,7 @@ bool CBotClass::ExecuteMethode(long& nIdent,
|
|||
|
||||
if (m_pParent != nullptr)
|
||||
{
|
||||
ret = m_pParent->m_pCalls->DoCall(nIdent, name, pThis, ppParams, pResult, pStack, pToken);
|
||||
ret = m_pParent->m_pCalls->DoCall(name, pThis, ppParams, pResult, pStack, pToken);
|
||||
if (ret >= 0) return ret;
|
||||
ret = m_pParent->m_pMethod->DoCall(nIdent, name, pThis, ppParams, pStack, pToken, m_pParent);
|
||||
}
|
||||
|
@ -500,7 +500,7 @@ bool CBotClass::CheckCall(CBotToken* &pToken,
|
|||
{
|
||||
std::string name = pToken->GetString();
|
||||
|
||||
if ( CBotCall::CheckCall(name) ) return true;
|
||||
if ( CBotExternalCallList::CheckCall(name) ) return true;
|
||||
|
||||
CBotFunction* pp = m_pMethod;
|
||||
while ( pp != nullptr )
|
||||
|
|
|
@ -49,7 +49,9 @@ enum CBotType
|
|||
CBotTypPointer = 12, //!< Pointer to a class (::CBotTypClass or ::CBotTypIntrinsic)
|
||||
CBotTypNullPointer = 13, //!< Null pointer
|
||||
CBotTypClass = 15, //!< Class instance
|
||||
CBotTypIntrinsic = 16 //!< Intrinsic class instance
|
||||
CBotTypIntrinsic = 16, //!< Intrinsic class instance
|
||||
|
||||
CBotTypMAX = 20
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* along with this program. If not, see http://gnu.org/licenses
|
||||
*/
|
||||
|
||||
#include "CBot/CBotCall.h"
|
||||
#include "CBotExternalCall.h"
|
||||
|
||||
#include "CBot/CBotToken.h"
|
||||
#include "CBot/CBotStack.h"
|
||||
|
@ -27,49 +27,34 @@
|
|||
#include "CBot/CBotVar/CBotVar.h"
|
||||
|
||||
|
||||
std::map<std::string, std::unique_ptr<CBotCall>> CBotCall::m_list = std::map<std::string, std::unique_ptr<CBotCall>>();
|
||||
void* CBotCall::m_user = nullptr;
|
||||
std::map<std::string, std::unique_ptr<CBotExternalCall>> CBotExternalCallList::m_list{};
|
||||
void* CBotExternalCallList::m_user = nullptr;
|
||||
|
||||
CBotCall::CBotCall(const std::string& name, RuntimeFunc rExec, CompileFunc rCompile)
|
||||
{
|
||||
m_name = name;
|
||||
m_rExec = rExec;
|
||||
m_rComp = rCompile;
|
||||
m_ident = CBotVar::NextUniqNum();
|
||||
}
|
||||
|
||||
CBotCall::~CBotCall()
|
||||
{
|
||||
}
|
||||
|
||||
void CBotCall::Clear()
|
||||
void CBotExternalCallList::Clear()
|
||||
{
|
||||
m_list.clear();
|
||||
}
|
||||
|
||||
bool CBotCall::AddFunction(const std::string& name, RuntimeFunc rExec, CompileFunc rCompile)
|
||||
bool CBotExternalCallList::AddFunction(const std::string& name, std::unique_ptr<CBotExternalCall> call)
|
||||
{
|
||||
m_list[name] = std::unique_ptr<CBotCall>(new CBotCall(name, rExec, rCompile));
|
||||
m_list[name] = std::move(call);
|
||||
return true;
|
||||
}
|
||||
|
||||
CBotTypResult CBotCall::CompileCall(CBotToken* &p, CBotVar** ppVar, CBotCStack* pStack, long& nIdent)
|
||||
CBotTypResult CBotExternalCallList::CompileCall(CBotToken*& p, CBotVar** ppVar, CBotCStack* pStack)
|
||||
{
|
||||
nIdent = 0;
|
||||
if (m_list.count(p->GetString()) == 0)
|
||||
return -1;
|
||||
|
||||
CBotCall* pt = m_list[p->GetString()].get();
|
||||
nIdent = pt->m_ident;
|
||||
CBotExternalCall* pt = m_list[p->GetString()].get();
|
||||
|
||||
std::unique_ptr<CBotVar> args = std::unique_ptr<CBotVar>(MakeListVars(ppVar));
|
||||
CBotVar* var = args.get(); // TODO: This shouldn't be a reference
|
||||
CBotTypResult r = pt->m_rComp(var, m_user);
|
||||
CBotTypResult r = pt->Compile(args.get(), m_user);
|
||||
|
||||
// if a class is returned, it is actually a pointer
|
||||
if (r.GetType() == CBotTypClass) r.SetType(CBotTypPointer);
|
||||
|
||||
if (r.GetType() > 20) // error?
|
||||
if (r.GetType() > CBotTypMAX) // error?
|
||||
{
|
||||
pStack->SetError(static_cast<CBotError>(r.GetType()), p);
|
||||
}
|
||||
|
@ -77,46 +62,26 @@ CBotTypResult CBotCall::CompileCall(CBotToken* &p, CBotVar** ppVar, CBotCStack*
|
|||
return r;
|
||||
}
|
||||
|
||||
void CBotCall::SetUserPtr(void* pUser)
|
||||
void CBotExternalCallList::SetUserPtr(void* pUser)
|
||||
{
|
||||
m_user = pUser;
|
||||
}
|
||||
|
||||
bool CBotCall::CheckCall(const std::string& name)
|
||||
bool CBotExternalCallList::CheckCall(const std::string& name)
|
||||
{
|
||||
return m_list.count(name) > 0;
|
||||
}
|
||||
|
||||
int CBotCall::DoCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack, CBotTypResult& rettype)
|
||||
int CBotExternalCallList::DoCall(CBotToken* token, CBotVar** ppVar, CBotStack* pStack, const CBotTypResult& rettype)
|
||||
{
|
||||
CBotCall* pt = nullptr;
|
||||
|
||||
if (nIdent > 0)
|
||||
{
|
||||
for (const auto& it : m_list)
|
||||
{
|
||||
if (it.second->m_ident == nIdent)
|
||||
{
|
||||
pt = it.second.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pt == nullptr)
|
||||
{
|
||||
if (token != nullptr)
|
||||
{
|
||||
if (m_list.count(token->GetString()) > 0)
|
||||
{
|
||||
pt = m_list[token->GetString()].get();
|
||||
nIdent = pt->m_ident;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pt == nullptr)
|
||||
if (token == nullptr)
|
||||
return -1;
|
||||
|
||||
if (m_list.count(token->GetString()) == 0)
|
||||
return -1;
|
||||
|
||||
CBotExternalCall* pt = m_list[token->GetString()].get();
|
||||
|
||||
CBotStack* pile = pStack->AddStackEOX(pt);
|
||||
if (pile == EOX) return true;
|
||||
|
||||
|
@ -133,16 +98,14 @@ int CBotCall::DoCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack*
|
|||
|
||||
pile->SetError(CBotNoErr, token); // save token for the position in case of error
|
||||
return pt->Run(pStack);
|
||||
|
||||
}
|
||||
|
||||
bool CBotCall::RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack)
|
||||
bool CBotExternalCallList::RestoreCall(CBotToken* token, CBotVar** ppVar, CBotStack* pStack)
|
||||
{
|
||||
if (m_list.count(token->GetString()) == 0)
|
||||
return false;
|
||||
|
||||
CBotCall* pt = m_list[token->GetString()].get();
|
||||
nIdent = pt->m_ident;
|
||||
CBotExternalCall* pt = m_list[token->GetString()].get();
|
||||
|
||||
CBotStack* pile = pStack->RestoreStackEOX(pt);
|
||||
if ( pile == nullptr ) return true;
|
||||
|
@ -151,7 +114,35 @@ bool CBotCall::RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBot
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CBotCall::Run(CBotStack* pStack)
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CBotExternalCall::CBotExternalCall()
|
||||
{
|
||||
}
|
||||
|
||||
CBotExternalCall::~CBotExternalCall()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CBotExternalCallDefault::CBotExternalCallDefault(RuntimeFunc rExec, CompileFunc rCompile)
|
||||
: CBotExternalCall()
|
||||
{
|
||||
m_rExec = rExec;
|
||||
m_rComp = rCompile;
|
||||
}
|
||||
|
||||
CBotExternalCallDefault::~CBotExternalCallDefault()
|
||||
{
|
||||
}
|
||||
|
||||
CBotTypResult CBotExternalCallDefault::Compile(CBotVar* args, void* user)
|
||||
{
|
||||
return m_rComp(args, user);
|
||||
}
|
||||
|
||||
bool CBotExternalCallDefault::Run(CBotStack* pStack)
|
||||
{
|
||||
CBotStack* pile = pStack->AddStackEOX(this);
|
||||
if ( pile == EOX ) return true;
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* This file is part of the Colobot: Gold Edition source code
|
||||
* Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://gnu.org/licenses
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CBot/CBotUtils.h"
|
||||
#include "CBot/CBotEnums.h"
|
||||
#include "CBot/CBotDefines.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class CBotStack;
|
||||
class CBotCStack;
|
||||
class CBotVar;
|
||||
class CBotTypResult;
|
||||
class CBotToken;
|
||||
|
||||
/**
|
||||
* \brief Interface for external CBot calls
|
||||
*
|
||||
* \see CBotExternalCallList
|
||||
* \see CBotExternalCallDefault
|
||||
*/
|
||||
class CBotExternalCall
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \see CBotProgram::AddFunction()
|
||||
*/
|
||||
CBotExternalCall();
|
||||
|
||||
/**
|
||||
* \brief Destructor
|
||||
*/
|
||||
virtual ~CBotExternalCall();
|
||||
|
||||
/**
|
||||
* \brief Compile the function
|
||||
*
|
||||
* \param Arguments (only types!) passed to the function
|
||||
* \param User pointer provided to CBotProgram::Compile()
|
||||
*/
|
||||
virtual CBotTypResult Compile(CBotVar* args, void* user) = 0;
|
||||
|
||||
/**
|
||||
* \brief Execute the function
|
||||
*
|
||||
* \param pStack Stack to execute the function on
|
||||
* \return false to request program interruption, true otherwise
|
||||
*/
|
||||
virtual bool Run(CBotStack* pStack) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Default implementation of CBot external call, using compilation and runtime functions
|
||||
*/
|
||||
class CBotExternalCallDefault : public CBotExternalCall
|
||||
{
|
||||
public:
|
||||
typedef bool (*RuntimeFunc)(CBotVar* args, CBotVar* result, int& exception, void* user);
|
||||
typedef CBotTypResult (*CompileFunc)(CBotVar*& args, void* user);
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param rExec Runtime function
|
||||
* \param rCompile Compilation function
|
||||
* \see CBotProgram::AddFunction()
|
||||
*/
|
||||
CBotExternalCallDefault(RuntimeFunc rExec, CompileFunc rCompile);
|
||||
|
||||
/**
|
||||
* \brief Destructor
|
||||
*/
|
||||
virtual ~CBotExternalCallDefault();
|
||||
|
||||
virtual CBotTypResult Compile(CBotVar* args, void* user);
|
||||
virtual bool Run(CBotStack* pStack);
|
||||
|
||||
private:
|
||||
RuntimeFunc m_rExec;
|
||||
CompileFunc m_rComp;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Class for mangaging CBot external calls
|
||||
*
|
||||
* \see CBotProgram::AddFunction() for information on how to add your functions to this list
|
||||
*/
|
||||
class CBotExternalCallList
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Add a new function to the list
|
||||
* \param name Function name
|
||||
* \param call Function to add
|
||||
* \return true
|
||||
*/
|
||||
static bool AddFunction(const std::string& name, std::unique_ptr<CBotExternalCall> call);
|
||||
|
||||
/**
|
||||
* \brief Find and call compile function
|
||||
*
|
||||
* This function sets an error in compilation stack in case of failure
|
||||
*
|
||||
* \param p Token representing the function name
|
||||
* \param ppVars List of arguments (only types!)
|
||||
* \param pStack Compilation stack
|
||||
* \return CBotTypResult representing the return type of the function (::CBotTypVar), or an error (::CBotError)
|
||||
*/
|
||||
static CBotTypResult CompileCall(CBotToken*& p, CBotVar** ppVars, CBotCStack* pStack);
|
||||
|
||||
/**
|
||||
* \brief Check if function with given name has been defined
|
||||
* \param name Name to check
|
||||
* \return true if function was defined
|
||||
*/
|
||||
static bool CheckCall(const std::string& name);
|
||||
|
||||
/**
|
||||
* \brief Find and call runtime function
|
||||
*
|
||||
* This function sets an error in runtime stack in case of failure
|
||||
*
|
||||
* \param token Token representing the function name
|
||||
* \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
|
||||
*/
|
||||
static int DoCall(CBotToken* token, 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 pStack Runtime stack
|
||||
* \return false on failure (e.g. function doesn't exist)
|
||||
*/
|
||||
static bool RestoreCall(CBotToken* token, CBotVar** ppVar, CBotStack* pStack);
|
||||
|
||||
/**
|
||||
* \brief Set user pointer to pass to compile functions
|
||||
*
|
||||
* This is for compile functions only, runtime functions use CBotStack::GetPUser()
|
||||
*
|
||||
* \param pUser User pointer
|
||||
*/
|
||||
static void SetUserPtr(void* pUser);
|
||||
|
||||
/**
|
||||
* \brief Reset the list of registered functions
|
||||
*/
|
||||
static void Clear();
|
||||
|
||||
private:
|
||||
static std::map<std::string, std::unique_ptr<CBotExternalCall>> m_list;
|
||||
static void* m_user;
|
||||
};
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "CBot/CBotVar/CBotVar.h"
|
||||
|
||||
#include "CBot/CBotCall.h"
|
||||
#include "CBotExternalCall.h"
|
||||
#include "CBot/CBotStack.h"
|
||||
#include "CBot/CBotCStack.h"
|
||||
#include "CBot/CBotClass.h"
|
||||
|
@ -77,7 +77,7 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
|
|||
CBotToken* p = tokens.get()->GetNext(); // skips the first token (separator)
|
||||
|
||||
pStack->SetProgram(this); // defined used routines
|
||||
CBotCall::SetUserPtr(pUser);
|
||||
CBotExternalCallList::SetUserPtr(pUser);
|
||||
|
||||
// Step 2. Find all function and class definitions
|
||||
while ( pStack->IsOk() && p != nullptr && p->GetType() != 0)
|
||||
|
@ -312,8 +312,7 @@ bool CBotProgram::AddFunction(const std::string& name,
|
|||
bool rExec(CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
|
||||
CBotTypResult rCompile(CBotVar*& pVar, void* pUser))
|
||||
{
|
||||
// stores pointers to the two functions
|
||||
return CBotCall::AddFunction(name, rExec, rCompile);
|
||||
return CBotExternalCallList::AddFunction(name, std::unique_ptr<CBotExternalCall>(new CBotExternalCallDefault(rExec, rCompile)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -435,7 +434,7 @@ void CBotProgram::Init()
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CBotProgram::Free()
|
||||
{
|
||||
CBotToken::ClearDefineNum() ;
|
||||
CBotCall::Clear() ;
|
||||
CBotClass::Free() ;
|
||||
CBotToken::ClearDefineNum();
|
||||
CBotExternalCallList::Clear();
|
||||
CBotClass::Free();
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
// Modules inlcude
|
||||
#include "CBot/CBotStack.h"
|
||||
#include "CBot/CBotCall.h"
|
||||
#include "CBotExternalCall.h"
|
||||
|
||||
#include "CBot/CBotInstr/CBotFunction.h"
|
||||
|
||||
|
@ -153,7 +153,7 @@ CBotStack* CBotStack::AddStack(CBotInstr* instr, UnknownEnumBlock bBlock)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotStack* CBotStack::AddStackEOX(CBotCall* instr, UnknownEnumBlock bBlock)
|
||||
CBotStack* CBotStack::AddStackEOX(CBotExternalCall* instr, UnknownEnumBlock bBlock)
|
||||
{
|
||||
if (m_next != nullptr)
|
||||
{
|
||||
|
@ -292,7 +292,7 @@ CBotStack* CBotStack::AddStack(CBotInstr* instr, bool bBlock)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotStack* CBotStack::AddStackEOX(CBotCall* instr, bool bBlock)
|
||||
CBotStack* CBotStack::AddStackEOX(CBotExternalCall* instr, bool bBlock)
|
||||
{
|
||||
if (m_next != nullptr)
|
||||
{
|
||||
|
@ -378,7 +378,7 @@ CBotStack* CBotStack::RestoreStack(CBotInstr* instr)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotStack* CBotStack::RestoreStackEOX(CBotCall* instr)
|
||||
CBotStack* CBotStack::RestoreStackEOX(CBotExternalCall* instr)
|
||||
{
|
||||
CBotStack* p = RestoreStack();
|
||||
p->m_call = instr;
|
||||
|
@ -619,7 +619,7 @@ void CBotStack::SetTimer(int n)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotStack::Execute()
|
||||
{
|
||||
CBotCall* instr = nullptr; // the most highest instruction
|
||||
CBotExternalCall* instr = nullptr; // the most highest instruction
|
||||
CBotStack* pile;
|
||||
|
||||
CBotStack* p = this;
|
||||
|
@ -744,7 +744,7 @@ bool CBotStack::ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBo
|
|||
|
||||
// first looks by the identifier
|
||||
|
||||
res = CBotCall::DoCall(nIdent, nullptr, ppVar, this, rettype );
|
||||
res = CBotExternalCallList::DoCall(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 = CBotCall::DoCall(nIdent, token, ppVar, this, rettype );
|
||||
res = CBotExternalCallList::DoCall(token, 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 ( !CBotCall::RestoreCall(nIdent, token, ppVar, this) )
|
||||
if ( !CBotExternalCallList::RestoreCall(token, ppVar, this))
|
||||
m_prog->GetFunctions()->RestoreCall(nIdent, token->GetString(), ppVar, this );
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
// Forward declaration
|
||||
class CBotInstr;
|
||||
class CBotCall;
|
||||
class CBotExternalCall;
|
||||
class CBotVar;
|
||||
class CBotProgram;
|
||||
class CBotToken;
|
||||
|
@ -174,9 +174,9 @@ public:
|
|||
|
||||
|
||||
CBotStack* AddStack(CBotInstr* instr = nullptr, UnknownEnumBlock bBlock = UnknownEnumBlock::UNKNOWN_FALSE); // extends the stack
|
||||
CBotStack* AddStackEOX(CBotCall* instr = nullptr, UnknownEnumBlock bBlock = UnknownEnumBlock::UNKNOWN_FALSE); // extends the stack
|
||||
CBotStack* AddStackEOX(CBotExternalCall* instr = nullptr, UnknownEnumBlock bBlock = UnknownEnumBlock::UNKNOWN_FALSE); // extends the stack
|
||||
CBotStack* RestoreStack(CBotInstr* instr = nullptr);
|
||||
CBotStack* RestoreStackEOX(CBotCall* instr = nullptr);
|
||||
CBotStack* RestoreStackEOX(CBotExternalCall* instr = nullptr);
|
||||
|
||||
CBotStack* AddStack2(UnknownEnumBlock bBlock = UnknownEnumBlock::UNKNOWN_FALSE); // extends the stack
|
||||
bool Return(CBotStack* pFils); // transmits the result over
|
||||
|
@ -258,7 +258,7 @@ private:
|
|||
|
||||
CBotInstr* m_instr; // the corresponding instruction
|
||||
IsFunctionParam m_bFunc; // an input of a function?
|
||||
CBotCall* m_call; // recovery point in a extern call
|
||||
CBotExternalCall* m_call; // recovery point in a extern call
|
||||
friend class CBotTry;
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ set(SOURCES
|
|||
CBotStack.cpp
|
||||
CBotCStack.cpp
|
||||
CBotToken.cpp
|
||||
CBotCall.cpp
|
||||
CBotExternalCall.cpp
|
||||
CBotDefParam.cpp
|
||||
CBotCallMethode.cpp
|
||||
CBotTypResult.cpp
|
||||
|
|
Loading…
Reference in New Issue